PageSourceSearch

https://portal.uicalaska.com/Scripts/sockeye.xrm.form.js

js uicalaska.com collected 2026-09-25 04:14:42 UTC 55,720 bytes, 1,421 lines download raw bytes

1window._PARENT_FORMS = window._PARENT_FORMS || [];
2window.ACTIVE_FORM = null;
3//Prevents backspace except in the case of textareas and text inputs to prevent user navigation.
4$(document).keydown(function (e) {
5    var preventKeyPress;
6    if (e.keyCode == 8) {
7        var d = e.srcElement || e.target;
8        switch (d.tagName.toUpperCase()) {
9            case 'TEXTAREA':
10                preventKeyPress = d.readOnly || d.disabled;
11                break;
12            case 'INPUT':
13                preventKeyPress = d.readOnly || d.disabled ||
14                    (d.attributes["type"] && $.inArray(d.attributes["type"].value.toLowerCase(), ["radio", "checkbox", "submit", "button"]) >= 0);
15                break;
16            case 'DIV':
17            case 'SPAN':
18                preventKeyPress = d.readOnly || d.disabled || !(d.attributes["contentEditable"] && d.attributes["contentEditable"].value == "true");
19                break;
20            default:
21                preventKeyPress = true;
22                break;
23        }
24    }
25    else
26        preventKeyPress = false;
27
28    if (preventKeyPress)
29        e.preventDefault();
30});
31
32// Track Ajax Requests, so we can abort them if we navigate away.
33(function ($) {
34    var max_concurrent_requests = 2;
35    // Set up queue for pending requests
36    var XHRQueueTimer = null;
37    var queuedXHR = [];
38    // Set up array of all pending requests
39    var pendingXHR = [];
40    // Add request to array when making a request
41    $(document).ajaxSend(function (e, jqXHR, options) {
42        pendingXHR.push(jqXHR);
43    });
44    // Remove request when complete
45    $(document).ajaxComplete(function (e, jqXHR, options) {
46        pendingXHR = $.grep(pendingXHR, function (x) { return x != jqXHR });
47    });
48
49    // function to enqueueXHR
50    $.enqueueXHR = function (callback) {
51        queuedXHR.push(callback);
52        if (XHRQueueTimer == null) {
53            XHRQueueTimer = setTimeout(function checkQueue() {
54                while (queuedXHR.length > 0 && pendingXHR.length < max_concurrent_requests) {
55                    try {
56                        queuedXHR.shift()();
57                    } catch (err) { }
58                }
59                if (queuedXHR.length > 0) {
60                    XHRQueueTimer = setTimeout(checkQueue, 500);
61                }
62                else {
63                    XHRQueueTimer = null;
64                }
65            }, 0);
66        }
67    }
68
69    // define abortAllXHR function
70    $.abortAllXHR = function (exception) {
71        // Remove all queued requests
72        queuedXHR.length = 0;
73        // abort all pending requests
74        $.each(pendingXHR, function (idx, jqXHR) {
75            if (exception != jqXHR) {
76                jqXHR.abort();
77            } else {
78                //alert("fatal try to abort xhr");
79            }
80        });
81    }
82
83})(jQuery);
84
85// Set up address change tracking... only want to attach this event once for the whole page, so must do it before out "triggerReady" setup.
86//(function ($) {
87//    // Sort Out address changes.
88//    $.address.change(onAddressChange);
89//})(jQuery);
90
91// Overrides jQuery-ready and makes it triggerable with $.triggerReady
92// This script needs to be included before other scripts using the jQuery-ready.
93// Tested with jQuery 1.7
94// Taken from http://stackoverflow.com/questions/2238030/trigger-document-ready-so-ajax-code-i-cant-modify-is-executed
95(function () {
96    var readyList = [];
97    // Store a reference to the original ready method.
98    var originalReadyMethod = jQuery.fn.ready;
99    // Override jQuery.fn.ready
100    jQuery.fn.ready = function () {
101        if (arguments.length && arguments.length > 0 && typeof arguments[0] === 'function') {
102            readyList.push(arguments[0]);
103        }
104
105        // Execute the original method.
106        originalReadyMethod.apply(this, arguments);
107    };
108    // Used to trigger all ready events
109    $.triggerReady = function () {
110        $(readyList).each(function () { this(); });
111    };
112})();
113
114//function onAddressChange(event) {
115//    if (window.tabEvent || window.closingSubForm) { return }
116//    var path = event.pathNames;
117
118//    // Determine if we need to close a subform.
119//    var depth = 0;
120//    var i;
121//    if (depth == 0 && path.length > 0) {
122//        for (i = path.length - 1; i >= 0; i--) {
123//            // get depth in path
124//            if (path[i].indexOf("sub_") == 0) {
125//                depth = parseInt(path[i].substring(path[i].indexOf("_") + 1)) || 0;
126//                break;
127//            }
128//        }
129//    }
130//    if (depth < window._PARENT_FORMS.length) {
131//        window.closingSubForm = true;
132//        closeXrmSubFormNow();
133//        window.closingSubForm = false;
134//    }
135//    if (depth > window._PARENT_FORMS.length) {
136//        // We have extra subform(s) here, (probably from a bookmark or refresh), remove them.
137//        // Start at beginning and find first subform > current depth, then remove the rest of the tag
138//        for (var j = i; i >= 0; i--) {
139//            // get depth in path
140//            if (path[i].indexOf("sub_") == 0) {
141//                depth = parseInt(path[i].substring(path[i].indexOf("_") + 1)) || 0;
142//                if (depth > window._PARENT_FORMS.length) {
143//                    // Remove everything from j to end.
144//                    path.splice(j, path.length - j);
145//                }
146//                if (depth == window._PARENT_FORMS.length) {
147//                    break;
148//                }
149//            }
150//        }
151//        // Write back to address.
152//        $.address.value(path.join("/"));
153//    }
154
155//    // attempt to navigate to a tab.
156//    if (path.length > 0 && path[path.length - 1].indexOf("tab_") == 0) {
157//        // Navigate to tab.
158//        $("#" + path[path.length - 1]).find(".ui-tabs-anchor").click();
159//    }
160//    else if (path.length > 0 && path[path.length - 1].indexOf("a_") == 0) { // finally assume path is a fragment id and try to jump to it.
161//        scrollToElement($("#" + path[path.length - 1].substr(2)));
162//    }
163//}
164
165function initializeTabInterface($form) {
166    $form = $form || $("form.xrmform").last();
167    // Setup Collapsible Tabs
168    $form.find("div.xrmform-tab-container").off("click.formcollapse").on("click.formcollapse", "h3.xrmform-tab-header", function () {
169        var tab = $(this).closest(".xrmform-tab");
170        if (tab.hasClass("xrmform-tab-collapsed")) {
171            tab.removeClass("xrmform-tab-collapsed");
172            tab.addClass("xrmform-tab-expanded");
173            // Find all grids and re-initialize them.
174            setTimeout(function () { tab.trigger("showtab.xrmform", [tab]); }, 100);
175        } else {
176            tab.addClass("xrmform-tab-collapsed");
177            tab.removeClass("xrmform-tab-expanded");
178        }
179
180    })
181}
182
183function setupChangeTracking($form) {
184    $form = $form || $("form.xrmform").last();
185    // TODO: Detect and submit only changes.
186    ignoreUnload = false;
187    $form.data("isDirty", false);
188    $form.find("input, [contenteditable='true']").not("[type='password'], [name='username']").change(
189        function () {
190            $(this).triggerChange();
191        }
192    );
193
194    $(window).on("beforeunload", function () {
195        var parentFormDirty = false;
196        $.each(window._PARENT_FORMS, function (idx, item) {
197            if (item.isDirty) {
198                parentFormDirty = true;
199            }
200        });
201        var gridsDirty = false;
202        $(".xrm-ui-grid").each(function () {
203            if ($(this).xrmgrid("hasPendingEdits")) {
204                gridsDirty = true;
205            }
206        });
207
208
209        if ($form.data("isDirty") && !ignoreUnload) {
210            return "You have unsaved changes. Are you sure you want to leave this page?";
211        }
212        else if (gridsDirty) {
213            return "You have unsaved changes in one or more data tables. Are you sure you want to leave this page?";
214        }
215        else if (parentFormDirty) {
216            return "You have unsaved changes in a parent form. Are you sure you want to leave this page?";
217        }
218        else if (!ignoreUnload) {
219            disableForm(true);
220        }
221        ignoreUnload = false;
222    });
223
224}
225
226function disableSection(section, allControls) {
227    $(section).find("input[type=hidden]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
228    $(section).find("input[type=text]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
229    $(section).find("input[type=number]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
230    $(section).find("input[type=button]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
231    $(section).find("input[type=checkbox]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
232    $(section).find("input[type=radio]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");//.attr("readonly", "readonly");
233    $(section).find("textarea").not(!allControls ? ".readonly-enabled" : "").attr("readonly", "readonly");
234    $(section).find("button, .btn").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
235    $(section).find("select").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");//disabled to prevent field submission
236    $(section).find("span.xrmplaceholder[data-editable='true']").not(!allControls ? ".readonly-enabled" : "").removeAttr("contentEditable");
237    $(section).find("div.xrm-ui-ctrl").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
238    $(section).find("input[type=file]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
239}
240
241function enableSection(section, allControls) {
242    $(section).find("input[type=hidden]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
243    $(section).find("input[type=text]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
244    $(section).find("input[type=number]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
245    $(section).find("input[type=button]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
246    $(section).find("input[type=checkbox]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
247    $(section).find("input[type=radio]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");//.removeAttr("readonly");
248    $(section).find("textarea").not(!allControls ? ".readonly-enabled" : "").removeAttr("readonly");
249    $(section).find("button, .btn").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
250    $(section).find("select").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
251    $(section).find("span.xrmplaceholder[data-editable='true']").not(!allControls ? ".readonly-enabled" : "").attr("contentEditable", true);
252    $(section).find("div.xrm-ui-ctrl").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
253    $(section).find("input[type=file]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
254}
255
256
257function disableForm($form, allControls) {
258    $form = $($form) || $("form.xrmform").last();
259    $form.find("input[type=hidden]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
260    $form.find("input[type=text]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
261    $form.find("input[type=number]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
262    $form.find("input[type=button]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
263    $form.find("input[type=checkbox]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
264    $form.find("input[type=radio]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");//.attr("readonly", "readonly");
265    $form.find("textarea").not(!allControls ? ".readonly-enabled" : "").attr("readonly", "readonly");
266    $form.find("button, .btn").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
267    $form.find("select").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
268    $form.find("span.xrmplaceholder[data-editable='true']").not(!allControls ? ".readonly-enabled" : "").removeAttr("contentEditable");
269    $form.find("div.xrm-ui-ctrl").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
270    $form.find("input[type=file]").not(!allControls ? ".readonly-enabled" : "").attr("disabled", "disabled");
271}
272
273function enableForm($form, allControls) {
274    $form = $($form) || $("form.xrmform").last();
275    // Display Busy Indicator
276    $form.find("form.xrmform").closest("div.xrmform-container").busyIndicator(false);
277    $form.find("input[type=hidden]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
278    $form.find("input[type=text]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
279    $form.find("input[type=number]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
280    $form.find("input[type=button]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
281    $form.find("input[type=checkbox]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
282    $form.find("input[type=radio]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");//.removeAttr("readonly");
283    $form.find("textarea").not(!allControls ? ".readonly-enabled" : "").removeAttr("readonly");
284    $form.find("button, .btn").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
285    $form.find("select").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
286    $form.find("span.xrmplaceholder[data-editable='true']").not(!allControls ? ".readonly-enabled" : "").attr("contentEditable", true);
287    $form.find("div.xrm-ui-ctrl").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
288    $form.find("input[type=file]").not(!allControls ? ".readonly-enabled" : "").removeAttr("disabled");
289
290}
291
292function processNotifications() {
293    $("div.notification-data").each(function () {
294        var id = $(this).attr("id");
295        var level = parseInt($(this).data("level")) || 0;
296        var content = $(this).html();
297        var closeable = $(this).data("iscloseable") || true;
298        addNotification(id, level, content, closeable);
299        $(this).remove();
300    });
301}
302
303function initializeForm(vmInitialized, $form) {
304
305    $form = $form || $("form.xrmform").last();
306    if (typeof xrmViewModel !== 'undefined') {
307        if (!xrmViewModel && !vmInitialized) {
308            initializeForm(true);
309            return;
310        }
311        else if (!vmInitialized) {
312            // Add a class so we can find our form after vue is done processing our form.
313            $form.addClass("mounting");
314            xrmViewModel.$nextTick(function () {
315                this.$mount($form[0]);
316                xrmViewModel.$nextTick(function () {
317                    // Get our form back and remove class.
318                    initializeForm(true, $("form.mounting").removeClass("mounting"));
319                });
320            });
321            return;
322        }
323    }
324
325    // Add Asteriks to Required Fields
326    $form.find($("div.xrmform-cell:has([data-val-required])")).decorateRequired(true);
327    $form.find($("div.xrmform-cell:has([data-val-requiredif])")).decorateRequired(true);
328
329    // to determine which button submitted the form
330    $form.find("input[type=submit], button[type='submit']").click(function () {
331        $form.validate().cancelSubmit = true;
332        var $submitAction = $("#submitButton");
333        if ($submitAction.length == 0) {
334            $submitAction.add($("<input>").attr("type", "hidden").attr("name", "submitButton").attr("id", "submitButton"))
335            $(this).closest("form.xrmform").append($submitAction);
336        }
337        $submitAction.val($(this).attr("id"));
338    });
339
340    $form.on("submit", function (e) {
341        if ($(this).data("submitasync")) {
342            Xrm.Page.data.save(false, $form);
343            e.preventDefault();
344            return false;
345        }
346        else {
347            // Validate form, and then allow to submit.
348            switch ($("#submitButton").val()) {
349                case "back":
350                case "cancel":
351                    // Don't validate form on back or cancel (wizard actions)
352                    break;
353                default:
354                    $form.validate();
355                    if (!$form.valid()) {
356                        e.preventDefault();
357                        return false;
358                    }
359
360                    $form.find("input[type=submit], button[type='submit']").attr("disabled", "disabled");
361                    break;
362            }
363            // Reset form dirty flag
364            $form.data("isDirty", false);
365        }
366    });
367
368    // Setup Tabs - removing this since our forms do not need it anymore (per Nate)
369    //  initializeTabInterface($form);
370
371    // Setup Controls
372    var $container = $form.length > 0 ? $form.closest(".xrmform-container") : $(".xrmform-container");
373    $container.initializeXrmControls();
374    $.validator.unobtrusive.parse($form);
375
376    setupChangeTracking($form);
377
378    $form.find("a.xrmform-help-link").click(function (e) {
379        e.preventDefault();
380        url = $(this).attr("href");
381        var height = top.document.body.clientHeight;
382        var width = 400;
383        var fromleft = Math.min(top.screenLeft + top.document.body.clientWidth + 5, screen.width - width);
384        var fromtop = top.screenTop;
385        var viewer = window.open(url, "helpviewer", "width=" + width + ",height=" + height + ",resizable=1,status=1,scrollbars=1,left=" + fromleft + ",top=" + fromtop);
386        viewer.focus();
387    });
388
389    // Configure Approval Process Stuff.
390    if (loadApprovalProcess) { loadApprovalProcess($form.find("input[name='approvalprocessidentifier']").val()); }
391
392
393    // Display Status Message
394    if ($form.find("div.status-message").length == 1) {
395        $form.find("#xrmform-footer").addClass("ui-state-highlight");
396        $form.find("#xrmform-footer").busyIndicator(true, $("div.status-message").html());
397        setTimeout(function () {
398            $form.find("#xrmform-footer").removeClass("ui-state-highlight", 500);
399        }, 5000);
400    }
401
402    // Determine if form is read-only and disable form accordingly
403    $form.find("#FormIsReadOnly").on("change", function () {
404        if ($.parseJSON($(this).val())) {
405            extractModel($form);
406        }
407    });
408    if ($.parseJSON($form.find("#FormIsReadOnly").val() || "false")) {
409        disableForm($form);
410    }
411
412    //onload disable sections that have inline edit applied
413    //set on click event 
414
415    if ($form.find(".xrmform-section-header-inline").length > 0) {
416        $(".xrmform-section-header-inline").each(function () {
417            verifyInlineEditDisplay(this);
418            $(this).on("click", function () {
419                inlineEditClick(this);
420            });
421            disableSection($(this).closest(".xrmform-section"), false);
422        });
423        //hide submit button on inline edit forms
424        if ($("button#submitButton").length > 0) {
425            $("button#submitButton").css("display", "none");
426        }
427
428        if ($("input[type=submit]").length > 0) {
429            $("input[type=submit]").hide();
430        }
431
432    }
433
434    processNotifications();
435}
436
437
438
439$(function () {
440    $form = $("form.xrmform").last();
441    initializeForm(false, $form);
442    extractModel();
443    $(window).trigger("resize");
444});
445
446function focusFirst($form) {
447    $form = $form || $("form.xrmform.").last();
448    if ($form.data("autofocus") == false) {
449        return;
450    }
451    // Start with most generic, work to most specific.
452    // First button
453    $($form.find("#xrmform-footer").find(".xrm-button").get().reverse()).focus();
454    // First Tab
455    $form.find("a.ui-tabs-anchor:first").parent("li").focus();
456    // First Control.
457    var first = $form.find('input[type!="submit"]:enabled:visible:first');
458    if (first.length > 0) { first.focus(); document.body.scrollTop = document.documentElement.scrollTop = 0; }
459    else {
460        // Determine if there is an iframe on the page.  If so, poll for its body ready, and set focus.
461        if ($form.find('iframe').length > 0) {
462            frm = $('iframe:first');
463            setTimeout(function focusIframe() {
464                if (frm.contents() && frm.contents().find('body').length > 0) {
465                    frm.contents().find('body').focus();
466                    document.body.scrollTop = document.documentElement.scrollTop = 0;
467                }
468                else {
469                    setTimeout(focusIframe, 50);
470                }
471            }, 0);
472        }
473    }
474}
475
476function getScriptFromUrl(url) {
477    var scriptUrl, regex, regexResult;
478    regex = /\/?(.*)[\?,#]/;
479    regexResult = regex.exec(url);
480    if (regexResult != null) {
481        scriptUrl = regexResult[1];
482        if (scriptUrl.indexOf("/") == -1) {
483            scriptUrl += "/Index";
484        }
485    }
486    return scriptUrl;
487}
488
489// like $.getScript, but will always load the file into devtools. Useful for dynamically loading modal scripts.
490jQuery.loadScript = function (url, callback) {
491    jQuery.ajax({
492        url: url,
493        dataType: 'script',
494        success: callback,
495        async: true
496    });
497}
498
499function openXrmFormAsModal(url) {
500    var d = $.Deferred();
501    // Display Busy Dialog
502    $(document).busyIndicator(true, "Gathering Information...");
503
504    if (url.indexOf("~") == 0) {
505        url = url.substring(1);
506    }
507
508    if (url.indexOf("/") == 0) {
509        url = url.substring(1);
510    }
511
512
513    $.ajax({
514        url: window.applicationBaseUrl + url,
515        cache: false,
516        success: function (html) {
517            // Close Our busy indicator
518            $(document).busyIndicator(false);
519            initializeModalForm(html).done(function (isConfirmed) { d.resolve(isConfirmed); });
520        },
521        error: function (err) {
522            $(document).busyIndicator(false);
523            Xrm.Utility.alertDialog("An Error Occurred. " + err.responseJSON || err.readyState);
524            d.fail(err);
525        }
526    });
527
528    return d;
529}
530
531
532function initializeModalForm(html) {
533    var isConfirmed = false;
534    var d = $.Deferred();
535
536    // Parse returned html
537    var $contents = $(html);
538
539    // Re-position Form Header into Modal Header.
540    $contents.find(".form-header-container").append($contents.find(".xrmform-header"));
541
542    // Get current number of modals, set ID accordingly.
543    var modalIdx = $("div#modals .modal").length;
544    var containerId = "modalcontainer" + modalIdx;
545    var modalId = "modallayout" + modalIdx;
546
547    $contents.attr("id", modalId);
548
549    var waitViewModel = $.Deferred();
550    if (typeof xrmViewModel !== 'undefined') {
551
552        var vmModal = Vue.extend({ template: $contents.wrap("<div>").parent().html(), methods: {} });
553        $("#modals").append('<div id="' + containerId + '"></div>');
554        new vmModal().$mount($('#' + containerId)[0]);
555
556        xrmViewModel.$nextTick(function () {
557            waitViewModel.resolve();
558        });
559    }
560    else {
561        $("#modals").append($('<div id="' + containerId + '"></div>').append($contents));
562        waitViewModel.resolve();
563    }
564
565    $.when(waitViewModel).then(function () {
566
567        //setTimeout(initializeForm, 1000);
568
569        $node = $('#' + modalId);
570        $form = $node.find("form.xrmform");
571
572        // Launch Modal
573        $node.on('shown.bs.modal', function (event) {
574            // Load dynamic scripts from modal dialog.
575            var scripts = $('script[type="dynscript"]').remove();
576            $(scripts).each(function () {
577                $.getScript(this.src, function () { });
578            });
579
580            waitViewModel = $.Deferred();
581            if (typeof xrmViewModel !== 'undefined') {
582                xrmViewModel.$nextTick(function () {
583                    waitViewModel.resolve();
584                });
585            }
586            else {
587                waitViewModel.resolve();
588            }
589
590            $.when(waitViewModel).then(function () {
591                initializeForm(true, $form);
592            });
593
594        });
595
596
597        $(window).trigger("resize");
598        $node.on('hidden.bs.modal', function (event) {
599            try {
600                d.resolve(isConfirmed);
601            } catch (err) {
602                console.warn(err.message);
603            }
604            // Clean up all hidden modals.
605            $('#modals div.modal:hidden').remove();
606        });
607        $node.modal();
608
609        if ($($form).find("input.xrm-button").length > 0) {
610            $($form).find("input.xrm-button").hide();
611        }
612
613        $node.on("click", "button.a-confirm", function (e) {
614            Xrm.Page.data.save(false, $form).done(function (e) {
615                isConfirmed = true;
616                e.preventDefault();
617                $node.modal('hide');
618                //re-enable opening form
619                //enableForm();
620            });
621            e.preventDefault();
622            return false;
623        });
624
625
626        $node.on("click", "button.a-close", function (e) {
627            $node.modal('hide');
628            e.preventDefault();
629            return false;
630        });
631    });
632
633    return d;
634}
635
636
637function getCurrentFormContainer() {
638    // find the most nested div.xrmform
639    var $container;
640    var _maxdepth = 0;
641    $("div.xrmform").each(function () {
642        var depth = $(this).parents("div.xrmform").length;
643        if (depth >= _maxdepth) {
644            _maxdepth = depth;
645            $container = $(this);
646        }
647    });
648    return $container;
649}
650
651function getCurrentNotificationContainer() {
652    // determine if this notification exists...
653    var $container = $("div#modals").find(".xrmform-notifications:visible").last();
654    if ($container.length == 0) {
655        $container = $(".xrmform-notifications").last();
656    }
657    return $container;
658}
659
660function addNotification(id, level, message, closeable, actions) {
661
662    id = id || new Date().getMilliseconds();
663    // remove existing notification with this id.
664    //$("div.xrmform-notification#" + id).remove();
665
666    var style;
667    var icon;
668    switch (level) {
669        case 1: // warning
670            style = "alert-warning";
671            break;
672        case 2: // error
673            style = "alert-danger";
674            break;
675        case 3: // loading
676            style = "alert-info";
677            break;
678        case 4: // success
679            style = "alert-success";
680            break;
681        case 0: // information
682        default:
683            style = "alert-info";
684            break;
685    }
686
687    var notif = $("<div>")
688        .addClass("xrmform-notification alert fade in " + (actions && actions.length ? 'clearfix' : ''))
689        .addClass(style)
690        .attr("id", id)
691        .html('<span class="' + (actions && actions.length ? 'pull-left' : '') + '">' + message + '</span>');
692
693    setTimeout(function () {
694        // determine if this notification exists...
695        var $container = getCurrentNotificationContainer();
696
697
698        var existing = $container.find("#" + id);
699        if (existing.length > 0) {
700            existing.replaceWith(notif);
701        } else {
702            $container.append(notif); //updated to first because modals open in new location, at the beginning of the content wrapper
703
704        }
705        if (closeable) {
706            notif.addClass("alert-dismissable").prepend('<button type="button" class="close readonly-enabled" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>');
707        }
708        if (actions) {
709            var $actions = $('<span class="pull-right">');
710            if (!$.isArray(actions)) {
711                actions = [actions];
712            }
713            $.each(actions, function (idx, action) {
714                var $action = $('<button>')
715                    .attr("type", "button")
716                    .addClass("btn btn-default readonly-enabled")
717                    .css("margin-left", "5px")
718                    .on("click", function () { $.isFunction(action.callback) ? action.callback.apply(this) : alert("missing callback!"); return false; })
719                    .text(action.name)
720                    .attr("title", action.tooltip || action.name);
721                if (action.icon) {
722                    $icon = $('<span class="glyphicon ' + action.icon + '"></span>');
723                    if (action.name != "") { $icon.css("padding-right", "5px"); }
724                    $action.prepend($icon);
725                }
726                $actions.append($action);
727                //if (idx < actions.length - 1) { $actions.append('<span style="padding-left: 10px; padding-right:10px" >|</span>');}
728            });
729            // Look for existing notification with same id...
730
731            notif.append($actions);
732        }
733
734    }, 0);
735    return $(notif);
736}
737
738function removeNotification(id, immediate) {
739    // determine if this notification exists...
740    var $container = getCurrentNotificationContainer();
741    if (!immediate) {
742        $container.children("div#" + id).fadeOut(500, function () {
743            $container.children("div#" + id).first().remove();
744        });
745    } else {
746        $container.children("div#" + id).first().remove();
747    }
748}
749
750function clearNotifications() {
751    var $container = getCurrentNotificationContainer();
752    $container.empty();
753}
754
755function toggleSideNavigation() {
756    var show = ($(".xrmform-tab-container").data("shownavigation") || "false").toLowerCase() === "true";
757    var mainBody = $("#main-body");
758    var sidebarMainMenu = $('#sidebar-menu .main-menu');
759    var mainContent = $('.main-content');
760
761    if (show) {
762        mainBody.addClass("col-md-9 col-lg-10");
763        // mainBody.scrollspy({ target: "#sidebar-menu" });
764        sidebarMainMenu.parent().show();
765        mainContent.find('h3').each(function () {
766            var hidden = $(this).closest(".xrmform-tab-withlabel").hasClass("hidden");
767            var parentid = $(this).closest(".xrmform-tab-withlabel").attr("id");
768            var contentType = $(this).hasClass("panel-title");
769            if (parentid != undefined && !hidden && !contentType) {
770                sidebarMainMenu.append('<li id="' + parentid + '-menu"><a class="nav-anchor" href="#' + parentid + '">' + $(this).html() + '</li>');
771            }
772        });
773        mainContent.find('h4').each(function () {
774            var hidden = $(this).closest(".xrmform-section").hasClass("hidden");
775            var parentid = $(this).closest(".xrmform-section").attr("id");
776            if (parentid != undefined && !hidden) {
777                prevTitle = sidebarMainMenu.find('#' + $(this).closest(".xrmform-tab-withlabel").attr("id") + '-menu');
778                prevTitle.not(":has(ul)").append('<ul class="sub-menu"></ul>');
779                prevTitle.find('.sub-menu').append('<li id="' + parentid + '-menu"><a class="nav-anchor" href="#' + parentid + '">' + $(this).html() + '</li>');
780            }
781        });
782        $('[data-spy="scroll"]').each(function () {
783            var $spy = $(this).scrollspy('refresh');
784        });
785
786        $('#sidebar-menu > ul').affix({
787            offset: {
788                top: function () {
789                    return $('.xrmform-header').offset().top - 20;
790                }
791            }
792        });
793
794    }
795    else {
796        mainBody.removeClass("col-md-9 col-lg-10");
797        sidebarMainMenu.parent().hide();
798    }
799}
800
801function verifyInlineEditDisplay(item) {
802    var $item = $(item);
803
804    if ($(item).closest(".xrmform-section").length > 0) {
805        //if section does not contain cells, then hide the button
806        if ($(item).closest(".xrmform-section").find(".xrmform-cell").length > 0) {
807            //need to determine whether to show/hide based on field display
808            var allDisabled = true;
809
810            $(item).closest(".xrmform-section").find(".xrmform-cell").each(function (idx, cell) {
811                $cell = $(cell);
812                //check input fields - if disabled, add readonly-enabled class
813                if ($cell.find("input").length > 0) {
814                    if ($cell.find("input").attr("disabled") != null) {
815                        $cell.find("input").addClass("readonly-enabled");
816                    } else {
817                        allDisabled = false;
818                    }
819                }
820
821                //check input fields
822                if ($cell.find("input[type=checkbox]").length > 0) {
823                    if ($cell.find("input[type=checkbox]").attr("readonly") != null) {
824                        $cell.find("input[type=checkbox]").addClass("readonly-enabled");
825                    } else {
826                        allDisabled = false;
827                    }
828                }
829
830                //check text area fields
831                if ($cell.find("textarea").length > 0) {
832                    if ($cell.find("textarea").attr("readonly") != null) {
833                        $cell.find("textarea").addClass("readonly-enabled");
834                    } else {
835                        allDisabled = false;
836                    }
837                }
838                //check button fields
839                if ($cell.find("button, .btn").length > 0) {
840                    if ($cell.find("button, .btn").attr("disabled") != null) {
841                        $cell.find("button, .btn").addClass("readonly-enabled");
842                    } else {
843                        allDisabled = false;
844                    }
845                }
846                // check select fields
847                if ($cell.find("select").length > 0) {
848                    if ($cell.find("select").attr("disabled") != null) {
849                        $cell.find("select").addClass("readonly-enabled");
850                    } else {
851                        allDisabled = false;
852                    }
853                }
854
855            });
856
857            if (!allDisabled) {
858                $(item).show();
859            }
860
861        }
862    }
863}
864
865function inlineEditUndo(item) {
866    if ($(item).closest(".xrmform-section").length > 0) {
867        var $section = $(item).closest(".xrmform-section")[0];
868        var $form = $(item).closest("form.xrmform");
869
870        $($section).removeClass("inline-editing");
871        $("a#close-edit").remove();
872
873        var $editElement = $("a#" + $section.id);
874
875        $($editElement).attr("data-mode", "edit");
876        $($editElement).attr("title", "Edit");
877        $($editElement).find("label").text("EDIT");
878        $($editElement).find("span").replaceWith("<span class=\"glyphicon glyphicon-edit\"/>");
879
880        //Undo Edits and reset arrays
881        $.each(editingInputFields, function (index, field) {
882            $("#" + field.key).val(field.value);
883            $("#" + field.key).trigger("change");
884            //console.log(field.key + ' : ' + field.value);
885        });
886
887        $.each(editingSelect2Fields, function (index, field) {
888            if ($("#" + field.key).length > 0) {
889                $("#" + field.key)[0].textContent = field.value;
890
891                //console.log(field.key + ' : ' + field.value);
892            }
893        });
894
895        $.each(editingRadioFields, function (index, field) {
896            if ($("#" + field.key).length > 0) {
897                $("#" + field.key)[0].checked = field.value;
898                // console.log(field.key + ' : ' + field.value);
899            }
900        });
901
902        $.each(editingCheckboxFields, function (index, field) {
903            if ($("#" + field.key).length > 0) {
904                $("#" + field.key)[0].checked = field.value;
905                // console.log(field.key + ' : ' + field.value);
906            }
907        });
908
909        editingInputFields = [];
910        editingSelect2Fields = [];
911        editingRadioFields = [];
912        editingCheckboxFields = [];
913
914        //enable other edit links
915
916        $form.find(".xrmform-section-header-inline").not("#" + $section.id).removeAttr("disabled");
917        $form.valid();
918        disableSection($section);
919        $form.data("isDirty", false);
920        $(item).trigger("undoComplete");
921    }
922}
923
924var editingInputFields = [];
925var editingSelect2Fields = [];
926var editingRadioFields = [];
927var editingCheckboxFields = [];
928
929function inlineEditClick(item) {
930    var $form = $(item).closest("form.xrmform");
931
932    if ($(item).closest(".xrmform-section").length > 0) {
933        var $section = $(item).closest(".xrmform-section")[0];
934
935        if ($(item).attr("data-mode") == "edit") {
936            $($section).addClass("inline-editing");
937            enableSection($section);
938
939            $(item).attr("data-mode", "save");
940            $(item).attr("title", "Save");
941            $(item).find("label").text("SAVE");
942
943            $(item).find("span").replaceWith("<span class=\"glyphicon glyphicon-floppy-disk\"/>");
944
945            //disable other edit links
946
947            $form.find(".xrmform-section-header-inline").not("#" + $section.id).attr("disabled", "disabled");
948
949            $(item).after("<a id=\"close-edit\" class=\"xrmform-section-header xrmform-section-header-inline inline-editing-close\" style=\"display: block;float:right;\" title=\"Undo Edits\"><span class=\"glyphicon glyphicon-share-alt glyphicon-flipped\" /></a>");
950
951            if ($($section).find(".inline-editing-close").length > 0) {
952                $($section).find(".inline-editing-close").each(function () {
953                    $(this).on("click", function () {
954                        inlineEditUndo(this);
955                    });
956                });
957            }
958
959            //push list of current values to store for undo functionality
960            $($section).find("input[type=hidden], .xrm-ui-input").each(function (idx, e) {
961                editingInputFields.push({
962                    key: e.id,
963                    value: e.value
964                });
965            });
966
967            //handle lookup/input fields
968            $($section).find(".select2-chosen").each(function (idx, e) {
969                editingSelect2Fields.push({
970                    key: e.id,
971                    value: e.textContent
972                });
973            });
974            //handle radio buttons
975            $($section).find(".xrm-ui-radiobutton").each(function (idx, e) {
976                editingRadioFields.push({
977                    key: e.id,
978                    value: e.checked
979                });
980            });
981
982            $($section).find("input[type=checkbox]").each(function (idx, e) {
983                editingCheckboxFields.push({
984                    key: e.id,
985                    value: e.checked
986                });
987            });
988        }
989        else if ($(item).attr("data-mode") == "save") {
990            $("a#close-edit").hide();
991            $(item).find("label").text("SAVING");
992            $(item).find("span").replaceWith("<span class=\"glyphicon glyphicon-refresh glyphicon-spin\" />");
993
994            var e = $.Event();
995            e.wait = new $.Deferred();
996            //e.wait.resolve();
997
998            if ($(item).closest(".xrmform-section").find("input").length > 0 && !$(item).closest(".xrmform-section").find("input").valid() ||
999                $(item).closest(".xrmform-section").find("textarea").length > 0 && !$(item).closest(".xrmform-section").find("textarea").valid()) {
1000                $($section).addClass("inline-editing");
1001                enableSection($section);
1002                $(item).attr("data-mode", "save");
1003                $(item).attr("title", "Save");
1004                $(item).find("label").text("SAVE");
1005                $(item).find("span").replaceWith("<span class=\"glyphicon glyphicon-floppy-disk\"/>");
1006                $("a#close-edit").show();
1007                $(item).trigger("saveError");
1008                //return;
1009            } else {
1010                e.wait.resolve();
1011            }
1012
1013            e.wait.done(function () {
1014                Xrm.Page.data.save(true, $form).done(function (e) {
1015                    e.preventDefault();
1016
1017                    $(item).attr("data-mode", "edit");
1018                    $(item).attr("title", "Edit");
1019                    $(item).find("label").text("EDIT");
1020                    $(item).find("span").replaceWith("<span class=\"glyphicon glyphicon-edit\"/>");
1021
1022                    //enable other edit links
1023                    var $form = $(item).closest("form.xrmform");
1024                    $form.find(".xrmform-section-header-inline").not("#" + $section.id).removeAttr("disabled");
1025
1026                    $("a#close-edit").remove();
1027
1028                    editingInputFields = [];
1029                    editingSelect2Fields = [];
1030                    editingRadioFields = [];
1031                    editingCheckboxFields = [];
1032
1033                    $(item).trigger("saveComplete");
1034
1035                    disableSection($section);
1036                    $($section).removeClass("inline-editing");
1037
1038                }).fail(function (e) {
1039                    $($section).addClass("inline-editing");
1040                    enableSection($section);
1041                    $(item).attr("data-mode", "save");
1042                    $(item).attr("title", "Save");
1043                    $(item).find("label").text("SAVE");
1044                    $(item).find("span").replaceWith("<span class=\"glyphicon glyphicon-floppy-disk\"/>");
1045                    $("a#close-edit").show();
1046                    $(item).trigger("saveError");
1047                    Xrm.Utility.alertDialog(e.responseJSON);
1048                });
1049
1050            }).fail(function (e) {
1051                $($section).addClass("inline-editing");
1052                enableSection($section);
1053                $(item).attr("data-mode", "save");
1054                $(item).attr("title", "Save");
1055                $(item).find("label").text("SAVE");
1056                $(item).find("span").replaceWith("<span class=\"glyphicon glyphicon-floppy-disk\"/>");
1057                $("a#close-edit").show();
1058                $(item).trigger("saveError");
1059            });
1060        }
1061    }
1062}
1063
1064
1065
1066$(function () {
1067    window.tabEvent = false;
1068    window.closingSubForm = false;
1069
1070    $('iframe').on("click", function () { $(this).contents().find("body").focus(); });
1071
1072    //Supress menu clicks
1073    $('.noclick').on("click", function (e) {
1074        if (e.stopPropagation) {
1075            e.stopPropagation();
1076        }
1077        else if (window.event) {
1078            window.event.cancelBubble = true;
1079        }
1080    });
1081
1082    // Ignore grid links.
1083    $('body').on("click", "div.xrm-ui-grid-toolbar a[href='#']", function (e) {
1084        e.preventDefault();
1085    });
1086    toggleSideNavigation();
1087
1088    // Handle modal anchors
1089    $('body').on("click", "a[target='xrm_modal']", function (event) {
1090        event.preventDefault();
1091        openXrmFormAsModal($(this).attr("href"));
1092        return false;
1093    });
1094
1095
1096});
1097
1098function scrollToElement($element) {
1099    // scroll item into view
1100    if ($element.length > 0 && !isInView($(".xrmform-tab-container"), $element)) {
1101        $(".xrmform-tab-container").scrollTo($element);
1102    }
1103}
1104
1105function isInView($container, $element) {
1106    var conTop = $container.scrollTop();
1107    var conBottom = conTop + $container.height();
1108
1109    var elemTop = $element.position().top;
1110    var elemBottom = elemTop + $element.height();
1111
1112    return ((elemBottom <= conBottom) && (elemTop >= conTop));
1113}
1114
1115function isDirty($form) {
1116    var $form = $form || $("form.xrmform").last();
1117    var parentFormDirty = false;
1118    $.each(window._PARENT_FORMS, function (idx, item) {
1119        if (item.isDirty) {
1120            parentFormDirty = true;
1121        }
1122    });
1123    var gridsDirty = false;
1124    $(".xrm-ui-grid").each(function () {
1125        if ($(this).xrmgrid("hasPendingEdits")) {
1126            gridsDirty = true;
1127        }
1128    });
1129
1130    return ($form.data("isDirty") || gridsDirty || parentFormDirty);
1131
1132}
1133
1134function extractModel($form) {
1135    var $form = $form || $("form.xrmform").last();
1136    var model = {};
1137    var keyvaluepairs = $form.serializeArray();
1138    $.each(keyvaluepairs, function (idx, keyvaluepair) {
1139        // First split key on .
1140        var parent = model;
1141        var path = keyvaluepair.name.split(".");
1142        for (var i = 0; i < path.length - 1; i++) {
1143            parent[path[i]] = parent[path[i]] || {};
1144            parent = parent[path[i]];
1145        }
1146        // Finally Set the value
1147        parent[path[path.length - 1]] = keyvaluepair.value;
1148    });
1149    return model;
1150}
1151
1152function updateModel(model) {
1153
1154}
1155
1156
1157$(window).on("show.bs.modal resize", function (e) {
1158    var height = $(window).height() - 200;
1159    var width = $(window).width() < 768 ? $(window).width() : $(window).width() - 20;
1160
1161    $(".modal-body").each(function () {
1162        $(this).css("max-width", width);
1163        $(this).css("max-height", height);
1164    });
1165});
1166
1167
1168var FormType = {
1169    Undefined: 0,
1170    Create: 1,
1171    Update: 2,
1172    ReadOnly: 3,
1173    Disabled: 4
1174}
1175
1176Xrm = {};
1177Xrm.Utility = {};
1178Xrm.Utility.alertDialog = function (message, callback) {
1179    var $modal = $("#alert-dialog");
1180    if ($modal.length == 0) {
1181
1182        $modal = $('<div class="modal" id="alert-dialog" style="z-index: 9999;" data-keyboard="false" data-backdrop="static" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> \
1183                                <div class="vertical-alignment-helper"> \
1184                                    <div class="modal-dialog modal-md vertical-align-center"> \
1185                                        <div class="modal-content"> \
1186                                            <div class="modal-header"> \
1187                                                <h4 class="modal-title" id="myModalLabel"></h4> \
1188                                            </div> \
1189                                            <div class="modal-body" > \
1190                                                <span><img src="' + applicationBaseUrl + 'Images/grid/warning.png" /></span> \
1191                                                <span>' + message + '</span>\
1192                                            </div > \
1193                                            <div class="modal-footer"><button type="button" class="btn btn-primary" data-dismiss="modal">Close</button></div> \
1194                                        </div> \
1195                                    </div> \
1196                                </div > \
1197                            </div>').appendTo('body');
1198
1199
1200    }
1201
1202    $modal.on("hidden.bs.modal", function (e) {
1203        $modal.remove();
1204        if ($.isFunction(callback)) { setTimeout(callback, 0); }
1205    });
1206
1207    // Launch Modal
1208    $modal.modal();
1209};
1210
1211// Xrm.Page
1212Xrm.Page = {};
1213
1214Xrm.Page.data = {};
1215
1216Xrm.Page.data.save = function (saveSectionOnly, $form) {
1217    // create deferred object for calling code.
1218    var d = $.Deferred();
1219
1220    //determine if it is a main form or modal
1221    $form = $form || $('div#modals').find("form.xrmform").last() || $('form.xrmform').last();
1222    ExecuteSave(saveSectionOnly, $form, d);
1223
1224    return d;
1225};
1226
1227function ExecuteSave(saveSectionOnly, $form, d) {
1228    removeNotification("oper", true);
1229    switch ($form.find("#submitButton").val()) {
1230        case "back":
1231        case "cancel":
1232            return;
1233            break;
1234        default:
1235            var gridisDirty = false;
1236            $(".xrm-ui-grid").each(function () {
1237                if ($(this).xrmgrid("hasPendingEdits")) {
1238                    gridisDirty = true;
1239                }
1240            });
1241            if (gridisDirty) {
1242                alert("There are un-saved changes in one of the grids. Please resolve and save again.");
1243                d.fail();
1244                return d;
1245            }
1246            if (!saveSectionOnly) {
1247                $form.validate();
1248                if (!$form.valid()) {
1249                    setTimeout(function () {
1250                        d.reject();
1251                    }, 0);
1252                    return d;
1253                }
1254            }
1255            break;
1256    }
1257
1258    // Prompt if we have a confirmation Attribute.
1259    // notification
1260    $confirm = $.Deferred();
1261    if ($form.attr("data-confirmation") == "true") {
1262        // setup modal and button click events
1263        if ($('#confirm-save-modal').length == 0) {
1264            $('body').append('<div class="modal fade" id="confirm-save-modal" role="dialog"> \
1265                                        <div class="vertical-alignment-helper"> \
1266                                            <div class="modal-dialog vertical-align-center"> \
1267                                                <div class="modal-content"> \
1268                                                    <form class="form-horizontal" method="post" id="delete_file_form"> \
1269                                                        <div class="modal-body"> \
1270                                                            ' + $form.attr("data-confirmation-msg") + ' \
1271                                                        </div> \
1272                                                        <div class="modal-footer"> \
1273                                                            <button data-dismiss="modal" class="btn btn-danger" name="confirm_save" id="confirm-save-button">Ok</button> \
1274                                                            <button data-dismiss="modal" class="btn btn-default" name="confirm_save" id="cancel-save-button">Cancel</button> \
1275                                                        </div> \
1276                                                     </form> \
1277                                                 </div> \
1278                                             </div> \
1279                                           </div> \
1280                                        </div>');
1281        }
1282
1283        // setup click events with save logic
1284        $('#confirm-save-modal .modal-footer #confirm-save-button').off('click').on('click', function (event) {
1285            $confirm.resolve();
1286        });
1287
1288        $('#confirm-save-modal .modal-footer #cancel-save-button').off('click').on('click', function (event) {
1289            $confirm.reject();
1290        });
1291
1292        // show modal
1293        $('#confirm-save-modal').modal('show');
1294    } else {
1295        $confirm.resolve();
1296    }
1297    // If no confirmation, die a horrible death
1298    $confirm.fail(function () { d.reject(); });
1299    // Wait for confirmation...
1300    $confirm.done(function () {
1301        // Set ownerid field to disabled to prevent submitting.
1302        $form.find("input[name^='ownerid']").attr("disabled", "disabled");
1303        var data = new FormData($form[0]);
1304        var opts = {
1305            url: $form.attr("action"),
1306            data: data,
1307            cache: false,
1308            contentType: false,
1309            processData: false,
1310            type: 'POST'
1311        }
1312        if (data.fake) {
1313            // browser doesn't support FormData
1314            opts.xhr = function () { var xhr = jQuery.ajaxSettings.xhr(); xhr.send = xhr.sendAsBinary; return xhr; }
1315            opts.contentType = "multipart/form-data; boundary=" + data.boundary;
1316            opts.data = data.toString();
1317        }
1318
1319        if (!saveSectionOnly) {            
1320            $(document).busyIndicator(true, "Saving Changes...", false);
1321            disableForm();
1322        }
1323
1324        $.ajax(opts)
1325            .done(function (reference) {
1326                // Reset form dirty flag (allows redirect)
1327                $form.data("isDirty", false);
1328                var e = $.Event();
1329                if (reference) {
1330                    e.data = reference;
1331                }
1332                d.resolve(e);
1333                if (!e.isDefaultPrevented()) {
1334                    // Save successful, now re-retrieve record
1335                    location.replace(location.href.replace("new", reference.Id));
1336                } else {
1337                    $(document).busyIndicator(false);
1338                }
1339            })
1340            .fail(function (a, b, c) {
1341                d.reject(a);
1342                if (!saveSectionOnly) {
1343                    enableForm();
1344                    $(document).busyIndicator(false);
1345                    addNotification("oper", 2, a.responseJSON || c, true);
1346                }
1347            });
1348
1349        //$.post($form.attr("action"), $form.serialize(), null, "json")
1350    });
1351
1352    return d;
1353}
1354
1355Xrm.Page.data.refresh = function (save) {
1356
1357};
1358
1359Xrm.Page.data.entity = {};
1360
1361Xrm.Page.data.entity.getIsDirty = function ($form) {
1362    $form = $(item).closest("form.xrmform");
1363    var parentFormDirty = false;
1364    $.each(window._PARENT_FORMS, function (idx, item) {
1365        if (item.isDirty) {
1366            parentFormDirty = true;
1367        }
1368    });
1369    var gridsDirty = false;
1370    $(".xrm-ui-grid").each(function () {
1371        if ($(this).xrmgrid("hasPendingEdits")) {
1372            gridsDirty = true;
1373        }
1374    });
1375
1376    return ($form.data("isDirty") || gridsDirty || parentFormDirty);
1377}
1378
1379Xrm.Page.data.entity.getId = function ($form) {
1380    var $form = $(item).closest("form.xrmform");
1381    return $form.find("#Id").val();
1382}
1383
1384Xrm.Page.data.entity.getEntityName = function ($form) {
1385    var $form = $(item).closest("form.xrmform");
1386    return $form.find("#LogicalName").val();
1387}
1388// Xrm.Page.ui
1389Xrm.Page.ui = {};
1390
1391Xrm.Page.ui.getFormType = function ($form) {
1392    var $form = $(item).closest("form.xrmform");
1393    if ($form.length == 0) { return FormType.Undefined; }
1394    if ($form.find("#FormIsReadOnly").val() == "true") return FormType.ReadOnly;
1395    if ($form.find("#Id").val() == "00000000-0000-0000-0000-000000000000") return FormType.Create;
1396    return FormType.Update;
1397}
1398
1399$(document).on('show.bs.modal', '.modal', function () {
1400    var zIndex = 1050 + (10 * $('.modal:visible').length);
1401    $(this).css('z-index', zIndex);
1402    var bdzindex = zIndex - 1;
1403    // $('.modal-backdrop').not('.modal-stack').css('z-index', zIndex - 1).addClass('modal-stack zIndex-' + bdzindex);
1404});
1405$(document).on('shown.bs.modal', '.modal', function () {
1406    var zIndex = $(this).css('z-index');
1407    var bdzindex = zIndex - 1;
1408    $('.modal-backdrop').not('.modal-stack').css('z-index', bdzindex).addClass('modal-stack');
1409});
1410
1411$(document).on('hidden.bs.modal', '.modal', function () {
1412    if ($('.modal:visible').length > 0) {
1413        $(document.body).addClass('modal-open');
1414        $('.modal:visible').focus();
1415
1416    }
1417    //var zIndex = $(this).css('z-index') - 1;
1418    //$('.modal-backdrop.modal-stack.zIndex-' + zIndex).remove();
1419
1420    //$('.modal:visible').length && $(document.body).addClass('modal-open');
1421});

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.