fix vertical top menu underline width
[ryf-theme.git] / 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 // Unfortunately, :focusable is only made available when using jQuery
63 // UI. While this would be the most semantic pseudo selector to use
64 // here, jQuery UI may not always be loaded. Instead, just use :visible
65 // here as this just needs some sort of selector here. This activates
66 // delegate binding to elements in jQuery so it can work it's bubbling
67 // focus magic since elements don't really propagate their focus events.
68 // @see https://www.drupal.org/project/bootstrap/issues/3013236
69 .on('focus.bs.popover', ':visible', function (e) {
70 var $target = $(e.target);
71 if (_this.$activePopover && _this.getOption('autoClose') && !_this.$activePopover.is($target) && !$target.closest('.popover.in')[0]) {
72 _this.$activePopover.popover('hide');
73 _this.$activePopover = null;
74 }
75 })
76 .on('click.bs.popover', function (e) {
77 var $target = $(e.target);
78 if (_this.$activePopover && _this.getOption('autoClose') && !$target.is('[data-toggle=popover]') && !$target.closest('.popover.in')[0]) {
79 _this.$activePopover.popover('hide');
80 _this.$activePopover = null;
81 }
82 })
83 .on('keyup.bs.popover', function (e) {
84 if (_this.$activePopover && _this.getOption('autoClose') && e.which === 27) {
85 _this.$activePopover.popover('hide');
86 _this.$activePopover = null;
87 }
88 })
89 ;
90
91 var elements = $(context).find('[data-toggle=popover]').toArray();
92 for (var i = 0; i < elements.length; i++) {
93 var $element = $(elements[i]);
94 var options = $.extend({}, $.fn.popover.Constructor.DEFAULTS, $element.data());
95
96 // Store the original trigger.
97 options.originalTrigger = options.trigger;
98
99 // If the trigger is "click", then we'll handle it manually here.
100 if (options.trigger === 'click') {
101 options.trigger = 'manual';
102 }
103
104 // Retrieve content from a target element.
105 var target = options.target || $element.is('a[href^="#"]') && $element.attr('href');
106 var $target = $document.find(target).clone();
107 if (!options.content && $target[0]) {
108 $target.removeClass('visually-hidden hidden').removeAttr('aria-hidden');
109 options.content = $target.wrap('<div/>').parent()[options.html ? 'html' : 'text']() || '';
110 }
111
112 // Initialize the popover.
113 $element.popover(options);
114
115 // Handle clicks manually.
116 if (options.originalTrigger === 'click') {
117 // To ensure the element is bound multiple times, remove any
118 // previously set event handler before adding another one.
119 $element
120 .off('click.drupal.bootstrap.popover')
121 .on('click.drupal.bootstrap.popover', function (e) {
122 $(this).popover('toggle');
123 e.preventDefault();
124 e.stopPropagation();
125 })
126 ;
127 }
128 }
129 },
130 detach: function (context) {
131 // Immediately return if popovers are not available.
132 if (!$.fn.popover || !$.fn.popover.Constructor.DEFAULTS.enabled) {
133 return;
134 }
135
136 // Destroy all popovers.
137 $(context).find('[data-toggle="popover"]')
138 .off('click.drupal.bootstrap.popover')
139 .popover('destroy')
140 ;
141 },
142 getOption: function(name, defaultValue, element) {
143 var $element = element ? $(element) : this.$activePopover;
144 var options = $.extend(true, {}, $.fn.popover.Constructor.DEFAULTS, ($element && $element.data('bs.popover') || {}).options);
145 if (options[name] !== void 0) {
146 return options[name];
147 }
148 return defaultValue !== void 0 ? defaultValue : void 0;
149 }
150 };
151
152 })(window.jQuery, window.Drupal, window.Drupal.bootstrap);