(function($) { 'use strict'; /******************************** ********** plugins************** *******************************/ /** * search screen plugin * @param {object} options */ function Search(options) { this.options = $.extend({ container: null, hideOnClickOutside: false, menuActiveClass: 'nav-active', menuOpener: '.nav-opener', menuDrop: '.nav-drop', toggleEvent: 'click.search', outsideClickEvent: 'click.search touchstart.search pointerdown.search MSPointerDown.search' }, options); this.initStructure(); this.attachEvents(); } Search.prototype = { initStructure: function() { this.page = $('html'); this.container = $(this.options.container); this.opener = this.container.find(this.options.menuOpener); this.drop = this.container.find(this.options.menuDrop); }, attachEvents: function() { var self = this; if (activateResizeHandler) { activateResizeHandler(); activateResizeHandler = null; } this.outsideClickHandler = function(e) { //console.log(e); if (self.isOpened()) { var target = $(e.target); if (!target.closest(self.opener).length && !target.closest(self.drop).length) { self.hide(); } } }; this.openerClickHandler = function(e) { e.preventDefault(); self.toggle(); }; this.opener.on(this.options.toggleEvent, this.openerClickHandler); }, isOpened: function() { return this.container.hasClass(this.options.menuActiveClass); }, show: function() { this.container.addClass(this.options.menuActiveClass); if (this.options.hideOnClickOutside) { this.page.on(this.options.outsideClickEvent, this.outsideClickHandler); } }, hide: function() { this.container.removeClass(this.options.menuActiveClass); if (this.options.hideOnClickOutside) { this.page.off(this.options.outsideClickEvent, this.outsideClickHandler); } }, toggle: function() { if (this.isOpened()) { this.hide(); } else { this.show(); } }, destroy: function() { this.container.removeClass(this.options.menuActiveClass); this.opener.off(this.options.toggleEvent, this.clickHandler); this.page.off(this.options.outsideClickEvent, this.outsideClickHandler); } }; var activateResizeHandler = function() { var win = $win, doc = $('html'), resizeClass = 'resize-active', flag, timer; var removeClassHandler = function() { flag = false; doc.removeClass(resizeClass); }; var resizeHandler = function() { if (!flag) { flag = true; doc.addClass(resizeClass); } clearTimeout(timer); timer = setTimeout(removeClassHandler, 500); }; win.on('resize orientationchange', resizeHandler); }; $.fn.search = function(options) { return this.each(function() { var params = $.extend({}, options, { container: this }), instance = new Search(params); $.data(this, 'Search', instance); }); }; /** * image adjustment plugin */ var ImageStretcher = { getDimensions: function(data) { // calculate element coords to fit in mask var ratio = data.imageRatio || (data.imageWidth / data.imageHeight), slideWidth = data.maskWidth, slideHeight = slideWidth / ratio; if (slideHeight < data.maskHeight) { slideHeight = data.maskHeight; slideWidth = slideHeight * ratio; } return { width: slideWidth, height: slideHeight, top: (data.maskHeight - slideHeight) / 2, left: (data.maskWidth - slideWidth) / 2 }; }, getRatio: function(image) { if (image.prop('naturalWidth')) { return image.prop('naturalWidth') / image.prop('naturalHeight'); } else { var img = new Image(); img.src = image.prop('src'); return img.width / img.height; } }, imageLoaded: function(image, callback) { var self = this; var loadHandler = function() { callback.call(self); }; if (image.prop('complete')) { loadHandler(); } else { image.one('load', loadHandler); } }, resizeHandler: function() { var self = this; $.each(this.imgList, function(index, item) { if (item.image.prop('complete')) { self.resizeImage(item.image, item.container); } }); }, resizeImage: function(image, container) { this.imageLoaded(image, function() { var styles = this.getDimensions({ imageRatio: this.getRatio(image), maskWidth: container.width(), maskHeight: container.height() }); image.css({ width: styles.width, height: styles.height, marginTop: styles.top, marginLeft: styles.left }); }); }, add: function(options) { var container = $(options.container ? options.container : window), image = typeof options.image === 'string' ? container .find(options.image) : $(options.image); // resize image this.resizeImage(image, container); // add resize handler once if needed if (!this.win) { this.resizeHandler = $.proxy(this.resizeHandler, this); this.imgList = []; this.win = $win; this.win.on('resize orientationchange', this.resizeHandler); } // store item in collection this.imgList.push({ container: container, image: image }); } }; /** * open close plugin * @param {object} options */ function OpenClose(options) { this.options = $.extend({ addClassBeforeAnimation: true, hideOnClickOutside: false, activeClass: 'active', opener: '.opener', slider: '.slide', animSpeed: 400, effect: 'fade', event: 'click' }, options); this.init(); } OpenClose.prototype = { init: function() { if (this.options.holder) { this.findElements(); this.attachEvents(); this.makeCallback('onInit', this); } }, findElements: function() { this.holder = $(this.options.holder); this.opener = this.holder.find(this.options.opener); this.slider = this.holder.find(this.options.slider); }, attachEvents: function() { // add handler var self = this; this.eventHandler = function(e) { e.preventDefault(); if (self.slider.hasClass(slideHiddenClass)) { self.showSlide(); } else { self.hideSlide(); } }; self.opener.bind(self.options.event, this.eventHandler); // hover mode handler if (self.options.event === 'over') { self.opener.bind('mouseenter', function() { if (!self.holder.hasClass(self.options.activeClass)) { self.showSlide(); } }); self.holder.bind('mouseleave', function() { self.hideSlide(); }); } // outside click handler self.outsideClickHandler = function(e) { if (self.options.hideOnClickOutside) { var target = $(e.target); if (!target.is(self.holder) && !target.closest(self.holder) .length) { self.hideSlide(); } } }; // set initial styles if (this.holder.hasClass(this.options.activeClass)) { $doc.bind('click touchstart', self.outsideClickHandler); } else { this.slider.addClass(slideHiddenClass); } }, showSlide: function() { var self = this; if (self.options.addClassBeforeAnimation) { self.holder.addClass(self.options.activeClass); } self.slider.removeClass(slideHiddenClass); $doc.bind('click touchstart', self.outsideClickHandler); self.makeCallback('animStart', true); toggleEffects[self.options.effect].show({ box: self.slider, speed: self.options.animSpeed, complete: function() { if (!self.options.addClassBeforeAnimation) { self.holder.addClass(self.options.activeClass); } self.makeCallback('animEnd', true); } }); }, hideSlide: function() { var self = this; if (self.options.addClassBeforeAnimation) { self.holder.removeClass(self.options.activeClass); } $doc.unbind('click touchstart', self.outsideClickHandler); self.makeCallback('animStart', false); toggleEffects[self.options.effect].hide({ box: self.slider, speed: self.options.animSpeed, complete: function() { if (!self.options.addClassBeforeAnimation) { self.holder.removeClass(self.options.activeClass); } self.slider.addClass(slideHiddenClass); self.makeCallback('animEnd', false); } }); }, destroy: function() { this.slider.removeClass(slideHiddenClass) .css({ display: '' }); this.opener.unbind(this.options.event, this.eventHandler); this.holder.removeClass(this.options.activeClass) .removeData( 'OpenClose'); $doc.unbind('click touchstart', this.outsideClickHandler); }, makeCallback: function(name) { if (typeof this.options[name] === 'function') { var args = Array.prototype.slice.call(arguments); args.shift(); this.options[name].apply(this, args); } } }; // add stylesheet for slide on DOMReady var slideHiddenClass = 'js-slide-hidden'; (function() { var tabStyleSheet = $('