PageSourceSearch

https://www.stgeorge-sporting.org/stg/plugins/system/jsntplframework/assets/joomlashine/js/utils.js

js stgeorge-sporting.org collected 2026-10-02 23:53:50 UTC 33,418 bytes, 1,157 lines download raw bytes

1/**
2* @author    JoomlaShine.com http://www.joomlashine.com
3* @copyright Copyright (C) 2008 - 2011 JoomlaShine.com. All rights reserved.
4* @license   GNU/GPL v2 http://www.gnu.org/licenses/gpl-2.0.html
5*/
6var JSNUtils = {
7	/* ============================== BROWSER  ============================== */
8	/**
9	 * Encode double quote character to comply with Opera browser
10	 * Add more rules here if needed
11	 */
12	encodeCookie: function(value) {
13		return value.replace(/\"/g, '%22');
14	},
15
16	/**
17	 * Decode double quote character back to normal
18	 */
19	decodeCookie: function(value) {
20		return value.replace(/\%22/g, '"');
21	},
22
23	writeCookie: function (name,value,days){
24		value = JSNUtils.encodeCookie(value);
25
26		if (days) {
27			var date = new Date();
28			date.setTime(date.getTime()+(days*24*60*60*1000));
29			var expires = "; expires="+date.toGMTString();
30		} else expires = "";
31
32		document.cookie = name+"="+value+expires+"; path=/";
33	},
34
35	readCookie: function (name){
36		var nameEQ = name + "=";
37		var ca = document.cookie.split(';');
38		for(var i=0;i < ca.length;i++) {
39			var c = ca[i];
40			while (c.charAt(0)==' ') c = c.substring(1,c.length);
41			if (c.indexOf(nameEQ) == 0) return JSNUtils.decodeCookie(c.substring(nameEQ.length,c.length));
42		}
43		return null;
44	},
45
46	isIE7: function() {
47		return (navigator.appVersion.indexOf("MSIE 7.")!=-1);
48	},
49
50	isDesktopViewOnMobile: function (params) {
51		if (params && params.responsiveLayout) {
52			if (!params.responsiveLayout.contains('mobile') && (JSNUtils.checkSmartphone()|| JSNUtils.checkTablet())) {
53				document.body.addClass('jsn-desktop-on-mobile');
54			}
55		}
56
57		return document.body.hasClass('jsn-mobile');
58	},
59
60	initMenuForDesktopView: function () {
61		var sitetools = document.id('jsn-sitetools-menu');
62
63		if (sitetools != null)
64			sitetools.addClass('sitetool-desktop-on-mobile');
65
66		document.getElements('ul.menu-mainmenu').addClass('jsn-desktop-on-mobile');
67	},
68
69	getBrowserInfo: function(){
70		var name	= '';
71		var version = '';
72		var ua 		= navigator.userAgent.toLowerCase();
73		var match	= ua.match(/(opera|ie|firefox|chrome|version)[\s\/:]([\w\d\.]+)?.*?(safari|version[\s\/:]([\w\d\.]+)|$)/) || [null, 'unknown', 0];
74		if (match[1] == 'version')
75		{
76			name = match[3];
77		}
78		else
79		{
80			name = match[1];
81		}
82		version = parseFloat((match[1] == 'opera' && match[4]) ? match[4] : match[2]);
83
84		return {'name': name, 'version': version};
85	},
86
87	/* ============================== DEVICE  ============================== */
88
89	checkMobile: function(){
90		var uagent = navigator.userAgent.toLowerCase(), isMobile = false, mobiles = [
91			"midp","240x320","blackberry","netfront","nokia","panasonic",
92			"portalmmm","sharp","sie-","sonyericsson","symbian",
93			"windows ce","benq","mda","mot-","opera mini",
94			"philips","pocket pc","sagem","samsung","sda",
95			"sgh-","vodafone","xda","palm","iphone",
96			"ipod","android", "ipad"
97		];
98
99		for (var i = 0; i < mobiles.length; i++) {
100			if (uagent.indexOf(mobiles[i]) != -1) {
101				isMobile = true;
102			}
103		}
104
105		return isMobile;
106	},
107
108	getScreenWidth: function(){
109		var screenWidth;
110
111		if( typeof( window.innerWidth ) == 'number' )
112		{
113			// IE 9+ and other browsers
114			screenWidth = window.innerWidth;
115		}
116		else if (document.documentElement && document.documentElement.clientWidth)
117		{
118			//IE 6 - 8
119			screenWidth = document.documentElement.clientWidth;
120		}
121
122		return screenWidth;
123	},
124
125	checkSmartphone: function(){
126		var screenWidth = JSNUtils.getScreenWidth(), isSmartphone = false;
127
128		if (screenWidth >= 320 && screenWidth < 480)
129		{
130			isSmartphone = true;
131		}
132
133		return isSmartphone;
134	},
135
136	checkTablet: function(){
137		var screenWidth = JSNUtils.getScreenWidth(), isTablet = false;
138
139		if (screenWidth >= 481 && screenWidth < 1024)
140		{
141			isTablet = true;
142		}
143
144		return isTablet;
145	},
146
147	getScreenType: function(){
148		var screenType;
149
150		if (JSNUtils.checkSmartphone()) {
151			screenType = 'smartphone';
152		} else if (JSNUtils.checkTablet()) {
153			screenType = 'tablet';
154		} else {
155			screenType = 'desktop';
156		}
157
158		return screenType;
159	},
160
161
162	/* ============================== DOM - GENERAL ============================== */
163
164	addEvent: function(target, event, func){
165		if (target.addEventListener){
166			target.addEventListener(event, func, false);
167			return true;
168		} else if (target.attachEvent){
169			var result = target.attachEvent("on"+event, func);
170			return result;
171		} else {
172			return false;
173		}
174	},
175
176	getElementsByClass: function(targetParent, targetTag, targetClass, targetLevel){
177		var elements, tags, tag, tagClass;
178
179		if(targetLevel == undefined){
180			tags = targetParent.getElementsByTagName(targetTag);
181		}else{
182			tags = JSNUtils.getChildrenAtLevel(targetParent, targetTag, targetLevel);
183		}
184
185		elements = [];
186
187		for(var i=0;i<tags.length;i++){
188			tagClass = tags[i].className;
189			if(tagClass != "" && JSNUtils.checkSubstring(tagClass, targetClass, " ", false)){
190				elements[elements.length] = tags[i];
191			}
192		}
193
194		return elements;
195	},
196
197	getFirstChild: function(targetEl, targetTagName){
198		var nodes, node;
199		nodes = targetEl.childNodes;
200		for(var i=0;i<nodes.length;i++){
201			node = nodes[i];
202			if (node.tagName == targetTagName)
203				return node;
204		}
205		return null;
206	},
207
208	getFirstChildAtLevel: function(targetEl, targetTagName, targetLevel){
209		var child, nodes, node;
210		nodes = targetEl.childNodes;
211		for(var i=0;i<nodes.length;i++){
212			node = nodes[i];
213			if (targetLevel == 1) {
214				if(node.tagName == targetTagName) return node;
215			} else {
216				child = JSNUtils.getFirstChildAtLevel(node, targetTagName, targetLevel-1);
217				if(child != null) return child;
218			}
219		}
220		return null;
221	},
222
223	getChildren: function(targetEl, targetTagName){
224		var nodes, node;
225		var children = [];
226		nodes = targetEl.childNodes;
227		for(var i=0;i<nodes.length;i++){
228			node = nodes[i];
229			if(node.tagName == targetTagName)
230				children.push(node);
231		}
232		return children;
233	},
234
235	getChildrenAtLevel: function(targetEl, targetTagName, targetLevel){
236		var children = [];
237		var nodes, node;
238		nodes = targetEl.childNodes;
239		for(var i=0;i<nodes.length;i++){
240			node = nodes[i];
241			if (targetLevel == 1) {
242				if(node.tagName == targetTagName) children.push(node);
243			} else {
244				children = children.concat(JSNUtils.getChildrenAtLevel(node, targetTagName, targetLevel-1));
245			}
246		}
247		return children;
248	},
249
250	addClass: function(targetTag, targetClass){
251		if(targetTag.className == ""){
252			targetTag.className = targetClass;
253		} else {
254			if(!JSNUtils.checkSubstring(targetTag.className, targetClass, " ")){
255				targetTag.className += " " + targetClass;
256			}
257		}
258	},
259
260	getViewportSize: function(){
261		var myWidth = 0, myHeight = 0;
262
263		if( typeof( window.innerWidth ) == 'number' ) {
264			//Non-IE
265			myWidth = window.innerWidth;
266			myHeight = window.innerHeight;
267		} else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
268			//IE 6+ in 'standards compliant mode'
269			myWidth = document.documentElement.clientWidth;
270			myHeight = document.documentElement.clientHeight;
271		} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
272			//IE 4 compatible
273			myWidth = document.body.clientWidth;
274			myHeight = document.body.clientHeight;
275		}
276
277		return {width:myWidth, height:myHeight };
278	},
279
280	addURLPrefix: function(targetId)
281	{
282		var navUrl 			= window.location.href;
283		var targetEl 		= document.getElementById(targetId);
284		if(targetEl != undefined && targetEl.tagName.toUpperCase() == 'A')
285		{
286			orgHref = targetEl.href;
287			targetEl.href = navUrl + ((navUrl.indexOf(orgHref) != -1)?'':orgHref);
288		}
289	},
290
291	/* ============================== DOM - GUI ============================== */
292	/* ============================== DOM - GUI - MENU ============================== */
293
294	/**
295	 * Reposition submenu if it goes off screen area.
296	 */
297	setSubmenuPosition: function(enableRTL)
298	{
299		// Initialize parameters
300		var maxSize, parents, enableRTL = enableRTL || false;
301
302		// Get all parents
303		parents = document.getElements('ul.menu-mainmenu > li.parent');
304
305		if (!parents.length) return;
306
307		// Add level to all submenus
308		parents.each(function(parent) {
309			var submenu = parent.getChildren('ul'), level = 0;
310
311			while (submenu.length) {
312				var tmp = [];
313
314				// Increase submenu level
315				level++;
316
317				// Add class to indicate submenu level
318				submenu.each(function(ul) {
319					ul.addClass('jsn-submenu-level-' + level);
320
321					// Get nested submenus
322					tmp = tmp.extend(ul.getElements('> li.parent > ul'));
323				});
324
325				// Set nested submenus
326				submenu = tmp;
327			}
328
329			// Store max level of submenu
330			parent.jsnMaxSubmenuLevel = level;
331		});
332
333		// Declare some utilities
334		var placeSubmenu = function(parent, flipBack) {
335			var	width = 0, submenu = parent.getElement('ul.jsn-submenu-level-' + parent.jsnMaxSubmenuLevel),
336				farLeft = (enableRTL || flipBack) ? submenu.getPosition().x : parent.getPosition().x;
337
338			// Calculate total width when all nested submenus are expanded
339			if ( ! enableRTL) {
340				while (!submenu.hasClass('menu-mainmenu')) {
341					width += submenu.getSize().x;
342	
343					// Travel back the DOM tree
344					submenu = submenu.getParent().getParent();
345				}
346			}
347
348			// Check if there is any submenu goes off screen when all nested submenus are expanded
349			if (((enableRTL || flipBack) && farLeft < 0) || ((!enableRTL || flipBack) && farLeft + width > maxSize.x)) {
350				if (!flipBack) {
351					parent.addClass('jsn-submenu-flipback');
352
353					// Check if there is any submenu goes off screen in the opposite side after flipping back
354					placeSubmenu(parent, true);
355				} else {
356					parent.removeClass('jsn-submenu-flipback');
357				}
358			}
359		},
360
361		resizeHandler = function() {
362			// Disable left-right scrolling
363			document.body.setStyle('overflow-x', 'hidden');
364
365			// Temporary disable transition effect
366			document.body.removeClass('jsn-css3');
367
368			// Update max screen area
369			maxSize = window.getSize();
370
371			// Restore original position for all submenu
372			parents.removeClass('jsn-submenu-flipback');
373
374			// Place all submenus
375			parents.each(function(parent) {
376				var submenus = parent.getElements('ul');
377
378				// Make sure all submenus is visible
379				submenus.setStyle('display', 'block');
380
381				// Place nested submenus
382				placeSubmenu(parent);
383
384				// Restore default visibility state for submenu
385				submenus.setStyle('display', '');
386			});
387
388			// Re-enable transition effect if not viewing desktop site on mobile
389			document.body.hasClass('jsn-desktop-on-mobile') || document.body.addClass('jsn-css3');
390
391			// Restore original left-right scrolling
392			document.body.setStyle('overflow-x', '');
393		};
394
395		// Handle window resize event
396		window.addEvent('resize', function() {
397			placeSubmenu.timer && clearTimeout(placeSubmenu.timer);
398			placeSubmenu.timer = setTimeout(resizeHandler, 500);
399		});
400
401		// Place all submenus
402		resizeHandler();
403	},
404
405	setMobileMenu: function(menuClass)
406	{
407		var toggle = function() {
408			this.toggleClass("active");
409			this.getNext("ul").toggleClass("jsn-menu-mobile");
410
411			document.getElements("." + menuClass + " .jsn-menu-toggle").each(function (item) {
412				var a = item.getPrevious(),
413					size = a.getSize();
414
415				item.setStyle('height', size.y);
416			});
417		};
418
419		// Setup toggle for main trigger
420		document.getElements("ul." + menuClass).getPrevious(".jsn-menu-toggle").addEvent('click', toggle);
421
422		// Setup toggle for children triggers
423		document.getElements("ul." + menuClass + " .jsn-menu-toggle").addEvent('click', toggle);
424
425		window.addEvent('resize', function () {
426			if (window.getSize().x > 960) {
427				document.getElements('ul.jsn-menu-mobile').removeClass('jsn-menu-mobile');
428			}
429		});
430	},
431
432	setMobileSticky: function()
433	{
434		var page 			= document.id('jsn-page'),
435			menu   			= document.id('jsn-menu'),
436			menuToggler 	= menu.getElement('.jsn-menu-toggle'),
437			mainMenu 		= menu.getElement('ul.menu-mainmenu'),
438			menuSize 		= menu.getCoordinates(),
439			menuPlacehoder 	= new Element('div', { 'id': 'jsn-menu-placeholder' }),
440			menuParent		= menu.getParent(),
441			menuParentOffset = menuParent.getCoordinates(),
442			menuLeft 		= menuSize.left,
443			menuPaddingHorz = parseInt(menu.getStyle('padding-left')) + parseInt(menu.getStyle('padding-right')),
444			menuBorderHorz  = parseInt(menu.getStyle('border-left')) + parseInt(menu.getStyle('border-right')),
445			isSticked		= false,
446			touchStartOffset = {},
447			isFixedSupport  = JSNUtils.isFixedSupport();
448
449		menuPlacehoder.setStyles({
450			height: menuSize.height,
451			margin: menu.getStyle('margin')
452		});
453
454		var getMaxMenuHeight = function () { return window.innerHeight - menuSize.height; };
455		var getTouchDirection = function (touchEvent) { return touchEvent.touches[0].pageY > touchStartOffset.y ? 'up' : 'down'; };
456
457		var resetMenuPosition = function () {
458			if (window.getScroll().y < menuPlacehoder.getPosition().y) {
459				menu
460					.removeClass('jsn-menu-sticky')
461					.removeAttribute('style');
462
463				menuPlacehoder.dispose();
464				mainMenu.setStyles({
465					'max-height': 'auto',
466					'overflow-y': 'hidden'
467				});
468
469				isSticked = false;
470			}
471		};
472
473		var getMenuWidth = function (forceMenuWidth) {
474			var menuWidth = forceMenuWidth || menuSize.width;
475
476			if (!isNaN(menuPaddingHorz))
477				menuWidth = menuWidth - menuPaddingHorz;
478
479			if (!isNaN(menuBorderHorz))
480				menuWidth = menuWidth - menuBorderHorz;
481
482			return menuWidth;
483		};
484
485		var fx = new Fx.Morph(menu, { transition: Fx.Transitions.Expo.easeOut });
486			fx.addEvent('complete', resetMenuPosition);
487
488		var makeMenuStick = function () {
489			var scrollTop = window.getScroll().y,
490				menuOffsetTop = menu.getPosition().y;
491
492			if (mainMenu.getStyle('display') == 'block')
493				return;
494
495			if (scrollTop > menuOffsetTop && menuParent.getElement('#jsn-menu-placeholder') == null && isSticked == false) {
496				if (fx.isRunning())
497					fx.cancel();
498
499				menuSize = menu.getCoordinates();
500				menuLeft = menuSize.left;
501
502				menu.addClass('jsn-menu-sticky')
503					.setStyles({
504						'left'		: menuLeft,
505						'width'		: getMenuWidth(),
506						'position'	: isFixedSupport ? 'fixed' : 'absolute',
507						'top'		: isFixedSupport ? 0 : scrollTop,
508						'z-index'   : 9999999
509					});
510
511				menuPlacehoder.inject(menu, 'before');
512				isSticked = true;
513			}
514		};
515
516		var updatePosition = function () {
517			makeMenuStick();
518
519			var scrollTop = window.getScroll().y,
520				placeHoderOffset = menuPlacehoder.getPosition().y;
521
522			if (fx.isRunning()) fx.pause();
523
524			// Reset menu position
525			if (isSticked == true && placeHoderOffset > scrollTop && menu.getStyle('position') == 'fixed') {
526				menu.setStyles({
527					position 	: 'absolute',
528					top 		: scrollTop,
529					left 		: menuPlacehoder.getCoordinates().left,
530					width		: getMenuWidth()
531				});
532
533				fx.start({ top: placeHoderOffset });
534			}
535
536			// Update menu position
537			else if (isSticked == true && menu.getStyle('position') == 'absolute') {
538				var menuTop = menu.getPosition().y;
539
540				if (mainMenu.getStyle('display') == 'block')
541					return;
542
543				fx.start({
544					top: (placeHoderOffset > scrollTop) ? placeHoderOffset : scrollTop,
545					left: menuPlacehoder.getCoordinates().left
546				});
547			}
548
549			else {
550				menu.setStyle('left', menuPlacehoder.getCoordinates().left);
551			}
552		};
553
554		var updatePositionTimeout = null,
555			updateMenuSizeTimeout = null,
556			isMovedToTop          = false,
557			backupWindowScroll    = null,
558			pageHeight = page.getSize().y;
559
560		menu.getElements('.jsn-menu-toggle').addEvent('click', function () {
561			var menuHeight = menu.getSize().y + mainMenu.getSize().y;
562
563			if (menuToggler.hasClass('active')) {
564				if (menuHeight > window.getSize().y && menu.hasClass('jsn-menu-sticky')) {
565					backupWindowScroll = window.getScroll();
566
567					page.setStyles({ 'height': menuHeight, 'overflow': 'hidden' });
568					menu.setStyles({ 'position': 'absolute', 'top': 0 });
569
570					if (isMovedToTop == false) {
571						window.scrollTo(0, 0);
572						isMovedToTop = true;
573					}
574				}
575				else {
576					page.setStyles({ 'height': '', 'overflow': 'visible' });
577					isMovedToTop = false;
578				}
579			}
580			else {
581				page.setStyles({ 'height': '', 'overflow': 'visible' });
582				isMovedToTop = false;
583
584				updatePosition();
585			}
586		});
587
588		window.addEvent('touchmove', makeMenuStick);
589		window.addEvent('scroll', updatePosition);
590		window.addEvent('resize', function () {
591			clearTimeout(updateMenuSizeTimeout);
592			updateMenuSizeTimeout = setTimeout(function () {
593				if (isSticked == true) {
594					menuSize = menuPlacehoder.getCoordinates();
595					menu.setStyle('width', getMenuWidth());
596				}
597				else {
598					menuSize = menu.getCoordinates();
599				}
600			}, 100);
601		});
602
603		window.addEvent('orientationchange', function () {
604			updatePosition();
605		});
606
607		window.addEvent('load', function () {
608			clearTimeout(updatePositionTimeout);
609			updatePositionTimeout = setTimeout(updatePosition, 100);
610		});
611	},
612
613	setDropdownModuleEvents: function ()
614	{
615		document.getElements('div#jsn-menu div.display-dropdown.jsn-modulecontainer h3.jsn-moduletitle')
616			.addEvent('click', function (e) {
617				var
618				elm = e.target;
619				while (!elm.hasClass('jsn-modulecontainer'))
620					elm = elm.getParent();
621
622				elm.toggleClass('jsn-dropdown-active');
623			});
624	},
625
626	setMobileSitetool: function()
627	{
628		var siteToolPanel = document.id("jsn-sitetoolspanel");
629
630		if (siteToolPanel)
631		{
632			siteToolPanel.getElements("li.jsn-sitetool-control").addEvent("click", function() {
633				this.toggleClass("active");
634			});
635		}
636	},
637
638	getSelectMenuitemIndex: function(elementID)
639	{
640		var childs = document.id(elementID).childNodes;
641		var count  = childs.length;
642		var index  = 0;
643
644		for (var i = 0; i < count; i++)
645		{
646			if(childs[i].className != undefined && childs[i].className.indexOf('parent') != -1)
647			{
648				if(childs[i].className.indexOf('active') != -1)
649				{
650					return index;
651				}
652				index++;
653			}
654		}
655		return -1;
656	},
657
658	createImageMenu: function(menuId, imageClass){
659		if (!document.getElementById) return;
660
661		var list = document.getElementById(menuId);
662		var listItems;
663
664		var listItem;
665
666		if(list != undefined) {
667			listItems = list.getElementsByTagName("LI");
668			for(i=0, j=0;i<listItems.length;i++){
669				listItem = listItems[i];
670				if (listItem.parentNode == list) {
671					listItem.className += " " + imageClass + (j+1);
672					j++;
673				}
674			}
675		}
676	},
677
678	/* Set position of side menu sub panels */
679	setSidemenuLayout: function(menuClass, rtlLayout)
680	{
681		var sidemenus, sidemenu, smChildren, smChild, smSubmenu;
682		sidemenus = JSNUtils.getElementsByClass(document, "UL", menuClass);
683		if (sidemenus != undefined) {
684			for(var i=0;i<sidemenus.length;i++){
685				sidemenu = sidemenus[i];
686				smChildren = JSNUtils.getChildren(sidemenu, "LI");
687				if (smChildren != undefined) {
688					for(var j=0;j<smChildren.length;j++){
689						smChild = smChildren[j];
690						smSubmenu = JSNUtils.getFirstChild(smChild, "UL");
691						if (smSubmenu != null) {
692							if(rtlLayout == true) { smSubmenu.style.marginRight = smChild.offsetWidth+"px"; }
693							else { smSubmenu.style.marginLeft = smChild.offsetWidth+"px"; }
694						}
695					}
696				}
697			}
698		}
699	},
700
701	/* Set position of sitetools sub panel */
702	setSitetoolsLayout: function(sitetoolsId, rtlLayout)
703	{
704		var sitetoolsContainer, parentItem, sitetoolsPanel, neighbour;
705		sitetoolsContainer = document.getElementById(sitetoolsId);
706		if (sitetoolsContainer != undefined) {
707			parentItem = JSNUtils.getFirstChild(sitetoolsContainer, "LI");
708			sitetoolsPanel = JSNUtils.getFirstChild(parentItem, "UL");
709			if (rtlLayout == true) {
710				sitetoolsPanel.style.marginRight = -1*(sitetoolsPanel.offsetWidth - parentItem.offsetWidth) + "px";
711			} else {
712				sitetoolsPanel.style.marginLeft = -1*(sitetoolsPanel.offsetWidth - parentItem.offsetWidth) + "px";
713			}
714		}
715	},
716
717	/* Change template setting stored in cookie */
718	setTemplateAttribute: function(templatePrefix, attribute, value)
719	{
720		var templateParams = JSON.parse(JSNUtils.readCookie(templatePrefix + 'params')) || {};
721
722		templateParams[attribute] = value;
723
724		JSNUtils.writeCookie(templatePrefix + 'params', JSON.stringify(templateParams));
725
726		window.location.reload(true);
727	},
728
729	createExtList: function(listClass, extTag, className, includeNumber){
730		if (!document.getElementById) return;
731
732		var lists = JSNUtils.getElementsByClass(document, "UL", listClass);
733		var list;
734		var listItems;
735		var listItem;
736
737		if(lists != undefined) {
738			for(j=0;j<lists.length;j++){
739				list = lists[j];
740				listItems = JSNUtils.getChildren(list, "LI");
741				for(i=0,k=0;i<listItems.length;i++){
742					listItem = listItems[i];
743					if(className !=''){
744						listItem.innerHTML = '<'+ extTag + ' class='+className+'>' + (includeNumber?(k+1):'') + '</'+  extTag +'>' + listItem.innerHTML;
745					}else{
746						listItem.innerHTML = '<'+ extTag + '>' + (includeNumber?(k+1):'') + '</'+  extTag +'>' + listItem.innerHTML;
747					}
748					k++;
749				}
750			}
751		}
752	},
753
754	createGridLayout: function(containerTag, containerClass, columnClass, lastcolumnClass) {
755		var gridLayouts, gridLayout, gridColumns, gridColumn, columnsNumber;
756		gridLayouts = JSNUtils.getElementsByClass(document, containerTag, containerClass);
757		for(var i=0;i<gridLayouts.length;i++){
758			gridLayout = gridLayouts[i];
759			gridColumns = JSNUtils.getChildren(gridLayout, containerTag);
760			columnsNumber = gridColumns.length;
761			JSNUtils.addClass(gridLayout, containerClass + columnsNumber);
762			JSNUtils.addClass(gridLayout, 'clearafter');
763			for(var j=0;j<columnsNumber;j++){
764				gridColumn = gridColumns[j];
765				JSNUtils.addClass(gridColumn, columnClass);
766				if(j == gridColumns.length-1) {
767					JSNUtils.addClass(gridColumn, lastcolumnClass);
768				}
769				gridColumn.innerHTML = '<div class="' + columnClass + '_inner">' + gridColumn.innerHTML + '</div>';
770			}
771		}
772	},
773
774	sfHover: function(menuId, menuDelay) {
775		if(menuId == undefined) return;
776
777		var delay = (menuDelay == undefined)?0:menuDelay;
778		var pEl = document.getElementById(menuId);
779		if (pEl != undefined) {
780			var sfEls = pEl.getElementsByTagName("li");
781			for (var i=0; i<sfEls.length; ++i) {
782				sfEls[i].onmouseover=function() {
783					clearTimeout(this.timer);
784					if(this.className.indexOf("sfhover") == -1) {
785						this.className += " sfhover";
786					}
787				}
788				sfEls[i].onmouseout=function() {
789					this.timer = setTimeout(JSNUtils.sfHoverOut.bind(this), delay);
790				}
791			}
792		}
793	},
794
795	sfHoverOut: function() {
796		clearTimeout(this.timer);
797		this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
798	},
799
800	setFontSize: function (targetId, fontSize){
801		var targetObj = (document.getElementById) ? document.getElementById(targetId) : document.all(targetId);
802		targetObj.style.fontSize = fontSize + '%';
803	},
804
805	setVerticalPosition: function(pName, pAlignment) {
806		var targetElement = document.getElementById(pName);
807
808		if (targetElement != undefined) {
809			var topDelta, vpHeight, pHeight;
810			vpHeight = (JSNUtils.getViewportSize()).height;
811			pHeight = targetElement.offsetHeight;
812			switch(pAlignment){
813				case "top":
814					topDelta = 0;
815				break;
816
817				case "middle":
818					topDelta = Math.floor((100 - Math.round((pHeight/vpHeight)*100))/2);
819				break;
820
821				case "bottom":
822					topDelta = 100 - Math.round((pHeight/vpHeight)*100);
823				break;
824			}
825
826			topDelta = (topDelta < 0)?0:topDelta;
827
828			targetElement.style.top = topDelta + "%";
829
830			targetElement.style.visibility = "visible";
831		}
832	},
833
834	setupLayout: function()
835	{
836		var	container = document.id('jsn-content_inner7'), maxWidth = document.id('jsn-content_inner').getSize().x, flip, flipElm, width,
837			colLeft, colLeftBg, colRight, colRightBg, colInnerLeft, colInnerLeftBg, colInnerRight, colInnerRightBg;
838
839		// Get left column
840		colLeft = container.getChildren().length > 1 ? container.getElement('> .order1') : null;
841		colLeft = (colLeft && colLeft.id != 'jsn-maincontent') ? colLeft : container.getElement('> .order2');
842		colLeftBg = colLeft ? document.id('jsn-content_inner') : null;
843
844		// Set correct position for left column's background element
845		if (colLeft && colLeftBg) {
846			flip = colLeft.hasClass('order1') ? false : true;
847			flipElm = document.id('jsn-content_inner1');
848			width = ((flip ? colLeft.getPosition(container).x : colLeft.getSize().x) / maxWidth) * 100;
849
850			colLeftBg.setStyle(flip ? 'left' : 'right', (flip ? width : 100 - width) + '%');
851			flipElm.setStyle(flip ? 'right' : 'left', (flip ? width : 100 - width) + '%');
852		}
853
854		// Get right column
855		colRight = container.getChildren().length > 1 ? container.getElement('> .order' + container.getChildren().length) : null;
856		colRight = (colRight && colRight.id != 'jsn-maincontent') ? colRight : container.getElement('> .order' + (container.getChildren().length - 1));
857		colRightBg = colRight ? document.id('jsn-content_inner2') : null;
858
859		// Set correct position for right column's background element
860		if (colRight && colRightBg) {
861			flip = colRight.hasClass('order' + container.getChildren().length) ? false : true;
862			flipElm = document.id('jsn-content_inner3');
863			width = ((flip ? maxWidth - colRight.getPosition(container).x - colRight.getSize().x : colRight.getSize().x) / maxWidth) * 100;
864
865			colRightBg.setStyle(flip ? 'right' : 'left', (flip ? width : 100 - width) + '%');
866			flipElm.setStyle(flip ? 'left' : 'right', (flip ? width : 100 - width) + '%');
867		}
868
869		// Get inner-left column
870		container = document.id('jsn-maincontent');
871		colInnerLeft = container.getChildren().length > 1 ? container.getElement('> .order1') : null;
872		colInnerLeft = (colInnerLeft && colInnerLeft.id != 'jsn-centercol') ? colInnerLeft : null;
873		colInnerLeftBg = colInnerLeft ? document.id('jsn-content_inner4') : null;
874
875		// Set correct position for inner-left column's background element
876		if (colInnerLeft && colInnerLeftBg) {
877			flipElm = document.id('jsn-content_inner5');
878			width = ((colInnerLeft.getPosition(container.getParent()).x + colInnerLeft.getSize().x) / maxWidth) * 100;
879
880			colInnerLeftBg.setStyle('right', (100 - width) + '%');
881			flipElm.setStyle('left', (100 - width) + '%');
882		}
883
884		// Get inner-right column
885		colInnerRight = container.getChildren().length > 1 ? container.getElement('> .order' + container.getChildren().length) : null;
886		colInnerRight = (colInnerRight && colInnerRight.id != 'jsn-centercol') ? colInnerRight : null;
887		colInnerRightBg = colInnerRight ? document.id('jsn-content_inner6') : null;
888
889		// Set correct position for inner-right column's background element
890		if (colInnerRight && colInnerRightBg) {
891			flipElm = document.id('jsn-content_inner7');
892			width = (colInnerRight.getPosition(container.getParent()).x / maxWidth) * 100;
893
894			colInnerRightBg.setStyle('left', width + '%');
895			flipElm.setStyle('right', width + '%');
896		}
897	},
898
899	setEqualHeight: function()
900	{
901		var containerClass 	= "jsn-horizontallayout";
902		var columnClass 	= "jsn-modulecontainer_inner";
903		var horizontallayoutObjs = document.getElements('.' + containerClass);
904		var maxHeight = 0;
905		Array.each(horizontallayoutObjs, function(item) {
906			var columns = item.getElements('.'+columnClass);
907			maxHeight = 0;
908			Array.each(columns, function(col) {
909				var coordinates = col.getCoordinates();
910				if (coordinates.height > maxHeight) maxHeight = coordinates.height;
911			});
912			Array.each(columns, function(col) {
913				col.setStyle('height',maxHeight);
914			});
915		});
916	},
917
918
919	/* ============================== MOOTOOLS ANIMATION  ============================== */
920
921	setToTopLinkCenter: function(rtl, jquery)
922	{
923		/* Min distance to be away from top for the link to be displayed */
924		var min = 200;
925
926		/* Determine RTL layout or not to set margin correctly */
927		var marginFrom = "margin-left";
928		if (rtl === true) {
929			marginFrom = "margin-right";
930		}
931
932		if (jquery) {
933			var element = $j('#jsn-gotoplink');
934			if (!element.length) return;
935			element.hide();
936			($j(window).scrollTop() >= min) ? element.fadeIn() : element.fadeOut();
937		} else if (typeof(MooTools) != 'undefined') {
938			var element = document.id('jsn-gotoplink');
939			if (!element) return;
940			var elementHeight = element.getSize().y;
941
942			element
943				.setStyle('margin-left', -(element.getSize().x/2))
944				.set('opacity','0')
945				.fade((window.getScroll().y >= min) ? 'in' : 'out')
946				.fade((window.getScroll().y >= min) ? 1 : 0);
947
948			if (!JSNUtils.isFixedSupport()) {
949			 	element.setStyle('position', 'absolute');
950			 	window.addEvent('scroll', function () {
951			 		var height = window.innerHeight;
952			 		element.setStyle('bottom', 'auto');
953			 		element.setStyle('top', window.getScroll().y + (height - elementHeight));
954			 	});
955			}
956		}
957	},
958
959	isFixedSupport: function () {
960		var userAgent = window.navigator.userAgent + '',
961			isAppleDevice = /ipod|ipad|iphone/.test(userAgent.toLowerCase()),
962			isWindowPhone = /Windows Phone/.test(userAgent),
963			isAndroid     = /Android/.test(userAgent),
964			isSupported   = true;
965
966		if (isAppleDevice || isWindowPhone || isAndroid) {
967			var pattern = /AppleWebKit\/([0-9]+\.[0-9]+)\s+/;
968
969			if (isWindowPhone)
970				pattern = /IEMobile\/([0-9]+\.[0-9]+);/;
971
972			if (pattern.test(userAgent)) {
973				var result  = pattern.exec(userAgent);
974				var version = result[1];
975
976				isSupported = ((isAppleDevice || isAndroid) && JSNUtils.versionCompare(version, '534.1', '>='));
977			}
978		}
979
980		return isSupported;
981	},
982
983	versionCompare: function (v1, v2, operator) {
984	    this.php_js = this.php_js || {};
985	    this.php_js.ENV = this.php_js.ENV || {};
986
987	    var i = 0,
988	        x = 0,
989	        compare = 0,
990	        vm = {
991	            'dev': -6,
992	            'alpha': -5,
993	            'a': -5,
994	            'beta': -4,
995	            'b': -4,
996	            'RC': -3,
997	            'rc': -3,
998	            '#': -2,
999	            'p': -1,
1000	            'pl': -1
1001	        },
1002
1003	        prepVersion = function (v) {
1004	            v = ('' + v).replace(/[_\-+]/g, '.');
1005	            v = v.replace(/([^.\d]+)/g, '.$1.').replace(/\.{2,}/g, '.');
1006	            return (!v.length ? [-8] : v.split('.'));
1007	        },
1008
1009	        numVersion = function (v) {
1010	            return !v ? 0 : (isNaN(v) ? vm[v] || -7 : parseInt(v, 10));
1011	        };
1012	    v1 = prepVersion(v1);
1013	    v2 = prepVersion(v2);
1014	    x = Math.max(v1.length, v2.length);
1015	    for (i = 0; i < x; i++) {
1016	        if (v1[i] == v2[i]) {
1017	            continue;
1018	        }
1019	        v1[i] = numVersion(v1[i]);
1020	        v2[i] = numVersion(v2[i]);
1021	        if (v1[i] < v2[i]) {
1022	            compare = -1;
1023	            break;
1024	        } else if (v1[i] > v2[i]) {
1025	            compare = 1;
1026	            break;
1027	        }
1028	    }
1029	    if (!operator) {
1030	        return compare;
1031	    }
1032
1033	    switch (operator) {
1034	    case '>':
1035	    case 'gt':
1036	        return (compare > 0);
1037	    case '>=':
1038	    case 'ge':
1039	        return (compare >= 0);
1040	    case '<=':
1041	    case 'le':
1042	        return (compare <= 0);
1043	    case '==':
1044	    case '=':
1045	    case 'eq':
1046	        return (compare === 0);
1047	    case '<>':
1048	    case '!=':
1049	    case 'ne':
1050	        return (compare !== 0);
1051	    case '':
1052	    case '<':
1053	    case 'lt':
1054	        return (compare < 0);
1055	    default:
1056	        return null;
1057	    }
1058	},
1059
1060	setSmoothScroll: function(jquery)
1061	{
1062		var objBrowser = JSNUtils.getBrowserInfo();
1063
1064		// Setup smooth go to top link
1065		if (jquery) {
1066			$j('#jsn-gotoplink').click(function(e) {
1067				e.preventDefault();
1068				var gotoplinkOffset = $j('#top').offset().top;
1069				$j('html,body').animate({scrollTop: gotoplinkOffset}, 500);
1070				return false;
1071			});
1072		} else if (typeof(MooTools) != 'undefined') {
1073			new Fx.SmoothScroll({
1074				duration: 300,
1075				links: '#jsn-gotoplink'		// Target to only the gotop link
1076			}, window);
1077		}
1078	},
1079
1080	setFadeScroll: function(jquery)
1081	{
1082		var min     = 200;
1083		if (jquery) {
1084			var element = $j('#jsn-gotoplink');
1085			if(element == null) return false;
1086
1087			$j(window).scroll(function () {
1088				($j(window).scrollTop() >= min) ? element.fadeIn() : element.fadeOut();
1089			});
1090		} else if (typeof(MooTools) != 'undefined') {
1091			var element = document.id('jsn-gotoplink');
1092			if (element == null) return false;
1093			if (parseFloat(MooTools.version) < 1.2)
1094			{
1095				var fx 		   = new Fx.Style(element, "opacity", {duration: 500});
1096				var inside 	   = false;
1097				window.addEvent('scroll',function(e) {
1098					var position   = window.getSize().scroll;
1099					var y          = position.y;
1100					if (y >= min)
1101					{
1102						if (!inside)
1103						{
1104							inside = true;
1105							fx.start(0, 1);
1106						}
1107					}
1108					else
1109					{
1110						if (inside)
1111						{
1112							inside = false;
1113							fx.start(1, 0);
1114						}
1115					}
1116				}.bind(this));
1117			}
1118			else
1119			{
1120				window.addEvent('scroll',function(e) {
1121					element.fade((window.getScroll().y >= min) ? 'in' : 'out');
1122					element.fade((window.getScroll().y >= min) ? 1 : 0);
1123				}.bind(this));
1124			}
1125		}
1126	},
1127
1128	/* ============================== TEXT  ============================== */
1129
1130	checkSubstring: function(targetString, targetSubstring, delimeter, wholeWord){
1131		if(wholeWord == undefined) wholeWord = false;
1132		var parts = targetString.split(delimeter);
1133		for (var i = 0; i < parts.length; i++){
1134			if (wholeWord && parts[i] == targetSubstring) return true;
1135			if (!wholeWord && parts[i].indexOf(targetSubstring) > -1) return true;
1136		}
1137		return false;
1138	},
1139
1140	/* ============================== REMOVE DUPLICATE CSS3 TAG IN IE7 - CSS3 PIE  ============================== */
1141
1142	removeCss3Duplicate: function(className)
1143	{
1144		var element = document.getElements('.' + className);
1145		if (element != undefined)
1146		{
1147			element.each(function(e){
1148				var elementParent = e.getParent();
1149				var duplicateTag = elementParent.getChildren('css3-container');
1150				if (duplicateTag.length && duplicateTag.length > 1)
1151				{
1152					elementParent.removeChild(duplicateTag[0]);
1153				}
1154			});
1155		}
1156	}
1157};

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.