PageSourceSearch

https://www.elanrewardscard.com/combo?browserId=chrome&minifierTyp…assets%2Fjs%2Fjsvalidate.js&t=1789209610000

js elanrewardscard.com collected 2026-10-04 12:53:19 UTC 72,300 bytes, 1,972 lines download raw bytes

1/* makeURLAbsolute is cribbed from jQuery Mobile, and modified to suit our needs.*/
2/*!
3* jQuery Mobile 1.4.5
4* Git HEAD hash: 68e55e78b292634d3991c795f06f5e37a512decc <> Date: Fri Oct 31 2014 17:33:30 UTC
5* http:/ /jquerymobile.com
6*
7* Copyright 2010, 2014 jQuery Foundation, Inc. and other contributors
8* Released under the MIT license.
9* http:/ /jquery.org/license
10*
11*/
12
13/*Parse a URL into a structure that allows easy access to
14all of the URL components by name.*/
15function parseUrl( url ) {
16	var matches = new RegExp('^\\s*(((([^:\\/#\\?]+:)?(?:(\\/\\/)((?:(([^:@\\/#\\?]+)(?:\\:([^:@\\/#\\?]+))?)@)?(([^:\\/#\\?\\]\\[]+|\\[[^\\/\\]@#?]+\\])(?:\\:([0-9]+))?))?)?)?((\\/?(?:[^\\/\\?#]+\\/+)*)([^\\?#]*)))?(\\?[^#]+)?)(#.*)?').exec( url || "" ) || [];
17
18	/* Create an object that allows the caller to access the sub-matches
19	   by name. Note that IE returns an empty string instead of undefined,
20	   like all other browsers do, so we normalize everything so its consistent
21	   no matter what browser we're running on. */
22	return {
23		href:         matches[  0 ] || "",
24		hrefNoHash:   matches[  1 ] || "",
25		hrefNoSearch: matches[  2 ] || "",
26		domain:       matches[  3 ] || "",
27		protocol:     matches[  4 ] || "",
28		doubleSlash:  matches[  5 ] || "",
29		authority:    matches[  6 ] || "",
30		username:     matches[  8 ] || "",
31		password:     matches[  9 ] || "",
32		host:         matches[ 10 ] || "",
33		hostname:     matches[ 11 ] || "",
34		port:         matches[ 12 ] || "",
35		pathname:     matches[ 13 ] || "",
36		directory:    matches[ 14 ] || "",
37		filename:     matches[ 15 ] || "",
38		search:       matches[ 16 ] || "",
39		hash:         matches[ 17 ] || ""
40	};
41}
42
43/*Turn relPath into an asbolute path. absPath is
44an optional absolute path which describes what
45relPath is relative to.*/
46function makePathAbsolute( relPath, absPath ) {
47	var absStack,
48		relStack,
49		i, d;
50
51	if ( relPath && relPath.charAt( 0 ) === "/" ) {
52		return relPath;
53	}
54
55	relPath = relPath || "";
56	absPath = absPath ? absPath.replace( /^\/|(\/[^\/]*|[^\/]+)$/g, "" ) : "";
57
58	absStack = absPath ? absPath.split( "/" ) : [];
59	relStack = relPath.split( "/" );
60
61	for ( i = 0; i < relStack.length; i++ ) {
62		d = relStack[ i ];
63		switch ( d ) {
64			case ".":
65				break;
66			case "..":
67				if ( absStack.length ) {
68					absStack.pop();
69				}
70				break;
71			default:
72				absStack.push( d );
73				break;
74		}
75	}
76	return "/" + absStack.join( "/" );
77}
78
79/*Turn the specified relative URL into an absolute one. This function
80can handle all relative variants (protocol, site, document, query, fragment).
81 modified to omit the search and hash part of the URL.*/
82function makeUrlAbsolute( relUrl, absUrl ) {
83	var relObj = parseUrl( relUrl );
84	if (relObj.protocol !== "") {
85		return relUrl;
86	}
87	if ( absUrl === undefined ) {
88		absUrl = window.location.href;
89	}
90	var absObj = parseUrl( absUrl );
91
92
93	var protocol = relObj.protocol || absObj.protocol;
94	var doubleSlash = relObj.protocol ? relObj.doubleSlash : ( relObj.doubleSlash || absObj.doubleSlash );
95	var authority = relObj.authority || absObj.authority;
96	var hasPath = relObj.pathname !== "";
97	var pathname = makePathAbsolute( relObj.pathname || absObj.filename, absObj.pathname );
98
99	return protocol + doubleSlash + authority + pathname;
100}
101
102function compareURLs(url1, url2) {
103	var absUrl1 = makeUrlAbsolute(url1);
104	var absUrl2 = makeUrlAbsolute(url2);
105	return absUrl1 === absUrl2;
106}
107
108function injectlinks(source, target) {
109	/* iterate over all source links.*/ 
110	$("#"+source+" li>a").each(function() {
111		/* check for duplicate href.*/
112		var sourceHref = $( this ).attr('href');
113		if (sourceHref != "") {
114			var inject = true;
115			$("#mobileNavbar > ul > ul > li>a").each(function() {
116				if (compareURLs(sourceHref,$( this ).attr('href'))) {
117					inject=false;
118				}
119			});
120			/* inject non-duplicates.*/
121			if (inject) {
122			    var injectedLinks = $( this ).clone();
123                injectedLinks.attr("id", "mobile" + this.id);
124                $("#"+target).append($(injectedLinks).wrap("<li></li>").parent());
125				$(document).trigger("linkInjected", this);
126			}
127		}
128
129	});
130}
131//==================================================================================================================
132//  jQuery prototypes
133//------------------------------------------------------------------------------------------------------------------
134jQuery.fn.extend({
135	//------------------------------------------------------------------------------------------------------------------
136	//  locate the input group (returns the ancestor containing the Group class or the parent of the current element)
137	//------------------------------------------------------------------------------------------------------------------
138	inputGroup: function() {
139		var $rv = $();
140		this.each(function() {
141			$rv = $rv.add($($(this).closest("."+$(this).attr("id")+"Group")[0] ||
142			                $(this).closest("."+$(this).attr("name")+"Group")[0] ||
143			                $(this).parent()[0]));
144		});
145		return $rv;
146	},
147	
148	//------------------------------------------------------------------------------------------------------------------
149	//  addError to input (returns the elements that have had errors added)
150	//------------------------------------------------------------------------------------------------------------------
151	addInputError: function(errorMessage, alert) {
152		alert = (alert !== undefined) ? alert : true; 
153		errorMsg = (errorMessage !== undefined) ? errorMessage : this.attr('error-msg');
154		
155		var $rv = $();
156		this.each(function () {
157			var alertRoleAttr = alert?' role="alert"':'';
158	        if(!$(this).attr("aria-invalid")){
159	        	$rv=$rv.add($(this));
160	            fieldErrorId = typeof ($(this).attr("name")) !== 'undefined' ? $(this).attr("name") + "Error" : "";
161	            $(this).inputGroup().children(".validation-error").length
162	                            ? $(this).inputGroup().children(".validation-error")
163	                            : $(this).inputGroup().append('<div id="' + fieldErrorId + '" class="validation-error"' + alertRoleAttr + '></div>');
164	            var error = $(this).inputGroup().children(".validation-error");
165	            $(this).attr("aria-invalid", "true");
166	            $(this).inputGroup().addClass("has-validation-error");
167	            error.html('<span class="message-icon"><svg data-name="Outline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">' +
168	            '<path d="M18.67,17.67l-8-16a.79.79,0,0,0-1.34,0l-8,16A.75.75,0,0,0,2,18.75H18a.75.75,0,0,0,.67-1.08ZM3.21,17.25,10,3.68l6.79,13.57ZM9.25,8h1.5v5H9.25Zm1.46,6.29a1.15,1.15,0,0,1,.21.33.94.94,0,0,1,0,.76,1.15,1.15,0,0,1-.21.33,1,1,0,0,1-1.63-1.09,1,1,0,0,1,.21-.33,1,1,0,0,1,.9-.27.6.6,0,0,1,.19.06l.18.09Z"/>' +
169	            '</svg></span>
169<p>' + errorMessage + '</p>');
170	        }
171		});
172		return $rv;
173    },
174
175	//------------------------------------------------------------------------------------------------------------------
176	//Check for Errors (returns the elements have are invalid)
177	//------------------------------------------------------------------------------------------------------------------
178	checkForErrors: function() {
179		var $rv = $();
180		this.each(function() {
181			var isValid=false;
182			if(this.validity.valid){
183			    var visibleId = $(this).attr('id');
184			    if(visibleId && visibleId.match("^visible")){
185			        var hiddenInput = $(this).next();
186			        if(hiddenInput.length && hiddenInput[0].validity.valid){
187			            isValid=true;
188			        }
189			    } else {
190			        isValid=true;
191			    }
192			}
193			if(!isValid){
194	        	$rv=$rv.add($(this));
195			    $(this).trigger( "invalid" );
196			}
197		});
198		return $rv;
199	},
200	
201	//==================================================================================================================
202	//  Remove Errors
203	//------------------------------------------------------------------------------------------------------------------
204	removeErrors: function() {
205		var $rv = $();
206		this.each(function () {
207		    $(this).inputGroup().children(".validation-error").remove();
208		    $(this).inputGroup().removeClass("has-validation-error");
209	        $(this).removeAttr( "aria-invalid" );
210        	$rv=$rv.add($(this));
211		});
212		return $rv;
213	},
214
215	//==================================================================================================================
216	//  add focus class from FORM LABEL
217	//------------------------------------------------------------------------------------------------------------------
218	addFocusClass: function() {
219		this.inputGroup().children("label").removeClass("input-label").addClass("input-focus-label");
220		return this;
221	},
222	
223	//==================================================================================================================
224	//  remove focus class from FORM LABEL
225	//------------------------------------------------------------------------------------------------------------------
226	removeFocusClass: function() {
227		var $rv = this.filter(function () {
228			if (this.value) {return false;}
229			if ($(this).prevAll(".input-group-addon")[0]) {return false;}
230			return $(this).is('input:not([type="date"],[type="hidden"],[type="checkbox"],[type="radio"],[type="button"],[type="submit"]),:not(select)');
231		});
232		$rv.inputGroup().children("label").addClass("input-label").removeClass("input-focus-label");
233		return $rv;
234	},
235	
236	//==================================================================================================================
237	//  Initialize focus class for FORM LABEL
238	//------------------------------------------------------------------------------------------------------------------
239	initializeFocusClass: function() {
240		return this.addFocusClass().removeFocusClass();
241	},
242
243	//==================================================================================================================
244	//  Return whether the first element is required,
245	//  OR
246	//  Set the required attribute for all elements, show/hide the Helper text if it is "(Optional)", 
247	//    and check for errors, which may show or hide a field level error message.
248	//------------------------------------------------------------------------------------------------------------------
249	required: function(isRequired) {
250		if (isRequired == undefined) {
251			// return the value of the required property for the first matched field.
252			return $(this).first().prop("required");
253		}
254		// add/remove the required attribute, set/remove the (Optional) helper text, and fire the change method
255		$(this).inputGroup().children("[id$="+$(this).attr("id")+"Help]").filter(":contains(Optional),:contains(Opcional)").toggle(!isRequired);
256		if (isRequired) {
257			return $(this).filter(function(index){return !$(this).prop("required")}).attr("required",true).removeErrors().checkForErrors();
258		} else {
259			return $(this).filter(function(index){return $(this).prop("required")}).removeAttr("required").removeErrors().checkForErrors();
260		}
261	}
262});
263
264//==================================================================================================================
265//  addError to input.  This function is suitable for using in a jQuery event handler
266//------------------------------------------------------------------------------------------------------------------
267function addInputError(errorField, errorMsg){
268	errorMsg = (typeof errorMsg !== undefined) ? errorMsg : "";
269    if(errorField.originalEvent instanceof Event || (typeof errorField === 'object' && errorField.type == 'invali
269d')) {
270        $(this).addInputError($(this).attr('error-msg') ? $(this).attr('error-msg') : $(this)[0].title ? $(this)[0].title : $(this)[0].validationMessage, true);
271    } else {
272        $(this).addInputError(errorMsg, false);
273    }
274}
275
276//==================================================================================================================
277//  Check for Errors.  This function is suitable for using in a jQuery event handler
278//------------------------------------------------------------------------------------------------------------------
279function checkForErrors(){
280	$(this).checkForErrors();
281    return true;
282}
283
284//==================================================================================================================
285//  Remove Errors.  This function is suitable for using in a jQuery event handler
286//------------------------------------------------------------------------------------------------------------------
287function removeErrors(){
288	$(this).removeErrors();
289}
290
291//==================================================================================================================
292//  add focus class from FORM LABEL.  This function is suitable for using in a jQuery event handler
293//------------------------------------------------------------------------------------------------------------------
294function addFocusClass(){
295    $(this).addFocusClass();
296}
297
298//==================================================================================================================
299//  remove focus class from FORM LABEL.  This function is suitable for using in a jQuery event handler
300//------------------------------------------------------------------------------------------------------------------
301function removeFocusClass(){
302    $(this).removeFocusClass();
303}
304
305//==================================================================================================================
306//  Initialize focus class for FORM LABEL.  This function is suitable for using in a jQuery event handler
307//------------------------------------------------------------------------------------------------------------------
308function initializeFocusClass(){
309    $(this).initializeFocusClass();
310}
311
312//==================================================================================================================
313//  Format Currency amount to two decimal points for FORM INPUT
314//------------------------------------------------------------------------------------------------------------------
315function formatCurrencyAmount(num) {
316    if (num == '') {return '';}
317
318    num = Number(num.toString().replace(/\$|\,/g, ''));
319    num = Math.round((num + Number.EPSILON) * 100) / 100;
320    if (isNaN(num)) {
321        return "0.00";
322    }
323    return num.toFixed(2);
324}
325
326//==================================================================================================================
327//  Apply Standard focus class to FORM LABEL
328//------------------------------------------------------------------------------------------------------------------
329$(document).ready(function() {
330    $('input:not([type="date"],[type="hidden"],[type="checkbox"],[type="radio"],[type="button"],[type="submit"])').initializeFocusClass();
331    $("[id^=visible]").initializeFocusClass();
332    $('input:not([type="date"],[type="hidden"],[type="checkbox"],[type="radio"],[type="button"],[type="submit"])').focus(addFocusClass);
333    $('input:not([type="date"],[type="hidden"],[type="checkbox"],[type="radio"],[type="button"],[type="submit"])').focusout(removeFocusClass);
334    $('input, select, textarea').focus(removeErrors);
335    $('input, select, textarea').blur(checkForErrors);
336    $('input, select, textarea').on('invalid', addInputError);
337});
338
339/*!
340 * Platform.js
341 * Copyright 2014-2018 Benjamin Tan
342 * Copyright 2011-2013 John-David Dalton
343 * Available under MIT license
344 */
345;(function() {
346  'use strict';
347
348  /** Used to determine if values are of the language type `Object`. */
349  var objectTypes = {
350    'function': true,
351    'object': true
352  };
353
354  /** Used as a reference to the global object. */
355  var root = (objectTypes[typeof window] && window) || this;
356
357  /** Backup possible global object. */
358  var oldRoot = root;
359
360  /** Detect free variable `exports`. */
361  var freeExports = objectTypes[typeof exports] && exports;
362
363  /** Detect free variable `module`. */
364  var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
365
366  /** Detect free variable `global` from Node.js or Browserified code and use it as `root`. */
367  var freeGlobal = freeExports && freeModule && typeof global == 'object' && global;
368  if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal || freeGlobal.self === freeGlobal)) {
369    root = freeGlobal;
370  }
371
372  /**
373   * Used as the maximum length of an array-like object.
374   * See the [ES6 spec](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength)
375   * for more details.
376   */
377  var maxSafeInteger = Math.pow(2, 53) - 1;
378
379  /** Regular expression to detect Opera. */
380  var reOpera = /\bOpera/;
381
382  /** Possible global object. */
383  var thisBinding = this;
384
385  /** Used for native method references. */
386  var objectProto = Object.prototype;
387
388  /** Used to check for own properties of an object. */
389  var hasOwnProperty = objectProto.hasOwnProperty;
390
391  /** Used to resolve the internal `[[Class]]` of values. */
392  var toString = objectProto.toString;
393
394  /*--------------------------------------------------------------------------*/
395
396  /**
397   * Capitalizes a string value.
398   *
399   * @private
400   * @param {string} string The string to capitalize.
401   * @returns {string} The capitalized string.
402   */
403  function capitalize(string) {
404    string = String(string);
405    return string.charAt(0).toUpperCase() + string.slice(1);
406  }
407
408  /**
409   * A utility function to clean up the OS name.
410   *
411   * @private
412   * @param {string} os The OS name to clean up.
413   * @param {string} [pattern] A `RegExp` pattern matching the OS name.
414   * @param {string} [label] A label for the OS.
415   */
416  function cleanupOS(os, pattern, label) {
417    // Platform tokens are defined at:
vendor: 8,661 bytes, lines 418-697
418    // http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
419    // http://web.archive.org/web/20081122053950/http://msdn.microsoft.com/en-us/library/ms537503(VS.85).aspx
420    var data = {
421      '10.0': '10',
422      '6.4':  '10 Technical Preview',
423      '6.3':  '8.1',
424      '6.2':  '8',
425      '6.1':  'Server 2008 R2 / 7',
426      '6.0':  'Server 2008 / Vista',
427      '5.2':  'Server 2003 / XP 64-bit',
428      '5.1':  'XP',
429      '5.01': '2000 SP1',
430      '5.0':  '2000',
431      '4.0':  'NT',
432      '4.90': 'ME'
433    };
434    // Detect Windows version from platform tokens.
435    if (pattern && label && /^Win/i.test(os) && !/^Windows Phone /i.test(os) &&
436        (data = data[/[\d.]+$/.exec(os)])) {
437      os = 'Windows ' + data;
438    }
439    // Correct character case and cleanup string.
440    os = String(os);
441
442    if (pattern && label) {
443      os = os.replace(RegExp(pattern, 'i'), label);
444    }
445
446    os = format(
447      os.replace(/ ce$/i, ' CE')
448        .replace(/\bhpw/i, 'web')
449        .replace(/\bMacintosh\b/, 'Mac OS')
450        .replace(/_PowerPC\b/i, ' OS')
451        .replace(/\b(OS X) [^ \d]+/i, '$1')
452        .replace(/\bMac (OS X)\b/, '$1')
453        .replace(/\/(\d)/, ' $1')
454        .replace(/_/g, '.')
455        .replace(/(?: BePC|[ .]*fc[ \d.]+)$/i, '')
456        .replace(/\bx86\.64\b/gi, 'x86_64')
457        .replace(/\b(Windows Phone) OS\b/, '$1')
458        .replace(/\b(Chrome OS \w+) [\d.]+\b/, '$1')
459        .split(' on ')[0]
460    );
461
462    return os;
463  }
464
465  /**
466   * An iteration utility for arrays and objects.
467   *
468   * @private
469   * @param {Array|Object} object The object to iterate over.
470   * @param {Function} callback The function called per iteration.
471   */
472  function each(object, callback) {
473    var index = -1,
474        length = object ? object.length : 0;
475
476    if (typeof length == 'number' && length > -1 && length <= maxSafeInteger) {
477      while (++index < length) {
478        callback(object[index], index, object);
479      }
480    } else {
481      forOwn(object, callback);
482    }
483  }
484
485  /**
486   * Trim and conditionally capitalize string values.
487   *
488   * @private
489   * @param {string} string The string to format.
490   * @returns {string} The formatted string.
491   */
492  function format(string) {
493    string = trim(string);
494    return /^(?:webOS|i(?:OS|P))/.test(string)
495      ? string
496      : capitalize(string);
497  }
498
499  /**
500   * Iterates over an object's own properties, executing the `callback` for each.
501   *
502   * @private
503   * @param {Object} object The object to iterate over.
504   * @param {Function} callback The function executed per own property.
505   */
506  function forOwn(object, callback) {
507    for (var key in object) {
508      if (hasOwnProperty.call(object, key)) {
509        callback(object[key], key, object);
510      }
511    }
512  }
513
514  /**
515   * Gets the internal `[[Class]]` of a value.
516   *
517   * @private
518   * @param {*} value The value.
519   * @returns {string} The `[[Class]]`.
520   */
521  function getClassOf(value) {
522    return value == null
523      ? capitalize(value)
524      : toString.call(value).slice(8, -1);
525  }
526
527  /**
528   * Host objects can return type values that are different from their actual
529   * data type. The objects we are concerned with usually return non-primitive
530   * types of "object", "function", or "unknown".
531   *
532   * @private
533   * @param {*} object The owner of the property.
534   * @param {string} property The property to check.
535   * @returns {boolean} Returns `true` if the property value is a non-primitive, else `false`.
536   */
537  function isHostType(object, property) {
538    var type = object != null ? typeof object[property] : 'number';
539    return !/^(?:boolean|number|string|undefined)$/.test(type) &&
540      (type == 'object' ? !!object[property] : true);
541  }
542
543  /**
544   * Prepares a string for use in a `RegExp` by making hyphens and spaces optional.
545   *
546   * @private
547   * @param {string} string The string to qualify.
548   * @returns {string} The qualified string.
549   */
550  function qualify(string) {
551    return String(string).replace(/([ -])(?!$)/g, '$1?');
552  }
553
554  /**
555   * A bare-bones `Array#reduce` like utility function.
556   *
557   * @private
558   * @param {Array} array The array to iterate over.
559   * @param {Function} callback The function called per iteration.
560   * @returns {*} The accumulated result.
561   */
562  function reduce(array, callback) {
563    var accumulator = null;
564    each(array, function(value, index) {
565      accumulator = callback(accumulator, value, index, array);
566    });
567    return accumulator;
568  }
569
570  /**
571   * Removes leading and trailing whitespace from a string.
572   *
573   * @private
574   * @param {string} string The string to trim.
575   * @returns {string} The trimmed string.
576   */
577  function trim(string) {
578    return String(string).replace(/^ +| +$/g, '');
579  }
580
581  /*--------------------------------------------------------------------------*/
582
583  /**
584   * Creates a new platform object.
585   *
586   * @memberOf platform
587   * @param {Object|string} [ua=navigator.userAgent] The user agent string or
588   *  context object.
589   * @returns {Object} A platform object.
590   */
591  function parse(ua) {
592
593    /** The environment context object. */
594    var context = root;
595
596    /** Used to flag when a custom context is provided. */
597    var isCustomContext = ua && typeof ua == 'object' && getClassOf(ua) != 'String';
598
599    // Juggle arguments.
600    if (isCustomContext) {
601      context = ua;
602      ua = null;
603    }
604
605    /** Browser navigator object. */
606    var nav = context.navigator || {};
607
608    /** Browser user agent string. */
609    var userAgent = nav.userAgent || '';
610
611    ua || (ua = userAgent);
612
613    /** Used to flag when `thisBinding` is the [ModuleScope]. */
614    var isModuleScope = isCustomContext || thisBinding == oldRoot;
615
616    /** Used to detect if browser is like Chrome. */
617    var likeChrome = isCustomContext
618      ? !!nav.likeChrome
619      : /\bChrome\b/.test(ua) && !/internal|\n/i.test(toString.toString());
620
621    /** Internal `[[Class]]` value shortcuts. */
622    var objectClass = 'Object',
623        airRuntimeClass = isCustomContext ? objectClass : 'ScriptBridgingProxyObject',
624        enviroClass = isCustomContext ? objectClass : 'Environment',
625        javaClass = (isCustomContext && context.java) ? 'JavaPackage' : getClassOf(context.java),
626        phantomClass = isCustomContext ? objectClass : 'RuntimeObject';
627
628    /** Detect Java environments. */
629    var java = /\bJava/.test(javaClass) && context.java;
630
631    /** Detect Rhino. */
632    var rhino = java && getClassOf(context.environment) == enviroClass;
633
634    /** A character to represent alpha. */
635    var alpha = java ? 'a' : '\u03b1';
636
637    /** A character to represent beta. */
638    var beta = java ? 'b' : '\u03b2';
639
640    /** Browser document object. */
641    var doc = context.document || {};
642
643    /**
644     * Detect Opera browser (Presto-based).
645     * http://www.howtocreate.co.uk/operaStuff/operaObject.html
646     * http://dev.opera.com/articles/view/opera-mini-web-content-authoring-guidelines/#operamini
647     */
648    var opera = context.operamini || context.opera;
649
650    /** Opera `[[Class]]`. */
651    var operaClass = reOpera.test(operaClass = (isCustomContext && opera) ? opera['[[Class]]'] : getClassOf(opera))
652      ? operaClass
653      : (opera = null);
654
655    /*------------------------------------------------------------------------*/
656
657    /** Temporary variable used over the script's lifetime. */
658    var data;
659
660    /** The CPU architecture. */
661    var arch = ua;
662
663    /** Platform description array. */
664    var description = [];
665
666    /** Platform alpha/beta indicator. */
667    var prerelease = null;
668
669    /** A flag to indicate that environment features should be used to resolve the platform. */
670    var useFeatures = ua == userAgent;
671
672    /** The browser/environment version. */
673    var version = useFeatures && opera && typeof opera.version == 'function' && opera.version();
674
675    /** A flag to indicate if the OS ends with "/ Version" */
676    var isSpecialCasedOS;
677
678    /* Detectable layout engines (order is important). */
679    var layout = getLayout([
680      { 'label': 'EdgeHTML', 'pattern': '(?:Edge|EdgA|EdgiOS)' },
681      'Trident',
682      { 'label': 'WebKit', 'pattern': 'AppleWebKit' },
683      'iCab',
684      'Presto',
685      'NetFront',
686      'Tasman',
687      'KHTML',
688      'Gecko'
689    ]);
690
691    /* Detectable browser names (order is important). */
692    var name = getName([
693      'Adobe AIR',
694      'Arora',
695      'Avant Browser',
696      'Breach',
697      'Camino',
vendor: 11,309 bytes, lines 698-1029
698      'Electron',
699      'Epiphany',
700      'Fennec',
701      'Flock',
702      'Galeon',
703      'GreenBrowser',
704      'iCab',
705      'Iceweasel',
706      'K-Meleon',
707      'Konqueror',
708      'Lunascape',
709      'Maxthon',
710      { 'label': 'Microsoft Edge', 'pattern': '(?:Edge|Edg|EdgA|EdgiOS)' },
711      'Midori',
712      'Nook Browser',
713      'PaleMoon',
714      'PhantomJS',
715      'Raven',
716      'Rekonq',
717      'RockMelt',
718      { 'label': 'Samsung Internet', 'pattern': 'SamsungBrowser' },
719      'SeaMonkey',
720      { 'label': 'Silk', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
721      'Sleipnir',
722      'SlimBrowser',
723      { 'label': 'SRWare Iron', 'pattern': 'Iron' },
724      'Sunrise',
725      'Swiftfox',
726      'Waterfox',
727      'WebPositive',
728      'Opera Mini',
729      { 'label': 'Opera Mini', 'pattern': 'OPiOS' },
730      'Opera',
731      { 'label': 'Opera', 'pattern': 'OPR' },
732      'Chrome',
733      { 'label': 'Chrome Mobile', 'pattern': '(?:CriOS|CrMo)' },
734      { 'label': 'Firefox', 'pattern': '(?:Firefox|Minefield)' },
735      { 'label': 'Firefox for iOS', 'pattern': 'FxiOS' },
736      { 'label': 'IE', 'pattern': 'IEMobile' },
737      { 'label': 'IE', 'pattern': 'MSIE' },
738      'Safari'
739    ]);
740
741    /* Detectable products (order is important). */
742    var product = getProduct([
743      { 'label': 'BlackBerry', 'pattern': 'BB10' },
744      'BlackBerry',
745      { 'label': 'Galaxy S', 'pattern': 'GT-I9000' },
746      { 'label': 'Galaxy S2', 'pattern': 'GT-I9100' },
747      { 'label': 'Galaxy S3', 'pattern': 'GT-I9300' },
748      { 'label': 'Galaxy S4', 'pattern': 'GT-I9500' },
749      { 'label': 'Galaxy S5', 'pattern': 'SM-G900' },
750      { 'label': 'Galaxy S6', 'pattern': 'SM-G920' },
751      { 'label': 'Galaxy S6 Edge', 'pattern': 'SM-G925' },
752      { 'label': 'Galaxy S7', 'pattern': 'SM-G930' },
753      { 'label': 'Galaxy S7 Edge', 'pattern': 'SM-G935' },
754      'Google TV',
755      'Lumia',
756      'iPad',
757      'iPod',
758      'iPhone',
759      'Kindle',
760      { 'label': 'Kindle Fire', 'pattern': '(?:Cloud9|Silk-Accelerated)' },
761      'Nexus',
762      'Nook',
763      'PlayBook',
764      'PlayStation Vita',
765      'PlayStation',
766      'TouchPad',
767      'Transformer',
768      { 'label': 'Wii U', 'pattern': 'WiiU' },
769      'Wii',
770      'Xbox One',
771      { 'label': 'Xbox 360', 'pattern': 'Xbox' },
772      'Xoom'
773    ]);
774
775    /* Detectable manufacturers. */
776    var manufacturer = getManufacturer({
777      'Apple': { 'iPad': 1, 'iPhone': 1, 'iPod': 1 },
778      'Archos': {},
779      'Amazon': { 'Kindle': 1, 'Kindle Fire': 1 },
780      'Asus': { 'Transformer': 1 },
781      'Barnes & Noble': { 'Nook': 1 },
782      'BlackBerry': { 'PlayBook': 1 },
783      'Google': { 'Google TV': 1, 'Nexus': 1 },
784      'HP': { 'TouchPad': 1 },
785      'HTC': {},
786      'LG': {},
787      'Microsoft': { 'Xbox': 1, 'Xbox One': 1 },
788      'Motorola': { 'Xoom': 1 },
789      'Nintendo': { 'Wii U': 1,  'Wii': 1 },
790      'Nokia': { 'Lumia': 1 },
791      'Samsung': { 'Galaxy S': 1, 'Galaxy S2': 1, 'Galaxy S3': 1, 'Galaxy S4': 1 },
792      'Sony': { 'PlayStation': 1, 'PlayStation Vita': 1 }
793    });
794
795    /* Detectable operating systems (order is important). */
796    var os = getOS([
797      'Windows Phone',
798      'Android',
799      'CentOS',
800      { 'label': 'Chrome OS', 'pattern': 'CrOS' },
801      'Debian',
802      'Fedora',
803      'FreeBSD',
804      'Gentoo',
805      'Haiku',
806      'Kubuntu',
807      'Linux Mint',
808      'OpenBSD',
809      'Red Hat',
810      'SuSE',
811      'Ubuntu',
812      'Xubuntu',
813      'Cygwin',
814      'Symbian OS',
815      'hpwOS',
816      'webOS ',
817      'webOS',
818      'Tablet OS',
819      'Tizen',
820      'Linux',
821      'Mac OS X',
822      'Macintosh',
823      'Mac',
824      'Windows 98;',
825      'Windows '
826    ]);
827
828    /*------------------------------------------------------------------------*/
829
830    /**
831     * Picks the layout engine from an array of guesses.
832     *
833     * @private
834     * @param {Array} guesses An array of guesses.
835     * @returns {null|string} The detected layout engine.
836     */
837    function getLayout(guesses) {
838      return reduce(guesses, function(result, guess) {
839        return result || RegExp('\\b' + (
840          guess.pattern || qualify(guess)
841        ) + '\\b', 'i').exec(ua) && (guess.label || guess);
842      });
843    }
844
845    /**
846     * Picks the manufacturer from an array of guesses.
847     *
848     * @private
849     * @param {Array} guesses An object of guesses.
850     * @returns {null|string} The detected manufacturer.
851     */
852    function getManufacturer(guesses) {
853      return reduce(guesses, function(result, value, key) {
854        // Lookup the manufacturer by product or scan the UA for the manufacturer.
855        return result || (
856          value[product] ||
857          value[/^[a-z]+(?: +[a-z]+\b)*/i.exec(product)] ||
858          RegExp('\\b' + qualify(key) + '(?:\\b|\\w*\\d)', 'i').exec(ua)
859        ) && key;
860      });
861    }
862
863    /**
864     * Picks the browser name from an array of guesses.
865     *
866     * @private
867     * @param {Array} guesses An array of guesses.
868     * @returns {null|string} The detected browser name.
869     */
870    function getName(guesses) {
871      return reduce(guesses, function(result, guess) {
872        return result || RegExp('\\b' + (
873          guess.pattern || qualify(guess)
874        ) + '\\b', 'i').exec(ua) && (guess.label || guess);
875      });
876    }
877
878    /**
879     * Picks the OS name from an array of guesses.
880     *
881     * @private
882     * @param {Array} guesses An array of guesses.
883     * @returns {null|string} The detected OS name.
884     */
885    function getOS(guesses) {
886      return reduce(guesses, function(result, guess) {
887        var pattern = guess.pattern || qualify(guess);
888        if (!result && (result =
889              RegExp('\\b' + pattern + '(?:/[\\d.]+|[ \\w.]*)', 'i').exec(ua)
890            )) {
891          result = cleanupOS(result, pattern, guess.label || guess);
892        }
893        return result;
894      });
895    }
896
897    /**
898     * Picks the product name from an array of guesses.
899     *
900     * @private
901     * @param {Array} guesses An array of guesses.
902     * @returns {null|string} The detected product name.
903     */
904    function getProduct(guesses) {
905      return reduce(guesses, function(result, guess) {
906        var pattern = guess.pattern || qualify(guess);
907        if (!result && (result =
908              RegExp('\\b' + pattern + ' *\\d+[.\\w_]*', 'i').exec(ua) ||
909              RegExp('\\b' + pattern + ' *\\w+-[\\w]*', 'i').exec(ua) ||
910              RegExp('\\b' + pattern + '(?:; *(?:[a-z]+[_-])?[a-z]+\\d+|[^ ();-]*)', 'i').exec(ua)
911            )) {
912          // Split by forward slash and append product version if needed.
913          if ((result = String((guess.label && !RegExp(pattern, 'i').test(guess.label)) ? guess.label : result).split('/'))[1] && !/[\d.]+/.test(result[0])) {
914            result[0] += ' ' + result[1];
915          }
916          // Correct character case and cleanup string.
917          guess = guess.label || guess;
918          result = format(result[0]
919            .replace(RegExp(pattern, 'i'), guess)
920            .replace(RegExp('; *(?:' + guess + '[_-])?', 'i'), ' ')
921            .replace(RegExp('(' + guess + ')[-_.]?(\\w)', 'i'), '$1 $2'));
922        }
923        return result;
924      });
925    }
926
927    /**
928     * Resolves the version using an array of UA patterns.
929     *
930     * @private
931     * @param {Array} patterns An array of UA patterns.
932     * @returns {null|string} The detected version.
933     */
934    function getVersion(patterns) {
935      return reduce(patterns, function(result, pattern) {
936        return result || (RegExp(pattern +
937          '(?:-[\\d.]+/|(?: for [\\w-]+)?[ /-])([\\d.]+[^ ();/_-]*)', 'i').exec(ua) || 0)[1] || null;
938      });
939    }
940
941    /**
942     * Returns `platform.description` when the platform object is coerced to a string.
943     *
944     * @name toString
945     * @memberOf platform
946     * @returns {string} Returns `platform.description` if available, else an empty string.
947     */
948    function toStringPlatform() {
949      return this.description || '';
950    }
951
952    /*------------------------------------------------------------------------*/
953
954    // Convert layout to an array so we can add extra details.
955    layout && (layout = [layout]);
956
957    // Detect product names that contain their manufacturer's name.
958    if (manufacturer && !product) {
959      product = getProduct([manufacturer]);
960    }
961    // Clean up Google TV.
962    if ((data = /\bGoogle TV\b/.exec(product))) {
963      product = data[0];
964    }
965    // Detect simulators.
966    if (/\bSimulator\b/i.test(ua)) {
967      product = (product ? product + ' ' : '') + 'Simulator';
968    }
969    // Detect Opera Mini 8+ running in Turbo/Uncompressed mode on iOS.
970    if (name == 'Opera Mini' && /\bOPiOS\b/.test(ua)) {
971      description.push('running in Turbo/Uncompressed mode');
972    }
973    // Detect IE Mobile 11.
974    if (name == 'IE' && /\blike iPhone OS\b/.test(ua)) {
975      data = parse(ua.replace(/like iPhone OS/, ''));
976      manufacturer = data.manufacturer;
977      product = data.product;
978    }
979    // Detect iOS.
980    else if (/^iP/.test(product)) {
981      name || (name = 'Safari');
982      os = 'iOS' + ((data = / OS ([\d_]+)/i.exec(ua))
983        ? ' ' + data[1].replace(/_/g, '.')
984        : '');
985    }
986    // Detect Kubuntu.
987    else if (name == 'Konqueror' && !/buntu/i.test(os)) {
988      os = 'Kubuntu';
989    }
990    // Detect Android browsers.
991    else if ((manufacturer && manufacturer != 'Google' &&
992        ((/Chrome/.test(name) && !/\bMobile Safari\b/i.test(ua)) || /\bVita\b/.test(product))) ||
993        (/\bAndroid\b/.test(os) && /^Chrome/.test(name) && /\bVersion\//i.test(ua))) {
994      name = 'Android Browser';
995      os = /\bAndroid\b/.test(os) ? os : 'Android';
996    }
997    // Detect Silk desktop/accelerated modes.
998    else if (name == 'Silk') {
999      if (!/\bMobi/i.test(ua)) {
1000        os = 'Android';
1001        description.unshift('desktop mode');
1002      }
1003      if (/Accelerated *= *true/i.test(ua)) {
1004        description.unshift('accelerated');
1005      }
1006    }
1007    // Detect PaleMoon identifying as Firefox.
1008    else if (name == 'PaleMoon' && (data = /\bFirefox\/([\d.]+)\b/.exec(ua))) {
1009      description.push('identifying as Firefox ' + data[1]);
1010    }
1011    // Detect Firefox OS and products running Firefox.
1012    else if (name == 'Firefox' && (data = /\b(Mobile|Tablet|TV)\b/i.exec(ua))) {
1013      os || (os = 'Firefox OS');
1014      product || (product = data[1]);
1015    }
1016    // Detect false positives for Firefox/Safari.
1017    else if (!name || (data = !/\bMinefield\b/i.test(ua) && /\b(?:Firefox|Safari)\b/.exec(name))) {
1018      // Escape the `/` for Firefox 1.
1019      if (name && !product && /[\/,]|^[^(]+?\)/.test(ua.slice(ua.indexOf(data + '/') + 8))) {
1020        // Clear name of false positives.
1021        name = null;
1022      }
1023      // Reassign a generic name.
1024      if ((data = product || manufacturer || os) &&
1025          (product || manufacturer || /\b(?:Android|Symbian OS|Tablet OS|webOS)\b/.test(os))) {
1026        name = /[a-z]+(?: Hat)?/i.exec(/\bAndroid\b/.test(os) ? os : data) + ' Browser';
1027      }
1028    }
1029    // Add Chrome version to description for Electron.
vendor: 6,712 bytes, lines 1030-1196
1030    else if (name == 'Electron' && (data = (/\bChrome\/([\d.]+)\b/.exec(ua) || 0)[1])) {
1031      description.push('Chromium ' + data);
1032    }
1033    // Detect non-Opera (Presto-based) versions (order is important).
1034    if (!version) {
1035      version = getVersion([
1036        '(?:Cloud9|CriOS|CrMo|Edge|Edg|EdgA|EdgiOS|FxiOS|IEMobile|Iron|Opera ?Mini|OPiOS|OPR|Raven|SamsungBrowser|Silk(?!/[\\d.]+$))',
1037        'Version',
1038        qualify(name),
1039        '(?:Firefox|Minefield|NetFront)'
1040      ]);
1041    }
1042    // Detect stubborn layout engines.
1043    if ((data =
1044          layout == 'iCab' && parseFloat(version) > 3 && 'WebKit' ||
1045          /\bOpera\b/.test(name) && (/\bOPR\b/.test(ua) ? 'Blink' : 'Presto') ||
1046          /\b(?:Midori|Nook|Safari)\b/i.test(ua) && !/^(?:Trident|EdgeHTML)$/.test(layout) && 'WebKit' ||
1047          !layout && /\bMSIE\b/i.test(ua) && (os == 'Mac OS' ? 'Tasman' : 'Trident') ||
1048          layout == 'WebKit' && /\bPlayStation\b(?! Vita\b)/i.test(name) && 'NetFront'
1049        )) {
1050      layout = [data];
1051    }
1052    // Detect Windows Phone 7 desktop mode.
1053    if (name == 'IE' && (data = (/; *(?:XBLWP|ZuneWP)(\d+)/i.exec(ua) || 0)[1])) {
1054      name += ' Mobile';
1055      os = 'Windows Phone ' + (/\+$/.test(data) ? data : data + '.x');
1056      description.unshift('desktop mode');
1057    }
1058    // Detect Windows Phone 8.x desktop mode.
1059    else if (/\bWPDesktop\b/i.test(ua)) {
1060      name = 'IE Mobile';
1061      os = 'Windows Phone 8.x';
1062      description.unshift('desktop mode');
1063      version || (version = (/\brv:([\d.]+)/.exec(ua) || 0)[1]);
1064    }
1065    // Detect IE 11 identifying as other browsers.
1066    else if (name != 'IE' && layout == 'Trident' && (data = /\brv:([\d.]+)/.exec(ua))) {
1067      if (name) {
1068        description.push('identifying as ' + name + (version ? ' ' + version : ''));
1069      }
1070      name = 'IE';
1071      version = data[1];
1072    }
1073    // Leverage environment features.
1074    if (useFeatures) {
1075      // Detect server-side environments.
1076      // Rhino has a global function while others have a global object.
1077      if (isHostType(context, 'global')) {
1078        if (java) {
1079          data = java.lang.System;
1080          arch = data.getProperty('os.arch');
1081          os = os || data.getProperty('os.name') + ' ' + data.getProperty('os.version');
1082        }
1083        if (rhino) {
1084          try {
1085            version = context.require('ringo/engine').version.join('.');
1086            name = 'RingoJS';
1087          } catch(e) {
1088            if ((data = context.system) && data.global.system == context.system) {
1089              name = 'Narwhal';
1090              os || (os = data[0].os || null);
1091            }
1092          }
1093          if (!name) {
1094            name = 'Rhino';
1095          }
1096        }
1097        else if (
1098          typeof context.process == 'object' && !context.process.browser &&
1099          (data = context.process)
1100        ) {
1101          if (typeof data.versions == 'object') {
1102            if (typeof data.versions.electron == 'string') {
1103              description.push('Node ' + data.versions.node);
1104              name = 'Electron';
1105              version = data.versions.electron;
1106            } else if (typeof data.versions.nw == 'string') {
1107              description.push('Chromium ' + version, 'Node ' + data.versions.node);
1108              name = 'NW.js';
1109              version = data.versions.nw;
1110            }
1111          }
1112          if (!name) {
1113            name = 'Node.js';
1114            arch = data.arch;
1115            os = data.platform;
1116            version = /[\d.]+/.exec(data.version);
1117            version = version ? version[0] : null;
1118          }
1119        }
1120      }
1121      // Detect Adobe AIR.
1122      else if (getClassOf((data = context.runtime)) == airRuntimeClass) {
1123        name = 'Adobe AIR';
1124        os = data.flash.system.Capabilities.os;
1125      }
1126      // Detect PhantomJS.
1127      else if (getClassOf((data = context.phantom)) == phantomClass) {
1128        name = 'PhantomJS';
1129        version = (data = data.version || null) && (data.major + '.' + data.minor + '.' + data.patch);
1130      }
1131      // Detect IE compatibility modes.
1132      else if (typeof doc.documentMode == 'number' && (data = /\bTrident\/(\d+)/i.exec(ua))) {
1133        // We're in compatibility mode when the Trident version + 4 doesn't
1134        // equal the document mode.
1135        version = [version, doc.documentMode];
1136        if ((data = +data[1] + 4) != version[1]) {
1137          description.push('IE ' + version[1] + ' mode');
1138          layout && (layout[1] = '');
1139          version[1] = data;
1140        }
1141        version = name == 'IE' ? String(version[1].toFixed(1)) : version[0];
1142      }
1143      // Detect IE 11 masking as other browsers.
1144      else if (typeof doc.documentMode == 'number' && /^(?:Chrome|Firefox)\b/.test(name)) {
1145        description.push('masking as ' + name + ' ' + version);
1146        name = 'IE';
1147        version = '11.0';
1148        layout = ['Trident'];
1149        os = 'Windows';
1150      }
1151      os = os && format(os);
1152    }
1153    // Detect prerelease phases.
1154    if (version && (data =
1155          /(?:[ab]|dp|pre|[ab]\d+pre)(?:\d+\+?)?$/i.exec(version) ||
1156          /(?:alpha|beta)(?: ?\d)?/i.exec(ua + ';' + (useFeatures && nav.appMinorVersion)) ||
1157          /\bMinefield\b/i.test(ua) && 'a'
1158        )) {
1159      prerelease = /b/i.test(data) ? 'beta' : 'alpha';
1160      version = version.replace(RegExp(data + '\\+?$'), '') +
1161        (prerelease == 'beta' ? beta : alpha) + (/\d+\+?/.exec(data) || '');
1162    }
1163    // Detect Firefox Mobile.
1164    if (name == 'Fennec' || name == 'Firefox' && /\b(?:Android|Firefox OS)\b/.test(os)) {
1165      name = 'Firefox Mobile';
1166    }
1167    // Obscure Maxthon's unreliable version.
1168    else if (name == 'Maxthon' && version) {
1169      version = version.replace(/\.[\d.]+/, '.x');
1170    }
1171    // Detect Xbox 360 and Xbox One.
1172    else if (/\bXbox\b/i.test(product)) {
1173      if (product == 'Xbox 360') {
1174        os = null;
1175      }
1176      if (product == 'Xbox 360' && /\bIEMobile\b/.test(ua)) {
1177        description.unshift('mobile mode');
1178      }
1179    }
1180    // Add mobile postfix.
1181    else if ((/^(?:Chrome|IE|Opera)$/.test(name) || name && !product && !/Browser|Mobi/.test(name)) &&
1182        (os == 'Windows CE' || /Mobi/i.test(ua))) {
1183      name += ' Mobile';
1184    }
1185    // Detect IE platform preview.
1186    else if (name == 'IE' && useFeatures) {
1187      try {
1188        if (context.external === null) {
1189          description.unshift('platform preview');
1190        }
1191      } catch(e) {
1192        description.unshift('embedded');
1193      }
1194    }
1195    // Detect BlackBerry OS version.
1196    // http://docs.blackberry.com/en/developers/deliverables/18169/
vendor: 5,386 bytes, lines 1196-1312
1196HTTP_headers_sent_by_BB_Browser_1234911_11.jsp
1197    else if ((/\bBlackBerry\b/.test(product) || /\bBB10\b/.test(ua)) && (data =
1198          (RegExp(product.replace(/ +/g, ' *') + '/([.\\d]+)', 'i').exec(ua) || 0)[1] ||
1199          version
1200        )) {
1201      data = [data, /BB10/.test(ua)];
1202      os = (data[1] ? (product = null, manufacturer = 'BlackBerry') : 'Device Software') + ' ' + data[0];
1203      version = null;
1204    }
1205    // Detect Opera identifying/masking itself as another browser.
1206    // http://www.opera.com/support/kb/view/843/
1207    else if (this != forOwn && product != 'Wii' && (
1208          (useFeatures && opera) ||
1209          (/Opera/.test(name) && /\b(?:MSIE|Firefox)\b/i.test(ua)) ||
1210          (name == 'Firefox' && /\bOS X (?:\d+\.){2,}/.test(os)) ||
1211          (name == 'IE' && (
1212            (os && !/^Win/.test(os) && version > 5.5) ||
1213            /\bWindows XP\b/.test(os) && version > 8 ||
1214            version == 8 && !/\bTrident\b/.test(ua)
1215          ))
1216        ) && !reOpera.test((data = parse.call(forOwn, ua.replace(reOpera, '') + ';'))) && data.name) {
1217      // When "identifying", the UA contains both Opera and the other browser's name.
1218      data = 'ing as ' + data.name + ((data = data.version) ? ' ' + data : '');
1219      if (reOpera.test(name)) {
1220        if (/\bIE\b/.test(data) && os == 'Mac OS') {
1221          os = null;
1222        }
1223        data = 'identify' + data;
1224      }
1225      // When "masking", the UA contains only the other browser's name.
1226      else {
1227        data = 'mask' + data;
1228        if (operaClass) {
1229          name = format(operaClass.replace(/([a-z])([A-Z])/g, '$1 $2'));
1230        } else {
1231          name = 'Opera';
1232        }
1233        if (/\bIE\b/.test(data)) {
1234          os = null;
1235        }
1236        if (!useFeatures) {
1237          version = null;
1238        }
1239      }
1240      layout = ['Presto'];
1241      description.push(data);
1242    }
1243    // Detect WebKit Nightly and approximate Chrome/Safari versions.
1244    if ((data = (/\bAppleWebKit\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
1245      // Correct build number for numeric comparison.
1246      // (e.g. "532.5" becomes "532.05")
1247      data = [parseFloat(data.replace(/\.(\d)$/, '.0$1')), data];
1248      // Nightly builds are postfixed with a "+".
1249      if (name == 'Safari' && data[1].slice(-1) == '+') {
1250        name = 'WebKit Nightly';
1251        prerelease = 'alpha';
1252        version = data[1].slice(0, -1);
1253      }
1254      // Clear incorrect browser versions.
1255      else if (version == data[1] ||
1256          version == (data[2] = (/\bSafari\/([\d.]+\+?)/i.exec(ua) || 0)[1])) {
1257        version = null;
1258      }
1259      // Use the full Chrome version when available.
1260      data[1] = (/\bChrome\/([\d.]+)/i.exec(ua) || 0)[1];
1261      // Detect Blink layout engine.
1262      if (data[0] == 537.36 && data[2] == 537.36 && parseFloat(data[1]) >= 28 && layout == 'WebKit') {
1263        layout = ['Blink'];
1264      }
1265      // Detect JavaScriptCore.
1266      // http://stackoverflow.com/questions/6768474/how-can-i-detect-which-javascript-engine-v8-or-jsc-is-used-at-runtime-in-androi
1267      if (!useFeatures || (!likeChrome && !data[1])) {
1268        layout && (layout[1] = 'like Safari');
1269        data = (data = data[0], data < 400 ? 1 : data < 500 ? 2 : data < 526 ? 3 : data < 533 ? 4 : data < 534 ? '4+' : data < 535 ? 5 : data < 537 ? 6 : data < 538 ? 7 : data < 601 ? 8 : '8');
1270      } else {
1271        layout && (layout[1] = 'like Chrome');
1272        data = data[1] || (data = data[0], data < 530 ? 1 : data < 532 ? 2 : data < 532.05 ? 3 : data < 533 ? 4 : data < 534.03 ? 5 : data < 534.07 ? 6 : data < 534.10 ? 7 : data < 534.13 ? 8 : data < 534.16 ? 9 : data < 534.24 ? 10 : data < 534.30 ? 11 : data < 535.01 ? 12 : data < 535.02 ? '13+' : data < 535.07 ? 15 : data < 535.11 ? 16 : data < 535.19 ? 17 : data < 536.05 ? 18 : data < 536.10 ? 19 : data < 537.01 ? 20 : data < 537.11 ? '21+' : data < 537.13 ? 23 : data < 537.18 ? 24 : data < 537.24 ? 25 : data < 537.36 ? 26 : layout != 'Blink' ? '27' : '28');
1273      }
1274      // Add the postfix of ".x" or "+" for approximate versions.
1275      layout && (layout[1] += ' ' + (data += typeof data == 'number' ? '.x' : /[.+]/.test(data) ? '' : '+'));
1276      // Obscure version for some Safari 1-2 releases.
1277      if (name == 'Safari' && (!version || parseInt(version) > 45)) {
1278        version = data;
1279      }
1280    }
1281    // Detect Opera desktop modes.
1282    if (name == 'Opera' &&  (data = /\bzbov|zvav$/.exec(os))) {
1283      name += ' ';
1284      description.unshift('desktop mode');
1285      if (data == 'zvav') {
1286        name += 'Mini';
1287        version = null;
1288      } else {
1289        name += 'Mobile';
1290      }
1291      os = os.replace(RegExp(' *' + data + '$'), '');
1292    }
1293    // Detect Chrome desktop mode.
1294    else if (name == 'Safari' && /\bChrome\b/.exec(layout && layout[1])) {
1295      description.unshift('desktop mode');
1296      name = 'Chrome Mobile';
1297      version = null;
1298
1299      if (/\bOS X\b/.test(os)) {
1300        manufacturer = 'Apple';
1301        os = 'iOS 4.3+';
1302      } else {
1303        os = null;
1304      }
1305    }
1306    // Strip incorrect OS versions.
1307    if (version && version.indexOf((data = /[\d.]+$/.exec(os))) == 0 &&
1308        ua.indexOf('/' + data + '-') > -1) {
1309      os = trim(os.replace(data, ''));
1310    }
1311    // Add layout engine.
1312    if (layout && !/\b(?:Avant|Nook)\b/.test(name) && (
vendor: 9,088 bytes, lines 1313-1596
1313        /Browser|Lunascape|Maxthon/.test(name) ||
1314        name != 'Safari' && /^iOS/.test(os) && /\bSafari\b/.test(layout[1]) ||
1315        /^(?:Adobe|Arora|Breach|Midori|Opera|Phantom|Rekonq|Rock|Samsung Internet|Sleipnir|Web)/.test(name) && layout[1])) {
1316      // Don't add layout details to description if they are falsey.
1317      (data = layout[layout.length - 1]) && description.push(data);
1318    }
1319    // Combine contextual information.
1320    if (description.length) {
1321      description = ['(' + description.join('; ') + ')'];
1322    }
1323    // Append manufacturer to description.
1324    if (manufacturer && product && product.indexOf(manufacturer) < 0) {
1325      description.push('on ' + manufacturer);
1326    }
1327    // Append product to description.
1328    if (product) {
1329      description.push((/^on /.test(description[description.length - 1]) ? '' : 'on ') + product);
1330    }
1331    // Parse the OS into an object.
1332    if (os) {
1333      data = / ([\d.+]+)$/.exec(os);
1334      isSpecialCasedOS = data && os.charAt(os.length - data[0].length - 1) == '/';
1335      os = {
1336        'architecture': 32,
1337        'family': (data && !isSpecialCasedOS) ? os.replace(data[0], '') : os,
1338        'version': data ? data[1] : null,
1339        'toString': function() {
1340          var version = this.version;
1341          return this.family + ((version && !isSpecialCasedOS) ? ' ' + version : '') + (this.architecture == 64 ? ' 64-bit' : '');
1342        }
1343      };
1344    }
1345    // Add browser/OS architecture.
1346    if ((data = /\b(?:AMD|IA|Win|WOW|x86_|x)64\b/i.exec(arch)) && !/\bi686\b/i.test(arch)) {
1347      if (os) {
1348        os.architecture = 64;
1349        os.family = os.family.replace(RegExp(' *' + data), '');
1350      }
1351      if (
1352          name && (/\bWOW64\b/i.test(ua) ||
1353          (useFeatures && /\w(?:86|32)$/.test(nav.cpuClass || nav.platform) && !/\bWin64; x64\b/i.test(ua)))
1354      ) {
1355        description.unshift('32-bit');
1356      }
1357    }
1358    // Chrome 39 and above on OS X is always 64-bit.
1359    else if (
1360        os && /^OS X/.test(os.family) &&
1361        name == 'Chrome' && parseFloat(version) >= 39
1362    ) {
1363      os.architecture = 64;
1364    }
1365
1366    ua || (ua = null);
1367
1368    /*------------------------------------------------------------------------*/
1369
1370    /**
1371     * The platform object.
1372     *
1373     * @name platform
1374     * @type Object
1375     */
1376    var platform = {};
1377
1378    /**
1379     * The platform description.
1380     *
1381     * @memberOf platform
1382     * @type string|null
1383     */
1384    platform.description = ua;
1385
1386    /**
1387     * The name of the browser's layout engine.
1388     *
1389     * The list of common layout engines include:
1390     * "Blink", "EdgeHTML", "Gecko", "Trident" and "WebKit"
1391     *
1392     * @memberOf platform
1393     * @type string|null
1394     */
1395    platform.layout = layout && layout[0];
1396
1397    /**
1398     * The name of the product's manufacturer.
1399     *
1400     * The list of manufacturers include:
1401     * "Apple", "Archos", "Amazon", "Asus", "Barnes & Noble", "BlackBerry",
1402     * "Google", "HP", "HTC", "LG", "Microsoft", "Motorola", "Nintendo",
1403     * "Nokia", "Samsung" and "Sony"
1404     *
1405     * @memberOf platform
1406     * @type string|null
1407     */
1408    platform.manufacturer = manufacturer;
1409
1410    /**
1411     * The name of the browser/environment.
1412     *
1413     * The list of common browser names include:
1414     * "Chrome", "Electron", "Firefox", "Firefox for iOS", "IE",
1415     * "Microsoft Edge", "PhantomJS", "Safari", "SeaMonkey", "Silk",
1416     * "Opera Mini" and "Opera"
1417     *
1418     * Mobile versions of some browsers have "Mobile" appended to their name:
1419     * eg. "Chrome Mobile", "Firefox Mobile", "IE Mobile" and "Opera Mobile"
1420     *
1421     * @memberOf platform
1422     * @type string|null
1423     */
1424    platform.name = name;
1425
1426    /**
1427     * The alpha/beta release indicator.
1428     *
1429     * @memberOf platform
1430     * @type string|null
1431     */
1432    platform.prerelease = prerelease;
1433
1434    /**
1435     * The name of the product hosting the browser.
1436     *
1437     * The list of common products include:
1438     *
1439     * "BlackBerry", "Galaxy S4", "Lumia", "iPad", "iPod", "iPhone", "Kindle",
1440     * "Kindle Fire", "Nexus", "Nook", "PlayBook", "TouchPad" and "Transformer"
1441     *
1442     * @memberOf platform
1443     * @type string|null
1444     */
1445    platform.product = product;
1446
1447    /**
1448     * The browser's user agent string.
1449     *
1450     * @memberOf platform
1451     * @type string|null
1452     */
1453    platform.ua = ua;
1454
1455    /**
1456     * The browser/environment version.
1457     *
1458     * @memberOf platform
1459     * @type string|null
1460     */
1461    platform.version = name && version;
1462
1463    /**
1464     * The name of the operating system.
1465     *
1466     * @memberOf platform
1467     * @type Object
1468     */
1469    platform.os = os || {
1470
1471      /**
1472       * The CPU architecture the OS is built for.
1473       *
1474       * @memberOf platform.os
1475       * @type number|null
1476       */
1477      'architecture': null,
1478
1479      /**
1480       * The family of the OS.
1481       *
1482       * Common values include:
1483       * "Windows", "Windows Server 2008 R2 / 7", "Windows Server 2008 / Vista",
1484       * "Windows XP", "OS X", "Ubuntu", "Debian", "Fedora", "Red Hat", "SuSE",
1485       * "Android", "iOS" and "Windows Phone"
1486       *
1487       * @memberOf platform.os
1488       * @type string|null
1489       */
1490      'family': null,
1491
1492      /**
1493       * The version of the OS.
1494       *
1495       * @memberOf platform.os
1496       * @type string|null
1497       */
1498      'version': null,
1499
1500      /**
1501       * Returns the OS string.
1502       *
1503       * @memberOf platform.os
1504       * @returns {string} The OS string.
1505       */
1506      'toString': function() { return 'null'; }
1507    };
1508
1509    platform.parse = parse;
1510    platform.toString = toStringPlatform;
1511
1512    if (platform.version) {
1513      description.unshift(version);
1514    }
1515    if (platform.name) {
1516      description.unshift(name);
1517    }
1518    if (os && name && !(os == String(os).split(' ')[0] && (os == name.split(' ')[0] || product))) {
1519      description.push(product ? '(' + os + ')' : 'on ' + os);
1520    }
1521    if (description.length) {
1522      platform.description = description.join(' ');
1523    }
1524    return platform;
1525  }
1526
1527  /*--------------------------------------------------------------------------*/
1528
1529  // Export platform.
1530  var platform = parse();
1531
1532  // Some AMD build optimizers, like r.js, check for condition patterns like the following:
1533  if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
1534    // Expose platform on the global object to prevent errors when platform is
1535    // loaded by a script tag in the presence of an AMD loader.
1536    // See http://requirejs.org/docs/errors.html#mismatch for more details.
1537    root.platform = platform;
1538
1539    // Define as an anonymous module so platform can be aliased through path mapping.
1540    define(function() {
1541      return platform;
1542    });
1543  }
1544  // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
1545  else if (freeExports && freeModule) {
1546    // Export for CommonJS support.
1547    forOwn(platform, function(value, key) {
1548      freeExports[key] = value;
1549    });
1550  }
1551  else {
1552    // Export to the global object.
1553    root.platform = platform;
1554  }
1555}.call(this));
1556
1557//
1558// +----------------------------------------------------------------------+
1559// | Unobtrusive Javascript Validation for YUI v2.0 (2007-03-04)          |
1560// | http://blog.jc21.com                                                 |
1561// +----------------------------------------------------------------------+
1562// | Attaches Events to all forms on a page and checks their form         |
1563// | elements classes to provide some validation.                         |
1564// +----------------------------------------------------------------------+
1565// | Copyright: jc21.com 2008                                             |
1566// +----------------------------------------------------------------------+
1567// | Licence: Absolutely free. Don't mention it.                          |
1568// +----------------------------------------------------------------------+
1569// | Author: Jamie Curnow <[email protected]>                                   |
1570// +----------------------------------------------------------------------+
1571//
1572//
1573
1574
1575
1576//==================================================================================================================
1577//  Trim Whitespace
1578//------------------------------------------------------------------------------------------------------------------
1579String.prototype.trim=function(){
1580	return this.replace(/^\s*|\s*$/g,'');
1581}
1582String.prototype.ltrim=function(){
1583	return this.replace(/^\s*/g,'');
1584}
1585String.prototype.rtrim=function(){
1586	return this.replace(/\s*$/g,'');
1587}
1588
1589//==================================================================================================================
1590//  FIC_checkForm
1591//  Form Input Checking by JC
1592/*
1593		Apply these class names to form elements:
1594
1595		* required (not blank)
1596		* validate-number (a valid number)
1597		* validate-digits (digits only, spaces allowed.)
1598		* validate-alpha (letters only)
1599		* validate-alphanum (only letters and numbers)
1600		* validate-date (a valid date value)
1601		* validate-email (a valid email address)
1602		* validate-url (a valid URL)
1603		* validate-date-au (a date formatted as; dd/mm/yyyy)
1604		* validate-currency-dollar (a valid dollar value)
1605		* validate-one-required (At least one checkbox/radio element must be selected in a group)
1606		* validate-not-first (Selects only, must choose an option other than the first)
1607		* validate-not-empty (Selects only, must choose an option with a value that is not empty)
1608		* validate-regex (requires the element to have a 'regex=' attribute applied)
1609
1610		Also, you can specify this attribute for text, passwird and textarea elements:
1611		* minlength="x" (where x is the minimum number of characters)
1612*/
1613//------------------------------------------------------------------------------------------------------------------
1614function FIC_checkForm(e) {
1615	var errs = new Array();
1616
1617	//this function is called when a form is submitted.
1618	if (typeof(e) == "string") {
1619		//the id was supplied, get the object reference
1620		e = xGetElementById(e);
1621		if (!e) {
1622			return true;
1623		}
1624	}
1625
1626	var elm=e;
1627	if (!e.nodeName) {
1628		//was fired by yahoo
1629		elm = (e.srcElement) ? e.srcElement : e.target;
1630	}
1631	if (elm.nodeName.toLowerCase() != 'form') {
1632		elm = searchUp(elm,'form');
1633	}
1634
1635	var all_valid = true;
1636
1637	//access form elements
1638	//inputs
1639	var f_in = elm.getElementsByTagName('input');
1640	//selects
1641	var f_sl = elm.getElementsByTagName('select');
1642	//textareas
1643	var f_ta = elm.getElementsByTagName('textarea');
1644
1645	//check inputs
1646	for (i=0;i<f_in.length;i++) {
1647		if (f_in[i].type.toLowerCase() != 'submit' && f_in[i].type.toLowerCase() != 'button' && f_in[i].type.toLowerCase() != 'hidden') {
1648			if (isVisible(f_in[i])) {
1649				var cname = ' '+f_in[i].className.replace(/^\s*|\s*$/g,'')+' ';
1650				cname = cname.toLowerCase();
1651				alert(cname);
1652				var inv = f_in[i].value.trim();
1653				var t = f_in[i].type.toLowerCase();
1654				var cext = '';
1655				if (t == 'text' || t == 'password') {
1656					//text box
1657					var valid = FIC_checkField(cname,f_in[i]);
1658				} else if(t == 'radio' || t == 'checkbox'){
1659					// radio or checkbox
1660					var valid = FIC_checkRadCbx(cname,f_in[i],f_in);
1661					cext = '-cr';
1662				} else {
1663					var valid = true;
1664				}
1665
1666				if (valid) {
1667					removeClassName(f_in[i],'validation-failed'+cext);
1668					addClassName(f_in[i],'validation-passed'+cext);
1669				} else {
1670					removeClassName(f_in[i],'validation-passed'+cext);
1671					addClassName(f_in[i],'validation-failed'+cext);
1672					//try to get title
1673					if (f_in[i].getAttribute('title')){
1674						errs[errs.length] = f_in[i].getAttribute('title');
1675					}
1676					all_valid = false;
1677				}
1678			}
1679		}
1680	} //end for i
1681
1682	//check textareas
1683	for (i=0;i<f_ta.length;i++) {
1684		if (isVisible(f_ta[i])) {
1685			var cname = ' '+f_ta[i].className.replace(/^\s*|\s*$/g,'')+' ';
1686			cname = cname.toLowerCase();
1687			var valid = FIC_checkField(cname,f_ta[i]);
1688
1689			if (valid) {
1690				removeClassName(f_ta[i],'validation-failed');
1691				addClassName(f_ta[i],'validation-passed');
1692			} else {
1693				removeClassName(f_ta[i],'validation-passed');
1694				addClassName(f_ta[i],'validation-failed');
1695				//try to get title
1696				if (f_ta[i].getAttribute('title')){
1697					errs[errs.length] = f_ta[i].getAttribute('title');
1698				}
1699				all_valid = false;
1700			}
1701		}
1702	} //end for i
1703
1704	//check selects
1705	for (i=0;i<f_sl.length;i++) {
1706		if (isVisible(f_sl[i])) {
1707			var cname = ' '+f_sl[i].className.replace(/^\s*|\s*$/g,'')+' ';
1708			cname = cname.toLowerCase();
1709			var valid = FIC_checkSel(cname,f_sl[i]);
1710			if (valid) {
1711				removeClassName(f_sl[i],'validation-failed-sel');
1712				addClassName(f_sl[i],'validation-passed-sel');
1713			} else {
1714				removeClassName(f_sl[i],'validation-passed-sel');
1715				addClassName(f_sl[i],'validation-failed-sel');
1716				//try to get title
1717				if (f_sl[i].getAttribute('title')){
1718					errs[errs.length] = f_sl[i].getAttribute('title');
1719				}
1720				all_valid = false;
1721			}
1722		}
1723	} //end for i
1724
1725	if (!all_valid) {
1726		if (errs.length > 0){
1727			alert("We have found the following error(s):\n\n  * "+errs.join("\n  * ")+"\n\nPlease check the fields and try again");
1728		} else {
1729			alert('Some required values are not correct. Please check the items in red.');
1730		}
1731		
1732		e.preventDefault();
1733		e.stopPropagation();
1734		
1735	}
1736	return all_valid;
1737} // end FIC_checkForm
1738
1739//==================================================================================================================
1740//  FIC_checkField
1741//	c = className
1742//	e = the element
1743//------------------------------------------------------------------------------------------------------------------
1744function FIC_checkField(c,e) {
1745	var valid = true;
1746	var t = e.value.trim();
1747
1748	//search for required
1749	if (c.indexOf(' required ') != -1 && t.length == 0) {
1750		//required found, and not filled in
1751		valid = false;
1752	}
1753
1754	//check length
1755	if (c.indexOf(' required ') != -1){
1756		//check for minlength.
1757		var m = e.getAttribute('minlength');
1758		if (m && Math.abs(m) > 0){
1759			if (e.value.length < Math.abs(m)){
1760				valid = false;
1761			}
1762		}
1763	}
1764
1765	//search for validate-
1766	if (c.indexOf(' validate-number ') != -1 && isNaN(t) && t.match(/[^\d]/)) {
1767		//number bad
1768		valid = false;
1769	} else if (c.indexOf(' validate-digits ') != -1 && t.replace(/ /,'').match(/[^\d]/)) {
1770		//digit bad
1771		valid = false;
1772	} else if (c.indexOf(' validate-alpha ') != -1 && !t.match(/^[a-zA-Z]+$/)) {
1773		//alpha bad
1774		valid = false;
1775	} else if (c.indexOf(' validate-alphanum ') != -1 && t.match(/\W/)) {
1776		//alpha bad
1777		valid = false;
1778	} else if (c.indexOf(' validate-date ') != -1) {
1779		var d = new date(t);
1780		if (isNaN(d)) {
1781			//date bad
1782			valid = false;
1783		}
1784	} else if (c.indexOf(' validate-email ') != -1 && !t.match(/\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/)) {
1785		//email bad
1786		valid = false;
1787		if (c.indexOf(' required ') == -1 && t.length == 0) {
1788			valid = true;
1789		}
1790	} else if (c.indexOf(' validate-url ') != -1 && !t.match(/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i)) {
1791		//url bad
1792		valid = false;
1793	} else if (c.indexOf(' validate-date-au ') != -1 && !t.match(/^(\d{2})\/(\d{2})\/(\d{4})$/)) {
1794		valid = false;
1795//	} else if (c.indexOf(' validate-currency-dollar ') != -1 && !t.match(/^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/)) {
1796	} else if (c.indexOf(' validate-currency-dollar ') != -1 &&
1797			(!t.match(/(^(0|[1-9][0-9]*)$)|((^(0?|[1-9][0-9]*)\.(0*[1-9][0-9]*)$)|(^[1-9]+[0-9]*\.0+$)|(^0\.0+$))/) ||
1798			t.length && 0)) {
1799		valid = false;
1800	} else if (c.indexOf(' validate-regex ') != -1) {
1801        var r = RegExp(e.getAttribute('regex'));
1802        if (r && ! t.match(r)) {
1803            valid = false;
1804        }
1805    }
1806
1807	return valid;
1808}
1809
1810//==================================================================================================================
1811//  FIC_checkRadCbx
1812//	c = className
1813//	e = this element, radio or checkbox
1814//	f = input fields dom element
1815//------------------------------------------------------------------------------------------------------------------
1816function FIC_checkRadCbx(c,e,f){
1817	var valid = true;
1818
1819	//search for required
1820	if (c.indexOf(' validate-one-required ') != -1) {
1821		//required found
1822		//check if other checkboxes or radios have been selected.
1823		valid = false;
1824		for (var i=0;i<f.length;i++){
1825			if(f[i].name.toLowerCase() == e.name.toLowerCase() && f[i].checked){
1826				valid = true;
1827				break;
1828			}
1829		}
1830	}
1831
1832	return valid;
1833}
1834
1835//==================================================================================================================
1836//  FIC_checkSel
1837//	c = className
1838//	e = this select element
1839//------------------------------------------------------------------------------------------------------------------
1840function FIC_checkSel(c,e){
1841	var valid = true;
1842	//search for validate-
1843	if (c.indexOf(' validate-not-first ') != -1 && e.selectedIndex == 0) {
1844		//bad
1845		valid = false;
1846	} else if (c.indexOf(' validate-not-empty ') != -1 && e.options[e.selectedIndex].value.length == 0) {
1847		//bad
1848		valid = false;
1849	}
1850	return valid;
1851}
1852
1853//==================================================================================================================
1854//  addClassName
1855//------------------------------------------------------------------------------------------------------------------
1856function addClassName(e,t) {
1857	if (typeof e == "string") {
1858		e = xGetElementById(e);
1859	}
1860	//code to change and replace strings
1861	var ec = ' ' + e.className.replace(/^\s*|\s*$/g,'') + ' ';
1862	var nc = ec;
1863	t = t.replace(/^\s*|\s*$/g,'');
1864	//check if not already there
1865	if (ec.indexOf(' '+t+' ') == -1) {
1866		//not found, add it
1867		nc = ec + t;
1868	}
1869	//return the changed text!
1870	e.className = nc.replace(/^\s*|\s*$/g,''); //trimmed whitespace
1871	return true;
1872}
1873
1874//==================================================================================================================
1875//  removeClassName
1876//------------------------------------------------------------------------------------------------------------------
1877function removeClassName(e,t) {
1878	if (typeof e == "string") {
1879		e = xGetElementById(e);
1880	}
1881	//code to change and replace strings
1882	var ec = ' ' + e.className.replace(/^\s*|\s*$/g,'') + ' ';
1883	var nc = ec;
1884	t = t.replace(/^\s*|\s*$/g,'');
1885	//check if not already there
1886	if (ec.indexOf(' '+t+' ') != -1) {
1887		//found, so lets remove it
1888		nc = ec.replace(' ' + t.replace(/^\s*|\s*$/g,'') + ' ',' ');
1889	}
1890	//return the changed text!
1891	e.className = nc.replace(/^\s*|\s*$/g,''); //trimmed whitespace
1892	return true;
1893}
1894
1895//==================================================================================================================
1896//  attachToForms
1897//------------------------------------------------------------------------------------------------------------------
1898function attachToForms(e) {
1899	//search dom for all forms
1900	var frms = document.getElementsByTagName('form');
1901	for(var i=0;i<frms.length;i++) {
1902		//YAHOO.util.Event.addListener(frms[i], "submit", FIC_checkForm);
1903		if(frms[i].addEventListener){
1904			frms[i].addEventListener("submit", FIC_checkForm, false);  //Modern browsers
1905		}else if(frms[i].attachEvent){
1906			frms[i].attachEvent('onsubmit', FIC_checkForm);            //Old IE
1907		}
1908	}
1909}
1910
1911//==================================================================================================================
1912//  isVisible
1913//------------------------------------------------------------------------------------------------------------------
1914function isVisible(e) {
1915	//returns true is should be visible to user.
1916	if (typeof e == "string") {
1917		e = xGetElementById(e);
1918	}
1919	while (e.nodeName.toLowerCase() != 'body' && e.style.display.toLowerCase() != 'none' && e.style.visibility.toLowerCase() != 'hidden') {
1920		e = e.parentNode;
1921	}
1922	if (e.nodeName.toLowerCase() == 'body') {
1923		return true;
1924	} else{
1925		return false;
1926	}
1927}
1928
1929
1930//==================================================================================================================
1931//  searchUp
1932//------------------------------------------------------------------------------------------------------------------
1933function searchUp(elm,findElm,debug) {
1934	//this function searches the dom tree upwards for the findElm node starting from elm.
1935	//check if elm is reference
1936
1937	if(typeof(elm) == 'string') {
1938		elm = xGetElementById(elm);
1939	}
1940	//search up
1941	//get the parent findElm
1942	while (elm && elm.parentNode && elm.nodeName.toLowerCase() != findElm && elm.nodeName.toLowerCase() != 'body') {
1943		elm = elm.parentNode;
1944	}
1945	return elm;
1946}
1947
1948//==================================================================================================================
1949//  xGetElementById
1950//------------------------------------------------------------------------------------------------------------------
1951function xGetElementById(e) {
1952	if(typeof(e)!='string') return e;
1953	if(document.getElementById) e=document.getElementById(e);
1954	else if(document.all) e=document.all[e];
1955	else e=null;
1956	return e;
1957}
1958
1959//YAHOO.util.Event.addListener(window, "load", attachToForms);
1960
1961
1962//==================================================================================================================
1963//  TO HIDE THE LANGUAGE CONVERSION OPTION IN A PAGE
1964//------------------------------------------------------------------------------------------------------------------
1965
1966function fnHideLangConversion() {	
1967	$("[href*='/c/portal/update_language']").parent().hide().next(":contains(|)").hide();
1968	$('[name="changeLanguageLink"]').parent().hide().next(":contains(|)").hide();
1969}
1970
1971//================================================================================
1972//----------------------------------------------------------------------------------

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.