PageSourceSearch

https://public.hiscox.fr/Scripts/webinsurepublic-1.js?version=PL2Q8v6-sEK4sW6PEZwkZA

js hiscox.fr collected 2026-09-26 00:34:46 UTC 173,269 bytes, 4,461 lines download raw bytes

1
2var Instanda = Instanda || {};
3
4// Instanda Common Constructor
5Instanda.Common = function (options) {
6
7    "use strict";
8
9    options = options || {};
10};
11
12Instanda.Common.prototype = function () {
13
14    "use strict";
15
16    // Private members
17    var
18        abortEvent = function (event) {
19
20            if (event) {
21
22                if (event.stopPropagation) {
23                    event.stopPropagation();
24                }
25
26                if (event.preventDefault) {
27                    event.preventDefault();
28                } else {
29                    event.returnValue = false;
30                }
31            }
32        },
33        keepSessionActive = function (encryptedQuoteRef) {
34            var url = 'SessionKeepActive?timeStamp=' + escape(new Date());
35
36            if (encryptedQuoteRef) {
37                url = url + '&encryptedQuoteRef=' + escape(encryptedQuoteRef);
38            }
39
40            var img = new Image(1, 1);
41            img.src = url;
42        },
43        KeepLockOnPolicy = function (quoteref) {
44            var result = false;
45            var currentUrl = encodeURIComponent(window.location.pathname + window.location.search);
46
47            $.ajax({
48                type: "GET",
49                async: false,
50                url: '/Public/KeepLockOnPolicy?quoteref=' + escape(quoteref) + '&currentUrl=' + currentUrl,
51                success: function (response) {
52                    // use the named variable 'response' consistently
53                    if (typeof response.success !== 'undefined' && response.success) {
54                        if (response.redirectUrl) {
55                            if (response.bannerMessage) {
56                                toastr.clear();
57                                toastr.info(response.bannerMessage);
58                            }
59
60                            setTimeout(function () {window.location.href = response.redirectUrl}, 100);
61                        }
62
63                        result = true;
64                    }
65                },
66                complete: function (jqXHR, textStatus) {
67                    if (typeof jqXHR.responseJSON !== "undefined" && typeof jqXHR.responseJSON.notExtendSession === "undefined") {
68                        jqXHR.responseJSON.notExtendSession = true;
69                    }
70                }
71            });
72
73            return result;
74        },
75        KeepLockOnPolicyPromise = function (quoteref) {
76            var currentUrl = encodeURIComponent(window.location.pathname + window.location.search);
77            return $.ajax({
78                type: "GET",
79                url: '/Public/KeepLockOnPolicy?quoteref=' + encodeURIComponent(quoteref) + '&currentUrl=' + currentUrl,
80                success: function (response) {
81                    if (response && response.success) {
82                        if (response.redirectUrl) {
83                            if (response.bannerMessage) {
84                                toastr.clear();
85                                toastr.info(response.bannerMessage);
86                            }
87
88                            setTimeout(function () {window.location.href = response.redirectUrl}, 100);
89                        }
90                    }
91                }
92            });
93        };
94
95    // Public members
96    return {
97        abortEvent: abortEvent,
98        keepSessionActive: keepSessionActive,
99        KeepLockOnPolicy: KeepLockOnPolicy,
100        KeepLockOnPolicyPromise: KeepLockOnPolicyPromise
101    };
102}();
103
104
105// Instanda AioiEVB Constructor
106Instanda.AioiEVB = function (options) {
107
108    "use strict";
109
110    options = options || {};
111};
112
113Instanda.AioiEVB.prototype = function () {
114
115    "use strict";
116
117    // Private members
118    const controllerName = "PublicAioiEvb";
119
120    let
121        configureDocumentFields = function (documentId) {
122
123            if (documentId &&
124                documentId !== undefined &&
125                documentId !== null &&
126                documentId.length !== 0) {
127
128                $(".aioi-evb-dialog:first .modal-body").show();
129
130            } else {
131
132                $(".aioi-evb-dialog:first .modal-body").hide();
133            }
134        },
135        configureDocumentRequestButton = function (properties) {
136
137            if (properties &&
138                properties.documentId &&
139                properties.documentId !== undefined &&
140                properties.documentId !== null &&
141                properties.documentId.length !== 0) {
142
143                $(".aioi-evb-dialog-document-request-button").text("Request New Document");
144
145            } else {
146
147                $(".aioi-evb-dialog-document-request-button").text("Request Document");
148            }
149        },
150        downloadDocument = function (properties) {
151
152            if (properties.quoteRef !== null &&
153                Number.isInteger(properties.packageId) &&
154                properties.packageId > 0 &&
155                properties.documentId !== null) {
156
157                window.location = "/" + controllerName + "/DownloadAioiEvbDocument?" + $.param(properties);
158            }
159        },
160        resetDialog = function () {
161
162            setEvbNumberField(null);
163            setDocumentId(null);
164            configureDocumentFields(null);
165            setValidationErrors(null, null);
166        },
167        setDocumentId = function (documentId) {
168
169            let $field = $(".aioi-evb-dialog:first .aioi-evb-dialog-document-download .aioi-evb-dialog-document-download-l
169ink:first");
170
171            if ($field.length !== 0) {
172
173                if (documentId &&
174                    documentId !== undefined &&
175                    documentId !== null &&
176                    documentId.length !== 0) {
177
178                    $field
179                        .data("documentId", documentId)
180                        .parent()
181                        .show()
182                        ;
183
184                } else {
185
186                    $field
187                        .data("documentId", null)
188                        .parent()
189                        .hide()
190                        ;
191                }
192            }
193        },
194        setEvbNumberField = function (evbNumber) {
195
196            let $field = $(".aioi-evb-dialog:first .aioi-evb-dialog-document-number input.aioi-evb-dialog-document-number-value:first");
197
198            if ($field.length !== 0) {
199
200                if (evbNumber &&
201                    evbNumber !== undefined &&
202                    evbNumber !== null &&
203                    evbNumber.length !== 0) {
204
205                    $field
206                        .val(evbNumber)
207                        .parent()
208                        .show()
209                        ;
210
211                } else {
212
213                    $field
214                        .val(null)
215                        .parent()
216                        .hide()
217                        ;
218                }
219            }
220        },
221        setValidationErrors = function (errorMessage, validationErrors) {
222
223            let $field = $(".aioi-evb-dialog:first .aioi-evb-dialog-errors-validation");
224
225            if ($field.length !== 0) {
226
227                if (errorMessage === null ||
228                    errorMessage === undefined ||
229                    errorMessage.length === 0) {
230
231                    $field
232                        .hide()
233                        .html(null)
234                        ;
235
236                } else {
237
238                    let validationErrorsHTML = errorMessage;
239
240                    if (validationErrors &&
241                        validationErrors !== undefined &&
242                        validationErrors !== null &&
243                        validationErrors.length !== 0) {
244
245                        validationErrorsHTML += "<br /><br />";
246
247                        $.each(validationErrors, function (_index, error) {
248                            validationErrorsHTML += error;
249                        });
250                    }
251
252                    $field
253                        .html(validationErrorsHTML)
254                        .show()
255                        ;
256
257                    configureDocumentFields(properties);
258                }
259            }
260        },
261        showDialog = function (quoteRef, packageId, multiItemId, multiItemIndex) {
262
263            if (quoteRef &&
264                quoteRef !== undefined &&
265                quoteRef !== null &&
266                quoteRef.length !== 0 &&
267                Number.isInteger(packageId) &&
268                packageId > 0) {
269
270                let $dialog = $(".aioi-evb-dialog:first");
271
272                if (!isResponsiveTheme) {
273
274                    $dialog
275                        .data("quoteRef", quoteRef)
276                        .data("packageId", packageId)
277                        .data("multiItemId", multiItemId)
278                        .data("multiItemIndex", multiItemIndex)
279                        .dialog("open")
280                        ;
281
282                } else {
283
284                    properties.documentId = null;
285                    properties.evbNumber = null;
286                    properties.multiItemId = multiItemId;
287                    properties.multiItemIndex = multiItemIndex;
288                    properties.packageId = packageId;
289                    properties.quoteRef = quoteRef;
290
291                    aioiEVB.tryLoadExisting(properties);
292
293                    $dialog.modal("show");
294                }
295            }
296        },
297        submitRequest = function (properties) {
298
299            if (properties.quoteRef !== null &&
300                Number.isInteger(properties.packageId) &&
301                properties.packageId > 0) {
302
303                resetDialog();
304                $(".aioi-evb-dialog-document-request-button").text("Document Requested...");
305
306                var spinner = ShowWaitingAnimation();
307
308                $.ajax({
309                    url: "/" + controllerName + "/SubmitRequestToAioiEvbService",
310                    type: "POST",
311                    contentType: "application/json",
312                    data: JSON.stringify({
313                        quoteRef: properties.quoteRef,
314                        packageId: properties.packageId,
315                        multiItemId: properties.multiItemId,
316                        multiItemIndex: properties.multiItemIndex
317                    }),
318                    cache: false,
319                    dataType: "json"
320                })
321                    .done(function (_data, _textStatus, jqXHR) {
322
323                        let responseJSON = null;
324
325                        if (jqXHR && jqXHR.responseText && jqXHR.responseText.length > 0) {
326
327                            responseJSON = JSON.parse(jqXHR.responseText);
328
329                            if (responseJSON.evbNumber &&
330                                responseJSON.evbNumber !== undefined &&
331                                responseJSON.evbNumber !== null) {
332
333                                properties.evbNumber = responseJSON.evbNumber;
334                                setEvbNumberField(responseJSON.evbNumber);
335                            }
336
337                            if (responseJSON.documentId &&
338                                responseJSON.documentId !== undefined &&
339                                responseJSON.documentId !== null) {
340
341                                properties.documentId = responseJSON.documentId;
342                                setDocumentId(responseJSON.documentId);
343                            }
344
345                            setValidationErrors(responseJSON.errorMessage, responseJSON.validationErrors);
346
347                            configureDocumentFields(properties);
348                            configureDocumentRequestButton(properties);
349                        }
350                    })
351                    .fail(function (_jqXHR, _textStatus, _errorThrown) {
352                        configureDocumentRequestButton(properties);
353                        setValidationErrors(properties.errorMessageGeneric);
354                    })
355                    .always(function () {
356
357                        HideWaitingAnimation(spinner);
358                        $(".aioi-evb-dialog-document-request-button").prop("disabled", false);
359                    })
360                    ;
361            }
362        },
363        tryLoadExisting = function (properties) {
364
365            setEvbNumberField(null);
366            setDocumentId(null);
367            configureDocumentRequestButton(properties);
368            $(".aioi-evb-dialog-document-request-button").prop("disabled", true);
369
370            if (properties.quoteRef !== null &&
371                Number.isInteger(properties.packageId) &&
372                properties.packageId > 0) {
373
374                var spinner = ShowWaitingAnimation();
375
376                $.ajax({
377                    url: "/" + controllerName + "/TryLoadAioiEVB",
378                    contentType: "json",
379                    data: {
380                        quoteRef: properties.quoteRef,
381                        packageId: properties.packageId,
382                        multiItemId: properties.multiItemId,
383                        multiItemIndex: properties.multiItemIndex
384                    },
385                    cache: false,
386                    dataType: "json"
387                })
388                    .done(function (_data, _textStatus, jqXHR) {
389
390                        let responseJSON = null;
391
392                        if (jqXHR && jqXHR.responseText && jqXHR.responseText.length > 0) {
393
394                            responseJSON = JSON.parse(jqXHR.responseText);
395
396                            if (responseJSON.evbNumber &&
397                                responseJSON.evbNumber !== undefined) {
398
399                                properties.evbNumber = responseJSON.evbNumber;
400                                setEvbNumberField(responseJSON.evbNumber);
401
402                            } else {
403
404                                properties.evbNumber = null;
405                            }
406
407                            if (responseJSON.documentId &&
408                                responseJSON.documentId !== undefined) {
409
410                                properties.documentId = responseJSON.documentId;
411                                setDocumentId(responseJSON.documentId);
412
413                            } else {
414
415                                properties.documentId = null;
416                            }
417
418                            configureDocumentFields(properties.documentId);
419                            configureDocumentRequestButton(properties);
420                        }
421                    })
422                    .always(function () {
423
424                        HideWaitingAnimation(spinner);
425                        $(".aioi-evb-dialog-document-request-button").prop("disabled", false);
426                    })
427                    ;
428            }
429        }
430        ;
431
432    // Public members
433    return {
434        downloadDocument: downloadDocument,
435        resetDialog: resetDialog,
436        showDialog: showDialog,
437        submitRequest: submitRequest,
438        tryLoadExisting: tryLoadExisting
439    };
440}();
441
442
443// Shim for IE since it does not support the isInteger function
444Number.isInteger = Number.isInteger || function (value) {
445
446    return typeof value === "number" &&
447        isFinite(value) &&
448        Math.floor(value) === value;
449};
450
451// Ensure styling of Bootstrap dialog buttons does not conflict with jQuery dialog buttons
452if ($.fn.button && $.fn.button.noConflict) {
453    var bootstrapButton = $.fn.button.noConflict();
454    if (bootstrapButton) {
455        $.fn.bootstrapBtn = bootstrapButton;
456    }
457}
458
459/*
460 * @param integer v: value
461 * @param integer n: length of decimal
462 * @param integer x: length of whole part
463 * @param mixed   s: sections delimiter
464 * @param mixed   c: decimal delimiter
465 */
466Instanda.formatAsCurrency = function formatAsCurrency(v, n, x, s, c) {
467    var re = '\\d(?=(\\d{' + (x || 3) + '})+' + (n > 0 ? '\\D' : '$') + ')',
468        num = v.toFixed(Math.max(0, ~~n));
469
470    return (c ? num.replace('.', c) : num).replace(new RegExp(re, 'g'), '$&' + (s || ','));
471};
472
473Instanda.stripNonNumeric = function stripNonNumeric(str) {
474    str += '';
475    str = str.replace(/,/g, '');
476    return str;
477}
478
479Instanda.MutationObserver = function(targetNode, onChildListMutation, onAttributeMutation, onCharacterDataMutation) {
480
481    const config = { attributes: true, childList: true, subtree: true, characterData: true };
482
483    function mutationObserverCallback(mutationsList, observer) {
484        for (let i = 0; i < mutationsList.length; i++) {
485            if (mutationsList[i].type === 'childList') {
486                if (onChildListMutation) {
487                    onChildListMutation();
488                }
489            } else if (mutationsList[i].type === 'attributes') {
490                if (onAttributeMutation) {
491                    onAttributeMutation();
492                }
493            } else if (mutationsList.type === 'characterData') {
494                if (onCharacterDataMutation) {
495                    onCharacterDataMutation();
496                }
497            }
498        }
499    }
500
501    let autosaveMutationObserver = new MutationObserver(mutationObserverCallback);
502
503    function observe() {
504        autosaveMutationObserver.observe(targetNode, config);
505    }
506
507    function disconnect() {
508        autosaveMutationObserver.disconnect();
509    }
510
511    return {
512        observe: observe,
513        disconnect: disconnect
514    }
515};
516
517function toggleCheckbox(checkboxValue) {
518    var checkbox = $("input[value='" + checkboxValue + "']");
519    checkbox.attr('checked', !checkbox.attr('checked'));
520}
521
522function clickButton(buttonValue) {
523    var button = $("button[value='" + buttonValue + "']");
524    button.click();
525}
526
527function showChildQuestions(elementRoot, questionBoxId, maxRepeats) {
528    var numberOfRepeats = $("#" + questionBoxId).val();
529    for (var i = 0; i < maxRepeats; i++) {
530        var element = $("#" + elementRoot + i);
531        if (i < numberOfRepeats) {
532            element.slideDown();
533        } else {
534            element.slideUp();
535        }
536    }
537}
538
539function addMultiItemEvent(item){
540    // set the value in the summary to the value they've just typed in
541    let inputSelector = $("#" + item + " :input");
542
543    // There is a bug in the datepicker where it takes focus from the input box, and then changes the value.
544    // So we catch the change and blur events, then wait until the value is set, then set the text
545    inputSelector.on("change", function () {
546        let changedInput = $(this);
547        
548        setTimeout(function () {
549            updateMultiItemSummary(changedInput, false, false);
550        }, 500);
551    });
552    
553    inputSelector.on("blur change", function () {
554        let blurredInput = $(this);
555
556        setTimeout(function () {
557            if (!blurredInput.is(':radio:unchecked')) {
558                try {
559                    const inputByName = ".instanda-multi-item-summary-item [data-newid='" + $.escapeSelector("li_" + blurredInput.prop("name")) + "']";
560                    const input = $(inputByName);
561                    if (input.length) {
562                        input.text(blurredInput.val());
563                    }
564                } catch (error) { }
565            }
566        }, 500);
567    }).blur();
568}
569
570function showMultiItem(item) {
571
572    var $id = $(item).data("multi-item-variable-name");
573    
574    $('#' + $id).slideToggle(250, function() {
575            const event = new Event("slideToggleFinished");
576            document.dispatchEvent(event);
577    });
578    
579    if ($(item).text() == $(item).data("editactiontext")) {
580        addMultiItemEvent($id);
581        $(item).text($(item).data("stopeditactiontext"));
582
583        // raise an event for ajax load to wire up any bootstrap date pickers
584        if (isResponsiveTheme) {
585            const event = new CustomEvent('multiItemShowClicked', {
586                "detail": {
587                    "clientOriginalShortDatePatternForDatePicker":clientOriginalShortDatePatternForDatePicker,
588                    "clientOriginalShortDatePattern":clientOriginalShortDatePattern,
589                    "isTouchDevice":isTouchDevice,
590                    "isResponsiveTheme":isResponsiveTheme}
591            });
592            document.dispatchEvent(event);
593        }
594    } else {
595        $(item).text($(item).data("editactiontext"));
596    }
597}
598
599function addInitialMultiItems(sampleItem, multiItemHolder, minItems, maxItems, multiItemCount, newItemIndex, itemIndexList, elementRoot, multiItemAssociationQuestionId, dateTimePickerFormat) {
600
601    if (multiItemCount.val() < minItems) {
602        for (var i = multiItemCount.val(); i < minItems; i++) {
603            addMultiItemByClone(sampleItem, multiItemHolder, minItems, maxItems, multiItemCount, newItemIndex, itemIndexList, elementRoot, multiItemAssociationQuestionId, dateTimePickerFormat);
604        }
605    }
606
607    UpdateMultiItemPositions(itemIndexList.val());
608
609    if (parseInt(multiItemCount.val()) === 0 && minItems === 0 && $('[data-action="remove-multi-item"]').length !== 0)
610        return;
611
612    $("#" + elementRoot + "addButton").attr("disabled", multiItemCount.val() >= maxItems);
613    $('button[id^="' + elementRoot + 'removeButton_"]').attr("disabled", multiItemCount.val() == minItems);
614    $('[data-action="remove-multi-item"][data-multi-item-variable-name*="' + elementRoot + '"]').attr("disabled", parseInt(multiItemCount.val()) === minItems);
615
616    if (!hasEnoughSavedInstances()) {
617        disableFormActionButtons();
618    }
619}
620
621function removeLastMultiItem(minItems, maxItems, multiItemCount, multiItemIndexList, multiItemAssociationQuestionId, elementRoot) {
622
623    var multiItemToDelete = '.instanda-multi-item-' + elementRoot + getMaxArrayElement(multiItemIndexList.val());
624    var lastEditDivOpened = $("div[data-type='instanda multi item edit']").filter(function (index) {
625        return $(this).is(":visible") === true;
626    }).last();
627
628    // update the summary tab while you remove items
629    var currentValue = parseInt(multiItemCount.val());
630    if (currentValue > minItems) {
631        if (lastEditDivOpened.length === 0) {
632            $(`div[id^='multi-item-summary-${elementRoot}']`).last().remove();
633        } else {
634            // if we have edit divs opened then remove the item associated with the last div edit opened
635            var idOfTheLastEditDivOpened = lastEditDivOpened.attr("id");
636            multiItemToDelete = '.instanda-multi-item-' + idOfTheLastEditDivOpened;
637            $("#multi-item-summary-" + idOfTheLastEditDivOpened).remove();
638        }
639
640        if (currentValue == minItems + 1) {
641            $("button[data-type='removeButton']").prop("disabled", true);
642        }
643    }
644    removeCurrentMultiItem(multiItemToDelete, minItems, maxItems, multiItemCount, multiItemIndexList, multiItemAssociationQuestionId, elementRoot);
645}
646
647function removeCurrentMultiItem(multiItem, minItems, maxItems, multiItemCount, multiItemIndexList, multiItemAssociationQuestionId, elementRoot) {
648
649    if ($(multiItem).length <= 0) {
650        return;
651    }
652
653    var currentValue = parseInt(multiItemCount.val());
654    if (currentValue >= minItems) {
655        currentValue--;
656        multiItemCount.val(currentValue);
657        var itemNumberInDivCss = $(multiItem).attr('class')
658            .replace('instanda-multi-item instanda-multi-item-' + elementRoot, '')
659            .replace(' instanda-question-multi-item-hidden', '')
660            .replace(' saved', '')
661            .replace(' draft', '');
662
663        $(multiItem).slideUp(function () {
664            $(multiItem).remove();
665        });
666
667        multiItemIndexList.val(removeCSVArrayElement(multiItemIndexList.val(), itemNumberInDivCss));
668
669        const multiItemAssociationInstancePerContainer = `[name="Question${multiItemAssociationQuestionId}_InstancePerContainer"]`;
670        const multiItemAssociationInstanceCount = `[name="Question${multiItemAssociationQuestionId}_InstanceCount"]`;
671        const multiItemAssociationInstanceIndexList = `[name="Question${multiItemAssociationQuestionId}_InstanceIndexList"]`;
672        if (document.querySelector(multiItemAssociationInstanceCount)) {
673            let instancePerContainer = document.querySelector(multiItemAssociationInstancePerContainer).value;
674            let instanceCountElement = document.querySelector(multiItemAssociationInstanceCount);
675
676            let instanceIndexList = document.querySelector(multiItemAssociationInstanceIndexList);
677            let indexList = JSON.parse(instanceIndexList.value);
678            delete indexList[itemNumberInDivCss];
679            instanceIndexList.value = JSON.stringify(indexList);
680
681            instanceCountElement.value = parseInt(instanceCountElement.value) - parseInt(instancePerContainer);
682        }
683    }
684
685    UpdateMultiItemPositions(multiItemIndexList.val());
686
687    $("#" + elementRoot + "addButton").attr("disabled", currentValue == maxItems);
688    $('button[id^="' + elementRoot + 'removeButton_"]').attr("disabled", currentValue == minItems);
689    $('[data-action="remove-multi-item"][data-multi-item-variable-name*="' + elementRoot + '"]').attr("disabled", parseInt(multiItemCount.val()) === minItems);
690
691    if (currentValue == minItems) {
692        $('[data-action="hide-multi-items"]').hide();
693    } else {
694        $('[data-action="hide-multi-items"]').show();
695    }
696
697    var id = '#' + 'multi-item-summary-' + multiItem.replace('#', '');
698
699    $(id).remove();
700    clearErrors();
701}
702
703function UpdateMultiItemPositions(multiItemIndexList) {
704    $("[data-mindex]").each(function () {
705        var newPosition = GetMultiItemPosition(multiItemIndexList, $(this).data("mindex"));
706        $(this).val(newPosition);
707    });
708}
709
710function GetMultiItemPosition(multiItemIndexList, multiItemIndex) {
711    var array = multiItemIndexList.split(',');
712    array.sort(function (a, b) { return a - b; });
713
714    var position = $.inArray(multiItemIndex.toString(), array);
715    if (position < 0) {
716        return "";
717    } else {
718        return position + 1;
719    }
720}
721
722function removeCSVArrayElement(inputArray, elementToRemove) {
723    var array = inputArray.split(',');
724
725    var position = $.inArray(elementToRemove, array);
726    if (position < 0) {
727        return inputArray;
728    }
729
730    array.splice(position, 1);
731    return array.join(",");
732}
733
734function addCSVArrayElement(inputArray, elementToAdd) {
735    var array = [];
736    if (inputArray != "") {
737        array = inputArray.split(',');
738    }
739
740    array.push(elementToAdd);
741    return array.join(",");
742}
743
744function getMaxArrayElement(inputArray) {
745    var array = [];
746    if (inputArray != "" && inputArray != undefined) {
747        array = inputArray.split(',');
748    }
749
750    return Math.max.apply(Math, array);
751}
752
753function addMultiItemForExisting(sampleItem, elementRoot, index, multiItemAssociationQuestionId) {
754    const dataTargetSelector = "data-target";
755    
756    let removeButton = document.querySelector("button[data-type='removeButton']")
757    // when adding an item be sure remove button is enabled
758    if(removeButton) {
759        removeButton.disabled = false
760    }
761    else {
762        removeButton = document.querySelector("#" + elementRoot + "removeButton")
763        
764        if (removeButton)
765            removeButton.disabled = false;
766    }
767
768    let newMultiItem = sampleItem.cloneNode(true);
769    let miContents = newMultiItem.querySelector("#MultiItemNameAndIndex")
770    miContents.append(document.querySelector("input[name=MultiItemNameAndIndex_position]").cloneNode(true))
771    let container = document.querySelector('#' + elementRoot + index);
772
773    let helpIconLinks = miContents.querySelectorAll(".instanda-responsive-help-icon-link");
774    
775    helpIconLinks.forEach(function (helpIconLink) {
776        let dataTarget = helpIconLink.getAttribute(dataTargetSelector);
777        //Find specific helpText in newMultiItem that is being targeted by each helpIcon
778        let helpText = miContents.querySelector(dataTarget);
779        helpIconLink.setAttribute(dataTargetSelector, dataTarget + "_" + index);
780        helpText.id = helpText.id + "_" + index;
781    });
782
783    miContents.style.display = "block";
784    // Remove existing calendar trigger img if it exists as a new one will be added automatically
785    var datepicker = miContents.querySelector(".ui-datepicker-trigger")
786    
787    if(datepicker)
788        datepicker.remove();
789    
790    var content = miContents.innerHTML;
791    content = content.replace(/MultiItemNameAndIndex/gi, elementRoot + index);
792    content = content.replace(/MultiItemIndex/gi, index);
793
794    // Replace placeholder child MIA index under multi-item question with the actual index
795    if (multiItemAssociationQuestionId !== 0) {
796        const multiItemAssociationInstancePerContainer = `[name="Question${multiItemAssociationQuestionId}_InstancePerContainer"]`;
797        const multiItemAssociationInstanceCount = `[name="Question${multiItemAssociationQuestionId}_InstanceCount"]`;
798        const multiItemAssociationMaxIndex = `[name="Question${multiItemAssociationQuestionId}_InstanceMaxIndex"]`;
799        const multiItemAssociationInstanceIndexList = `[name="Question${multiItemAssociationQuestionId}_InstanceIndexList"]`;
800        if (document.querySelector(multiItemAssociationMaxIndex)) {
801            let maxIndex = document.querySelector(multiItemAssociationMaxIndex).value;
802            let instanceIndexList = document.querySelector(multiItemAssociationInstanceIndexList);
803            let indexList = JSON.parse(instanceIndexList.value);
804
805            let miaPattern = new RegExp(`HiddenMIA${multiItemAssociationQuestionId}_Index.{7}`, 'gi')
806            let matches = content.match(miaPattern);
807            let uniqueMatches = [...new Set(matches)];
808            let indexInContainer = [];
809            uniqueMatches.forEach(match => {
810                maxIndex++;
811                const regex = new RegExp(match, 'gi');
812                content = content.replace(regex, maxIndex);
813                indexInContainer.push(maxIndex);
814            });
815            indexList[index] = indexInContainer;
816            instanceIndexList.value = JSON.stringify(indexList);
817
818            document.querySelector(multiItemAssociationMaxIndex).value = maxIndex;
819
820            let instancePerContainer = document.querySelector(multiItemAssociationInstancePerContainer).value;
821            let instanceCountElement = document.querySelector(multiItemAssociationInstanceCount);
822
823            instanceCountElement.value = parseInt(instanceCountElement.value) + parseInt(instancePerContainer);
824        }
825    }
826
827    // Remove hasDatepicker class if its in the html as a new one will be added automatically
828    content = content.replace(/hasDatepicker/gi, "");
829    var indexRegEx = new RegExp(elementRoot + "0", "gi");
830    content = content.replace(indexRegEx, elementRoot + index);
831    container.innerHTML = content;
832    
833    if (isResponsiveTheme) {
834        datepickerLogic(clientOriginalShortDatePatternForDatePicker, clientOriginalShortDatePattern, isTouchDevice, isResponsiveTheme);
835    }
836
837    var element = document.querySelector("#" + elementRoot + index);
838    element.style.display = "none";
839
840    var summary = element.closest(".instanda-multi-item-summary-item")
841    
842    if(summary)
843        summary.style.display = "block";
844
845    // Add events for any DocumentUploadQuestions
846    var fileUpload = document.querySelector("#" + elementRoot + index + ' .instanda-file-input')
847    
848    if(fileUpload) {
849        fileUpload.addEventListener("change", function () {
850            this.parentNode.querySelector('.instanda-file-input-selected').textContent = (this.value.split('\\').pop());
851        });
852    }
853
854    document.querySelector("#" + element.dataset["summaryHeader"]).style.display = "block";
855}
856
857function addMultiItemByClone(sampleItem, multiItemHolder, minItems, maxItems, multiItemCount, newItemIndex, itemIndexList, elementRoot, multiItemAssociationQuestionId, dateTimePickerFormat) {
858    $("button[data-type='removeButton']").prop("disabled", false);
859    // when adding an item be sure remove button is enabled
860    $("#" + elementRoot + "removeButton").prop("disabled", false);
861    if (parseInt(multiItemCount.val()) < maxItems) {
862        multiItemCount.val(parseInt(multiItemCount.val()) + 1);
863        newItemIndex.val(parseInt(newItemIndex.val()) + 1);
864    } else {
865        return;
866    }
867
868    var currentItemIndex = newItemIndex.val();
869    var multiItemCountVar = multiItemCount.val();
870    var newMultiItem = sampleItem.clone();
871
872    // If it is IE we need to manually clone radio 'checked' attributes
873    if (IsIE()) {
874        $('input[type=radio]:checked', sampleItem).each(function () {
875            $('#' + $(this).attr('id'), newMultiItem).attr('checked', true);
876        });
877    }
878
879    let helpIconLinks = $(".instanda-responsive-help-icon-link", newMultiItem);
880
881    helpIconLinks.each(function () {
882        //Find specific helpText in newMultiItem that is being targeted by each helpIcon
883        let helpText = $( $(this).attr("data-target"), newMultiItem);
884        $(this).attr("data-target", $(this).attr("data-target") + "_" + currentItemIndex);
885        helpText.prop("id", helpText.prop("id") + "_" + currentItemIndex);
886    });
887
888    newMultiItem.show();
889    // Remove existing calendar trigger img if it exists as a new one will be added automatically
890    newMultiItem.find(".ui-datepicker-trigger").remove();
891    var content = newMultiItem.html();
892    content = content.replace(/MultiItemNameAndIndex/gi, elementRoot + currentItemIndex);
893    content = content.replace(/MultiItemIndex/gi, currentItemIndex);
894    
895    // Replace placeholder child MIA index under multi-item question with the actual index
896    if (multiItemAssociationQuestionId !== 0) {
897        const multiItemAssociationInstancePerContainer = `[name="Question${multiItemAssociationQuestionId}_InstancePerContainer"]`;
898        const multiItemAssociationInstanceCount = `[name="Question${multiItemAssociationQuestionId}_InstanceCount"]`;
899        const multiItemAssociationMaxIndex = `[name="Question${multiItemAssociationQuestionId}_InstanceMaxIndex"]`;
900        const multiItemAssociationInstanceIndexList = `[name="Question${multiItemAssociationQuestionId}_InstanceIndexList"]`;
901        if (document.querySelector(multiItemAssociationMaxIndex)) {
902            let maxIndex = document.querySelector(multiItemAssociationMaxIndex).value;
903            let instanceIndexList = document.querySelector(multiItemAssociationInstanceIndexList);
904            let indexList = JSON.parse(instanceIndexList.value);
905
906            let miaPattern = new RegExp(`HiddenMIA${multiItemAssociationQuestionId}_Index.{7}`, 'gi')
907            let matches = content.match(miaPattern);
908            let uniqueMatches = [...new Set(matches)];
909            let indexInContainer = [];
910            uniqueMatches.forEach(match => {
911                maxIndex++;
912                const regex = new RegExp(match, 'gi');
913                content = content.replace(regex, maxIndex);
914                indexInContainer.push(maxIndex);
915            });
916            indexList[currentItemIndex] = indexInContainer;
917            instanceIndexList.value = JSON.stringify(indexList);
918
919            document.querySelector(multiItemAssociationMaxIndex).value = maxIndex;
920
921            let instancePerContainer = document.querySelector(multiItemAssociationInstancePerContainer).value;
922            let instanceCountElement = document.querySelector(multiItemAssociationInstanceCount);
923
924            instanceCountElement.value = parseInt(instanceCountElement.value) + parseInt(instancePerContainer);
925        }
926    }
927
928    // Remove hasDatepicker class if its in the html as a new one will be added automatically
929    content = content.replace(/hasDatepicker/gi, "");
930    var indexRegEx = new RegExp(elementRoot + "0", "gi");
931    content = content.replace(indexRegEx, elementRoot + currentItemIndex);
932    multiItemHolder.append(content);
933    if (isResponsiveTheme) {
934        datepickerLogic(clientOriginalShortDatePatternForDatePicker, clientOriginalShortDatePattern, isTouchDevice, isResponsiveTheme);
935    }
936
937    var element = $("#" + elementRoot + currentItemIndex);
938    element.hide();
939
940    if (IsIE()) {
941        // Input fields cannot be focused when inside a large animated multi item without a long animation time, so just show it
942        element.show();
943    } else {
944        element.slideDown();
945    }
946
947    element.closest(".instanda-multi-item-summary-item").show();
948    
949    itemIndexList.val(addCSVArrayElement(itemIndexList.val(), currentItemIndex));
950
951    UpdateMultiItemPositions(itemIndexList.val());
952    
953    
954    $("#" + elementRoot + "addButton").attr("disabled", multiItemCountVar >= maxItems);
955    $('button[id^="' + elementRoot + 'removeButton_"]').attr("disabled", multiItemCountVar == minItems);
956    $('[data-action="remove-multi-item"][data-multi-item-variable-name*="' + elementRoot + '"]').attr("disabled", parseInt(multiItemCount.val()) === minItems);
957
958    // Add events for any DocumentUploadQuestions
959    $("#" + elementRoot + currentItemIndex + ' .instanda-file-input').change(function () {
960        $(this).parent().find('.instanda-file-input-selected').text($(this).val().split('\\').pop());
961    });
962
963    // Add event for the input fields to update the summary fields
964    addMultiItemEvent(elementRoot + currentItemIndex);
965
966    $("#" + element.data("summaryHeader")).show();
967
968    const event = new CustomEvent('multiItemAddedByClone', { detail: {root: elementRoot, index: currentItemIndex} });
969    document.dispatchEvent(event);
970}
971
972function IsIE() {
973    var sAgent = window.navigator.userAgent;
974    var Idx = sAgent.indexOf("MSIE");
975    if (Idx > 0 || !!navigator.userAgent.match(/Trident\/7\./)) {
976        return true;
977    } else {
978        return false;
979    }
980}
981
982function toggleChildQuestions(childrenElementName, value, triggeredByYes) {
983    var element = $("#" + childrenElementName);
984    if ((triggeredByYes && value == "Yes") || (!triggeredByYes && value == "No")) {
985        element.slideDown();
986    } else {
987        element.slideUp();
988    }
989}
990
991function toggleDropdownChoiceChildQuestions(childrenElementName, allChildrenElementNames, select, choiceToChildrenMap) {
992    if (window.navigator.userAgent.indexOf('Trident/') > 0 && select.selectedOptions == undefined) {
993        for (var i = 0; i < select.options.length; i++) {
994            if (select.options[i].selected) {
995                var selectedChildrenElementName = childrenElementName + select.options[i].getAttribute("data-id");
996                toggleChoiceChildQuestions(selectedChildrenElementName, allChildrenElementNames, choiceToChildrenMap);
997            }
998        }
999    }
1000    else if (select != null && select.selectedOptions != null && select.selectedOptions.length > 0) {
1001        var selectedChildrenElementName = childrenElementName + select.selectedOptions[0].getAttribute("data-id");
1002        toggleChoiceChildQuestions(selectedChildrenElementName, allChildrenElementNames, choiceToChildrenMap);
1003    }
1004}
1005
1006function toggleChoiceChildQuestions(selectedElementName, allChildrenElementNames, choiceToChildrenMap) {
1007    {
1008        if (!choiceToChildrenMap) 
1009        {
1010            for (let i = 0; i < allChildrenElementNames.length; i++) 
1011            {
1012                let childrenElementNameToHide = allChildrenElementNames[i];
1013
1014                if (childrenElementNameToHide !== selectedElementName) 
1015                {
1016                    $("#" + childrenElementNameToHide).slideUp(100);
1017                }
1018            }
1019
1020            $("#" + selectedElementName).slideDown();
1021            return;
1022        }
1023
1024        var childrenElementNames = choiceToChildrenMap[selectedElementName];
1025
1026        for (let i = 0; i < allChildrenElementNames.length; i++) 
1027        {
1028            let childrenElementNameToHide = allChildrenElementNames[i];
1029            if (!childrenElementNames || !childrenElementNames.includes(childrenElementNameToHide)) 
1030            {
1031                $("#" + childrenElementNameToHide).slideUp(100);
1032            }
1033        }
1034
1035        if (childrenElementNames) {
1036            for (let i = 0; i < childrenElementNames.length; i++) 
1037            {
1038                var childrenElementNameToShow = childrenElementNames[i];
1039                $("#" + childrenElementNameToShow).slideDown(100);
1040            }
1041        }
1042    }
1043}
1044
1045function lookupCarDetails(reallyLookUp, colourVariableName, makeVariableName, modelVariableName,
1046    registrationVariableName, yearOfManufactureVariableName, abiGroupVariableName,
1047    doorPlanCodeVariableName, wheelPlanCodeVariableName, grossVehicleWeightV
1047ariableName,
1048    engineCapacityVariableName, transmissionCodeVariableName, questionId, prefix) {
1049
1050    var carDetailsSelector = 'instanda-car-details-question-input';
1051
1052    var notFoundSelector = 'vehicle-not-found';
1053    var forbiddenSelector = 'vehicle-access-forbidden';
1054    var lookupErrorSelector = 'vehicle-lookup-error';
1055    var regEmptySelector = 'registration-empty';
1056    var registrationNumberLengthErrorSelector = 'registration-length-incorrect';
1057    var systemFailureSelector = "system-failure";
1058
1059    if (questionId) {
1060        carDetailsSelector = carDetailsSelector + '_' + questionId;
1061        notFoundSelector = notFoundSelector + '_' + questionId;
1062        forbiddenSelector = forbiddenSelector + '_' + questionId;
1063        lookupErrorSelector = lookupErrorSelector + '_' + questionId;
1064        regEmptySelector = regEmptySelector + '_' + questionId;
1065        registrationNumberLengthErrorSelector = registrationNumberLengthErrorSelector + '_' + questionId;
1066        systemFailureSelector = systemFailureSelector + "_" + questionId;
1067    }
1068
1069    if (prefix) {
1070        carDetailsSelector = prefix + carDetailsSelector;
1071        notFoundSelector = prefix + notFoundSelector;
1072        forbiddenSelector = prefix + forbiddenSelector;
1073        lookupErrorSelector = prefix + lookupErrorSelector;
1074        regEmptySelector = prefix + regEmptySelector;
1075        registrationNumberLengthErrorSelector = prefix + registrationNumberLengthErrorSelector;
1076        systemFailureSelector = prefix + systemFailureSelector;
1077    }
1078
1079    carDetailsSelector = '#' + carDetailsSelector;
1080    notFoundSelector = '#' + notFoundSelector;
1081    forbiddenSelector = '#' + forbiddenSelector;
1082    lookupErrorSelector = '#' + lookupErrorSelector;
1083    regEmptySelector = '#' + regEmptySelector;
1084    registrationNumberLengthErrorSelector = '#' + registrationNumberLengthErrorSelector;
1085    systemFailureSelector = '#' + systemFailureSelector;
1086
1087    $(notFoundSelector).hide();
1088    $(regEmptySelector).hide();
1089    $(registrationNumberLengthErrorSelector).hide();
1090    $(systemFailureSelector).hide();
1091
1092    var reg = $("#" + registrationVariableName).val().trim();
1093
1094    var urlToCall = "LookupCarDetails?registration=" + reg;
1095
1096    var populateFieldsFunction = function (data, textStatus, XMLHttpRequest) {
1097        if (data == "VehicleNotFound") {
1098            $(notFoundSelector).show();
1099        } else if (data == "AccessForbidden") {
1100            $(forbiddenSelector).show();
1101        } else if (data == "InvalidRegistrationNumber") {
1102            $(registrationNumberLengthErrorSelector).show();
1103        } else if (data == "SystemFailure") {
1104            $(systemFailureSelector).show();
1105        } else {
1106            $("#" + colourVariableName).val(data.Colour);
1107            $("#" + makeVariableName).val(data.Make);
1108            $("#" + modelVariableName).val(data.Model);
1109            $("#" + yearOfManufactureVariableName).val(data.YearOfManufacture);
1110            $("#" + abiGroupVariableName).val(data.ABIGroup);
1111            $("#" + doorPlanCodeVariableName).val(data.DoorPlanCodeVariableName);
1112            $("#" + wheelPlanCodeVariableName).val(data.WheelPlanCodeVariableName);
1113            $("#" + grossVehicleWeightVariableName).val(data.GrossVehicleWeightVariableName);
1114            $("#" + engineCapacityVariableName).val(data.EngineCapacityVariableName);
1115            $("#" + transmissionCodeVariableName).val(data.TransmissionCodeVariableName);
1116
1117
1118            $(carDetailsSelector).show();
1119        }
1120    };
1121
1122    var clear = function () {
1123        var data = {
1124            Color: null,
1125            Make: null,
1126            Model: null,
1127            YearOfManufacture: null,
1128            ABIGroup: null
1129        };
1130        populateFieldsFunction(data);
1131    };
1132
1133    var showFieldsFunction = function (XMLHttpRequest, textStatus) {
1134        $("#" + colourVariableName).parent().slideDown();
1135    };
1136
1137    var errorFunction = function (XMLHttpRequest, textStatus, errorThrown) {
1138        $(lookupErrorSelector).show();
1139        clear();
1140    };
1141
1142    if (reg.length < 1) {
1143        $(regEmptySelector).show();
1144    } else {
1145        if (reallyLookUp) {
1146            $.ajax({
1147                url: urlToCall,
1148                success: populateFieldsFunction,
1149                dataType: "json",
1150                error: errorFunction,
1151                complete: showFieldsFunction
1152            });
1153        } else {
1154            showFieldsFunction(null, null);
1155        }
1156    }
1157}
1158
1159function getHostname(fullUrl) {
1160    if (!fullUrl) {
1161        return null;
1162    }
1163    var hostnameRegex = new RegExp('^https?://([^/]+)', 'im');
1164    var matches = fullUrl.match(hostnameRegex);
1165    if (matches.length > 0) {
1166        return [1].toString();
1167    }
1168}
1169
1170function escapeString(value) {
1171    // As mentioned on http://api.jquery.com/category/selectors/
1172    return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1");
1173}
1174
1175/*
1176Ensures that all unhandled JavaScript errors are displayed and logged
1177
1178Exceptions to this rule should be added explicitly
1179*/
1180
1181$(function () {
1182    $(document.body).on('click', '[data-action="show-multi-item"]', function (e) {
1183        showMultiItem(this);
1184    });
1185    try {
1186        toastr.options = {
1187            "closeButton": true,
1188            "debug": false,
1189            "newestOnTop": false,
1190            "progressBar": false,
1191            "positionClass": "toast-bottom-full-width",
1192            "preventDuplicates": false,
1193            "onclick": null,
1194            "showDuration": "300",
1195            "hideDuration": "1000",
1196            "timeOut": 0,
1197            "extendedTimeOut": 0,
1198            "showEasing": "swing",
1199            "hideEasing": "linear",
1200            "showMethod": "fadeIn",
1201            "hideMethod": "fadeOut",
1202            "tapToDismiss": false,
1203            "escapeHtml": true
1204        };
1205
1206    } catch (e) {
1207        console.log(e);
1208    }
1209});
1210
1211function copyToClipboard(text) {
1212    var $temp = $("<input style='position: absolute; left: -1000px; '>");
1213    $("body").append($temp);
1214    $temp.val(text).select();
1215    document.execCommand("copy");
1216    setTimeout(function () { $temp.remove(); }, 50);
1217}
1218
1219function showModalError(errorMessageParams) {
1220    if (jQuery().dialog) {
1221        $("#javascriptError").dialog({ width: 800, height: 600, modal: true, title: "JavaScript error" }).load("/JavaScriptError/BugTrackerMessage?" + errorMessageParams);
1222    }
1223    else if (jQuery().modal) {
1224        $.get("/JavaScriptError/BugTrackerMessage?" + errorMessageParams, function (data) {
1225            if (jQuery().modal) {
1226                $('#instanda-error-modal .modal-body').html(data);
1227                try {
1228                    // try the modal
1229                    $('#instanda-error-modal').modal();
1230                } catch (e) {
1231                    try {
1232                        // manually manipulate the dom
1233                        $('#instanda-error-modal').css('display', 'block');
1234                        // show the modal
1235                        $('#instanda-error-modal').addClass('in');
1236                        // allow us to dismiss the modal
1237                        $('#instanda-error-modal [data-dismiss=modal]').click(function () {
1238                            $('#instanda-error-modal').css('display', '');
1239                        });
1240                        $('#instanda-error-modal [data-dismiss=modal]').css('z-index', '999');
1241                    } catch (e) {
1242                        console.log(e);
1243                    }
1244                }
1245            } else {
1246                console.log(data);
1247            }
1248        });
1249    }
1250}
1251
1252window.onerror = function (message, url, linenumber) {
1253
1254    if (!url) {
1255        url = "unknown";
1256    }
1257
1258    var errorMessageParams = "message=" + encodeURIComponent(message) + "&url=" + encodeURIComponent(url) + "&linenumber=" + encodeURIComponent(linenumber);
1259
1260    if (typeof url.indexOf !== "function") {
1261        return;
1262    }
1263
1264    //Filter out spurious errors
1265    if (url.indexOf("CKEditor") == -1
1266        && message.indexOf("CKEDITOR") == -1
1267        && url.indexOf("chrome://") == -1
1268        && message.indexOf("scanTheDomAndMakeSomeMagic") == -1
1269        && message.indexOf("Access is denied") == -1
1270        && message.indexOf("zopim") == -1
1271        && message.indexOf("SkypeClick2Call") == -1) {
1272        $.ajaxSetup({ cache: false });
1273        $.ajax({
1274            url: "/JavaScriptError/Log?" + errorMessageParams,
1275            success: function (displayError) {
1276                if (displayError === true) { // bugid 12839
1277                    $.get("/JavaScriptError/ErrorMessage?" + errorMessageParams, function (data) {
1278                        // hold the onerror event temporarily
1279                        var onError = window.onerror;
1280                        // remove quotes from message
1281                        var cleanParams = errorMessageParams.split('"').join("&quot;").split("'").join('&quot;');
1282                        try {
1283                            // unhook the onerror event
1284                            window.onerror = function (error) {
1285                                console.log(error);
1286                            };
1287                            // create a button
1288                            var $moreDetails = $("<button type='button' class=\"toastr-modal-btn clear pull-right\" href='#' onclick=\"showModalError('" + cleanParams + "'); \">")
1289                            $moreDetails.text('More Details');
1290                            data.message = data.message || '';
1291                            data.message = data.message.split('"').join("&quot;").split("'").join('&quot;');
1292                            // add button to error message
1293                            var message = data.message + $moreDetails.prop('outerHTML');
1294                            var title = data.release + ' ' + data.title;
1295                            // onclick event is added to copy message to clipboard
1296                            title += " - <small onclick=\"copyToClipboard('" + data.message + "')\">Click on this <a href=https://instanda.atlassian.net/secure/CreateIssueDetails!init.jspa?pid=10000&issuetype=10004 target=_blank>JIRA link</a> and copy and paste the below content in the description field of the issue</small>";
1297                            toastr.error(message, title, {
1298                                allowHtml: true,
1299                                escapeHtml: false
1300                            });
1301                        } catch (e) {
1302                            showModalError(cleanParams);
1303                        }
1304                        finally {
1305                            // reassign the onerror event
1306                            window.onerror = onError;
1307                        }
1308                    });
1309                    return;
1310                }
1311            }
1312        });
1313        return true;
1314    }
1315    return true;
1316};
1317
1318$(function () {
1319
1320    "use strict";
1321
1322    $(".instanda-questionList").on("click.Instanda", ".instanda-helpIcon", function (event) {
1323
1324        var $helpIcon = $(this),
1325            common = new Instanda.Common();
1326
1327        if ($helpIcon.length !== 0) {
1328
1329            // Ensure any other help text items are hidden first, with exception for the item which has been clicked
1330            $(".instanda-helpText").not($helpIcon.siblings(".instanda-helpText")).hide();
1331
1332            // Toggle the visibility of the clicked item
1333            $helpIcon
1334                .siblings(".instanda-helpText")
1335                .slideToggle();
1336        }
1337
1338        common.abortEvent(event);
1339    });
1340
1341    $(document).on("keyup", null, function (event) {
1342
1343        // Hide the wait spinner when visible and the user presses the Escape key
1344        if (event && event.which === 27 && window.globalSpinner) {
1345
1346            HideWaitingAnimation(window.globalSpinner);
1347        }
1348    });
1349
1350    $('.instanda-question-yes-no-parent-yes input:radio:checked').each(function () {
1351        $(this).prop("checked", true).trigger("click");
1352    });
1353
1354    $('.instanda-question-parent-yes-no select').each(function () {
1355        $(this).prop("val", "Yes").trigger("onchange");
1356    });
1357
1358});
1359
1360
1361$(function () {
1362    var parent = $('.input-validation-error:radio, .input-validation-error:checkbox')
1363        .removeClass('input-validation-error')
1364        .parent().each(function (index, element) {
1365            if ($(element).hasClass("confirmQuestion")) {
1366                $(element).parent().addClass("input-validation-error");
1367            } else {
1368                $(element).addClass("input-validation-error");
1369            }
1370        });
1371});
1372
1373
1374function createAutoCompleteQuestion(autoCompleteQuestionId, autoCompleteList, defaultItem, msgIfNotFound,
1375    isError, name, showAdditionalInfo, hideAdditionalInfo, messageIfUnselected, readOnly, placeholder, basicSiteSelectFunc) {
1376
1377    // Fix for multi-items : INS-11928
1378    if (autoCompleteQuestionId.indexOf("0_") > -1)
1379        autoCompleteQuestionId = autoCompleteQuestionId.replace("0_", "0");
1380
1381    $(function () {
1382        if (!name) {
1383            name = autoCompleteQuestionId;
1384        }
1385
1386        var parent = $("#" + autoCompleteQuestionId).parent();
1387        $("#" + autoCompleteQuestionId).remove();
1388
1389        if (readOnly) {
1390
1391            if (placeholder) {
1392                $(parent).append('<input readonly="readonly" placeholder="' + placeholder + '" id="' + autoCompleteQuestionId + '" type="text" class="typeahead autocomplete form-control' + (isError ? ' input-validation-error' : '') + '" name="' + name + '" value="' + defaultItem + '" />');
1393            }
1394            else {
1395                $(parent).append('<input readonly="readonly" id="' + autoCompleteQuestionId + '" type="text" class="typeahead autocomplete form-control' + (isError ? ' input-validation-error' : '') + '" name="' + name + '" value="' + defaultItem + '" />');
1396            }
1397
1398        } else {
1399
1400            if (placeholder) {
1401                $(parent).append('<input placeholder="' + placeholder + '" id="' + autoCompleteQuestionId + '" type="text" class="typeahead autocomplete form-control' + (isError ? ' input-validation-error' : '') + '" name="' + name + '" value="' + defaultItem + '" />');
1402            }
1403            else {
1404                $(parent).append('<input id="' + autoCompleteQuestionId + '" type="text" class="typeahead autocomplete form-control' + (isError ? ' input-validation-error' : '') + '" name="' + name + '" value="' + defaultItem + '" />');
1405            }
1406        }
1407
1408        if (!jQuery().typeahead && jQuery().autocomplete) {
1409            if (!basicSiteSelectFunc) {
1410                basicSiteSelectFunc = function (event, ui) {
1411                    var lastValue = autoCompleteList[autoCompleteList.length - 1];
1412                    if (ui.item.value == lastValue && showAdditionalInfo) {
1413                        showAdditionalInfo();
1414                    } else if (ui.item.value != lastValue && hideAdditionalInfo) {
1415                        hideAdditionalInfo();
1416                    }
1417
1418                    var msgContainer = $("span[data-valmsg-for='" + escapeString(name) + "']");
1419                    msgContainer.text('');
1420                };
1421            }
1422
1423            $("#" + autoCompleteQuestionId).autocomplete({
1424                source: function (request, response) {
1425                    var results = $.ui.autocomplete.filter(autoCompleteList, request.term);
1426                    response(results.slice(0, Number.MAX_VALUE));
1427                },
1428                select: function (event, ui) {
1429                    basicSiteSelectFunc(event, ui);
1430                },
1431                change: function (event, ui) {
1432                    var inputValue = $(this).val();
1433                    var msgContainer = $("span[data-valmsg-for='" + escapeString(name) + "']");
1434                    if (!ui.item) {
1435                        if (!inputValue) {
1436                            msgContainer.text(messageIfUnselected);
1437                            msgContainer.removeClass("field-validation-valid").addClass("field-validation-error");
1438                            return false;
1439                        } else if (jQuery.inArray(inputValue, autoCompleteList) == -1) {
1440                            msgContainer.text(msgIfNotFound);
1441                            msgContainer.removeClass("field-validation-valid").addClass("field-validation-error");
1442                            return false;
1443                        } else {
1444                            msgContainer.text('');
1445                            msgContainer.removeClass("field-validation-error").addClass("field-validation-valid");
1446                        }
1447                    } else {
1448                        msgContainer.text('');
1449                        msgContainer.removeClass("field-validation-error").addClass("field-validation-valid");
1450                    }
1451
1452                    return true;
1453                },
1454                open: function (event, ui) {
1455                    if (navigator.userAgent.match(/(iPod|iPhone|iPad)/)) {
1456                        // Fixes ios needing 2 touches to select a iten from them menu
1457                        $('.ui-autocomplete').off('menufocus hover mouseover');
1458                    }
1459                }
1460            });
1461
1462        } else {
1463
1464            if (typeof Bloodhound == "function") {
1465                //var autoCompleteValues = new Bloodhound({
1466                //    datumTokenizer: Bloodhound.tokenizers.whitespace,
1467                //    queryTokenizer: Bloodhound.tokenizers.whitespace,
1468                //    local: substringMatcher(autoCompleteList)
1469                //});
1470
1471                $('#' + autoCompleteQuestionId + '.typeahead').typeahead({
1472                    hint: true,
1473                    highlight: true,
1474                    minLength: 1
1475                },
1476                    {
1477                        name: name,
1478                        source: substringMatcher(autoCompleteList),
1479                        limit: Number.MAX_VALUE
1480                    }
1481                ).on('typeahead:selected', function (obj, datum) {
1482
1483                    var lastValue = autoCompleteList[autoCompleteList.length - 1];
1484
1485                    if (datum.value == lastValue && showAdditionalInfo) {
1486                        showAdditionalInfo();
1487                    } else if (datum.value != lastValue && hideAdditionalInfo) {
1488                        hideAdditionalInfo();
1489                    }
1490                });
1491            }
1492        }
1493
1494        $(".instanda-multi-item #" + autoCompleteQuestionId).on("change", function () {
1495            // set the value in the summary to the value they've just typed in
1496            var inputBox = $(this);
1497
1498            if (jQuery.fn.typeahead) {
1499                $(inputBox).typeahead('val', this.value);
1500            }
1501
1502            // There is a bug in the datepicker where it takes focus from the input box, and then changes the value.
1503            // So we catch the change event, then wait until the value is set, then set the text
1504            setTimeout(function () {
1505
1506                updateMultiItemSummary(inputBox, false, false);
1507
1508            }, 500);
1509
1510        });
1511
1512        document.dispatchEvent(new CustomEvent('autoCompleteQuestionAdded', { detail: autoCompleteQuestionId }));
1513    });
1514
1515}
1516
1517var substringMatcher = function (strs) {
1518    return function findMatches(q, cb) {
1519        var matches = [];
1520
1521        q = q.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
1522        var substrRegex = new RegExp(q, 'i');
1523
1524        $.each(strs, function (i, str) {
1525            if (substrRegex.test(str)) {
1526                matches.push(str);
1527            }
1528        });
1529
1530        cb(matches);
1531    };
1532};
1533
1534
1535
1536function ieButtonFix() {
1537    var buttons = document.getElementsByTagName('button');
1538    for (var i = 0; i < buttons.length; i++) {
1539        //This script does not work if there is already an onclick event defined
1540        if (buttons[i].onclick) continue;
1541
1542        buttons[i].onclick = function () {
1543            for (j = 0; j < this.form.elements.length; j++)
1544                if (this.form.elements[j].tagName == 'BUTTON')
1545                    this.form.elements[j].disabled = true;
1546            this.disabled = false;
1547            this.value = this.attributes.getNamedItem("value").nodeValue;
1548            $(this).parents("form").submit();
1549        };
1550    }
1551}
1552
1553//Address postcode
1554
1555function displayAddressOptions(addressButton, addressData, isAddressSplit) {
1556
1557    "use strict";
1558
1559    var elements = null,
1560        message = "",
1561        selectListButtons = null;
1562
1563    if (addressButton) {
1564
1565        elements = getPostCodeElements(addressButton);
1566
1567        if (elements) {
1568
1569            if (addressData && addressData !== undefined) {
1570
1571                if (addressData.Status) {
1572
1573                    if (addressData.Status.Success === true) {
1574
1575                        selectListButtons = createSelectButtonsAddress(addressData.Results, isAddressSplit);
1576
1577                        var showData8ResultsUnderPostcode = $("#ShowData8UnderPostcode").val();
1578
1579                        if (showData8ResultsUnderPostcode != "undefined" && showData8ResultsUnderPostcode == "True") {
1580                            $(".instanda-address-postcode").append("<div class=\"postcodelookup\">" + selectListButtons + "</div>");
1581                        } else {
1582                            if (typeof elements.parentDiv.length !== "undefined" && elements.parentDiv.length > 1) {
1583                                $(elements.parentDiv[0]).append("<div class=\"postcodelookup\">" + selectListButtons + "</div>");
1584                            } else {
1585                                $(elements.parentDiv).append("<div class=\"postcodelookup\">" + selectListButtons + "</div>");
1586                            }
1587                        }
1588                    }
1589
1590                    // Add the error message
1591                    if (addressData.Status.ErrorMessage && addressData.Status.ErrorMessage.length !== 0) {
1592
1593                        message += addressData.Status.ErrorMessage;
1594                        setPostCodeInputValidState(elements.postCode, false);
1595                    }
1596
1597                    // Add the warning message
1598                    if (addressData.Status.WarningMessage && addressData.Status.WarningMessage.length !== 0) {
1599
1600                        if (message && message.length !== 0) {
1601                            // Append two new line breaks
1602                            message += "\n\n";
1603                        }
1604
1605                        message += "Warning: " + addressData.Status.WarningMessage;
1606                    }
1607                }
1608            }
1609        }
1610    }
1611
1612    if (message && message.length !== 0) {
1613        alert(message);
1614    }
1615}
1616
1617function getPostCodeElements(element) {
1618
1619    const questionItemClass = ".questionItem";
1620    const instandaQuestionItemClass = ".instanda-question-item";
1621
1622    var $element = $(element);
1623
1624    var postcodeTextboxSelector = $element.data('postcode');
1625
1626    return {
1627
1628        parentDiv: $element
1629            .closest(questionItemClass),
1630
1631        textBoxes: $element
1632            .closest(questionItemClass)
1633            .children("input"),
1634
1635        addressLine1: $element
1636            .closest(instandaQuestionItemClass)
1637            .find(".instanda-address-line-1 Input"),
1638
1639        addressLine2: $element
1640            .closest(instandaQuestionItemClass)
1641            .find(".instanda-address-line-2 input"),
1642
1643        buildingNumber: $element
1644            .closest(instandaQuestionItemClass)
1645            .find(".instanda-address-building-number Input"),
1646
1647        buildingName: $element
1648            .closest(instandaQuestionItemClass)
1649            .find(".instanda-address-building-name Input"),
1650
1651        street: $element
1652            .closest(instandaQuestionItemClass)
1653            .find(".instanda-address-street-name Input"),
1654
1655        locality: $element
1656            .closest(instandaQuestionItemClass)
1657            .find(".instanda-address-locality Input"),
1658
1659        city: $element
1660            .closest(instandaQuestionItemClass)
1661            .find(".instanda-address-city input"),
1662
1663        county: $element
1664            .closest(instandaQuestionItemClass)
1665            .find(".instanda-address-county input"),
1666
1667        postCode: $('#' + postcodeTextboxSelector)[0]
1668    };
1669}
1670
1671function lookupAddressByPostCode(addressButton, questionId, postCodeIsBlankMessage, lookUpServiceNotAvailableMessage, isAddressSplit) {
1672
1673    "use strict";
1674
1675    var $addressButton = $(addressButton),
1676        addressData = null,
1677        elements = null,
1678        postCode = "";
1679
1680    if ($addressButton) {
1681
1682        elements = getPostCodeElements($addressButton);
1683
1684        if (elements) {
1685
1686            if (elements.postCode) {
1687                postCode = elements.postCode.value;
1688                setPostCodeInputValidState(elements.postCode, true);
1689            }
1690
1691            // Clear the results from any previous search
1692            $(elements.parentDiv)
1693                .find(".postcodelookup")
1694                .remove();
1695
1696            if (postCode.length === 0) {
1697
1698                // Notify the user that the postcode has not been specified
1699                if (!postCodeIsBlankMessage || postCodeIsBlankMessage.length === 0) {
1700                    postCodeIsBlankMessage = "Please enter the postcode";
1701                }
1702
1703                setPostCodeInputValidState(elements.postCode, false);
1704                alert(postCodeIsBlankMessage);
1705            } else {
1706
1707                $addressButton.prop("disabled", true);
1708
1709                var editButton = $(elements.parentDiv).find('.address-search-edit');
1710                if (editButton.length === 1) {
1711                    editButton.prop("disabled", true);
1712                }
1713
1714                $.ajax({
1715                    url: 'GetAddressListForPostcode?postcode=' + postCode + '&questionid=' + questionId,
1716                    dataType: "json",
1717                    success: function (data) {
1718                        addressData = data;
1719                        displayAddressOptions($addressButton, addressData, isAddressSplit);
1720                        $(elements.parentDiv).find('.single-line-address').hide();
1721                    },
1722                    error: function (XMLHttpRequest, textStatus, errorThrown) {
1723                        alert(lookUpServiceNotAvailableMessage);
1724                    },
1725                    complete: function (jqXHR, textStatus) {
1726
1727                        $addressButton.prop("disabled", false);
1728
1729                        if (editButton.length === 1) {
1730                            editButton.prop("disabled", false);
1731                        }
1732                    }
1733                });
1734            }
1735        }
1736    }
1737}
1738
1739function setPostCodeInputValidState(postCodeInput, isValid) {
1740
1741    if (postCodeInput) {
1742
1743        if (isValid === false) {
1744            // Ensure the bootstrap error validation class is removed
1745            $(postCodeInput).addClass("input-validation-error");
1746        } else {
1747            // Apply the bootstrap error validation class
1748            $(postCodeInput).removeClass("input-validation-error");
1749        }
1750    }
1751}
1752
1753function PostcodeAddressUpdateAndClose(elementButton) {
1754    //Get the parent div
1755    var elements = getPostCodeElements(elementButton);
1756    var singleLineAddress = $(elements.parentDiv).find('.single-line-address');
1757
1758    if ($(elementButton)[0].value != "none") {
1759        var selectedValue = $(elementButton)[0].value;
1760        var addressLines = selectedValue.split('#');
1761
1762        elements.addressLine1.val('');
1763        elements.addressLine2.val('');
1764        elements.buildingNumber.val('');
1765        elements.buildingName.val('');
1766        elements.street.val('');
1767        elements.locality.val('');
1768        elements.city.val('');
1769        elements.county.val('');
1770
1771        if (addressLines[0]) {
1772            addressLines[0] = toTitleCase(addressLines[0]);
1773            elements.buildingNumber.val(addressLines[0]);
1774        }
1775        if (addressLines[1]) {
1776            addressLines[1] = toTitleCase(addressLines[1]);
1777            elements.buildingName.val(addressLines[1]);
1778        }
1779        if (addressLines[2]) {
1780            addressLines[2] = toTitleCase(addressLines[2]);
1781            elements.street.val(addressLines[2]);
1782        }
1783        if (addressLines[3]) {
1784            addressLines[3] = toTitleCase(addressLines[3]);
1785            elements.locality.val(addressLines[3]);
1786        }
1787
1788        if (addressLines[4]) {
1789            elements.addressLine1.val(addressLines[4]);
1790        }
1791
1792        // handle address line 2
1793        if (addressLines[5] && addressLines[6] && addressLines[7]) {
1794            elements.addressLine2.val(addressLines[5] + ', ' + addressLines[6] + ', ' + addressLines[7]);
1795        } else if (addressLines[5] && addressLines[6]) {
1796            elements.addressLine2.val(addressLines[5] + ', ' + addressLines[6]);
1797        } else if (addressLines[5] && addressLines[7]) {
1798            elements.addressLine2.val(addressLines[5] + ', ' + addressLines[7]);
1799        } else if (addressLines[5]) {
1800            elements.addressLine2.val(addressLines[5]);
1801        } else if (addressLines[6] && addressLines[7]) {
1802            elements.addressLine2.val(addressLines[6] + ', ' + addressLines[7]);
1803        } else if (addressLines[6]) {
1804            elements.addressLine2.val(addressLines[6]);
1805        } else if (addressLines[7]) {
1806            elements.addressLine2.val(addressLines[7]);
1807        }
1808
1809        if (addressLines[8]) {
1810            elements.city.val(addressLines[8]);
1811        }
1812
1813        elements.county.val(addressLines[9]);
1814
1815        // make sure the change event is triggered
1816        $.each(elements, function () {
1817            $(this).change();
1818        });
1819
1820        if (typeof singleLineAddress != "undefined") {
1821            // combine building number/name & street into the same address part for the comma delimited display
1822            var fullAddress = addressLines;
1823            fullAddress[0] = fullAddress[0] + " " + fullAddress[1] + " " + fullAddress[2];
1824            fullAddress[0] = $.trim(fullAddress[0].replace(/\s\s+/g, ' '));
1825            fullAddress[1] = "";
1826            fullAddress[2] = "";
1827
1828            singleLineAddress.val(fullAddress.filter(n => n).join(", "))
1829        }
1830    }
1831
1832    if (typeof singleLineAddress != "undefined" && singleLineAddress.val()) {
1833        singleLineAddress.show();
1834    }
1835
1836    //Remove all the radio boxes
1837    var showData8ResultsUnderPostcode = $("#ShowData8UnderPostcode").val();
1838
1839    if (showData8ResultsUnderPostcode != "undefined" && showData8ResultsUnderPostcode == "True") {
1840        $(".instanda-address-postcode").children(".postcodelookup").slideUp();
1841    } else {
1842        $(elements.parentDiv).children(".postcodelookup").slideUp();
1843    }
1844}
1845
1846
1847
1848function createSelectButtonsAddress(data, isAddressSplit) {
1849    var buttonStrings = "";
1850    for (var i in data) {
1851        var button = "<button value=\"";
1852        var addressLines = data[i].Address.Lines;
1853        var rawAddress = data[i].RawAddress;
1854
1855        var buttonValue = '';
1856        var rawAddressIsSet = isSet(rawAddress);
1857
1858        if (isAddressSplit && rawAddressIsSet && (isSet(rawAddress.BuildingNumber) || isSet(rawAddress.SubBuildingName))) {
1859            var subBuildingName = isSet(rawAddress.SubBuildingName) ? rawAddress.SubBuildingName : "";
1860            var buildingNumber = isSet(rawAddress.BuildingNumber) && rawAddress.BuildingNumber !== 0 ? rawAddress.BuildingNumber : "";
1861
1862            if (subBuildingName !== "" && buildingNumber !== "") {
1863                subBuildingName += " ";
1864            }
1865
1866            buttonValue += subBuildingName + buildingNumber + '#';
1867        } else {
1868            buttonValue += '#';
1869        }
1870
1871        if (isAddressSplit && rawAddressIsSet && isSet(rawAddress.BuildingName)) {
1872            buttonValue += rawAddress.BuildingName + '#';
1873        } else {
1874            buttonValue += '#';
1875        }
1876
1877        if (isAddressSplit && rawAddressIsSet && (isSet(rawAddress.ThoroughfareName) || isSet(rawAddress.ThoroughfareDesc))) {
1878            var thoroughfareName = isSet(rawAddress.ThoroughfareName) ? rawAddress.ThoroughfareName : "";
1879            var thoroughfareDesc = isSet(rawAddress.ThoroughfareDesc) && thoroughfareName !== ""
1880                ? " " + rawAddress.ThoroughfareDesc : rawAddress.ThoroughfareDesc;
1881            buttonValue += thoroughfareName + thoroughfareDesc + '#';
1882        } else {
1883            buttonValue += '#';
1884        }
1885
1886        if (isAddressSplit && rawAddressIsSet && isSet(rawAddress.DependentLocality)) {
1887            buttonValue += rawAddress.DependentLocality + '#';
1888        } else {
1889            buttonValue += '#';
1890        }
1891
1892        if (!isAddressSplit && addressLines.length > 0 && addressLines[0]) {
1893            buttonValue += addressLines[0] + '#';
1894        } else {
1895            buttonValue += '#';
1896        }
1897
1898        if (!isAddressSplit && addressLines.length > 1 && addressLines[1]) {
1899            buttonValue += addressLines[1] + '#';
1900        } else {
1901            buttonValue += '#';
1902        }
1903
1904        if (!isAddressSplit && addressLines.length > 2 && addressLines[2]) {
1905            buttonValue += addressLines[2] + '#';
1906        } else {
1907            buttonValue += '#';
1908        }
1909
1910        if (!isAddressSplit && addressLines.length > 3 && addressLines[3]) {
1911            buttonValue += addressLines[3] + '#';
1912        } else {
1913            buttonValue += '#';
1914        }
1915
1916        if (addressLines.length > 4 && addressLines[4]) {
1917            buttonValue += addressLines[4] + '#';
1918        } else {
1919            buttonValue += '#';
1920        }
1921
1922        if (addressLines.length > 5 && addressLines[5]) {
1923            buttonValue += addressLines[5] + '#';
1924        } else {
1925            buttonValue += '#';
1926        }
1927
1928        if (addressLines.length > 6 && addressLines[6]) {
1929            buttonValue += addressLines[6] + '#';
1930        } else {
1931            buttonValue += '#';
1932        }
1933
1934        button += buttonValue;
1935        button = button + "\" onclick=\"PostcodeAddressUpdateAndClose(this);return false;\">Select</button>&nbsp;" + addressLines.join(" ") + "<br/>";
1936        buttonStrings = buttonStrings + button;
1937    }
1938
1939    buttonStrings += "<button value=\"none\" onclick=\"PostcodeAddressUpdateAndClose(this);return false;\">None of the above</button><br/>";
1940
1941    return buttonStrings;
1942}
1943
1944//Working
1945function hierarchyFindNode(hierarchy, choiceOptions, currentNode) {
1946
1947    "use strict";
1948
1949    var nameOfNodeToFind = "",
1950        foundNode = null,
1951        i = 0;
1952
1953    if (hierarchy && hierarchy.length !== 0) {
1954
1955        nameOfNodeToFind = hierarchy[0] || "";
1956
1957        if (nameOfNodeToFind && nameOfNodeToFind.length !== 0) {
1958
1959            if (currentNode && typeof (currentNode) != undefined) {
1960                if (currentNode.SubHierarchy && currentNode.SubHierarchy.length !== 0) {
1961                    for (i = 0; i < currentNode.SubHierarchy.length; i++) {
1962
1963                        if (decodedString(currentNode.SubHierarchy[i].ValueEncoded.trim().toLowerCase()) === decodedString(nameOfNodeToFind.trim().toLowerCase())) {
1964                            foundNode = currentNode.SubHierarchy[i];
1965                            break;
1966                        }
1967                    }
1968                }
1969            } else {
1970                for (i = 0; i < choiceOptions.length; i++) {
1971                    if (decodedString(choiceOptions[i].ValueEncoded.trim().toLowerCase()) === decodedString(nameOfNodeToFind.trim().toLowerCase())) {
1972                        foundNode = choiceOptions[i];
1973                        break;
1974                    }
1975                }
1976
1977                if (foundNode !== null && hierarchy.length > 1) {
1978                    return hierarchyFindNode(hierarchy.slice(1), choiceOptions, foundNode);
1979                }
1980
1981                return foundNode;
1982            }
1983
1984            if (foundNode !== undefined && hierarchy.length > 1) {
1985                return hierarchyFindNode(hierarchy.slice(1), choiceOptions, foundNode);
1986            }
1987        }
1988    } else {
1989        throw "hierarchy was not initialised when it needed to be.";
1990    }
1991
1992    return foundNode;
1993}
1994
1995//Decode function fix for INS-3747 
1996function decodedString(str) {
1997    var parser = new DOMParser;
1998    return parser.parseFromString(str, 'text/html').body.textContent.toLowerCase();
1999}
2000
2001//Returns a hierarchy object or undefined if not found
2002function choiceHierarchyFindNode(level, value, choiceOptions) {
2003    for (var i = 0; i < choiceOptions.length; i++) {
2004        if (choiceOptions[i].Level == level && choiceOptions[i].ValueEncoded == value) {
2005            return choiceOptions[i];
2006        } else if (choiceOptions[i].SubHierarchy.length > 0) {
2007            var option = choiceHierarchyFindNode(level, value, choiceOptions[i].SubHierarchy);
2008            if (option != undefined) {
2009                return option;
2010            }
2011        }
2012    }
2013    return undefined;
2014}
2015
2016function removeSelectListOptions($element) {
2017
2018    "use strict";
2019
2020    if ($element && $element.length !== 0) {
2021
2022        $element
2023            .children()
2024            .remove()
2025            .end()
2026            .append("<option value=\"\" selected=\"true\">Please select</option>");
2027    }
2028}
2029
2030function removeRadioButtonListOptions($element) {
2031
2032    "use strict";
2033
2034    if ($element && $element.length !== 0) {
2035
2036        $element
2037            .children()
2038            .remove()
2039            .end();
2040    }
2041}
2042
2043function addSelectListOptions($selectElement, options, selectedValue, size) {
2044
2045    "use strict";
2046
2047    var optionHTML = "",
2048        i = 0;
2049
2050    if (options.length !== 0) {
2051
2052        if ($selectElement && $selectElement.length !== 0) {
2053
2054            if (size < 1) {
2055                size = options.length;
2056            }
2057
2058            var labelId = $selectElement.data('labelid');
2059
2060            $selectElement.show();
2061            $('#' + labelId).show();
2062
2063            $selectElement.attr('size', size);
2064
2065            for (i = 0; i < options.length; i++) {
2066
2067                optionHTML = "";
2068                optionHTML += "<option";
2069                optionHTML += " value=\"" + options[i].ValueEncoded.trim() + "\"";
2070
2071                if (options[i].ValueEncoded.trim().toLowerCase() === selectedValue.trim().toLowerCase()) {
2072                    optionHTML += " selected=\"true\"";
2073                }
2074
2075                optionHTML += ">";
2076                optionHTML += options[i].Value.trim();
2077                optionHTML += "</option>";
2078
2079                $selectElement
2080                    .append(optionHTML);
2081            }
2082        }
2083    }
2084}
2085
2086function addAutoCompleteListOptions($selectElement, options, selectedValue, size, placeholder, functionNameSuffix) {
2087
2088    "use strict";
2089
2090    var optionHTML = "",
2091        i = 0,
2092        displayOptions = [];
2093
2094    if (options.length !== 0) {
2095
2096        if ($selectElement && $selectElement.length !== 0) {
2097
2098            if (size < 1) {
2099                size = options.length;
2100            }
2101
2102            $selectElement.show();
2103
2104            $selectElement.attr('size', size);
2105
2106            for (i = 0; i < options.length; i++) {
2107
2108                optionHTML = "";
2109                optionHTML += "<option";
2110                optionHTML += " value=\"" + options[i].ValueEncoded.trim() + "\"";
2111
2112                if (options[i].ValueEncoded.trim().toLowerCase() === selectedValue.trim().toLowerCase()) {
2113                    optionHTML += " selected=\"true\"";
2114                }
2115
2116                optionHTML += ">";
2117                optionHTML += options[i].Value.trim();
2118                optionHTML += "</option>";
2119
2120                $selectElement
2121                    .append(optionHTML);
2122
2123                displayOptions.push(options[i].Value.trim());
2124            }
2125        }
2126    }
2127
2128    window["renderAutoCompleteQuestion" + functionNameSuffix]($selectElement[0].id, displayOptions, selectedValue, $selectElement[0].name, placeholder);
2129}
2130
2131function updateMultiItemSummary(elementId, removeVal, isRadioBtn) {
2132
2133    var inputBox;
2134    var inputBoxId;
2135
2136    //alert('element is :' + typeof (elementId));
2137
2138    if (!isRadioBtn)
2139        isRadioBtn = $(elementId).is(':radio');
2140
2141    if (isRadioBtn) {
2142        inputBox = typeof(elementId) === "string" ? $("#" + elementId) : $(elementId);
2143
2144        if (inputBox.data("newid"))
2145            inputBoxId = inputBox.data("newid").toString();
2146        else
2147            inputBoxId = inputBox.attr("id").toString();
2148    }
2149    else {
2150        inputBox = elementId;
2151        inputBoxId = elementId.attr("id").toString();
2152    };
2153
2154    //only set the summary box if the input id is valid
2155    if (typeof inputBox !== "undefined") {
2156        try {
2157
2158            var multiItemRoot = inputBoxId.substring(0, inputBoxId.indexOf('_')).trim();
2159            var multiItemSummaryListRadioHeadings = [];
2160
2161            //get all the visible multi-item summary headings
2162            $('.instanda-multi-item-summary-item .instanda-multi-item-summary-answer:visible').each(function () {
2163
2164                var multiItemId = $(this).prop("id").toString();
2165                var multiItemIndex = multiItemId.substring(multiItemId.indexOf('MultiItem'), multiItemId.length);
2166                multiItemIndex = multiItemIndex.substr(0, multiItemIndex.indexOf('_')).replace("MultiItem", "");
2167
2168                // filter the list so we get the correct index of the input field                    
2169                if (multiItemId.indexOf(multiItemRoot) >= 0) {
2170                    multiItemSummaryListRadioHeadings.push($(this).prop("id"));
2171                }
2172
2173            });
2174
2175            //check which heading the input box needs to populate
2176            $.each(multiItemSummaryListRadioHeadings, function (index, value) {
2177
2178                var check = value.toLowerCase();
2179                var inputName = inputBoxId.toString();
2180                inputName = inputName.toLowerCase();
2181
2182                if (check.endsWith(inputName)) {
2183                    //update the multi-item summary view
2184                    if (removeVal != true) {
2185                        $("#" + value).text(inputBox.val());
2186                    } else {
2187                        $("#" + value).text("...");
2188                    }
2189                }
2190            });
2191
2192        } catch (error) { }
2193    }
2194}
2195
2196function deselectRadioButtonIfSelected(group, elementId) {
2197
2198    if ($(group).attr('previousSelectedRadioButton') == elementId) {
2199        $('#' + elementId).prop('checked', false);
2200        $(group).removeAttr('previousSelectedRadioButton');
2201        updateMultiItemSummary(elementId, true, true)
2202    } else {
2203        $(group).attr('previousSelectedRadioButton', elementId);
2204        updateMultiItemSummary(elementId, false, true)
2205    }
2206}
2207
2208function addRadioButtonListOptions(name, $selectElement, options, selectedValue, prefix) {
2209
2210    "use strict";
2211
2212    var optionHTML = "",
2213        i = 0;
2214
2215    if (options.length !== 0) {
2216
2217        if ($selectElement && $selectElement.length !== 0) {
2218
2219            var labelId = $selectElement.data('labelid');
2220
2221            $selectElement.show();
2222            $('#' + labelId).show();
2223
2224            for (i = 0; i < options.length; i++) {
2225
2226                var inputId = name + "_radio_" + (i + 1);
2227                var radioButtonName = $($selectElement).data('name') || name;
2228
2229                optionHTML = "<div class='radio instanda-question-input instanda-question-radio-hierarchy-parent' id='" + name + "_radio_wrapper_" + (i + 1) + "'>";
2230                optionHTML += "<label> <input id='" + inputId + "' type='radio' class='instanda-hierarchy-input" + prefix + " instanda-question-radio-hierarchy' name='" + radioButtonName + "' data-newid='" + name + "'";
2231                optionHTML += " value=\"" + options[i].ValueEncoded.trim() + "\" onClick=\"deselectRadioButtonIfSelected('#" + name + "', '" + inputId + "')\"";
2232
2233                if (options[i].ValueEncoded.trim().toLowerCase() === selectedValue.trim().toLowerCase()) {
2234                    optionHTML += " checked=\"checked\"";
2235                }
2236
2237                optionHTML += "/>";
2238                optionHTML += options[i].Value.trim();
2239                optionHTML += "</label> </div>";
2240
2241                $selectElement
2242                    .append(optionHTML)
2243                    ;
2244            }
2245        }
2246    }
2247}
2248
2249function choiceHierarchyAddSelectEvent(variableNamesAsStringArray, tree) {
2250
2251    $("select.instanda-hierarchy-input").on("change", null, function () {
2252        hierarchySelect(this, variableNamesAsStringArray, tree);
2253    });
2254
2255    $("body").on('change', 'input[type=radio].instanda-hierarchy-input', function () {
2256        hierarchySelect(this, variableNamesAsStringArray, tree);
2257    });
2258}
2259
2260function hierarchySelect(self, variableNamesAsStringArray, tree, prefix, placeholder) {
2261
2262    var functionNameSuffix = "";
2263    if (variableNamesAsStringArray && variableNamesAsStringArray.length >= 0)
2264        functionNameSuffix = variableNamesAsStringArray[0];
2265
2266    if (typeof (prefix) === 'undefined') {
2267        prefix = '';
2268    }
2269
2270    var localVariableName = $(self).data('newid') || $(self).attr("id"),
2271        variableLevels = variableNamesAsStringArray,
2272        value = "",
2273        level = null,
2274        existingHierarchy = null,
2275        i = 0,
2276        foundNode = null,
2277        selectedValue = "",
2278        $variablesLevelElement = null;
2279
2280    //Must check to make sure this returns greater than -1
2281    level = $.inArray(localVariableName, variableLevels);
2282    existingHierarchy = [];
2283
2284    if (level < 0) {
2285        level = 0;
2286    }
2287
2288    if (level === 0) {
2289        existingHierarchy[0] = $('#' + variableNamesAsStringArray[0]).val() ||
2290            $("input[data-newid ='" + variableNamesAsStringArray[0] + "']:checked").val();
2291    } else {
2292
2293        for (i = 0; i <= level; i++) {
2294            existingHierarchy[i] = $('#' + variableNamesAsStringArray[i]).val() ||
2295                $("input[data-newid ='" + variableNamesAsStringArray[i] + "']:checked").val();
2296        }
2297    }
2298
2299    foundNode = hierarchyFindNode(existingHierarchy, tree);
2300    var nextLevel = level + 1;
2301    $variablesLevelElement = $("#" + variableLevels[nextLevel]);
2302
2303    if ($variablesLevelElement && $variablesLevelElement.length !== 0) {
2304
2305        for (i = nextLevel; i < variableLevels.length; i++) {
2306            $variablesLevelElement = $("#" + variableLevels[i]);
2307            if ($variablesLevelElement[0]) {
2308                if ($variablesLevelElement[0].className.indexOf("radio") >= 0) {
2309                    removeRadioButtonListOptions($variablesLevelElement);
2310                } else {
2311                    removeSelectListOptions($variablesLevelElement);
2312                }
2313            }
2314        }
2315
2316        $variablesLevelElement = $("#" + variableLevels[nextLevel]);
2317        value = $(self).val() || "";
2318
2319        if (value.length !== 0) {
2320
2321            value = $(self).val() || "";
2322            if (value.length !== 0) {
2323                if (foundNode && foundNode.length !== 0) {
2324
2325                    if (foundNode && foundNode.length !== 0 && value !== "Please select") {
2326
2327                        selectedValue = $('#' + variableNamesAsStringArray[nextLevel]).val() || "";
2328                        if (foundNode && foundNode.SubHierarchyInputType === 0) {
2329                            addSelectListOptions($variablesLevelElement,
2330                                foundNode.SubHierarchy,
2331                                selectedValue.trim(),
2332                                foundNode.SubSize);
2333                        }
2334
2335                        if (foundNode && foundNode.SubHierarchyInputType === 1) {
2336                            addRadioButtonListOptions(variableLevels[nextLevel],
2337                                $variablesLevelElement,
2338                                foundNode.SubHierarchy,
2339                                selectedValue.trim(), prefix);
2340                        }
2341
2342                        if (foundNode && foundNode.SubHierarchyInputType === 2) {
2343                            addAutoCompleteListOptions($variablesLevelElement,
2344                                foundNode.SubHierarchy,
2345                                selectedValue.trim(),
2346                                foundNode.SubSize,
2347                                placeholder,
2348                                functionNameSuffix);
2349                        }
2350
2351                        if (foundNode && foundNode.length !== 0) {
2352                            selectedValue = $('#' + variableNamesAsStringArray[nextLevel]).val() || "";
2353                            selectedValue = $('#' + variableNamesAsStringArray[nextLevel]).val() || "";
2354                        }
2355                    }
2356                }
2357            }
2358        }
2359    }
2360}
2361
2362
2363function DisableButton(jquerySelector) {
2364    $(jquerySelector).attr("disabled", true);
2365    $(jquerySelector).parents("form").submit();
2366}
2367
2368function ImageRadioButtonClick(clickedImage) {
2369    var radioButton = $(clickedImage).prev();
2370    radioButton.trigger("click");
2371    radioButton.trigger("change");
2372    
2373    var group = radioButton.data('group');
2374    var selector = '[data-group="' + group + '"]';
2375
2376    var images = $(selector).next();
2377
2378    images.addClass("deselectedChoiceImage");
2379
2380    $(clickedImage).removeClass("deselectedChoiceImage");
2381}
2382
2383function ShowHelpTextOnFocus(mode) {
2384
2385    if (mode === "OnFocused") {
2386
2387        $(function () {
2388
2389            $('.questionItem').each(function (index, value) {
2390
2391                if ($('.helpText', value).length >= 1) {
2392
2393                    $('input,select,textarea,.instanda-helpIcon', value).on("mouseover", null, function () {
2394
2395                        var self = this;
2396                        var noHelp = $(this).data('no-help');
2397                        if (!noHelp) {
2398                            setTimeout(function () {
2399                                $(self)
2400                                    .parents('.instanda-question-item:first')
2401                                    .find('.instanda-helpText:first')
2402                                    .show();
2403                            }, 500);
2404                        }
2405
2406                    }).on("mouseout", null, function () {
2407                        var self = this;
2408                        setTimeout(function () {
2409                            $(self)
2410                                .parents('.instanda-question-item:first')
2411                                .find('.instanda-helpText:first')
2412                                .hide();
2413                        }, 500);
2414
2415                    });
2416                }
2417            });
2418        });
2419    }
2420}
2421
2422function emailPolicyDocumentPdf(url, packageId, sendTo, quoteRef) {
2423    var data = { packageId: packageId, sendTo: sendTo, quoteRef: quoteRef };
2424
2425    var theCall = $.ajax({
2426        type: 'post',
2427        url: url,
2428        data: data,
2429        error: function (jqXHR, textStatus, errorThrown) {
2430            if (jqXHR.status === 412) {
2431                alert(jqXHR.statusText);
2432            }
2433        }
2434    });
2435}
2436
2437function sendDocumentsByProtocol(url, quoteRef) {
2438    var data = { quoteRef: quoteRef };
2439
2440    var theCall = $.ajax({
2441        type: 'post',
2442        url: url,
2443        data: data,
2444        error: function (jqXHR, textStatus, errorThrown) {
2445            if (jqXHR.status === 412) {
2446                alert(jqXHR.statusText);
2447            }
2448        }
2449    });
2450}
2451
2452var emailStatusInterval = null;
2453var emailQuoteImg = $('#emailQuoteImg');
2454var currentIcon = emailQuoteImg.attr('src');
2455
2456function multiEmailQuoteDocumentPdf(url, sendingIcon) {
2457
2458    genUrl = url;
2459    $('.instanda-email-quote-link').click(function (e) {
2460
2461        e.preventDefault();
2462
2463        let ctrl = $(this);
2464        ctrl.attr('src', sendingIcon);
2465        ctrl.off().text('SENDING EMAIL PLEASE WAIT ...');
2466        let spinner = ShowWaitingAnimation();
2467        toastr.clear();
2468        statusId = guidGenerator();
2469        methodName = 'EmailQuoteDocument';
2470
2471        let quoteRef = ctrl.data('quoteref');
2472        let packageId = ctrl.data('packageid');
2473        let controlId = ctrl[0].id;
2474
2475        emailQuote(quoteRef, packageId, 'EmailQuoteDocument', multiEmailQuoteDocumentPdfCallBack(controlId, spinner));
2476    });
2477}
2478
2479function multiEmailQuoteDocumentPdfCallBack(controlId, spinner) {
2480
2481    return function () {
2482
2483        if (controlId)
2484            $("#" + controlId).text('EMAIL SENT').css("pointer-events", 'none');
2485
2486        if (spinner)
2487            HideWaitingAnimation(spinner);
2488    }
2489}
2490
2491async function emailQuoteDocumentPdf(url, sendingIcon) {
2492    const emailQuotelink = $('#emailQuoteLinkLink');
2493    const emailQuoteImg = $('#emailQuoteImg');
2494
2495    // Ensure only one click handler
2496    emailQuotelink.off('click').on('click', async (e) => {
2497        e.preventDefault();
2498
2499        const params = new URLSearchParams(url.split('?')[1]);
2500        const encryptedQuoteRef = params.get('quoteRef');
2501
2502        const common = new Instanda.Common();
2503
2504        try {
2505            // Await the lock check
2506            const result = await common.KeepLockOnPolicyPromise(encryptedQuoteRef);
2507
2508            //INP-7519 - if the policy got locked by another user, the page gets refreshed and that will trigger read only mode
2509            if (result?.success === false) {
2510                location.reload();
2511                return;
2512            }
2513
2514        } catch (err) {
2515            console.error('Lock check failed', err);
2516        }
2517
2518        // Show sending email UI
2519        emailQuoteImg.attr({ src: sendingIcon, alt: 'Sending...' });
2520        emailQuotelink.off().text('SENDING EMAIL PLEASE WAIT ...');
2521        ShowWaitingAnimation();
2522        toastr.clear();
2523
2524        // Set globals (consider refactoring later to avoid globals)
2525        statusId = guidGenerator();
2526        methodName = 'EmailQuoteDocument';
2527        pdfUrl = url;
2528        genUrl = url;
2529
2530        // Start document generation
2531        startDocGen("email", emailQuotelink);
2532    });
2533}
2534
2535function ShowWaitingAnimation(timeout) {
2536    $("#WaitingOpaqueBox").show();
2537    $("#WaitingAnimationGraphic").show();
2538    var opts = {
2539        lines: 12, // The number of lines to draw
2540        length: 15, // The length of each line
2541        width: 5, // The line thickness
2542        radius: 12, // The radius of the inner circle
2543        color: '#999', // #rgb or #rrggbb
2544        speed: 1, // Rounds per second
2545        trail: 60, // Afterglow percentage
2546        shadow: false // Whether to render a shadow
2547    };
2548    var target = document.getElementById('WaitingAnimationGraphic');
2549    window.globalSpinner = new Spinner(opts).spin(target);
2550    if (timeout === undefined) {
2551        timeout = 5 * 60 * 1000;
2552    }
2553    setTimeout(HideWaitingAnimation, timeout);
2554
2555    return window.globalSpinner;
2556}
2557
2558function HideWaitingAnimation(spinner) {
2559    $("#WaitingOpaqueBox").hide();
2560    $("#WaitingAnimationGraphic").hide();
2561    if (window.globalSpinner) {
2562        window.globalSpinner.spin(false);
2563    }
2564}
2565
2566function showReferralEmailMessage(message, classValue) {
2567    let $container = $('#referralEmail-message-container');
2568    $container.hide();
2569    $('#referralEmail-message').text(message);
2570    $container.removeClass().addClass(classValue);
2571    $container.fadeIn().delay(10000).fadeOut();
2572}
2573
2574function sendReferralEmail(quoteRef, packageId) {
2575    var common = new Instanda.Common();
2576    var lockingFailed = !common.KeepLockOnPolicy(quoteRef); 
2577    if (lockingFailed) {
2578        if (window.opener) {
2579            window.opener.location.reload();
2580        }
2581        else {
2582            location.reload();
2583        }
2584    }
2585    else {
2586        var url = "/Public/SendReferralNotificationToUnderWriter?quoteRef=" + quoteRef + "&packageId=" + packageId;
2587        $.ajaxSettings.cache = false;
2588        $.ajax({
2589            type: 'get',
2590            url: url,
2591            success: function (data) {
2592                if (data.ResponseMessage != "EmailSentOk") {
2593                    if (data.RedirectToDashboard == false) {
2594                        redirectToRetrieveQuote(false, data.ErrorMessage);
2595                    } else {
2596                        redirectToAgentDashboard(false, data.ErrorMessage);
2597                    }
2598                } else {
2599                    if (data.RedirectToDashboard == false) {
2600                        redirectToRetrieveQuote(true, '');
2601                    } else {
2602                        redirectToAgentDashboard(true, '');
2603                    }
2604                }
2605            },
2606            error: function (data) {
2607                if (data.status === 412) {
2608                    alert(data.statusText + ' (end users will not see this message).');
2609                } else if (data.status != 0) {
2610                    redirectToRetrieveQuote(false);
2611                }
2612            }
2613        });
2614    }
2615}
2616
2617function redirectToRetrieveQuote(success, message) {
2618    window.location.href = "/Public/RetrieveQuote?showEmailNotification=true&emailSuccess=" + success + "&message=" + message;
2619}
2620
2621function redirectToAgentDashboard(success, message) {
2622    window.location.href = "/Public/AgentDashboard?showEmailNotification=true&emailSuccess=" + success + "&message=" + message;
2623}
2624
2625function showNotesDialog(quoteRef, unencryptedQuoteRef, readOnly) {
2626    var notesDialog = "#notesPopupDialog" + quoteRef;
2627
2628    var onDone;
2629
2630    if (!isResponsiveTheme) {
2631        if (readOnly === true) {
2632            onDone = function () {
2633                var textAreaValue = $('textarea[name="notes"]').val();
2634                $('textarea[name="notes"]').val("");
2635                $(notesDialog).dialog({
2636                    dialogClass: "no-close",
2637                    buttons: [
2638                        {
2639                            text: "Cancel",
2640                            click: function () {
2641                                $(this).dialog("close");
2642                            }
2643                        }
2644                    ],
2645                    minWidth: 600,
2646                    maxHeight: 600,
2647                    draggable: false,
2648                    title: "Notes: QuoteRef (" + unencryptedQuoteRef + ")",
2649                    resizable: false,
2650                    open: function () {
2651                        $('textarea[name="notes"]').val(textAreaValue);
2652                    }
2653                });
2654            };
2655        } else {
2656            onDone = function () {
2657                var textAreaValue = $('textarea[name="notes"]').val();
2658                $('textarea[name="notes"]').val("");
2659                $(notesDialog).dialog({
2660                    dialogClass: "no-close",
2661                    buttons: [
2662                        {
2663                            text: "Save & close",
2664                            click: function () {
2665                                if (saveNote(quoteRef)) {
2666                                    $(this).dialog("close");
2667                                }
2668                            }
2669                        },
2670                        {
2671                            text: "Cancel",
2672                            click: function () {
2673                                $(this).dialog("close");
2674                            }
2675                        }
2676                    ],
2677                    minWidth: 600,
2678                    maxHeight: 600,
2679                    draggable: false,
2680                    title: "Notes: QuoteRef (" + unencryptedQuoteRef + ")",
2681                    resizable: false,
2682                    open: function () {
2683                        $('textarea[name="notes"]').val(textAreaValue);
2684                    }
2685                });
2686            };
2687        }
2688
2689        getNotes(quoteRef, onDone);
2690    }
2691}
2692
2693function showPaymentsDialog(quoteRef, unencryptedQuoteRef) {
2694    var boltDialog = "#boltPopupDialog" + quoteRef;
2695
2696    if (!isResponsiveTheme) {
2697        var onDone = function () {
2698            $(boltDialog).dialog({
2699                dialogClass: "no-close",
2700                buttons: [
2701                    {
2702                        text: "Close",
2703                        click: function () {
2704                            $(this).dialog("close");
2705                        }
2706                    }
2707                ],
2708                minHeight: 600,
2709                minWidth: 900,
2710                draggable: true,
2711                title: "Payments : QuoteRef (" + unencryptedQuoteRef + ")",
2712                resizable: false,
2713            });
2714        };
2715        getPayments(onDone);
2716    }
2717}
2718
2719function showReferralNotesDialog(quoteRef, packageId, unencryptedQuoteRef) {
2720    var notesDialog = "#referralNotesPopupDialog" + unencryptedQuoteRef;
2721    if (!isResponsiveTheme) {
2722        var onDone = function () {
2723            $(notesDialog).dialog({
2724                dialogClass: "no-close",
2725                buttons: [
2726                    {
2727                        text: "Save & continue",
2728                        click: function () {
2729                            saveReferralNote(quoteRef, unencryptedQuoteRef);
2730                            sendReferralEmail(quoteRef, packageId);
2731                            $(this).dialog("close");
2732                        }
2733                    },
2734                    {
2735                        text: "Continue without notes",
2736                        click: function () {
2737                            saveReferralNote(quoteRef, unencryptedQuoteRef);
2738                            sendReferralEmail(quoteRef, packageId);
2739                            $(this).dialog("close");
2740                        }
2741                    },
2742                    {
2743                        text: "Cancel",
2744                        click: function () {
2745                            $(this).dialog("close");
2746                        }
2747                    }
2748                ],
2749                minWidth: 600,
2750                maxHeight: 600,
2751                draggable: false,
2752                title: "Referral Notes: QuoteRef (" + unencryptedQuoteRef + ")",
2753                resizable: false
2754            });
2755        };
2756        getReferralNotes(quoteRef, unencryptedQuoteRef, onDone);
2757    }
2758}
2759
2760function getNotes(quoteRef, done) {
2761    var url = "/Public/GetNotes?quoteRef=" + quoteRef;
2762    var notesObj = '#txtNotes' + quoteRef;
2763
2764    var notesDialogPlaceholder = GetNotesDialogPlaceholder();
2765    $.ajax({
2766        cache: false,
2767        url: url,
2768        contentType: "application/json",
2769        success: function (response) {
2770            $(notesObj).html('');
2771           
2772            BuildNotesContainer(notesDialogPlaceholder);
2773            var jsonObj = JSON.parse(response);
2774
2775            if (jsonObj && jsonObj.error) {
2776                notesDialogPlaceholder.html("Error getting notes!");
2777            } else {
2778                $.each(jsonObj.Note, function (i, item) {
2779                    BuildNote(item);
2780                });
2781                notesDialogPlaceholder.append("<br/>");
2782            }
2783
2784            if (done) {
2785                done();
2786            }
2787        },
2788        failure: function (msg) {
2789            notesDialogPlaceholder.html(msg);
2790            if (done) { done(); }
2791        }
2792    });
2793}
2794function BuildNotesContainer(notesPlaceholder) {
2795    notesPlaceholder.html('');
2796    var notesDiv = "<div class='notesContent' style='overflow-y:scroll; max-height:250px; text-align:left'></div>";
2797    notesPlaceholder.append(notesDiv);
2798}
2799
2800function BuildNote(note) {
2801    var noteQuerySelector = ".instanda-notes-dialog-placeholder > .notesContent";
2802    $(noteQuerySelector).append(note.Content).append("<br/>").append("<b><span id='CreatedBy' style='color:grey'>Created By</span> : </b>").append(note.CreatedBy);
2803    $(noteQuerySelector).append("<br/>").append("<b><span id='CreatedOn' style='color:grey'>Created On</span> : </b>").append(note.CreatedOn).append("<hr/>");
2804}
2805
2806function getPayments(done) {
2807    if (done) {
2808        done();
2809    }
2810}
2811
2812function getReferralNotes(quoteRef, unencryptedQuoteRef, done) {
2813    var url = "/Public/GetReferralNotes?quoteRef=" + quoteRef;
2814    var notesObj = '#txtReferralNotes' + unencryptedQuoteRef;
2815
2816    $.ajax({
2817        cache: false,
2818        url: url,
2819        contentType: "application/json",
2820        success: function (response) {
2821            $(notesObj).html('');
2822            $('.instanda-referral-notes-dialog-placeholder').html('');
2823            var notesDiv = "<div class='referralNotesContent' style='overflow-y:scroll; max-height:250px; text-align:left'></div>";
2824            $('.instanda-referral-notes-dialog-placeholder').append(notesDiv);
2825            var jsonObj = JSON.parse(response);
2826            $.each(jsonObj.ReferralNotes, function (i, item) {
2827
2828                $(".referralNotesContent").append(item.Content).append("<br/>").append("<b><span id='CreatedBy' style='color:grey'>Created By</span> : </b>").append(item.CreatedBy);
2829                $(".referralNotesContent").append("<br/>").append("<b><span id='CreatedBy' style='color:grey'>Created On</span> : </b>").append(item.CreatedOn).append("<hr/>");
2830            });
2831
2832            $('.instanda-referral-notes-dialog-placeholder').append("<br/>");
2833
2834            if (done) { done(); }
2835        },
2836        failure: function (msg) {
2837            $('.instanda-referral-notes-dialog-placeholder').html(msg);
2838            if (done) { done(); }
2839        }
2840    });
2841}
2842
2843function saveNote(quoteRef) {
2844    var saveUrl = "/Public/SaveNote?quoteRef=" + quoteRef;
2845    var notesObj = '#txtNotes' + quoteRef;
2846
2847    var notesDialogPlaceholder = GetNotesDialogPlaceholder();
2848
2849    if ($(notesObj).val().length > 1000) {
2850        notesDialogPlaceholder.html('Note not saved! Must not exceed 1000 chars per note!');
2851        return false;
2852    }
2853
2854    $.ajax({
2855        type: 'POST',
2856        url: saveUrl,
2857        data: {
2858            quoteRef: quoteRef,
2859            notes: $(notesObj).val()
2860        },
2861        success: function (response) { //do nothing
2862            notesDialogPlaceholder.html('');
2863            var jsonObj = JSON.parse(response);
2864
2865            if (jsonObj && jsonObj.error) {
2866                alert("There was error appending the notes to the database. Please try again.");
2867            }
2868
2869            $(notesObj).val('');
2870        },
2871        error: function () { alert("There was error appending the notes to the database. Please try again."); }
2872    });
2873
2874    return true;
2875}
2876
2877function saveReferralNote(quoteRef, unencryptedQuoteRef) {
2878
2879    var saveUrl = "/Public/SaveReferralNote?quoteRef=" + quoteRef;
2880    var notesObj = '#txtReferralNotes' + unencryptedQuoteRef;
2881    $.ajax({
2882        type: 'POST',
2883        url: saveUrl,
2884        data: {
2885            quoteRef: quoteRef,
2886            referralNotes: $(notesObj).val()
2887        },
2888        success: function (response) { //do nothing
2889            $('.instanda-referral-notes-dialog-placeholder').html('');
2890            var jsonObj = JSON.parse(response);
2891            $(notesObj).val('');
2892        },
2893        error: function () { alert("There was error appending the referral notes to the database. Please try again."); }
2894    });
2895}
2896
2897function NotesDialogClick(quoteRef, unencryptedQuoteRef, readOnly) {
2898    var link = '[data-action="show-notes-dialog-' + quoteRef + '"]';
2899    $(link).on('click', function (e) {
2900        showNotesDialog(quoteRef, unencryptedQuoteRef, readOnly);
2901        e.preventDefault();
2902        return false;
2903    });
2904}
2905
2906function GetNotesDialogPlaceholder() {
2907    return $('.instanda-notes-dialog-placeholder')
2908}
2909
2910function ResponsiveAgentShowBootstrapModal(encryptedModel) {
2911
2912    var openModalPopup = function () {
2913        $('#notesPopupDialog' + encryptedModel).modal('show');
2914    };
2915
2916    getNotes(encryptedModel, openModalPopup);
2917}
2918
2919function BoltDialogClick(quoteRef, unencryptedQuoteRef) {
2920    var link = '[data-action="show-bolt-dialog-' + quoteRef + '"]';
2921    $(link).on('click', function (e) {
2922        showPaymentsDialog(quoteRef, unencryptedQuoteRef);
2923        e.preventDefault();
2924        if ($('.instanda-payments-dialog-placeholder').is(':visible')) {
2925            setTimeout(function () { $('.instanda-payments-dialog-placeholder').hide(); }, 5000);
2926        }
2927        return false;
2928    });
2929}
2930
2931function ReferralNotesDialogClick(unencryptedQuoteRef, packageId, quoteRef) {
2932    var link = '[data-action="show-referral-notes-dialog-' + quoteRef + '"]';
2933    $(link).on('click', function (e) {
2934        showReferralNotesDialog(quoteRef, packageId, unencryptedQuoteRef);
2935        e.preventDefault();
2936        return false;
2937    });
2938}
2939
2940function showQuoteChangeLogDialog(quoteRef, unencryptedQuoteRef) {
2941    var table = $("#changeLogTable").DataTable({
2942        "ajax": {
2943            "url": "/Public/GetQuoteChangeLog",
2944            "type": "GET",
2945            "contentType": "application/json",
2946            "data": {
2947                "quoteRef": quoteRef
2948            },
2949            "dataType": "json",
2950            "cache": false
2951        },
2952        "columns": [
2953            { "data": "Subject" },
2954            { "data": "Action" },
2955            { "data": "Summary" },
2956            { "data": "Description" }
2957        ]
2958    });
2959
2960    var changeLogDialog = $("#quoteChangeLogDialog");
2961
2962    // Get the window dimensions.
2963    var width = $(window).width();
2964    var height = $(window).height();
2965    // Provide some space between the window edges.
2966    width = width - 50;
2967    height = height - 200;
2968
2969    changeLogDialog.dialog({
2970        dialogClass: "no-close",
2971        buttons: [
2972            {
2973                text: "Close",
2974                click: function () {
2975                    $(this).dialog("close");
2976                    table.destroy();
2977                    $("#changeLogTable").empty();
2978                }
2979            }],
2980        position: { my: "center center", at: "center top", of: window },
2981        width: width,
2982        draggable: false,
2983        title: "Change Log for QuoteRef " + unencryptedQuoteRef,
2984        resizable: false,
2985        height: height
2986    });
2987    $('.no-close.ui-dialog').css({ position: "fixed", top: "20px" });
2988    changeLogDialog.show();
2989}
2990
2991function OpenXmlWorkbookLink(data, ReportTitle) {
2992
2993    var fileName = "";
2994
2995    fileName += ReportTitle.replace(/ /g, "_");
2996
2997    var decoded = $("<div/>").html(data).text();
2998
2999    var uri = 'data:text/xml,' + encodeURIComponent(decoded.trim());
3000
3001    var link = document.createElement("a");
3002    link.href = uri;
3003
3004    link.style = "visibility:hidden";
3005    link.download = fileName + ".xml";
3006
3007    document.body.appendChild(link);
3008    link.click();
3009    document.body.removeChild(link);
3010}
3011
3012function OpenLink(uri) {
3013
3014    var fileName = "xxx";
3015
3016    var link = document.createElement("a");
3017    link.href = uri;
3018
3019    link.style = "visibility:hidden";
3020    link.download = fileName + ".xml";
3021
3022    document.body.appendChild(link);
3023    link.click();
3024    document.body.removeChild(link);
3025}
3026
3027function blockRenewal(packageId, policyNumber, checkbox) {
3028
3029    var linkId = $(checkbox).data('link');
3030    var isChecked = $(checkbox).is(':checked');
3031    var renewLink = $("a[policyNumber='" + policyNumber + "']");
3032
3033    var spinner = ShowWaitingAnimation();
3034    $.post("BlockRenewal?packageId=" + packageId + "&policyNumber=" + policyNumber + "&block=" + isChecked, function () {
3035
3036        if (isChecked) {
3037            $('#' + linkId).hide();
3038            renewLink.hide();
3039            $('[data-action="' + linkId + '"]').hide();
3040        }
3041        else {
3042            $('#' + linkId).show();
3043            renewLink.show();
3044            $('[data-action="' + linkId + '"]').show();
3045        }
3046        HideWaitingAnimation(spinner);
3047    }).fail(function (jqXHR, textStatus, error) {
3048
3049        var errorMessage = "";
3050
3051        if (jqXHR.responseJSON) {
3052            if (jqXHR.responseJSON.IsRedirect) {
3053                window.location.href = jqXHR.responseJSON.RedirectURL;
3054                return;
3055            } else if (jqXHR.responseJSON.HTMLContent) {
3056                var htmlPageContent = jqXHR.responseJSON.HTMLContent;
3057                document.write(htmlPageContent);
3058                document.close();
3059                return;
3060            } else if (jqXHR.responseJSON.ErrorMessage) {
3061                errorMessage = jqXHR.responseJSON.ErrorMessage;
3062            } else {
3063                errorMessage = jqXHR.responseJSON;
3064            }
3065        } else {
3066            if (jqXHR.responseText !== "") {
3067                errorMessage = JSON.parse(jqXHR.responseText);
3068            }
3069            else {
3070                if (error !== "") {
3071                    errorMessage = error;
3072                }
3073                else {
3074                    // We don't have an error message, so we don't know if the policy updated or not
3075                    errorMessage = "Unknown error, please contact technical support";
3076                }
3077            }
3078        }
3079
3080        HideWaitingAnimation(spinner);
3081
3082        showValidationErrors({
3083            ValidationErrors: [ errorMessage ]
3084        });
3085        window.scrollTo(0, 0);
3086    });
3087
3088    return true;
3089}
3090
3091// Save button methods
3092
3093function displaySavedMessage() {
3094
3095    $("#savemsg")
3096        .fadeIn("fast")
3097        .delay(3000)
3098        .fadeOut("slow");
3099}
3100
3101function getUploadProgress(root, statusOnly = false) {
3102    let uploadIdentifier = root.uploadIdentifier.value
3103    
3104    $.get('/Public/GetUploadProgress', {
3105        quoteRef: root.quoteRef,
3106        uploadIdentifier: uploadIdentifier
3107    }, function (data) {
3108        root.uploadProgressContainer.querySelector('#uploadProgressBar').value = data.percentComplete;
3109        
3110        let progressStatusSelector = root.uploadProgressContainer.querySelector('#uploadProgressStatus');
3111        
3112        if(data.statusMessage) {
3113            progressStatusSelector.innerHTML = data.statusMessage;
3114        }
3115        
3116        const miUploadCounts = root.uploadProgressContainer.querySelectorAll(".mi-upload-count");
3117        const miCurrentUploadCounts = root.uploadProgressContainer.querySelectorAll(".mi-current-upload-count");
3118        
3119        if(miUploadCounts.length > 0)
3120        {
3121            if (data.totalRows !== undefined && data.totalRows !== null && data.totalRows > -1) {
3122                miUploadCounts.forEach(function(x) { x.innerHTML = data.totalRows });
3123            } else {
3124                miUploadCounts.forEach(function(x) { x.innerHTML = "--" });
3125            }
3126        }
3127        if(miCurrentUploadCounts.length > 0) 
3128        {
3129            if (data.uploadedRows !== undefined && data.uploadedRows !== null) {
3130                miCurrentUploadCounts.forEach(function(x) { x.innerHTML = data.uploadedRows });
3131            } else {
3132                miCurrentUploadCounts.forEach(function(x) { x.innerHTML = "0" });
3133            }
3134        }
3135        
3136        if (data.isComplete || data.isCancelled) {
3137            if (!statusOnly && data.isComplete && data.success === true) {
3138                const validationSummary = document.querySelector('*[class^="validation-summary"] ul');
3139
3140
3141                if (data.fileToken) {
3142                    document.querySelector("#multi-item-upload-file-token-" + root.questionId).value = data.fileToken;
3143                }
3144
3145                if (data.success === true) {
3146                    
3147                    fetch("/Public/GetMultIItemSummaryView?quoteRef=" + encodeURIComponent(root.quoteRef) +
3148                        "&questionId=" + encodeURIComponent(root.questionId), {
3149                        headers: {
3150                            'X-Requested-With': 'XMLHttpRequest'
3151                        }
3152                    })
3153                        .then(res => { return res.text(); })
3154                        .then(html => {
3155                            const child = document.getElementById("multiItemSummary_" + root.questionId);
3156                            const parent = child.parentElement;
3157                            parent.innerHTML = html;
3158                            initMultiItemUpload(data);
3159                            setupMultiItemAjaxButtons();
3160                            const addButton = document.querySelector("#" + root.variableName + "addButton");
3161                            if(addButton != null) {
3162                                addButton.disabled = data.uploadedRows >= root.maxItems;
3163                            }
3164                        });
3165
3166                } else {
3167                    for (let i = 0; i < data.validationMessages.length; i++) {
3168                        validationSummary.innerHTML = ""
3169                        let message = document.createElement("li")
3170                        message.innerHTML = data.validationMessages[i]
3171                        validationSummary.appendChild(message);
3172                    }
3173
3174                    if (data.validationMessages) {
3175                        root.failureMsg(data.failureMessage, data.validationMessages, data.fileToken);
3176                    }
3177
3178                    if (data.validationFileCreated) {
3179                        document.querySelector("#download-multi-item-validated-file-" + root.questionId).style.display = 'block';
3180                    }
3181                }
3182
3183                root.setControls(true);
3184
3185                root.uploadProgressContainer.style.display = 'none';
3186
3187            } else if(data.isCancelled) {
3188                 fetch("/Public/GetMultIItemSummaryView?quoteRef=" + encodeURIComponent(root.quoteRef) +
3189                            "&questionId=" + encodeURIComponent(root.questionId), {
3190                            headers: {
3191                                'X-Requested-With': 'XMLHttpRequest'
3192                            }
3193                        })
3194                            .then(res => { return res.text(); })
3195                            .then(html => {
3196                                const child = document.getElementById("multiItemSummary_" + root.questionId);
3197                                const parent = child.parentElement;
3198                                parent.innerHTML = html;
3199                                initMultiItemUpload(data);
3200                                setupMultiItemAjaxButtons();
3201                                const addButton = document.querySelector("#" + root.variableName + "addButton"); 
3202                                if(addButton != null) {
3203                                    addButton.disabled = data.uploadedRows >= root.maxItems;
3204                                }
3205                            });
3206            } else if (data.success !== true) {
3207                for (var i = 0; i < data.validationMessages.length; i++) {
3208                    document.querySelector('*[class^="validation-summary"] ul').innerHTML = ""
3209                    let message = document.createElement("li")
3210                    message.innerHTML = data.validationMessages[i]
3211                    document.querySelector('*[class^="validation-summary"] ul').appendChild(message);
3212                }
3213
3214                if (data.validationMessages) {
3215                    root.failureMsg(data.statusMessage, data.validationMessages, data.fileToken);
3216                }
3217
3218                if (data.validationFileCreated) {
3219                    document.querySelector("#download-multi-item-validated-file-" + root.questionId).style.display = 'block';
3220                }
3221
3222                root.uploadProgressContainer.style.display = 'none';
3223
3224                root.setControls(false, true);
3225            }
3226            
3227        } else {
3228            let callback = getUploadProgress.bind(null, root, statusOnly);
3229
3230            setTimeout(callback, 1000);
3231        }
3232    });
3233}
3234
3235function displayErrorMessages(errors) {
3236    if (errors) {
3237
3238        if ($('#TargetPage').length > 0) {
3239            $('#TargetPage').val('');
3240        }
3241
3242        let summaryErrors = '';
3243        for (i = 0; i < errors.length; i++) {
3244            result = errors[i];
3245
3246            if (result.InvalidInputFieldName && result.InvalidInputFieldName.length !== 0 && !/\s/g.test(result.InvalidInputFieldName)) {
3247                const invalidInput = $("#" + result.InvalidInputFieldName);
3248                if (invalidInput.length) {
3249                    invalidInput.addClass("input-validation-error");
3250                    const errorSpan = $("[data-valmsg-for=" + result.InvalidInputFieldName + "]");
3251                    errorSpan.removeClass("field-validation-valid");
3252                    errorSpan.addClass("field-validation-error");
3253                    errorSpan.data("server-side-error", true);
3254                    errorSpan.html(result.ValidationMessages[0]);
3255                }
3256
3257                summaryErrors += '<li>' + result.ValidationMessages[0] + '</li>';
3258            } else if (result.ValidationMessages && result.ValidationMessages.length) {
3259                summaryErrors += '<li>' + result.ValidationMessages[0] + '</li>';
3260            } else if (result.IsException) {
3261                summaryErrors += '<li>' + result.ErrorMessage + '</li>';
3262            } else if (result.IsDeclined) {
3263                summaryErrors += '<li>' + result.Message + '</li>';
3264            }
3265        }
3266
3267        $('*[class^="validation-summary"] ul').html("").append(summaryErrors);
3268        $('.validation-summary-valid').addClass('validation-summary-errors').removeClass('validation-summary-valid');
3269
3270        //necesary to display the error summary 
3271        $('.alert-dismissible').removeClass('hidden');
3272
3273        setTimeout(function () {
3274            $('*[class^="validation-summary"] ul')[0].scrollIntoView(false);
3275        }, 1);
3276    }
3277    else {
3278        $('.validation-summary-errors').addClass('validation-summary-valid').removeClass('validation-summary-errors');
3279        $('.alert-dismissible').addClass('hidden');
3280    }
3281}
3282
3283function clearErrors() {
3284
3285    var $form = $("form");
3286    var $validator = $form.validate();
3287    // get errors 
3288    var $errors = $form.find(".field-validation-error");
3289    // remove the validation messages
3290    //INS-5536 the content of the message has to be cleared
3291    $errors.each(function () {
3292        $(this).html("");
3293    });
3294    $errors.removeClass("field-validation-error");
3295
3296    $errors.addClass("field-validation-valid");
3297    // remove input error classes
3298    var $inputs = $form.find(".input-validation-error");
3299    $inputs.removeClass("input-validation-error");
3300    $validator.resetForm();
3301
3302    //for responsive sites, summary needs to be cleared as well INS-5536
3303    if ($(".validation-summary-errors")[0]) {
3304        $('.alert-dismissible').addClass('hidden');
3305        $('.alert-dismissible ul').html("");
3306    }
3307}
3308
3309function disableFormActionButtonsOnContinue(form) {
3310
3311    form = $(form);
3312    validator.run(form);
3313    form.validate();
3314
3315    if (form.valid() && areInstandaQuestionsValid(form[0])) {
3316        disableFormActionButtons();
3317    }
3318
3319    return true;
3320}
3321
3322const buttonSelectors = {
3323    continueButton: "button[name='continueButton']",
3324    continueInput: "input[name='continueButton']",
3325    backButton: "button[name='backButton']",
3326    backInput: "input[name='backButton']",
3327    backButtonId: "#backButton",
3328    saveButton: "button[name='saveButton']",
3329    saveInput: "input[name='saveButton']",
3330    recalculateButton: "button[name='recalculateButton']",
3331    recalculateInput: "input[name='recalculateButton']"
3332}
3333
3334function disableFormActionButtons() {
3335    for (let buttonSelectorKey in buttonSelectors) {
3336        let button = document.querySelector(buttonSelectors[buttonSelectorKey]);
3337        if (button !== null) {
3338            button.setAttribute("disabled", "disabled");
3339        }
3340    }
3341}
3342
3343function enableFormActionButtons() {
3344    for (let buttonSelectorKey in buttonSelectors) {
3345        let button = document.querySelector(buttonSelectors[buttonSelectorKey]);
3346        if (button !== null) {
3347            button.removeAttribute('disabled');
3348        }
3349    }
3350}
3351
3352function saveAnswersFrom(url, quoteRefInputName, backwardsUrl, savedFromKey, savedFromValue, callback) {
3353    $('<input>').attr({
3354        type: 'hidden',
3355        name: savedFromKey,
3356        value: savedFromValue
3357    }).appendTo('form');
3358
3359    saveAnswers(url, quoteRefInputName, backwardsUrl, callback);
3360}
3361
3362function saveAnswers(url, quoteRefInputName, backwardsUrl, callback) {
3363
3364    disableFormActionButtons();
3365    clearErrors();
3366
3367    if (backwardsUrl != null) {
3368        $('<input>').attr({
3369            type: 'hidden',
3370            name: 'backButtonPressed'
3371        }).appendTo('form');
3372    }
3373
3374    if (window.FormData) {
3375
3376        var formElement = "#instandaquestions";
3377
3378        if ($(formElement).length === 0) {
3379            formElement = "form";
3380        }
3381
3382        var formValues = new FormData($(formElement)[0]);
3383
3384        //INS-5568 CKEditor values need to be extracted and added for ajax calls
3385        if (typeof CKEDITOR !== 'undefined') {
3386            $.each(CKEDITOR.instances, function (index, value) {
3387                if (index === "QuoteReferralNoteEditor") {
3388                    return; // QuoteReferralNoteEditor has its own save functionality
3389                }
3390
3391                try { //values should not already be in formdata but we can try delete, not supported in IE/Edge
3392                    formValues.delete(value.element.$.name);
3393                }
3394                catch (e) { //is IE/Edge
3395                }
3396
3397                formValues.append(value.element.$.name, CKEDITOR.instances[value.name].getData());
3398            });
3399        }
3400
3401
3402        $.ajax({
3403            url: url,
3404            processData: false,
3405            contentType: false,
3406            type: "POST",
3407            data: formValues,
3408            success: function (data, textStatus, jqXHR) {
3409
3410                // update the summary list
3411                $("#ul-instanda-multi-item-summary-answer li span[id^='li_']").each(function () {
3412                    var elementID = $(this).attr("id");
3413                    // remove the "li_" part from id
3414                    var elementInFormID = elementID.substring(3);
3415                    if ($("#" + elementInFormID).val() !== undefined && $("#" + elementInFormID).val() !== "undefined") {
3416                        $("#" + elementID).html($("#" + elementInFormID).val());
3417                    } else {
3418                        // check if it is a radiobutton type
3419                        var elementInForm = $("input[name='" + elementInFormID + "']").filter(":radio").filter(":checked");
3420                        if (elementInForm.length === 1) {
3421                            $("#" + elementID).html(elementInForm.val());
3422                        }
3423                    }
3424                });
3425
3426                if (typeof quoteIsReadOnly !== "undefined" && quoteIsReadOnly === true) {
3427                    location.href = backwardsUrl;
3428                    return;
3429                }
3430                if (jqXHR != null && typeof jqXHR.responseJSON !== "undefined" && jqXHR.responseJSON != null) {
3431
3432                    //Make sure we got a valid response from the controller action
3433                    if (typeof jqXHR.responseJSON.QuoteRef === "undefined") {
3434                        var message = "";
3435                        var errorMessage;
3436                        var skipThrowingException = false;
3437
3438                        //Handling session problems
3439                        if (jqXHR.responseJSON) {
3440                            errorMessage = processQuestionSaveException(jqXHR);
3441                            skipThrowingException = true;
3442                        }
3443
3444                        if (errorMessage == null || errorMessage.length < 1) {
3445                            if (typeof jqXHR.responseText !== 'undefined' && jqXHR.responseText != null
3446                                && jqXHR.responseText.indexOf("Your session has expired") > -1
3447                                || jqXHR.responseText.indexOf('<input type="submit" value="Log On" class="btn btn-green" />') > -1) {
3448                                errorMessage = "Your session has expired.";
3449                                skipThrowingException = true;
3450                            } else {
3451                                errorMessage = "Save call failed to return a valid response.";
3452                            }
3453                        }
3454
3455                        if (errorMessage != null) {
3456                            message = errorMessage;
3457                        }
3458
3459                        $('*[class^="validation-summary"] ul').html("").append("<li>" + message + "</li>");
3460                        $('.validation-summary-valid').addClass('validation-summary-errors').removeClass('validation-summary-valid');
3461
3462                        if (!skipThrowingException) {
3463                            $(buttonSelectors.continueButton).prop('disabled', false);
3464                            $(buttonSelectors.continueInput).prop('disabled', false);
3465                            throw JSON.stringify({ message: 'AJAX call failed to return expected result.', toURL: url, backwardsUrl: backwardsUrl });
3466                        }
3467                    } else {
3468                        displayErrorMessages(jqXHR.responseJSON.Errors);
3469
3470                        setTimeout(function () {
3471                            if (backwardsUrl != null && jqXHR.responseJSON.Errors !== null) {
3472                                if (confirm('Any changes will be lost. Do you wish to continue?')) {
3473                                    $('form').trigger('reinitialize.areYouSure');
3474                                    location.href = backwardsUrl;
3475                                    return;
3476                                }
3477                            }
3478
3479                            $('input[name="' + quoteRefInputName + '"]').val(jqXHR.responseJSON.QuoteRef);
3480                            if (jqXHR.responseJSON.Errors === null || (typeof jqXHR.responseJSON.Errors !== "undefined" && jqXHR.responseJSON.Errors.length === 0)) {
3481                                $('form').trigger('reinitialize.areYouSure');
3482
3483                                if (backwardsUrl != null) {
3484                                    location.href = backwardsUrl;
3485                                } else {
3486                                    displaySavedMessage();
3487                                }
3488                            }
3489                        }, 50);
3490
3491                    }
3492                } else {
3493                    var contentType = jqXHR.getResponseHeader("Content-Type");
3494                    if (contentType && contentType.indexOf("text/html") >= 0) {
3495                        //if it returns html, then probably a redirect happened and most likely caused by the locking (INP-6703) so refresh the page
3496                        location.reload();
3497                    }
3498                    else {
3499                        errorMessage = "Save call failed to return a valid response.";
3500                        var error = { IsException: true, ErrorMessage: errorMessage };
3501                        var errorArray = [error];
3502                        displayErrorMessages(errorArray);
3503                    }
3504                }
3505
3506                if (callback) {
3507                    callback(textStatus);
3508                }
3509            },
3510            error: function (jqXHR, textStatus, errorThrown) {
3511                processQuestionSaveException(jqXHR);
3512            },
3513            complete: function (jqXHR, textStatus) {
3514                enableFormActionButtons();
3515            }
3516        });
3517
3518    } else {
3519        alert("Your browser is not supported!");
3520    }
3521}
3522
3523function processQuestionSaveException(jqXHR) {
3524
3525    var errorMessage = "";
3526
3527    if (typeof jqXHR.responseJSON !== "undefined" && jqXHR.responseJSON !== null) {
3528        if (typeof jqXHR.responseJSON.IsRedirect !== "undefined" && jqXHR.responseJSON.IsRedirect) {
3529            $('form').trigger('reinitialize.areYouSure'); //disable the unsaved changes warning
3530            window.location.href = jqXHR.responseJSON.RedirectURL;
3531            return "redirecting.....";
3532        } else if (typeof jqXHR.responseJSON.HTMLContent !== "undefined" && jqXHR.responseJSON.HTMLContent != null) {
3533            $('form').trigger('reinitialize.areYouSure'); //disable the unsaved changes warning
3534            var htmlPageContent = jqXHR.responseJSON.HTMLContent;
3535            document.write(htmlPageContent);
3536            document.close();
3537            return "redirecting.....";
3538        } else if (typeof jqXHR.responseJSON.ErrorMessage !== "undefined" && jqXHR.responseJSON.ErrorMessage != null) {
3539            errorMessage = jqXHR.responseJSON.ErrorMessage;
3540        } else {
3541            errorMessage = jqXHR.responseJSON;
3542            return errorMessage;
3543        }
3544    } else {
3545        return undefined;
3546    }
3547
3548    var error = { IsException: true, ErrorMessage: errorMessage };
3549    var errorArray = [error];
3550    displayErrorMessages(errorArray);
3551}
3552
3553function MoveToPage(pageName, quoteRef) {
3554    if ($('#TargetPage').length <= 0) {
3555        $('<input>').attr({
3556            type: 'hidden',
3557            id: 'TargetPage',
3558            name: 'TargetPage',
3559            value: pageName
3560        }).appendTo('form');
3561    } else {
3562        $("#TargetPage").val(pageName);
3563    }
3564
3565    $("form").submit(function (e) {
3566        if ($('.field-validation-error:visible').length > 0) {
3567            $("#TargetPage").val("");
3568            $.ajax({
3569                url: "/public/ClearTargetPage/?quoteref=" + quoteRef
3570            });
3571        }
3572    });
3573
3574    if (pageName == '') {
3575        return;
3576    }
3577
3578    if ($(buttonSelectors.continueInput).length > 0) {
3579        ClickButton($(buttonSelectors.continueInput));
3580    } else if ($(buttonSelectors.continueButton).length > 0) {
3581        ClickButton($(buttonSelectors.continueButton));
3582    } else if ($("button[name='quoteButton']").length > 0) {
3583        ClickButton($("button[name='quoteButton']"));
3584    } else if ($("input[value='Continue']").length > 0) {
3585        ClickButton($("input[value='Continue']"));
3586    } else {
3587        $.ajax({
3588            url: "/public/ClearTargetPage/?quoteref=" + quoteRef
3589        });
3590
3591        $("#TargetPage").val("");
3592    }
3593}
3594
3595//For coping with JavaScript redirects in IE where the UrlReferrer needs to be known by the target.
3596//UrlReferrer will be null in such cases so build a link (<a>) element for the target instead and click it.
3597function redirectForIE(targetUrl) {
3598    var link = document.createElement('a');
3599    link.href = targetUrl;
3600    document.body.appendChild(link);
3601    link.click();
3602}
3603
3604function ClickButton($button) {
3605    setTimeout(function () {
3606        $button.click();
3607    }, 1);
3608}
3609
3610function PreventDoubleSubmission(form) {
3611    $(form).on('submit', function (e) {
3612        if (form.data('submitted') === true) {
3613            e.preventDefault();
3614        } else if ($('.field-validation-error:has(>span)').not("[data-server-side-error='true']").length == 0) {
3615            form.data('submitted', true);
3616        }
3617    });
3618}
3619
3620function TransferQuote() {
3621    var transferUrl = "/Public/TransferQuote";
3622
3623    $.ajax({
3624        type: 'POST',
3625        url: transferUrl,
3626        data: {
3627            quoteRef: $('#quoteRefToTrasnfer').val(),
3628            salesPersonId: $('#TransferToAgent').val()
3629        },
3630        success: function (response) {
3631            if (response.isSuccess == null) {
3632                alert("There was error changing the agent.");
3633            }
3634        },
3635        error: function () { alert("There was error changing the agent. Please try again."); }
3636    });
3637
3638    return true;
3639}
3640
3641function DeleteUploadedFileFromLink(uploadId, url, antiForgeryToken) {
3642    var linkElement = $("#uploadedFileContainer" + uploadId);
3643    if (linkElement.length) {
3644        $.ajax({
3645            method: "GET",
3646            url: url,
3647            success: function () {
3648                linkElement.slideUp(400, function () {
3649                    $(this).remove();
3650                });
3651            },
3652            error: function () {
3653                alert("Failed to delete file");
3654            }
3655        });
3656    }
3657}
3658
3659function AppendNewDocumentUploadInput(questionId, multiItemPrefix) {
3660    let containerName = "#instanda-document-upload-input-container-" + multiItemPrefix + questionId;
3661    let containerElement = $(containerName);
3662    if (containerElement.length) {
3663        const browseFileText = containerElement.find('#BrowseFilesButtonText').text();
3664        const noFileSelectedText = containerElement.find('#NoFileSelectedText').text();
3665        const fileSelectedText = containerElement.find('#FileSelectedText').text();
3666
3667        let divCount = $(containerName + " > div").length;
3668        let identifier = questionId + '-' + (divCount + 1);
3669        let labelId = multiItemPrefix + "selectedFileLabel" + identifier;
3670        let idAndName = multiItemPrefix + 'DocumentUploadQuestion' + identifier;
3671        let htmlToAppend =
3672            '<div class="instanda-document-upload-input">' +
3673            '<input class="instanda-file-input" id="' + idAndName + '" name="' + idAndName + '" type="file" value>' +
3674            '<input type="hidden" name="uploadedFilesQuestionIds" value="' + questionId + '">' +
3675            '<label for="' + idAndName + '" class="instanda-file-input-label-btn btn btn-default">' + browseFileText + '</label>' +
3676            '<label class="instanda-file-input-selected" id="' + labelId + '">' + noFileSelectedText + '</label>' +
3677            '<span class="field-validation-valid" data-valmsg-for="' + idAndName + '" data-valmsg-replace="true"></span>' +
3678            '</div>';
3679
3680        containerElement.find('.instanda-document-upload-add-btn').before(htmlToAppend);
3681
3682        $('#' + idAndName).change(function () {
3683            if ($(this).val().trim() != "") {
3684                $('#' + labelId).text($(this).val().split('\\').pop() + " (" + fileSelectedText + ")");
3685            } else {
3686                $('#' + labelId).text(noFileSelectedText);
3687            }
3688
3689            let valSpan = $(this).parent().find('.field-validation-error');
3690            if (valSpan && valSpan.length) {
3691                valSpan.addClass('field-validation-valid');
3692                valSpan.removeClass('field-validation-error');
3693            }
3694        });
3695    }
3696}
3697
3698$(function () {
3699    // On entering the screen page load
3700    setRadioButtonClasses();
3701
3702    // Radio button clicked after page has loaded
3703    $(document).on('click', 'input[type="radio"]', function () {
3704        if ($(this).prop('checked')) {
3705            $(this).parent('label').addClass('instanda-selected', 300).removeClass('instanda-unselected', 300);
3706        }
3707
3708        $(this).closest('.instanda-question-item, .referral-review-line, .instanda-payment-options').find('input[type="radio"]:not(:checked)').parent('label').addClass('instanda-unselected', 300).removeClass('instanda-selected', 300);
3709    });
3710
3711    // default close must not remove the element from ther DOM, but hide it instead: INS - 5536
3712    $('#innerBody').on('close.bs.alert', function (e) {
3713        if ($(e.target).length > 0) {
3714            e.preventDefault();
3715            $(e.target).addClass('hidden');
3716        }
3717    });
3718});
3719
3720function setRadioButtonClasses() {
3721    var radiosChecked = document.querySelectorAll('input[type="radio"]:checked');
3722    for (var x = 0; x < radiosChecked.length; x++) {
3723        if (radiosChecked[x].parentElement.nodeName === "LABEL") {
3724            radiosChecked[x].parentElement.classList.add("instanda-selected");
3725            radiosChecked[x].parentElement.classList.remove("instanda-unselected");
3726        }
3727    }
3728    var radiosUnchecked = document.querySelectorAll('input[type="radio"]:not(:checked)');
3729    for (var y = 0; y < radiosUnchecked.length; y++) {
3730        if (radiosUnchecked[y].parentElement.nodeName === "LABEL") {
3731            radiosUnchecked[y].parentElement.classList.add("instanda-unselected");
3732            radiosUnchecked[y].parentElement.classList.remove("instanda-selected");
3733        }
3734    }
3735}
3736
3737function CarBrandsAndModelsYearChange(yearOfManufactureSelector, brandVariableSelector, brandVariableName, failureDivSelector, isInitialCall) {
3738    if ($(yearOfManufactureSelector).val().length === 4) {
3739
3740        var url = '/Public/GetCABrands?year=' + $(yearOfManufactureSelector).val(),
3741            carBrandsTexts = carBrandsTexts || [],
3742            carBrandsObjects = carBrandsObjects || [];;
3743
3744        $("body").css("cursor", "progress");
3745
3746        var brandVariableNameElementId = brandVariableSelector.replace("#", "");
3747        $('.instanda-question-inner-label-' + brandVariableNameElementId).show();
3748
3749        $.ajax({
3750            url: url,
3751            dataType: 'json',
3752            success: function (data, textStatus, jqXHR) {
3753                console.debug(data);
3754
3755                $(brandVariableSelector).empty();
3756
3757                carBrandsTexts[brandVariableNameElementId] = [];
3758                carBrandsObjects[brandVariableNameElementId] = [];
3759
3760                $.each(data, function (index, value) {
3761                    var selectedClass = "";
3762
3763                    if ($("#Text_".concat(brandVariableNameElementId)).val() === value.name) {
3764                        selectedClass = "selected-brand";
3765                    }
3766
3767                    carBrandsTexts[brandVariableNameElementId].push(value.name);
3768                    carBrandsObjects[brandVariableNameElementId].push(value);
3769
3770                    if ($(brandVariableSelector).is("ul")) {
3771                        $(brandVariableSelector).append(
3772                            $('<li class="list-group-item list-group-item-action">').append(value.name).data({
3773                                id: value.id,
3774                                name: value.name
3775                            }).addClass(selectedClass));
3776                    }
3777                    else if ($(brandVariableSelector).is("select")) {
3778                        let selectedOption = "";
3779
3780                        if (selectedClass !== "")
3781                            selectedOption = "selected";
3782
3783                        $(brandVariableSelector).append(
3784                            $("<option value='".concat(value.name, "' ").concat(selectedOption, " >")).append(value.name).data({
3785                                id: value.id,
3786                                name: value.name
3787                            }).addClass(selectedClass));
3788                    }
3789                    else if ($(brandVariableSelector).hasClass("car-brands-wrapper-radio-".concat(brandVariableNameElementId))) {
3790                        if (value.name !== '') {
3791
3792                            let selectedRadio = "";
3793
3794                            if (selectedClass !== "")
3795                                selectedRadio = "checked";
3796
3797                            $(brandVariableSelector).append(
3798                                $("<input type=\"radio\" id=\"".concat(brandVariableNameElementId, "_radio").concat(value.id, "\" name=\"").concat(brandVariableName, "_radio\" value=\"").concat(value.name, "\" ").concat(selectedRadio, "/>"))
3799                                    .data({
3800                                        id: value.id,
3801                                        name: value.name
3802                                    })
3803                                    .addClass(selectedClass));
3804
3805                            $(brandVariableSelector).append("".concat(value.name, "<br/>"));
3806                        }
3807                    }
3808                });
3809
3810                if ($(brandVariableSelector).is("input:text")) {
3811                    if (!isInitialCall) {
3812                        $(brandVariableSelector).val('');
3813                    }
3814
3815                    if (typeof jQuery.ui !== 'undefined') {
3816                        var options = {
3817                            source: carBrandsTexts[brandVariableNameElementId],
3818                            minLength: 0,
3819                            select: function (event, ui) {
3820                                let brand = carBrandsObjects[brandVariableNameElementId].filter(function (o) {
3821                                    return o.name === ui.item.label;
3822                                })[0];
3823                                $(this).data("id", brand.id);
3824                                $(this).data("name", brand.name);
3825                                $(this).blur();
3826                            }
3827                        };
3828
3829
3830                        $(brandVariableSelector).autocomplete(options);
3831                    }
3832                    else {
3833                        $(brandVariableSelector).typeahead('destroy');
3834
3835                        $(brandVariableSelector).typeahead({
3836                            hint: true,
3837                            highlight: true,
3838                            minLength: 1
3839                        },
3840                            {
3841                                name: 'brands',
3842                                source: substringMatcher(carBrandsTexts[brandVariableNameElementId]),
3843                                limit: Number.MAX_VALUE
3844                            })
3845                            .on('typeahead:selected', function (evt, item) {
3846                                let brand = carBrandsObjects[brandVariableNameElementId].filter(function (o) {
3847                                    return o.name === item;
3848                                })[0];
3849                                $(this).data("id", brand.id);
3850                                $(this).data("name", brand.name);
3851
3852                                $(brandVariableSelector).blur();
3853                            });
3854                    }
3855                }
3856
3857                if (isInitialCall) {
3858                    $(brandVariableSelector).trigger("change:initial");
3859                } else {
3860                    $(brandVariableSelector + " li:first").click();
3861                }
3862
3863                $(failureDivSelector).css("display", "none");
3864                $("*").css("cursor", "");
3865            },
3866            error: function () {
3867                $(failureDivSelector).css("display", "block");
3868                $("*").css("cursor", "");
3869            }
3870        });
3871    }
3872}
3873
3874function CarBrandsAndModelsBrandChange(clickedObject, yearOfManufactureSelector, brandVariableSelector, failureDivSelector, modelVariableSelector, modelVariableName,
3875    bodyTypeVariableName, isInitialCall) {
3876
3877    if ($(yearOfManufactureSelector).val().length !== 4) {
3878        return;
3879    }
3880
3881    var selected = clickedObject !== null ? $(clickedObject).data('id') : null,
3882        carModelsObjects = carModelsObjects || [],
3883        carModelsTexts = carModelsTexts || [];
3884
3885    if (isInitialCall) {
3886        $(brandVariableSelector).find('.selected-brand').removeClass("selected-brand");
3887        var selectedName = $("#Text_" + brandVariableSelector.replace("#", "")).val();
3888
3889        if ($(brandVariableSelector).is('ul')) {
3890            selected = $(brandVariableSelector + ' li').filter(function () {
3891                return $(this).text() === selectedName;
3892            }).addClass("selected-brand").data('id');
3893
3894            if (typeof $(brandVariableSelector + ' li:contains(' + selectedName + ')').position() !== "undefined") {
3895                var elementPosition = $(brandVariableSelector + ' li:contains(' + selectedName + ')').position().top - $(brandVariableSelector).position().top;
3896
3897                $(brandVariableSelector).parent().animate({
3898                    scrollTop: elementPosition
3899                }, 100);
3900            }
3901        }
3902        else if ($(brandVariableSelector).is('select')) {
3903            selected = $(brandVariableSelector + ' option').filter(function () {
3904                return $(this).text() === selectedName;
3905            }).addClass("selected-brand").data('id');
3906        }
3907        else {
3908            var selectedInput = $(brandVariableSelector + ' input').filter(function () {
3909                return $(this).val() === selectedName;
3910            });
3911
3912            if ($(selectedInput).is(':radio')) {
3913                $(selectedInput).addClass("selected-brand");
3914                if (typeof $(selectedInput).position() !== "undefined") {
3915                    var radioElementPosition = $(selectedInput).position().top - $(brandVariableSelector).position().top;
3916
3917                    $(selectedInput).parent().animate({
3918                        scrollTop: radioElementPosition
3919                    }, 100);
3920                }
3921            }
3922
3923            selected = selectedInput.data('id');
3924        }
3925
3926        if (selected === null) {
3927            selected = 0;
3928        }
3929    }
3930
3931    if (selected || selected === 0) {
3932        if (!isInitialCall) {
3933            $(brandVariableSelector).find('.selected-brand').removeClass("selected-brand");
3934
3935            if (!$(clickedObject).is("input:text")) {
3936                $(clickedObject).addClass("selected-brand");
3937            }
3938
3939            $("#Text_" + brandVariableSelector.replace("#", "")).val($(clickedObject).data('name')).change();
3940
3941            if ($("#li_" + brandVariableSelector).length !== 0) {
3942                $("#li_" + brandVariableSelector).text($(clickedObject).data('name')); //needed for the multi-itemsummary
3943            }
3944        }
3945
3946        var url = '/Public/GetCAModels?brandId=' + selected + '&year=' + $(yearOfManufactureSelector).val();
3947
3948        $("body").css("cursor", "progress");
3949
3950        var modelVariableElementId = modelVariableSelector.replace("#", "");
3951        $(".instanda-question-inner-label-".concat(modelVariableElementId)).show();
3952
3953        if ($(brandVariableSelector).is(":visible")) {
3954            $(".car-models-wrapper-dropdown-".concat(modelVariableElementId)).show();
3955            $(".car-models-wrapper-autocomplete-".concat(modelVariableElementId)).show();
3956            $(".car-models-wrapper-radio-".concat(modelVariableElementId)).show();
3957            $(".car-models-wrapper-".concat(modelVariableElementId)).show();
3958        }
3959
3960        $(modelVariableSelector).empty();
3961
3962        $.ajax({
3963            url: url,
3964            dataType: 'json',
3965            success: function (data) {
3966                console.debug(data);
3967                carModelsObjects[modelVariableElementId] = [];
3968                carModelsTexts[modelVariableElementId] = [];
3969
3970                $.each(data, function (index, value) {
3971                    var powerType = "PS";
3972
3973                    if ('power_type' in value) {
3974                        powerType = value.power_type;
3975                    }
3976
3977                    var text = value.name + ' ' + value.body_type.name + ' ' + value.power + ' ' + powerType;
3978
3979                    if (value.name == '') {
3980                        text = '';
3981                    }
3982
3983                    var selectedClass = "";
3984
3985                    if (isInitialCall) {
3986                        if ($("#Text_".concat(modelVariableElementId)).val() === value.name) {
3987
3988                            selectedClass = "selected-model";
3989                        }
3990                    }
3991                    else {
3992                        $('#Text_' + bodyTypeVariableName).val(value.body_type.name);
3993                        $('#Text_' + bodyTypeVariableName).change();
3994
3995                        if ($("#li_" + bodyTypeVariableName).length !== 0) {
3996                            $("#li_" + bodyTypeVariableName).text(value.body_type.name); //needed for the multi-itemsummary
3997                        }
3998                    }
3999
4000                    carModelsObjects[modelVariableElementId].push(value);
4001                    carModelsTexts[modelVariableElementId].push(text);
4002
4003                    if ($(modelVariableSelector).is("ul")) {
4004                        $(modelVariableSelector).append(
4005                            $('<li class="list-group-item list-group-item-action">').append(text).data({
4006                                id: value.id,
4007                                name: value.name,
4008                                power: value.power,
4009                                powertype: value.power_type,
4010                                bodytypeid: value.body_type.id,
4011                                bodytypename: value.body_type.name,
4012                                photo_url: value.photo_url,
4013                                cylinder: value.cylinder,
4014                                capacity: value.capacity
4015                            }).addClass(selectedClass));
4016                    }
4017                    else if ($(modelVariableSelector).is("select")) {
4018                        let selectedOption = "";
4019
4020                        if (selectedClass !== "")
4021                            selectedOption = "selected";
4022
4023                        $(modelVariableSelector).append(
4024                            $("<option value='".concat(value.name, "' ").concat(selectedOption, ">")).append(text).data({
4025                                id: value.id,
4026                                name: value.name,
4027                                power: value.power,
4028                                powertype: value.power_type,
4029                                bodytypeid: value.body_type.id,
4030                                bodytypename: value.body_type.name,
4031                                photo_url: value.photo_url,
4032                                cylinder: value.cylinder,
4033                                capacity: value.capacity
4034                            }).addClass(selectedClass));
4035                    }
4036                    else if (value.name !== '') {
4037                        if ($(modelVariableSelector).hasClass("car-models-wrapper-radio-".concat(modelVariableElementId))) {
4038
4039                            let selectedRadio = "";
4040
4041                            if (selectedClass !== "")
4042                                selectedRadio = "checked";
4043
4044                            $(modelVariableSelector).append(
4045                                $("<input type=\"radio\" id=\"".concat(modelVariableElementId, "_radio")
4046                                    .concat(value.id, "\" name=\"")
4047                                    .concat(modelVariableName, "_radio\" value=\"")
4048                                    .concat(value.name, "\" ")
4049                                    .concat(selectedRadio, "/>"))
4050                                    .data({
4051                                        id: value.id,
4052                                        name: value.name,
4053                                        power: value.power,
4054                                        powertype: value.power_type,
4055                                        bodytypeid: value.body_type.id,
4056                                        bodytypename: value.body_type.name,
4057                                        photo_url: value.photo_url,
4058                                        cylinder: value.cylinder,
4059                                        capacity: value.capacity
4060                                    })
4061                                    .addClass(selectedClass));
4062
4063                            $(modelVariableSelector).append("".concat(text, "<br/>"));
4064                        }
4065                    }
4066                });
4067
4068                if ($(modelVariableSelector).is("input:text")) {
4069                    if (!isInitialCall) {
4070                        $(modelVariableSelector).val('');
4071                    }
4072
4073                    if (typeof jQuery.ui !== 'undefined') {
4074                        var options = {
4075                            source: carModelsTexts[modelVariableElementId],
4076                            minLength: 0,
4077                            select: function (event, ui) {
4078                                let modelIndex = carModelsTexts[modelVariableElementId].indexOf(ui.item.label);
4079                                let model = carModelsObjects[modelVariableElementId][modelIndex];
4080                                $(this).data("id", model.id);
4081                                $(this).data("name", model.name);
4082                                $(this).data("photo_url", model.photo_url);
4083                                $(this).data("power", model.power);
4084                                $(this).data("bodytypename", model.body_type.name);
4085                                $(this).data("bodytypeid", model.body_type.id);
4086                                $(this).data("cylinder", model.cylinder);
4087                                $(this).data("capacity", model.capacity);
4088                                $(this).data("powertype", model.power_type);
4089                                $(this).blur();
4090                            }
4091                        };
4092
4093                        $(modelVariableSelector).autocomplete(options);
4094                    }
4095                    else {
4096                        $(modelVariableSelector).typeahead('destroy');
4097
4098                        $(modelVariableSelector).typeahead({
4099                            hint: true,
4100                            highlight: true,
4101                            minLength: 1
4102                        },
4103                            {
4104                                name: 'models',
4105                                source: substringMatcher(carModelsTexts[modelVariableElementId]),
4106                                limit: Number.MAX_VALUE
4107                            })
4108                            .on('typeahead:selected', function (evt, item) {
4109                                let modelIndex = carModelsTexts[modelVariableElementId].indexOf(item);
4110                                if (modelIndex > -1) {
4111                                    let model = carModelsObjects[modelVariableElementId][modelIndex];
4112                                    $(this).data("id", model.id);
4113                                    $(this).data("name", model.name);
4114                                    $(this).data("photo_url", model.photo_url);
4115                                    $(this).data("power", model.power);
4116                                    $(this).data("bodytypename", model.body_type.name);
4117                                    $(this).data("bodytypeid", model.body_type.id);
4118                                    $(this).data("cylinder", model.cylinder);
4119                                    $(this).data("capacity", model.capacity);
4120                                    $(this).data("powertype", model.power_type);
4121                                }
4122
4123                                $(modelVariableSelector).blur();
4124                            });
4125                    }
4126                }
4127
4128                if (isInitialCall) {
4129                    $(modelVariableSelector).trigger("change:initial").blur();
4130                } else {
4131                    $(modelVariableSelector + " li:first").click().blur();
4132                }
4133
4134                $(failureDivSelector).css("display", "none");
4135                $("*").css("cursor", "");
4136            },
4137            error: function () {
4138                $(failureDivSelector).css("display", "block");
4139                $("*").css("cursor", "");
4140            }
4141        });
4142    }
4143}
4144
4145function CarBrandsAndModelsModelChange(clickedObject, failureDivSelector, modelVariableSelector, modelIdVariableSelector, bodyTypeSelector, powerSelector, powerTypeSelector,
4146    bodyTypeIdSelector, priceIdSelector, grade1Selector, grade2Selector, grade3Selector, grade4Selector, grade5Selector,
4147    currencySelector, countrySelector, pictureUrlSelector, capacitySelector, cylinderSelector, isInitialCall) {
4148
4149    var selected = clickedObject !== null ? $(clickedObject).data('id') : null;
4150
4151    if (!isInitialCall && selected) {
4152        $(modelVariableSelector).find('.selected-model').removeClass("selected-model");
4153
4154        if (!$(clickedObject).is("input:text")) {
4155            $(clickedObject).addClass("selected-model");
4156        }
4157
4158        var modelVariableElementId = modelVariableSelector.replace("#", "");
4159
4160        $("#Text_" + modelVariableElementId).val($(clickedObject).data('name')).change();
4161
4162        if ($("#li_" + modelVariableElementId).length !== 0) {
4163            $("#li_" + modelVariableElementId).text($(clickedObject).data('name')); //needed for the multi-itemsummary
4164        }
4165
4166        $(modelIdVariableSelector).val(selected).change();
4167
4168        $(pictureUrlSelector).val($(clickedObject).data('photo_url')).change().blur();
4169
4170        var selectedPower = $(clickedObject).data('power');
4171
4172        if (selectedPower) {
4173            $(powerSelector).val(selectedPower).change().blur();
4174        } else {
4175            $(powerSelector).val("").change().blur();
4176        }
4177
4178        var selectedBodyType = $(clickedObject).data('bodytypename');
4179        if (selectedBodyType) {
4180            $(bodyTypeSelector).val(selectedBodyType).change().blur();
4181        } else {
4182            $(bodyTypeSelector).val("").change().blur();
4183        }
4184
4185        var selectedBodyTypeId = $(clickedObject).data('bodytypeid');
4186        if (selectedBodyTypeId) {
4187            $(bodyTypeIdSelector).val(selectedBodyTypeId).change().blur();
4188        } else {
4189            $(bodyTypeIdSelector).val("").change().blur();
4190        }
4191
4192        var selectedCylinders = $(clickedObject).data('cylinder');
4193        if (selectedCylinders) {
4194            $(cylinderSelector).val(selectedCylinders).change().blur();
4195        } else {
4196            $(cylinderSelector).val("").change().blur();
4197        }
4198
4199        var selectedCapacity = $(clickedObject).data('capacity');
4200        if (selectedCapacity) {
4201            $(capacitySelector).val(selectedCapacity).change().blur();
4202        } else {
4203            $(capacitySelector).val("").change().blur();
4204        }
4205
4206        var selectedPowerType = $(clickedObject).data('powertype');
4207        if (selectedPowerType) {
4208            $(powerTypeSelector).val(selectedPowerType).change().blur();
4209        } else {
4210            $(powerTypeSelector).val("PS").change().blur();
4211        }
4212
4213        var url = '/Public/GetCAPrices?modelId=' + selected;
4214
4215        $("body").css("cursor", "progress");
4216
4217        $.ajax({
4218            url: url,
4219            dataType: 'json',
4220            success: function (data) {
4221                console.debug(data);
4222
4223                $(priceIdSelector).val(data.id).change().blur();
4224                $(grade1Selector).val(data.grade1).change().blur();
4225                $(grade2Selector).val(data.grade2).change().blur();
4226                $(grade3Selector).val(data.grade3).change().blur();
4227                $(grade4Selector).val(data.grade4).change().blur();
4228                $(grade5Selector).val(data.grade5).change().blur();
4229                $(currencySelector).val(data.currency).change().blur();
4230                $(countrySelector).val(data.country).change().blur();
4231
4232                if (window['summaryAlreadyShown' + modelVariableElementId] === 0) {
4233                    window['summaryAlreadyShown' + modelVariableElementId]++;
4234                    $('.car-brands-and-models-show-summary-' + modelVariableElementId).click();
4235                }
4236
4237                $(failureDivSelector).css("display", "none");
4238                $("*").css("cursor", "");
4239            },
4240            error: function () {
4241                $(failureDivSelector).css("display", "block");
4242                $("*").css("cursor", "");
4243            }
4244        });
4245    }
4246    else if (isInitialCall) {
4247        $(modelVariableSelector).find('.selected-model').removeClass("selected-model");
4248        selected = $(modelIdVariableSelector).val();
4249
4250        if ($(modelVariableSelector).is("ul")) {
4251            var listItems = $(modelVariableSelector + " li");
4252            listItems.each(function (idx, li) {
4253                var product = $(li);
4254                if (product.data("id") == selected) {
4255                    product.addClass("selected-model");
4256
4257                    var elementPosition = $(modelVariableSelector + ' li:contains("' + product.data("name") + '")').position().top - $(modelVariableSelector).position().top;
4258
4259                    $(modelVariableSelector).parent().animate({
4260                        scrollTop: elementPosition
4261                    }, 100);
4262                }
4263            });
4264        }
4265
4266        var selectedInput = $(modelVariableSelector + ' input').filter(function () {
4267            return $(this).data("id") == selected;
4268        });
4269
4270        if ($(selectedInput).is(':radio')) {
4271            if (typeof $(selectedInput).position() !== "undefined") {
4272                var modelRadioElementPosition = $(selectedInput).position().top - $(modelVariableSelector).position().top;
4273                $(selectedInput).parent().animate({
4274                    scrollTop: modelRadioElementPosition
4275                }, 100);
4276            }
4277        }
4278    }
4279
4280    $(powerTypeSelector + ' option:not(:selected)').prop('disabled', true);
4281    $(powerTypeSelector + ' option:selected').prop('disabled', false);
4282}
4283
4284function CheckIfClassicAnalyticsInterfaceIsAvailable(onFailure) {
4285    var url = '/Public/GetCABrands?year=2001'; //sample year
4286
4287    $.ajax({
4288        url: url,
4289        dataType: 'json',
4290        success: function (data) {
4291            if (!Array.isArray(data) || data.length <= 1) {
4292                onFailure();
4293            }
4294        },
4295        error: function () {
4296            onFailure();
4297        }
4298    });
4299}
4300
4301function HideElements(elementsToHide) {
4302    for (var i = 0; i < elementsToHide.length; i++) {
4303
4304        var targetElement = $(elementsToHide[i]);
4305
4306        //fix for ul with dynamically created li in IE
4307        if (navigator.userAgent.match(/msie|trident/i) && targetElement.is("ul")) {
4308            targetElement = targetElement.parent();
4309        }
4310
4311        if (targetElement.css("display") !== "none" && targetElement.css("visibility") !== "hidden") {
4312            targetElement.slideUp();
4313        }
4314    }
4315}
4316
4317function ShowElements(elementsToShow) {
4318    for (var i = 0; i < elementsToShow.length; i++) {
4319
4320        var targetElement = $(elementsToShow[i]);
4321
4322        //fix for ul with dynamically created li in IE
4323        if (navigator.userAgent.match(/msie|trident/i) && targetElement.is("ul")) {
4324            targetElement = targetElement.parent();
4325        }
4326
4327        targetElement.slideDown();
4328    }
4329}
4330
4331const createDivSelector = function(maskedName, append) {
4332    return `div[name='${maskedName}${append}']`;
4333}
4334
4335function EditMaskedInput(name, maskedName) {
4336    var maskedInput = $("input[name='" + name + "']");
4337    maskedInput.removeAttr('disabled');
4338    maskedInput.val('');
4339    maskedInput.attr('data-val', 'true');
4340
4341    $("input[name='" + maskedName + "']").val('');
4342    $(createDivSelector(maskedName, "_edit_icon")).hide();
4343    $(createDivSelector(maskedName, "_cancel_icon")).show();
4344}
4345
4346function MaskedInputCancel(name, maskedName, value) {
4347    var maskedInput = $("input[name='" + name + "']")
4348    maskedInput.val(value);
4349    maskedInput.attr('disabled', 'disabled');
4350    maskedInput.attr('data-val', 'false');
4351
4352    $("input[name='" + maskedName + "']").val('masked');
4353    $(createDivSelector(maskedName, "_cancel_icon")).hide();
4354    $(createDivSelector(maskedName, "_edit_icon")).show();
4355}
4356
4357function uuidv4() {
4358    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
4359        var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8);
4360        return v.toString(16);
4361    });
4362}
4363
4364function verifyOosMtaDetailChange(encryptedQuoteRef, url) {
4365    $.ajax({
4366        type: "POST",
4367        url: url,
4368        data: { 'quoteRef': encryptedQuoteRef },
4369        success: function (response) {
4370            if (response.result === "ClientException") {
4371                window.alert(response.message);
4372            } else {
4373                window.location = response.redirectUrl;
4374            }
4375        },
4376        error: function (jqXHR, exception) {
4377            alert('Error : Server returned response with status ' + jqXHR.status);
4378        }
4379    });
4380}
4381
4382function showValidationErrors(response) {
4383    if (response.ValidationErrors.length > 0) {
4384        let $validationSummary = $('.validation-summary-valid');
4385        let $divAlert = $("div[role='alert']");
4386
4387        $validationSummary
4388            .addClass("validation-summary-errors")
4389            .removeClass("validation-summary-valid");
4390
4391        $divAlert
4392            .removeClass('hidden')
4393            .addClass('show');
4394
4395        var list = document.createElement("ul");
4396
4397        for (var i = 0; i < response.ValidationErrors.length; i++) {
4398            var item = document.createElement("li");
4399            item.appendChild(document.createTextNode(response.ValidationErrors[i]));
4400            list.append(item);
4401        }
4402
4403        $(".validation-summary-errors").empty().append(list);
4404    }
4405}
4406
4407function isSet(prop) {
4408    return typeof prop != "undefined";
4409}
4410
4411function toTitleCase(str) {
4412    str = str.toLowerCase();
4413    return str.replace(/(?:^|\s)\w/g, function (match) {
4414        return match.toUpperCase();
4415    });
4416}
4417
4418function oosCloseQuoteToBuyFlow(buttonElement) {
4419    let $btn = $(buttonElement);
4420    let requiresValidation = $btn.data('requires-validation') === true || $btn.data('requires-validation') === 'true';
4421    let validationUrl = $btn.data('validation-url');
4422
4423    let $form = $('form');
4424    if ($form.length > 0) {
4425        if ($form.hasClass('dirty') && !confirm('Changes you made may not be saved.')) {
4426            return;
4427        }
4428
4429        $form.trigger('reinitialize.areYouSure');
4430    }
4431
4432    ShowWaitingAnimation();
4433
4434    if (!requiresValidation || !validationUrl) {
4435        window.parent.postMessage({ type: 'oosCloseQuoteToBuyFlow' }, window.location.origin);
4436        return;
4437    }
4438
4439    disableFormActionButtons();
4440    clearErrors();
4441
4442    $.ajax({
4443        url: validationUrl,
4444        type: 'POST',
4445        data: { __RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val() },
4446        success: function (response) {
4447            if (!response.Errors) {
4448                window.parent.postMessage({ type: 'oosCloseQuoteToBuyFlow' }, window.location.origin);
4449            } else {
4450                HideWaitingAnimation();
4451                displayErrorMessages(response.Errors);
4452                enableFormActionButtons();
4453            }
4454        },
4455        error: function () {
4456            HideWaitingAnimation();
4457            displayErrorMessages([{ InvalidInputFieldName: '', ValidationMessages: ['An unexpected error occurred. Please try again.'] }]);
4458            enableFormActionButtons();
4459        }
4460    });
4461}

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.