1// $Id: beforeUnload.js 27849 2017-11-13 14:21:10Z warren $ 2// Functions to handle prompting when user navigates away from an unsaved form 3 4// Declare global variables 5var beforeUnloadFired = false; 6var keepaliveCount = 0; 7var isSubmit = false; // should be set to "true" in form's "onSubmit" handler (prevent prompts when submitting a form) 8var keepAliveTimer = 0; // Records time from the second last keepAliveLimit is started 9var warningAlertTimer = 2400; // 40 minutes = 2400 seconds 10 11// Get a form object for the form we wish to check 12function getFormToCheck () { 13 if (typeof window.formToCheck == 'string' && document.forms[window.formToCheck]) { 14 return document.forms[window.formToCheck]; 15 } 16 17 return document.forms[0]; 18} 19 20// Cycle through all form fields, and return as soon as a changed field has been detected 21function hasFormChanged (form) { 22 var changed = false; 23 var ignoreFormField = "ignoreFieldDefaultValueChanged"; 24 25 if (form) { 26 var fields = form.elements; 27 28 for (var i = 0; !changed && i < fields.length; i++) { 29 if (fields[i].nodeName == "FIELDSET" || fields[i].nodeName == "LABEL" || multipleClasses("check", fields[i], ignoreFormField)) { 30 // filter fieldset and label elements (label elements are part of elements array in BlackBerry OS 5.x, and undesired), and fields with attached className 'ignoreFieldDefaultValueChanged' 31 continue; 32 } 33 changed = hasFieldChanged(fields[i]); 34 if ((debug = 0) && changed) { 35 alert(fields[i].name + " has changed."); 36 } 37 } 38 } 39 40 return changed; 41} 42 43// Detect if a particular form field value or selection has changed from a load-time default 44function hasFieldChanged (formElement) { 45 switch (formElement.type.toLowerCase()) { 46 case 'text': 47 case 'textarea': 48 case 'password': 49 case 'number': 50 case 'date': 51 case 'color': 52 case 'range': 53 case 'month': 54 case 'week': 55 case 'time': 56 case 'datetime': 57 case 'datetime-local': 58 case 'email': 59 case 'search': 60 case 'tel': 61 case 'url': 62 if (formElement.value != formElement.defaultValue) { 63 return true; 64 } 65 break; 66 case 'radio': 67 case 'checkbox': 68 if (formElement.checked != formElement.defaultChecked) { 69 return true; 70 } 71 break; 72 73 case 'select-one': 74 case 'select-multiple': 75 var i; 76 var hasDefaultValue = false; 77 for (i = 0; i < formElement.options.length; i++) { 78 if (formElement.options[i].defaultSelected) { 79 hasDefaultValue = true; 80 i = formElement.options.length; 81 } 82 } 83 84 for (i = 0; i < formElement.options.length; i++) { 85 if (hasDefaultValue) { 86 if (formElement.options[i].selected != formElement.options[i].defaultSelected) { 87 return true; 88 } 89 } else if (formElement.options[i].selected && i != 0) { 90 return true; 91 } 92 } 93 break; 94 } 95 96 return false; 97} 98 99// Keep a session alive by making an Ajax call at regular intervals 100function keepAlive (options) { 101 var nowDate = Math.round(new Date().getTime() / 1000).toString(); 102 var formToCheck = getFormToCheck(); 103 104 if (typeof links != 'undefined' && typeof links["help_keepAlive"] != 'undefined') { 105 var defaults = { 106 keepaliveLimit: 3, 107 url: links["help_keepAlive"], 108 method: 'get', 109 async: true, 110 data: { date: nowDate }, 111 headers: { Accept: 'application/json' } 112 }; 113 114 // override default options 115 if (typeof options != 'undefined') { 116 for (var key in defaults) { 117 if (!options.hasOwnProperty(key)) { 118 options[key] = defaults[key]; 119 } 120 } 121 } else { 122 options = defaults; 123 } 124 125 if (!hasFormChanged(formToCheck)) { 126 // reset counter if nothing has changed in the form 127 keepaliveCount = 0; 128 return false; 129 } 130 131 var keepaliveLimitReached = false; 132 if (typeof jQuery != 'undefined') { 133 // if jQuery is available 134 $.ajax(options) 135 .done(function(data, textStatus, transport) { 136 var contentType = transport.getResponseHeader('Content-Type') || ''; 137 if (contentType.indexOf('application/json') !== -1) { 138 json = {}; 139 $.extend(json, jQuery.parseJSON(transport.responseText) || {}); 140 } 141 }); 142 if (options.keepaliveLimit != 0 && keepaliveCount == options.keepaliveLimit - 1) { 143 keepaliveLimitReached = true; 144 } 145 } else if ((options.keepaliveLimit == 0 && keepaliveCount == 0) || (options.keepaliveLimit != 0 && keepaliveCount == options.keepaliveLimit - 1)) { 146 // if jQuery is not available 147 keepaliveLimitReached = true; 148 } 149 keepaliveCount++; 150 151 // This timer is required so that we can alert users when their session is about to end. 152 if (options.keepaliveLimit != 0 && keepaliveCount == (options.keepaliveLimit - 1)) { 153 var keepaliveAlert = setInterval(function () { 154 keepAliveTimer++; 155 156 if (keepAliveTimer >= warningAlertTimer) { 157 alert(valStrings["keepaliveAlert"]); 158 clearInterval(keepaliveAlert); 159 } 160 }, 1000); 161 } 162 163 if (keepaliveLimitReached && typeof keepaliveID != 'undefined') { 164 // clears the current interval after keepaliveLimit has been reached 165 clearInterval(keepaliveID); 166 return false;
167 } 168 } else { 169 keepaliveCount = 0; 170 return false; 171 } 172} 173 174// Event handler function for "onBeforeUnload" & "onUnload" events 175function interceptUnload (e) { 176 if (!isSubmit) { 177 var formToCheck = getFormToCheck(); 178 179 if (hasFormChanged(formToCheck)) { 180 if (typeof e == 'undefined') { 181 e = window.event; 182 } 183 184 if (typeof buttonToFocus == 'string' && formToCheck.elements[buttonToFocus]) { 185 formToCheck.elements[buttonToFocus].focus(); 186 } else if (typeof buttonToFocus == 'string' && document.getElementById(buttonToFocus)) { 187 document.getElementById(buttonToFocus).focus(); 188 } else { 189 // guess by iterating over the form's elements, in reverse, for efficiency 190 for (var i = formToCheck.elements.length - 1; i >= 0; i--) { 191 if (formToCheck.elements[i].type.toLowerCase() == 'submit') { 192 formToCheck.elements[i].focus(); 193 break; 194 } 195 } 196 } 197 198 if (e.type == 'beforeunload') { 199 // where possible prompt user, attempting to show custom text where supported 200 beforeUnloadFired = true; 201 e.returnValue = valStrings["unloadPrompt"]; // Firefox (< 4.0 see ), IE 202 return valStrings["unloadPrompt"]; // Webkit, Safari, Chrome etc. 203 } else if (!beforeUnloadFired) { 204 // just notify user as a fallback 205 alert(valStrings["unloadPrompt"]); 206 return true; 207 } 208 } 209 } 210} 211 212if (typeof jQuery != 'undefined') { 213 $(window).unload(function(e) { 214 return interceptUnload(e); 215 }); 216 $(window).on('beforeunload', function(e){ 217 return interceptUnload(e); 218 }); 219} else { 220 // fallback 221 window.onunload = interceptUnload; 222 window.onbeforeunload = interceptUnload; 223} 224
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.