PageSourceSearch

https://actee.com/App_Plugins/UmbracoForms/Assets/Themes/Default/umbracoforms.js

js actee.com collected 2026-10-07 15:26:41 UTC 23,500 bytes, 568 lines download raw bytes

1(function () {
2
3
4    // polyfill for matches and closest
5    if (!Element.prototype.matches) Element.prototype.matches = Element.prototype.msMatchesSelector;
6    if (!Element.prototype.closest) Element.prototype.closest = function (selector) {
7        var el = this;
8        while (el) {
9            if (el.matches(selector)) {
10                return el;
11            }
12            el = el.parentElement;
13        }
14    };
15
16
17
18    //execute init() on document ready
19    if (document.readyState === "complete" || (document.readyState !== "loading" && !document.documentElement.doScroll)) {
20        listen();
21    } else {
22        document.addEventListener("DOMContentLoaded", listen);
23    }
24
25    function listen() {
26        if (typeof umbracoFormsCollection === "undefined") {
27            //this will occur if this js file is loaded before the inline scripts, in which case
28            //we'll listen for the inline scripts to execute a custom event.
29            document.addEventListener("umbracoFormLoaded", init);
30        }
31        else {
32            initCollection(umbracoFormsCollection);
33        }
34    }
35
36    function initCollection(formsCollection) {
37        configureUmbracoFormsValidation();
38
39        for (var i = 0; i < formsCollection.length; i++) {
40            init({ form: formsCollection[i] });
41        }
42    }
43
44    function init(e) {
45
46        var formItem = JSON.parse(decodeURI(e.form));
47
48        var forms = document.querySelectorAll('.umbraco-forms-form');
49
50        for( var i = 0; i < forms.length; i++) {
51            var form = forms[i];
52
53            dependencyCheck(form);
54
55            var page = form.querySelector('.umbraco-forms-page');
56            var conditions = new UmbracoFormsConditions(page,
57                formItem.fieldSetConditions,
58                formItem.fieldConditions,
59                formItem.recordValues);
60            conditions.watch();
61        }
62    }
63
64    /** Configures the jquery validation for Umbraco forms */
65    function configureUmbracoFormsValidation() {
66
67        if (window.aspnetValidation !== undefined) {
68            // Asp-net validation setup:
69
70            var validationService = new aspnetValidation.ValidationService();
71
72            // TODO: equivilant to this:
73            /*
74            $.validator.setDefaults({
75                ignore: ":hidden"
76            });
77            */
78           
79            function required(value, element, params) {
80                // Handle single and multiple checkboxes:
81                if(element.type.toLowerCase() === "checkbox" || element.type.toLowerCase() === "radio") {
82                    var allCheckboxesOfThisName = element.form.querySelectorAll("input[name='"+element.name+"']");
83                    for (var i=0; i<allCheckboxesOfThisName.length; i++) {
84                        if (allCheckboxesOfThisName[i].checked === true) {
85                            return true;
86                        }
87                    }
88                    return false;
89                }
90                return Boolean(value);
91            }
92            validationService.addProvider("requiredcb", required);
93            validationService.addProvider("required", required);// this will go instead of the build-in required.
94
95
96            function umbracoforms_regex(value, element, params) {
97                if (!value || !params.pattern) {
98                    return true;
99                }
100        
101                var r = new RegExp(params.pattern);
102                return r.test(value);
103            }
104            validationService.addProvider("umbracoforms_regex", umbracoforms_regex);
105
106            function wrapProviderWithIgnorerBehaviour(provider) {
107                return function(value, element, params) {
108                    
109                    // If field is hidden we ignorer the validation.
110                    if (element.offsetParent === null) {
111                        return true;
112                    }
113
114                    return provider(value, element, params);
115                }
116            }
117
118            // we can only incept with default validator if we do it after bootstrapping but before window load event triggers validationservice.
119            window.addEventListener('load', function() {
120
121                // Wrap all providers with ignorer hidden fields logic:
122                for (var key in validationService.providers) {
123                    validationService.providers[key] = wrapProviderWithIgnorerBehaviour(validationService.providers[key]);
124                }
125            });
126
127            // bootstrap validation service.
128            validationService.bootstrap();
129
130            // Without jquery validation, the previous page submit button click isn't sent with it's name,
131            // so can't be used server-side to determine whether to go forward or back.
132            // Hence we'll use an alternate method, setting a hidden field that's also used in the check.
133            var handlePreviousClicked = function () {
134                this.form.elements["PreviousClicked"].value = "clicked";
135            };
136            var previousButtonElements = document.getElementsByClassName("prev cancel");
137            for (var i = 0; i < previousButtonElements.length; i++) {
138                previousButtonElements[i].form.elements["PreviousClicked"].value = "";
139                previousButtonElements[i].addEventListener('click', handlePreviousClicked, false);
140            }
141
142        } else if (typeof jQuery === "function" && $.validator) {
143            //Jquery validation setup
144
145            $.validator.setDefaults({
146                ignore: ":hidden"
147            });
148
149            $.validator.unobtrusive.adapters.addBool("requiredcb", "required");
150
151
152            $.validator.addMethod("umbracoforms_regex", function (value, element) {
153
154                var regex = $(element).attr("data-regex");
155                var val = $(element).val();
156                if (val.length === 0) {
157                    return true;
158                }
159                return val.match(regex);
160            });
161
162            $.validator.unobtrusive.adapters.addBool("regex", "umbracoforms_regex");
163
164            var submitInputs = document.querySelectorAll(".umbraco-forms-form input[type=submit]:not(.cancel)");
165            for (var i = 0; i < submitInputs.length; i++) {
166                var input = submitInputs[i];
167                input.addEventListener("click", function (evt) {
168                    evt.preventDefault();
169                    var frm = $(this).closest("form");
170                    frm.validate();
171                    if (frm.valid()) {
172                        frm.submit();
173                        this.setAttribute("disabled", "disabled");
174    
175                    }
176                }.bind(input));
177            }
178        }
179
180    }
181
182    /**
183     * method to determine if Umbraco Forms can run and has the required dependencies loaded
184     * @param {Form Element} formEl the element of the form
185     */
186    function dependencyCheck(formEl) {
187        // Only perform check if the global 'Umbraco.Sys' is null/undefined.
188        // If present means we are in backoffice & that this is being rendered as a macro preview and We do not need to perform this check here.
189        // Similarly we need a check for if running in a rich text editor.
190        var isBackOffice = function () {
191            return typeof Umbraco !== "undefined" && typeof Umbraco.Sys !== "undefined";
192        };
193        var isBackOfficeRte = function () {
194            return document.body.id === "tinymce";
195        };
196        if (isBackOffice() || isBackOfficeRte()) {
197            return;
198        }
199
200        var errorElement = document.createElement("div");
201        errorElement.className = "umbraco-forms missing-library";
202        errorElement.style.color = "#fff";
203        errorElement.style.backgroundColor = "#9d261d";
204        errorElement.style.padding = "15px";
205        errorElement.style.margin = "10px 0";
206        var errorMessage = "";
207
208        //Ensure umbracoForm is not null
209        if (formEl) {
210
211            //Check to see if the message for the form has been inserted already
212            var checkForExistinhgErr = formEl.getElementsByClassName('umbraco-forms missing-library');
213            if (checkForExistinhgErr.length > 0) {
214                return;
215            }
216
217            var hasValidationFramework = false;
218
219            if (window.jQuery && $ && $.validator !== undefined) {
220                hasValidationFramework = true;
221            } else if (window.aspnetValidation !== undefined) {
222                hasValidationFramework = true;
223            }
224
225            if(hasValidationFramework === false) {
226                errorMessage = errorMessage + "Umbraco Forms requires a validation framework to run, please read documentation for posible options.";
227            }
228
229            if (errorMessage !== "") {
230                errorElement.innerHTML = errorMessage + '<br/> <a href="https://our.umbraco.org/documentation/products/umbracoforms/developer/Prepping-Frontend/" target="_blank" style="text-decoration:underline;
230 color:#fff;">See Umbraco Forms Documentation</a>';
231
232                formEl.insertBefore(errorElement, formEl.childNodes[0]);
233            }
234        }
235    }
236
237    /**
238     * Class to handle Umbraco Forms conditional statements
239     * @param {any} form a reference to the form
240     * @param {any} fieldsetConditions a reference to the fieldset conditions
241     * @param {any} fieldConditions a reference to the field conditions
242     * @param {any} values the form values
243     * @return {Object} reference to the created class
244     */
245    function UmbracoFormsConditions(form, fieldsetConditions, fieldConditions, values) {
246
247        //our conditions "class" - must always be newed to work as it uses a form instance to operate on
248        //load all the information from the dom and serverside info and then the class will take care of the rest
249
250        var self = {};
251        self.form = form;
252        self.fieldsetConditions = fieldsetConditions;
253        self.fieldConditions = fieldConditions;
254        self.values = values;
255        self.dataTypes = {};
256
257        //Iterates through all the form elements found on the page to update the registered value
258        function populateFieldValues(page, formValues, dataTypes) {
259
260            var selectFields = page.querySelectorAll("select");
261            for(var i=0; i<selectFields.length; i++) {
262                var field = selectFields[i];
263                formValues[field.getAttribute("id")] = field.value ? field.querySelector("option[value='" + field.value.replace(/'/g, "\\'") + "']").innerText : null;
264                dataTypes[field.getAttribute("id")] = "select";
265            }
266
267            var textareaFields = page.querySelectorAll("textarea");
268            for(var i=0; i<textareaFields.length; i++) {
269                var field = textareaFields[i];
270                formValues[field.getAttribute("id")] = field.value;
271                dataTypes[field.getAttribute("id")] = "textarea";
272            }
273
274            // clear out all saved checkbox values to we can safely append
275            var checkboxFields = page.querySelectorAll("input[type=checkbox]");
276            for(var i=0; i<checkboxFields.length; i++) {
277                var field = checkboxFields[i];
278                formValues[field.getAttribute("name")] = null;
279                dataTypes[field.getAttribute("id")] = "checkbox";
280            }
281
282            //$page.find("input").each(function () {
283            var inputFields = page.querySelectorAll("input");
284            for(var i=0; i<inputFields.length; i++) {
285                var field = inputFields[i];
286
287                if (field.getAttribute('type') === "text" || field.getAttribute("type") === "hidden") {
288                    formValues[field.getAttribute("id")] = field.value;
289                    dataTypes[field.getAttribute("id")] = "text";
290                }
291
292                if (field.getAttribute('type') === "radio") {
293                    if (field.matches(':checked')) {
294                        formValues[field.getAttribute("name")] = field.value;
295                        dataTypes[field.getAttribute("id")] = "radio";
296                    }
297                }
298
299                if (field.getAttribute("type") === "checkbox") {
300                    if (field.getAttribute("id") !== field.getAttribute("name")) {
301                        if (field.matches(":checked")) {
302                            if (formValues[field.getAttribute("name")] === null) {
303                                formValues[field.getAttribute("name")] = field.value;
304                            }
305                            else {
306                                formValues[field.getAttribute("name")] += ";;" + field.value;
307                            }
308                        }
309                    }
310                    else {
311                        formValues[field.getAttribute("name")] = (field.matches(":checked") ? "true" : "false");
312                    }
313                }
314            }
315        }
316
317        /* Public api */
318
319        self.operators = {
320            Is: function (value, expected, dataType) {
321                if ((value || "") === expected) {
322                    return true;
323                }
324                if (value == null) {
325                    return (expected == value);
326                }
327
328                if (dataType === "checkbox") {
329                    if (expected.toUpperCase() === "TRUE" || expected.toUpperCase() === "ON") {
330                        expected = "true"
331                    } else if (expected.toUpperCase() === "FALSE" || expected.toUpperCase() === "OFF") {
332                        expected = "false"
333                    }
334                }
335
336                var values = value.split(';;');
337                var matchingExpected = values.filter(
338                    function (o) {
339                        return o === expected;
340                    });
341                return matchingExpected.length > 0;
342            },
343            IsNot: function (value, unexpected, dataType) {
344                if (value == null) {
345                    return (unexpected != value);
346                }
347                var values = value.split(';;');
348                var matchingUnexpected = values.filter(
349                    function (o) {
350                        return o === unexpected;
351                    });
352
353                if (dataType === "checkbox") {
354                    if (unexpected.toUpperCase() === "TRUE" || unexpected.toUpperCase() === "ON") {
355                        unexpected = "true"
356                    } else if (unexpected.toUpperCase() === "FALSE" || unexpected.toUpperCase() === "OFF") {
357                        unexpected = "false"
358                    }
359                }
360                return (value || "") !== unexpected && matchingUnexpected.length === 0;
361            },
362            GreaterThen: function (value, limit, dataType) {
363                return parseInt(value) > parseInt(limit);
364            },
365            LessThen: function (value, limit, dataType) {
366                return parseInt(value) < parseInt(limit);
367            },
368            StartsWith: function (value, criteria, dataType) {
369                return value && value.indexOf(criteria) === 0;
370            },
371            EndsWith: function (value, criteria, dataType) {
372                return value && value.indexOf(criteria) === value.length - criteria.length;
373            },
374            Contains: function (value, criteria, dataType) {
375                return value && value.indexOf(criteria) > -1;
376            }
377        };
378
379        self.watch = function () {
380            // This is a special case for pikaday
381            // The only way around to pickup the value, for now, is to 
382            // subscribe to blur events 
383            var datepickerfields = self.form.querySelectorAll('.datepickerfield');
384            for(var i = 0; i < datepickerfields.length; i++) {
385                var field = datepickerfields[i];
386                field.addEventListener('blur', function () {
387                    if(this.value===""){
388                        // Here comes the hack
389                        // Force the hidden datepicker field the datepicker field
390                        var id = this.getAttribute("id");
391                        var hiddenDatePickerField = id.substr(0, id.length-2);
392                        self.values[hiddenDatePickerField]="";
393                        document.getElementById(hiddenDatePickerField).value="";// sadly we cant use querySelector with current mark-up (would need to prefix IDs)
394                    }
395    
396                    populateFieldValues(self.form, self.values, self.dataTypes);
397                    //process the conditions
398                    self.run();
399                }.bind(field));
400            }
401            //subscribe to change events
402            var changeablefields = self.form.querySelectorAll("input, textarea, select");
403            for(var i = 0; i < changeablefields.length; i++) {
404                var field = changeablefields[i];
405                field.addEventListener("change", function () {
406                    populateFieldValues(self.form, self.values, self.dataTypes);
407                    //process the conditions
408                    self.run();
409                }.bind(field));
410            }
411
412            //register all values from the current fields on the page
413            populateFieldValues(self.form, self.values, self.dataTypes);
414
415            //the initial run-through of all the conditions
416            self.run();
417        };
418
419        self.run = function () {
420            var fsId,
421                fieldId,
422
423                /*
424                fsConditions = params.fsConditions || {},
425                fieldConditions = params.fieldConditions || {},
426                values = params.values || {},*/
427
428                cachedResults = {};
429
430            function evaluateRuleInstance(rule) {
431                var value = self.values[rule.field],
432                    dataType = self.dataTypes[rule.field],
433                    func = self.operators[rule.operator],
434                    result = value !== null && func(value, rule.value, dataType);
435                return result;
436            }
437
438            function evaluateRule(rule) {
439                var dependencyIsVisible = true;
440
441                if (self.fieldConditions[rule.field]) {
442                    dependencyIsVisible = isVisible(rule.field, self.fieldConditions[rule.field]);
443                }
444
445                if (dependencyIsVisible) {
446                    return evaluateRuleInstance(rule);
447                }
448                else {
449                    return false;
450                }
451            }
452
453            function evaluateCondition(id, condition) {
454                // This was once pretty. Now it needs refactoring again. :)
455
456                var any = condition.logicType === "Any",
457                    all = condition.logicType === "All",
458                    fieldsetVisibilities = {},
459                    hasHiddenFieldset = false,
460                    success = true,
461                    rule,
462                    i;
463
464                for (i = 0; i < condition.rules.length; i++) {
465                    rule = condition.rules[i];
466
467                    if (id === rule.field || id === rule.fieldsetId) {
468                        throw new Error("Field or fieldset " + id + " has a condition on itself.");
469                    }
470
471                    if (fieldsetVisibilities[rule.fieldsetId] !== undefined) {
472                        continue;
473                    }
474
475                    if (self.fieldsetConditions[rule.fieldsetId]) {
476
477                        fieldsetVisibilities[rule.fieldsetId] =
478                            isVisible(rule.fieldsetId, self.fieldsetConditions[rule.fieldsetId]);
479
480                        if (!fieldsetVisibilities[rule.fieldsetId]) {
481                            hasHiddenFieldset = true;
482                        }
483                    }
484                    else {
485                        fieldsetVisibilities[rule.fieldsetId] = true;
486                    }
487                }
488
489                if (all && hasHiddenFieldset) {
490                    return false;
491                }
492
493                for (i = 0; i < condition.rules.length; i++) {
494                    rule = condition.rules[i];
495
496                    if (fieldsetVisibilities[rule.fieldsetId]) {
497                        success = evaluateRule(condition.rules[i]);
498                    }
499                    else {
500                        success = false;
501                    }
502
503                    if (any && success) {
504                        break;
505                    }
506                    if (all && !success) {
507                        break;
508                    }
509                }
510                return success;
511            }
512
513            function evaluateConditionVisibility(id, condition) {
514                var show = condition.actionType === "Show",
515                    cachedResult = cachedResults[id];
516
517                var success;
518                if (cachedResult === undefined) {
519                    cachedResults[id] = show; // set default value to avoid circular issues
520                    success = (cachedResults[id] = evaluateCondition(id, condition));
521                } else {
522                    success = cachedResult;
523                }
524
525                var visible = !(success ^ show);
526                return visible;
527            }
528
529            function isVisible(id, condition) {
530                if (condition) {
531                    return evaluateConditionVisibility(id, condition);
532                }
533                return true;
534            }
535
536            function handleCondition(element, id, condition, type) {
537                var shouldShow = isVisible(id, condition);
538                if (element) {
539                    if (shouldShow) {
540                        element.style.display = "";
541                    }
542                    else {
543                        element.style.display = "none";
544                    }
545                }
546            }
547
548            for (fsId in self.fieldsetConditions) {
549                if (self.fieldsetConditions.hasOwnProperty(fsId)) {
550                    handleCondition(document.getElementById(fsId), fsId, self.fieldsetConditions[fsId], "Fieldset");// sadly we cant use querySelector with current mark-up (would need to prefix IDs)
551                }
552            }
553
554            for (fieldId in self.fieldConditions) {
555                if (self.fieldConditions.hasOwnProperty(fieldId)) {
556                    if (document.getElementById(fieldId)) {
557                        handleCondition(document.getElementById(fieldId).closest(".umbraco-forms-field"),// sadly we cant use querySelector with current mark-up (would need to prefix IDs)
558                            fieldId,
559                            self.fieldConditions[fieldId],
560                            "Field");
561                    }
562                }
563            }
564        };
565
566        return self;
567    }
568})();

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.