spiderfw 0.6.39 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG +2 -0
  3. data/Rakefile +4 -3
  4. data/VERSION +1 -1
  5. data/apps/core/admin/public/css/sass/admin.css +61 -12
  6. data/apps/core/admin/public/sass/admin.scss +51 -0
  7. data/apps/core/admin/views/login.layout.shtml +1 -1
  8. data/apps/core/components/assets.rb +34 -2
  9. data/apps/core/components/po/it/spider_components.po +2 -2
  10. data/apps/core/components/public/bootstrap/scss/_aggiunte_bootstrap_3.scss +54 -0
  11. data/apps/core/components/public/bootstrap/scss/_pagination.scss +1 -1
  12. data/apps/core/components/public/bootstrap/scss/_variables.scss +2 -0
  13. data/apps/core/components/public/bootstrap/scss/bootstrap.css +48 -2
  14. data/apps/core/components/public/bootstrap/scss/bootstrap.scss +4 -1
  15. data/apps/core/components/public/bootstrap_3/img/glyphicons-halflings-regular.eot +0 -0
  16. data/apps/core/components/public/bootstrap_3/img/glyphicons-halflings-regular.svg +272 -213
  17. data/apps/core/components/public/bootstrap_3/img/glyphicons-halflings-regular.ttf +0 -0
  18. data/apps/core/components/public/bootstrap_3/img/glyphicons-halflings-regular.woff +0 -0
  19. data/apps/core/components/public/bootstrap_3/img/glyphicons-halflings-regular.woff2 +0 -0
  20. data/apps/core/components/public/bootstrap_3/js/affix.js +48 -26
  21. data/apps/core/components/public/bootstrap_3/js/alert.js +8 -6
  22. data/apps/core/components/public/bootstrap_3/js/button.js +27 -17
  23. data/apps/core/components/public/bootstrap_3/js/carousel.js +66 -39
  24. data/apps/core/components/public/bootstrap_3/js/collapse.js +73 -42
  25. data/apps/core/components/public/bootstrap_3/js/dropdown.js +54 -40
  26. data/apps/core/components/public/bootstrap_3/js/modal.js +102 -42
  27. data/apps/core/components/public/bootstrap_3/js/popover.js +6 -11
  28. data/apps/core/components/public/bootstrap_3/js/scrollspy.js +47 -33
  29. data/apps/core/components/public/bootstrap_3/js/tab.js +48 -21
  30. data/apps/core/components/public/bootstrap_3/js/tooltip.js +118 -60
  31. data/apps/core/components/public/bootstrap_3/js/transition.js +15 -4
  32. data/apps/core/components/public/bootstrap_3/scss/_alerts.scss +8 -2
  33. data/apps/core/components/public/bootstrap_3/scss/_badges.scss +14 -3
  34. data/apps/core/components/public/bootstrap_3/scss/_button-groups.scss +23 -19
  35. data/apps/core/components/public/bootstrap_3/scss/_buttons.scss +22 -13
  36. data/apps/core/components/public/bootstrap_3/scss/_carousel.scss +28 -2
  37. data/apps/core/components/public/bootstrap_3/scss/_close.scss +1 -0
  38. data/apps/core/components/public/bootstrap_3/scss/_code.scss +7 -0
  39. data/apps/core/components/public/bootstrap_3/scss/_component-animations.scss +3 -1
  40. data/apps/core/components/public/bootstrap_3/scss/_dropdowns.scss +11 -9
  41. data/apps/core/components/public/bootstrap_3/scss/_forms.scss +190 -68
  42. data/apps/core/components/public/bootstrap_3/scss/_glyphicons.scss +83 -13
  43. data/apps/core/components/public/bootstrap_3/scss/_grid.scss +4 -4
  44. data/apps/core/components/public/bootstrap_3/scss/_input-groups.scss +1 -0
  45. data/apps/core/components/public/bootstrap_3/scss/_jumbotron.scss +8 -4
  46. data/apps/core/components/public/bootstrap_3/scss/_list-group.scss +13 -12
  47. data/apps/core/components/public/bootstrap_3/scss/_media.scss +40 -30
  48. data/apps/core/components/public/bootstrap_3/scss/_mixins.scss +1 -0
  49. data/apps/core/components/public/bootstrap_3/scss/_modals.scss +7 -4
  50. data/apps/core/components/public/bootstrap_3/scss/_navbar.scss +36 -32
  51. data/apps/core/components/public/bootstrap_3/scss/_navs.scss +3 -3
  52. data/apps/core/components/public/bootstrap_3/scss/_normalize.scss +12 -13
  53. data/apps/core/components/public/bootstrap_3/scss/_pager.scss +2 -3
  54. data/apps/core/components/public/bootstrap_3/scss/_pagination.scss +4 -3
  55. data/apps/core/components/public/bootstrap_3/scss/_panels.scss +38 -7
  56. data/apps/core/components/public/bootstrap_3/scss/_popovers.scss +5 -7
  57. data/apps/core/components/public/bootstrap_3/scss/_print.scss +96 -96
  58. data/apps/core/components/public/bootstrap_3/scss/_progress-bars.scss +20 -22
  59. data/apps/core/components/public/bootstrap_3/scss/_responsive-embed.scss +10 -9
  60. data/apps/core/components/public/bootstrap_3/scss/_responsive-utilities.scss +8 -3
  61. data/apps/core/components/public/bootstrap_3/scss/_scaffolding.scss +15 -4
  62. data/apps/core/components/public/bootstrap_3/scss/_tables.scss +15 -14
  63. data/apps/core/components/public/bootstrap_3/scss/_theme.scss +57 -13
  64. data/apps/core/components/public/bootstrap_3/scss/_thumbnails.scss +2 -2
  65. data/apps/core/components/public/bootstrap_3/scss/_tooltip.scss +13 -7
  66. data/apps/core/components/public/bootstrap_3/scss/_type.scss +21 -21
  67. data/apps/core/components/public/bootstrap_3/scss/_utilities.scss +3 -4
  68. data/apps/core/components/public/bootstrap_3/scss/_variables.scss +54 -32
  69. data/apps/core/components/public/bootstrap_3/scss/bootstrap.css +8772 -0
  70. data/apps/core/components/public/bootstrap_3/scss/bootstrap.scss +6 -0
  71. data/apps/core/components/public/bootstrap_3/scss/mixins/_background-variant.scss +2 -1
  72. data/apps/core/components/public/bootstrap_3/scss/mixins/_buttons.scss +19 -1
  73. data/apps/core/components/public/bootstrap_3/scss/mixins/_forms.scss +5 -1
  74. data/apps/core/components/public/bootstrap_3/scss/mixins/_gradients.scss +1 -1
  75. data/apps/core/components/public/bootstrap_3/scss/mixins/_grid-framework.scss +4 -10
  76. data/apps/core/components/public/bootstrap_3/scss/mixins/_grid.scss +7 -7
  77. data/apps/core/components/public/bootstrap_3/scss/mixins/_hide-text.scss +3 -3
  78. data/apps/core/components/public/bootstrap_3/scss/mixins/_labels.scss +1 -1
  79. data/apps/core/components/public/bootstrap_3/scss/mixins/_list-group.scss +3 -2
  80. data/apps/core/components/public/bootstrap_3/scss/mixins/_opacity.scss +1 -1
  81. data/apps/core/components/public/bootstrap_3/scss/mixins/_pagination.scss +2 -1
  82. data/apps/core/components/public/bootstrap_3/scss/mixins/_panels.scss +4 -0
  83. data/apps/core/components/public/bootstrap_3/scss/mixins/_progress-bar.scss +3 -1
  84. data/apps/core/components/public/bootstrap_3/scss/mixins/_reset-text.scss +18 -0
  85. data/apps/core/components/public/bootstrap_3/scss/mixins/_responsive-visibility.scss +1 -1
  86. data/apps/core/components/public/bootstrap_3/scss/mixins/_text-emphasis.scss +2 -1
  87. data/apps/core/components/public/bootstrap_3/scss/mixins/_vendor-prefixes.scss +11 -13
  88. data/apps/core/components/public/css/table_base.css +46 -1
  89. data/apps/core/components/public/fontawesome_4/fonts/font-awesome/fontawesome-webfont.eot +0 -0
  90. data/apps/core/components/public/fontawesome_4/fonts/font-awesome/fontawesome-webfont.svg +565 -0
  91. data/apps/core/components/public/fontawesome_4/fonts/font-awesome/fontawesome-webfont.ttf +0 -0
  92. data/apps/core/components/public/fontawesome_4/fonts/font-awesome/fontawesome-webfont.woff +0 -0
  93. data/apps/core/components/public/fontawesome_4/fonts/font-awesome/fontawesome-webfont.woff2 +0 -0
  94. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome.css +2893 -0
  95. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome/_animated.scss +34 -0
  96. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome/_bordered-pulled.scss +16 -0
  97. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome/_core.scss +12 -0
  98. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome/_extras.scss +44 -0
  99. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome/_fixed-width.scss +6 -0
  100. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome/_icons.scss +596 -0
  101. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome/_larger.scss +13 -0
  102. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome/_list.scss +19 -0
  103. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome/_mixins.scss +26 -0
  104. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome/_path.scss +14 -0
  105. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome/_rotated-flipped.scss +20 -0
  106. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome/_stacked.scss +20 -0
  107. data/apps/core/components/public/fontawesome_4/stylesheets/font-awesome/_variables.scss +608 -0
  108. data/apps/core/components/public/fontawesome_4/stylesheets/font_awesome.css +2893 -0
  109. data/apps/core/components/public/fontawesome_4/stylesheets/font_awesome.scss +17 -0
  110. data/apps/core/components/public/js/paginatore.js +307 -0
  111. data/apps/core/components/public/js/spin.js +399 -0
  112. data/apps/core/components/public/mmenu/js/jquery.mmenu.js +133 -0
  113. data/apps/core/components/public/mmenu/scss/extensions/_jquery.mmenu.borderstyle.scss +33 -0
  114. data/apps/core/components/public/mmenu/scss/extensions/_jquery.mmenu.effects.scss +199 -0
  115. data/apps/core/components/public/mmenu/scss/extensions/_jquery.mmenu.fullscreen.scss +24 -0
  116. data/apps/core/components/public/mmenu/scss/extensions/_jquery.mmenu.iconbar.scss +26 -0
  117. data/apps/core/components/public/mmenu/scss/extensions/_jquery.mmenu.multiline.scss +15 -0
  118. data/apps/core/components/public/mmenu/scss/extensions/_jquery.mmenu.pagedim.scss +36 -0
  119. data/apps/core/components/public/mmenu/scss/extensions/_jquery.mmenu.pageshadow.scss +36 -0
  120. data/apps/core/components/public/mmenu/scss/extensions/_jquery.mmenu.positioning.scss +87 -0
  121. data/apps/core/components/public/mmenu/scss/extensions/_jquery.mmenu.themes.scss +76 -0
  122. data/apps/core/components/public/mmenu/scss/extensions/_jquery.mmenu.tileview.scss +98 -0
  123. data/apps/core/components/public/mmenu/scss/extensions/_jquery.mmenu.widescreen.scss +61 -0
  124. data/apps/core/components/public/mmenu/scss/inc/_colors.scss +175 -0
  125. data/apps/core/components/public/mmenu/scss/inc/_mixins.scss +135 -0
  126. data/apps/core/components/public/mmenu/scss/inc/_sizing.scss +86 -0
  127. data/apps/core/components/public/mmenu/scss/inc/_variables.scss +61 -0
  128. data/apps/core/components/public/mmenu/scss/jquery.mmenu.scss +478 -0
  129. data/apps/core/components/widgets/table/table.rb +7 -0
  130. data/apps/core/components/widgets/table/table.shtml +50 -17
  131. data/apps/core/forms/tags/row.erb +1 -1
  132. data/lib/spiderfw/cmd/cmd.rb +2 -0
  133. data/lib/spiderfw/cmd/commands/assets.rb +12 -0
  134. data/lib/spiderfw/controller/mixins/visual.rb +1 -0
  135. data/lib/spiderfw/create.rb +0 -1
  136. data/lib/spiderfw/i18n/gettext.rb +33 -0
  137. data/lib/spiderfw/i18n/javascript_parser.rb +2 -2
  138. data/lib/spiderfw/i18n/shtml_parser.rb +2 -2
  139. data/lib/spiderfw/model/model.rb +2 -1
  140. data/lib/spiderfw/setup/app_manager.rb +8 -0
  141. data/lib/spiderfw/spider.rb +9 -1
  142. data/lib/spiderfw/templates/layout.rb +47 -39
  143. data/lib/spiderfw/templates/template.rb +12 -4
  144. metadata +46 -1
@@ -1,8 +1,8 @@
1
1
  /* ========================================================================
2
- * Bootstrap: popover.js v3.1.1
2
+ * Bootstrap: popover.js v3.3.5
3
3
  * http://getbootstrap.com/javascript/#popovers
4
4
  * ========================================================================
5
- * Copyright 2011-2014 Twitter, Inc.
5
+ * Copyright 2011-2015 Twitter, Inc.
6
6
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7
7
  * ======================================================================== */
8
8
 
@@ -19,7 +19,7 @@
19
19
 
20
20
  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
21
21
 
22
- Popover.VERSION = '3.1.1'
22
+ Popover.VERSION = '3.3.5'
23
23
 
24
24
  Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
25
25
  placement: 'right',
@@ -46,7 +46,7 @@
46
46
  var content = this.getContent()
47
47
 
48
48
  $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
49
- $tip.find('.popover-content').empty()[ // we use append for html objects to maintain js events
49
+ $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events
50
50
  this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
51
51
  ](content)
52
52
 
@@ -72,12 +72,7 @@
72
72
  }
73
73
 
74
74
  Popover.prototype.arrow = function () {
75
- return this.$arrow = this.$arrow || this.tip().find('.arrow')
76
- }
77
-
78
- Popover.prototype.tip = function () {
79
- if (!this.$tip) this.$tip = $(this.options.template)
80
- return this.$tip
75
+ return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
81
76
  }
82
77
 
83
78
 
@@ -90,7 +85,7 @@
90
85
  var data = $this.data('bs.popover')
91
86
  var options = typeof option == 'object' && option
92
87
 
93
- if (!data && option == 'destroy') return
88
+ if (!data && /destroy|hide/.test(option)) return
94
89
  if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
95
90
  if (typeof option == 'string') data[option]()
96
91
  })
@@ -1,8 +1,8 @@
1
1
  /* ========================================================================
2
- * Bootstrap: scrollspy.js v3.1.1
2
+ * Bootstrap: scrollspy.js v3.3.5
3
3
  * http://getbootstrap.com/javascript/#scrollspy
4
4
  * ========================================================================
5
- * Copyright 2011-2014 Twitter, Inc.
5
+ * Copyright 2011-2015 Twitter, Inc.
6
6
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7
7
  * ======================================================================== */
8
8
 
@@ -14,41 +14,46 @@
14
14
  // ==========================
15
15
 
16
16
  function ScrollSpy(element, options) {
17
- var href
18
- var process = $.proxy(this.process, this)
19
-
20
- this.$element = $(element).is('body') ? $(window) : $(element)
21
- this.$body = $('body')
22
- this.$scrollElement = this.$element.on('scroll.bs.scrollspy', process)
17
+ this.$body = $(document.body)
18
+ this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
23
19
  this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
24
- this.selector = (this.options.target
25
- || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7
26
- || '') + ' .nav li > a'
27
- this.offsets = $([])
28
- this.targets = $([])
20
+ this.selector = (this.options.target || '') + ' .nav li > a'
21
+ this.offsets = []
22
+ this.targets = []
29
23
  this.activeTarget = null
24
+ this.scrollHeight = 0
30
25
 
26
+ this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
31
27
  this.refresh()
32
28
  this.process()
33
29
  }
34
30
 
35
- ScrollSpy.VERSION = '3.1.1'
31
+ ScrollSpy.VERSION = '3.3.5'
36
32
 
37
33
  ScrollSpy.DEFAULTS = {
38
34
  offset: 10
39
35
  }
40
36
 
37
+ ScrollSpy.prototype.getScrollHeight = function () {
38
+ return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
39
+ }
40
+
41
41
  ScrollSpy.prototype.refresh = function () {
42
- var offsetMethod = this.$element[0] == window ? 'offset' : 'position'
42
+ var that = this
43
+ var offsetMethod = 'offset'
44
+ var offsetBase = 0
43
45
 
44
- this.offsets = $([])
45
- this.targets = $([])
46
+ this.offsets = []
47
+ this.targets = []
48
+ this.scrollHeight = this.getScrollHeight()
46
49
 
47
- var self = this
50
+ if (!$.isWindow(this.$scrollElement[0])) {
51
+ offsetMethod = 'position'
52
+ offsetBase = this.$scrollElement.scrollTop()
53
+ }
48
54
 
49
55
  this.$body
50
56
  .find(this.selector)
51
- .filter(':visible')
52
57
  .map(function () {
53
58
  var $el = $(this)
54
59
  var href = $el.data('target') || $el.attr('href')
@@ -57,50 +62,53 @@
57
62
  return ($href
58
63
  && $href.length
59
64
  && $href.is(':visible')
60
- && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null
65
+ && [[$href[offsetMethod]().top + offsetBase, href]]) || null
61
66
  })
62
67
  .sort(function (a, b) { return a[0] - b[0] })
63
68
  .each(function () {
64
- self.offsets.push(this[0])
65
- self.targets.push(this[1])
69
+ that.offsets.push(this[0])
70
+ that.targets.push(this[1])
66
71
  })
67
72
  }
68
73
 
69
74
  ScrollSpy.prototype.process = function () {
70
75
  var scrollTop = this.$scrollElement.scrollTop() + this.options.offset
71
- var scrollHeight = this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
76
+ var scrollHeight = this.getScrollHeight()
72
77
  var maxScroll = this.options.offset + scrollHeight - this.$scrollElement.height()
73
78
  var offsets = this.offsets
74
79
  var targets = this.targets
75
80
  var activeTarget = this.activeTarget
76
81
  var i
77
82
 
83
+ if (this.scrollHeight != scrollHeight) {
84
+ this.refresh()
85
+ }
86
+
78
87
  if (scrollTop >= maxScroll) {
79
- return activeTarget != (i = targets.last()[0]) && this.activate(i)
88
+ return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
80
89
  }
81
90
 
82
- if (activeTarget && scrollTop <= offsets[0]) {
83
- return activeTarget != (i = targets[0]) && this.activate(i)
91
+ if (activeTarget && scrollTop < offsets[0]) {
92
+ this.activeTarget = null
93
+ return this.clear()
84
94
  }
85
95
 
86
96
  for (i = offsets.length; i--;) {
87
97
  activeTarget != targets[i]
88
98
  && scrollTop >= offsets[i]
89
- && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
90
- && this.activate( targets[i] )
99
+ && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
100
+ && this.activate(targets[i])
91
101
  }
92
102
  }
93
103
 
94
104
  ScrollSpy.prototype.activate = function (target) {
95
105
  this.activeTarget = target
96
106
 
97
- $(this.selector)
98
- .parentsUntil(this.options.target, '.active')
99
- .removeClass('active')
107
+ this.clear()
100
108
 
101
109
  var selector = this.selector +
102
- '[data-target="' + target + '"],' +
103
- this.selector + '[href="' + target + '"]'
110
+ '[data-target="' + target + '"],' +
111
+ this.selector + '[href="' + target + '"]'
104
112
 
105
113
  var active = $(selector)
106
114
  .parents('li')
@@ -115,6 +123,12 @@
115
123
  active.trigger('activate.bs.scrollspy')
116
124
  }
117
125
 
126
+ ScrollSpy.prototype.clear = function () {
127
+ $(this.selector)
128
+ .parentsUntil(this.options.target, '.active')
129
+ .removeClass('active')
130
+ }
131
+
118
132
 
119
133
  // SCROLLSPY PLUGIN DEFINITION
120
134
  // ===========================
@@ -1,8 +1,8 @@
1
1
  /* ========================================================================
2
- * Bootstrap: tab.js v3.1.1
2
+ * Bootstrap: tab.js v3.3.5
3
3
  * http://getbootstrap.com/javascript/#tabs
4
4
  * ========================================================================
5
- * Copyright 2011-2014 Twitter, Inc.
5
+ * Copyright 2011-2015 Twitter, Inc.
6
6
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
7
7
  * ======================================================================== */
8
8
 
@@ -14,10 +14,14 @@
14
14
  // ====================
15
15
 
16
16
  var Tab = function (element) {
17
+ // jscs:disable requireDollarBeforejQueryAssignment
17
18
  this.element = $(element)
19
+ // jscs:enable requireDollarBeforejQueryAssignment
18
20
  }
19
21
 
20
- Tab.VERSION = '3.1.1'
22
+ Tab.VERSION = '3.3.5'
23
+
24
+ Tab.TRANSITION_DURATION = 150
21
25
 
22
26
  Tab.prototype.show = function () {
23
27
  var $this = this.element
@@ -26,27 +30,35 @@
26
30
 
27
31
  if (!selector) {
28
32
  selector = $this.attr('href')
29
- selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
33
+ selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
30
34
  }
31
35
 
32
36
  if ($this.parent('li').hasClass('active')) return
33
37
 
34
- var previous = $ul.find('.active:last a')[0]
35
- var e = $.Event('show.bs.tab', {
36
- relatedTarget: previous
38
+ var $previous = $ul.find('.active:last a')
39
+ var hideEvent = $.Event('hide.bs.tab', {
40
+ relatedTarget: $this[0]
41
+ })
42
+ var showEvent = $.Event('show.bs.tab', {
43
+ relatedTarget: $previous[0]
37
44
  })
38
45
 
39
- $this.trigger(e)
46
+ $previous.trigger(hideEvent)
47
+ $this.trigger(showEvent)
40
48
 
41
- if (e.isDefaultPrevented()) return
49
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return
42
50
 
43
51
  var $target = $(selector)
44
52
 
45
53
  this.activate($this.closest('li'), $ul)
46
54
  this.activate($target, $target.parent(), function () {
55
+ $previous.trigger({
56
+ type: 'hidden.bs.tab',
57
+ relatedTarget: $this[0]
58
+ })
47
59
  $this.trigger({
48
60
  type: 'shown.bs.tab',
49
- relatedTarget: previous
61
+ relatedTarget: $previous[0]
50
62
  })
51
63
  })
52
64
  }
@@ -55,15 +67,21 @@
55
67
  var $active = container.find('> .active')
56
68
  var transition = callback
57
69
  && $.support.transition
58
- && $active.hasClass('fade')
70
+ && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
59
71
 
60
72
  function next() {
61
73
  $active
62
74
  .removeClass('active')
63
75
  .find('> .dropdown-menu > .active')
64
- .removeClass('active')
76
+ .removeClass('active')
77
+ .end()
78
+ .find('[data-toggle="tab"]')
79
+ .attr('aria-expanded', false)
65
80
 
66
- element.addClass('active')
81
+ element
82
+ .addClass('active')
83
+ .find('[data-toggle="tab"]')
84
+ .attr('aria-expanded', true)
67
85
 
68
86
  if (transition) {
69
87
  element[0].offsetWidth // reflow for transition
@@ -72,17 +90,22 @@
72
90
  element.removeClass('fade')
73
91
  }
74
92
 
75
- if (element.parent('.dropdown-menu')) {
76
- element.closest('li.dropdown').addClass('active')
93
+ if (element.parent('.dropdown-menu').length) {
94
+ element
95
+ .closest('li.dropdown')
96
+ .addClass('active')
97
+ .end()
98
+ .find('[data-toggle="tab"]')
99
+ .attr('aria-expanded', true)
77
100
  }
78
101
 
79
102
  callback && callback()
80
103
  }
81
104
 
82
- transition ?
105
+ $active.length && transition ?
83
106
  $active
84
- .one($.support.transition.end, next)
85
- .emulateTransitionEnd(150) :
107
+ .one('bsTransitionEnd', next)
108
+ .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
86
109
  next()
87
110
 
88
111
  $active.removeClass('in')
@@ -92,7 +115,7 @@
92
115
  // TAB PLUGIN DEFINITION
93
116
  // =====================
94
117
 
95
- function Plugin( option ) {
118
+ function Plugin(option) {
96
119
  return this.each(function () {
97
120
  var $this = $(this)
98
121
  var data = $this.data('bs.tab')
@@ -120,9 +143,13 @@
120
143
  // TAB DATA-API
121
144
  // ============
122
145
 
123
- $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
146
+ var clickHandler = function (e) {
124
147
  e.preventDefault()
125
148
  Plugin.call($(this), 'show')
126
- })
149
+ }
150
+
151
+ $(document)
152
+ .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
153
+ .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)
127
154
 
128
155
  }(jQuery);
@@ -1,9 +1,9 @@
1
1
  /* ========================================================================
2
- * Bootstrap: tooltip.js v3.1.1
2
+ * Bootstrap: tooltip.js v3.3.5
3
3
  * http://getbootstrap.com/javascript/#tooltip
4
4
  * Inspired by the original jQuery.tipsy by Jason Frame
5
5
  * ========================================================================
6
- * Copyright 2011-2014 Twitter, Inc.
6
+ * Copyright 2011-2015 Twitter, Inc.
7
7
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
8
8
  * ======================================================================== */
9
9
 
@@ -15,17 +15,20 @@
15
15
  // ===============================
16
16
 
17
17
  var Tooltip = function (element, options) {
18
- this.type =
19
- this.options =
20
- this.enabled =
21
- this.timeout =
22
- this.hoverState =
18
+ this.type = null
19
+ this.options = null
20
+ this.enabled = null
21
+ this.timeout = null
22
+ this.hoverState = null
23
23
  this.$element = null
24
+ this.inState = null
24
25
 
25
26
  this.init('tooltip', element, options)
26
27
  }
27
28
 
28
- Tooltip.VERSION = '3.1.1'
29
+ Tooltip.VERSION = '3.3.5'
30
+
31
+ Tooltip.TRANSITION_DURATION = 150
29
32
 
30
33
  Tooltip.DEFAULTS = {
31
34
  animation: true,
@@ -48,7 +51,12 @@
48
51
  this.type = type
49
52
  this.$element = $(element)
50
53
  this.options = this.getOptions(options)
51
- this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
54
+ this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
55
+ this.inState = { click: false, hover: false, focus: false }
56
+
57
+ if (this.$element[0] instanceof document.constructor && !this.options.selector) {
58
+ throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
59
+ }
52
60
 
53
61
  var triggers = this.options.trigger.split(' ')
54
62
 
@@ -108,6 +116,15 @@
108
116
  $(obj.currentTarget).data('bs.' + this.type, self)
109
117
  }
110
118
 
119
+ if (obj instanceof $.Event) {
120
+ self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
121
+ }
122
+
123
+ if (self.tip().hasClass('in') || self.hoverState == 'in') {
124
+ self.hoverState = 'in'
125
+ return
126
+ }
127
+
111
128
  clearTimeout(self.timeout)
112
129
 
113
130
  self.hoverState = 'in'
@@ -119,6 +136,14 @@
119
136
  }, self.options.delay.show)
120
137
  }
121
138
 
139
+ Tooltip.prototype.isInStateTrue = function () {
140
+ for (var key in this.inState) {
141
+ if (this.inState[key]) return true
142
+ }
143
+
144
+ return false
145
+ }
146
+
122
147
  Tooltip.prototype.leave = function (obj) {
123
148
  var self = obj instanceof this.constructor ?
124
149
  obj : $(obj.currentTarget).data('bs.' + this.type)
@@ -128,6 +153,12 @@
128
153
  $(obj.currentTarget).data('bs.' + this.type, self)
129
154
  }
130
155
 
156
+ if (obj instanceof $.Event) {
157
+ self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
158
+ }
159
+
160
+ if (self.isInStateTrue()) return
161
+
131
162
  clearTimeout(self.timeout)
132
163
 
133
164
  self.hoverState = 'out'
@@ -145,8 +176,9 @@
145
176
  if (this.hasContent() && this.enabled) {
146
177
  this.$element.trigger(e)
147
178
 
148
- if (e.isDefaultPrevented()) return
149
- var that = this;
179
+ var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
180
+ if (e.isDefaultPrevented() || !inDom) return
181
+ var that = this
150
182
 
151
183
  var $tip = this.tip()
152
184
 
@@ -173,6 +205,7 @@
173
205
  .data('bs.' + this.type, this)
174
206
 
175
207
  this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
208
+ this.$element.trigger('inserted.bs.' + this.type)
176
209
 
177
210
  var pos = this.getPosition()
178
211
  var actualWidth = $tip[0].offsetWidth
@@ -180,13 +213,12 @@
180
213
 
181
214
  if (autoPlace) {
182
215
  var orgPlacement = placement
183
- var $parent = this.$element.parent()
184
- var parentDim = this.getPosition($parent)
216
+ var viewportDim = this.getPosition(this.$viewport)
185
217
 
186
- placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' :
187
- placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' :
188
- placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' :
189
- placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' :
218
+ placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
219
+ placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
220
+ placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
221
+ placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
190
222
  placement
191
223
 
192
224
  $tip
@@ -197,16 +229,19 @@
197
229
  var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
198
230
 
199
231
  this.applyPlacement(calculatedOffset, placement)
200
- this.hoverState = null
201
232
 
202
- var complete = function() {
233
+ var complete = function () {
234
+ var prevHoverState = that.hoverState
203
235
  that.$element.trigger('shown.bs.' + that.type)
236
+ that.hoverState = null
237
+
238
+ if (prevHoverState == 'out') that.leave(that)
204
239
  }
205
240
 
206
241
  $.support.transition && this.$tip.hasClass('fade') ?
207
242
  $tip
208
- .one($.support.transition.end, complete)
209
- .emulateTransitionEnd(150) :
243
+ .one('bsTransitionEnd', complete)
244
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
210
245
  complete()
211
246
  }
212
247
  }
@@ -224,8 +259,8 @@
224
259
  if (isNaN(marginTop)) marginTop = 0
225
260
  if (isNaN(marginLeft)) marginLeft = 0
226
261
 
227
- offset.top = offset.top + marginTop
228
- offset.left = offset.left + marginLeft
262
+ offset.top += marginTop
263
+ offset.left += marginLeft
229
264
 
230
265
  // $.fn.offset doesn't round pixel values
231
266
  // so we use setOffset directly with our own function B-0
@@ -253,16 +288,18 @@
253
288
  if (delta.left) offset.left += delta.left
254
289
  else offset.top += delta.top
255
290
 
256
- var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
257
- var arrowPosition = delta.left ? 'left' : 'top'
258
- var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
291
+ var isVertical = /top|bottom/.test(placement)
292
+ var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
293
+ var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'
259
294
 
260
295
  $tip.offset(offset)
261
- this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
296
+ this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
262
297
  }
263
298
 
264
- Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
265
- this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
299
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
300
+ this.arrow()
301
+ .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
302
+ .css(isVertical ? 'top' : 'left', '')
266
303
  }
267
304
 
268
305
  Tooltip.prototype.setContent = function () {
@@ -273,16 +310,17 @@
273
310
  $tip.removeClass('fade in top bottom left right')
274
311
  }
275
312
 
276
- Tooltip.prototype.hide = function () {
313
+ Tooltip.prototype.hide = function (callback) {
277
314
  var that = this
278
- var $tip = this.tip()
315
+ var $tip = $(this.$tip)
279
316
  var e = $.Event('hide.bs.' + this.type)
280
317
 
281
- this.$element.removeAttr('aria-describedby')
282
-
283
318
  function complete() {
284
319
  if (that.hoverState != 'in') $tip.detach()
285
- that.$element.trigger('hidden.bs.' + that.type)
320
+ that.$element
321
+ .removeAttr('aria-describedby')
322
+ .trigger('hidden.bs.' + that.type)
323
+ callback && callback()
286
324
  }
287
325
 
288
326
  this.$element.trigger(e)
@@ -291,10 +329,10 @@
291
329
 
292
330
  $tip.removeClass('in')
293
331
 
294
- $.support.transition && this.$tip.hasClass('fade') ?
332
+ $.support.transition && $tip.hasClass('fade') ?
295
333
  $tip
296
- .one($.support.transition.end, complete)
297
- .emulateTransitionEnd(150) :
334
+ .one('bsTransitionEnd', complete)
335
+ .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
298
336
  complete()
299
337
 
300
338
  this.hoverState = null
@@ -304,7 +342,7 @@
304
342
 
305
343
  Tooltip.prototype.fixTitle = function () {
306
344
  var $e = this.$element
307
- if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {
345
+ if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
308
346
  $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
309
347
  }
310
348
  }
@@ -315,20 +353,27 @@
315
353
 
316
354
  Tooltip.prototype.getPosition = function ($element) {
317
355
  $element = $element || this.$element
356
+
318
357
  var el = $element[0]
319
358
  var isBody = el.tagName == 'BODY'
320
- return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
321
- scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
322
- width: isBody ? $(window).width() : $element.outerWidth(),
323
- height: isBody ? $(window).height() : $element.outerHeight()
324
- }, isBody ? {top: 0, left: 0} : $element.offset())
359
+
360
+ var elRect = el.getBoundingClientRect()
361
+ if (elRect.width == null) {
362
+ // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
363
+ elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
364
+ }
365
+ var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
366
+ var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
367
+ var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
368
+
369
+ return $.extend({}, elRect, scroll, outerDims, elOffset)
325
370
  }
326
371
 
327
372
  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
328
- return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
329
- placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
373
+ return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
374
+ placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
330
375
  placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
331
- /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
376
+ /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }
332
377
 
333
378
  }
334
379
 
@@ -352,7 +397,7 @@
352
397
  var rightEdgeOffset = pos.left + viewportPadding + actualWidth
353
398
  if (leftEdgeOffset < viewportDimensions.left) { // left overflow
354
399
  delta.left = viewportDimensions.left - leftEdgeOffset
355
- } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
400
+ } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
356
401
  delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
357
402
  }
358
403
  }
@@ -378,19 +423,17 @@
378
423
  }
379
424
 
380
425
  Tooltip.prototype.tip = function () {
381
- return this.$tip = this.$tip || $(this.options.template)
426
+ if (!this.$tip) {
427
+ this.$tip = $(this.options.template)
428
+ if (this.$tip.length != 1) {
429
+ throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
430
+ }
431
+ }
432
+ return this.$tip
382
433
  }
383
434
 
384
435
  Tooltip.prototype.arrow = function () {
385
- return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')
386
- }
387
-
388
- Tooltip.prototype.validate = function () {
389
- if (!this.$element[0].parentNode) {
390
- this.hide()
391
- this.$element = null
392
- this.options = null
393
- }
436
+ return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
394
437
  }
395
438
 
396
439
  Tooltip.prototype.enable = function () {
@@ -415,12 +458,27 @@
415
458
  }
416
459
  }
417
460
 
418
- self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
461
+ if (e) {
462
+ self.inState.click = !self.inState.click
463
+ if (self.isInStateTrue()) self.enter(self)
464
+ else self.leave(self)
465
+ } else {
466
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
467
+ }
419
468
  }
420
469
 
421
470
  Tooltip.prototype.destroy = function () {
471
+ var that = this
422
472
  clearTimeout(this.timeout)
423
- this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
473
+ this.hide(function () {
474
+ that.$element.off('.' + that.type).removeData('bs.' + that.type)
475
+ if (that.$tip) {
476
+ that.$tip.detach()
477
+ }
478
+ that.$tip = null
479
+ that.$arrow = null
480
+ that.$viewport = null
481
+ })
424
482
  }
425
483
 
426
484
 
@@ -433,7 +491,7 @@
433
491
  var data = $this.data('bs.tooltip')
434
492
  var options = typeof option == 'object' && option
435
493
 
436
- if (!data && option == 'destroy') return
494
+ if (!data && /destroy|hide/.test(option)) return
437
495
  if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
438
496
  if (typeof option == 'string') data[option]()
439
497
  })