PageSourceSearch

https://www.nema.org/Scripts/googleanalytics.js

js nema.org collected 2026-09-24 08:26:18 UTC 29,878 bytes, 1,067 lines download raw bytes

1/**
2 * Determine if variable an object
3 * @param {any} input object
4 * @returns {bool} Returns true if object
5 */
6function isObject(input) {
7	return typeof input === 'object' && input !== null;
8}
9
10/**
11 * Determine if variable a jquery object
12 * @param {object} input object
13 * @returns {bool} Returns true if jQuery object
14 */
15function isJQueryObject(input) {
16	return input instanceof jQuery;
17}
18
19/**
20 * Determine if date passed is a date object
21 * @param {any} date
22 */
23function isDateObject(date) {
24	return date && Object.prototype.toString.call(date) === "[object Date]" && !isNaN(date);
25}
26
27/**
28 * Determine if variable not set, undefined, null, or an empty jquery object
29 * @param {any} input object
30 * @returns {bool} Returns true if null
31 */
32function isNull(input) {
33	return typeof input === undefined || input === undefined || input === null || (isJQueryObject(input) && input.length === 0);
34}
35
36/**
37 * Determine if variable not set, undefined, null, empty jquery object, or empty string
38 * @param {any} input object
39 * @returns {bool} Returns true if null or empty
40 */
41function isNullOrEmpty(input) {
42	return isNull(input)
43		|| (typeof input === 'string' && input === "")
44		|| (typeof input === 'object' && Object.keys(input).length === 0);
45}
46
47/**
48 * Determine if two strings are equal
49 * @param {string} input1 string 
50 * @param {string} input2 string
51 * @param {bool} isIgnoreCase if true, will ignore case when compare
52 * @returns {bool} Returns true if equal
53 */
54function isEqual(input1, input2, isIgnoreCase) {
55	return (isNullOrEmpty(isIgnoreCase) || isIgnoreCase === false)
56		? input1 === input2
57		: (input1 + "").toUpperCase() === (input2 + "").toUpperCase();
58}
59
60function isEqualIgnoreCase(input1, input2) {
61	return isEqual(input1, input2, true);
62}
63
64/**
65 * Determine if substring inside a string or array
66 * @param {any} input string or string array to search in
67 * @param {string} substring string to search for
68 * @param {bool} isIgnoreCase if true, will ignore case when compare
69 * @returns {bool} Returns true if contained
70 */
71function contains(input, substring, isIgnoreCase) {
72	if (isNull(input)) { return false; }
73	if (isNullOrEmpty(isIgnoreCase)) { isIgnoreCase = false; }
74
75	if (Array.isArray(input)) {
76
77		// array
78		for (var i = 0; i < input.length; i++) {
79			if (substring === null && input[i] === null) {
80				return true;
81			}
82			else if (isIgnoreCase && input[i].toUpperCase() === substring.toUpperCase()) {
83				return true;
84			}
85			else if (!isIgnoreCase && input[i] === substring) {
86				return true;
87			}
88		}
89		return false;
90	}
91	else if (isObject(input)) {
92
93		// object
94		console.error("contains() function will not work for an object");
95		return false;
96	}
97	else {
98
99		// string
100		return isIgnoreCase
101			? input.toUpperCase().indexOf(substring.toUpperCase()) !== -1
102			: input.indexOf(substring) !== -1;
103	}
104}
105
106/**
107 * Is passed value a string?
108 * @param {any} input
109 */
110function isString(input) {
111	return typeof input === 'string' || input instanceof String;
112}
113
114function startsWith(stringToSearchIn, substring, isIgnoreCase) {
115	if (isNullOrEmpty(substring)) {
116		return true;
117	}
118	if (isNullOrEmpty(stringToSearchIn)) {
119		return false;
120	}
121	if (isIgnoreCase) {
122		substring = substring.toLowerCase();
123		stringToSearchIn = stringToSearchIn.toLowerCase();
124	}
125	return stringToSearchIn.lastIndexOf(substring, 0) === 0
126}
127
128/**
129 * Convert string to nullable boolean
130 * @param {string} input string to convert
131 * @returns {bool} nullable boolean
132 */
133function convertToBool(input) {
134	if (isNullOrEmpty(input)) { return null; }
135	if (input === true || input === 1 || input === "1" || isEqualIgnoreCase(input, "true")) {
136		return true;
137	}
138	if (input === false || input === 0 || input === "0" || isEqualIgnoreCase(input, "false")) {
139		return false;
140	}
141	return null;
142}
143
144function convertToInt(input) {
145	if (isNullOrEmpty(input)) { return null; }
146	var o = parseInt(input.replace("$", "").replace(/,/g, ""), 10);
147	return isNaN(o) ? null : o;
148}
149
150function convertToFloat(input) {
151	if (isNullOrEmpty(input)) { return null; }
152	var o = parseFloat(input.replace("$", "").replace(/,/g, ""));
153	return isNaN(o) ? null : o;
154}
155
156/**
157 * Convert number to currency formatted string
158 * If whole number, no decimal places displayed
159 * http://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-money-in-javascript
160 * @param {Number} input number to convert
161 * @returns {string} currency formatted number
162 */
163function formatMoney(input) {
164	if (isNull(input) || isNaN(input)) {
165		return null;
166	}
167	var formatter = new Intl.NumberFormat('en-US', {
168		style: 'currency',
169		currency: 'USD'
170	});
171	return formatter.format(input).replace(".00", "");
172}
173
174/**
175 * Convert number into comma separated string
176 * If whole number, no decimal places displayed
177 * http://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-money-in-javascript
178 * @param {Number} input number to convert
179 * @returns {string} formatted number
180 */
181function formatNumber(input) {
182	if (isNull(input) || isNaN(input)) {
183		return null;
184	}
185	return new Intl.NumberFormat('en-US').format(input).replace(".00", "");
186}
187
188/**
189 * Get local timezone offset from UTC. For example, EST is -5 
190 * @returns {number} timezone offset 
191 */
192function localTimezoneOffset() {
193	return (new Date().getTimezoneOffset() / 60) * -1
194}
195
196/**
197 * parse string into date
198 * @param {any} input
199 */
200function parseDate(input) {
201	if (isNullOrEmpty(input)) { return null; }
202	if (isDateObject(input)) { return input; }
203	var dateAsNumber = Date.parse(input);
204	if (isNaN(dateAsNumber)) { return null; }
205	return new Date(dateAsNumber);
206}
207
208/**
209 * Number of days between two dates
210 * https://stackoverflow.com/questions/542938/how-do-i-get-the-number-of-days-between-two-dates-in-javascript
211 * @param {any} first
212 * @param {any} second
213 * @returns {number} Number of days (rounded) between two dates
214 */
215function daysBetween(first, second) {
216	// Take the difference between the dates and divide by milliseconds per day.
217	// Round to nearest whole number to deal with DST.
218	return Math.round((second - first) / (1000 * 60 * 60 * 24));
219}
220
221/**
222 * Number of days since epoch (1970-01-01)
223 * @param {any} date
224 * @returns {number} days
225 */
226function daysSinceEpoch(date) {
227	return Math.floor(date / 8.64e7);
228}
229
230
231/**
232* Port of strftime(). Compatibility notes:
233*
234* %c - formatted string is slightly different
235* %D - not implemented (use "%m/%d/%y" or "%d/%m/%y")
236* %e - space is not added
237* %E - not implemented
238* %h - not implemented (use "%b")
239* %k - space is not added
240* %n - not implemented (use "\n")
241* %O - not implemented
242* %r - not implemented (use "%I:%M:%S %p")
243* %R - not implemented (use "%H:%M")
244* %t - not implemented (use "\t")
245* %T - not implemented (use "%H:%M:%S")
246* %U - not implemented
247* %W - not implemented
248* %+ - not implemented
249* %% - not implemented (use "%")
250*
251* strftime() reference:
252* http://man7.org/linux/man-pages/man3/strftime.3.html
253*
254* Day of year (%j) code based on Joe Orost's answer:
255* http://stackoverflow.com/questions/8619879/javascript-calculate-the-day-of-the-year-1-366
256*
257* Week number (%V) code based on Taco van den Broek's prototype:
258* http://techblog.procurios.nl/k/news/view/33796/14863/calculate-iso-8601-week-and-year-in-javascript.html
259* @param {string} sFormat
260* @param {date} date
261*/
262function formatDateTime(sFormat, date) {
263	if (!(date instanceof Date)) date = new Date();
264	var nDay = date.getDay(),
265		nDate = date.getDate(),
266		nMonth = date.getMonth(),
267		nYear = date.getFullYear(),
268		nHour = date.getHours(),
269		aDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
270		aMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
271		aDayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
272		isLeapYear = function () {
273			return (nYear % 4 === 0 && nYear % 100 !== 0) || nYear % 400 === 0;
274		},
275		getThursday = function () {
276			var target = new Date(date);
277			target.setDate(nDate - ((nDay + 6) % 7) + 3);
278			return target;
279		},
280		zeroPad = function (nNum, nPad) {
281			return ('' + (Math.pow(10, nPad) + nNum)).slice(1);
282		};
283	return sFormat.replace(/%[a-z]/gi, function (sMatch) {
284		return {
285			'%a': aDays[nDay].slice(0, 3),
286			'%A': aDays[nDay],
287			'%b': aMonths[nMonth].slice(0, 3),
288			'%B': aMonths[nMonth],
289			'%c': date.toUTCString(),
290			'%C': Math.floor(nYear / 100),
291			'%d': zeroPad(nDate, 2),
292			'%e': nDate,
293			'%F': date.toISOString().slice(0, 10),
294			'%G': getThursday().getFullYear(),
295			'%g': ('' + getThursday().getFullYear()).slice(2),
296			'%H': zeroPad(nHour, 2),
297			'%I': zeroPad((nHour + 11) % 12 + 1, 2),
298			'%j': zeroPad(aDayCount[nMonth] + nDate + ((nMonth > 1 && isLeapYear()) ? 1 : 0), 3),
299			'%k': '' + nHour,
300			'%l': (nHour + 11) % 12 + 1,
301			'%m': zeroPad(nMonth + 1, 2),
302			'%M': zeroPad(date.getMinutes(), 2),
303			'%p': (nHour < 12) ? 'AM' : 'PM',
304			'%P': (nHour < 12) ? 'am' : 'pm',
305			'%s': Math.round(date.getTime() / 1000),
306			'%S': zeroPad(date.getSeconds(), 2),
307			'%u': nDay || 7,
308			'%V': (function () {
309				var target = getThursday(),
310					n1stThu = target.valueOf();
311				target.setMonth(0, 1);
312				var nJan1 = target.getDay();
313				if (nJan1 !== 4) target.setMonth(0, 1 + ((4 - nJan1) + 7) % 7);
314				return zeroPad(1 + Math.ceil((n1stThu - target) / 604800000), 2);
315			})(),
316			'%w': '' + nDay,
317			'%x': date.toLocaleDateString(),
318			'%X': date.toLocaleTimeString(),
319			'%y': ('' + nYear).slice(2),
320			'%Y': nYear,
321			'%z': date.toTimeString().replace(/.+GMT([+-]\d+).+/, '$1'),
322			'%Z': date.toTimeString().replace(/.+\((.+?)\)$/, '$1')
323		}[sMatch] || sMatch;
324	});
325}
326
327/**
328 * Format ISO 8601 format date: 2021-08-19
329 * @param {any} date
330 * @returns {string} ISO 8601 format date. Example: 2021-08-19
331 */
332function formatDateIso8601(date) {
333	return formatDateTime("%Y-%m-%d", date);
334}
335
336/**
337 * Format standard 12 hour time. Example: 9:00 PM
338 * @param {any} date
339 * @returns {string} 12 hour time: 9:00 PM
340 */
341function formatTime(date) {
342	return formatDateTime("%I:%M %p", date).replace(/^0+/, "");
343}
344
345/**
346 * Format day of the week. Example: Wednesday
347 * @param {any} date
348 * @returns {string} Day of the Week (full name). Example: Wednesday
349 */
350function formatDayOfWeek(date) {
351	return formatDateTime("%A", date);
352}
353
354/**
355 * Appends an important style to jQuery object's existing styles
356 * This is needed b/c the jQuery css function won't work with '!important' attribute
357 * @param {any} element
358 * @param {string} style
359 */
360function appendImportantStyle(element, style) {
361	if (isNull(element) || !isJQueryObject(element)) {
362		console.log("Element passed is null or not jQuery object");
363		return;
364	}
365	if (isNullOrEmpty(style)) {
366		console.log("No style passed");
367		return;
368	}
369	element.attr('style', function (i, s) { return (s || '') + style });
370}
371
372function copyToClipboard(input) {
373	if (isNull(input)) { return; }
374
375	// string
376	if (typeof input === 'string' || input instanceof String) {
377		var textArea = document.createElement("textarea");
378		textArea.value = input;
379		textArea.style.top = "0";
380		textArea.style.left = "0";
381		textArea.style.position = "fixed";
382		document.body.appendChild(textArea);
383		textArea.focus();
384		textArea.select();
385		var isSuccess = privateCopyToClipboard(input);
386		document.body.removeChild(textArea);
387		return isSuccess;
388	}
389
390	// get input element
391	var element;
392	if (isJQueryObject(input)) {
393		if (input.length === 0) { return; }
394		element = input[0];
395	}
396	else {
397		element = input;
398	}
399
400	// select element text
401	input.select();
402	input.focus();
403	if (input.setSelectionRange) {
404		input.setSelectionRange(0, 99999);
405	}
406
407	// copy to clipboard
408	return privateCopyToClipboard(input.value);
409}
410
411function privateCopyToClipboard(text) {
412	// internet explorer
413	var isSuccess = false;
414	if (navigator.clipboard) {
415		navigator.clipboard.writeText(text).then(function () {
416			isSuccess = true;
417		}, function (err) {
418			isSuccess = false;
419		});
420	}
421	if (isSuccess) { return true; }
422
423	// all other browsers
424	try {
425		if (document.execCommand("copy")) {
426			isSuccess = true;
427		}
428		else {
429			isSuccess = false;
430		}
431	}
432	catch (err) {
433		isSuccess = false;
434	}
435	return isSuccess;
436}
437
438/**
439 * Determine if value exists in select dropdown list
440 * @param {any} control Select dropdownlist element
441 * @param {string} value select option value
442 */
443function isOptionValueExist(control, value) {
444	if (isNull(control)) {
445		return false;
446	}
447	if (!isJQueryObject(control)) {
448		control = $(control);
449	}
450	return control.find("option[value='" + value + "']").length > 0;
451}
452
453/**
454 * Get URL
455 * @param {bool} isExcludeQueryString Exclude Query String?
456 * @returns {string} URL
457 */
458function getUrl(isExcludeQueryString) {
459	return isExcludeQueryString
460		? window.location.href.split('?')[0]
461		: window.location.href;
462}
463
464/**
465 * Get URL Query String
466 * @param {bool} isPrependQuestionMark Include question mark if not empty
467 * @returns {string} URL
468 */
469function getUrlQueryString(isPrependQuestionMark) {
470	var o = window.location.href.indexOf("?") !== -1
471		? window.location.href.split('?')[1]
472		: "";
473	return (isPrependQuestionMark && o !== "" ? "?" : "") + o;
474}
475
476function getUrlQueryStringFromUrl(url, isPrependQuestionMark) {
477	if (isNullOrEmpty(url) || url.indexOf("?") === -1) { return ""; }
478	var o = url.split("?")[1];
479	return (isPrependQuestionMark && o !== "" ? "?" : "") + o;
480}
481
482/**
483 * Get URL parameters as an object
484 * https://gomakethings.com/getting-all-query-string-values-from-a-url-with-vanilla-js/
485 * @param {string} url URL (optional)
486 * @returns {object} URL parameters as an object
487 */
488function getUrlParameters(url) {
489	url = isNullOrEmpty(url) ? getUrl() : url;
490	var params = {};
491	if (isNullOrEmpty(url) || isNullOrEmpty(getUrlQueryStringFromUrl(url, false))) {
492		return params;
493	}
494	var parser = document.createElement('a');
495	parser.href = url;
496	var query = parser.search.substring(1);
497	var vars = query.split('&');
498	for (var i = 0; i < vars.length; i++) {
499		var pair = vars[i].split('=');
500		if (pair.length === 0) { continue; }
501		params[pair[0]] = decodeUrlValue(pair.length > 1 ? pair[1] : "");
502	}
503	return params;
504}
505
506/**
507 * Returns URL parameter value
508 * @param {any} parameterName The parameter name, can pass a string or array of str
508ings
509 * @returns {string} parameter value
510 */
511function getUrlParameterValue(parameterName) {
512	if (isNull(parameterName)) { return null; }
513
514	// create an array of parameters to find
515	var parameterNames = Array.isArray(parameterName)
516		? parameterName
517		: (parameterName.indexOf(",") !== -1
518			? parameterName.split(',')
519			: new Array(parameterName)
520		);
521	if (parameterNames.length === 0) { return null; }
522
523	// get current url parameters
524	var parameters = getUrlParameters();
525	if (isNull(parameters) || parameters.length === 0) { return null; }
526
527	// find match
528	for (var i = 0; i < parameterNames.length; i++) {
529		for (var p in parameters) {
530			if (!parameters.hasOwnProperty(p)
531				|| (parameterNames[i] + "").toUpperCase().trim() !== (p + "").toUpperCase()) {
532				continue;
533			}
534			return parameters[p];
535		}
536	}
537	return null;
538}
539
540/**
541 * Convert url parameters object into querystring
542 * @param {object} parameters Parameters object
543 * @param {bool} isPrependQuestionMark If true, will start query string with a question mark (if any parameters passed)
544 * @returns {string} Query string
545 */
546function convertUrlParametersToQueryString(parameters, isPrependQuestionMark) {
547	if (isNull(parameters) || parameters.length === 0) { return null; }
548	var queryString = "";
549	for (var p in parameters) {
550		if (!parameters.hasOwnProperty(p)) { continue; }
551		var value = isNullOrEmpty(parameters[p]) ? "" : parameters[p];
552		queryString += "&" + p + "=" + encodeURIComponent(value);
553	}
554	return queryString.length > 0
555		? (isPrependQuestionMark ? "?" : "") + queryString.substr(1)
556		: queryString;
557}
558
559/**
560 * Add or update parameter and return URL
561 * @param {string} name Parameter Name
562 * @param {string} value Parameter Value
563 * @param {string} url URL (optional)
564 * @returns {string} url
565 */
566function addUrlParameter(name, value, url) {
567	if (isNullOrEmpty(url)) { url = getUrl(); }
568	var key = (name + "").toUpperCase();
569	if (key === "[OBJECT OBJECT]") {
570		return addUrlParameters(name, url);
571	}
572	var path = url.indexOf("?") !== -1 ? url.substring(0, url.indexOf("?")) : url;
573
574	// get existing parameters
575	var parameters = getUrlParameters(url);
576
577	// update parameter
578	var isParameterAlreadyExist = false;
579	for (var p in parameters) {
580		if (!parameters.hasOwnProperty(p)) { continue; }
581		if ((p + "").toUpperCase() === key) {
582			isParameterAlreadyExist = true;
583			parameters[p] = value;
584			break;
585		}
586	}
587
588	// add parameter
589	if (!isParameterAlreadyExist) {
590		parameters[name] = value;
591	}
592
593	// return path + querystring
594	return path + convertUrlParametersToQueryString(parameters, true);
595}
596
597/**
598 * Add or update parameters and return URL
599 * @param {object} parameters Parameters to add { name1: "value", name2: "value" }
600 * @param {string} url URL (optional)
601 * @returns {string} url
602 */
603function addUrlParameters(parameters, url) {
604	if (isNull(parameters)) { parameters = {}; }
605	if (isNullOrEmpty(url)) { url = getUrl(); }
606	var path = url.indexOf("?") !== -1 ? url.substring(0, url.indexOf("?")) : url;
607
608	// get existing parameters
609	var existingParameters = getUrlParameters(url);
610
611	// merge new parameters with existing
612	parameters = mergeUrlParameters(parameters, existingParameters);
613
614	// return path + querystring
615	return path + convertUrlParametersToQueryString(parameters, true);
616}
617
618/**
619 * Ad url parameters to a query string
620 * @param {object} parameters new url parameters. Example: { year: "2018", month: "1" }
621 * @param {any} queryString query string to update
622 * @returns {string} querystring
623 */
624function addUrlParametersToQueryString(parameters, queryString) {
625	if (isNullOrEmpty(queryString)) { queryString = ""; }
626	if (isNullOrEmpty(parameters) || !isObject(parameters)) { return queryString; }
627	var existingParameters = getUrlParameters(queryString);
628	var merged = mergeUrlParameters(parameters, existingParameters);
629	var o = convertUrlParametersToQueryString(merged, false);
630	return isNullOrEmpty(o)
631		? ""
632		: (isNullOrEmpty(queryString) || queryString.length > 0 && queryString.substr(0, 1) === "?" ? "?" : "") + o;
633}
634
635/**
636 * Merge URL Parameters
637 * @param {object} newParameters These are the new parameters that will be added
638 * @param {object} existingParameters These are the existing parameters that will be overwritten
639 * @returns {object} Returns a merged parameters object
640 */
641function mergeUrlParameters(newParameters, existingParameters) {
642	if (isNull(existingParameters) || existingParameters.length === 0) {
643		return isNull(newParameters) ? {} : newParameters;
644	}
645	if (isNull(newParameters) || newParameters.length === 0) {
646		return isNull(existingParameters) ? {} : existingParameters;
647	}
648	var o = {};
649
650	// add existing parameters to new object
651	for (existingParameter in existingParameters) {
652		o[existingParameter] = existingParameters[existingParameter];
653	}
654
655	// update existing parameter values with new values
656	for (newParameter in newParameters) {
657		var key = (newParameter + "").toUpperCase();
658		for (p in o) {
659			if ((p + "").toUpperCase() === key) {
660				o[p] = newParameters[newParameter];
661				break;
662			}
663		}
664	}
665
666	// add new parameters
667	for (newParameter in newParameters) {
668		var key = (newParameter + "").toUpperCase();
669		var isNew = true;
670		for (p in o) {
671			if ((p + "").toUpperCase() === key) {
672				isNew = false;
673				break;
674			}
675		}
676		if (isNew) {
677			o[newParameter] = newParameters[newParameter];
678		}
679	}
680	return o;
681}
682
683/**
684 * Update the URL displayed in the browser address bar. Does not refresh browser.
685 * @param {any} url
686 * @param {bool} isUpdateHistory
687 */
688function setAddressbarUrl(url, isUpdateHistory) {
689	if (convertToBool(isUpdateHistory) === true) {
690		window.history.pushState({}, "", url);
691	}
692	else {
693		window.history.replaceState({}, "", url);
694	}
695}
696
697function GetAnchor() {
698	return $(location).attr('hash');
699}
700
701/**
702 * Determine if email address is valid
703 * \S = [^ \t\r\n\f]
704 * @param {string} email
705 */
706function isValidEmail(email) {
707	if (isNullOrEmpty(email)) { return false; }
708	var regEx = /^\S+@\S+\.\S+$/;
709	return regEx.test(email);
710}
711
712function isValidCurrencyAmount(amount) {
713	if (isNullOrEmpty(amount)) { return false; }
714	var parsed = amount.replace("$", "").replace(/,/g, "").trim();
715	return parsed != null && !isNaN(+parsed);
716}
717
718/**
719 * Disable Button: Adds disabled="disabled" attribute and adds "disabled" css class
720 * Works for both input buttons and anchor buttons
721 * @param {object} button button/anchor object or element ID
722 */
723function disableButton(button) {
724	if (typeof button === 'string') {
725		if (button.length > 0 && button.substr(0, 1) !== "#") {
726			button = "#" + button;
727		}
728	}
729	$(button).attr("disabled", "disabled");
730	if (!$(button).hasClass("disabled")) {
731		$(button).addClass("disabled");
732	}
733}
734
735/**
736 * Enable Button: Removed "disable" attribute css class
737 * Works for both input buttons and anchor buttons
738 * @param {object} button button/anchor object or element ID
739 */
740function enableButton(button) {
741	if (typeof button === 'string') {
742		if (button.length > 0 && button.substr(0, 1) !== "#") {
743			button = "#" + button;
744		}
745	}
746	$(button).removeAttr("disabled");
747	$(button).removeClass("disabled");
748}
749
750function enableButtons() {
751	$("input[type='button']").removeAttr("disabled");
752	$("input[type='button']").removeClass("disabled");
753
754	$("input[type='submit']").removeAttr("disabled");
755	$("input[type='submit']").removeClass("disabled");
756
757	$("button").removeAttr("disabled");
758	$("button").removeClass("disabled");
759}
760
761/**
762 * Decode URL parameter value
763 * @param {string} input URL encoded value to decode
764 * @returns {string} URL decoded value
765 */
766function decodeUrlValue(input) {
767	if (isNull(input)) { return null; }
768	// replace plus symbol (+) with %20
769	input = input.replace(/\+/g, '%20')
770	return decodeURIComponent(input);
771}
772
773/**
774 * Decode HTML
775 * @param {string} text HTML encoded text to decode
776 * @returns {string} HTML decoded text
777 */
778function decodeHtml(text) {
779	if (isNull(text)) { return null; }
780	var textArea = document.createElement('textarea');
781	textArea.innerHTML = text;
782	return textArea.value;
783}
784
785/**
786 * Encode HTML
787 * @param {string} text text to encode for HTML
788 * @returns {string} HTML encoded text
789 */
790function encodeHtml(text) {
791	if (isNull(text)) { return null; }
792	var textArea = document.createElement('textarea');
793	textArea.innerText = text;
794	return textArea.innerHTML;
795}
796
797/**
798 * Get browser scroll bar width/height
799 * @returns {int} scrollbar width/height
800 * */
801function getScrollbarSize() {
802	var scrollDiv = document.createElement("div");
803	scrollDiv.style.width = "100px";
804	scrollDiv.style.height = "100px";
805	scrollDiv.style.overflow = "scroll";
806	scrollDiv.style.position = "absolute";
807	scrollDiv.style.top = "-9999px";
808	document.body.appendChild(scrollDiv);
809
810	// get the scrollbar width
811	var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
812
813	// delete the DIV 
814	document.body.removeChild(scrollDiv);
815
816	return scrollbarWidth;
817}
818
819function scrollToElement(element, speed) {
820	if (!isJQueryObject(element)) {
821		if (!contains(element, "#") && !contains(element, ".") && !contains(element, " ")) {
822			element = "#" + element;
823		}
824		var element = $(element);
825	}
826	if (isNull(element)) {
827		console.log("Failed to get element to scroll to: " + element);
828		return;
829	}
830	if (isNullOrEmpty(speed)) { speed = "slow"; }
831	$("body,html").animate({ scrollTop: element.offset().top }, speed);
832}
833
834// determine if current page is a popup  (isPopUp=1)
835// IMPORTANT! Masterpage call this function, don't break it
836function isPopUp() {
837	return convertToBool(getUrlParameterValue("isPopUp")) === true;
838}
839
840function isPrint() {
841	return convertToBool(getUrlParameterValue("isPrint")) === true;
842}
843
844function setCookie(name, value, days) {
845	var expires = "";
846	if (days) {
847		var date = new Date();
848		date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
849		expires = "; expires=" + date.toUTCString();
850	}
851	document.cookie = name + "=" + (encodeURIComponent(value) || "") + expires + "; path=/; SameSite=None; Secure;";
852}
853
854function getUsernameByCookie() {
855	var cookies = document.cookie.split(";");
856	for (var i = 0; i < cookies.length; i++) {
857		var cookiePair = cookies[i].split("=");
858		if (cookiePair[0].trim() === "username") {
859			return decodeUrlValue(cookiePair[1]);
860		}
861	}
862
863	return "";
864}
865
866function getEmailByCookie() {
867	var cookies = document.cookie.split(";");
868	for (var i = 0; i < cookies.length; i++) {
869		var cookiePair = cookies[i].split("=");
870		if (cookiePair[0].trim() === "email") {
871			return decodeUrlValue(cookiePair[1]);
872		}
873	}
874
875	return "";
876}
877
878function getUsername() {
879
880	// use cookie
881	var username = getUsernameByCookie();
882	if (!isNullOrEmpty(username)) {
883		return username;
884    }
885
886	// use api
887	$.ajax({
888		type: "GET",
889		url: "/RestAPI/NemaServices/NemaUserService/GetUsername",
890		datatype: "text",
891		cache: true,
892		success: function (data) {
893			username = isNullOrEmpty(data) ? "" : data;
894		},
895		async: false
896	});
897
898	// set cookie
899	if (!isNullOrEmpty(username)) {
900		setCookie("username", username, 90);
901	}
902
903	return username;
904}
905
906function getEmail() {
907
908	// use cookie
909	var email = getEmailByCookie();
910	if (!isNullOrEmpty(email) && contains(email, "@")) {
911		return email;
912	}
913	var username = getUsernameByCookie();
914	if (!isNullOrEmpty(username)) {
915		if (contains(username, "@")) {
916			return username;
917		}
918		else {
919			$.ajax({
920				type: "GET",
921				url: "/RestAPI/NemaServices/NemaUserService/GetEmail?username=" + username,
922				datatype: "text",
923				cache: true,
924				success: function (data) {
925					email = isNullOrEmpty(data) ? "" : data;
926				},
927				async: false
928			});
929
930			// set cookie
931			if (!isNullOrEmpty(email)) {
932				setCookie("email", email, 90);
933			}
934
935			return email;
936        }
937	}
938
939	// use api
940	email = "";
941	$.ajax({
942		type: "GET",
943		url: "/RestAPI/NemaServices/NemaUserService/GetEmail",
944		datatype: "text",
945		cache: true,
946		success: function (data) {
947			email = isNullOrEmpty(data) ? "" : data;
948		},
949		async: false
950	});
951
952	// set cookie
953	if (!isNullOrEmpty(email)) {
954		setCookie("email", email, 90);
955	}
956
957	return email;
958}
959
960function isNemaStaff(username) {
961	var username = isNullOrEmpty(username)
962		? getUsername()
963		: username;
964	if (isNullOrEmpty(username)) { return false; }
965	username = username.toLowerCase().trim();
966	if (username.indexOf("@") === -1) {
967		return true;
968	}
969	var nemaDomains = [ "nema.org", "medicalimaging.org", "dicomstandard.org", "esfi.org" ];
970	for (var i = 0; i < nemaDomains.length; i++) {
971		if (username.length > nemaDomains[i].length
972			&& username.substring(username.length - nemaDomains[i].length - 1) === "@" + nemaDomains[i]) {
973			return true;
974		}
975	}
976
977	return false;
978}
979
980function isNemaMember(username) {
981
982	// user username
983	var username = isNullOrEmpty(username)
984		? getUsername()
985		: username;
986	if (isNullOrEmpty(username)) { return false; }
987	username = username.toLowerCase().trim();
988	if (username.indexOf("@") === -1) {
989		return false;
990	}
991
992	// use api
993	var result = "";
994	$.ajax({
995		type: "GET",
996		url: "/RestAPI/NemaServices/NemaUserService/IsNemaMember",
997		datatype: "text",
998		cache: true,
999		success: function (data) {
1000			result = isNullOrEmpty(data) ? "" : data; 
1001		},
1002		async: false
1003	});
1004
1005	return isEqualIgnoreCase(result, "true");
1006}
1007
1008/**
1009 * Get error message returned from ajax request
1010 * @returns {int} scrollbar width/height
1011 * */
1012function getWebServiceErrorMessage(jqXHR)
1013{
1014	if (isNull(jqXHR)) {
1015		return "";
1016	}
1017	if (!isNull(jqXHR.responseJSON)
1018		&& jqXHR.responseJSON.hasOwnProperty("ResponseStatus")
1019		&& jqXHR.responseJSON["ResponseStatus"].hasOwnProperty("Message")) {
1020		return jqXHR.responseJSON["ResponseStatus"]["Message"];
1021	}
1022	if (jqXHR.hasOwnProperty("responseText")
1023		&& !isNullOrEmpty(jqXHR["responseText"])) {
1024		return jqXHR["responseText"];
1025    }
1026	return "";
1027}
1028
1029
1030
1031
1032
1033
1034/**
1035Google Analytics Tag
1036**/
1037window.dataLayer = window.dataLayer || [];
1038function gtag() { dataLayer.push(arguments); }
1039gtag('js', new Date());
1040
1041gtag('config', 'UA-25027700-1', {
1042    'custom_map': { 'dimension1': 'IsUserNemaStaff' }
1043});
1044//gtag('event', 'session_start', { 'IsUserNemaStaff': 'yes' });
1045//gtag('event', 'page_view', { 'IsUserNemaStaff': 'yes' });
1046
1047
1048//Code for tracking outbound links
1049document.addEventListener('click', function (event) {
1050  var link = event.target;
1051  while(link && (typeof link.tagName == 'undefined' || link.tagName.toLowerCase() != 'a' || !link.href)) {
1052    link = link.parentNode
1053  }
1054
1055  if (link && link.href && link.host && link.host !== location.host) {
1056    gtag('event', 'Click', {
1057      event_category: 'Outbound Link',
1058      event_label : link.href
1059    });
1060
1061    // Allow event to be sent before the page is unloaded
1062    if(!link.target || link.target.match(/^_(self|parent|top)$/i)) {
1063      setTimeout(function() { location.href = link.href; }, 150);
1064      event.preventDefault();
1065    }
1066  }
1067})

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.