1//// mobile.js submenu nav - all below 2 3 4Weebly = Weebly || {}; 5 6Weebly.mobile_navigation = (function($) { 7 8 var SLIDE_RIGHT = "SLIDE_RIGHT", 9 SLIDE_DOWN = "SLIDE_DOWN", 10 SLIDE_STATIC = "SLIDE_STATIC", 11 IOS_ADDRESS_BAR_HEIGHT = 60; 12 13 var isOpen = false, 14 isMoving = false, 15 supportsTouch = false, 16 pendingResizeData = null, 17 isiOS = ( navigator.userAgent.match(/(iPad|iPhone|iPod)/i) ? true : false ), 18 supports3D = ('WebKitCSSMatrix' in window && 'm11' in new WebKitCSSMatrix()), 19 supportsTouch = false, 20 menuOffsetY = 0, 21 navStyle = SLIDE_STATIC, 22 $menuWrapper, $menuButton, $menu, $body, supports3D; 23 24 25 /** 26 * Add a css transition 27 * 28 * @param jquery $o object to animate 29 * @param string property a css transitionable property 30 * @param number speed the ms speed of animation 31 * @param function cb callback function after animation completes 32 * @return undefined 33 */ 34 35 var addTransition = function($o, property, speed, cb) { 36 if (!speed) { 37 speed = 500; 38 } 39 40 $o.css({ 41 webkitTransitionDuration : speed + 'ms', 42 webkitTransitionProperty : property, 43 webkitTransitionTimingFunction : 'linear' 44 }); 45 46 var onTransistionEnd = function(e) { 47 $o.off('webkitTransitionEnd', onTransistionEnd); 48 49 $o.css({ 50 webkitTransitionDuration : '', 51 webkitTransitionProperty : '', 52 webkitTransitionTimingFunction : '' 53 }); 54 55 cb(); 56 } 57 $o.on('webkitTransitionEnd', onTransistionEnd); 58 }; 59 60 /** 61 * Utility animate function for css transitions 62 * 63 * @param jquery $o object to animate 64 * @param object from css properties to animate from 65 * @param object to css properties to animate to 66 * @param number speed the ms speed of animation 67 * @param function cb callback function after animation completes 68 * @return undefined 69 */ 70 var animate = function($o, from, to, speed, cb) { 71 if (!speed) { 72 speed = 500; 73 } 74 if (supports3D) { 75 76 $o.css({ webkitTransitionDuration : '0ms' }); 77 $o.css(from); 78 79 setTimeout(function() { 80 addTransition($o, 'all', speed, cb); 81 82 var props = {}; 83 for (property in to) { 84 if (!to.hasOwnProperty(property)) { 85 continue; 86 } 87 props[property] = to[property]; 88 } 89 $o.css(props); 90 }, 0); 91 } else { 92 //jquery.animate isn't working too well here, disable for now 93 to.avoidCSSTransitions = true; 94 $o.animate(to, { 95 duration : speed, 96 complete : cb 97 }); 98 } 99 }; 100 101 /** 102 * Controls the menu effect when a menu button is tapped 103 * 104 * @param event e event handler 105 * @return undefined 106 */ 107 var menuTap = function(e) { 108 var menuHeight = $menuWrapper.outerHeight(), 109 effectStart, effectEnd, fromCSS, toCSS; 110 111 if (isMoving) { 112 return; 113 } 114 115 isOpen = !isOpen; 116 console.log("1 " + isOpen); 117 118 isMoving = true; 119 120 if (isOpen) { 121 console.log("1 " + isOpen); 122 $body.addClass('menu-open'); 123 } 124 125 var cb = function() { 126 isMoving = false; 127 128 if (!isOpen) { 129 $body.removeClass('menu-open'); 130 } 131 }; 132 133 if (navStyle === SLIDE_DOWN) { 134 // '10' here is compensating for the box shadows overlapping 135 // each other between the header and the menu 136 if (!isOpen) { 137 effectStart = 0; 138 effectEnd = -menuHeight - 10; 139 } else { 140 effectStart = -menuHeight - 10; 141 effectEnd = 0; 142 } 143 144 fromCSS = { 145 '-webkit-transform' : 'translate3d( 0px, ' + effectStart + 'px, 0)' 146 }; 147 148 toCSS = {
149 '-webkit-transform': 'translate3d( 0px, ' + effectEnd + 'px, 0)' 150 }; 151 152 if (!supports3D) { 153 fromCSS = { top : menuOffsetY + effectStart + 'px' }; 154 toCSS = { top : menuOffsetY + effectEnd + 'px' }; 155 } 156 157 animate($menuWrapper, fromCSS, toCSS, 300, cb); 158 } else if (navStyle === SLIDE_RIGHT) { 159 var $pageWrapper = $('#wsite-page-wrapper'); 160 161 cb = function() { 162 isMoving = false; 163 164 if (!isOpen) { 165 $body.removeClass('menu-open'); 166 $menuWrapper.hide(); 167 $body.css('overflow-x', 'visible'); 168 $('#wsite-viewport').css({ 169 'overflow' : 'visible', 170 'height' : '' 171 }); 172 $pageWrapper.css({'background' : 'none', 'height' : ''}); 173 $pageWrapper.css({'height' : ''}); 174 } else { 175 $pageWrapper.one('click', closeMenu); 176 } 177 178 // causes flickering if visible 179 if (!isOpen) { 180 var $backgroundImage = (Weebly.mobile) ? $('#w-fixed-bg') : $('.wsite-background'); 181 $backgroundImage.show(); 182 } 183 }; 184 185 var closeMenu = function(e) { 186 if (!isOpen) { 187 return; 188 } 189 190 menuTap(); 191 192 e.stopImmediatePropagation(); 193 e.preventDefault(); 194 $pageWrapper.off('click', closeMenu); 195 }; 196 197 var timeoutLength = 0; 198 199 if (!isOpen) { 200 effectStart = '80%'; 201 effectEnd = '0%'; 202 } else { 203 effectStart = '0%'; 204 effectEnd = '80%'; 205 206 var $backgroundImage = (Weebly.mobile) ? $('#w-fixed-bg') : $('.wsite-background'); 207 if ($backgroundImage.length === 0) { 208 $backgroundImage = $body; 209 } 210 211 var browserPadding = (isiOS) ? IOS_ADDRESS_BAR_HEIGHT : 0; 212 var $windowProxy = $('#w-mobile-phone-screen'); 213 $windowProxy = ($windowProxy.length > 0) ? $windowProxy : $(window); 214 215 $pageWrapper.css({ 216 'background-color' : $backgroundImage.css('background-color') || 'white', 217 'background-image' : $backgroundImage.css('background-image'), 218 'background-position' : $backgroundImage.css('background-position'), 219 'background-size' : $backgroundImage.css('background-size'), 220 'background-repeat' : $backgroundImage.css('background-repeat'), 221 'background-clip' : $backgroundImage.css('background-clip'), 222 'height' : Math.max($backgroundImage.height(), $windowProxy.height() + browserPadding) + 'px' 223 }); 224 225 //eliminate the 'flicker' from waiting for the background image to load 226 if ($backgroundImage.css('background-image').length > 0 && supports3D && supportsTouch) { 227 timeoutLength = 260; 228 } 229 230 // causes flickering if visible 231 if ($backgroundImage !== $body) { 232 $backgroundImage.hide(); 233 } 234 235 $body.css({ 'overflow-x' : 'hidden' }); 236 237 setTimeout(function() { 238 $menuWrapper.show(); 239 }, timeoutLength); 240 } 241 242 fromCSS = { 243 '-webkit-transform': 'translate3d(' + effectStart + ', 0px, 0)' 244 }; 245 246 toCSS = { 247 '-webkit-transform': 'translate3d(' + effectEnd + ', 0px, 0
247)' 248 }; 249 250 if (!supports3D) { 251 fromCSS = { left : effectStart }; 252 toCSS = { left : effectEnd }; 253 } 254 255 setTimeout(function() { 256 animate($pageWrapper, fromCSS, toCSS, 300, cb); 257 }, timeoutLength); 258 } 259 260 }; 261 262 /** 263 * Tweens the menu left or right 264 * 265 * @param jquery $oldSlide the current slide being moved out 266 * @param jquery $newSlide the new slide being moved in 267 * @param bool rightToLeft move to the right if true, left if false 268 * @return undefined 269 */ 270 var tweenMenu = function($oldSlide, $newSlide, rightToLeft) { 271 var $animContainer = $('.wsite-animation-wrap', $menu), 272 sign = (rightToLeft) ? 1 : -1; 273 274 if (isMoving) { 275 return; 276 } 277 isMoving = true; 278 279 var newHeight = Math.max($newSlide.outerHeight(), $oldSlide.outerHeight()); 280 281 $menu.css({ 282 height : newHeight + 'px' 283 }); 284 285 var menuWidth = $menu.width(); 286 287 var toX = -sign * menuWidth + 'px'; 288 289 var fromCSS = { 290 '-webkit-transform': 'translate3d( 0, 0px, 0)' 291 }; 292 293 var toCSS = { 294 '-webkit-transform': 'translate3d(' + toX + ', 0px, 0
294)' 295 }; 296 297 if (supports3D) { 298 $newSlide.css({ 299 '-webkit-transform': 'translate3d(' + (sign * menuWidth) + 'px, 0px, 0)' 300 }); 301 } else { 302 $newSlide.css({ 303 'left': (sign * menuWidth) + 'px' 304 }); 305 306 fromCSS = { left : 0 }; 307 toCSS = { left : toX }; 308 } 309 310 $newSlide.show(); 311 312 var cb = function() { 313 $oldSlide.hide(); 314 315 var slideHeight = $newSlide.outerHeight(); 316 //reset animation container 317 $menu.css({ height : slideHeight + 'px' }); 318 $animContainer.css(fromCSS); 319 $newSlide.css(fromCSS); 320 321 isMoving = false; 322 }; 323 324 animate($animContainer, fromCSS, toCSS, 300, cb); 325 }; 326 327 /** 328 * Adds a an active state css class so that button presses 329 * can be styled 330 * 331 * @param jquery $element element(s) to add state to 332 * @param string tagName selector to filter dom elemenets 333 * @return undefined 334 */ 335 var addActiveState = function($element, tagName) { 336 $element.on('touchstart', tagName, function(ev) { 337 $(this).addClass('active'); 338 }); 339 $element.on('touchend', tagName, function(ev) { 340 $(this).removeClass('active'); 341 }); 342 }; 343 344 345 /** 346 * Measures the size of the content area to try and place footer 347 * fixed at the bottom of the screen if the screen space is larger 348 * 349 * @return undefined 350 */ 351 var resizeContentWindow = function() { 352 }; 353 354 355 /** 356 * Resizes the vertical height of the mobile menu 357 * 358 * @return undefined 359 */ 360 var resizeMenu = function() { 361 if (!$menu) { 362 return; 363 } 364 var menuHeight = $menu.find('.wsite-menu-slide:visible').outerHeight(); 365 if (menuHeight > 0) { 366 $menu.css({ height : menuHeight + 'px' }); 367 } 368 }; 369 370 /** 371 * Inits the body to detect touch support 372 * 373 * @return undefined 374 */ 375 var initBody = function() { 376 $body = $('body'); 377 378 if (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch) { 379 $body.removeClass('no-touch'); 380 $body.addClass('touch'); 381 supportsTouch = true; 382 } 383 }; 384
385 var initBackground = function() { 386 var isFixedBG = ($body.css('background-attachment').indexOf('fixed') > -1 || $body.css('position').indexOf('fixed') > -1); 387 388 if (Weebly.mobile || !isFixedBG) { 389 return; 390 } 391 392 $body.prepend('<div class="wsite-background"></div>'); 393 var $backgroundImage = $body.find('.wsite-background'); 394 395 $backgroundImage.css({ 396 'background-color' : $body.css('background-color') || 'rgba(0,0,0,0)', 397 'background-image' : $body.css('background-image'), 398 'background-position' : $body.css('background-position'), 399 'background-size' : $body.css('background-size'), 400 'background-repeat' : $body.css('background-repeat'), 401 'background-clip' : $body.css('background-clip'), 402 'position' : 'fixed', 403 'top' : $body.css('top'), 404 'left' : $body.css('left'), 405 'height' : '100%', 406 'width' : '100%' 407 }); 408 $body.css('background', 'none'); 409 } 410 411 /** 412 * Inits the mobile menu structure 413 * 414 * @return undefined 415 */ 416 var initMenu = function() { 417 var $sideMenus = $('#navmobile .wsite-menu-wrap'), 418 $headerUl, $sliderContainer; 419 420 $menuButton = $('#nav-trigger'); 421 $headerUl = $('#navmobile .wsite-menu-default'); 422 423 $headerUl.wrap('<div class="wsite-mobile-menu" />'); 424 $menu = $headerUl.up('.wsite-mobile-menu'); 425 $menuWrapper = $headerUl.up('#wrapper'); 426 $menuWrapper = ($menuWrapper.length > 0) ? $menuWrapper : $menu; 427 428 isOpen = false; 429 isMoving = false; 430 431 // if (!Weebly.mobile) { 432 // $menuButton.on('click', menuTap); 433 // } 434 435 var slideCSS = { 436 position: 'absolute', 437 top: '0', 438 left: '0', 439 width: '100%' 440 }; 441 442 // something to select on 443 $headerUl.addClass('wsite-menu-slide').css(slideCSS); 444 $sideMenus.addClass('wsite-menu-slide').css(slideCSS); 445 446 // new css settings can cause jarring while animations render, 447 // set the settings here even though they don't really 'do anything' 448 $headerUl.css({ 'left' : '0'}); 449 if (supports3D) { 450 $headerUl.css({'-webkit-transform': 'translate3d( 0, 0px, 0)'}); 451 } 452 453 $menu.append('<div class="wsite-animation-wrap"></div>'); 454 $sliderContainer = $('.wsite-animation-wrap', $menu); 455 $sliderContainer.css({ position: 'relative' }); 456 if (supports3D) { 457 $sliderContainer.css({'-webkit-backface-visibility': 'hidden'}); 458 } 459 $sliderContainer.append($headerUl); 460 461 $sideMenus.each(function() { 462 var $sideMenu = $(this), 463 $parentAnchor = $sideMenu.prev(), 464 $ul = $sideMenu.children('ul'), 465 $previousMenu = $sideMenu.parents('.wsite-menu-slide'); 466 467 var $backLink = $('<li class="wsite-menu-back-item">' 468 + '<a><span class="wsite-menu-mobile-arrow"></span><span class="wsite-menu-back">Back</span></a>' 469 + '</li>'); 470 $backLink.on('click', function(ev) { 471 tweenMenu($sideMenu, $previousMenu, false); 472 }); 473 474 if ($parentAnchor.attr("href")) { 475 var $sideMenuRoot = $parentAnchor.clone(true, true); 476 var $rootLink = $('<li class="wsite-menu-master-item"></li>').html($sideMenuRoot); 477 } 478 479 $ul.prepend($rootLink); 480 $ul.prepend($backLink); 481 482 $parentAnchor.removeAttr('href').removeAttr('onclick'); 483 $parentAnchor.append('<span class="wsite-menu-mobile-arrow"></span>'); 484 $parentAnchor.on('click', function(ev) { 485 tweenMenu($previousMenu, $sideMenu, true); 486 }); 487 488 $sideMenu.css({ 'left' : '0' }); 489 if (supports3D) { 490 $sideMenu.css({'-webkit-transform': 'translate3d( 0, 0px, 0)'}); 491 } 492 493 $sliderContainer.append($sideMenu); 494 }); 495 496 $menu.css({ 'display' : 'block'}); 497 $menuWrapper.css({ 'display' : 'block'}); 498 resizeMenu(); 499 500 if ($body.hasClass('wsite-menu-dropdown')) { 501 initSlideDown(); 502 } else if ($body.hasClass('wsite-menu-slideright')) { 503 initSlideRight(); 504 } 505 506 // prefer active state classes over html active 507 if (supportsTouch) { 508 addActiveState($('.wsite-home-link')); 509 addActiveState($menuButton); 510 addActiveState($menu, 'a'); 511 } 512 }; 513 514 var initSlideRight = function() { 515 navStyle = SLIDE_RIGHT; 516 517 var $children = $body.contents(); 518 519 $body.prepend('<div id="wsite-viewport" ><div id="wsite-page-wrapper" /></div>'); 520 var $pageWrapper = $('#wsite-page-wrapper'); 521 522 for (var i = 0; i < $children.length; i++) { 523 var child = $children[i]; 524 $pageWrapper[0].appendChild(child); 525 } 526 527 $pageWrapper.css({ 528 'position' : 'relative', 529 'background' : 'none', 530 'z-index' : '3', 531 'left' : '0', 532 'top' : '0' 533 534 }); 535 if (supports3D) { 536 $pageWrapper.css({
537 '-webkit-backface-visibility': 'hidden', 538 '-webkit-transform' : 'translateZ(0)', 539 '-webkit-transform': 'translate3d( 0, 0, 0)' 540 }); 541 } 542 543 var menuHeight = $pageWrapper.height(); 544 545 $menuWrapper.css({ 546 'top' : '0', 547 'left' : '0', 548 'min-height' : '100%', 549 'width' : '80%', 550 'position' : 'absolute' 551 }); 552 553 $menuWrapper.hide(); 554 555 $body.find('#wsite-viewport').css({ 556 'height' : '', 557 'width' : '100%' 558 }).append($menuWrapper); 559 }; 560 561 var initSlideDown = function() { 562 navStyle = SLIDE_DOWN; 563 564 $menuWrapper.css({ 565 'position' : 'absolute', 566 'width' : '100%', 567 'z-index' : 6 568 }); 569 570 var position = $menuWrapper.position(); 571 menuOffsetY = (position) ? position.top : 0; 572 573 //adjust menu to start behind header and closed 574 var yPos = -$menuWrapper.outerHeight() - 10; 575 if (supports3D) { 576 $menuWrapper.css({ 577 '-webkit-transform' : 'translate3d( 0px, ' + yPos + 'px, 0)', 578 '-webkit-backface-visibility' : 'hidden' 579 }); 580 } else { 581 $menuWrapper.css({ 582 'top' : (menuOffsetY + yPos) + 'px' 583 }); 584 } 585 }; 586 587 588 /** 589 * Close the menu 590 * 591 * @return undefined 592 */ 593 var closeMenu = function() { 594 if (isOpen) { 595 menuTap(null); 596 } 597 }; 598 599 var isMenuOpen = function() { 600 return isOpen; 601 }; 602 603 var init = function() { 604 $body = $('#icontent'); 605 $body = ($body.length > 0) ? $body : $('body'); 606 607 // May be able to dump this flag in the future, 608 // but fixing 3d transition flickering issues was in theme css 609 if (!$body.hasClass('wsite-render3d')) { 610 supports3D = false; 611 } 612 613 initMenu();
614 whenThemeCSSLoaded(initBackground); 615 }; 616 617 if (!Weebly.mobile) { 618 // reset iframe content sizes 619 $(window).on("message", function(event) { 620 if (!event.origin || event.origin.indexOf('weebly.com') === -1) { 621 return; 622 } 623 624 pendingResizeData = event.data; 625 }); 626 } 627 628 // dom ready 629 $(function() { 630 initBody(); 631 init(); 632 633 if (window.FastClick) { 634 FastClick.attach($('.wsite-menu-button')[0]); 635 FastClick.attach($('.wsite-mobile-menu')[0]); 636 } 637 638 }); 639 640 return { 641 init : init, 642 closeMenu : closeMenu, 643 resizeScreen : resizeContentWindow, 644 resizeMenu : resizeMenu, 645 menuTap : menuTap, 646 isMenuOpen : isMenuOpen 647 }; 648 649}(Weebly.jQuery));
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.