PageSourceSearch

https://queenslibrary.org/themes/bootstrap/js/drupal.bootstrap.js?tl8z8n

js queenslibrary.org collected 2026-09-24 08:47:20 UTC 18,660 bytes, 600 lines download raw bytes

1/**
2 * @file
3 * Drupal Bootstrap object.
4 */
5
6/**
7 * All Drupal Bootstrap JavaScript APIs are contained in this namespace.
8 *
9 * @param {underscore} _
10 * @param {jQuery} $
11 * @param {Drupal} Drupal
12 * @param {drupalSettings} drupalSettings
13 */
14(function (_, $, Drupal, drupalSettings) {
15  'use strict';
16
17  /**
18   * @typedef Drupal.bootstrap
19   */
20  var Bootstrap = {
21    processedOnce: {},
22    settings: drupalSettings.bootstrap || {}
23  };
24
25  /**
26   * Wraps Drupal.checkPlain() to ensure value passed isn't empty.
27   *
28   * Encodes special characters in a plain-text string for display as HTML.
29   *
30   * @param {string} str
31   *   The string to be encoded.
32   *
33   * @return {string}
34   *   The encoded string.
35   *
36   * @ingroup sanitization
37   */
38  Bootstrap.checkPlain = function (str) {
39    return str && Drupal.checkPlain(str) || '';
40  };
41
42  /**
43   * Creates a jQuery plugin.
44   *
45   * @param {String} id
46   *   A jQuery plugin identifier located in $.fn.
47   * @param {Function} plugin
48   *   A constructor function used to initialize the for the jQuery plugin.
49   * @param {Boolean} [noConflict]
50   *   Flag indicating whether or not to create a ".noConflict()" helper method
51   *   for the plugin.
52   */
53  Bootstrap.createPlugin = function (id, plugin, noConflict) {
54    // Immediately return if plugin doesn't exist.
55    if ($.fn[id] !== void 0) {
56      return this.fatal('Specified jQuery plugin identifier already exists: @id. Use Drupal.bootstrap.replacePlugin() instead.', {'@id': id});
57    }
58
59    // Immediately return if plugin isn't a function.
60    if (typeof plugin !== 'function') {
61      return this.fatal('You must provide a constructor function to create a jQuery plugin "@id": @plugin', {'@id': id, '@plugin':  plugin});
62    }
63
64    // Add a ".noConflict()" helper method.
65    this.pluginNoConflict(id, plugin, noConflict);
66
67    $.fn[id] = plugin;
68  };
69
70  /**
71   * Diff object properties.
72   *
73   * @param {...Object} objects
74   *   Two or more objects. The first object will be used to return properties
75   *   values.
76   *
77   * @return {Object}
78   *   Returns the properties of the first passed object that are not present
79   *   in all other passed objects.
80   */
81  Bootstrap.diffObjects = function (objects) {
82    var args = Array.prototype.slice.call(arguments);
83    return _.pick(args[0], _.difference.apply(_, _.map(args, function (obj) {
84      return Object.keys(obj);
85    })));
86  };
87
88  /**
89   * Map of supported events by regular expression.
90   *
91   * @type {Object<Event|MouseEvent|KeyboardEvent|TouchEvent,RegExp>}
92   */
93  Bootstrap.eventMap = {
94    Event: /^(?:load|unload|abort|error|select|change|submit|reset|focus|blur|resize|scroll)$/,
95    MouseEvent: /^(?:click|dblclick|mouse(?:down|enter|leave|up|over|move|out))$/,
96    KeyboardEvent: /^(?:key(?:down|press|up))$/,
97    TouchEvent: /^(?:touch(?:start|end|move|cancel))$/
98  };
99
100  /**
101   * Extends a jQuery Plugin.
102   *
103   * @param {String} id
104   *   A jQuery plugin identifier located in $.fn.
105   * @param {Function} callback
106   *   A constructor function used to initialize the for the jQuery plugin.
107   *
108   * @return {Function|Boolean}
109   *   The jQuery plugin constructor or FALSE if the plugin does not exist.
110   */
111  Bootstrap.extendPlugin = function (id, callback) {
112    // Immediately return if plugin doesn't exist.
113    if (typeof $.fn[id] !== 'function') {
114      return this.fatal('Specified jQuery plugin identifier does not exist: @id', {'@id':  id});
115    }
116
117    // Immediately return if callback isn't a function.
118    if (typeof callback !== 'function') {
119      return this.fatal('You must provide a callback function to extend the jQuery plugin "@id": @callback', {'@id': id, '@callback':  callback});
120    }
121
122    // Determine existing plugin constructor.
123    var constructor = $.fn[id] && $.fn[id].Constructor || $.fn[id];
124    var plugin = callback.apply(constructor, [this.settings]);
125    if (!$.isPlainObject(plugin)) {
126      return this.fatal('Returned value from callback is not a plain object that can be used to extend the jQuery plugin "@id": @obj', {'@obj':  plugin});
127    }
128
129    this.wrapPluginConstructor(constructor, plugin, true);
130
131    return $.fn[id];
132  };
133
134  Bootstrap.superWrapper = function (parent, fn) {
135    return function () {
136      var previousSuper = this.super;
137      this.super = parent;
138      var ret = fn.apply(this, arguments);
139      if (previousSuper) {
140        this.super = previousSuper;
141      }
142      else {
143        delete this.super;
144      }
145      return ret;
146    };
147  };
148
149  /**
150   * Provide a helper method for displaying when something is went wrong.
151   *
152   * @param {String} message
153   *   The message to display.
154   * @param {Object} [args]
155   *   An arguments to use in message.
156   *
157   * @return {Boolean}
158   *   Always returns FALSE.
159   */
160  Bootstrap.fatal = function (message, args) {
161    if (this.settings.dev && console.warn) {
162      for (var name in args) {
163        if (args.hasOwnProperty(name) && typeof args[name] === 'object') {
164          args[name] = JSON.stringify(args[name]);
165        }
166      }
167      Drupal.throwError(new Error(Drupal.formatString(message, args)));
168    }
169    return false;
170  };
171
172  /**
173   * Intersects object properties.
174   *
175   * @param {...Object} objects
176   *   Two or more objects. The first object will be used to return properties
177   *   values.
178   *
179   * @return {Object}
180   *   Returns the properties of first passed object that intersects with all
181   *   other passed objects.
182   */
183  Bootstrap.intersectObjects = function (objects) {
184    var args = Array.prototype.slice.call(arguments);
185    return _.pick(args[0], _.intersection.apply(_, _.map(args, function (obj) {
186      return Object.keys(obj);
187    })));
188  };
189
190  /**
191   * Normalizes an object's values.
192   *
193   * @param {Object} obj
194   *   The object to normalize.
195   *
196   * @return {Object}
197   *   The normalized object.
198   */
199  Bootstrap.normalizeObject = function (obj) {
200    if (!$.isPlainObject(obj)) {
201      return obj;
202    }
203
204    for (var k in obj) {
205      if (typeof obj[k] === 'string') {
206        if (obj[k] === 'true') {
207          obj[k] = true;
208        }
209        else if (obj[k] === 'false') {
210          obj[k] = false;
211        }
212        else if (obj[k].match(/^[\d-.]$/)) {
213          obj[k] = parseFloat(obj[k]);
214        }
215      }
216      else if ($.isPlainObject(obj[k])) {
217        obj[k] = Bootstrap.normalizeObject(obj[k]);
218      }
219    }
220
221    return obj;
222  };
223
224  /**
225   * An object based once plugin (similar to jquery.once, but without the DOM).
226   *
227   * @param {String} id
228   *   A unique identifier.
229   * @param {Function} callback
230   *   The callback to invoke if the identifier has not yet been seen.
231   *
232   * @return {Bootstrap}
233   */
234  Bootstrap.once = function (id, callback) {
235    // Immediately return if identifier has already been processed.
236    if (this.processedOnce[id]) {
237      return this;
238    }
239    callback.call(this, this.settings);
240    this.processedOnce[id] = true;
241    return this;
242  };
243
244  /**
245   * Provide jQuery UI like ability to get/set options for Bootstrap plugins.
246   *
247   * @param {string|object} key
248   *   A string value of the option to set, can be dot like to a nested key.
249   *   An object of key/value pairs.
250   * @param {*} [value]
251   *   (optional) A value to set for key.
252   *
253   * @returns {*}
254   *   - Returns nothing if key is an object or both key and value parameters
255   *   were provided to set an option.
256   *   - Returns the a value for a specific setting if key was provided.
257   *   - Returns an object of key/value pairs of all the options if no key or
258   *   value parameter was provided.
259   *
260   * @see https://github.com/jquery/jquery-ui/blob/master/ui/widget.js
261   */
262  Bootstrap.option = function (key, value) {
263    var options = $.isPlainObject(key) ? $.extend({}, key) : {};
264
265    // Get all options (clone so it doesn't reference the internal object).
266    if (arguments.length === 0) {
267      return $.extend({}, this.options);
268    }
269
270    // Get/set single option.
271    if (typeof key === "string") {
272      // Handle nested keys in dot notation.
273      // e.g., "foo.bar" => { foo: { bar: true } }
274      var parts = key.split('.');
275      key = parts.shift();
276      var obj = options;
277      if (parts.length) {
278        for (var i = 0; i < parts.length - 1; i++) {
279          obj[parts[i]] = obj[parts[i]] || {};
280          obj = obj[parts[i]];
281        }
282        key = parts.pop();
283      }
284
285      // Get.
286      if (arguments.length === 1) {
287        return obj[key] === void 0 ? null : obj[key];
288      }
289
290      // Set.
291      obj[key] = value;
292    }
293
294    // Set multiple options.
295    $.extend(true, this.options, options);
296  };
297
298  /**
299   * Adds a ".noConflict()" helper method if needed.
300   *
301   * @param {String} id
302   *   A jQuery plugin identifier located in $.fn.
303   * @param {Function} plugin
304   * @param {Function} plugin
305   *   A constructor function used to initialize the for the jQuery plugin.
306   * @param {Boolean} [noConflict]
307   *   Flag indicating whether or not to create a ".noConflict()" helper method
308   *   for the plugin.
309   */
310  Bootstrap.pluginNoConflict = function (id, plugin, noConflict) {
311    if (plugin.noConflict === void 0 && (noConflict === void 0 || noConflict)) {
312      var old = $.fn[id];
313      plugin.noConflict = function () {
314        $.fn[id] = old;
315        return this;
316      };
317    }
318  };
319
320  /**
321   * Creates a handler that relays to another event name.
322   *
323   * @param {HTMLElement|jQuery} target
324   *   A target element.
325   * @param {String} name
326   *   The name of the event to trigger.
327   * @param {Boolean} [stopPropagation=true]
328   *   Flag indicating whether to stop the propagation of the event, defaults
329   *   to true.
330   *
331   * @return {Function}
332   *   An even handler callback function.
333   */
334  Bootstrap.relayEvent = function (target, name, stopPropagation) {
335    return function (e) {
336      if (stopPropagation === void 0 || stopPropagation) {
337        e.stopPropagation();
338      }
339      var $target = $(target);
340      var parts = name.split('.').filter(Boolean);
341      var type = parts.shift();
342      e.target = $target[0];
343      e.currentTarget = $target[0];
344      e.namespace = parts.join('.');
345      e.type = type;
346      $target.trigger(e);
347    };
348  };
349
350  /**
351   * Replaces a Bootstrap jQuery plugin definition.
352   *
353   * @param {String} id
354   *   A jQuery plugin identifier located in $.fn.
355   * @param {Function} callback
356   *   A callback function that is immediately invoked and must return a
357   *   function that will be used as the plugin constructor.
358   * @param {Boolean} [noConflict]
359   *   Flag indicating whether or not to create a ".noConflict()" helper method
360   *   for the plugin.
361   */
362  Bootstrap.replacePlugin = function (id, callback, noConflict) {
363    // Immediately return if plugin doesn't exist.
364    if (typeof $.fn[id] !== 'function') {
365      return this.fatal('Specified jQuery plugin identifier does not exist: @id', {'@id':  id});
366    }
367
368    // Immediately return if callback isn't a function.
369    if (typeof callback !== 'function') {
370      return this.fatal('You must provide a valid callback function to replace a jQuery plugin: @callback', {'@callback': callback});
371    }
372
373    // Determine existing plugin constructor.
374    var constructor = $.fn[id] && $.fn[id].Constructor || $.fn[id];
375    var plugin = callback.apply(constructor, [this.settings]);
376
377    // Immediately return if plugin isn't a function.
378    if (typeof plugin !== 'function') {
379      return this.fatal('Returned value from callback is not a usable function to replace a jQuery plugin "@id": @plugin', {'@id': id, '@plugin': plugin});
380    }
381
382    this.wrapPluginConstructor(constructor, plugin);
383
384    // Add a ".noConflict()" helper method.
385    this.pluginNoConflict(id, plugin, noConflict);
386
387    $.fn[id] = plugin;
388  };
389
390  /**
391   * Simulates a native event on an element in the browser.
392   *
393   * Note: This is a fairly complete modern implementation. If things aren't
394   * working quite the way you intend (in older browsers), you may wish to use
395   * the jQuery.simulate plugin. If it's available, this method will defer to
396   * that plugin.
397   *
398   * @see https://github.com/jquery/jquery-simulate
399   *
400   * @param {HTMLElement|jQuery} element
401   *   A DOM element to dispatch event on. Note: this may be a jQuery object,
402   *   however be aware that this will trigger the same event for each element
403   *   inside the jQuery collection; use with caution.
404   * @param {String|String[]} type
405   *   The type(s) of event to simulate.
406   * @param {Object} [options]
407   *   An object of options to pass to the event constructor. Typically, if
408   *   an event is being proxied, you should just pass the original event
409   *   object here. This allows, if the browser supports it, to be a truly
410   *   simulated event.
411   *
412   * @return {Boolean}
413   *   The return value is false if event is cancelable and at least one of the
414   *   event handlers which handled this event called Event.preventDefault().
415   *   Otherwise it returns true.
416   */
417  Bootstrap.simulate = function (element, type, options) {
418    // Handle jQuery object wrappers so it triggers on each element.
419    var ret = true;
420    if (element instanceof $) {
421      element.each(function () {
422        if (!Bootstrap.simulate(this, type, options)) {
423          ret = false;
424        }
425      });
426      return ret;
427    }
428
429    if (!(element instanceof HTMLElement)) {
430      this.fatal('Passed element must be an instance of HTMLElement, got "@type" instead.', {
431        '@type': typeof element,
432      });
433    }
434
435    // Defer to the jQuery.simulate plugin, if it's available.
436    if (typeof $.simulate === 'function') {
437      new $.simulate(element, type, options);
438      return true;
439    }
440
441    var event;
442    var ctor;
443    var types = [].concat(type);
444    for (var i = 0, l = types.length; i < l; i++) {
445      type = types[i];
446      for (var name in this.eventMap) {
447        if (this.eventMap[name].test(type)) {
448          ctor = name;
449          break;
450        }
451      }
452      if (!ctor) {
453        throw new SyntaxError('Only rudimentary HTMLEvents, KeyboardEvents and MouseEvents are supported: ' + type);
454      }
455      var opts = {bubbles: true, cancelable: true};
456      if (ctor === 'KeyboardEvent' || ctor === 'MouseEvent') {
457        $.extend(opts, {ctrlKey: !1, altKey: !1, shiftKey: !1, metaKey: !1});
458      }
459      if (ctor === 'MouseEvent') {
460        $.extend(opts, {button: 0, pointerX: 0, pointerY: 0, view: window});
461      }
462      if (options) {
463        $.extend(opts, options);
464      }
465      if (typeof window[ctor] === 'function') {
466        event = new window[ctor](type, opts);
467        if (!element.dispatchEvent(event)) {
468          ret = false;
469        }
470      }
471      else if (document.createEvent) {
472        event = document.createEvent(ctor);
473        event.initEvent(type, opts.bubbles, opts.cancelable);
474        if (!element.dispatchEvent(event)) {
475          ret = false;
476        }
477      }
478      else if (typeof element.fireEvent === 'function') {
479        event = $.extend(document.createEventObject(), opts);
480        if (!element.fireEvent('on' + type, event)) {
481          ret = false;
482        }
483      }
484      else if (typeof element[type]) {
485        element[type]();
486      }
487    }
488    return ret;
489  };
490
491  /**
492   * Strips HTML and returns just text.
493   *
494   * @param {String|Element|jQuery} html
495   *   A string of HTML content, an Element DOM object or a jQuery object.
496   *
497   * @return {String}
498   *   The text without HTML tags.
499   *
500   * @todo Replace with http://locutus.io/php/strings/strip_tags/
501   */
502  Bootstrap.stripHtml = function (html) {
503    if (html instanceof $) {
504      html = html.html();
505    }
506    else if (html instanceof Element) {
507      html = html.innerHTML;
508    }
509    var tmp = document.createElement('DIV');
510    tmp.innerHTML = html;
511    return (tmp.textContent || tmp.innerText || '').replace(/^[\s\n\t]*|[\s\n\t]*$/, '');
512  };
513
514  /**
515   * Provide a helper method for displaying when something is unsupported.
516   *
517   * @param {String} type
518   *   The type of unsupported object, e.g. method or option.
519   * @param {String} name
520   *   The name of the unsupported object.
521   * @param {*} [value]
522   *   The value of the unsupported object.
523   */
524  Bootstrap.unsupported = function (type, name, value) {
525    Bootstrap.warn('Unsupported by Drupal Bootstrap: (@type) @name -> @value', {
526      '@type': type,
527      '@name': name,
528      '@value': typeof value === 'object' ? JSON.stringify(value) : value
529    });
530  };
531
532  /**
533   * Provide a helper method to display a warning.
534   *
535   * @param {String} message
536   *   The message to display.
537   * @param {Object} [args]
538   *   Arguments to use as replacements in Drupal.formatString.
539   */
540  Bootstrap.warn = function (message, args) {
541    if (this.settings.dev && console.warn) {
542      console.warn(Drupal.formatString(message, args));
543    }
544  };
545
546  /**
547   * Wraps a plugin with common functionality.
548   *
549   * @param {Function} constructor
550   *   A plugin constructor being wrapped.
551   * @param {Object|Function} plugin
552   *   The plugin being wrapped.
553   * @param {Boolean} [extend = false]
554   *   Whether to add super extensibility.
555   */
556  Bootstrap.wrapPluginConstructor = function (constructor, plugin, extend) {
557    var proto = constructor.prototype;
558
559    // Add a jQuery UI like option getter/setter method.
560    var option = this.option;
561    if (proto.option === void(0)) {
562      proto.option = function () {
563        return option.apply(this, arguments);
564      };
565    }
566
567    if (extend) {
568      // Handle prototype properties separately.
569      if (plugin.prototype !== void 0) {
570        for (var key in plugin.prototype) {
571          if (!plugin.prototype.hasOwnProperty(key)) continue;
572          var value = plugin.prototype[key];
573          if (typeof value === 'function') {
574            proto[key] = this.superWrapper(proto[key] || function () {}, value);
575          }
576          else {
577            proto[key] = $.isPlainObject(value) ? $.extend(true, {}, proto[key], value) : value;
578          }
579        }
580      }
581      delete plugin.prototype;
582
583      // Handle static properties.
584      for (key in plugin) {
585        if (!plugin.hasOwnProperty(key)) continue;
586        value = plugin[key];
587        if (typeof value === 'function') {
588          constructor[key] = this.superWrapper(constructor[key] || function () {}, value);
589        }
590        else {
591          constructor[key] = $.isPlainObject(value) ? $.extend(true, {}, constructor[key], value) : value;
592        }
593      }
594    }
595  };
596
597  // Add Bootstrap to the global Drupal object.
598  Drupal.bootstrap = Drupal.bootstrap || Bootstrap;
599
600})(window._, window.jQuery, window.Drupal, window.drupalSettings);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.