bootstrap.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /**
  2. * @file
  3. * bootstrap.js
  4. *
  5. * Provides general enhancements and fixes to Bootstrap's JS files.
  6. */
  7. var Drupal = Drupal || {};
  8. (function($, Drupal){
  9. "use strict";
  10. Drupal.behaviors.bootstrap = {
  11. attach: function(context) {
  12. // Provide some Bootstrap tab/Drupal integration.
  13. $(context).find('.tabbable').once('bootstrap-tabs', function () {
  14. var $wrapper = $(this);
  15. var $tabs = $wrapper.find('.nav-tabs');
  16. var $content = $wrapper.find('.tab-content');
  17. var borderRadius = parseInt($content.css('borderBottomRightRadius'), 10);
  18. var bootstrapTabResize = function() {
  19. if ($wrapper.hasClass('tabs-left') || $wrapper.hasClass('tabs-right')) {
  20. $content.css('min-height', $tabs.outerHeight());
  21. }
  22. };
  23. // Add min-height on content for left and right tabs.
  24. bootstrapTabResize();
  25. // Detect tab switch.
  26. if ($wrapper.hasClass('tabs-left') || $wrapper.hasClass('tabs-right')) {
  27. $tabs.on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
  28. bootstrapTabResize();
  29. if ($wrapper.hasClass('tabs-left')) {
  30. if ($(e.target).parent().is(':first-child')) {
  31. $content.css('borderTopLeftRadius', '0');
  32. }
  33. else {
  34. $content.css('borderTopLeftRadius', borderRadius + 'px');
  35. }
  36. }
  37. else {
  38. if ($(e.target).parent().is(':first-child')) {
  39. $content.css('borderTopRightRadius', '0');
  40. }
  41. else {
  42. $content.css('borderTopRightRadius', borderRadius + 'px');
  43. }
  44. }
  45. });
  46. }
  47. });
  48. }
  49. };
  50. /**
  51. * Behavior for .
  52. */
  53. Drupal.behaviors.bootstrapFormHasError = {
  54. attach: function (context, settings) {
  55. if (settings.bootstrap && settings.bootstrap.formHasError) {
  56. var $context = $(context);
  57. $context.find('.form-item.has-error:not(.form-type-password.has-feedback)').once('error', function () {
  58. var $formItem = $(this);
  59. var $input = $formItem.find(':input');
  60. $input.on('keyup focus blur', function () {
  61. var value = $input.val() || false;
  62. $formItem[value ? 'removeClass' : 'addClass']('has-error');
  63. $input[value ? 'removeClass' : 'addClass']('error');
  64. });
  65. });
  66. }
  67. }
  68. };
  69. /**
  70. * Bootstrap Popovers.
  71. */
  72. Drupal.behaviors.bootstrapPopovers = {
  73. attach: function (context, settings) {
  74. if (settings.bootstrap && settings.bootstrap.popoverEnabled) {
  75. var $currentPopover = $();
  76. if (settings.bootstrap.popoverOptions.triggerAutoclose) {
  77. $(document).on('click', function (e) {
  78. if ($currentPopover.length && !$(e.target).is('[data-toggle=popover]') && $(e.target).parents('.popover.in').length === 0) {
  79. $currentPopover.popover('hide');
  80. $currentPopover = $();
  81. }
  82. });
  83. }
  84. var elements = $(context).find('[data-toggle=popover]').toArray();
  85. for (var i = 0; i < elements.length; i++) {
  86. var $element = $(elements[i]);
  87. var options = $.extend({}, settings.bootstrap.popoverOptions, $element.data());
  88. if (!options.content) {
  89. options.content = function () {
  90. var target = $(this).data('target');
  91. return target && $(target) && $(target).length && $(target).clone().removeClass('element-invisible').wrap('<div/>').parent()[$(this).data('bs.popover').options.html ? 'html' : 'text']() || '';
  92. }
  93. }
  94. $element.popover(options).on('click', function (e) {
  95. e.preventDefault();
  96. });
  97. if (settings.bootstrap.popoverOptions.triggerAutoclose) {
  98. $element.on('show.bs.popover', function () {
  99. if ($currentPopover.length) {
  100. $currentPopover.popover('hide');
  101. }
  102. $currentPopover = $(this);
  103. });
  104. }
  105. }
  106. }
  107. }
  108. };
  109. /**
  110. * Bootstrap Tooltips.
  111. */
  112. Drupal.behaviors.bootstrapTooltips = {
  113. attach: function (context, settings) {
  114. if (settings.bootstrap && settings.bootstrap.tooltipEnabled) {
  115. var elements = $(context).find('[data-toggle="tooltip"]').toArray();
  116. for (var i = 0; i < elements.length; i++) {
  117. var $element = $(elements[i]);
  118. var options = $.extend({}, settings.bootstrap.tooltipOptions, $element.data());
  119. $element.tooltip(options);
  120. }
  121. }
  122. }
  123. };
  124. /**
  125. * Anchor fixes.
  126. */
  127. var $scrollableElement = $();
  128. Drupal.behaviors.bootstrapAnchors = {
  129. attach: function(context, settings) {
  130. var i, elements = ['html', 'body'];
  131. if (!$scrollableElement.length) {
  132. for (i = 0; i < elements.length; i++) {
  133. var $element = $(elements[i]);
  134. if ($element.scrollTop() > 0) {
  135. $scrollableElement = $element;
  136. break;
  137. }
  138. else {
  139. $element.scrollTop(1);
  140. if ($element.scrollTop() > 0) {
  141. $element.scrollTop(0);
  142. $scrollableElement = $element;
  143. break;
  144. }
  145. }
  146. }
  147. }
  148. if (!settings.bootstrap || settings.bootstrap.anchorsFix !== '1') {
  149. return;
  150. }
  151. var anchors = $(context).find('a').toArray();
  152. for (i = 0; i < anchors.length; i++) {
  153. if (!anchors[i].scrollTo) {
  154. this.bootstrapAnchor(anchors[i]);
  155. }
  156. }
  157. $scrollableElement.once('bootstrap-anchors', function () {
  158. $scrollableElement.on('click.bootstrap-anchors', 'a[href*="#"]:not([data-toggle],[data-target],[data-slide])', function(e) {
  159. if (this.scrollTo) {
  160. this.scrollTo(e);
  161. }
  162. });
  163. });
  164. },
  165. bootstrapAnchor: function (element) {
  166. element.validAnchor = element.nodeName === 'A' && (location.hostname === element.hostname || !element.hostname) && (element.hash.replace(/#/,'').length > 0);
  167. element.scrollTo = function(event) {
  168. var attr = 'id';
  169. var $target = $(element.hash);
  170. // Check for anchors that use the name attribute instead.
  171. if (!$target.length) {
  172. attr = 'name';
  173. $target = $('[name="' + element.hash.replace('#', '') + '"]');
  174. }
  175. // Immediately stop if no anchors are found.
  176. if (!this.validAnchor && !$target.length) {
  177. return;
  178. }
  179. // Anchor is valid, continue if there is an offset.
  180. var offset = $target.offset().top - parseInt($scrollableElement.css('paddingTop'), 10) - parseInt($scrollableElement.css('marginTop'), 10);
  181. if (offset > 0) {
  182. if (event) {
  183. event.preventDefault();
  184. }
  185. var $fakeAnchor = $('<div/>')
  186. .addClass('element-invisible')
  187. .attr(attr, $target.attr(attr))
  188. .css({
  189. position: 'absolute',
  190. top: offset + 'px',
  191. zIndex: -1000
  192. })
  193. .appendTo($scrollableElement);
  194. $target.removeAttr(attr);
  195. var complete = function () {
  196. location.hash = element.hash;
  197. $fakeAnchor.remove();
  198. $target.attr(attr, element.hash.replace('#', ''));
  199. };
  200. if (Drupal.settings.bootstrap.anchorsSmoothScrolling) {
  201. $scrollableElement.animate({ scrollTop: offset, avoidTransforms: true }, 400, complete);
  202. }
  203. else {
  204. $scrollableElement.scrollTop(offset);
  205. complete();
  206. }
  207. }
  208. };
  209. }
  210. };
  211. /**
  212. * Tabledrag theming elements.
  213. */
  214. Drupal.theme.tableDragChangedMarker = function () {
  215. return '<span class="tabledrag-changed glyphicon glyphicon-warning-sign text-warning"></span>';
  216. };
  217. Drupal.theme.tableDragChangedWarning = function () {
  218. return '<div class="tabledrag-changed-warning alert alert-warning messages warning">' + Drupal.theme('tableDragChangedMarker') + ' ' + Drupal.t('Changes made in this table will not be saved until the form is submitted.') + '</div>';
  219. };
  220. })(jQuery, Drupal);