PageSourceSearch

https://www.jmatch.jp/assets/js/jquery.remodal.js

js jmatch.jp collected 2026-09-28 08:09:56 UTC 12,458 bytes, 514 lines download raw bytes

1(function(root, factory) {
2  if (typeof define === 'function' && define.amd) {
3    define(['jquery'], function($) {
4      return factory(root, $);
5    });
6  } else if (typeof exports === 'object') {
7    factory(root, require('jquery'));
8  } else {
9    factory(root, root.jQuery || root.Zepto);
10  }
11})(this, function(global, $) {
12
13  'use strict';
14
15  /**
16   * Name of the plugin
17   * @private
18   * @type {String}
19   */
20  var pluginName = 'remodal';
21
22  /**
23   * Namespace for CSS and events
24   * @private
25   * @type {String}
26   */
27  var namespace = global.remodalGlobals && global.remodalGlobals.namespace || pluginName;
28
29  /**
30   * Default settings
31   * @private
32   * @type {Object}
33   */
34  var defaults = $.extend({
35    hashTracking: true,
36    closeOnConfirm: true,
37    closeOnCancel: true,
38    closeOnEscape: true,
39    closeOnAnyClick: true
40  }, global.remodalGlobals && global.remodalGlobals.defaults);
41
42  /**
43   * Current modal
44   * @private
45   * @type {Remodal}
46   */
47  var current;
48
49  /**
50   * Scrollbar position
51   * @private
52   * @type {Number}
53   */
54  var scrollTop;
55
56  /**
57   * Get a transition duration in ms
58   * @private
59   * @param {jQuery} $elem
60   * @return {Number}
61   */
62  function getTransitionDuration($elem) {
63    var duration = $elem.css('transition-duration') ||
64        $elem.css('-webkit-transition-duration') ||
65        $elem.css('-moz-transition-duration') ||
66        $elem.css('-o-transition-duration') ||
67        $elem.css('-ms-transition-duration') ||
68        '0s';
69
70    var delay = $elem.css('transition-delay') ||
71        $elem.css('-webkit-transition-delay') ||
72        $elem.css('-moz-transition-delay') ||
73        $elem.css('-o-transition-delay') ||
74        $elem.css('-ms-transition-delay') ||
75        '0s';
76
77    var max;
78    var len;
79    var num;
80    var i;
81
82    duration = duration.split(', ');
83    delay = delay.split(', ');
84
85    // The duration length is the same as the delay length
86    for (i = 0, len = duration.length, max = Number.NEGATIVE_INFINITY; i < len; i++) {
87      num = parseFloat(duration[i]) + parseFloat(delay[i]);
88
89      if (num > max) {
90        max = num;
91      }
92    }
93
94    return num * 1000;
95  }
96
97  /**
98   * Get a scrollbar width
99   * @private
100   * @return {Number}
101   */
102  function getScrollbarWidth() {
103    if ($(document.body).height() <= $(window).height()) {
104      return 0;
105    }
106
107    var outer = document.createElement('div');
108    var inner = document.createElement('div');
109    var widthNoScroll;
110    var widthWithScroll;
111
112    outer.style.visibility = 'hidden';
113    outer.style.width = '100px';
114    document.body.appendChild(outer);
115
116    widthNoScroll = outer.offsetWidth;
117
118    // Force scrollbars
119    outer.style.overflow = 'scroll';
120
121    // Add inner div
122    inner.style.width = '100%';
123    outer.appendChild(inner);
124
125    widthWithScroll = inner.offsetWidth;
126
127    // Remove divs
128    outer.parentNode.removeChild(outer);
129
130    return widthNoScroll - widthWithScroll;
131  }
132
133  /**
134   * Lock the screen
135   * @private
136   */
137  function lockScreen() {
138    var $html = $('html');
139    var lockedClass = namespace + '-is-locked';
140    var paddingRight;
141    var $body;
142
143    if (!$html.hasClass(lockedClass)) {
144      $body = $(document.body);
145
146      // Zepto does not support '-=', '+=' in the `css` method
147      paddingRight = parseInt($body.css('padding-right'), 10) + getScrollbarWidth();
148
149      $body.css('padding-right', paddingRight + 'px');
150      $html.addClass(lockedClass);
151    }
152  }
153
154  /**
155   * Unlock the screen
156   * @private
157   */
158  function unlockScreen() {
159    var $html = $('html');
160    var lockedClass = namespace + '-is-locked';
161    var paddingRight;
162    var $body;
163
164    if ($html.hasClass(lockedClass)) {
165      $body = $(document.body);
166
167      // Zepto does not support '-=', '+=' in the `css` method
168      paddingRight = parseInt($body.css('padding-right'), 10) - getScrollbarWidth();
169
170      $body.css('padding-right', paddingRight + 'px');
171      $html.removeClass(lockedClass);
172    }
173  }
174
175  /**
176   * Parse a string with options
177   * @private
178   * @param str
179   * @returns {Object}
180   */
181  function parseOptions(str) {
182    var obj = {};
183    var arr;
184    var len;
185    var val;
186    var i;
187
188    // Remove spaces before and after delimiters
189    str = str.replace(/\s*:\s*/g, ':').replace(/\s*,\s*/g, ',');
190
191    // Parse a string
192    arr = str.split(',');
193    for (i = 0, len = arr.length; i < len; i++) {
194      arr[i] = arr[i].split(':');
195      val = arr[i][1];
196
197      // Convert a string value if it is like a boolean
198      if (typeof val === 'string' || val instanceof String) {
199        val = val === 'true' || (val === 'false' ? false : val);
200      }
201
202      // Convert a string value if it is like a number
203      if (typeof val === 'string' || val instanceof String) {
204        val = !isNaN(val) ? +val : val;
205      }
206
207      obj[arr[i][0]] = val;
208    }
209
210    return obj;
211  }
212
213  /**
214   * Remodal constructor
215   * @param {jQuery} $modal
216   * @param {Object} options
217   * @constructor
218   */
219  function Remodal($modal, options) {
220    var remodal = this;
221    var tdOverlay;
222    var tdModal;
223    var tdBg;
224
225    remodal.settings = $.extend({}, defaults, options);
226
227    // Build DOM
228    remodal.$body = $(document.body);
229    remodal.$overlay = $('.' + namespace + '-overlay');
230
231    if (!remodal.$overlay.length) {
232      remodal.$overlay = $('<div>').addClass(namespace + '-overlay');
233      remodal.$body.append(remodal.$overlay);
234    }
235
236    remodal.$bg = $('.' + namespace + '-bg');
237    //remodal.$closeButton = $('<a href="#"></a>').addClass(namespace + '-close');
238    remodal.$wrapper = $('<div>').addClass(namespace + '-wrapper');
239    remodal.$modal = $modal;
240    remodal.$modal.addClass(namespace);
241    remodal.$modal.css('visibility', 'visible');
242
243    remodal.$modal.append(remodal.$closeButton);
244    remodal.$wrapper.append(remodal.$modal);
245    remodal.$body.append(remodal.$wrapper);
246    remodal.$confirmButton = remodal.$modal.find('.' + namespace + '-confirm');
247    remodal.$cancelButton = remodal.$modal.find('.' + namespace + '-cancel');
248
249    // Calculate timeouts
250    tdOverlay = getTransitionDuration(remodal.$overlay);
251    tdModal = getTransitionDuration(remodal.$modal);
252    tdBg = getTransitionDuration(remodal.$bg);
253    remodal.td = Math.max(tdOverlay, tdModal, tdBg);
254
255    // Add the close button event listener
256    remodal.$wrapper.on('click.' + namespace, '.' + namespace + '-close', function(e) {
257      e.preventDefault();
258
259      remodal.close();
260    });
261
262    // Add the cancel button event listener
263    remodal.$wrapper.on('click.' + namespace, '.' + namespace + '-cancel', function(e) {
264      e.preventDefault();
265
266      remodal.$modal.trigger('cancel');
267
268      if (remodal.settings.closeOnCancel) {
269        remodal.close('cancellation');
270      }
271    });
272
273    // Add the confirm button event listener
274    remodal.$wrapper.on('click.' + namespace, '.' + namespace + '-confirm', function(e) {
275      e.preventDefault();
276
277      remodal.$modal.trigger('confirm');
278
279      if (remodal.settings.closeOnConfirm) {
280        remodal.close('confirmation');
281      }
282    });
283
284    // Add the keyboard event listener
285    $(document).on('keyup.' + namespace, function(e) {
286      if (e.keyCode === 27 && remodal.settings.closeOnEscape) {
287        remodal.close();
288      }
289    });
290
291    // Add the overlay event listener
292    remodal.$wrapper.on('click.' + namespace, function(e) {
293      var $target = $(e.target);
294
295      if (!$target.hasClass(namespace + '-wrapper')) {
296        return;
297      }
298
299      if (remodal.settings.closeOnAnyClick) {
300        remodal.close();
301      }
302    });
303
304    remodal.index = $[pluginName].lookup.push(remodal) - 1;
305    remodal.busy = false;
306  }
307
308  /**
309   * Open a modal window
310   * @public
311   */
312  Remodal.prototype.open = function() {
313
314    // Check if the animation was completed
315    if (this.busy) {
316      return;
317    }
318
319    var remodal = this;
320    var id;
321
322    remodal.busy = true;
323    remodal.$modal.trigger('open');
324
325    id = remodal.$modal.attr('data-' + pluginName + '-id');
326
327    if (id && remodal.settings.hashTracking) {
328      scrollTop = $(window).scrollTop();
329      location.hash = id;
330    }
331
332    if (current && current !== remodal) {
333      current.$overlay.hide();
334      current.$wrapper.hide();
335      current.$body.removeClass(namespace + '-is-active');
336    }
337
338    current = remodal;
339
340    lockScreen();
341    remodal.$overlay.show();
342    remodal.$wrapper.show();
343
344    setTimeout(function() {
345      remodal.$body.addClass(namespace + '-is-active');
346      remodal.$wrapper.scrollTop(0);
347
348      setTimeout(function() {
349        remodal.busy = false;
350        remodal.$modal.trigger('opened');
351      }, remodal.td + 50);
352    }, 25);
353  };
354
355  /**
356   * Close a modal window
357   * @public
358   * @param {String|undefined} reason A reason to close
359   */
360  Remodal.prototype.close = function(reason) {
361
362    // Check if the animation was completed
363    if (this.busy) {
364      return;
365    }
366
367    var remodal = this;
368
369    remodal.busy = true;
370    remodal.$modal.trigger({
371      type: 'close',
372      reason: reason
373    });
374
375    if (
376      remodal.settings.hashTracking &&
377      remodal.$modal.attr('data-' + pluginName + '-id') === location.hash.substr(1)
378    ) {
379      location.hash = '';
380      $(window).scrollTop(scrollTop);
381    }
382
383    remodal.$body.removeClass(namespace + '-is-active');
384
385    setTimeout(function() {
386      remodal.$overlay.hide();
387      remodal.$wrapper.hide();
388      unlockScreen();
389
390      remodal.busy = false;
391      remodal.$modal.trigger({
392        type: 'closed',
393        reason: reason
394      });
395    }, remodal.td + 50);
396  };
397
398  /**
399   * Special plugin object for instances.
400   * @public
401   * @type {Object}
402   */
403  $[pluginName] = {
404    lookup: []
405  };
406
407  /**
408   * Plugin constructor
409   * @param {Object} options
410   * @returns {JQuery}
411   * @constructor
412   */
413  $.fn[pluginName] = function(opts) {
414    var instance;
415    var $elem;
416
417    this.each(function(index, elem) {
418      $elem = $(elem);
419
420      if ($elem.data(pluginName) == null) {
421        instance = new Remodal($elem, opts);
422        $elem.data(pluginName, instance.index);
423
424        if (
425          instance.settings.hashTracking &&
426          $elem.attr('data-' + pluginName + '-id') === location.hash.substr(1)
427        ) {
428          instance.open();
429        }
430      } else {
431        instance = $[pluginName].lookup[$elem.data(pluginName)];
432      }
433    });
434
435    return instance;
436  };
437
438  $(document).ready(function() {
439
440    // data-remodal-target opens a modal window with the special Id.
441    $(document).on('click', '[data-' + pluginName + '-target]', function(e) {
442      e.preventDefault();
443
444      var elem = e.currentTarget;
445      var id = elem.getAttribute('data-' + pluginName + '-target');
446      var $target = $('[data-' + pluginName + '-id=' + id + ']');
447
448      $[pluginName].lookup[$target.data(pluginName)].open();
449    });
450
451    // Auto initialization of modal windows.
452    // They should have the 'remodal' class attribute.
453    // Also you can write `data-remodal-options` attribute to pass params into the modal.
454    $(document).find('.' + namespace).each(function(i, container) {
455      var $container = $(container);
456      var options = $container.data(pluginName + '-options');
457
458      if (!options) {
459        options = {};
460      } else if (typeof options === 'string' || options instanceof String) {
461        options = parseOptions(options);
462      }
463
464      $container[pluginName](options);
465    });
466  });
467
468  /**
469   * Hashchange handler
470   * @private
471   * @param {Event} e
472   * @param {Boolean} [closeOnEmptyHash=true]
473   */
474  function hashHandler(e, closeOnEmptyHash) {
475    var id = location.hash.replace('#', '');
476    var instance;
477    var $elem;
478
479    if (typeof closeOnEmptyHash === 'undefined') {
480      closeOnEmptyHash = true;
481    }
482
483    if (!id) {
484      if (closeOnEmptyHash) {
485
486        // Check if we have currently opened modal and animation was completed
487        if (current && !current.busy && current.settings.hashTracking) {
488          current.close();
489        }
490      }
491    } else {
492
493      // Catch syntax error if your hash is bad
494      try {
495        $elem = $(
496          '[data-' + pluginName + '-id=' +
497          id.replace(new RegExp('/', 'g'), '\\/') + ']'
498        );
499      } catch (err) {}
500
501      if ($elem && $elem.length) {
502        instance = $[pluginName].lookup[$elem.data(pluginName)];
503
504        if (instance && instance.settings.hashTracking) {
505          instance.open();
506        }
507      }
508
509    }
510  }
511
512  $(window).bind('hashchange.' + namespace, hashHandler);
513
514});

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.