PageSourceSearch

https://www.chesco.org/Assets/Scripts/DateTimePicker/cp.datetimepicker.js

js chesco.org collected 2026-09-24 09:09:51 UTC 30,447 bytes, 667 lines download raw bytes

1/**
2    cp.datepicker.js provides an JavaScript Date picker control.
3 */
4var cp = cp || {};
5
6cp.datetimepicker = (function ($) {
7    var keyCodes = {
8        tab: 9,
9        downArrow: 40
10    };
11
12    // These are the publicly-accessible methods
13    if (!$) { return; }
14    return {
15        createTimePicker: createTimePicker,
16        createDatePicker: createDatePicker,
17    };
18
19
20    // getOptionsFromHtmlAttributes parses through any attribute in the user-specific HTML date or time picker and
21    // overwrites the values in "options" with values corresponding to "data-cp-datetimepicker-{optionName}".  The
22    // "optionName" portion of the attribute should correspond to a property of the pickadate or pickatime
23    // options element.
24    function getOptionsFromHtmlAttributes($inputElement, originalOptions) {
25        $($inputElement[0].attributes).each(function () {
26            if (this.name.match('^data-cp-datetimepicker-')) {
27                var optionName = this.name.replace('data-cp-datetimepicker-', '');
28                var originalValue = originalOptions[optionName];
29                if (!originalValue) {
30                    // We only want to set the option value if it was not already set in the JavaScript options.
31                    // That is, the JavaScript options should always win over the HTML5 options.
32
33                    var optionVal = this.value;
34                    if (parseInt(optionVal)) {
35                        optionVal = parseInt(optionVal);
36                    }
37
38                    originalOptions[optionName] = optionVal;
39                }
40            }
41        });
42        return originalOptions;
43    }
44
45    // createTimePicker creates a new time picker object out of the DOM object specified by timeTextboxSelector.
46    // The timeTextboxSelector object must be an HTML INPUT element.
47    function createTimePicker(timeTextboxSelector, options) {
48
49        // The actualy Input Time component will be a hidden field.  The DOM object in the source HTML
50        // will be the editable text field for the user.
51
52        options = options || {};
53
54        var $inputTextBox = $(timeTextboxSelector);
55
56        if (!($inputTextBox) || $inputTextBox.length === 0) {
57            // We got passed a bad selector
58            console.log('ERR: cp.datetimepicker :: Could not find element: ' + timeTextboxSelector);
59            return;
60        }
61
62        // Set any options that were specified directly from within the HTML tag.
63        options = getOptionsFromHtmlAttributes($inputTextBox, options);
64
65        //Wrap fieldSetSelector inside div if wrapInsideDiv is true
66        var fieldSetSelector = '<fieldset class="fieldset__datetimepicker__wrapper">';
67
68        if (options.wrapInsideDiv) {
69            fieldSetSelector = '<div class="t-widget t-timepicker">' + fieldSetSelector + '</div>';
70        }
71
72        $fieldset = $(fieldSetSelector);
73        $inputTextBox.wrap($fieldset);
74
75        var $hiddenTimeInput = $('<input type="text" class="cp_input_datetime" tabindex="-1"/>');
76        $hiddenTimeInput.attr('data-cp-time-textbox-selector', timeTextboxSelector);
77
78        $hiddenTimeInput.attr('aria-hidden', true);
79
80        $hiddenTimeInput.insertAfter($inputTextBox);
81
82        // We need to force "editable" in the options, otherwise things start to break.
83        options.editable = true;
84        $hiddenTimeInput.pickatime(options);
85
86        var pickerObject = $hiddenTimeInput.pickatime('picker');	// reference to the pickatime object
87        $inputTextBox.attr("role", "combobox");
88        $inputTextBox.attr("aria-haspopup", "listbox");
89        $inputTextBox.attr("aria-expanded", "false");
90        $inputTextBox.attr("aria-controls", pickerObject.$root.attr("id"));
91
92        // Bugfix - https://civicplus.tpondemand.com/entity/182182-211-agenda-center-module-main-page
93        // Move aria-owns from the hidden <input> to the interactive one
94        $inputTextBox.attr("aria-owns", pickerObject.$node.attr("aria-owns"));
95        pickerObject.$node.removeAttr("aria-owns");
96
97        $inputTextBox.on({
98            change: function () {
99                var inputTime = this.value;
100                pickerObject.set('customSelect', insertColonIfOverFourChars(inputTime), options);
101            },
102            keydown: function (e) {
103                if (e.keyCode === keyCodes.downArrow) {
104                    e.preventDefault();
105                    pickerObject.open(true);
106                }
107            },
108            focus: function (e) {
109                if (e.relatedTarget !== pickerObject.$holder[0]) {
110                    // If the previously focused control was the picker object, don't open it again after closing it
111                    pickerObject.open(false);
112                }
113                // We have to set the tab-index of the "clear" button, so tabbing through fields works properly.
114                $('.picker__button--clear').attr('tabindex', -1);
115            },
116            blur: function (e) {
117                // If user shifts focus from the input element to its datepicker, then we do not want to close the datepicker.
118                if (!e.relatedTarget?.closest(".picker")) {
119                    pickerObject.close(true);
120                }
121            }
122        });
123
124        pickerObject.on({
125            open: function () {
126                $inputTextBox.attr("aria-expanded", "true");
127            },
128            close: function () {
129                $inputTextBox.attr("aria-expanded", "false");
130                $inputTextBox.focus();
131            },
132            set: function (e) {
133                var inputVal = $inputTextBox.val();
134                var selectedVal = autoTimeFormat(inputVal);
135                if (typeof e.clear === "object" || (typeof e.select !== "undefined" && (!isNaN(e.select) || !isNaN(e.select.pick))) || (e.customSelect && !selectedVal.match(/^([1-9]|1[012])(:[0-5]\d) [APap][mM]$/))) {
136                    selectedVal = this.get('value') === '' ? '12:00 AM' : this.get('value');
137                }
138                $inputTextBox.val(selectedVal);
139                $inputTextBox.attr('value', selectedVal);
140                // closing the selection area if the user had picked a time.
141                if (!e.relatedTarget?.closest(".picker")) {
142                    pickerObject.close(true);
143                    $inputTextBox.attr("aria-expanded", "false");
144                }
145            }
146        });
147
148        // Priming initialization if there was a value specified for the input
149        if ($inputTextBox.val() !== '') {
150            pickerObject.set('select', $inputTextBox.val(), options);
151        }
152
153        $(pickerObject.$root).find('.picker__list').attr('aria-label', 'Time List');
154
155        return pickerObject;
156    }
157
158    // createDatePicker creates a new date picker object using the element specified by "dateTextboxSelector".
159    // The dateTextboxSelector object must be an HTML INPUT element.
160    function createDatePicker(dateTextboxSelector, options) {
161        // The actualy Input Date component will be a hidden field.  The DOM object in the source HTML
162        // will be the editable text field for the user.
163        options = options || {};
164
165        var $inputTextBox = $(dateTextboxSelector);
166
167        if (!($inputTextBox) || $inputTextBox.length === 0) {
168            // We got passed a bad selector
169            console.log('ERR: cp.datetimepicker :: Could not find element: ' + dateTextboxSelector);
170            return;
171        }
172
173        // Set any options that were specified directly from within the HTML tag.
174        options = getOptionsFromHtmlAttributes($inputTextBox, options);
175        var dateAsString = $inputTextBox.val();
176        if (options.format == 'dd/mm/yyyy' && dateAsString.length > 0) {
177            var splitDate = autoCompleteDate(dateAsString, options.format).split('/');
178            $inputTextBox.val(splitDate[1] + '/' + splitDate[0] + '/' + splitDate[2]);
179        }
180
181        if (options.useNativeControls) {
182            $inputTextBox.prop('type', 'date');
183            return;
184        }
185
186        var $hiddenDateInput = $('<input type="text" class="cp_input_datetime" tabindex="-1"/>');
187        $hiddenDateInput.attr('data-cp-date-textbox-selector', dateTextboxSelector);
188
189        $hiddenDateInput.attr('aria-hidden', true);
190        var fieldsetSelector = '<fieldset class="fieldset__datetimepicker__wrapper"></fieldset>';
191        if (options.wrapInsideDiv)
192            fieldsetSelector = '<div class="t-widget t-datepicker">' + fieldsetSelector + '</div>';
193
194        $fieldset = $(fieldsetSelector);
195        $fieldset.attr("data-cp-datetimepicker-selector", dateTextboxSelector);
196        $inputTextBox.wrap($fieldset);
197        $hiddenDateInput.insertAfter($inputTextBox);
198
199        // We have to force the editable option, otherwise things start to break.
200        options.editable = true;
201
202        $hiddenDateInput.pickadate(options);
203
204        var pickerObject = $hiddenDateInput.pickadate('picker');	// reference to the pickadate object
205        $inputTextBox.attr("role", "combobox");
206        $inputTextBox.attr("aria-haspopup", "dialog");
207        $inputTextBox.attr("aria-expanded", "false");
208        $inputTextBox.attr("aria-controls", pickerObject.$root.attr("id"));
209
210        // Bugfix - https://civicplus.tpondemand.com/entity/182182-2
21011-agenda-center-module-main-page
211        // Move aria-owns from the hidden <input> to the interactive one
212        $inputTextBox.attr("aria-owns", pickerObject.$node.attr("aria-owns"));
213        pickerObject.$node.removeAttr("aria-owns");
214
215        var allowDatePickerFocus = false;
216        var isTabbingAwayFromDatePicker = false;
217
218        // Keep only the visible picker action controls in the keyboard path; date cells are tracked through aria-activedescendant.
219        function getPickerControls($holder) {
220            return $holder.find('.picker__nav--prev, .picker__nav--next, .picker__button--today, .picker__button--clear, .picker__button--close').filter(function () {
221                return !$(this).hasClass('picker__nav--disabled') && $(this).attr('aria-hidden') !== 'true';
222            });
223        }
224
225        function enablePickerControlTabbing() {
226            getPickerControls(pickerObject.$holder).attr('tabindex', '0');
227        }
228
229        function restorePickerControlFocus(selector) {
230            setTimeout(function () {
231                updateActiveDescendant();
232                enablePickerControlTabbing();
233                pickerObject.$holder.find(selector).first().focus();
234            }, 0);
235        }
236
237        function getNextTabbableElement() {
238            const $focusableElements = $('a[href], area[href], input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex], [contenteditable=true]').filter(function () {
239                const $element = $(this);
240                const tabindex = $element.attr('tabindex');
241
242                return $element.is(':visible') && tabindex !== '-1' && $element.attr('aria-hidden') !== 'true' && this !== pickerObject.$holder[0] && !$.contains(pickerObject.$holder[0], this);
243            });
244
245            const currentInputIndex = $focusableElements.index($inputTextBox);
246            if (currentInputIndex !== -1 && currentInputIndex < $focusableElements.length - 1) {
247                return $focusableElements.eq(currentInputIndex + 1);
248            }
249
250            return $();
251        }
252
253        // Add handler to make sure datepicker is visible when shown
254        pickerObject && pickerObject.on('open', function () {
255            $inputTextBox.attr("aria-expanded", "true");
256            $inputTextBox.attr('aria-live', 'off');
257            $inputTextBox.attr('aria-atomic', 'false');
258            $inputTextBox.attr('role', 'textbox');
259
260            const selected = pickerObject.get('select');
261            if (!selected) {
262                pickerObject.set('highlight', new Date(), { muted: true });
263            }
264
265            const $holder = pickerObject.$holder;
266            const inputId = $inputTextBox.attr('id');
267
268            const inputLabel = ($('label[for="' + inputId + '"]').text() || '').trim();
269
270            const labelText = inputLabel || $inputTextBox.attr('aria-label') || $inputTextBox.attr('title') || 'Date picker calendar';
271
272            //Use the application role so screen readers pass arrow keys to the custom keyboard interaction.
273            $holder.attr({
274                'tabindex': allowDatePickerFocus ? '0' : '-1',
275                'role': 'application',
276                'aria-label': labelText
277            });
278
279            $holder.find('.picker__nav--prev, .picker__nav--next, .picker__button--today, .picker__button--clear, .picker__button--close').attr('tabindex', '-1');
280
281            //Only ONE focusable element
282            $holder.find('.picker__day').attr('tabindex', '-1');
283            $holder.find('.picker__day').attr('aria-hidden', 'true');
284
285            //Set aria-selected
286            $holder.find('.picker__day').each(function () {
287                const $day = $(this);
288                $day.attr('aria-selected', $day.hasClass('picker__day--selected') ? 'true' : 'false');
289            });
290
291            //Set active descendant
292            setTimeout(updateActiveDescendant, 0);
293
294            $holder.off('keydown.grid').on('keydown.grid', function (e) {
295                if (e.keyCode === keyCodes.tab) {
296                    const $controls = getPickerControls($holder);
297                    const currentIndex = $controls.index(e.target);
298
299                    if (currentIndex !== -1) {
300                        if (e.shiftKey && currentIndex === 0) {
301                            e.preventDefault();
302                            $holder.focus();
303                            return;
304                        }
305
306                        if (!e.shiftKey && currentIndex < $controls.length - 1) {
307                            e.preventDefault();
308                            $controls.eq(currentIndex + 1).focus();
309                        }
310
311                        if (!e.shiftKey && currentIndex === $controls.length - 1) {
312                            e.preventDefault();
313                            // Capture the next real page control before closing because picker DOM removal can disrupt native Tab focus.
314                            const $nextTabbableElement = getNextTabbableElement();
315                            isTabbingAwayFromDatePicker = true;
316                            allowDatePickerFocus = false;
317                            setTimeout(function () {
318                                pickerObject.close(true);
319                                setTimeout(function () {
320                                    $nextTabbableElement.focus();
321                                }, 0);
322                            }, 0);
323                        }
324
325                        return;
326                    }
327
328                    if ($holder.is(e.target) || $holder.has(e.target).length) {
329                        e.preventDefault();
330                        enablePickerControlTabbing();
331                        (e.shiftKey ? $controls.last() : $controls.first()).focus();
332                    }
333
334                    return;
335                }
336
337                if ($holder.is(e.target) && e.keyCode === 32) {
338                    e.preventDefault();
339                    $holder.find('.picker__day--highlighted:not(.picker__day--disabled)').click();
340                    return;
341                }
342
343                const $target = $(e.target);
344                if ($target.is('.picker__nav--prev, .picker__nav--next') && (e.keyCode === keyCodes.downArrow || e.which === keyCodes.downArrow || e.key === 'ArrowDown' || e.key === 'Down')) {
345                    e.preventDefault();
346                    $holder.focus();
347                    return;
348                }
349
350                if ($target.is('.picker__nav--prev, .picker__nav--next') && e.keyCode === 32) {
351                    e.preventDefault();
352                    $target.click();
353                }
354
355                setTimeout(() => {
356                    updateActiveDescendant();
357
358                    $holder.find('.picker__day').attr('aria-selected', 'false');
359
360                    const $selected = $holder.find('.picker__day--selected');
361                    if ($selected.length) {
362                        $selected.attr('aria-selected', 'true');
363                    }
364                }, 0);
365            });
366
367            $holder.off('click.grid', '.picker__nav--prev, .picker__nav--next').on('click.grid', '.picker__nav--prev, .picker__nav--next', function () {
368                const $target = $(this);
369                if (!$target.hasClass('picker__nav--disabled')) {
370                    restorePickerControlFocus($target.hasClass('picker__nav--prev') ? '.picker__nav--prev' : '.picker__nav--next');
371                }
372            });
373
374            // Add a slight delay to ensure that the flyout has been added to the dom and the flyoutHeight is nonzero
375            setTimeout(function () {
376                // Get the position of the datepicker flyout relative to the top of the document
377                var flyoutTop = pickerObject.$holder[0].getBoundingClientRect().top;
378
379                // Get the height of the datepicker flyout
380                var flyoutHeight = pickerObject.$holder[0].offsetHeight;
381
382                // Get the height of the viewport
383                var viewportHeight = window.innerHeight;
384
385                // Calculate the amount of scrolling needed to make the entire datepicker flyout visible
386                var scrollAmount = flyoutTop + flyoutHeight - viewportHeight;
387
388                // If the datepicker flyout is not fully visible, scroll the viewport down to make it visible
389                if (scrollAmount > 0) {
390                    window.scrollTo(0, scrollAmount + window.scrollY);
391                }
392            }, 50);
393        });
394
395        function focusInput() {
396            $inputTextBox.off("focus", openPicker);
397            $inputTextBox.focus();
398            setTimeout(function () {
399                $inputTextBox.on("focus", openPicker);
400            }, 0);
401        }
402
403        pickerObject.on('close', function () {
404            //Trigger the change event on the picker object's element.
405            window.parent.$(dateTextboxSelector).change();
406            $inputTextBox.attr("aria-expanded", "false");
407            pickerObject.$holder.attr('tabindex', '-1');
408            pickerObject.$holder.find('.picker__nav--prev, .picker__nav--next, .picker__button--today, .picker__button--clear, .picker__button--close').attr('tabindex', '-1');
409            if (!isTabbingAwayFromDatePicker) {
410                focusInput();
411            }
412            isTabbingAwayFromDatePicker = false;
413            allowDatePickerFocus = false;
414        });
415
416        // setDate is a helper function that should only be called from within this module.
417        function setDate(dateAsString, placeholder) {
418            if (dateAsString === '') {
419                pickerObject.set('clear', null, null);
420            } else {
421                if (pickerObject.component.settings.format == 'dd/mm/yyyy') {
422                    var splitDate = autoCompleteDate(dateAsString, pickerObject.component.settings.format).split('/');
423                    var date = splitDate[1] + '/' + splitDate[0] + '/' + splitDate[2];
424                    var epochDate = Date.parse(date);
425                } else {
426                    var epochDate = Date.parse(autoCompleteDate(dateAsString, pickerObject.component.settings.format));
427                }
428                if (!epochDate) {
429                    return;
430                } else {
431                    var parsedDate = new Date(epochDate);
432                    pickerObject.set('select',
433                        [parsedDate.getFullYear(), parsedDate.getMonth(), parsedDate.getDate()]);
434                }
435            }
436        }
437
438        function updateActiveDescendant() {
439            const $holder = pickerObject.$holder;
440            const $active = $holder.find('.picker__day--highlighted');
441            $holder.find('.picker__day').attr('aria-hidden', 'true');
442
443            if ($active.length) {
444                $active.attr('aria-hidden', 'false');
445                $holder.attr('aria-activedescendant', $active.attr('id'));
446
447                const dateValue = $active.data('pick');
448                if (dateValue) {
449                    const date = new Date(dateValue);
450
451                    const formatted = date.toLocaleDateString('en-US', {
452                        month: 'long',
453                        day: 'numeric',
454                        year: 'numeric'
455                    });
456
457                    // override for active cell
458                    $active.attr('aria-label', formatted);
459                }
460            }
461        }
462
463        var intervalID;
464
465        //Moves the date picker further up the DOM so it isn't overlapped https://civicplus.tpondemand.com/entity/22312
466        function adjustDTPicker() {
467            if (intervalID === 0) {
468                return;
469            }
470
471            var elemPicker = $('.picker--opened')[0];
472            if (elemPicker) {
473                $(elemPicker).appendTo('#cpDatePickerWrapper');
474                elemPicker.style.fontSize = 'inherit';
475            }
476
477            clearInterval(intervalID);
478
479            $('.cpDatePickerElevate').each(function () {
480                var $dateInput = $(this);
481                if ($dateInput.is(':focus')) {
482                    adjustFlyoutPosition($dateInput, $('#cpDatePickerWrapper'));
483                }
484            });
485
486            intervalID = 0;
487        }
488
489        if ($('#cpDatePickerWrapper').length > 0) {
490            $(window).resize(function () {
491                $('.cpDatePickerElevate').each(function () {
492                    var $dateInput = $(this);
493                    if ($dateInput.is(':focus')) {
494                        adjustFlyoutPosition($dateInput, $('#cpDatePickerWrapper'));
495                    }
496                });
497            });
498        }
499
500        function openPicker() {
501            allowDatePickerFocus = false;
502            // We have to set the tab-index of the "today", "close", and "clear" buttons, so tabbing through fields works properly.
503            $('.picker__button--close').attr('tabindex', -1);
504            $('.picker__button--today').attr('tabindex', -1);
505            $('.picker__button--clear').attr('tabindex', -1);
506            // pickerObject.$holder.find('[tabindex="-1"]').attr('tabindex', 0);
507            pickerObject.open(false);
508            if ($('#cpDatePickerWrapper').length > 0)
509                intervalID = setInterval(adjustDTPicker, 50);
510        }
511
512        $inputTextBox.on({
513            change: function () {
514                setDate(this.value);
515            },
516            focus: openPicker,
517            click: openPicker,
518            keydown: function (e) {
519                if (e.keyCode === keyCodes.tab) {
520                    isTabbingAwayFromDatePicker = true;
521                    pickerObject.$holder.attr('tabindex', -1);
522                    pickerObject.$holder.find('[tabindex="0"]').attr('tabindex', -1);
523                    pickerObject.close();
524                    isTabbingAwayFromDatePicker = false;
525                }
526                if (e.keyCode === keyCodes.downArrow) {
527                    e.preventDefault();
528                    allowDatePickerFocus = true;
529                    pickerObject.open();
530                    setTimeout(function () {
531                        enablePickerControlTabbing();
532                        pickerObject.$holder.attr('tabindex', '0').focus();
533                    }, 0);
534                }
535            },
536            blur: function (e) {
537                // If user shifts focus from the input element to its datepicker, then we do not want to close the datepicker.
538                if (!allowDatePickerFocus || !e.relatedTarget?.closest(".picker")) {
539                    pickerObject.close(true);
540                    $inputTextBox.attr("aria-expanded", "false");
541                }
542            },
543        });
544
545        pickerObject.on('set', function () {
546            $inputTextBox.val(this.get('value'));
547            $inputTextBox.attr('value', this.get('value'));
548
549            setTimeout(updateActiveDescendant, 0);
550        });
551
552        // Priming initialization if there was a value specified for the input
553        if ($inputTextBox.val() !== '') {
554            setDate($inputTextBox.val());
555        }
556
557
558        return pickerObject;
559    }
560
561    function insertColonIfOverFourChars(inputString) {
562        if (inputString != null && inputString.length > 3 && inputString.indexOf(":") < 0) {
563            inputString = inputString.slice(0, 2) + ":" + inputString.slice(2, inputString.length);
564        }
565        return inputString;
566    }
567
568    function autoCompleteDate(dateAsString, formatString) {
569        try {
570            var fdts = null;
571            var currentDate = new Date();
572
573            //guard clauses
574            if (formatString == null || formatString.length === 0) {
575                formatString === "mm/dd/yyyy";
576            }
577            if ((dateAsString == null || dateAsString.length == 0 || dateAsString.indexOf(".") != -1) && formatString.toLowerCase == "dd/mm/yyyy") {
578                return ('0' + currentDate.getDate()).slice(-2) + '/' + ('0' + (currentDate.getMonth() + 1)).slice(-2) + '/' + currentDate.getFullYear();
579            } else if (dateAsString == null || dateAsString.length == 0 || dateAsString.indexOf(".") != -1) {
580                return ('0' + (currentDate.getMonth() + 1)).slice(-2) + '/' + ('0' + currentDate.getDate()).slice(-2) + '/' + currentDate.getFullYear();
581            }
582
583            fdts = dateAsString.split("/");
584
585            if (fdts != null) {
586                //switch mm/dd/yyyy to be dd/mm/yyyy for logic further down
587                if (formatString.toLowerCase() !== "dd/mm/yyyy") {
588                    var day = fdts[1];
589                    var month = fdts[0];
590                    fdts[0] = day;
591                    fdts[1] = month;
592                }
593
594                if (fdts[0] == null || fdts[0] === '0' || fdts[0].length < 1 || fdts[0].length > 2) {
595                    fdts[0] = currentDate.getDate();
596                }
597                if (fdts[1] == null || fdts[1] === '0' || fdts[1].length < 1 || fdts[1].length > 2) {
598                    fdts[1] = currentDate.getMonth() + 1;
599                }
600                if (fdts[2] == null || (fdts[2].length !== 2 && fdts[2].length !== 4)) {
601                    //For last year's date it also adds time at the end of date so extracting year
602                    fdts[2] = !isNaN(fdts[2].substr(0, 4)) ? fdts[2].substr(0, 4) : currentDate.getFullYear();
603                } else if (fdts[2].length === 2) {
604                    var yr = fdts[2];
605                    var crDate = new Date();
606                    var crCtry = crDate.getFullYear();
607                    var pstCnry = crCtry - 100;
608                    crCtry = crCtry + ' ';
609                    pstCnry = pstCnry + ' ';
610                    crCtry = crCtry.substr(0, 2);
611                    pstCnry = pstCnry.substr(0, 2);
612                    if (yr >= 32)
613                        yr = pstCnry + yr;
614                    else
615                        yr = crCtry + yr;
616                    fdts[2] = yr;
617                }
618            }
619            if (formatString.toLowerCase() === "dd/mm/yyyy") {
620                dateAsString = ('0' + fdts[0]).slice(-2) + '/' + ('0' + fdts[1]).slice(-2) + '/' + fdts[2];
621            } else {
622                dateAsString = ('0' + fdts[1]).slice(-2) + '/' + ('0' + fdts[0]).slice(-2) + '/' + fdts[2];
623            }
624            return dateAsString;
625        } catch (e) {
626            return "";
627        }
628    }
629
630    function autoTimeFormat(inputString) {
631
632        const regex1 = /^(0?[1-9]|1[0-2]) ?([ap]m)$/i; //eg: 5AM -> 5:00 AM
633        const regex2 = /^(\d{1,2})(\d{2}) ?([ap]m)$/i; //eg: 500AM -> 5:00 AM
634        const regex3 = /^(\d{1,2})(?::(\d{2}))?\s*([ap]m)?$/i; //eg: 05:00 am or 5:00 am -> 5:00 AM
635
636        if (regex1.test(inputString)) {
637            return inputString.replace(regex1, (match, hour, period) => {
638                const hourNum = parseInt(hour);
639                const formattedHour = hourNum === 12 ? 12 : hourNum % 12; // Convert to 12-hour format
640                const formattedMinute = "00"; // Add 00 as minutes
641                const formattedPeriod = period.toUpperCase();
641 // Convert period to uppercase
642                return `${formattedHour}:${formattedMinute} ${formattedPeriod}`;
643            });
644        }
645        else if (regex2.test(inputString)) {
646            return inputString.replace(regex2, (match, hour, minute, period) => {
647                const hourNum = parseInt(hour);
648                const formattedHour = hourNum === 12 ? 12 : hourNum % 12; // Convert to 12-hour format
649                const formattedMinute = minute.padStart(2, "0"); // Pad minute with zero if necessary
650                const formattedPeriod = period.toUpperCase(); // Convert period to uppercase
651                return `${formattedHour}:${formattedMinute} ${formattedPeriod}`;
652            });
653        }
654        else if (regex3.test(inputString)) {
655            return inputString.replace(regex3, (match, hour, minute, period) => {
656                const hourNum = parseInt(hour);
657                const formattedHour = hourNum === 12 ? 12 : hourNum % 12; // Convert to 12-hour format
658                const formattedMinute = minute ? minute : "00"; // Set minute to "00" if not provided
659                const formattedPeriod = period ? period.toUpperCase() : ""; // Convert period to uppercase if provided
660                return `${formattedHour}:${formattedMinute} ${formattedPeriod}`;
661            });
662        }
663        else {
664            return inputString;
665        }
666    }
667})(jQuery);

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.