PageSourceSearch

https://www.echigo-kotsu.co.jp/contents/components/mtrdatepicker/mtr-datepicker.fix.js

js echigo-kotsu.co.jp collected 2026-10-02 16:26:30 UTC 88,166 bytes, 2,735 lines download raw bytes

1
2/**
3 * The main class of the MtrDatepicker
4 * Here inside is covered everything that you need to know
5 *
6 * @class MtrDatepicker
7 * @param {Object} inputConfig used for user configurations
8 */
9// eslint-disable-next-line no-unused-vars
10function MtrDatepicker (inputConfig) {
11  // The real implementation of the library starts here
12
13  // The main configuration properties
14  // All of them can be overridden by the init method
15  var config = {
16    targetElement: null,
17    defaultValues: {
18      hours: [],
19      minutes: [],
20      dates: [],
21      datesNames: [],
22      months: [],
23      years: []
24    },
25    hours: {
26      min: 1,
27      max: 12,
28      step: 1,
29      maxlength: 2
30    },
31    minutes: {
32      min: 0,
33      max: 50,
34      step: 10,
35      maxlength: 2
36    },
37    months: {
38      min: 0,
39      max: 11,
40      step: 1,
41      maxlength: 2
42    },
43    years: {
44      min: 2000,
45      max: 2050,
46      step: 1,
47      maxlength: 4
48    },
49
50    // Responsible for the transition of the sliders - animated or static
51    animations: true,
52
53    // Make auto switch between AM/PM when moving from 11AM to 12PM or backwards
54    smartHours: false,
55
56    // Validate the date to be only in the future
57    future: false,
58
59    // Disable the 12 hours time format and go to a full 24 hours experience
60    disableAmPm: false,
61
62    // perform the future validation after the date change
63    validateAfter: true,
64
65    // change the local timezone to a specific one
66    utcTimezone: 0,
67
68    transitionDelay: 100,
69    transitionValidationDelay: 500,
70    references: {
71      hours: null // Used to store references to the main elements
72    },
73
74    // Show the fields related with the date
75    datepicker: true,
76
77    // Show the fields related with the time
78    timepicker: true,
79
80//!!!!! Add Start
81    // ゼロパディングするか
82    zeroPadding: true,
83
84    // 入力不可とするか
85    inputReadonly: true,
86
87    // 矢印マウスダウン/タッチ中時、連続遷移するインターバル
88    mouseDownTransitionInterval: 200,
89
90    // [Tab]キーによるフォーカス遷移するか
91    focusMoveByTab: false,
92
93    // [←][→]キーによるフォーカス遷移するか
94    focusMoveByLR: true,
95//!!!!! Add End
96
97    monthsNames: {
98      0: 'Jan',
99      1: 'Feb',
100      2: 'Mar',
101      3: 'Apr',
102      4: 'May',
103      5: 'Jun',
104      6: 'Jul',
105      7: 'Aug',
106      8: 'Sep',
107      9: 'Oct',
108      10: 'Nov',
109      11: 'Dec'
110    },
111
112    daysNames: {
113      0: 'Sun',
114      1: 'Mon',
115      2: 'Tue',
116      3: 'Wed',
117      4: 'Thu',
118      5: 'Fri',
119      6: 'Sat'
120    },
121
122    timezones: null
123  };
124
125  // The main element which holds the datepicker
126  var targetElement;
127
128  var values = {
129    date: null,
130    timestamp: null,
131    ampm: true
132  };
133
134  var browser = null;
135
136  // Here are the attached user events
137  var defaultChangeEventsCategories = {
138    all: [],
139    time: [],
140    date: [],
141
142    hour: [],
143    minute: [],
144    ampm: [],
145    day: [],
146    month: [],
147    year: []
148  };
149
150  var events = {
151    onChange: clone(defaultChangeEventsCategories),
152    beforeChange: clone(defaultChangeEventsCategories),
153    afterChange: clone(defaultChangeEventsCategories)
154  };
155
156  var plugins = {
157
158  };
159
160  // Keep the wheel scroll in a timeout
161  var wheelTimeout = null;
162
163  // Keep the arrow click in a timeout
164  var arrowTimeout = {};
165
166//!!!!! Add Start
167  // passive非対応ブラウザ対応
168  var passiveSupported = false;
169
170  try {
171    window.addEventListener(
172      "test",
173      null,
174      Object.defineProperty({}, "passive", {
175        get: function () {
176          passiveSupported = true;
177        },
178      })
179    );
180  } catch (err) {}
181//!!!!! Add End
182  
183//!!!!! Add Start
184  var firstFocusElement = null;
185//!!!!! Add End
186  
187  /**
188   * The main init function which prepares the datepicker for use
189   *
190   * @param  {Object} inputConfig used to setup datepicker specific features
191   */
192  var init = function (inputConfig) {
193    browser = detectBrowser();
194
195    if (!validateInputConfig(inputConfig)) {
196      console.error('Initialization of the datepicker is blocked because of errors in the config.');
197      return;
198    }
199
200    setConfig(inputConfig);
201
202    targetElement = byId(config.targetElement);
203
204    setDatesRange();
205    createMarkup();
206  };
207
208  /**
209   * Detach all event listeners and clear the markup of the component
210   */
211  var destroy = function () {
212    // Clear all attached events
213    Object.keys(events).forEach(function (eventType) {
214      Object.keys(events[eventType]).forEach(function (fieldEvent) {
215        events[eventType][fieldEvent] = [];
216      });
217    });
218
219    // Clear the markup
220    while (targetElement.firstChild) {
221      targetElement.removeChild(targetElement.firstChild);
222    }
223  }
224
225  /**
226   * Attaching the user input config settings to override the default one
227   *
228   * @param {Object} input user input settings
229   */
230  var setConfig = function (input) {
231    config.targetElement = input.target;
232
233    config.animations = input.animations !== undefined ? input.animations : config.animations;
234    config.future = input.future !== undefined ? input.future : config.future;
235    config.validateAfter = input.validateAfter !== undefined ? input.validateAfter : config.validateAfter;
236    config.smartHours = input.smartHours !== undefined ? input.smartHours : config.smartHours;
237    config.disableAmPm = input.disableAmPm !== undefined ? input.disableAmPm : config.disableAmPm;
238    config.datepicker = input.datepicker !== undefined ? input.datepicker : config.datepicker;
239    config.timepicker = input.timepicker !== undefined ? input.timepicker : config.timepicker;
240
241    // Change the defaults if the AM/PM is disabled
242    if (config.disableAmPm) {
243      config.hours.min = 0;
244      config.hours.max = 23;
245    }
246
247    values.date = input.timestamp ? new Date(input.timestamp) : new Date();
248    values.date.setSeconds(0);
249
250    if (input.utcTimezone !== undefined) {
251      // We are sure that the timezones plugin is loaded because we've made a check in the input validation
252      plugins.timezones = new MtrDatepickerTimezones();
253      config.utcTimezone = plugins.timezones.getTimezone(input.utcTimezone);
254    } else {
255      config.utcTimezone = {
256        offset: input.utcTimezone !== undefined ? input.utcTimezone : (values.date.getTimezoneOffset() / 60 * -1)
257      };
258    }
259
260    var localTimezoneOffsetTimestamp = values.date.getTime() + (values.date.getTimezoneOffset() * 60 * 1000);
261    var timezoneOffsetTimestamp = localTimezoneOffsetTimestamp + (config.utcTimezone.offset * 60 * 60 * 1000);
262
263    values.date = new Date(timezoneOffsetTimestamp);
264    values.timestamp = values.date.getTime();
265
266    // Override minutes
267    config.minutes.min = (input.minutes !== undefined && input.minutes.min !== undefined) ? parseInt(input.minutes.min) : config.minutes.min;
268    config.minutes.max = (input.minutes !== undefined && input.minutes.max !== undefined) ? parseInt(input.minutes.max) : config.minutes.max;
269    config.minutes.step = (input.minutes !== undefined && input.minutes.step !== undefined) ? parseInt(input.minutes.step) : config.minutes.step;
270
271    // Override months
272    config.months.min = (input.months !== undefined && input.months.min !== undefined) ? parseInt(input.months.min) : config.months.min;
273    config.months.max = (input.months !== undefined && input.months.max !== undefined) ? parseInt(input.months.max) : config.months.max;
274    config.months.step = (input.months !== undefined && input.months.step !== undefined) ? parseInt(input.months.step) : config.months.step;
275
276    // Override years
277    config.years.min = (input.years !== undefined && input.years.min !== undefined) ? parseInt(input.years.min) : config.years.min;
278    config.years.max = (input.years !== undefined && input.years.max !== undefined) ? parseInt(input.years.max) : config.years.max;
279    config.years.step = (input.years !== undefined && input.years.step !== undefined) ? parseInt(input.years.step) : config.years.step;
280
281    // Init hours
282    config.defaultValues.hours = createRange(config.hours);
283    config.defaultValues.minutes = createRange(config.minutes);
284    config.defaultValues.months = createRange(config.months);
285    config.defaultValues.years = createRange(config.years);
286  };
287
288  var validateInputConfig = function (input) {
289    var result = true;
290
291    if (input.datepicker !== undefined && input.timepicker !== undefined) {
292      if (!input.datepicker && !input.timepicker) {
293        console.error('Invalid configuration: cannot disable both datepicker and timepicker at the same time.');
294        result = false;
295      }
296    }
297
298    if (input.minutes) {
299      // Validate data type
300      if (input.minutes.min !== undefined && !isNumber(input.minutes.min)) {
301        console.error('Invalid argument: minutes.min should be a number.');
302        result = false;
303      }
304      if (input.minutes.max !== undefined && !isNumber(input.minutes.max)) {
305        console.error('Invalid argument: minutes.max should be a number.');
306        result = false;
307      }
308      if (input.minutes.step !== undefined && !isNumber(input.minutes.step)) {
309        console.error('Invalid argument: minutes.step should be a number.');
310        result = false;
311      }
312
313      // Validate the range
314      if (input.minutes.min !== undefined && input.minutes.max !== undefined && input.minutes.max < input.minutes.min) {
315        console.error('Invalid argument: minutes.max should be larger than minutes.min.');
316        result = false;
317      }
318
319      if (input.minutes.min !== undefined &&
320        input.minutes.max !== undefined &&
321        input.minutes.step !== undefined &&
322        (input.minutes.step > (input.minutes.max - input.minutes.min))) {
323        console.error('Invalid argument: minutes.step should be less than minutes.max-minutes.min.');
324        result = false;
325      }
326    }
327
328    if (input.hours) {
329      // Validate data type
330      if (input.hours.min !== undefined && !isNumber(input.hours.min)) {
331        console.error('Invalid argument: hours.min should be a number.');
332        result = false;
333      }
334      if (input.hours.max !== undefined && !isNumber(input.hours.max)) {
335        console.error('Invalid argument: hours.max should be a number.');
336        result = false;
337      }
338      if (input.hours.step !== undefined && !isNumber(input.hours.step)) {
339        console.error('Invalid argument: hours.step should be a number.');
340        result = false;
341      }
342
343      // Validate the range
344      if (input.hours.min !== undefined && input.hours.max !== undefined && input.hours.max < input.hours.min) {
345        console.error('Invalid argument: hours.max should be larger than hours.min.');
346        result = false;
347      }
348
349      if (input.hours.min !== undefined &&
350        input.hours.max !== undefined &&
351        input.hours.step !== undefined &&
352        (input.hours.step > (input.hours.max - input.hours.min))) {
353        console.error('Invalid argument: hours.step should be less than hours.max-hours.min.');
354        result = false;
355      }
356    }
357
358    if (input.dates) {
359      // Validate data type
360      if (input.dates.min !== undefined && !isNumber(input.dates.min)) {
361        console.error('Invalid argument: dates.min should be a number.');
362        result = false;
363      }
364      if (input.dates.max !== undefined && !isNumber(input.dates.max)) {
365        console.error('Invalid argument: dates.max should be a number.');
366        result = false;
367      }
368      if (input.dates.step !== undefined && !isNumber(input.dates.step)) {
369        console.error('Invalid argument: dates.step should be a number.');
370        result = false;
371      }
372
373      // Validate the range
374      if (input.dates.min !== undefined && input.dates.max !== undefined && input.dates.max < input.dates.min) {
375        console.error('Invalid argument: dates.max should be larger than dates.min.');
376        result = false;
377      }
378
379      if (input.dates.min !== undefined &&
380        input.dates.max !== undefined &&
381        input.dates.step !== undefined &&
382        (input.dates.step > (input.dates.max - input.dates.min))) {
383        console.error('Invalid argument: dates.step should be less than dates.max-dates.min.');
384        result = false;
385      }
386    }
387
388    if (input.months) {
389      // Validate data type
390      if (input.months.min !== undefined && !isNumber(input.months.min)) {
391        console.error('Invalid argument: months.min should be a number.');
392        result = false;
393      }
394      if (input.months.max !== undefined && !isNumber(input.months.max)) {
395        console.error('Invalid argument: months.max should be a number.');
396        result = false;
397      }
398      if (input.months.step !== undefined && !isNumber(input.months.step)) {
399        console.error('Invalid argument: months.step should be a number.');
400        result = false;
401      }
402
403      // Validate the range
404      if (input.months.min !== undefined && input.months.max !== undefined && input.months.max < input.months.min) {
405        console.error('Invalid argument: months.max should be larger than months.min.');
406        result = false;
407      }
408
409      if (input.months.min !== undefined &&
410        input.months.max !== undefined &&
411        input.months.step !== undefined &&
412        (input.months.step > (input.months.max - input.months.min))) {
413        console.error('Invalid argument: months.step should be less than months.max-months.min.');
414        result = false;
415      }
416    }
417
418    if (input.years) {
419      // Validate data type
420      if (input.years.min !== undefined && !isNumber(input.years.min)) {
421        console.error('Invalid argument: years.min should be a number.');
422        result = false;
423      }
424      if (input.years.max !== undefined && !isNumber(input.years.max)) {
425        console.error('Invalid argument: years.max should be a number.');
426        result = false;
427      }
428      if (input.years.step !== undefined && !isNumber(input.years.step)) {
429        console.error('Invalid argument: years.step should be a number.');
430        result = false;
431      }
432
433      // Validate the range
434      if (input.years.min !== undefined && input.years.max !== undefined && input.years.max < input.years.min) {
435        console.error('Invalid argument: years.max should be larger than years.min.');
436        result = false;
437      }
438
439      if (input.years.min !== undefined &&
440        input.years.max !== undefined &&
441        input.years.step !== undefined && (input.years.step > (input.years.max - input.years.min))) {
442        console.error('Invalid argument: years.step should be less than years.max-years.min.');
443        result = false;
444      }
445    }
446
447    // Validate input timestamp
448    if (input.timestamp) {
449      // If the future dates is enabled, it will be a good idea to check the input timestamp, maybe it is in the past?
450      if (input.future) {
451        var timestampDate = new Date(input.timestamp);
452        var todayDate = new Date();
453
454        if (timestampDate.getTime() < todayDate.getTime()) {
455          console.error('Invalid argument: timestamp should be in the future if the future check is enabled.');
456          result = false;
457        }
458      }
459    }
460
461    if (input.utcTimezone !== undefined && typeof MtrDatepickerTimezones !== 'function') {
462      console.error('In order to use the timezones feature you should load the mtr-datepicker-timezones.min.js first.');
463      result = false;
464    }
465
466    // If there are any errors return a new target element with notice for the users
467    if (!result) {
468      targetElement = byId(input.target);
469
470      while (targetElement.firstChild) {
471        targetElement.removeChild(targetElement.firstChild);
472      }
473
474      var errorElement = document.createElement('div');
475      addClass(errorElement, 'mtr-error-message');
476      errorElement.appendChild(document.createTextNode('An error has occurred during the initialization of the datepicker.'));
477
478      targetElement.appendChild(errorElement);
479    }
480
481    return result;
482  };
483
484  var setDatesRange = function (month, year) {
485    month = month !== undefined ? month : getMonth();
486    year = year !== undefined ? year : getYear();
487
488    var datesRange = createRangeForDate(month, year);
489    config.dates = {
490      min: datesRange.min,
491      max: datesRange.max,
492      step: datesRange.step,
493      maxlength: 2
494    };
495    config.defaultValues.dates = datesRange.values;
496    config.defaultValues.datesNames = datesRange.names;
497  };
498
499  /**
500   * Generate the main markup used from the datepicker
501   * This means that here we are generating input sliders for hours, minutes, months, dates and years
502   * and a radio input for switching the time AM/PM
503   */
504  var createMarkup = function () {
505    // Clear all of the content of the target element
506    removeClass(targetElement, 'mtr-datepicker');
507    addClass(targetElement, 'mtr-datepicker');
508    while (targetElement.firstChild) {
509      targetElement.removeChild(targetElement.firstChild);
510    }
511
512    // Create time elements
513    if (config.timepicker) {
514      var hoursElement = createSliderInput({
515        name: 'hours',
516        values: config.defaultValues.hours,
517        value: getHours()
518//!!!!! Add Start
519        ,valueMaxLength: config.hours.maxlength
520//!!!!! Add End
521      });
522
523      var minutesElement = createSliderInput({
524        name: 'minutes',
525        values: config.defaultValues.minutes,
526        value: getMinutes()
527//!!!!! Add Start
528        ,valueMaxLength: config.minutes.maxlength
529//!!!!! Add End
530      });
531
532      var amPmElement;
533      if (!config.disableAmPm) {
534        amPmElement = createRadioInput({
535          name: 'ampm'
536        });
537      }
538
539      var rowTime = document.createElement('div');
540      rowTime.className = 'mtr-row';
541
542      var rowClearfixTime = document.createElement('div');
543      rowClearfixTime.className = 'mtr-clearfix';
544
545      rowTime.appendChild(hoursElement);
546      rowTime.appendChild(minutesElement);
547
548      if (!config.disableAmPm) {
549        rowTime.appendChild(amPmElement);
550      }
551
552      targetElement.appendChild(rowTime);
553      targetElement.appendChild(rowClearfixTime);
554      
555//!!!!! Add Start
556      firstFocusElement = hoursElement;
557//!!!!! Add End
558    }
559
560    // Create date elements
561    if (config.datepicker) {
562      var monthElement = createSliderInput({
563        name: 'months',
564        values: config.defaultValues.months,
565        valuesNames: config.monthsNames,
566        value: getMonth()
567//!!!!! Add Start
568        ,valueMaxLength: config.months.maxlength
569//!!!!! Add End
570      });
571
572      var dateElement = createSliderInput({
573        name: 'dates',
574        values: config.defaultValues.dates,
575        valuesNames: config.defaultValues.datesNames,
576        value: getDate()
577//!!!!! Add Start
578        ,valueMaxLength: config.dates.maxlength
579//!!!!! Add End
580      });
581
582      var yearElement = createSliderInput({
583        name: 'years',
584        values: config.defaultValues.years,
585        value: getYear()
586//!!!!! Add Start
587        ,valueMaxLength: config.years.maxlength
588//!!!!! Add End
589      });
590
591      var rowDate = document.createElement('div');
592      rowDate.className = 'mtr-row';
593
594      var rowClearfixDate = document.createElement('div');
595      rowClearfixDate.className = 'mtr-clearfix';
596
597      if (Array.isArray(config.datepicker)) {
598        // If provided use the desired order of the date fields
599        config.datepicker.forEach(function (field) {
600          switch (field) {
601            case 'months': rowDate.appendChild(monthElement); break;
602            case 'dates': rowDate.appendChild(dateElement); break;
603            case 'years': rowDate.appendChild(yearElement); break;
604            default: break;
605          }
606//!!!!! Add Start
607        if (!firstFocusElement) {
608          switch (field) {
609            case 'months': firstFocusElement = monthElement; break;
610            case 'dates': firstFocusElement = dateElement; break;
611            case 'years': firstFocusElement = yearElement; break;
612            default: break;
613          }
614        }
615//!!!!! Add End
616        });
617      } else {
618        rowDate.appendChild(monthElement);
619        rowDate.appendChild(dateElement);
620        rowDate.appendChild(yearElement);
621//!!!!! Add Start
622        if (!firstFocusElement) {
623          firstFocusElement = monthElement;
624        }
625//!!!!! Add End
626      }
627
628      targetElement.appendChild(rowDate);
629      targetElement.appendChild(rowClearfixDate);
630    }
631
632//!!!!! Modify Start
633//    setTimestamp(values.timestamp);
634    setTimestamp(values.timestamp, true);
635//!!!!! Modify End
636  };
637
638  /**
639   * This function is creating a slider input
640   *
641   * It is generating the required markup and attaching the needed event listeners
642   * The returned element is fully functional input field with arrows for navigating
643   * through the values
644   *
645   * @param  {object} elementConfig
646   * @return {HtmlElement}
647   */
648
649  var createSliderInput = function (elementConfig) {
650    var element = document.createElement('div');
651    element.className = 'mtr-input-slider';
652    config.references[elementConfig.name] = config.targetElement + '-input-' + elementConfig.name;
653    element.id = config.references[elementConfig.name];
654
655    // First, let's init the main elements
656    var divArrowUp = createUpArrow();
657    var divArrowDown = createDownArrow();
658
659    // Content of the input, holding the input and the available values
660    var divContent = document.createElement('div');
661    divContent.className = 'mtr-content';
662
663    var inputValue = createInputValue();
664    var divValues = createValues(inputValue);
665
666    // The, let's append them to the element in the correct order
667    element.appendChild(divArrowUp);
668
669    // Append holder of the input and values to the main element
670    divContent.appendChild(inputValue);
671    divContent.appendChild(divValues);
672
673    element.appendChild(divContent);
674
675    element.appendChild(divArrowDown);
676
677    // Here are the definitions of the functions which are used to generate the markup
678    // and to attach the needed event listeners
679
680    function createUpArrow () {
681      var divArrowUp = document.createElement('div');
682      divArrowUp.className = 'mtr-arrow up';
683      divArrowUp.appendChild(document.createElement('span'));
684//!!!!! Add Start
685      var divMark = document.createElement('div');
686      divMark.innerHTML = '+';
687      divArrowUp.appendChild(divMark);
688//!!!!! Add End
689
690      // Attach event listener
691//!!!!! Modify Start
692//      divArrowUp.addEventListener('click', function () {
693      function upCount() {
694//!!!!! Modify End
695        
696        // Prevent blur event
697        // var input = qSelect(inputValue, '.mtr-input');
698        addClass(inputValue, 'arrow-click');
699        addClass(divContent, 'mtr-active');
700
701        if (arrowTimeout[elementConfig.name]) {
702          window.clearTimeout(arrowTimeout[elementConfig.name]);
703        }
704
705        arrowTimeout[elementConfig.name] = setTimeout(function () {
706          removeClass(inputValue, 'arrow-click');
707          removeClass(divContent, 'mtr-active');
708        }, 1000);
709
710        // Change the value with the next one
711        var name = elementConfig.name;
712        var currentValue;
713
714        switch (name) {
715          case 'hours': currentValue = getHours(); break;
716          case 'minutes': currentValue = getMinutes(); break;
717          case 'dates': currentValue = getDate(); break;
718          case 'months': currentValue = getMonth(); break;
719          case 'years': currentValue = getYear(); break;
720        }
721
722        var indexInArray = config.defaultValues[name].indexOf(currentValue);
723        indexInArray++;
724
725        if (indexInArray >= config.defaultValues[name].length) {
726          indexInArray = 0;
727        }
728
729        switch (name) {
730          case 'hours':
731            // Check is we have to make a transform of the hour
732            var newHour = config.defaultValues[name][indexInArray];
733            if (!config.disableAmPm && (getIsPm() && newHour !== 12)) {
734              newHour += 12;
735            }
736            setHours(newHour);
737            break;
738          case 'minutes': setMinutes(config.defaultValues[name][indexInArray]); break;
739          case 'dates': setDate(config.defaultValues[name][indexInArray]); break;
740          case 'months': setMonth(config.defaultValues[name][indexInArray]); break;
741          case 'years': setYear(config.defaultValues[name][indexInArray]); break;
742        }
743//!!!!! Modify Start
744//      }, false);
745      }
746      // マウスボタンダウン中は連続カウントアップ
747      var timerMouseDown = null;
748      var mouseDownIntervalRaised = false;
749      function endUpCount() {
750        clearInterval(timerMouseDown);
751        timerMouseDown = null;
752        if (this.isLeave) {
753          mouseDownIntervalRaised = false;
754        }
755      }
756      
757      divArrowUp.addEventListener('mousedown', function() {
758        mouseDownIntervalRaised = false;
759        timerMouseDown = setInterval(function() {
760          mouseDownIntervalRaised = true;
761          upCount();
762        }, config.mouseDownTransitionInterval);
763      }, false);
764      
765      divArrowUp.addEventListener('click', function(e) {
766        if (!mouseDownIntervalRaised || !e.isTrusted) {
767          upCount();
768        }
769        mouseDownIntervalRaised = false;
770      }, false);
771      
772      divArrowUp.addEventListener('mouseup', {isLeave: false, handleEvent: endUpCount}, false);
773      divArrowUp.addEventListener('mouseleave', {isLeave: true, handleEvent: endUpCount}, false);
774      
775      // タッチも同様
776      var touchDownIntervalRaised = false;
777      divArrowUp.addEventListener('touchstart', function(e) {
778        e.preventDefault();
779        e.stopPropagation();
780        mouseDownIntervalRaised = false;
781        touchDownIntervalRaised = false;
782        e.currentTarget.classList.add('touch-active');
783        
784        timerMouseDown = setInterval(function() {
785          mouseDownIntervalRaised = true;
786          touchDownIntervalRaised = true;
787          upCount();
788        }, config.mouseDownTransitionInterval);
789      }, passiveSupported ? {passive: false} : false);
790      
791      divArrowUp.addEventListener('touchmove', function(e) {
792        var elmPt = document.elementFromPoint(e.touches[0].clientX, e.touches[0].clientY);
793        if (divArrowUp != elmPt && divArrowUp != elmPt.parentElement) {
794          this.isLeave = true;
795          endUpCount();
796          e.currentTarget.classList.remove('touch-active');
797        }
798      }, passiveSupported ? {passive: false} : false);
799      
800      divArrowUp.addEventListener('touchend', function(e) {
801        if (e.currentTarget.classList.contains('touch-active')) {
802          if (!touchDownIntervalRaised) {
803            upCount();
804          }
805          this.isLeave = false;
806          endUpCount();
807          e.currentTarget.classList.remove('touch-active');
808        }
809      }, passiveSupported ? {passive: false} : false);
810//!!!!! Modify End
811
812      return divArrowUp;
813    }
814
815    function createDownArrow () {
816      var divArrowDown = document.createElement('div');
817      divArrowDown.className = 'mtr-arrow down';
818      divArrowDown.appendChild(document.createElement('span'));
819//!!!!! Add Start
820      var divMark = document.createElement('div');
821      divMark.innerHTML = '-';
822      divArrowDown.appendChild(divMark);
823//!!!!! Add End
824
825//!!!!! Modify Start
826//      divArrowDown.addEventListener('click', function (e) {
827      function downCount() {
828//!!!!! Modify End
829        // Prevent blur event
830        // var input = qSelect(inputValue, '.mtr-input');
831        addClass(inputValue, 'arrow-click');
832        addClass(divContent, 'mtr-active');
833
834        if (arrowTimeout[elementConfig.name]) {
835          window.clearTimeout(arrowTimeout[elementConfig.name]);
836        }
837
838        arrowTimeout[elementConfig.name] = setTimeout(function () {
839          removeClass(inputValue, 'arrow-click');
840          removeClass(divContent, 'mtr-active');
841        }, 1000);
842
843        // Change the value with the prev one
844        var name = elementConfig.name;
845        var currentValue;
846
847        switch (name) {
848          case 'hours': currentValue = getHours(); break;
849          case 'minutes': currentValue = getMinutes(); break;
850          case 'dates': currentValue = getDate(); break;
851          case 'months': currentValue = getMonth(); break;
852          case 'years': currentValue = getYear(); break;
853        }
854
855        var indexInArray = config.defaultValues[name].indexOf(currentValue);
856        indexInArray--;
857
858        if (indexInArray < 0) {
859          indexInArray = config.defaultValues[name].length - 1;
860        }
861
862        switch (name) {
863          case 'hours':
864            // Check is we have to make a transform of the hour
865            var newHour = config.defaultValues[name][indexInArray];
866            if (!config.disableAmPm && (getIsPm() && newHour !== 12)) {
867              newHour += 12;
868            }
869            setHours(newHour);
870            break;
871          case 'minutes': setMinutes(config.defaultValues[name][indexInArray]); break;
872          case 'dates': setDate(config.defaultValues[name][indexInArray]); break;
873          case 'months': setMonth(config.defaultValues[name][indexInArray]); break;
874          case 'years': setYear(config.defaultValues[name][indexInArray]); break;
875        }
876//!!!!! Modify Start
877//      }, false);
878      }
879      // マウスボタンダウン中は連続カウントダウン
880      var timerMouseDown = null;
881      var mouseDownIntervalRaised = false;
882      function endDownCount() {
883        clearInterval(timerMouseDown);
884        timerMouseDown = null;
885        if (this.isLeave) {
886          mouseDownIntervalRaised = false;
887        }
888      }
889      
890      divArrowDown.addEventListener('mousedown', function() {
891        mouseDownIntervalRaised = false;
892        timerMouseDown = setInterval(function() {
893          mouseDownIntervalRaised = true;
894          downCount();
895        }, config.mouseDownTransitionInterval);
896      }, false);
897      
898      divArrowDown.addEventListener('click', function(e) {
899        if (!mouseDownIntervalRaised || !e.isTrusted) {
900          downCount();
901        }
902        mouseDownIntervalRaised = false;
903      }, false);
904      
905      divArrowDown.addEventListener('mouseup', {isLeave: false, handleEvent: endDownCount}, false);
906      divArrowDown.addEventListener('mouseleave', {isLeave: true, handleEvent: endDownCount}, false);
907      
908      // タッチも同様
909      var touchDownIntervalRaised = false;
910      divArrowDown.addEventListener('touchstart', function(e) {
911        e.preventDefault();
912        e.stopPropagation();
913        mouseDownIntervalRaised = false;
914        touchDownIntervalRaised = false;
915        e.currentTarget.classList.add('touch-active');
916        
917        timerMouseDown = setInterval(function() {
918          mouseDownIntervalRaised = true;
919          touchDownIntervalRaised = true;
920          downCount();
921        }, config.mouseDownTransitionInterval);
922      }, passiveSupported ? {passive: false} : false);
923      
924      divArrowDown.addEventListener('touchmove', function(e) {
925        var elmPt = document.elementFromPoint(e.touches[0].clientX, e.touches[0].clientY);
926        if (divArrowDown != elmPt && divArrowDown != elmPt.parentElement) {
927          this.isLeave = true;
928          endDownCount();
929          e.currentTarget.classList.remove('touch-active');
930        }
931      }, passiveSupported ? {passive: false} : false);
932      
933      divArrowDown.addEventListener('touchend', function(e) {
934        if (e.currentTarget.classList.contains('touch-active')) {
935          if (!touchDownIntervalRaised) {
936            downCount();
937          }
938          this.isLeave = false;
939          endDownCount();
940          e.currentTarget.classList.remove('touch-active');
941        }
942      }, passiveSupported ? {passive: false} : false);
943//!!!!! Modify End
944
945      return divArrowDown;
946    }
947
948    function createInputValue () {
949      var inputValue = document.createElement('input');
950//!!!!! Modify Start
951//      inputValue.value = elementConfig.value;
952      inputValue.value = paddingZero(elementConfig.value, elementConfig.valueMaxLength);
953//!!!!! Modify End
954      inputValue.type = 'text';
955      inputValue.className = 'mtr-input ' + elementConfig.name;
956      inputValue.style.display = 'none';
957//!!!!! Add Start
958      if (config.inputReadonly) {
959        inputValue.readOnly = true;
960      }
961//!!!!! Add End
962      
963      // Attach event listeners
964//!!!!! Add Start
965      inputValue.addEventListener('focus', function (e) {
966        if (!config.inputReadonly) {
967          inputValue.setSelectionRange(0, inputValue.value.length);
968        }
969      }, false);
970//!!!!! Add End
971      
972      inputValue.addEventListener('blur', function (e) {
973//!!!!! Modify Start
974//        // Blur event has to be called after specific amount of time
975//        // because it can be caused from an arrow button. In this case
976//        // we shouldn't apple the blur event body
977//        setTimeout(function () {
978//          blurEvent();
979//        }, 500);
980        
981        if (e.target.className.indexOf('arrow-click') > -1) {
982          // Blur event has to be called after specific amount of time
983          // because it can be caused from an arrow button. In this case
984          // we shouldn't apple the blur event body
985          setTimeout(function () {
986            blurEvent();
987          }, 500);
988        } else {
989          blurEvent();
990        }
991//!!!!! Modify End
992
993        function blurEvent () {
994          if (!targetElement) {
995            return;
996          }
997
998//!!!!! Modify Start
999//          var newValue = inputValue.value;
1000          var newValue = parseInt(inputValue.value);
1001//!!!!! Modify End
1002          var oldValue = inputValue.getAttribute('data-old-value');
1003
1004          // If the blur is called after click on arrow we shouldn't update the value
1005          if (e.target.className.indexOf('arrow-click') > -1) {
1006            removeClass(e.target, 'arrow-click');
1007            return;
1008          }
1009
1010          // If this is the month input we should decrement it because
1011          // the months are starting from 0
1012          if (inputValue.className.indexOf('months') > -1) {
1013            newValue--;
1014          }
1015
1016          // Validate the value
1017          if (validateValue(elementConfig.name, newValue) === false) {
1018//!!!!! Modify Start
1019//            inputValue.value = oldValue;
1020            inputValue.value = paddingZero(oldValue, elementConfig.valueMaxLength);
1021//!!!!! Modify End
1022            inputValue.focus();
1023//!!!!! Add Start
1024            if (!config.inputReadonly) {
1025              inputValue.setSelectionRange(0, inputValue.value.length);
1026            }
1027//!!!!! Add End
1028            return;
1029          }
1030
1031          // Trim the leading zero
1032          newValue = parseInt(newValue);
1033
1034          // If the future detection is ON validate the value again
1035          var target = elementConfig.name.substring(0, elementConfig.name.length - 1);
1036          if (elementConfig.name === 'dates') {
1037            target = 'day';
1038          }
1039
1040          if (config.future && !validateChange(target, newValue, oldValue)) {
1041            if (elementConfig.name === 'months') {
1042              oldValue++;
1043            }
1044
1045//!!!!! Modify Start
1046//            inputValue.value = oldValue;
1047            inputValue.value = paddingZero(oldValue, elementConfig.valueMaxLength);
1048//!!!!! Modify End
1049            inputValue.focus();
1050//!!!!! Add Start
1051            if (!config.inputReadonly) {
1052              inputValue.setSelectionRange(0, inputValue.value.length);
1053            }
1054//!!!!! Add End
1055            return;
1056          }
1057
1058          inputValue.style.display = 'none';
1059
1060          switch (elementConfig.name) {
1061//!!!!! Modify Start
1062//            case 'hours': setHours(newValue); break;
1063//            case 'minutes': setMinutes(newValue); break;
1064//            case 'dates': setDate(newValue); break;
1065//            case 'months': setMonth(newValue); break;
1066//            case 'years': setYear(newValue); break;
1067            case 'hours': setHours(newValue, true); break;
1068            case 'minutes': setMinutes(newValue, true); break;
1069            case 'dates': setDate(newValue, true); break;
1070            case 'months': setMonth(newValue, true); break;
1071            case 'years': setYear(newValue, true); break;
1072//!!!!! Modify End
1073          }
1074        }
1075      }, false);
1076
1077//!!!!! Add Start
1078      inputValue.addEventListener('keydown', function (e) {
1079        if (e.keyCode === 38) {
1080          // [↑]キー カウントアップ
1081          e.preventDefault();
1082          e.stopPropagation();
1083          
1084          var parent = inputValue.parentElement.parentElement;
1085          var arrow;
1086          arrow = qSelect(parent, '.mtr-arrow.up');
1087          arrow.click();
1088        } else if (e.keyCode === 40) {
1089          // [↓]キー カウントダウン
1090          e.preventDefault();
1091          e.stopPropagation();
1092          
1093          var parent = inputValue.parentElement.parentElement;
1094          var arrow;
1095          arrow = qSelect(parent, '.mtr-arrow.down');
1096          arrow.click();
1097        } else if (e.keyCode === 9 && config.focusMoveByTab) {
1098          // [Tab]キー 入力遷移
1099          e.preventDefault();
1100          e.stopPropagation();
1101          
1102          var parentElm = inputValue.parentElement.parentElement;
1103          var nextElement;
1104          if (event.shiftKey) {
1105            nextElement = parentElm.previousElementSibling;
1106            if (!nextElement) {
1107              nextElement = parentElm.parentElement.lastElementChild;
1108            }
1109          } else {
1110            nextElement = parentElm.nextElementSibling;
1111            if (!nextElement) {
1112              nextElement = parentElm.parentElement.firstElementChild;
1113            }
1114          }
1115          if (nextElement && nextElement != parentElm) {
1116            setFocusInput(nextElement);
1117          }
1118        } else if ((e.keyCode === 37 || e.keyCode === 39) && config.focusMoveByLR) {
1119          // [←][→]キー 入力遷移
1120          e.preventDefault();
1121          e.stopPropagation();
1122          
1123          var parentElm = inputValue.parentElement.parentElement;
1124          var nextElement;
1125          if (e.keyCode === 37) {
1126            nextElement = parentElm.previousElementSibling;
1127            if (!nextElement) {
1128              nextElement = parentElm.parentElement.lastElementChild;
1129            }
1130          } else {
1131            nextElement = parentElm.nextElementSibling;
1132            if (!nextElement) {
1133              nextElement = parentElm.parentElement.firstElementChild;
1134            }
1135          }
1136          if (nextElement && nextElement != parentElm) {
1137            setFocusInput(nextElement);
1138          }
1139        }
1140      }, false);
1141//!!!!! Add End
1142      
1143      // Accept the new values on <Enter>
1144      inputValue.addEventListener('keyup', function (e) {
1145        if (e.keyCode === 13) {
1146          e.preventDefault();
1147          inputValue.blur();
1148        }
1149      }, false);
1150
1151      // On wheel scroll we should change the value in the input
1152      inputValue.addEventListener('wheel', function (e) {
1153        e.preventDefault();
1154        e.stopPropagation();
1155
1156        // If the user is using the mouse wheel the values should be changed
1157        // var target = e.target;
1158        var wheelData = e.wheelDeltaY ? e.wheelDeltaY : (e.deltaY * -1);
1159
1160        var oldValue = parseInt(inputValue.value);
1161        var newValue;
1162
1163        var configMin = config[elementConfig.name].min;
1164        var configMax = config[elementConfig.name].max;
1165        var configStep = config[elementConfig.name].step;
1166
1167        if (elementConfig.name === 'months') {
1168          // If we are scrolling the months we should increment the value
1169          configMin++;
1170          configMax++;
1171        }
1172
1173        if (wheelData > 0) { // Scroll up
1174          if (oldValue < configMax) {
1175            newValue = oldValue + configStep;
1176          } else {
1177            newValue = configMin;
1178          }
1179        } else { // Scroll down
1180          if (oldValue > configMin) {
1181            newValue = oldValue - configStep;
1182          } else {
1183            newValue = configMax;
1184          }
1185        }
1186
1187//!!!!! Modify Start
1188//        inputValue.value = newValue;
1189        inputValue.value = paddingZero(newValue, elementConfig.valueMaxLength);
1190        if (!config.inputReadonly) {
1191          inputValue.setSelectionRange(0, inputValue.value.length);
1192        }
1193//!!!!! Modify End
1194        return false;
1195//!!!!! Modify Start
1196//      }, false);
1197      }, passiveSupported ? {passive: false} : false);
1198//!!!!! Modify End
1199
1200      return inputValue;
1201    }
1202
1203    function createValues (inputValue) {
1204      var divValues = createElementValues(elementConfig);
1205
1206      // On swipe, we should change the value in the input
1207      divValues.addEventListener('touchstart', function (e) {
1208        handleTouchStart(e);
1209//!!!!! Modify Start
1210//      }, false);
1211      }, passiveSupported ? {passive: true} : false);
1212//!!!!! Modify End
1213      divValues.addEventListener('touchmove', function (e) {
1214        handleTouchMove(e, function (direction) {
1215          var parent = divValues.parentElement.parentElement;
1216          var arrow;
1217
1218          if (direction > 0) { // Scroll up
1219            arrow = qSelect(parent, '.mtr-arrow.up');
1220          } else { // Scroll down
1221            arrow = qSelect(parent, '.mtr-arrow.down');
1222          }
1223
1224          arrow.click();
1225        });
1226//!!!!! Modify Start
1227//      }, false);
1228      }, passiveSupported ? {passive: true} : false);
1229//!!!!! Modify End
1230
1231      return divValues;
1232    }
1233
1234    return element;
1235  };
1236
1237  /**
1238   * Create HtmlElement with a radio button control
1239   *
1240   * @param  {object} elementConfig
1241   * @return {HtmlElement}
1242   */
1243  var createRadioInput = function (elementConfig) {
1244    var element = document.createElement('div');
1245    element.className = 'mtr-input-radio';
1246    config.references[elementConfig.name] = config.targetElement + '-input-' + elementConfig.name;
1247    element.id = config.references[elementConfig.name];
1248
1249    var formHolder = document.createElement('form');
1250    formHolder.name = config.references[elementConfig.name];
1251
1252    // First create the elements
1253    var radioAm = createInputValue('ampm', 1, 'AM');
1254    var radioPm = createInputValue('ampm', 0, 'PM');
1255
1256    formHolder.appendChild(radioAm);
1257    formHolder.appendChild(radioPm);
1258
1259    formHolder.ampm.value = getIsAm() ? '1' : '0';
1260
1261    element.appendChild(formHolder);
1262
1263    function createInputValue (radioName, radioValue, labelValue) {
1264      var divHolder = document.createElement('div');
1265      var label = document.createElement('label');
1266      var input = document.createElement('input');
1267      var elementId = config.targetElement + '-radio-' + radioName + '-' + labelValue;
1268
1269      var innerHtmlSpanValue = document.createElement('span');
1270      innerHtmlSpanValue.className = 'value';
1271      innerHtmlSpanValue.appendChild(document.createTextNode(labelValue));
1272
1273      var innerHtmlSpanRadio = document.createElement('span');
1274      innerHtmlSpanRadio.className = 'radio';
1275
1276      label.setAttribute('for', elementId);
1277      label.appendChild(innerHtmlSpanValue);
1278      label.appendChild(innerHtmlSpanRadio);
1279
1280      input.className = 'mtr-input ';
1281      input.type = 'radio';
1282      input.name = radioName;
1283      input.id = elementId;
1284      input.value = radioValue;
1285
1286      divHolder.appendChild(input);
1287      divHolder.appendChild(label);
1288
1289      // Attach event listeners
1290      input.addEventListener('change', function (e) {
1291        var result = setAmPm(radioValue);
1292
1293        if (!result && config.future) {
1294          setAmPm(!radioValue);
1295          e.preventDefault();
1296          e.stopPropagation();
1297          return false;
1298        }
1299      }, false);
1300
1301      return divHolder;
1302    }
1303
1304    return element;
1305  };
1306
1307  /**
1308   * This function is creating a new set of HtmlElement which
1309   * contains the default values for a specific input
1310   *
1311   * @param  {object} elementConfig
1312   * @return {HtmlElement}
1313   */
1314  var createElementValues = function (elementConfig) {
1315    var divValues = document.createElement('div');
1316    divValues.className = 'mtr-values';
1317    
1318//!!!!! Modify Start
1319//    elementConfig.values.forEach(function (value) {
1320////!!!!! Modify Start
1321////      var innerHTML = elementConfig.name === 'months' ? value + 1 : value;
1322//      var innerHTML = paddingZero(elementConfig.name === 'months' ? value + 1 : value, elementConfig.valueMaxLength);
1323////!!!!! Modify End
1324//
1325//      var divValueHolder = document.createElement('div');
1326//      divValueHolder.className = 'mtr-default-value-holder';
1327//      divValueHolder.setAttribute('data-value', value);
1328//
1329//      var divValue = document.createElement('div');
1330//      divValue.className = 'mtr-default-value';
1331//      divValue.setAttribute('data-value', value);
1332//
1333//      if (elementConfig.name === 'minutes' && value === 0) {
1334//        divValue.appendChild(document.createTextNode('00'));
1335//      } else {
1336//        divValue.appendChild(document.createTextNode(innerHTML));
1337//      }
1338//
1339//      divValueHolder.appendChild(divValue);
1340//
1341//      if (elementConfig.valuesNames) {
1342//        var divValueName = document.createElement('div');
1343//        divValueName.className = 'mtr-default-value-name';
1344//        divValueName.appendChild(document.createTextNode(elementConfig.valuesNames[value]));
1345//
1346//        divValue.className += ' has-name';
1347//
1348//        divValueHolder.appendChild(divValueName);
1349//      }
1350//
1351//      divValues.appendChild(divValueHolder);
1352//    });
1353
1354    // isFirstLast: before:-1/min~max:0/after:1
1355    function createElementValue(value, isFirstLast) {
1356      var innerHTML = paddingZero(elementConfig.name === 'months' ? value + 1 : value, elementConfig.valueMaxLength);
1357
1358      var divValueHolder = document.createElement('div');
1359      divValueHolder.className = 'mtr-default-value-holder';
1360      divValueHolder.setAttribute('data-value', value);
1361      if (isFirstLast === -1) {
1362        divValueHolder.classList.add('for-loop-only');
1363        divValueHolder.classList.add('before');
1364      } else if(isFirstLast === 1) {
1365        divValueHolder.classList.add('for-loop-only');
1366        divValueHolder.classList.add('after');
1367      }
1368
1369      var divValue = document.createElement('div');
1370      divValue.className = 'mtr-default-value';
1371      divValue.setAttribute('data-value', value);
1372      if (isFirstLast === -1) {
1373        divValue.classList.add('for-loop-only');
1374        divValue.classList.add('before');
1375      } else if(isFirstLast === 1) {
1376        divValue.classList.add('for-loop-only');
1377        divValue.classList.add('after');
1378      }
1379
1380      if (elementConfig.name === 'minutes' && value === 0) {
1381        divValue.appendChild(document.createTextNode('00'));
1382      } else {
1383        divValue.appendChild(document.createTextNode(innerHTML));
1384      }
1385
1386      divValueHolder.appendChild(divValue);
1387
1388      if (elementConfig.valuesNames) {
1389        var divValueName = document.createElement('div');
1390        divValueName.className = 'mtr-default-value-name';
1391        divValueName.appendChild(document.createTextNode(elementConfig.valuesNames[value]));
1392
1393        divValue.className += ' has-name';
1394
1395        divValueHolder.appendChild(divValueName);
1396      }
1397
1398      divValues.appendChild(divValueHolder);
1399    }
1400
1401    // before(max値)→min~max→after(min値)の順にValueElementを生成し、スクロールをスムーズに見せる
1402    // before
1403    createElementValue(elementConfig.values[elementConfig.values.length-1], -1);
1404
1405    // min~max
1406    elementConfig.values.forEach(function (value) {
1407      createElementValue(value, 0);
1408    });
1409
1410    // after
1411    createElementValue(elementConfig.values[0], 1)
1412//!!!!! Modify End
1413    
1414    // Attach listeners
1415    var inputClickEventListener = function () {
1416      // Show the input field for manual setup
1417      var parent = divValues.parentElement;
1418      var inputValue = qSelect(parent, '.mtr-input');
1419
1420      // If we are working with months we have to increment the value
1421      // because the months are starting from 0
1422      if (inputValue.className.indexOf('months') > -1) {
1423
1424//!!!!! Modify Start
1425//        inputValue.value = parseInt(inputValue.value) + 1;
1426        inputValue.value = paddingZero(parseInt(inputValue.value) + 1, elementConfig.valueMaxLength);
1427//!!!!! Modify End
1428      }
1429
1430      inputValue.style.display = 'block';
1431      inputValue.focus();
1432    };
1433
1434//!!!!! Modify Start
1435//    divValues.addEventListener('click', inputClickEventListener, false);
1436//    divValues.addEventListener('touchstart', inputClickEventListener, false);
1437//    divValues.addEventListener('touchend', inputClickEventListener, false);
1438    divValues.addEventListener('click', inputClickEventListener, passiveSupported ? {passive: true} : false);
1439    divValues.addEventListener('touchstart', inputClickEventListener, passiveSupported ? {passive: true} : false);
1440    divValues.addEventListener('touchend', inputClickEventListener, passiveSupported ? {passive: true} : false);
1441//!!!!! Modify End
1442
1443    divValues.addEventListener('wheel', function (e) {
1444      e.preventDefault();
1445      e.stopPropagation();
1446
1447      if (wheelTimeout) {
1448        return false;
1449      }
1450
1451      // If the user is using the mouse wheel the values should be changed
1452      var target = e.target;
1453      var parent = target.parentElement.parentElement.parentElement.parentElement; // value -> values -> content -> input slider
1454      // var values = qSelect(parent, '.mtr-values');
1455      // var input = qSelect(parent, '.mtr-input');
1456      var wheelData = e.wheelDeltaY ? e.wheelDeltaY : (e.deltaY * -1); // Firefox doesn't support wheelDataY, so we are using deltaY and changing the sign of the value
1457
1458      var arrow;
1459
1460      if (wheelData > 0) { // Scroll up
1461        arrow = qSelect(parent, '.mtr-arrow.up');
1462      } else { // Scroll down
1463        arrow = qSelect(parent, '.mtr-arrow.down');
1464      }
1465
1466      wheelTimeout = setTimeout(function () {
1467        clearWheelTimeout();
1468      }, 100);
1469
1470      arrow.click();
1471      return false;
1472//!!!!! Modify Start
1473//    }, false);
1474    }, passiveSupported ? {passive: false} : false);
1475//!!!!! Modify End
1476
1477    divValues.addEventListener('touchstart', function (e) {
1478      e.preventDefault();
1479      e.stopPropagation();
1480      return false;
1481//!!!!! Modify Start
1482//    }, false);
1483    }, passiveSupported ? {passive: false} : false);
1484//!!!!! Modify End
1485
1486    divValues.addEventListener('touchmove', function (e) {
1487      e.preventDefault();
1488      e.stopPropagation();
1489      return false;
1490//!!!!! Modify Start
1491//    }, false);
1492    }, passiveSupported ? {passive: false} : false);
1493//!!!!! Modify End
1494
1495    return divValues;
1496  };
1497
1498  var rebuildElementValues = function (reference, data) {
1499    var element = byId(reference);
1500    var elementContent = qSelect(element, '.mtr-content');
1501    var elementContentValues = qSelect(elementContent, '.mtr-values');
1502
1503    elementContentValues.parentNode.removeChild(elementContentValues);
1504    var elementContentNewValues = createElementValues({
1505      name: data.name,
1506      values: data.values,
1507      valuesNames: data.valuesNames
1508    });
1509
1510    elementContent.appendChild(elementContentNewValues);
1511  };
1512
1513  /**
1514   * Updating the date when a month or year is changed
1515   * It should recalculate the dates in the specific month and check
1516   * the position of the date (if it's bigger than the last date of the month)
1517   *
1518   * @param  {Number} newMonth
1519   * @param  {NUmber} newYar
1520   */
1521  var updateDate = function (newMonth, newYear) {
1522    newMonth = newMonth !== undefined ? newMonth : getMonth();
1523    newYear = newYear !== undefined ? newYear : getYear();
1524
1525    // After month change we should recalculate the range of the dates
1526    setDatesRange(newMonth, newYear);
1527
1528    if (config.datepicker && (
1529      Array.isArray(config.datepicker) && config.datepicker.indexOf('dates') > -1
1530    )) {
1531      rebuildElementValues(config.references.dates, {
1532        name: 'dates',
1533        values: config.defaultValues.dates,
1534        valuesNames: config.defaultValues.datesNames
1535      });
1536    }
1537
1538    // After the change in the dates of the month we should check is the current date exist
1539    // because if the current date is 31 and the month has only 30 days it is not correct
1540    var maxDay = config.defaultValues.dates[config.defaultValues.dates.length - 1];
1541    var currentDate = getDate();
1542
1543    if (currentDate > maxDay) {
1544      setDate(maxDay);
1545    }
1546  };
1547
1548  var validateValue = function (type, value) {
1549    value = parseInt(value);
1550
1551    // Strict, the value is exact in the array
1552    return config.defaultValues[type].indexOf(value) > -1;
1553  };
1554
1555  /**
1556   * This function is validating the change of the date
1557   *
1558   * If the config.feature is enabled this function will prevent selecting dates
1559   * in the past
1560   *
1561   * @param  {String} target
1562   * @param  {Number} newValue
1563   * @param  {Number} oldValue
1564   * @return {boolean}
1565   */
1566  var validateChange = function (target, newValue, oldValue) {
1567    if (config.future === false) {
1568      return true;
1569    }
1570
1571    var dateNow = new Date();
1572    var datePicker = new Date(values.date.getTime());
1573
1574    switch (target) {
1575      case 'hour':
1576        var isAm = getIsAm();
1577        if (isAm && newValue === 12) {
1578          newValue = 0;
1579        }
1580
1581        datePicker.setHours(newValue);
1582        break;
1583      case 'minute': datePicker.setMinutes(newValue); break;
1584      case 'ampm':
1585        var currentHours = datePicker.getHours();
1586        var newHours = currentHours;
1587
1588        if (newValue !== oldValue) {
1589          if (newValue === true && currentHours > 12) { // set AM
1590            newHours = currentHours - 12;
1591          } else if (newValue === true && currentHours === 12) {
1592            newHours = 0;
1593          } else if (newValue === false && currentHours < 12) { // Set PM
1594            newHours = currentHours + 12;
1595          } else if (newValue === false && currentHours === 12) { // Set PM
1596            newHours = 12;
1597          }
1598        }
1599
1600        datePicker.setHours(newHours);
1601        break;
1602      case 'day': datePicker.setDate(newValue); break;
1603      case 'month':
1604        datePicker.setMonth(newValue);
1605        break;
1606      case 'year': datePicker.setFullYear(newValue); break;
1607    }
1608
1609    dateNow.setSeconds(0);
1610    dateNow.setMilliseconds(0);
1611    datePicker.setSeconds(0);
1612    datePicker.setMilliseconds(0);
1613
1614    if (datePicker.getTime() < dateNow.getTime()) {
1615      return false;
1616    }
1617    return true;
1618  };
1619
1620  var clearWheelTimeout = function () {
1621    wheelTimeout = null;
1622  };
1623  
1624//!!!!! Add Start
1625  var focus = function () {
1626    setFocusInput(firstFocusElement);
1627  };
1628  
1629  var setFocusInput = function (targetElement) {
1630    if (!targetElement) return;
1631
1632    var inputValue = qSelect(targetElement, '.mtr-input');
1633    if (!inputValue) return;
1634
1635    // If we are working with months we have to increment the value
1636    // because the months are starting from 0
1637    if (inputValue.className.indexOf('months') > -1) {
1638      inputValue.value = paddingZero(parseInt(inputValue.value) + 1, elementConfig.valueMaxLength);
1639    }
1640
1641    inputValue.style.display = 'block';
1642    inputValue.focus();
1643  }
1644//!!!!! Add End
1645
1646  /*****************************************************************************
1647   * A lot of getters and setters now
1648   ****************************************************************************/
1649
1650  var setHours = function (input, preventAnimation) {
1651    var oldValue = values.date.getHours();
1652    var isChangeValid = validateChange('hour', input, oldValue);
1653    var isAm = getIsAm();
1654
1655    // If the smart hours are enabled and we want to gto from 11 Am to 12 PM, we should
1656    // disable the validation
1657    if (!config.disableAmPm && (config.smartHours && input === 12 && isAm)) {
1658      isChangeValid = true;
1659    }
1660
1661    if (!config.validateAfter && !isChangeValid) {
1662      showInputSliderError(config.references.hours);
1663      return;
1664    }
1665    executeChangeEvents('hour', 'beforeChange', input, oldValue);
1666    var newHour = input;
1667    if (!config.disableAmPm && input > 12) {
1668      input -= 12; // reduce the values with 12 hours
1669    }
1670
1671//!!!!! Modify Start
1672//    updateInputSlider(config.references.hours, input, preventAnimation);
1673    updateInputSlider(config.references.hours, oldValue, input, config.hours.step, config.hours.maxlength, preventAnimation);
1674//!!!!! Modify End
1675
1676    if (config.validateAfter && !isChangeValid) {
1677      showInputSliderError(config.references.hours);
1678
1679      setTimeout(function () {
1680        if (!config.disableAmPm && oldValue > 12) {
1681          oldValue -= 12;
1682        }
1683//!!!!! Modify Start
1684//        updateInputSlider(config.references.hours, oldValue, preventAnimation);
1685        updateInputSlider(config.references.hours, input, oldValue, config.hours.step, config.hours.maxlength, preventAnimation);
1686//!!!!! Modify End
1687
1688        executeChangeEvents('hour', 'onChange', input, oldValue);
1689        executeChangeEvents('hour', 'afterChange', input, oldValue);
1690      }, config.transitionValidationDelay);
1691    } else {
1692      values.timestamp = values.date.setHours(newHour);
1693      if (!config.disableAmPm && (config.smartHours && newHour === 12 && isAm)) {
1694        values.timestamp = values.date.setHours(12);
1695        setAmPm(false); // set to PM
1696      } else if (!config.disableAmPm && (config.smartHours && (newHour === 23 || newHour === 11) && oldValue === 12 && !isAm)) {
1697        newHour = 11;
1698        values.timestamp = values.date.setHours(newHour);
1699        setAmPm(true); // set to AM
1700      } else if (!config.disableAmPm && (!config.smartHours && newHour === 12 && isAm)) {
1701        values.timestamp = values.date.setHours(0);
1702      } else {
1703        values.timestamp = values.date.setHours(newHour);
1704      }
1705
1706      if (!config.disableAmPm && newHour > 12) {
1707        newHour -= 12; // reduce the values with 12 hours
1708        setAmPm(false); // set to PM
1709      }
1710
1711      executeChangeEvents('hour', 'onChange', input, oldValue);
1712      executeChangeEvents('hour', 'afterChange', input, oldValue);
1713    }
1714  };
1715
1716  var getHours = function () {
1717    var currentHours = values.date.getHours();
1718
1719    if (!config.disableAmPm) {
1720      var isAm = getIsAm();
1721      if (currentHours === 12 || currentHours === 0) {
1722        return 12;
1723      }
1724      return (currentHours < 12 && isAm) ? currentHours : currentHours - 12;
1725    } else {
1726      return currentHours;
1727    }
1728  };
1729
1730  var setMinutes = function (input, preventAnimation) {
1731    var oldValue = values.date.getMinutes();
1732    var isChangeValid = validateChange('minute', input, oldValue);
1733
1734    if (!config.validateAfter && !isChangeValid) {
1735      showInputSliderError(config.references.minutes);
1736      return;
1737    }
1738    executeChangeEvents('minute', 'beforeChange', input, oldValue);
1739    // TODO: validate
1740    // var defaultValues = config.defaultValues.minutes;
1741//!!!!! Modify Start
1742//    updateInputSlider(config.references.minutes, input, preventAnimation);
1743    updateInputSlider(config.references.minutes, oldValue, input, config.minutes.step, config.minutes.maxlength, preventAnimation);
1744//!!!!! Modify End
1745
1746    if (config.validateAfter && !isChangeValid) {
1747      showInputSliderError(config.references.minutes);
1748      setTimeout(function () {
1749//!!!!! Modify Start
1750//        updateInputSlider(config.references.minutes, oldValue, preventAnimation);
1751        updateInputSlider(config.references.minutes, input, oldValue, config.minutes.step, config.minutes.maxlength, preventAnimation);
1752//!!!!! Modify End
1753
1754        executeChangeEvents('minute', 'onChange', input, oldValue);
1755        executeChangeEvents('minute', 'afterChange', input, oldValue);
1756      }, config.transitionValidationDelay);
1757    } else {
1758      values.timestamp = values.date.setMinutes(input);
1759      executeChangeEvents('minute', 'onChange', input, oldValue);
1760      executeChangeEvents('minute', 'afterChange', input, oldValue);
1761    }
1762  };
1763
1764  var getMinutes = function () {
1765    return values.date.getMinutes();
1766  };
1767
1768  var setAmPm = function (setAmPm) {
1769    if (config.disableAmPm) {
1770      return;
1771    }
1772
1773    setAmPm = !!setAmPm;
1774
1775    var oldValue = getIsAm();
1776    if (!validateChange('ampm', setAmPm, oldValue)) {
1777      showInputRadioError(config.references.ampm, setAmPm);
1778
1779      if (browser.isSafari) {
1780        setTimeout(function () {
1781          setRadioFormValue(config.references.ampm, oldValue);
1782        }, 10);
1783      }
1784      return false;
1785    }
1786    executeChangeEvents('ampm', 'beforeChange', setAmPm, oldValue);
1787    // TODO: validate
1788
1789    var currentHours = values.date.getHours();
1790    var currentIsAm = getIsAm();
1791
1792    if (currentIsAm !== setAmPm) {
1793      if (setAmPm === true && currentHours >= 12) { // Set AM
1794        currentHours -= 12;
1795        values.timestamp = values.date.setHours(currentHours);
1796      } else if (setAmPm === false && currentHours < 12) { // Set PM
1797        currentHours += 12;
1798        values.timestamp = values.date.setHours(currentHours);
1799      }
1800    }
1801
1802    values.ampm = setAmPm;
1803    setRadioFormValue(config.references.ampm, setAmPm);
1804
1805    executeChangeEvents('ampm', 'onChange', setAmPm, oldValue);
1806    executeChangeEvents('ampm', 'afterChange', setAmPm, oldValue);
1807    return true;
1808  };
1809
1810  var setRadioFormValue = function (reference, setAmPm) {
1811    // If the timepicker or the AM/PM are disabled we don't have t do anything here
1812    if (!config.timepicker || config.disableAmPm) {
1813      return;
1814    }
1815
1816    var divRadioInput = byId(reference);
1817    var formRadio = qSelect(divRadioInput, 'form');
1818
1819    formRadio.ampm.value = setAmPm ? '1' : '0';
1820
1821    var radioAm = qSelect(formRadio, 'input.mtr-input[type="radio"][value="1"]');
1822    var radioPm = qSelect(formRadio, 'input.mtr-input[type="radio"][value="0"]');
1823
1824    if (setAmPm) {
1825      radioAm.setAttribute('checked', '');
1826      radioAm.checked = true;
1827      radioPm.removeAttribute('checked');
1828    } else {
1829      radioPm.setAttribute('checked', '');
1830      radioPm.checked = true;
1831      radioAm.removeAttribute('checked');
1832    }
1833  };
1834
1835  var getIsAm = function () {
1836    var currentHours = values.date.getHours();
1837    return currentHours >= 0 && currentHours <= 11;
1838  };
1839
1840  var getIsPm = function () {
1841    return !getIsAm();
1842  };
1843
1844  var setDate = function (newDate, preventAnimation) {
1845    var oldValue = values.date.getDate();
1846    var isChangeValid = validateChange('day', newDate, oldValue);
1847
1848    if (!config.validateAfter && !isChangeValid) {
1849      showInputSliderError(config.references.dates);
1850      return;
1851    }
1852    executeChangeEvents('day', 'beforeChange', newDate, oldValue);
1853
1854    // TODO: Validate input
1855//!!!!! Modify Start
1856//    updateInputSlider(config.references.dates, newDate, preventAnimation);
1857    updateInputSlider(config.references.dates, oldValue, newDate, 1, 2, preventAnimation);
1858//!!!!! Modify End
1859
1860    if (config.validateAfter && !isChangeValid) {
1861      showInputSliderError(config.references.dates);
1862      setTimeout(function () {
1863//!!!!! Modify Start
1864//        updateInputSlider(config.references.dates, oldValue, preventAnimation);
1865        updateInputSlider(config.references.dates, newDate, oldValue, 1, 2, preventAnimation);
1866//!!!!! Modify End
1867
1868        executeChangeEvents('day', 'onChange', newDate, oldValue);
1869        executeChangeEvents('day', 'afterChange', newDate, oldValue);
1870      }, config.transitionValidationDelay);
1871    } else {
1872      values.timestamp = values.date.setDate(newDate);
1873      executeChangeEvents('day', 'onChange', newDate, oldValue);
1874      executeChangeEvents('day', 'afterChange', newDate, oldValue);
1875    }
1876  };
1877
1878  var getDate = function () {
1879    return values.date.getDate();
1880  };
1881
1882  var setMonth = function (newMonth, preventAnimation) {
1883    var oldValue = values.date.getMonth();
1884    var isChangeValid = validateChange('month', newMonth, oldValue);
1885
1886    // TODO: Validate the number of days in the new month
1887    // Currently fails when transition from Mar 30 to Feb
1888
1889    if (!config.validateAfter && !isChangeValid) {
1890      showInputSliderError(config.references.months);
1891      return;
1892    }
1893    executeChangeEvents('month', 'beforeChange', newMonth, oldValue);
1894    // TODO: Validate input
1895
1896    // Finally, update the month
1897//!!!!! Modify Start
1898//    updateInputSlider(config.references.months, newMonth, preventAnimation);
1899    updateInputSlider(config.references.months, oldValue, newMonth, config.months.step, config.months.maxlength, preventAnimation);
1900//!!!!! Modify End
1901
1902    if (config.validateAfter && !isChangeValid) {
1903      showInputSliderError(config.references.months);
1904      setTimeout(function () {
1905//!!!!! Modify Start
1906//        updateInputSlider(config.references.months, oldValue, preventAnimation);
1907        updateInputSlider(config.references.months, newMonth, oldValue, config.months.step, config.months.maxlength, preventAnimation);
1908//!!!!! Modify End
1909
1910        executeChangeEvents('month', 'onChange', newMonth, oldValue);
1911        executeChangeEvents('month', 'afterChange', newMonth, oldValue);
1912      }, config.transitionValidationDelay);
1913    } else {
1914      values.timestamp = values.date.setMonth(newMonth);
1915      updateDate(newMonth);
1916      executeChangeEvents('month', 'onChange', newMonth, oldValue);
1917      executeChangeEvents('month', 'afterChange', newMonth, oldValue);
1918    }
1919  };
1920
1921  var getMonth = function () {
1922    return values.date.getMonth();
1923  };
1924
1925  var setYear = function (newYear, preventAnimation) {
1926    var oldValue = values.date.getFullYear();
1927    var isChangeValid = validateChange('year', newYear, oldValue);
1928
1929    if (!config.validateAfter && !isChangeValid) {
1930      showInputSliderError(config.references.years);
1931      return;
1932    }
1933    executeChangeEvents('year', 'beforeChange', newYear, oldValue);
1934    // TODO: Validate input
1935    updateDate(undefined, newYear);
1936//!!!!! Modify Start
1937//    updateInputSlider(config.references.years, newYear, preventAnimation);
1938    updateInputSlider(config.references.years, oldValue, newYear, config.years.step, config.years.maxlength, preventAnimation);
1939//!!!!! Modify End
1940
1941    if (config.validateAfter && !isChangeValid) {
1942      showInputSliderError(config.references.years);
1943      setTimeout(function () {
1944//!!!!! Modify Start
1945//        updateInputSlider(config.references.years, oldValue, preventAnimation);
1946        updateInputSlider(config.references.years, newYear, oldValue, config.years.step, config.years.maxlength, preventAnimation);
1947//!!!!! Modify End
1948
1949        executeChangeEvents('year', 'onChange', newYear, oldValue);
1950        executeChangeEvents('year', 'afterChange', newYear, oldValue);
1951      }, config.transitionValidationDelay);
1952    } else {
1953      values.timestamp = values.date.setFullYear(newYear);
1954      executeChangeEvents('year', 'onChange', newYear, oldValue);
1955      executeChangeEvents('year', 'afterChange', newYear, oldValue);
1956    }
1957  };
1958
1959  var getYear = function () {
1960    return values.date.getFullYear();
1961  };
1962
1963  // Bigger getter and setters
1964  var getTime = function () {
1965    return getHours() + ':' + getMinutes();
1966  };
1967
1968  var getFullTime = function () {
1969    var hours = getHours();
1970    var minutes = getMinutes();
1971    var amPm = getIsAm() ? 'AM' : 'PM';
1972
1973    if (minutes <= 9) {
1974      minutes = '0' + minutes;
1975    }
1976
1977    return hours + ':' + minutes + ' ' + amPm;
1978  };
1979
1980//!!!!! Modify Start
1981//  var setTimestamp = function (input) {
1982  var setTimestamp = function (input, preventAnimation) {
1983//!!!!! Modify End
1984    var roundedTimestamp = roundUpTimestamp(input);
1985
1986    values.date = new Date(roundedTimestamp);
1987    values.timestamp = roundedTimestamp;
1988
1989    var currentHours = values.date.getHours();
1990    var currentMinutes = getMinutes();
1991    var currentAmPm = currentHours >= 0 && currentHours < 12;
1992    var currentDate = getDate();
1993    var currentMonth = getMonth();
1994    var currentYear = getYear();
1995
1996//!!!!! Delete Start
1997//    currentHours = (currentHours === 0) ? 12 : currentHours;
1998//!!!!! Delete End
1999    
2000//!!!!! Modify Start
2001//    setHours(currentHours);
2002//    setMinutes(currentMinutes);
2003//    setMonth(currentMonth);
2004//    setYear(currentYear);
2005//    setDate(currentDate);
2006    setHours(currentHours, preventAnimation);
2007    setMinutes(currentMinutes, preventAnimation);
2008    setMonth(currentMonth, preventAnimation);
2009    setYear(currentYear, preventAnimation);
2010    setDate(currentDate, preventAnimation);
2011//!!!!! Modify End
2012    setAmPm(currentAmPm);
2013  };
2014
2015  var getTimestamp = function () {
2016    return values.date.getTime();
2017  };
2018
2019  /*****************************************************************************
2020   * A lot of actions here (used when event is triggered)
2021   ****************************************************************************/
2022  
2023  /**
2024   * Update the value of the input slider
2025   * @param  {string} reference id to the specific element
2026   * @param  {integer} newValue
2027   */
2028//!!!!! Modify Start
2029//  var updateInputSlider = function (reference, newValue, preventAnimation) {
2030  var updateInputSlider = function (reference, oldValue, newValue, step, valueMaxLength, preventAnimation) {
2031//!!!!! Modify End
2032    var element = byId(reference);
2033    preventAnimation = preventAnimation || false;
2034
2035    if (!element) {
2036      return;
2037    }
2038
2039    // Find the specific value
2040    var divValues = qSelect(element, '.mtr-content');
2041//!!!!! Modify Start
2042//    var divValue = qSelect(element, '.mtr-values .mtr-default-value[data-value="' + newValue + '"]');
2043    var divValue, divValue2 = null;
2044    if(Math.abs(newValue - oldValue) > step) {
2045      divValue = qSelect(element, '.mtr-values .mtr-default-value[data-value="' + newValue + '"].for-loop-only');
2046      divValue2 = qSelect(element, '.mtr-values .mtr-default-value[data-value="' + newValue + '"]:not(.for-loop-only)');
2047    } else {
2048      divValue = qSelect(element, '.mtr-values .mtr-default-value[data-value="' + newValue + '"]:not(.for-loop-only)');
2049    }
2050//!!!!! Modify End
2051    var divArrow = qSelect(element, '.mtr-arrow.up');
2052    var inputValue = qSelect(element, '.mtr-input');
2053
2054    var scrollTo = getRelativeOffset(divValues, divValue) + divArrow.clientHeight;
2055//!!!!! Add Start
2056    var scrollTo2;
2057    if (divValue2) {
2058      scrollTo2 = getRelativeOffset(divValues, divValue2) + divArrow.clientHeight;
2059    }
2060//!!!!! Add End
2061
2062//!!!!! Modify Start
2063//    inputValue.value = newValue;
2064    inputValue.value = paddingZero(newValue, valueMaxLength);
2065//!!!!! Modify End
2066    inputValue.setAttribute('data-old-value', newValue);
2067
2068    if (config.animations === false || preventAnimation) {
2069// !!!!! Modify Start
2070//      divValue.scrollIntoView();
2071      if (divValue2) {
2072        smoothScrollTo(divValues, scrollTo2, 0);
2073      } else {
2074        smoothScrollTo(divValues, scrollTo, 0);
2075      }
2076// !!!!! Modify End
2077    } else {
2078// !!!!! Modify Start
2079//      smoothScrollTo(divValues, scrollTo, config.transitionDelay);
2080      if (divValue2) {
2081        var smoothScroll2 = function () {
2082          smoothScrollTo(divValues, scrollTo2, 0);
2083        }
2084        // max→min/min→maxへの遷移時、一旦before/afterValueElementへスムーススクロールを実行後、コールバックにて本来のmin/max値を表示する
2085        smoothScrollTo(divValues, scrollTo, config.transitionDelay, smoothScroll2);
2086      } else {
2087        smoothScrollTo(divValues, scrollTo, config.transitionDelay);
2088      }
2089// !!!!! Modify End
2090    }
2091  };
2092
2093  /**
2094   * Add an error class to the current input slider when a validation has failed
2095   * @param  {String} reference id to the specific element
2096   */
2097  var showInputSliderError = function (reference) {
2098    var element = byId(reference);
2099    var divContent = qSelect(element, '.mtr-content');
2100    addClass(divContent, 'mtr-error');
2101
2102    setTimeout(function () {
2103      removeClass(divContent, 'mtr-error');
2104    }, config.transitionValidationDelay + 300);
2105  };
2106
2107  var showInputRadioError = function (reference, value) {
2108    if (typeof value === 'boolean') {
2109      value = value === true ? 1 : 0;
2110    }
2111
2112    var element = byId(reference);
2113    var divContent = qSelect(element, '.mtr-input[value="' + value + '"]');
2114    addClass(divContent, 'mtr-error');
2115
2116    setTimeout(function () {
2117      removeClass(divContent, 'mtr-error');
2118    }, config.transitionValidationDelay + 300);
2119  };
2120
2121  var executeChangeEvents = function (target, changeEvent, newValue, oldValue) {
2122    var callbackFunction = function (callback) {
2123      callback(target, newValue, oldValue);
2124    };
2125
2126    events[changeEvent][target].forEach(function (callback) {
2127      callbackFunction(callback);
2128    });
2129
2130    events[changeEvent].all.forEach(function (callback) {
2131      callbackFunction(callback);
2132    });
2133
2134    switch (target) {
2135      case 'hour':
2136      case 'minute':
2137      case 'ampm':
2138        events[changeEvent].time.forEach(function (callback) {
2139          callbackFunction(callback);
2140        });
2141        break;
2142      case 'day':
2143      case 'month':
2144      case 'year':
2145        events[changeEvent].date.forEach(function (callback) {
2146          callbackFunction(callback);
2147        });
2148        break;
2149    }
2150  };
2151
2152  /*****************************************************************************
2153   * Some Aliases
2154   ****************************************************************************/
2155
2156  function byId (selector) {
2157    return document.getElementById(selector);
2158  }
2159
2160  function qSelect (element, selector) {
2161    return element ? element.querySelector(selector) : null;
2162  }
2163
2164  function getRelativeOffset (parent, child) {
2165    if (parent && child) {
2166      return child.offsetTop - parent.offsetTop;
2167    }
2168    return 0;
2169  }
2170
2171  /**
2172   * A simple function which makes a clone of a specific JS Object
2173   * @param  {Object} obj
2174   * @return {Object}
2175   */
2176  function clone (obj) {
2177    var copy;
2178
2179    // Handle the 3 simple types, and null or undefined
2180    if (obj === null || typeof obj !== 'object') return obj;
2181
2182    // Handle Array
2183    if (obj instanceof Array) {
2184      copy = [];
2185      for (var i = 0, len = obj.length; i < len; i++) {
2186        copy[i] = clone(obj[i]);
2187      }
2188      return copy;
2189    }
2190
2191    // Handle Object
2192    if (obj instanceof Object) {
2193      copy = {};
2194      for (var attr in obj) {
2195        // eslint-disable-next-line no-prototype-builtins
2196        if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
2197      }
2198      return copy;
2199    }
2200
2201    throw new Error("Unable to copy obj! Its type isn't supported.");
2202  }
2203
2204  /**
2205   * A simple shortcut function to add a class to specific element
2206   * @param {HTMLElement} element
2207   * @param {string} className
2208   */
2209  function addClass (element, className) {
2210    if (!element) {
2211      return;
2212    }
2213
2214    if (element.className.indexOf(className) > -1) {
2215      return;
2216    }
2217
2218    element.className += ' ' + className;
2219  }
2220
2221  /**
2222   * Short alias for a function which is removing a class name from a specific element
2223   * @param {HtmlElement} element
2224   * @param {string} className
2225   */
2226  function removeClass (element, className) {
2227    if (!element) {
2228      return;
2229    }
2230
2231    if (element.className.indexOf(className) === -1) {
2232      return;
2233    }
2234
2235    element.className = element.className.replace(new RegExp(className, 'g'), '');
2236  }
2237
2238  /**
2239   * Check is a specific input a number
2240   * @param  {Number|String}  n
2241   * @return {Boolean}
2242   */
2243  function isNumber (input) {
2244    return Number(input) === input && input % 1 === 0;
2245  }
2246
2247  /**
2248   * Create array of values for a specific range with a given step
2249   * @param  {object} settings
2250   * @return {array}
2251   */
2252  function createRange (settings) {
2253    var from = settings.min;
2254    var to = settings.max;
2255    var step = settings.step;
2256    var range = [];
2257
2258    for (var i = from; i <= to; i += step) {
2259      range.push(i);
2260    }
2261
2262    return range;
2263  }
2264
2265  /**
2266   * Create a special range with dates for a specific month
2267   */
2268  function createRangeForDate (month, year) {
2269    var firstDay = new Date(year, month, 1);
2270    var lastDay = new Date(year, month + 1, 0);
2271
2272    var range = {
2273      values: [],
2274      names: [],
2275      min: firstDay.getDate(),
2276      max: lastDay.getDate(),
2277      step: 1
2278    };
2279
2280    var currentDate;
2281    for (var i = firstDay.getDate(); i <= lastDay.getDate(); i++) {
2282      currentDate = new Date(year, month, i);
2283
2284      range.values.push(i);
2285      range.names[i] = config.daysNames[currentDate.getDay()];
2286    }
2287
2288    return range;
2289  }
2290
2291  /**
2292    Smoothly scroll element to the given target (element.scrollTop)
2293    for the given duration
2294
2295    Returns a promise that's fulfilled when done, or rejected if
2296    interrupted
2297  */
2298//!!!!! Modify Start
2299//  var smoothScrollTo = function (element, target, duration) {
2300  var smoothScrollTimeout = null;
2301  var smoothScrollTo = function (element, target, duration, callBack) {
2302//!!!!! Modify End
2303    target = Math.round(target);
2304    duration = Math.round(duration);
2305    if (duration < 0) {
2306//!!!!! Add Start
2307      if (callBack) callBack();
2308      smoothScrollTimeout = null;
2309//!!!!! Add End
2310      return;
2311    }
2312    if (duration === 0) {
2313      window.devicePixelRatio !== 1
2314      element.scrollTop = target;
2315//!!!!! Add Start
2316      if (callBack) callBack();
2317      smoothScrollTimeout = null;
2318//!!!!! Add End
2319      return;
2320    }
2321
2322    var startTime = Date.now();
2323    var endTime = startTime + duration;
2324
2325    var startTop = element.scrollTop;
2326    var distance = target - startTop;
2327
2328    // https://coderwall.com/p/hujlhg/smooth-scrolling-without-jquery
2329    // based on http://en.wikipedia.org/wiki/Smoothstep
2330    var smoothStep = function (start, end, point) {
2331      if (point <= start) { return 0; }
2332      if (point >= end) { return 1; }
2333      var x = (point - start) / (end - start); // interpolation
2334      return x * x * (3 - 2 * x);
2335    };
2336
2337    // This is to keep track of where the element's scrollTop is
2338    // supposed to be, based on what we're doing
2339    var previousTop = element.scrollTop;
2340
2341//!!!!! Add Start
2342    // 連続したカウントアップ/ダウン発生時、タイマーが滞留してずれるため、直前のタイマーを破棄し最後の位置をセット
2343    if (smoothScrollTimeout) {
2344      clearTimeout(smoothScrollTimeout);
2345      smoothScrollTimeout = null;
2346    }
2347//!!!!! Add End
2348
2349    // This is like a think function from a game loop
2350//!!!!! Modify Start
2351//    var scrollFrame = function () {
2352    var scrollFrame = function (callBack) {
2353//!!!!! Modify End
2354//!!!!!ios?
2355      if (element.scrollTop !== previousTop) {
2356//!!!!! Add Start
2357        if (callBack) callBack();
2358        smoothScrollTimeout = null;
2359//!!!!! Add End
2360        return;
2361      }
2362//!!!!!ios?
2363
2364      // set the scrollTop for this frame
2365      var now = Date.now();
2366      var point = smoothStep(startTime, endTime, now);
2367      var frameTop = Math.round(startTop + (distance * point));
2368      element.scrollTop = frameTop;
2369
2370      // check if we're done!
2371      if (now >= endTime) {
2372//!!!!! Add Start
2373        if (callBack) callBack();
2374        smoothScrollTimeout = null;
2375//!!!!! Add End
2376        return;
2377      }
2378
2379      // If we were supposed to scroll but didn't, then we
2380      // probably hit the limit, so consider it done; not
2381      // interrupted.
2382//!!!!! Del Start ブラウザZoom対応
2383//      if (element.scrollTop === previousTop && element.scrollTop !== frameTop) {
2384//        return;
2385//      }
2386//!!!!! Del End
2387      previousTop = element.scrollTop;
2388
2389      // schedule next frame for execution
2390//!!!!! Modify Start
2391//      setTimeout(function () {
2392//        scrollFrame();
2393      smoothScrollTimeout = setTimeout(function () {
2394        scrollFrame(callBack);
2395//!!!!! Modify End
2396      }, 0);
2397    };
2398
2399    // bootstrap the animation process
2400//!!!!! Modify Start
2401//    setTimeout(function () {
2402//      scrollFrame();
2403    smoothScrollTimeout = setTimeout(function () {
2404      scrollFrame(callBack);
2405//!!!!! Modify End
2406    }, 0);
2407  };
2408
2409  /**
2410   * Round up a timestamp to the closest minutes (11:35 to 11:40)
2411   * @param  {Number} timestamp
2412   * @return {Number}
2413   */
2414  var roundUpTimestamp = function (timestamp) {
2415    var border = config.minutes.step * 60 * 1000;
2416    var delta = 0;
2417
2418    // We should round up the timestamp only of the minutes step is not set to 1
2419    if (config.minutes.step > 1) {
2420      delta = (border - (timestamp % border)) % timestamp;
2421    }
2422
2423    return (timestamp + delta);
2424  };
2425
2426  /**
2427   * Touch Support
2428   * http://stackoverflow.com/questions/2264072/detect-a-finger-swipe-through-javascript-on-the-iphone-and-android
2429   */
2430
2431  var xDown = null;
2432  var yDown = null;
2433
2434  function handleTouchStart (evt) {
2435    xDown = evt.touches[0].clientX;
2436    yDown = evt.touches[0].clientY;
2437  }
2438
2439  /**
2440   * @param  {Event} evt
2441   * @return {Number}
2442   */
2443  function handleTouchMove (evt, callback) {
2444    if (!xDown || !yDown) {
2445      return;
2446    }
2447
2448    var xUp = evt.touches[0].clientX;
2449    var yUp = evt.touches[0].clientY;
2450
2451    var xDiff = xDown - xUp;
2452    var yDiff = yDown - yUp;
2453
2454    if (Math.abs(xDiff) > Math.abs(yDiff)) {
2455      if (xDiff > 0) {
2456        /* left swipe */
2457      } else {
2458        /* right swipe */
2459      }
2460    } else {
2461      if (yDiff > 0) {
2462        /* up swipe */
2463        // eslint-disable-next-line standard/no-callback-literal
2464        callback(1);
2465      } else {
2466        /* down swipe */
2467        // eslint-disable-next-line standard/no-callback-literal
2468        callback(-1);
2469      }
2470    }
2471    /* reset values */
2472    xDown = null;
2473    yDown = null;
2474  }
2475
2476  /*****************************************************************************
2477   * PUBLIC API
2478   *
2479   * Getters
2480   ****************************************************************************/
2481
2482  // Here is a set of the default Date function
2483  // We are providing them because the user are familiar with them and
2484  // maybe this way they will implement this library easily in their system
2485
2486  // "Wed Sep 23 2015"
2487  var toDateString = function () {
2488    return values.date.toDateString();
2489  };
2490
2491  // "Wed, 23 Sep 2015 08:43:47 GMT"
2492  var toGMTString = function () {
2493    // Remove the offsets of the timezone
2494    var localTimezoneOffsetTimestamp = values.date.getTime() - (values.date.getTimezoneOffset() * 60 * 1000);
2495    var timezoneOffsetTimestamp = localTimezoneOffsetTimestamp - (config.utcTimezone.offset * 60 * 60 * 1000);
2496
2497    var date = new Date(timezoneOffsetTimestamp);
2498
2499    return date.toGMTString();
2500  };
2501
2502  // "2015-09-23T08:43:47.284Z"
2503  var toISOString = function () {
2504    return values.date.toISOString();
2505  };
2506
2507  // "9/23/2015"
2508  var toLocaleDateString = function () {
2509    return values.date.toLocaleDateString();
2510  };
2511
2512  // "9/23/2015, 11:43:47 AM"
2513  var toLocaleString = function () {
2514    return values.date.toLocaleString();
2515  };
2516
2517  // "11:43:47 AM"
2518  var toLocaleTimeString = function () {
2519    return values.date.toLocaleTimeString();
2520  };
2521
2522  // "Wed Sep 23 2015 11:43:47 GMT+0300 (EEST)"
2523  var toString = function () {
2524    if (plugins.timezones) {
2525      return toDateString() + ' ' + toTimeString();
2526    }
2527
2528    return values.date.toString();
2529  };
2530
2531  // 11:43:47 GMT+0300 (EEST)"
2532  var toTimeString = function () {
2533    if (plugins.timezones) {
2534      var toReturn = '';
2535      var timeString = values.date.toTimeString().split(' ');
2536
2537      toReturn += timeString[0];
2538      toReturn += ' GMT' + (config.utcTimezone.offset > 0 ? '+' : '-') + (Math.abs(config.utcTimezone.offset) < 10 ? '0' : '') + Math.abs(config.utcTimezone.offset) + '00';
2539      toReturn += ' (' + config.utcTimezone.abbr + ')';
2540
2541      return toReturn;
2542    }
2543
2544    return values.date.toTimeString();
2545  };
2546
2547  // "Wed, 23 Sep 2015 08:43:47 GMT"
2548  var toUTCString = function () {
2549    // Remove the offsets of the timezone
2550    var localTimezoneOffsetTimestamp = values.date.getTime() - (values.date.getTimezoneOffset() * 60 * 1000);
2551    var timezoneOffsetTimestamp = localTimezoneOffsetTimestamp - (config.utcTimezone.offset * 60 * 60 * 1000);
2552
2553    var date = new Date(timezoneOffsetTimestamp);
2554
2555    return date.toUTCString();
2556  };
2557
2558  /**
2559   * Return datetime in specific format
2560   * @param  {String} input
2561   * @return {String}
2562   *
2563   * M,MM, MMM
2564   * D,DD
2565   * Y,YY, YYYY
2566   *
2567   * h, hh
2568   * m, mm
2569   * a, AA
2570   * Z, ZZ
2571   */
2572  var format = function (input) {
2573    var currentHours = getHours();
2574    var currentMinutes = getMinutes();
2575    var currentAmPm = getIsAm();
2576
2577    var currentDate = getDate();
2578    var currentMonth = getMonth() + 1;
2579    var currentYear = getYear();
2580    var currentTimezone = config.utcTimezone.offset;
2581
2582    // Dates
2583    input = specialReplace(input, 'DD', prependZero(currentDate));
2584    input = specialReplace(input, 'D', currentDate);
2585
2586    // Years
2587    input = specialReplace(input, 'YYYY', currentYear);
2588    input = specialReplace(input, 'YY', currentYear.toString().substr(2));
2589    input = specialReplace(input, 'Y', currentYear);
2590
2591    // Hours
2592    input = specialReplace(input, 'HH', prependZero(transformAmPm(currentHours, currentAmPm)));
2593    input = specialReplace(input, 'hh', prependZero(currentHours));
2594    input = specialReplace(input, 'H', transformAmPm(currentHours, currentAmPm));
2595    input = specialReplace(input, 'h', currentHours);
2596
2597    // Minutes
2598    input = specialReplace(input, 'mm', prependZero(currentMinutes));
2599    input = specialReplace(input, 'm', getMinutes());
2600
2601    // Am Pm
2602    input = specialReplace(input, 'a', currentAmPm ? 'am' : 'pm');
2603    input = specialReplace(input, 'A', currentAmPm ? 'AM' : 'PM');
2604
2605    // Months
2606    // TODO: Make a special case for month with M (March, May)
2607    input = specialReplace(input, 'MMM', config.monthsNames[currentMonth - 1]);
2608    input = specialReplace(input, 'MM', prependZero(currentMonth));
2609    input = specialReplace(input, 'M', currentMonth);
2610
2611    input = specialReplace(input, 'ZZ', (currentTimezone > 0 ? '+' : '-') + prependZero(Math.abs(currentTimezone)) + ':00');
2612    input = specialReplace(input, 'Z', (currentTimezone > 0 ? '+' : '-') + Math.abs(currentTimezone) + ':00');
2613
2614    input = input.split('#%#').join('');
2615
2616    function specialReplace (input, selector, value) {
2617      var specialDelimiter = '#%#';
2618      var regex = new RegExp(selector + '(?!' + specialDelimiter + ')', 'g');
2619      input = input.replace(regex, value + specialDelimiter);
2620      return input;
2621    }
2622
2623    function prependZero (value) {
2624      return value <= 9 ? ('0' + value) : value;
2625    }
2626
2627    function transformAmPm (hours, ampm) {
2628      if (!config.disableAmPm) {
2629        if (hours === 12) {
2630          return ampm ? 0 : 12;
2631        }
2632        return ampm ? hours : hours + 12;
2633      } else {
2634        return hours;
2635      }
2636    }
2637
2638    return input;
2639  };
2640  
2641//!!!!! Add Start
2642  // ゼロパディング
2643  var paddingZero = function (value, valueMaxLength) {
2644    if (!config.zeroPadding || !valueMaxLength || valueMaxLength <= 0)
2645      return value;
2646    
2647    return (Array(valueMaxLength+1).join('0') + value).slice(-1 * valueMaxLength);
2648  }
2649//!!!!! Add End
2650
2651  /*****************************************************************************
2652   * PUBLIC API
2653   *
2654   * Events
2655   ****************************************************************************/
2656
2657  var onChange = function (target, callback) {
2658    events.onChange[target].push(callback);
2659  };
2660
2661  var beforeChange = function (target, callback) {
2662    events.beforeChange[target].push(callback);
2663  };
2664
2665  var afterChange = function (target, callback) {
2666    events.afterChange[target].push(callback);
2667  };
2668
2669  function detectBrowser () {
2670    var browser = {
2671      isChrome: false,
2672      isSafari: false,
2673      isFirefox: false
2674    };
2675
2676    if (navigator.userAgent.search('Safari') >= 0 && navigator.userAgent.search('Chrome') < 0) {
2677      browser.isSafari = true;
2678    }
2679
2680    return browser;
2681  }
2682
2683  /**
2684   * Public API here
2685   */
2686
2687  this.init = init;
2688  this.setConfig = setConfig;
2689  this.destroy = destroy;
2690
2691  // Closing these interfaces, use format, instead of them
2692  // this.getHours = getHours;
2693  // this.getMinutes = getMinutes;
2694  // this.getIsAm = getIsAm;
2695  // this.getIsPm = getIsPm;
2696  this.getTime = getTime;
2697  // this.getDate = getDate;
2698  // this.getMonth = getMonth;
2699  // this.getYear = getYear;
2700  this.getFullTime = getFullTime;
2701  this.getTimestamp = getTimestamp;
2702
2703  this.setHours = setHours;
2704  this.setMinutes = setMinutes;
2705  this.setAmPm = setAmPm;
2706  this.setDate = setDate;
2707  this.setMonth = setMonth;
2708  this.setYear = setYear;
2709  this.setTimestamp = setTimestamp;
2710//!!!!! Add Start
2711  this.focus = focus;
2712//!!!!! Add End
2713
2714  this.values = values;
2715
2716  // Here is the set with the default Date getters
2717  this.toDateString = toDateString;
2718  this.toGMTString = toGMTString;
2719  this.toISOString = toISOString;
2720  this.toLocaleDateString = toLocaleDateString;
2721  this.toLocaleString = toLocaleString;
2722  this.toLocaleTimeString = toLocaleTimeString;
2723  this.toString = toString;
2724  this.toTimeString = toTimeString;
2725  this.toUTCString = toUTCString;
2726  this.format = format;
2727
2728  // Here are some events which the api provides
2729  this.onChange = onChange;
2730  this.beforeChange = beforeChange;
2731  this.afterChange = afterChange;
2732
2733  // Lets init all
2734  init(inputConfig);
2735}

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.