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