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