Updated the Bootstrap theme.
[yaffs-website] / web / themes / contrib / bootstrap / js / popover.js
1 /**
2  * @file
3  * Bootstrap Popovers.
4  */
5
6 var Drupal = Drupal || {};
7
8 (function ($, Drupal, Bootstrap) {
9   "use strict";
10
11   var $document = $(document);
12
13   /**
14    * Extend the Bootstrap Popover plugin constructor class.
15    */
16   Bootstrap.extendPlugin('popover', function (settings) {
17     return {
18       DEFAULTS: {
19         animation: !!settings.popover_animation,
20         autoClose: !!settings.popover_auto_close,
21         enabled: settings.popover_enabled,
22         html: !!settings.popover_html,
23         placement: settings.popover_placement,
24         selector: settings.popover_selector,
25         trigger: settings.popover_trigger,
26         title: settings.popover_title,
27         content: settings.popover_content,
28         delay: parseInt(settings.popover_delay, 10),
29         container: settings.popover_container
30       }
31     };
32   });
33
34   /**
35    * Bootstrap Popovers.
36    *
37    * @todo This should really be properly delegated if selector option is set.
38    */
39   Drupal.behaviors.bootstrapPopovers = {
40     $activePopover: null,
41     attach: function (context) {
42       // Immediately return if popovers are not available.
43       if (!$.fn.popover || !$.fn.popover.Constructor.DEFAULTS.enabled) {
44         return;
45       }
46
47       var _this = this;
48
49       $document
50         .on('show.bs.popover', '[data-toggle=popover]', function () {
51           var $trigger = $(this);
52           var popover = $trigger.data('bs.popover');
53
54           // Only keep track of clicked triggers that we're manually handling.
55           if (popover.options.originalTrigger === 'click') {
56             if (_this.$activePopover && _this.getOption('autoClose') && !_this.$activePopover.is($trigger)) {
57               _this.$activePopover.popover('hide');
58             }
59             _this.$activePopover = $trigger;
60           }
61         })
62         .on('focus.bs.popover', ':focusable', function (e) {
63           var $target = $(e.target);
64           if (_this.$activePopover && _this.getOption('autoClose') && !_this.$activePopover.is($target) && !$target.closest('.popover.in')[0]) {
65             _this.$activePopover.popover('hide');
66             _this.$activePopover = null;
67           }
68         })
69         .on('click.bs.popover', function (e) {
70           var $target = $(e.target);
71           if (_this.$activePopover && _this.getOption('autoClose') && !$target.is('[data-toggle=popover]') && !$target.closest('.popover.in')[0]) {
72             _this.$activePopover.popover('hide');
73             _this.$activePopover = null;
74           }
75         })
76         .on('keyup.bs.popover', function (e) {
77           if (_this.$activePopover && _this.getOption('autoClose') && e.which === 27) {
78             _this.$activePopover.popover('hide');
79             _this.$activePopover = null;
80           }
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({}, $.fn.popover.Constructor.DEFAULTS, $element.data());
88
89         // Store the original trigger.
90         options.originalTrigger = options.trigger;
91
92         // If the trigger is "click", then we'll handle it manually here.
93         if (options.trigger === 'click') {
94           options.trigger = 'manual';
95         }
96
97         // Retrieve content from a target element.
98         var target = options.target || $element.is('a[href^="#"]') && $element.attr('href');
99         var $target = $document.find(target).clone();
100         if (!options.content && $target[0]) {
101           $target.removeClass('visually-hidden hidden').removeAttr('aria-hidden');
102           options.content = $target.wrap('<div/>').parent()[options.html ? 'html' : 'text']() || '';
103         }
104
105         // Initialize the popover.
106         $element.popover(options);
107
108         // Handle clicks manually.
109         if (options.originalTrigger === 'click') {
110           // To ensure the element is bound multiple times, remove any
111           // previously set event handler before adding another one.
112           $element
113             .off('click.drupal.bootstrap.popover')
114             .on('click.drupal.bootstrap.popover', function (e) {
115               $(this).popover('toggle');
116               e.preventDefault();
117               e.stopPropagation();
118             })
119           ;
120         }
121       }
122     },
123     detach: function (context) {
124       // Immediately return if popovers are not available.
125       if (!$.fn.popover || !$.fn.popover.Constructor.DEFAULTS.enabled) {
126         return;
127       }
128
129       // Destroy all popovers.
130       $(context).find('[data-toggle="popover"]')
131         .off('click.drupal.bootstrap.popover')
132         .popover('destroy')
133       ;
134     },
135     getOption: function(name, defaultValue, element) {
136       var $element = element ? $(element) : this.$activePopover;
137       var options = $.extend(true, {}, $.fn.popover.Constructor.DEFAULTS, (($element && $element.data('bs.popover')).options || {}).options);
138       if (options[name] !== void 0) {
139         return options[name];
140       }
141       return defaultValue !== void 0 ? defaultValue : void 0;
142     }
143   };
144
145 })(window.jQuery, window.Drupal, window.Drupal.bootstrap);