Version 1
[yaffs-website] / web / themes / contrib / bootstrap / js / drupal.bootstrap.js
1 /**
2  * @file
3  * Drupal Bootstrap object.
4  */
5
6 /**
7  * All Drupal Bootstrap JavaScript APIs are contained in this namespace.
8  *
9  * @namespace
10  */
11 (function ($, Drupal, drupalSettings) {
12   'use strict';
13
14   Drupal.bootstrap = {
15     settings: drupalSettings.bootstrap || {}
16   };
17
18   /**
19    * Wraps Drupal.checkPlain() to ensure value passed isn't empty.
20    *
21    * Encodes special characters in a plain-text string for display as HTML.
22    *
23    * @param {string} str
24    *   The string to be encoded.
25    *
26    * @return {string}
27    *   The encoded string.
28    *
29    * @ingroup sanitization
30    */
31   Drupal.bootstrap.checkPlain = function (str) {
32     return str && Drupal.checkPlain(str) || '';
33   };
34
35   /**
36    * Extends a Bootstrap plugin constructor.
37    *
38    * @param {string} id
39    *   A Bootstrap plugin identifier located in $.fn.
40    * @param {function} [callback]
41    *   A callback to extend the plugin constructor.
42    *
43    * @return {function|boolean}
44    *   The Bootstrap plugin or FALSE if the plugin does not exist.
45    */
46   Drupal.bootstrap.extendPlugin = function (id, callback) {
47     // Immediately return if the plugin does not exist.
48     if (!$.fn[id] || !$.fn[id].Constructor) return false;
49
50     // Extend the plugin if a callback was provided.
51     if ($.isFunction(callback)) {
52       var ret = callback.apply($.fn[id].Constructor, [this.settings]);
53       if ($.isPlainObject(ret)) {
54         $.extend(true, $.fn[id].Constructor, ret);
55       }
56     }
57
58     // Add a jQuery UI like option getter/setter method.
59     if ($.fn[id].Constructor.prototype.option === void(0)) {
60       $.fn[id].Constructor.prototype.option = this.option;
61     }
62
63     return $.fn[id].Constructor;
64   };
65
66   /**
67    * Replaces a Bootstrap jQuery plugin definition.
68    *
69    * @param {string} id
70    *   A Bootstrap plugin identifier located in $.fn.
71    * @param {function} [callback]
72    *   A callback to replace the jQuery plugin definition. The callback must
73    *   return a function that is used to construct a jQuery plugin.
74    *
75    * @return {function|boolean}
76    *   The Bootstrap jQuery plugin definition or FALSE if the plugin does not
77    *   exist.
78    */
79   Drupal.bootstrap.replacePlugin = function (id, callback) {
80     // Immediately return if plugin does not exist or not a valid callback.
81     if (!$.fn[id] || !$.fn[id].Constructor || !$.isFunction(callback)) return false;
82     var constructor = $.fn[id].Constructor;
83
84     var plugin = callback.apply(constructor);
85     if ($.isFunction(plugin)) {
86       plugin.Constructor = constructor;
87
88       var old = $.fn[id];
89       plugin.noConflict = function () {
90         $.fn[id] = old;
91         return this;
92       };
93       $.fn[id] = plugin;
94     }
95   };
96
97   /**
98    * Map of supported events by regular expression.
99    *
100    * @type {Object<Event|MouseEvent|KeyboardEvent|TouchEvent,RegExp>}
101    */
102   Drupal.bootstrap.eventMap = {
103     Event: /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,
104     MouseEvent: /^(?:click|dblclick|mouse(?:down|enter|leave|up|over|move|out))$/,
105     KeyboardEvent: /^(?:key(?:down|press|up))$/,
106     TouchEvent: /^(?:touch(?:start|end|move|cancel))$/
107   };
108
109   /**
110    * Simulates a native event on an element in the browser.
111    *
112    * Note: This is a pretty complete modern implementation. If things are quite
113    * working the way you intend (in older browsers), you may wish to use the
114    * jQuery.simulate plugin. If it's available, this method will defer to it.
115    *
116    * @see https://github.com/jquery/jquery-simulate
117    *
118    * @param {HTMLElement} element
119    *   A DOM element to dispatch event on.
120    * @param {String} type
121    *   The type of event to simulate.
122    * @param {Object} [options]
123    *   An object of options to pass to the event constructor. Typically, if
124    *   an event is being proxied, you should just pass the original event
125    *   object here. This allows, if the browser supports it, to be a truly
126    *   simulated event.
127    */
128   Drupal.bootstrap.simulate = function (element, type, options) {
129     // Defer to the jQuery.simulate plugin, if it's available.
130     if (typeof $.simulate === 'function') {
131       new $.simulate(element, type, options);
132       return;
133     }
134     var event;
135     var ctor;
136     for (var name in Drupal.bootstrap.eventMap) {
137       if (Drupal.bootstrap.eventMap[name].test(type)) {
138         ctor = name;
139         break;
140       }
141     }
142     if (!ctor) {
143       throw new SyntaxError('Only rudimentary HTMLEvents, KeyboardEvents and MouseEvents are supported: ' + type);
144     }
145     var opts = {bubbles: true, cancelable: true};
146     if (ctor === 'KeyboardEvent' || ctor === 'MouseEvent') {
147       $.extend(opts, {ctrlKey: !1, altKey: !1, shiftKey: !1, metaKey: !1});
148     }
149     if (ctor === 'MouseEvent') {
150       $.extend(opts, {button: 0, pointerX: 0, pointerY: 0, view: window});
151     }
152     if (options) {
153       $.extend(opts, options);
154     }
155     if (typeof window[ctor] === 'function') {
156       event = new window[ctor](type, opts);
157       element.dispatchEvent(event);
158     }
159     else if (document.createEvent) {
160       event = document.createEvent(ctor);
161       event.initEvent(type, opts.bubbles, opts.cancelable);
162       element.dispatchEvent(event);
163     }
164     else if (typeof element.fireEvent === 'function') {
165       event = $.extend(document.createEventObject(), opts);
166       element.fireEvent('on' + type, event);
167     }
168     else if (typeof element[type]) {
169       element[type]();
170     }
171   };
172
173   /**
174    * Provide jQuery UI like ability to get/set options for Bootstrap plugins.
175    *
176    * @param {string|object} key
177    *   A string value of the option to set, can be dot like to a nested key.
178    *   An object of key/value pairs.
179    * @param {*} [value]
180    *   (optional) A value to set for key.
181    *
182    * @returns {*}
183    *   - Returns nothing if key is an object or both key and value parameters
184    *   were provided to set an option.
185    *   - Returns the a value for a specific setting if key was provided.
186    *   - Returns an object of key/value pairs of all the options if no key or
187    *   value parameter was provided.
188    *
189    * @see https://github.com/jquery/jquery-ui/blob/master/ui/widget.js
190    *
191    * @todo This isn't fully working since Bootstrap plugins don't allow
192    * methods to return values.
193    */
194   Drupal.bootstrap.option = function (key, value) {
195     var options = key;
196     var parts, curOption, i;
197
198     // Don't return a reference to the internal hash.
199     if (arguments.length === 0) {
200       return $.extend({}, this.options);
201     }
202
203     // Handle a specific option.
204     if (typeof key === "string") {
205       // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
206       options = {};
207       parts = key.split(".");
208       key = parts.shift();
209       if (parts.length) {
210         curOption = options[key] = $.extend({}, this.options[key]);
211         for (i = 0; i < parts.length - 1; i++) {
212           curOption[parts[i]] = curOption[parts[i]] || {};
213           curOption = curOption[parts[i]];
214         }
215         key = parts.pop();
216         if (arguments.length === 1) {
217           return curOption[key] === undefined ? null : curOption[key];
218         }
219         curOption[key] = value;
220       }
221       else {
222         if (arguments.length === 1) {
223           return this.options[key] === undefined ? null : this.options[key];
224         }
225         options[key] = value;
226       }
227     }
228
229     // Set the new option(s).
230     for (key in options) {
231       if (!options.hasOwnProperty(key)) continue;
232       this.options[key] = options[key];
233     }
234     return this;
235   };
236
237 })(window.jQuery, window.Drupal, window.drupalSettings);