1/** 2 * UpSolution Theme Core JavaScript Code 3 * 4 * @requires jQuery 5 */ 6if (window.$us === undefined) window.$us = {}; 7 8/** 9 * Retrieve/set/erase dom modificator class <mod>_<value> for UpSolution CSS Framework 10 * @param {String} mod Modificator namespace 11 * @param {String} [value] Value 12 * @returns {string|jQuery} 13 */ 14jQuery.fn.usMod = function(mod, value){ 15 if (this.length == 0) return this; 16 // Remove class modificator 17 if (value === false) { 18 this.get(0).className = this.get(0).className.replace(new RegExp('(^| )' + mod + '\_[a-z0-9]+( |$)'), '$2'); 19 return this; 20 } 21 var pcre = new RegExp('^.*?' + mod + '\_([a-z0-9]+).*?$'), 22 arr; 23 // Retrieve modificator 24 if (value === undefined) { 25 return (arr = pcre.exec(this.get(0).className)) ? arr[1] : false; 26 } 27 // Set modificator 28 else { 29 this.usMod(mod, false).get(0).className += ' ' + mod + '_' + value; 30 return this; 31 } 32}; 33 34/** 35 * Convert data from PHP to boolean the right way 36 * @param {mixed} value 37 * @returns {Boolean} 38 */ 39$us.toBool = function(value){ 40 if (typeof value == 'string') return (value == 'true' || value == 'True' || value == 'TRUE' || value == '1'); 41 if (typeof value == 'boolean') return value; 42 return !!parseInt(value); 43}; 44 45// Fixing hovers for devices with both mouse and touch screen 46jQuery.isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); 47jQuery('html').toggleClass('no-touch', !jQuery.isMobile); 48 49/** 50 * Commonly used jQuery objects 51 */ 52!function($){ 53 $us.$window = $(window); 54 $us.$document = $(document); 55 $us.$html = $('html'); 56 $us.$body = $('.l-body:first'); 57 $us.$htmlBody = $us.$html.add($us.$body); 58 $us.$canvas = $('.l-canvas:first'); 59}(jQuery); 60 61/** 62 * $us.canvas 63 * 64 * All the needed data and functions to work with overall canvas. 65 */ 66!function($){ 67 "use strict"; 68 69 function USCanvas(options){ 70 71 // Setting options 72 var defaults = { 73 disableEffectsWidth: 900, 74 responsive: true 75 }; 76 this.options = $.extend({}, defaults, options || {}); 77 78 // Commonly used dom elements 79 this.$header = $us.$canvas.find('.l-header'); 80 this.$main = $us.$canvas.find('.l-main'); 81 this.$titlebar = $us.$canvas.find('.l-titlebar'); 82 this.$sections = $us.$canvas.find('.l-section'); 83 this.$firstSection = this.$sections.first(); 84 this.$fullscreenSections = this.$sections.filter('.height_full'); 85 this.$topLink = $('.w-toplink'); 86 87 // Canvas modificators 88 this.sidebar = $us.$canvas.usMod('sidebar'); 89 this.type = $us.$canvas.usMod('type'); 90 // Initial header position 91 this._headerPos = this.$header.usMod('pos'); 92 // Current header position 93 this.headerPos = this._headerPos; 94 this.headerBg = this.$header.usMod('bg'); 95 this.rtl = $us.$body.hasClass('rtl'); 96 97 // Will be used to count fullscreen sections heights and proper scroll positions 98 this.scrolledOccupiedHeight = 0; 99 100 // Boundable events 101 this._events = { 102 scroll: this.scroll.bind(this), 103 resize: this.resize.bind(this) 104 }; 105 106 $us.$window.on('scroll', this._events.scroll); 107 $us.$window.on('resize load', this._events.resize); 108 // Complex logics requires two initial renders: before inner elements render and after 109 setTimeout(this._events.resize, 25); 110 setTimeout(this._events.resize, 75); 111 } 112 113 USCanvas.prototype = { 114 115 /** 116 * Scroll-driven logics 117 */ 118 scroll: function(){ 119 var scrollTop = parseInt($us.$window.scrollTop()); 120 121 // Show/hide go to top link 122 this.$topLink.toggleClass('active', (scrollTop >= this.winHeight)); 123 }, 124 125 /** 126 * Resize-driven logics 127 */ 128 resize: function(){ 129 // Window dimensions 130 this.winHeight = parseInt($us.$window.height()); 131 this.winWidth = parseInt($us.$window.width()); 132 133 // Disabling animation on mobile devices 134 $us.$body.toggleClass('disable_effects', (this.winWidth <= this.options.disableEffectsWidth)); 135 136 // Updating fullscreen sections 137 if (this.$fullscreenSections.length > 0) { 138 this.$fullscreenSections.each(function(index, section){ 139 var $section = $(section), 140 sectionHeight = this.winHeight, 141 isFirstSection = (index == 0 && this.$titlebar.length == 0 && $section.is(this.$firstSection)); 142 // First section 143 if (isFirstSection) { 144 sectionHeight -= $section.offset().top; 145 } 146 // 2+ sections 147 else { 148 sectionHeight -= $us.header.scrolledOccupiedHeight; 149 } 150 $section.css('min-height', sectionHeight); 151 if ($section.hasClass('valign_center')) { 152 var $sectionH = $section.find('.l-section-h'), 153 sectionTopPadding = parseInt($section.css('padding-top')), 154 contentHeight = $sectionH.outerHeight(), 155 topMargin; 156 $sectionH.css('margin-top', ''); 157 // Section was extended by extra top padding that is overlapped by fixed solid header and n
157ot visible 158 var sectionOverlapped = isFirstSection && $us.header.pos == 'fixed' && $us.header.bg != 'transparent' && $us.header.orientation != 'ver'; 159 if (sectionOverlapped) { 160 // Part of first section is overlapped by header 161 topMargin = Math.max(0, (sectionHeight - sectionTopPadding - contentHeight) / 2); 162 } else { 163 topMargin = Math.max(0, (sectionHeight - contentHeight) / 2 - sectionTopPadding); 164 } 165 $sectionH.css('margin-top', topMargin || ''); 166 } 167 $section.find('.upb_row_bg').css('min-height', $section.height()); 168 }.bind(this)); 169 $us.$canvas.trigger('contentChange'); 170 } 171 172 // Fix scroll glitches that could occur after the resize 173 this.scroll(); 174 } 175 }; 176 177 $us.canvas = new USCanvas($us.canvasOptions || {}); 178 179}(jQuery); 180 181/** 182 * $us.header 183 * Dev note: should be initialized after $us.canvas 184 */ 185!function($){ 186 "use strict"; 187 function USHeader(settings){ 188 this.settings = settings || {}; 189 this.state = 'default'; // 'tablets' / 'mobiles' 190 this.$container = $us.$canvas.find('.l-header'); 191 this.$topCell = this.$container.find('.l-subheader.at_top .l-subheader-cell:first'); 192 this.$middleCell = this.$container.find('.l-subheader.at_middle .l-subheader-cell:first'); 193 this.$bottomCell = this.$container.find('.l-subheader.at_bottom .l-subheader-cell:first'); 194 this.$showBtn = $('.w-header-show:first'); 195 this.orientation = $us.$body.usMod('header'); 196 this.pos = this.$container.usMod('pos'); // 'fixed' / 'static' 197 this.bg = this.$container.usMod('bg'); // 'solid' / 'transparent' 198 199 // Will be used to count fullscreen sections heights and proper scroll positions 200 this.scrolledOccupiedHeight = 0; 201 202 this._events = { 203 scroll: this.scroll.bind(this), 204 resize: this.resize.bind(this), 205 contentChange: function(){ 206 this._countScrollable(); 207 }.bind(this), 208 hideMobileVerticalHeader: function(e){ 209 if ($.contains(this.$container[0], e.target)) return; 210 $us.$body 211 .off($.isMobile ? 'touchstart' : 'click', this._events.hideMobileVerticalHeader) 212 .removeClass('header-show'); 213 }.bind(this) 214 }; 215 this.$elms = {}; 216 this.$places = { 217 hidden: this.$container.find('.l-subheader.for_hidden') 218 }; 219 this.$container.find('.l-subheader-cell').each(function(index, cell){ 220 var $cell = $(cell); 221 this.$places[$cell.parent().parent().usMod('at') + '_' + $cell.usMod('at')] = $cell; 222 }.bind(this)); 223 var regexp = /(^| )ush_([a-z_]+)_([0-9]+)( |$)/; 224 this.$container.find('[class*=ush_]').each(function(index, elm){ 225 var $elm = $(elm), 226 matches = regexp.exec($elm.attr('class')); 227 if (!matches) return; 228 var id = matches[2] + ':' + matches[3]; 229 this.$elms[id] = $elm; 230 if ($elm.is('.w-vwrapper, .w-hwrapper')) { 231 this.$places[id] = $elm; 232 } 233 }.bind(this)); 234 // TODO Objects with the header elements 235 $us.$window.on('scroll', this._events.scroll); 236 $us.$window.on('resize load', this._events.resize); 237 this._updateHeaderScrollBreakpoint(); 238 this.resize(); 239 240 $us.$canvas.on('contentChange', function(){ 241 if (this.orientation == 'ver') this.docHeight = $us.$document.height(); 242 }.bind(this)); 243 244 this.$container.on('contentChange', this._events.contentChange); 245 246 this.$showBtn.on('click', function(e){ 247 if ($us.$body.hasClass('header-show')) return; 248 e.stopPropagation(); 249 $us.$body 250 .addClass('header-show') 251 .on($.isMobile ? 'touchstart' : 'click', this._events.hideMobileVerticalHeader); 252 }.bind(this)); 253 } 254 255 $.extend(USHeader.prototype, { 256 scroll: function(){ 257 var scrollTop = parseInt($us.$window.scrollTop()); 258 if (this.pos == 'fixed') { 259 if (this.orientation == 'hor') { 260 this.$container.toggleClass('sticky', scrollTop >= this.headerScrollBreakpoint); 261 } else if (this.$container.hasClass('scrollable') && this.docHeight > this.headerHeight + this.htmlTopMargin) { 262 var scrollRangeDiff = this.headerHeight - $us.canvas.winHeight + this.htmlTopMargin; 263 if (this._sidedHeaderScrollRange === undefined) { 264 this._sidedHeaderScrollRange = [0, scrollRangeDiff]; 265 } 266 if (scrollTop <= this._sidedHeaderScrollRange[0]) { 267 this._sidedHeaderScrollRange[0] = Math.max(0, scrollTop); 268 this._sidedHeaderScrollRange[1] = this._sidedHeaderScrollRange[0] + scrollRangeDiff; 269 this.$container.css({ 270 position: 'fixed', 271 top: this.htmlTopMargin 272 }); 273 } 274 else if (this._sidedHeaderScrollRange[0] < scrollTop && scrollTop < this._sidedHeaderScrollRange[1]) { 275 this.$container.css({ 276 position: 'absolute', 277 top: this._sidedHeaderScrollRange[0] 278 }); 279 } 280 else if (this._sidedHeaderScrollRange[1] <= scrollTop) { 281 this._sidedHeaderScrollRange[1] = Math.min(this.docHeight - $us.canvas.winHeight, scrollTop); 282 this._sidedHeaderScrollRange[0] = this._sidedHeaderScrollRange[1] - scrollRangeDiff; 283 this.$container.css({ 284 position: 'fixed', 285 top: $us.canvas.winHeight - this.headerHeight 286 }); 287 } 288 } 289 } 290 }, 291 resize: function(){ 292 var newState = 'default'; 293 if (window.innerWidth <= 900) newState = (window.innerWidth <= 600) ? 'mobiles' : 'tablets'; 294 this.setState(newState); 295 if (this.pos == 'fixed' && this.orientation == 'hor') { 296 var isSticky = this.$container.hasClass('sticky'); 297 this.$container.addClass('notransition'); 298 if (!isSticky) this.$container.addClass('sticky'); 299 this.scrolledOccupiedHeight = this.$container.height(); 300 if (!isSticky) this.$container.removeClass('sticky'); 301 // Removing with a small delay to prevent css glitch 302 setTimeout(function(){ 303 this.$container.removeClass('notransition'); 304 }.bind(this), 50); 305 } else /*if (this.orientation == 'ver' || this.pos == 'static')*/ { 306 this.scrolledOccupiedHeight = 0; 307 } 308 this._countScrollable(); 309 this.scroll(); 310 }, 311 setState: function(newState){ 312 if (newState == this.state) return; 313 var newOrientation = this.settings[newState].options.orientation || 'hor', 314 newPos = $us.toBool(this.settings[newState].options.sticky) ? 'fixed' : 'static', 315 newBg = $us.toBool(this.settings[newState].options.transparent) ? 'transparent' : 'solid'; 316 if (newOrientation == 'ver') { 317 newPos = 'fixed'; 318 newBg = 'solid'; 319 } 320 this.state = newState; 321 // Don't change the order: orientation -> pos -> bg -> layout 322 this._setOrientation(newOrientation); 323 this._setPos(newPos); 324 this._setBg(newBg); 325 this._setLayout(this.settings[newState].layout || {}); 326 $us.$body.usMod('state', newState); 327 if (newState == 'default') $us.$body.removeClass('header-show'); 328 // Updating the main menu because of dependencies 329 if ($us.nav !== undefined) $us.nav.resize(); 330 }, 331 _setOrientation: function(newOrientation){ 332 if (newOrientation == this.orientation) return; 333 $us.$body.usMod('header', newOrientation); 334 this.orientation = newOrientation; 335 }, 336 _countScrollable: function(){ 337 if (this.orientation == 'ver' && this.pos == 'fixed' && this.state == 'default') { 338 this.docHeight = $us.$document.height(); 339 this.htmlTopMargin = parseInt($us.$html.css('margin-top')); 340 this.headerHeight = this.$topCell.height() + this.$middleCell.height() + this.$bottomCell.height(); 341 if (this.headerHeight > $us.canvas.winHeight - this.htmlTopMargin) { 342 this.$container.addClass('scrollable'); 343 } else if (this.$container.hasClass('scrollable')) { 344 this.$container.removeClass('scrollable').resetInlineCSS('position', 'top', 'bottom'); 345 delete this._sidedHeaderScrollRange; 346 } 347 if (this.headerHeight + this.htmlTopMargin >= this.docHeight) { 348 this.$container.css({ 349 position: 'absolute', 350 top: 0 351 }); 352 } 353 } else if (this.$container.hasClass('scrollable')) { 354 this.$container.removeClass('scrollable').resetInlineCSS('position', 'top', 'bottom'); 355 delete this._sidedHeaderScrollRange; 356 } 357 }, 358 _updateHeaderScrollBreakpoint: function(){ 359 // Counting the new headerScrollBreakpoint 360 this.headerScrollBreakpoint = parseInt(.8 * this.settings[this.state].options.middle_height); 361 if ($us.toBool(this.settings[this.state].options.top_show)){ 362 this.headerScrollBreakpoint += parseInt(.8 * this.settings[this.state].options.top_height); 363 } 364 if ($us.toBool(this.settings[this.state].options.bottom_show)){ 365 this.headerScrollBreakpoint += parseInt(.8 * this.settings[this.state].options.bottom_height); 366 } 367 }, 368 _setPos: function(newPos){ 369 if (newPos == this.pos) return; 370 this.$container.usMod('pos', newPos); 371 if (newPos == 'static') { 372 this.$container.removeClass('sticky'); 373 } 374 this.pos = newPos; 375 this._countScrollable(); 376 }, 377 _setBg: function(newBg){ 378 if (newBg == this.bg) return; 379 this.$container.usMod('bg', newBg); 380 this.bg = newBg; 381 }, 382 /** 383 * Recursive function to place elements based on their ids 384 * @param {Array} elms 385 * @param {jQuery} $place 386 * @private 387 */ 388 _placeElements: function(elms, $place){ 389 for (var i = 0; i < elms.length; i++) { 390 var elmId; 391 if (typeof elms[i] == 'object') { 392 // Wrapper 393 elmId = elms[i][0]; 394 if (this.$places[elmId] === undefined || this.$elms[elmId] === undefined) continue; 395 this.$elms[elmId].appendTo($place); 396 this._placeElements(elms[i].shift(), this.$places[elmId]); 397 } else { 398 // Element 399 elmId = elms[i]; 400 if (this.$elms[elmId] === undefined) continue; 401 this.$elms[elmId].appendTo($place); 402 } 403 } 404 }, 405 _setLayout: function(newLayout){ 406 // Retrieving the currently shown layout structure 407 var curLayout = {}; 408 $.each(this.$places, function(place, $place){ 409 }.bind(this)); 410 for (var place in newLayout) { 411 if (!newLayout.hasOwnProperty(place) || this.$places[place] === undefined) continue; 412 this._placeElements(newLayout[place], this.$places[place]); 413 } 414 } 415 }); 416 $us.header = new USHeader($us.headerSettings || {}); 417}(jQuery); 418 419/** 420 * $us.nav 421 * 422 * Header navigation will all the possible states 423 * 424 * @requires $us.canvas 425 */ 426!function($){ 427 428 function USNav(){ 429 430 // Commonly used dom elements 431 this.$nav = $('.l-header .w-nav:first'); 432 if (this.$nav.length == 0) return; 433 this.$control = this.$nav.find('.w-nav-control'); 434 this.$items = this.$nav.find('.w-nav-item'); 435 this.$list = this.$nav.find('.w-nav-list.level_1'); 436 this.$subItems = this.$list.find('.w-nav-item.menu-item-has-children'); 437 this.$subAnchors = this.$list.find('.w-nav-item.menu-item-has-children > .w-nav-anchor'); 438 this.$subLists = this.$list.find('.w-nav-item.menu-item-has-children > .w-nav-list'); 439 this.$anchors = this.$nav.find('.w-nav-anchor'); 440 441 // Setting options 442 this.options = this.$nav.find('.w-nav-options:first')[0].onclick() || {}; 443 444 // In case the nav doesn't exist, do nothing 445 if (this.$nav.length == 0) return; 446 447 this.type = this.$nav.usMod('type'); 448 449 this.mobileOpened = false;
450 this.animationType = this.$nav.usMod('animation'); 451 var showFn = 'fadeInCSS', 452 hideFn = 'fadeOutCSS'; 453 if (this.animationType == 'height') { 454 showFn = 'slideDownCSS'; 455 hideFn = 'slideUpCSS'; 456 } 457 else if (this.animationType == 'mdesign') { 458 showFn = 'showMD'; 459 hideFn = 'hideMD'; 460 } 461 462 // Mobile menu toggler 463 this.$control.on('click', function(){ 464 this.mobileOpened = !this.mobileOpened; 465 if (this.mobileOpened) { 466 // Closing opened sublists 467 this.$items.filter('.opened').removeClass('opened'); 468 this.$subLists.resetInlineCSS('display', 'opacity', 'height', 'padding-top', 'padding-bottom', 'margin-top'); 469 this.$list.slideDownCSS(250, this._events.contentChanged); 470 } else { 471 this.$list.slideUpCSS(250, this._events.contentChanged); 472 } 473 }.bind(this)); 474 475 // Boundable events 476 this._events = { 477 // Mobile submenu togglers 478 toggle: function(e){ 479 if (this.type != 'mobile') return; 480 e.stopPropagation(); 481 e.preventDefault(); 482 var $item = $(e.currentTarget).closest('.w-nav-item'), 483 $sublist = $item.children('.w-nav-list'); 484 if ($item.hasClass('opened')) { 485 $item.removeClass('opened'); 486 $sublist.slideUpCSS(250, this._events.contentChanged); 487 } else { 488 $item.addClass('opened'); 489 $sublist.slideDownCSS(250, this._events.contentChanged); 490 } 491 }.bind(this), 492 resize: this.resize.bind(this), 493 contentChanged: function(){ 494 if (this.type == 'mobile' && $us.header.orientation == 'hor' && $us.canvas.headerPos == 'fixed') { 495 this.setFixedMobileMaxHeight(); 496 } 497 $us.header.$container.trigger('contentChange'); 498 }.bind(this) 499 }; 500 501 // Toggle on item clicks 502 if (this.options.mobileBehavior) { 503 this.$subAnchors.on('click', this._events.toggle); 504 } 505 // Toggle on arrows 506 else { 507 this.$list.find('.w-nav-item.menu-item-has-children > .w-nav-anchor > .w-nav-arrow').on('click', this._events.toggle); 508 } 509 // Mark all the togglable items 510 this.$subItems.each(function(){ 511 var $this = $(this), 512 $parentItem = $this.parent().closest('.w-nav-item'); 513 if ($parentItem.length == 0 || $parentItem.usMod('columns') === false) $this.addClass('togglable'); 514 }); 515 // Touch device handling in default (notouch) layout 516 if (!$us.$html.hasClass('no-touch')) { 517 this.$list.find('.w-nav-item.menu-item-has-children.togglable > .w-nav-anchor').on('click', function(e){ 518 if (this.type == 'mobile') return; 519 e.preventDefault(); 520 var $this = $(e.currentTarget), 521 $item = $this.parent(), 522 $list = $item.children('.w-nav-list'); 523 524 // Second tap: going to the URL 525 if ($item.hasClass('opened')) return location.assign($this.attr('href')); 526 $list[showFn](); 527 $item.addClass('opened'); 528 var outsideClickEvent = function(e){ 529 if ($.contains($item[0], e.target)) return; 530 $item.removeClass('opened'); 531 $list[hideFn](); 532 $us.$body.off('touchstart', outsideClickEvent); 533 }; 534 535 $us.$body.on('touchstart', outsideClickEvent); 536 }.bind(this)); 537 } 538 // Desktop device hovers 539 else { 540 this.$subItems 541 .filter('.togglable') 542 .on('mouseenter', function(e){ 543 if (this.type == 'mobile') return; 544 var $list = $(e.currentTarget).children('.w-nav-list'); 545 $list[showFn](); 546 }.bind(this)) 547 .on('mouseleave', function(e){ 548 if (this.type == 'mobile') return; 549 var $list = $(e.currentTarget).children('.w-nav-list'); 550 $list[hideFn](); 551 }.bind(this)); 552 } 553 // Close menu on anchor clicks 554 this.$anchors.on('click', function(e){ 555 if (this.type != 'mobile' || $us.header.orientation != 'hor') return; 556 // Toggled the item 557 if (this.options.mobileBehavior && $(e.currentTarget).closest('.w-nav-item').hasClass('menu-item-has-children')) return; 558 this.$list.slideUpCSS(); 559 this.mobileOpened = false; 560 }.bind(this)); 561 562 $us.$window.on('resize', this._events.resize); 563 setTimeout(function(){ 564 this.resize(); 565 $us.header.$container.trigger('contentChange'); 566 }.bind(this), 50); 567 } 568 569 USNav.prototype = { 570 571 /** 572 * Count proper dimensions 573 */ 574 setFixedMobileMaxHeight: function(){ 575 var listTop = Math.min(this.$list.position().top, $us.header.scrolledOccupiedHeight); 576 this.$list.css('max-height', $us.canvas.winHeight - listTop + 'px'); 577 }, 578 579 /** 580 * Resize handler 581 */ 582 resize: function(){ 583 if (this.$nav.length == 0) return; 584 var nextType = (window.innerWidth <= this.options.mobileWidth) ? 'mobile' : 'desktop'; 585 if ($us.header.orientation != this.headerOrientation || nextType != this.type) { 586 // Clearing the previous state 587 this.$subLists.resetInlineCSS('display', 'opacity', 'height', 'padding-top', 'padding-bottom', 'margin-top'); 588 if (this.headerOrientation == 'hor' && this.type == 'mobile') { 589 this.$list.resetInlineCSS('height', 'max-height', 'display', 'opacity', 'padding-top', 'padding-bottom'); 590 } 591 // Closing opened sublists 592 this.$items.removeClass('opened'); 593 // Applying the new state 594 if ($us.header.orientation == 'hor') { 595 if (nextType == 'desktop') { 596 this.$items.filter('.togglable').children('.w-nav-list').css('display', 'none'); 597 } else if (nextType == 'mobile') { 598 this.mobileOpened = false;
599 this.$list.css('height', 0); 600 this.$subLists.css('height', 0); 601 } 602 } 603 this.headerOrientation = $us.header.orientation; 604 this.type = nextType; 605 this.$nav.usMod('type', nextType); 606 } 607 // Max-height limitation for fixed header layouts 608 if ($us.header.orientation == 'hor' && this.type == 'mobile' && $us.canvas.headerPos == 'fixed') this.setFixedMobileMaxHeight(); 609 this.$list.removeClass('hidden'); 610 } 611 }; 612 613 $us.nav = new USNav(); 614 615}(jQuery); 616 617 618/** 619 * $us.scroll 620 * 621 * ScrollSpy, Smooth scroll links and hash-based scrolling all-in-one 622 * 623 * @requires $us.canvas 624 */ 625!function($){ 626 "use strict"; 627 628 function USScroll(options){ 629 630 // Setting options 631 var defaults = { 632 /** 633 * @param {String|jQuery} Selector or object of hash scroll anchors that should be attached on init 634 */ 635 attachOnInit: '.w-nav a[href*="#"], .w-menu a[href*="#"], a.w-btn[href*="#"], .w-iconbox a[href*="#"], .w-image a[href*="#"], ' + 636 '.vc_icon_element a[href*="#"], .vc_custom_heading a[href*="#"], a.w-portfolio-item-anchor[href*="#"], .widget_nav_menu a[href*="#"], .w-toplink, ' + 637 '.w-blog-post-meta-comments a[href*="#"], .w-comments-title a[href*="#"], .w-comments-item-date, a.smooth-scroll[href*="#"]', 638 /** 639 * @param {String} Classname that will be toggled on relevant buttons 640 */ 641 buttonActiveClass: 'active', 642 /** 643 * @param {String} Classname that will be toggled on relevant menu items 644 */ 645 menuItemActiveClass: 'current-menu-item', 646 /** 647 * @param {String} Classname that will be toggled on relevant menu ancestors 648 */ 649 menuItemAncestorActiveClass: 'current-menu-ancestor', 650 /** 651 * @param {Number} Duration of scroll animation 652 */ 653 animationDuration: 1200, 654 /** 655 * @param {String} Easing for scroll animation 656 */ 657 animationEasing: 'easeInOutQuint' 658 }; 659 this.options = $.extend({}, defaults, options || {}); 660 661 // Hash blocks with targets and activity indicators 662 this.blocks = {}; 663 664 // Is scrolling to some specific block at the moment? 665 this.isScrolling = false; 666 667 // Waypoints that will be called at certain scroll position 668 this.waypoints = []; 669 670 // Boundable events 671 this._events = { 672 cancel: this.cancel.bind(this), 673 scroll: this.scroll.bind(this), 674 resize: this.resize.bind(this) 675 }; 676 677 this._canvasTopOffset = 0; 678 $us.$window.on('resize load', this._events.resize); 679 setTimeout(this._events.resize, 75); 680 681 $us.$window.on('scroll', this._events.scroll); 682 setTimeout(this._events.scroll, 75); 683 684 if (this.options.attachOnInit) { 685 this.attach(this.options.attachOnInit); 686 } 687 688 // Recount scroll positions on any content changes 689 $us.$canvas.on('contentChange', this._countAllPositions.bind(this)); 690 691 // Handling initial document hash 692 if (document.location.hash && document.location.hash.indexOf('#!') == -1) { 693 var hash = document.location.hash, 694 scrollPlace = (this.blocks[hash] !== undefined) ? hash : undefined; 695 if (scrollPlace === undefined) { 696 try { 697 var $target = $(hash); 698 if ($target.length != 0) { 699 scrollPlace = $target; 700 } 701 } catch (error) { 702 //Do not have to do anything here since scrollPlace is already undefined 703 } 704 705 } 706 if (scrollPlace !== undefined) { 707 // While page loads, its content changes, and we'll keep the proper scroll on each sufficient content change 708 // until the page finishes loading or user scrolls the page manually 709 var keepScrollPositionTimer = setInterval(function(){ 710 this.scrollTo(scrollPlace); 711 }.bind(this), 100); 712 var clearHashEvents = function(){ 713 // Content size still may change via other script right after page load 714 setTimeout(function(){ 715 clearInterval(keepScrollPositionTimer); 716 $us.canvas.resize(); 717 this._countAllPositions(); 718 this.scrollTo(scrollPlace); 719 }.bind(this), 100); 720 $us.$window.off('load touchstart mousewheel DOMMouseScroll touchstart', clearHashEvents); 721 }.bind(this); 722 $us.$window.on('load touchstart mousewheel DOMMouseScroll touchstart', clearHashEvents); 723 } 724 } 725 } 726 727 USScroll.prototype = { 728 729 /** 730 * Count hash's target position and store it properly 731 * 732 * @param {String} hash 733 * @private 734 */ 735 _countPosition: function(hash){ 736 this.blocks[hash].top = Math.ceil(this.blocks[hash].target.offset().top - $us.header.scrolledOccupiedHeight - this._canvasTopOffset); 737 this.blocks[hash].bottom = this.blocks[hash].top + this.blocks[hash].target.outerHeight(false); 738 }, 739 740 /** 741 * Count all targets' positions for proper scrolling 742 * 743 * @private 744 */ 745 _countAllPositions: function(){ 746 // Take into account #wpadminbar (and others possible) offset 747 this._canvasTopOffset = $us.$canvas.offset().top; 748 for (var hash in this.blocks) { 749 if (!this.blocks.hasOwnProperty(hash)) continue; 750 this._countPosition(hash); 751 } 752 // Counting waypoints 753 for (var i = 0; i < this.waypoints.length; i++) { 754 this._countWaypoint(this.waypoints[i]); 755 } 756 }, 757 758 /** 759 * Indicate scroll position by hash 760 * 761 * @param {String} activeHash 762 * @private 763 */ 764 _indicatePosition: function(activeHash){ 765 var activeMenuAncestors = []; 766 for (var hash in this.blocks) { 767 if (!this.blocks.hasOwnProperty(hash)) continue; 768 if (this.blocks[hash].buttons !== undefined) { 769 this.blocks[hash].buttons.toggleClass(this.options.buttonActiveClass, hash === activeHash); 770 } 771 if (this.blocks[hash].menuItems !== undefined) { 772 this.blocks[hash].menuItems.toggleClass(this.options.menuItemActiveClass, hash === activeHash); 773 } 774 if (this.blocks[hash].menuAncestors !== undefined) { 775 this.blocks[hash].menuAncestors.removeClass(this.options.menuItemAncestorActiveClass); 776 } 777 } 778 if (this.blocks[activeHash] !== undefined && this.blocks[activeHash].menuAncestors !== undefined) { 779 this.blocks[activeHash].menuAncestors.addClass(this.options.menuItemAncestorActiveClass); 780 } 781 }, 782 783 /** 784 * Attach anchors so their targets will be listened for possible scrolls 785 * 786 * @param {String|jQuery} anchors Selector or list of anchors to attach 787 */ 788 attach: function(anchors){ 789 // Location pattern to check absolute URLs for current location 790 var locationPattern = new RegExp('^' + location.pathname.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&") + '#'); 791 792 var $anchors = $(anchors); 793 if ($anchors.length == 0) return; 794 $anchors.each(function(index, anchor){ 795 var $anchor = $(anchor), 796 href = $anchor.attr('href'), 797 hash = $anchor.prop('hash'); 798 // Ignoring ajax links 799 if (hash.indexOf('#!') != -1) return; 800 // Checking if the hash is connected with the current page 801 if (!( 802 // Link type: #something 803 href.charAt(0) == '#' || 804 // Link type: /#something 805 (href.charAt(0) == '/' && locationPattern.test(href)) || 806 // Link type: http://example.com/some/path/#something 807 href.indexOf(location.host + location.pathname + '#') > -1 808 )) return; 809 // Do we have an actual target, for which we'll need to count geometry? 810 if (hash != '' && hash != '#') { 811 // Attach target 812 if (this.blocks[hash] === undefined) { 813 var $target = $(hash); 814 // Don't attach anchors that actually have no target 815 if ($target.length == 0) return; 816 // If it's the only row in a submain, than use submain instead 817 if ($target.hasClass('g-cols') && $target.parent().children().length == 1) { 818 $target = $target.closest('.l-section'); 819 } 820 this.blocks[hash] = { 821 target: $target 822 }; 823 this._countPosition(hash); 824 } 825 // Attach activity indicator 826 if ($anchor.hasClass('w-nav-anchor')) { 827 var $menuIndicator = $anchor.closest('.w-nav-item'); 828 this.blocks[hash].menuItems = (this.blocks[hash].menuItems || $()).add($menuIndicator); 829 var $menuAncestors = $menuIndicator.parents('.menu-item-has-children'); 830 if ($menuAncestors.length > 0) { 831 this.blocks[hash].menuAncestors = (this.blocks[hash].menuAncestors || $()).add($menuAncestors); 832 } 833 } 834 else { 835 this.blocks[hash].buttons = (this.blocks[hash].buttons || $()).add($anchor); 836 } 837 } 838 $anchor.on('click', function(event){ 839 event.preventDefault(); 840 this.scrollTo(hash, true); 841 }.bind(this)); 842 }.bind(this)); 843 }, 844 845 /** 846 * Scroll page to a certain position or hash 847 * 848 * @param {Number|String|jQuery} place 849 * @param {Boolean} animate 850 */ 851 scrollTo: function(place, animate){ 852 var placeType, 853 newY; 854 // Scroll to top 855 if (place == '' || place == '#') { 856 newY = 0; 857 placeType = 'top'; 858 } 859 // Scroll by hash 860 else if (this.blocks[place] !== undefined) { 861 newY = this.blocks[place].top; 862 placeType = 'hash'; 863 } 864 else if (place instanceof $) { 865 newY = Math.floor(place.offset().top - $us.header.scrolledOccupiedHeight - this._canvasTopOffset); 866 placeType = 'element'; 867 } 868 else { 869 newY = Math.floor(place - $us.header.scrolledOccupiedHeight - this._canvasTopOffset); 870 } 871 var indicateActive = function(){ 872 if (placeType == 'hash') { 873 this._indicatePosition(place); 874 } 875 else { 876 this.scroll(); 877 } 878 }.bind(this); 879 if (animate) { 880 this.isScrolling = true; 881 $us.$htmlBody.stop(true, false).animate({ 882 scrollTop: newY + 'px' 883 }, { 884 duration: this.options.animationDuration, 885 easing: this.options.animationEasing, 886 always: function(){ 887 $us.$window.off('keydown mousewheel DOMMouseScroll touchstart', this._events.cancel); 888 this.isScrolling = false;
889 indicateActive(); 890 }.bind(this) 891 }); 892 // Allow user to stop scrolling manually 893 $us.$window.on('keydown mousewheel DOMMouseScroll touchstart', this._events.cancel); 894 } 895 else { 896 $us.$htmlBody.stop(true, false).scrollTop(newY); 897 indicateActive(); 898 } 899 }, 900 901 /** 902 * Cancel scroll 903 */ 904 cancel: function(){ 905 $us.$htmlBody.stop(true, false); 906 }, 907 908 /** 909 * Add new waypoint 910 * 911 * @param {jQuery} $elm object with the element 912 * @param {mixed} offset Offset from bottom of screen in pixels ('100') or percents ('20%') 913 * @param {Function} fn The function that will be called 914 */ 915 addWaypoint: function($elm, offset, fn){ 916 $elm = ($elm instanceof $) ? $elm : $($elm); 917 if ($elm.length == 0) return; 918 if (typeof offset != 'string' || offset.indexOf('%') == -1) { 919 // Not percent: using pixels 920 offset = parseInt(offset); 921 } 922 var waypoint = { 923 $elm: $elm, 924 offset: offset, 925 fn: fn 926 }; 927 this._countWaypoint(waypoint); 928 this.waypoints.push(waypoint); 929 }, 930 931 /** 932 * 933 * @param {Object} waypoint 934 * @private 935 */ 936 _countWaypoint: function(waypoint){ 937 var elmTop = waypoint.$elm.offset().top, 938 winHeight = $us.$window.height(); 939 if (typeof waypoint.offset == 'number') { 940 // Offset is defined in pixels 941 waypoint.scrollPos = elmTop - winHeight + waypoint.offset; 942 } else { 943 // Offset is defined in percents 944 waypoint.scrollPos = elmTop - winHeight + winHeight * parseInt(waypoint.offset) / 100; 945 } 946 }, 947 948 /** 949 * Scroll handler 950 */ 951 scroll: function(){ 952 var scrollTop = parseInt($us.$window.scrollTop()); 953 if (!this.isScrolling) { 954 var activeHash; 955 for (var hash in this.blocks) { 956 if (!this.blocks.hasOwnProperty(hash)) continue; 957 if (scrollTop >= this.blocks[hash].top && scrollTop < this.blocks[hash].bottom) { 958 activeHash = hash; 959 break; 960 } 961 } 962 this._indicatePosition(activeHash); 963 } 964 // Handling waypoints 965 for (var i = 0; i < this.waypoints.length; i++) { 966 if (this.waypoints[i].scrollPos < scrollTop) { 967 this.waypoints[i].fn(this.waypoints[i].$elm); 968 this.waypoints.splice(i, 1); 969 i--; 970 } 971 } 972 }, 973 974 /** 975 * Resize handler 976 */ 977 resize: function(){ 978 // Delaying the resize event to prevent glitches 979 setTimeout(function(){ 980 this._countAllPositions(); 981 this.scroll(); 982 }.bind(this), 150); 983 this._countAllPositions(); 984 this.scroll(); 985 } 986 }; 987 988 $(function(){ 989 $us.scroll = new USScroll($us.scrollOptions || {}); 990 }); 991 992}(jQuery); 993 994 995jQuery(function($){ 996 "use strict"; 997 998 // TODO Move all of the below to us.widgets 999 if ($.fn.magnificPopup) { 1000 1001 $('.product .images').magnificPopup({ 1002 type: 'image', 1003 delegate: 'a.with-lightbox', 1004 gallery: { 1005 enabled: true, 1006 navigateByImgClick: true, 1007 preload: [0, 1], 1008 tPrev: $us.langOptions.magnificPopup.tPrev, // Alt text on left arrow 1009 tNext: $us.langOptions.magnificPopup.tNext, // Alt text on right arrow 1010 tCounter: $us.langOptions.magnificPopup.tCounter // Markup for "1 of 7" counter 1011 }, 1012 removalDelay: 300, 1013 mainClass: 'mfp-fade', 1014 fixedContentPos: false 1015 1016 }); 1017 1018 $('a[ref=magnificPopup][class!=direct-link]').magnificPopup({ 1019 type: 'image', 1020 fixedContentPos: false 1021 }); 1022 } 1023 1024 if ($.fn.revolution) { 1025 $('.fullwidthbanner').revolution({ 1026 delay: 9000, 1027 startwidth: 1140, 1028 startheight: 500, 1029 soloArrowLeftHOffset: 20, 1030 soloArrowLeftVOffset: 0, 1031 soloArrowRightHOffset: 20, 1032 soloArrowRightVOffset: 0, 1033 onHoverStop: "on", // Stop Banner Timet at Hover on Slide on/off 1034 fullWidth: "on", 1035 hideThumbs: false, 1036 shadow: 0 //0 = no Shadow, 1,2,3 = 3 Different Art of Shadows - (No Shadow in Fullwidth Version !) 1037 }); 1038 // Redrawing all the Revolution Sliders 1039 if (window.revapi3 !== undefined && window.revapi3.revredraw !== undefined) { 1040 $us.$window.on('resize', function(){ 1041 window.revapi3.revredraw(); 1042 }); 1043 } 1044 } 1045 1046 $('.animate_fade, .animate_afc, .animate_afl, .animate_afr, .animate_aft, .animate_afb, .animate_wfc, ' + 1047 '.animate_hfc, .animate_rfc, .animate_rfl, .animate_rfr').each(function(){ 1048 $us.scroll.addWaypoint($(this), '15%', function($elm){ 1049 if (!$elm.hasClass('animate_start')) { 1050 setTimeout(function(){ 1051 $elm.addClass('animate_start'); 1052 }, 20); 1053 } 1054 }); 1055 }); 1056 $('.wpb_animate_when_almost_visible').each(function(){ 1057 $us.scroll.addWaypoint($(this), '15%', function($elm){ 1058 if (!$elm.hasClass('wpb_start_animation')) { 1059 setTimeout(function(){ 1060 $elm.addClass('wpb_start_animation'); 1061 }, 20); 1062 } 1063 }); 1064 }); 1065
1066 var $submainVideos = $('.l-section-video'); 1067 var updateVideosSizes = function(){ 1068 $submainVideos.each(function(){ 1069 var $this = $(this), 1070 $video = $this.find('video'), 1071 player = $video.data('mediaelementplayer'); 1072 // Hiding videos on small (some mobiles) resolutions 1073 if ($us.canvas.winWidth <= 1024) { 1074 if (player && player.pause && !player.media.paused) { 1075 player.pause(); 1076 } 1077 return $this.hide(); 1078 } 1079 var mejsContainer = $this.find('.mejs-container'), 1080 poster = $this.find('.mejs-mediaelement img'), 1081 videoWidth = $video.attr('width'), 1082 videoHeight = $video.attr('height'), 1083 videoProportion = videoWidth / videoHeight, 1084 parent = $this.parent(), 1085 parentWidth = parent.outerWidth(), 1086 parentHeight = parent.outerHeight(), 1087 proportion, 1088 centerX, centerY; 1089 if (mejsContainer.length == 0) return; 1090 1091 // Proper sizing 1092// if (video.length > 0 && video[0].player && video[0].player.media) videoWidth = video[0].player.media.videoWidth; 1093// if (video.length > 0 && video[0].player && video[0].player.media) videoHeight = video[0].player.media.videoHeight; 1094 if (player && player.play && player.media.paused) { 1095 player.play(); 1096 } 1097 $this.show(); 1098 parent.find('span.mejs-offscreen').hide(); 1099 1100 proportion = (parentWidth / parentHeight > videoWidth / videoHeight) ? parentWidth / videoWidth : parentHeight / videoHeight; 1101 $this.width(proportion * videoWidth); 1102 $this.height(proportion * videoHeight); 1103 1104 poster.width(proportion * videoWidth); 1105 poster.height(proportion * videoHeight); 1106 1107 centerX = (parentWidth < videoWidth * proportion) ? (parentWidth - videoWidth * proportion) / 2 : 0; 1108 centerY = (parentHeight < videoHeight * proportion) ? (parentHeight - videoHeight * proportion) / 2 : 0; 1109 1110 $this.css({left: centerX, top: centerY}); 1111 1112 mejsContainer.css({width: '100%', height: '100%'}); 1113 $video.css({'object-fit': 'cover', display: 'inline-block'}); 1114 }); 1115 }; 1116 if (window.MediaElementPlayer) { 1117 $('.l-section-video video').mediaelementplayer({ 1118 enableKeyboard: false, 1119 iPadUseNativeControls: false, 1120 pauseOtherPlayers: false, 1121 iPhoneUseNativeControls: false, 1122 AndroidUseNativeControls: false, 1123 videoWidth: '100%', 1124 videoHeight: '100%', 1125 success: function(mediaElement, domObject){ 1126 $(domObject).css('display', 'block'); 1127 updateVideosSizes(); 1128 } 1129 }); 1130 setTimeout(updateVideosSizes, 75); 1131 $us.$window.on('resize load', updateVideosSizes); 1132 } 1133 1134 jQuery('input[type="text"], input[type="email"], textarea').each(function(index, input){ 1135 var $input = $(input), 1136 $row = $input.closest('.w-form-row'); 1137 if ($input.attr('type') == 'hidden') return; 1138 $row.toggleClass('not-empty', $input.val() != ''); 1139 $input.on('input', function(){ 1140 $row.toggleClass('not-empty', $input.val() != ''); 1141 }); 1142 }); 1143 1144 jQuery('.l-section-img, .l-titlebar-img').each(function(){ 1145 var $this = $(this), 1146 img = new Image(); 1147 1148 img.onload = function(){ 1149 if (!$this.hasClass('loaded')) { 1150 $this.addClass('loaded') 1151 } 1152 }; 1153 1154 img.src = ($this.css('background-image') || '').replace(/url\(['"]*(.*?)['"]*\)/g, '$1'); 1155 }); 1156 1157 /* Ultimate Addons for Visual Composer integration */ 1158 jQuery('.upb_bg_img, .upb_color, .upb_grad, .upb_content_iframe, .upb_content_video, .upb_no_bg').each(function(){ 1159 var $bg = jQuery(this), 1160 $prev = $bg.prev(); 1161 1162 if ($prev.length == 0) { 1163 var $parent = $bg.parent(), 1164 $parentParent = $parent.parent(), 1165 $prevParentParent = $parentParent.prev(); 1166 1167 if ($prevParentParent.length) { 1168 $bg.insertAfter($prevParentParent); 1169 1170 if ($parent.children().length == 0) { 1171 $parentParent.remove(); 1172 } 1173 } 1174 } 1175 }); 1176 $('.g-cols > .ult-item-wrap').each(function(index, elm){ 1177 var $elm = jQuery(elm); 1178 $elm.replaceWith($elm.children()); 1179 }); 1180 jQuery('.overlay-show').click(function(){ 1181 window.setTimeout(function(){ 1182 $us.$canvas.trigger('contentChange'); 1183 }, 1000); 1184 }); 1185 1186}); 1187 1188/** 1189 * CSS-analog of jQuery slideDown/slideUp/fadeIn/fadeOut functions (for better rendering) 1190 */ 1191!function(){ 1192 1193 /** 1194 * Remove the passed inline CSS attributes. 1195 * 1196 * Usage: $elm.resetInlineCSS('height', 'width'); 1197 */ 1198 jQuery.fn.resetInlineCSS = function(){ 1199 for (var index = 0; index < arguments.length; index++) { 1200 this.css(arguments[index], ''); 1201 } 1202 return this; 1203 }; 1204 1205 jQuery.fn.clearPreviousTransitions = function(){ 1206 // Stopping previous events, if there were any 1207 var prevTimers = (this.data('animation-timers') || '').split(','); 1208 if (prevTimers.length >= 2) { 1209 this.resetInlineCSS('transition', '-webkit-transition'); 1210 prevTimers.map(clearTimeout); 1211 this.removeData('animation-timers'); 1212 } 1213 return this; 1214 }; 1215 /** 1216 * 1217 * @param {Object} css key-value pairs of animated css 1218 * @param {Number} duration in milliseconds 1219 * @param {Function} onFinish 1220 * @param {String} easing CSS easing name 1221 * @param {Number} delay in milliseconds 1222 */ 1223 jQuery.fn.performCSSTransition = function(css, duration, onFinish, easing, delay){ 1224 duration = duration || 250; 1225 delay = delay || 25; 1226 easing = easing || 'ease-in-out'; 1227 var $this = this, 1228 transition = []; 1229 1230 this.clearPreviousTransitions(); 1231 1232 for (var attr in css) { 1233 if (!css.hasOwnProperty(attr)) continue; 1234 transition.push(attr + ' ' + (duration / 1000) + 's ' + easing); 1235 } 1236 transition = transition.join(', '); 1237 $this.css({ 1238 transition: transition, 1239 '-webkit-transition': transition 1240 }); 1241 1242 // Starting the transition with a slight delay for the proper application of CSS transition properties 1243 var timer1 = setTimeout(function(){ 1244 $this.css(css); 1245 }, delay); 1246 1247 var timer2 = setTimeout(function(){ 1248 $this.resetInlineCSS('transition', '-webkit-transition'); 1249 if (typeof onFinish == 'function') onFinish(); 1250 }, duration + delay); 1251 1252 this.data('animation-timers', timer1 + ',' + timer2); 1253 }; 1254 // Height animations 1255 jQuery.fn.slideDownCSS = function(duration, onFinish, easing, delay){ 1256 if (this.length == 0) return; 1257 var $this = this; 1258 this.clearPreviousTransitions(); 1259 // Grabbing paddings 1260 this.resetInlineCSS('padding-top', 'padding-bottom'); 1261 var timer1 = setTimeout(function(){ 1262 var paddingTop = parseInt($this.css('padding-top')), 1263 paddingBottom = parseInt($this.css('padding-bottom')); 1264 // Grabbing the "auto" height in px 1265 $this.css({ 1266 visibility: 'hidden', 1267 position: 'absolute', 1268 height: 'auto', 1269 'padding-top': 0, 1270 'padding-bottom': 0, 1271 display: 'block' 1272 }); 1273 var height = $this.height(); 1274 $this.css({ 1275 overflow: 'hidden', 1276 height: '0px', 1277 visibility: '', 1278 position: '', 1279 opacity: 0 1280 }); 1281 $this.performCSSTransition({ 1282 height: height + paddingTop + paddingBottom, 1283 opacity: 1, 1284 'padding-top': paddingTop, 1285 'padding-bottom': paddingBottom 1286 }, duration, function(){ 1287 $this.resetInlineCSS('overflow').css('height', 'auto'); 1288 if (typeof onFinish == 'function') onFinish(); 1289 }, easing, delay); 1290 }, 25); 1291 this.data('animation-timers', timer1 + ',null'); 1292 }; 1293 jQuery.fn.slideUpCSS = function(duration, onFinish, easing, delay){ 1294 if (this.length == 0) return; 1295 this.clearPreviousTransitions(); 1296 this.css({ 1297 height: this.outerHeight(), 1298 overflow: 'hidden', 1299 'padding-top': this.css('padding-top'), 1300 'padding-bottom': this.css('padding-bottom'), 1301 opacity: 1 1302 }); 1303 var $this = this; 1304 this.performCSSTransition({ 1305 height: 0, 1306 'padding-top': 0, 1307 'padding-bottom': 0, 1308 opacity: 0 1309 }, duration, function(){ 1310 $this.resetInlineCSS('overflow', 'padding-top', 'padding-bottom', 'opacity').css({ 1311 display: 'none' 1312 }); 1313 if (typeof onFinish == 'function') onFinish(); 1314 }, easing, delay); 1315 }; 1316 // Opacity animations 1317 jQuery.fn.fadeInCSS = function(duration, onFinish, easing, delay){ 1318 if (this.length == 0) return; 1319 this.clearPreviousTransitions(); 1320 this.css({ 1321 opacity: 0, 1322 display: 'block' 1323 }); 1324 this.performCSSTransition({ 1325 opacity: 1 1326 }, duration, onFinish, easing, delay); 1327 }; 1328 jQuery.fn.fadeOutCSS = function(duration, onFinish, easing, delay){ 1329 if (this.length == 0) return; 1330 var $this = this; 1331 this.performCSSTransition({ 1332 opacity: 0 1333 }, duration, function(){ 1334 $this.css('display', 'none'); 1335 if (typeof onFinish == 'function') onFinish(); 1336 }, easing, delay); 1337 }; 1338 // Material design animations 1339 jQuery.fn.showMD = function(duration, onFinish, easing, delay){ 1340 if (this.length == 0) return; 1341 this.clearPreviousTransitions(); 1342 // Grabbing paddings 1343 this.resetInlineCSS('padding-top', 'padding-bottom'); 1344 var paddingTop = parseInt(this.css('padding-top')), 1345 paddingBottom = parseInt(this.css('padding-bottom')); 1346 // Grabbing the "auto" height in px 1347 this.css({ 1348 visibility: 'hidden', 1349 position: 'absolute', 1350 height: 'auto', 1351 'padding-top': 0, 1352 'padding-bottom': 0, 1353 'margin-top': -20, 1354 opacity: '', 1355 display: 'block' 1356 }); 1357 var height = this.height(); 1358 this.css({ 1359 overflow: 'hidden', 1360 height: '0px' 1361 }).resetInlineCSS('visibility', 'position'); 1362 var $this = this; 1363 this.performCSSTransition({ 1364 height: height + paddingTop + paddingBottom, 1365 'margin-top': 0, 1366 'padding-top': paddingTop, 1367 'padding-bottom': paddingBottom 1368 }, duration || 350, function(){ 1369 $this.resetInlineCSS('overflow', 'margin-top', 'padding-top', 'padding-bottom').css('height', 'auto'); 1370 if (typeof onFinish == 'function') onFinish(); 1371 }, easing || 'cubic-bezier(.23,1,.32,1)', delay || 150); 1372 }; 1373 jQuery.fn.hideMD = function(duration, onFinish, easing, delay){ 1374 if (this.length == 0) return; 1375 this.clearPreviousTransitions(); 1376 var $this = this; 1377 this.resetInlineCSS('margin-top'); 1378 this.performCSSTransition({ 1379 opacity: 0 1380 }, duration || 100, function(){ 1381 $this.css({ 1382 display: 'none' 1383 }).resetInlineCSS('opacity'); 1384 if (typeof onFinish == 'function') onFinish(); 1385 }, easing, delay); 1386 }; 1387 // Slide element left / right 1388 var slideIn = function($this, from){ 1389 if ($this.length == 0) return; 1390 $this.clearPreviousTransitions(); 1391 $this.css({width: 'auto', height: 'auto'}); 1392 var width = $this.width(), 1393 height = $this.height(); 1394 $this.css({ 1395 width: width, 1396 height: height, 1397 position: 'relative', 1398 left: (from == 'right') ? '100%' : '-100%', 1399 opacity: 0, 1400 display: 'block' 1401 }); 1402 $this.performCSSTransition({ 1403 left: '0%', 1404 opacity: 1 1405 }, arguments[0] || 250, function(){ 1406 $this.resetInlineCSS('position', 'left', 'opacity', 'display').css({width: 'auto', height: 'auto'}); 1407 }); 1408 }, 1409 slideOut = function($this, to){ 1410 if ($this.length == 0) return; 1411 $this.clearPreviousTransitions(); 1412 $this.css({ 1413 position: 'relative', 1414 left: 0, 1415 opacity: 1 1416 }); 1417 $this.performCSSTransition({ 1418 left: (to == 'left') ? '-100%' : '100%', 1419 opacity: 0 1420 }, arguments[0] || 250, function(){ 1421 $this.css({ 1422 display: 'none' 1423 }).resetInlineCSS('position', 'left', 'opacity'); 1424 }); 1425 }; 1426 jQuery.fn.slideOutLeft = function(){ 1427 slideOut(this, 'left'); 1428 }; 1429 jQuery.fn.slideOutRight = function(){ 1430 slideOut(this, 'right'); 1431 }; 1432 jQuery.fn.slideInLeft = function(){ 1433 slideIn(this, 'left'); 1434 }; 1435 jQuery.fn.slideInRight = function(){ 1436 slideIn(this, 'right'); 1437 }; 1438}();
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.