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