PageSourceSearch

https://www.jet2holidays.com/%5Csitecore%20modules/Web/ExperienceForms/scripts/form.tracking.js

js jet2holidays.com collected 2026-10-01 12:39:38 UTC 9,707 bytes, 240 lines download raw bytes

1(function($) {
2    var eventIds = {
3        fieldCompleted: "2ca692cb-bdb2-4c9d-a3b5-917b3656c46a",
4        fieldError: "ea27aca5-432f-424a-b000-26ba5f8ae60a"
5    };
6
7    function endsWith(str, suffix) {
8        return str.toLowerCase().indexOf(suffix.toLowerCase(), str.length - suffix.length) !== -1;
9    }
10
11    function getOwner(form, elementId) {
12        var targetId = elementId.slice(0, -(elementId.length - elementId.lastIndexOf(".") - 1)) + "Value";
13        return form.find("input[name=\"" + targetId + "\"]")[0];
14    }
15
16    function getSessionId(form) {
17        var formId = form[0].id;
18        var targetId = formId.slice(0, -(formId.length - formId.lastIndexOf("_") - 1)) + "FormSessionId";
19        var element = form.find("input[type='hidden'][id=\"" + targetId + "\"]");
20        return element.val();
21    }
22
23    function getElementName(element) {
24        var fieldName = element.name;
25        if (!endsWith(fieldName, "value")) {
26            return getFieldGuid(fieldName) + "Value";
27        }
28
29        return fieldName;
30    }
31
32    function getElementValue(element) {
33        var value;
34        if (element.type === "checkbox" || element.type === "radio") {
35            var form = $(element).closest("form");
36            var checkboxList = form.find("input[name='" + element.name + "']");
37            if (checkboxList.length > 1) {
38                value = [];
39                checkboxList = checkboxList.not(":not(:checked)");
40                $.each(checkboxList, function () {
41                    value.push($(this).val());
42                });
43            } else {
44                value = element.checked ? "1" : "0";
45            }
46        } else {
47            value = $(element).val();
48        }
49
50        if (value && Object.prototype.toString.call(value) === "[object Array]") {
51            value = value.join(",");
52        }
53
54        return value;
55    }
56
57    function getFieldGuid(fieldName) {
58        var searchPattern = "fields[";
59        var index = fieldName.toLowerCase().indexOf(searchPattern);
60        return fieldName.substring(0, index + searchPattern.length + 38);
61    }
62
63    function getFieldName(element) {
64        return $(element).attr("data-sc-field-name");
65    }
66
67    $.fxbFormTracker = function (el, options) {
68        this.el = el;
69        this.$el = $(el);
70        this.options = $.extend({}, $.fxbFormTracker.defaultOptions, options);
71        this.init();
72    },
73
74        $.fxbFormTracker.parse = function (formId) {
75            var $form = $(formId);
76            $form.track_fxbForms();
77
78            var isSessionExpired = parseInt($("[name$='.IsSessionExpired']").val());
79            if (isSessionExpired) {
80                alert($.fxbFormTracker.texts.expiredWebSession);
81            }
82        },
83
84        $.extend($.fxbFormTracker,
85            {
86                defaultOptions: {
87                    formId: null,
88                    sessionId: null,
89                    fieldId: null,
90                    fieldValue: null,
91                    duration: null
92                },
93
94                prototype: {
95                    init: function () {
96                        this.options.duration = 0;
97                        this.options.formId = this.$el.attr("data-sc-fxb");
98                    },
99
100                    startTracking: function () {
101                        this.options.sessionId = getSessionId(this.$el);
102
103                        var self = this;
104                        var inputs = this.$el.find("input:not([type='submit']), select, textarea");
105                        var trackedInputs = inputs.filter("[data-sc-tracking='True'], [data-sc-tracking='true']");
106                        var trackedNonDateInputs = trackedInputs.not("[type='date']");
107
108                        if (trackedInputs.length) {
109                            inputs.not(trackedInputs).on("focus",
110                                function () {
111                                    self.onFocusField(this);
112                                });
113
114                            trackedInputs.on("focus",
115                                function () {
116                                    self.onFocusField(this, true);
117                                }).on("blur",
118                                    function () {
119                                        self.onBlurField(this);
120                                    });
121
122                            trackedNonDateInputs.on("change",
123                                function () {
124                                    self.onBlurField(this);
125                                });
126                        }
127                    },
128
129                    onFocusField: function (element, hasTracking) {
130                        if (!hasTracking) {
131                            this.options.fieldId = "";
132                            return;
133                        }
134
135                        var fieldId = getElementName(element);
136
137                        if (this.options.fieldId !== fieldId) {
138                            this.options.fieldId = fieldId;
139                            this.options.duration = $.now();
140                            this.options.fieldValue = getElementValue(element);
141                        }
142                    },
143
144                    onBlurField: function (element) {
145                        var fieldId = getElementName(element);
146                        var timeStamp = $.now();
147
148                        if (!endsWith(fieldId, "value")) {
149                            var owner = getOwner(this.$el, fieldId);
150                            if (!owner) {
151                                return;
152                            }
153
154                            element = owner;
155                        }
156
157                        var duration = this.options.duration ? Math.round((timeStamp - this.options.duration) / 1000) : 0;
158                        var value = getElementValue(element);
159                        var fieldChanged = this.options.fieldId !== fieldId;
160                        if (fieldChanged) {
161                            this.options.fieldId = fieldId;
162                            this.options.duration = $.now();
163                            duration = 0;
164                        }
165                        if (fieldChanged || this.options.fieldValue !== value) {
166                            this.options.fieldValue = value;
167
168                            var fieldName = getFieldName(element);
169                            var clientEvent = this.buildEvent(fieldId, fieldName, eventIds.fieldCompleted, duration);
170
171                            var validator = this.$el.data("validator");
172                            var validationEvents = [];
173                            if (validator && !validator.element(element)) {
174                                validationEvents = this.checkClientValidation(element, fieldName, validator, duration);
175                            }
176
177                            this.trackEvents($.merge([clientEvent], validationEvents));
178                        }
179                    },
180
181                    buildEvent: function (fieldId, fieldName, eventId, duration) {
182                        var fieldIdHidden = getFieldGuid(fieldId) + "ItemId";
183
184                        fieldId = $("input[name=\"" + fieldIdHidden + "\"]").val();
185
186                        return {
187                            'formId': this.options.formId,
188                            'sessionId': this.options.sessionId,
189                            'eventId': eventId,
190                            'fieldId': fieldId,
191                            'duration': duration,
192                            'fieldName': fieldName
193                        };
194                    },
195
196                    checkClientValidation: function (element, fieldName, validator, duration) {
197                        var tracker = this;
198                        var events = [];
199
200                        $.each(validator.errorMap,
201                            function (key) {
202                                if (key === element.name) {
203                                    var clientEvent = tracker.buildEvent(key, fieldName, eventIds.fieldError, duration);
204                                    events.push(clientEvent);
205                                }
206                            });
207
208                        return events;
209                    },
210
211                    trackEvents: function (events) {
212                        $.ajax({
213                            type: "POST",
214                            url: "/fieldtracking/register",
215                            data: JSON.stringify(events),
216                            contentType: "application/json"
217                        }).done(function (data, textStatus, jqXhr) {
218                            if ((jqXhr.statusText === "OK" || jqXhr.statusText === "success") && jqXhr.responseText !== "") {
219                                alert(jqXhr.responseText);
220                            }
221                        });
222                    }
223                }
224            });
225
226    $.fn.track_fxbForms = function (options) {
227        return this.each(function () {
228            var tracker = $.data(this, "fxbForms.tracking");
229            if (tracker) {
230                tracker.startTracking();
231            } else {
232                tracker = new $.fxbFormTracker(this, options);
233                $.data(this, "fxbForms.tracking", tracker);
234                tracker.startTracking();
235            }
236        });
237    };
238
239    $("form[data-sc-fxb]").track_fxbForms();
240})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.