PageSourceSearch

https://com6-interactive.fr/wp-content/themes/Impreza/framework/js/us.core.js?ver=3.5

js com6-interactive.fr collected 2026-10-02 18:32:07 UTC 46,280 bytes, 1,453 lines download raw bytes

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

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.