PageSourceSearch

https://www.grabrooms.com/wp-content/plugins/wp-google-maps/lib/remodal.js?ver=5.8.17

js grabrooms.com collected 2026-09-24 12:19:31 UTC 19,413 bytes, 785 lines download raw bytes

1/*
2 *  Remodal - v1.1.1
3 *  Responsive, lightweight, fast, synchronized with CSS animations, fully customizable modal window plugin with declarative configuration and hash tracking.
4 *  http://vodkabears.github.io/remodal/
5 *
6 *  Made by Ilya Makarov
7 *  Under MIT License
8 */
9
10!(function(root, factory) {
11  if (typeof define === 'function' && define.amd) {
12    define(['jquery'], function($) {
13      return factory(root, $);
14    });
15  } else if (typeof exports === 'object') {
16    factory(root, require('jquery'));
17  } else {
18    factory(root, root.jQuery || root.Zepto);
19  }
20})(this, function(global, $) {
21
22  'use strict';
23
24  /**
25   * Name of the plugin
26   * @private
27   * @const
28   * @type {String}
29   */
30  var PLUGIN_NAME = 'remodal';
31
32  /**
33   * Namespace for CSS and events
34   * @private
35   * @const
36   * @type {String}
37   */
38  var NAMESPACE = global.REMODAL_GLOBALS && global.REMODAL_GLOBALS.NAMESPACE || PLUGIN_NAME;
39
40  /**
41   * Animationstart event with vendor prefixes
42   * @private
43   * @const
44   * @type {String}
45   */
46  var ANIMATIONSTART_EVENTS = $.map(
47    ['animationstart', 'webkitAnimationStart', 'MSAnimationStart', 'oAnimationStart'],
48
49    function(eventName) {
50      return eventName + '.' + NAMESPACE;
51    }
52
53  ).join(' ');
54
55  /**
56   * Animationend event with vendor prefixes
57   * @private
58   * @const
59   * @type {String}
60   */
61  var ANIMATIONEND_EVENTS = $.map(
62    ['animationend', 'webkitAnimationEnd', 'MSAnimationEnd', 'oAnimationEnd'],
63
64    function(eventName) {
65      return eventName + '.' + NAMESPACE;
66    }
67
68  ).join(' ');
69
70  /**
71   * Default settings
72   * @private
73   * @const
74   * @type {Object}
75   */
76  var DEFAULTS = $.extend({
77    hashTracking: true,
78    closeOnConfirm: true,
79    closeOnCancel: true,
80    closeOnEscape: true,
81    closeOnOutsideClick: true,
82    modifier: '',
83    appendTo: null
84  }, global.REMODAL_GLOBALS && global.REMODAL_GLOBALS.DEFAULTS);
85
86  /**
87   * States of the Remodal
88   * @private
89   * @const
90   * @enum {String}
91   */
92  var STATES = {
93    CLOSING: 'closing',
94    CLOSED: 'closed',
95    OPENING: 'opening',
96    OPENED: 'opened'
97  };
98
99  /**
100   * Reasons of the state change.
101   * @private
102   * @const
103   * @enum {String}
104   */
105  var STATE_CHANGE_REASONS = {
106    CONFIRMATION: 'confirmation',
107    CANCELLATION: 'cancellation'
108  };
109
110  /**
111   * Is animation supported?
112   * @private
113   * @const
114   * @type {Boolean}
115   */
116  var IS_ANIMATION = (function() {
117    var style = document.createElement('div').style;
118
119    return style.animationName !== undefined ||
120      style.WebkitAnimationName !== undefined ||
121      style.MozAnimationName !== undefined ||
122      style.msAnimationName !== undefined ||
123      style.OAnimationName !== undefined;
124  })();
125
126  /**
127   * Is iOS?
128   * @private
129   * @const
130   * @type {Boolean}
131   */
132  var IS_IOS = /iPad|iPhone|iPod/.test(navigator.platform);
133
134  /**
135   * Current modal
136   * @private
137   * @type {Remodal}
138   */
139  var current;
140
141  /**
142   * Scrollbar position
143   * @private
144   * @type {Number}
145   */
146  var scrollTop;
147
148  /**
149   * Returns an animation duration
150   * @private
151   * @param {jQuery} $elem
152   * @returns {Number}
153   */
154  function getAnimationDuration($elem) {
155    if (
156      IS_ANIMATION &&
157      $elem.css('animation-name') === 'none' &&
158      $elem.css('-webkit-animation-name') === 'none' &&
159      $elem.css('-moz-animation-name') === 'none' &&
160      $elem.css('-o-animation-name') === 'none' &&
161      $elem.css('-ms-animation-name') === 'none'
162    ) {
163      return 0;
164    }
165
166    var duration = $elem.css('animation-duration') ||
167      $elem.css('-webkit-animation-duration') ||
168      $elem.css('-moz-animation-duration') ||
169      $elem.css('-o-animation-duration') ||
170      $elem.css('-ms-animation-duration') ||
171      '0s';
172
173    var delay = $elem.css('animation-delay') ||
174      $elem.css('-webkit-animation-delay') ||
175      $elem.css('-moz-animation-delay') ||
176      $elem.css('-o-animation-delay') ||
177      $elem.css('-ms-animation-delay') ||
178      '0s';
179
180    var iterationCount = $elem.css('animation-iteration-count') ||
181      $elem.css('-webkit-animation-iteration-count') ||
182      $elem.css('-moz-animation-iteration-count') ||
183      $elem.css('-o-animation-iteration-count') ||
184      $elem.css('-ms-animation-iteration-count') ||
185      '1';
186
187    var max;
188    var len;
189    var num;
190    var i;
191
192    duration = duration.split(', ');
193    delay = delay.split(', ');
194    iterationCount = iterationCount.split(', ');
195
196    // The 'duration' size is the same as the 'delay' size
197    for (i = 0, len = duration.length, max = Number.NEGATIVE_INFINITY; i < len; i++) {
198      num = parseFloat(duration[i]) * parseInt(iterationCount[i], 10) + parseFloat(delay[i]);
199
200      if (num > max) {
201        max = num;
202      }
203    }
204
205    return max;
206  }
207
208  /**
209   * Returns a scrollbar width
210   * @private
211   * @returns {Number}
212   */
213  function getScrollbarWidth() {
214    if ($(document).height() <= $(window).height()) {
215      return 0;
216    }
217
218    var outer = document.createElement('div');
219    var inner = document.createElement('div');
220    var widthNoScroll;
221    var widthWithScroll;
222
223    outer.style.visibility = 'hidden';
224    outer.style.width = '100px';
225    document.body.appendChild(outer);
226
227    widthNoScroll = outer.offsetWidth;
228
229    // Force scrollbars
230    outer.style.overflow = 'scroll';
231
232    // Add inner div
233    inner.style.width = '100%';
234    outer.appendChild(inner);
235
236    widthWithScroll = inner.offsetWidth;
237
238    // Remove divs
239    outer.parentNode.removeChild(outer);
240
241    return widthNoScroll - widthWithScroll;
242  }
243
244  /**
245   * Locks the screen
246   * @private
247   */
248  function lockScreen() {
249    if (IS_IOS) {
250      return;
251    }
252
253    var $html = $('html');
254    var lockedClass = namespacify('is-locked');
255    var paddingRight;
256    var $body;
257
258    if (!$html.hasClass(lockedClass)) {
259      $body = $(document.body);
260
261      // Zepto does not support '-=', '+=' in the `css` method
262      paddingRight = parseInt($body.css('padding-right'), 10) + getScrollbarWidth();
263
264      $body.css('padding-right', paddingRight + 'px');
265      $html.addClass(lockedClass);
266    }
267  }
268
269  /**
270   * Unlocks the screen
271   * @private
272   */
273  function unlockScreen() {
274    if (IS_IOS) {
275      return;
276    }
277
278    var $html = $('html');
279    var lockedClass = namespacify('is-locked');
280    var paddingRight;
281    var $body;
282
283    if ($html.hasClass(lockedClass)) {
284      $body = $(document.body);
285
286      // Zepto does not support '-=', '+=' in the `css` method
287      paddingRight = parseInt($body.css('padding-right'), 10) - getScrollbarWidth();
288
289      $body.css('padding-right', paddingRight + 'px');
290      $html.removeClass(lockedClass);
291    }
292  }
293
294  /**
295   * Sets a state for an instance
296   * @private
297   * @param {Remodal} instance
298   * @param {STATES} state
299   * @param {Boolean} isSilent If true, Remodal does not trigger events
300   * @param {String} Reason of a state change.
301   */
302  function setState(instance, state, isSilent, reason) {
303
304    var newState = namespacify('is', state);
305    var allStates = [namespacify('is', STATES.CLOSING),
306                     namespacify('is', STATES.OPENING),
307                     namespacify('is', STATES.CLOSED),
308                     namespacify('is', STATES.OPENED)].join(' ');
309
310    instance.$bg
311      .removeClass(allStates)
312      .addClass(newState);
313
314    instance.$overlay
315      .removeClass(allStates)
316      .addClass(newState);
317
318    instance.$wrapper
319      .removeClass(allStates)
320      .addClass(newState);
321
322    instance.$modal
323      .removeClass(allStates)
324      .addClass(newState);
325
326    instance.state = state;
327    !isSilent && instance.$modal.trigger({
328      type: state,
329      reason: reason
330    }, [{ reason: reason }]);
331  }
332
333  /**
334   * Synchronizes with the animation
335   * @param {Function} doBeforeAnimation
336   * @param {Function} doAfterAnimation
337   * @param {Remodal} instance
338   */
339  function syncWithAnimation(doBeforeAnimation, doAfterAnimation, instance) {
340    var runningAnimationsCount = 0;
341
342    var handleAnimationStart = function(e) {
343      if (e.target !== this) {
344        return;
345      }
346
347      runningAnimationsCount++;
348    };
349
350    var handleAnimationEnd = function(e) {
351      if (e.target !== this) {
352        return;
353      }
354
355      if (--runningAnimationsCount === 0) {
356
357        // Remove event listeners
358        $.each(['$bg', '$overlay', '$wrapper', '$modal'], function(index, elemName) {
359          instance[elemName].off(ANIMATIONSTART_EVENTS + ' ' + ANIMATIONEND_EVENTS);
360        });
361
362        doAfterAnimation();
363      }
364    };
365
366    $.each(['$bg', '$overlay', '$wrapper', '$modal'], function(index, elemName) {
367      instance[elemName]
368        .on(ANIMATIONSTART_EVENTS, handleAnimationStart)
369        .on(ANIMATIONEND_EVENTS, handleAnimationEnd);
370    });
371
372    doBeforeAnimation();
373
374    // If the animation is not supported by a browser or its duration is 0
375    if (
376      getAnimationDuration(instance.$bg) === 0 &&
377      getAnimationDuration(instance.$overlay) === 0 &&
378      getAnimationDuration(instance.$wrapper) === 0 &&
379      getAnimationDuration(instance.$modal) === 0
380    ) {
381
382      // Remove event listeners
383      $.each(['$bg', '$overlay', '$wrapper', '$modal'], function(index, elemName) {
384        instance[elemName].off(ANIMATIONSTART_EVENTS + ' ' + ANIMATIONEND_EVENTS);
385      });
386
387      doAfterAnimation();
388    }
389  }
390
391  /**
392   * Closes immediately
393   * @private
394   * @param {Remodal} instance
395   */
396  function halt(instance) {
397    if (instance.state === STATES.CLOSED) {
398      return;
399    }
400
401    $.each(['$bg', '$overlay', '$wrapper', '$modal'], function(index, elemName) {
402      instance[elemName].off(ANIMATIONSTART_EVENTS + ' ' + ANIMATIONEND_EVENTS);
403    });
404
405    instance.$bg.removeClass(instance.settings.modifier);
406    instance.$overlay.removeClass(instance.settings.modifier).hide();
407    instance.$wrapper.hide();
408    unlockScreen();
409    setState(instance, STATES.CLOSED, true);
410  }
411
412  /**
413   * Parses a string with options
414   * @private
415   * @param str
416   * @returns {Object}
417   */
418  function parseOptions(str) {
419    var obj = {};
420    var arr;
421    var len;
422    var val;
423    var i;
424
425    // Remove spaces before and after delimiters
426    str = str.replace(/\s*:\s*/g, ':').replace(/\s*,\s*/g, ',');
427
428    // Parse a string
429    arr = str.split(',');
430    for (i = 0, len = arr.length; i < len; i++) {
431      arr[i] = arr[i].split(':');
432      val = arr[i][1];
433
434      // Convert a string value if it is like a boolean
435      if (typeof val === 'string' || val instanceof String) {
436        val = val === 'true' || (val === 'false' ? false : val);
437      }
438
439      // Convert a string value if it is like a number
440      if (typeof val === 'string' || val instanceof String) {
441        val = !isNaN(val) ? +val : val;
442      }
443
444      obj[arr[i][0]] = val;
445    }
446
447    return obj;
448  }
449
450  /**
451   * Generates a string separated by dashes and prefixed with NAMESPACE
452   * @private
453   * @param {...String}
454   * @returns {String}
455   */
456  function namespacify() {
457    var result = NAMESPACE;
458
459    for (var i = 0; i < arguments.length; ++i) {
460      result += '-' + arguments[i];
461    }
462
463    return result;
464  }
465
466  /**
467   * Handles the hashchange event
468   * @private
469   * @listens hashchange
470   */
471  function handleHashChangeEvent() {
472    var id = location.hash.replace('#', '');
473    var instance;
474    var $elem;
475
476    if (!id) {
477
478      // Check if we have currently opened modal and animation was completed
479      if (current && current.state === STATES.OPENED && current.settings.hashTracking) {
480        current.close();
481      }
482    } else {
483
484      // Catch syntax error if your hash is bad
485      try {
486        $elem = $(
487          '[data-' + PLUGIN_NAME + '-id="' + id + '"]'
488        );
489      } catch (err) {}
490
491      if ($elem && $elem.length) {
492        instance = $[PLUGIN_NAME].lookup[$elem.data(PLUGIN_NAME)];
493
494        if (instance && instance.settings.hashTracking) {
495          instance.open();
496        }
497      }
498
499    }
500  }
501
502  /**
503   * Remodal constructor
504   * @constructor
505   * @param {jQuery} $modal
506   * @param {Object} options
507   */
508  function Remodal($modal, options) {
509    var $body = $(document.body);
510    var $appendTo = $body;
511    var remodal = this;
512
513    remodal.settings = $.extend({}, DEFAULTS, options);
514    remodal.index = $[PLUGIN_NAME].lookup.push(remodal) - 1;
515    remodal.state = STATES.CLOSED;
516
517    remodal.$overlay = $('.' + namespacify('overlay'));
518
519    if (remodal.settings.appendTo !== null && remodal.settings.appendTo.length) {
520      $appendTo = $(remodal.settings.appendTo);
521    }
522
523    if (!remodal.$overlay.length) {
524      remodal.$overlay = $('<div>').addClass(namespacify('overlay') + ' ' + namespacify('is', STATES.CLOSED)).hide();
525      $appendTo.append(remodal.$overlay);
526    }
527
528    remodal.$bg = $('.' + namespacify('bg')).addClass(namespacify('is', STATES.CLOSED));
529
530    remodal.$modal = $modal
531      .addClass(
532        NAMESPACE + ' ' +
533        namespacify('is-initialized') + ' ' +
534        remodal.settings.modifier + ' ' +
535        namespacify('is', STATES.CLOSED))
536      .attr('tabindex', '-1');
537
538    remodal.$wrapper = $('<div>')
539      .addClass(
540        namespacify('wrapper') + ' ' +
541        remodal.settings.modifier + ' ' +
542        namespacify('is', STATES.CLOSED))
543      .hide()
544      .append(remodal.$modal);
545    $appendTo.append(remodal.$wrapper);
546
547    // Add the event listener for the close button
548    remodal.$wrapper.on('click.' + NAMESPACE, '[data-' + PLUGIN_NAME + '-action="close"]', function(e) {
549      e.preventDefault();
550
551      remodal.close();
552    });
553
554    // Add the event listener for the cancel button
555    remodal.$wrapper.on('click.' + NAMESPACE, '[data-' + PLUGIN_NAME + '-action="cancel"]', function(e) {
556      e.preventDefault();
557
558      remodal.$modal.trigger(STATE_CHANGE_REASONS.CANCELLATION);
559
560      if (remodal.settings.closeOnCancel) {
561        remodal.close(STATE_CHANGE_REASONS.CANCELLATION);
562      }
563    });
564
565    // Add the event listener for the confirm button
566    remodal.$wrapper.on('click.' + NAMESPACE, '[data-' + PLUGIN_NAME + '-action="confirm"]', function(e) {
567      e.preventDefault();
568
569      remodal.$modal.trigger(STATE_CHANGE_REASONS.CONFIRMATION);
570
571      if (remodal.settings.closeOnConfirm) {
572        remodal.close(STATE_CHANGE_REASONS.CONFIRMATION);
573      }
574    });
575
576    // Add the event listener for the overlay
577    remodal.$wrapper.on('click.' + NAMESPACE, function(e) {
578      var $target = $(e.target);
579
580      if (!$target.hasClass(namespacify('wrapper'))) {
581        return;
582      }
583
584      if (remodal.settings.closeOnOutsideClick) {
585        remodal.close();
586      }
587    });
588  }
589
590  /**
591   * Opens a modal window
592   * @public
593   */
594  Remodal.prototype.open = function() {
595    var remodal = this;
596    var id;
597
598    // Check if the animation was completed
599    if (remodal.state === STATES.OPENING || remodal.state === STATES.CLOSING) {
600      return;
601    }
602
603    id = remodal.$modal.attr('data-' + PLUGIN_NAME + '-id');
604
605    if (id && remodal.settings.hashTracking) {
606      scrollTop = $(window).scrollTop();
607      location.hash = id;
608    }
609
610    if (current && current !== remodal) {
611      halt(current);
612    }
613
614    current = remodal;
615    lockScreen();
616    remodal.$bg.addClass(remodal.settings.modifier);
617    remodal.$overlay.addClass(remodal.settings.modifier).show();
618    remodal.$wrapper.show().scrollTop(0);
619    remodal.$modal.focus();
620
621    syncWithAnimation(
622      function() {
623        setState(remodal, STATES.OPENING);
624      },
625
626      function() {
627        setState(remodal, STATES.OPENED);
628      },
629
630      remodal);
631  };
632
633  /**
634   * Closes a modal window
635   * @public
636   * @param {String} reason
637   */
638  Remodal.prototype.close = function(reason) {
639    var remodal = this;
640
641    // Check if the animation was completed
642    if (remodal.state === STATES.OPENING || remodal.state === STATES.CLOSING || remodal.state === STATES.CLOSED) {
643      return;
644    }
645
646    if (
647      remodal.settings.hashTracking &&
648      remodal.$modal.attr('data-' + PLUGIN_NAME + '-id') === location.hash.substr(1)
649    ) {
650      location.hash = '';
651      $(window).scrollTop(scrollTop);
652    }
653
654    syncWithAnimation(
655      function() {
656        setState(remodal, STATES.CLOSING, false, reason);
657      },
658
659      function() {
660        remodal.$bg.removeClass(remodal.settings.modifier);
661        remodal.$overlay.removeClass(remodal.settings.modifier).hide();
662        remodal.$wrapper.hide();
663        unlockScreen();
664
665        setState(remodal, STATES.CLOSED, false, reason);
666      },
667
668      remodal);
669  };
670
671  /**
672   * Returns a current state of a modal
673   * @public
674   * @returns {STATES}
675   */
676  Remodal.prototype.getState = function() {
677    return this.state;
678  };
679
680  /**
681   * Destroys a modal
682   * @public
683   */
684  Remodal.prototype.destroy = function() {
685    var lookup = $[PLUGIN_NAME].lookup;
686    var instanceCount;
687
688    halt(this);
689    this.$wrapper.remove();
690
691    delete lookup[this.index];
692    instanceCount = $.grep(lookup, function(instance) {
693      return !!instance;
694    }).length;
695
696    if (instanceCount === 0) {
697      this.$overlay.remove();
698      this.$bg.removeClass(
699        namespacify('is', STATES.CLOSING) + ' ' +
700        namespacify('is', STATES.OPENING) + ' ' +
701        namespacify('is', STATES.CLOSED) + ' ' +
702        namespacify('is', STATES.OPENED));
703    }
704  };
705
706  /**
707   * Special plugin object for instances
708   * @public
709   * @type {Object}
710   */
711  $[PLUGIN_NAME] = {
712    lookup: []
713  };
714
715  /**
716   * Plugin constructor
717   * @constructor
718   * @param {Object} options
719   * @returns {JQuery}
720   */
721  $.fn[PLUGIN_NAME] = function(opts) {
722    var instance;
723    var $elem;
724
725    this.each(function(index, elem) {
726      $elem = $(elem);
727
728      if ($elem.data(PLUGIN_NAME) == null) {
729        instance = new Remodal($elem, opts);
730        $elem.data(PLUGIN_NAME, instance.index);
731
732        if (
733          instance.settings.hashTracking &&
734          $elem.attr('data-' + PLUGIN_NAME + '-id') === location.hash.substr(1)
735        ) {
736          instance.open();
737        }
738      } else {
739        instance = $[PLUGIN_NAME].lookup[$elem.data(PLUGIN_NAME)];
740      }
741    });
742
743    return instance;
744  };
745
746  $(document).ready(function() {
747
748    // data-remodal-target opens a modal window with the special Id
749    $(document).on('click', '[data-' + PLUGIN_NAME + '-target]', function(e) {
750      e.preventDefault();
751
752      var elem = e.currentTarget;
753      var id = elem.getAttribute('data-' + PLUGIN_NAME + '-target');
754      var $target = $('[data-' + PLUGIN_NAME + '-id="' + id + '"]');
755
756      $[PLUGIN_NAME].lookup[$target.data(PLUGIN_NAME)].open();
757    });
758
759    // Auto initialization of modal windows
760    // They should have the 'remodal' class attribute
761    // Also you can write the `data-remodal-options` attribute to pass params into the modal
762    $(document).find('.' + NAMESPACE).each(function(i, container) {
763      var $container = $(container);
764      var options = $container.data(PLUGIN_NAME + '-options');
765
766      if (!options) {
767        options = {};
768      } else if (typeof options === 'string' || options instanceof String) {
769        options = parseOptions(options);
770      }
771
772      $container[PLUGIN_NAME](options);
773    });
774
775    // Handles the keydown event
776    $(document).on('keydown.' + NAMESPACE, function(e) {
777      if (current && current.settings.closeOnEscape && current.state === STATES.OPENED && e.keyCode === 27) {
778        current.close();
779      }
780    });
781
782    // Handles the hashchange event
783    $(window).on('hashchange.' + NAMESPACE, handleHashChangeEvent);
784  });
785});

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.