diff --git a/README.md b/README.md index a980583..d953d5b 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,7 @@ Have a bug or a request? Please open an issue [here](https://github.com/Themezly ## Credits jQuery Easing, Copyright 2008 George McGinley Smith -Licenses: BSD +Licenses: Open source under the 3-Clause BSD License Source: http://gsgd.co.uk/sandbox/jquery/easing/ Isotope, Copyright 2015 Metafizzy @@ -185,4 +185,15 @@ Source: https://necolas.github.io/normalize.css/ Font Awesome icons, Copyright Dave Gandy License: SIL Open Font License, version 1.1. -Source: http://fontawesome.io/ \ No newline at end of file +Source: http://fontawesome.io/ + +## Images + +License: Creative Commons CC0 +Source: https://stocksnap.io + +* https://stocksnap.io/photo/J2KJ6CNZTC +* https://stocksnap.io/photo/0PTTRQX5L1 +* https://stocksnap.io/photo/NOFSYE1P0V +* https://stocksnap.io/photo/BBA96CDDCD +* https://stocksnap.io/photo/O9V8SGL6FD \ No newline at end of file diff --git a/assets/css/thz-layout.css b/assets/css/thz-layout.css index a844853..5ab9f83 100644 --- a/assets/css/thz-layout.css +++ b/assets/css/thz-layout.css @@ -63,7 +63,8 @@ # Panels # Thz Sliders Extension # Thz Sections slider - # Site offline + # Site offline + # Customizer Hero # Clearings @@ -4061,6 +4062,32 @@ html.searchOpen:not(.canvasOpen) .thz-body-box { opacity:0.8; } +/* ============================================ + # Customizer Hero + ============================================ */ + +#thz-customizer-hero{ + padding:14vw 0; + text-align:center; + background:#fafafa; +} +#thz-customizer-hero .thz-heading-before{ + display:block; + font-weight: 600; + letter-spacing:1px; + color: #ccc; + text-transform: uppercase; + margin:0 0 15px; +} +#thz-customizer-hero .thz-heading-title{ + font-size:58px; + text-align: center; + margin:0 auto; +} +#thz-customizer-hero .thz-heading-sub{ + font-size:16px; +} + /* ============================================ # Clearings ============================================ */ diff --git a/assets/images/placeholders/1.jpg b/assets/images/placeholders/1.jpg index cff3356..1a96aa5 100644 Binary files a/assets/images/placeholders/1.jpg and b/assets/images/placeholders/1.jpg differ diff --git a/assets/images/placeholders/2.jpg b/assets/images/placeholders/2.jpg index ef421f5..b2a0c6b 100644 Binary files a/assets/images/placeholders/2.jpg and b/assets/images/placeholders/2.jpg differ diff --git a/assets/images/placeholders/3.jpg b/assets/images/placeholders/3.jpg index 0285d0b..6bafcc3 100644 Binary files a/assets/images/placeholders/3.jpg and b/assets/images/placeholders/3.jpg differ diff --git a/assets/images/placeholders/4.jpg b/assets/images/placeholders/4.jpg index bd38c7f..ad85cf2 100644 Binary files a/assets/images/placeholders/4.jpg and b/assets/images/placeholders/4.jpg differ diff --git a/assets/images/placeholders/5.jpg b/assets/images/placeholders/5.jpg index 6e6f00b..f8a8eed 100644 Binary files a/assets/images/placeholders/5.jpg and b/assets/images/placeholders/5.jpg differ diff --git a/assets/images/placeholders/thumb.jpg b/assets/images/placeholders/thumb.jpg index 196101f..a82107f 100644 Binary files a/assets/images/placeholders/thumb.jpg and b/assets/images/placeholders/thumb.jpg differ diff --git a/assets/js/dev/ThzCountdown.js b/assets/js/dev/ThzCountdown.js new file mode 100644 index 0000000..017332e --- /dev/null +++ b/assets/js/dev/ThzCountdown.js @@ -0,0 +1,112 @@ + /** + * @plugin ThzCountdown + * @version 1.0.0 + * @package Thz Framework + * @copyright Copyright(C) since 2015 Themezly.com. All Rights Reserved. + * @author Themezly + * @license MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * @websites http://www.themezly.com | http://www.youjoomla.com + */ +(function($) { + $.fn.ThzCountdown = function(options, callback) { + + + return this.each(function() { + + var settings = JSON.parse($(this).attr('data-settings')); + + // date is not set + if (!settings.date) { + $.error('Date is not defined.'); + } + + // incorrect date + if (!Date.parse(settings.date)) { + $.error('Please insert folowing date format; 12/24/2012 12:00:00.'); + } + + + // Save container + var container = $(this); + + /** + * Change client's local date to match offset timezone + * @return {Object} Fixed Date object. + */ + + var currentDate = function() { + // get client's current date + var date = new Date(); + + // turn date to utc + var utc = date.getTime() + (date.getTimezoneOffset() * 60000); + + // set new Date object + var new_date = new Date(utc + (3600000 * settings.offset)); + + return new_date; + }; + + /** + * Main countdown function that calculates everything + */ + function countdown() { + var target_date = new Date(settings.date), // set target date + current_date = currentDate(); // get fixed current date + + // difference of dates + var difference = target_date - current_date; + + // if difference is negative than it's pass the target date + if (difference < 0) { + // stop timer + clearInterval(interval); + + if (callback && typeof callback === 'function') callback(); + + return; + } + + // basic math variables + var _second = 1000, + _minute = _second * 60, + _hour = _minute * 60, + _day = _hour * 24; + + // calculate dates + var days = Math.floor(difference / _day), + hours = Math.floor((difference % _day) / _hour), + minutes = Math.floor((difference % _hour) / _minute), + seconds = Math.floor((difference % _minute) / _second); + + // based on the date change the reference text + var text_days = (days === 1) ? settings.day : settings.days, + text_hours = (hours === 1) ? settings.hour : settings.hours, + text_minutes = (minutes === 1) ? settings.minute : settings.minutes, + text_seconds = (seconds === 1) ? settings.second : settings.seconds; + + // fix dates so that it will show two digits + days = (String(days).length >= 2) ? days : '0' + days; + hours = (String(hours).length >= 2) ? hours : '0' + hours; + minutes = (String(minutes).length >= 2) ? minutes : '0' + minutes; + seconds = (String(seconds).length >= 2) ? seconds : '0' + seconds; + + // set to DOM + container.find('.thz-cd-d').text(days); + container.find('.thz-cd-h').text(hours); + container.find('.thz-cd-m').text(minutes); + container.find('.thz-cd-s').text(seconds); + + container.find('.thz-cd-dt').text(text_days); + container.find('.thz-cd-ht').text(text_hours); + container.find('.thz-cd-mt').text(text_minutes); + container.find('.thz-cd-st').text(text_seconds); + } + // start + + var interval = setInterval(countdown, 1000); + }); + + }; + +})(jQuery); \ No newline at end of file diff --git a/assets/js/dev/ThzGetTransform.js b/assets/js/dev/ThzGetTransform.js new file mode 100644 index 0000000..46d28af --- /dev/null +++ b/assets/js/dev/ThzGetTransform.js @@ -0,0 +1,112 @@ +/** + * @package Thz Get Transform Decompose Matrix + * @copyright Copyright(C) FT Web Studio Inc since 2015. All Rights Reserved. + * @author Themezly + * @license MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * @websites http://www.themezly.com | http://www.youjoomla.com + */ +(function($) { + + $.fn.ThzGetTransform = function(options) { + + var matrix = this.is(":visible") ? this.css( 'transform' ) : this.actual( 'transform' ); + + if( matrix == 'none' ){ + return; + } + + var a = matrix.split('(')[1].split(')')[0].split(','); + + var angle = Math.atan2(a[1], a[0]), + denom = Math.pow(a[0], 2) + Math.pow(a[1], 2), + scaleX = Math.sqrt(denom), + scaleY = (a[0] * a[3] - a[2] * a[1]) / scaleX, + skewX = Math.atan2(a[0] * a[2] + a[1] * a[3], denom); + var data = { + angle: angle / (Math.PI / 180), // this is rotation angle in degrees + scaleX: scaleX, // scaleX factor + scaleY: scaleY, // scaleY factor + skewX: skewX / (Math.PI / 180), // skewX angle degrees + skewY: 0, // skewY angle degrees + translateX: a[4], // translation point x + translateY: a[5] // translation point y + }; + + function ThzHas3d() { + + if (!window.getComputedStyle) { + return false; + } + + var el = document.createElement('p'), + has3d, + transforms = { + 'webkitTransform':'-webkit-transform', + 'OTransform':'-o-transform', + 'msTransform':'-ms-transform', + 'MozTransform':'-moz-transform', + 'transform':'transform' + }; + + // Add it to the body to get the computed style. + document.body.insertBefore(el, null); + + for (var t in transforms) { + if (el.style[t] !== undefined) { + el.style[t] = "translate3d(1px,1px,1px)"; + has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); + } + } + + document.body.removeChild(el); + + return (has3d !== undefined && has3d.length > 0 && has3d !== "none"); + } + + + + + if( options.current ){ + + var current = []; + + if( data.angle != 0 ){ + current.push('rotate('+data.angle+'deg)'); + } + + var scale = parseFloat(data.scaleX) + parseFloat(data.scaleY); + if( scale.toFixed(2) != 2 ){ + current.push('scale('+data.scaleX+','+data.scaleY+')'); + } + + var skew = parseFloat(data.skewX) + parseFloat(data.skewY); + if( skew != 0){ + current.push('skew('+data.skewX+','+data.skewY+')'); + } + + if( data.translateX != 0 || data.translateY != 0 ){ + + var $translate = ThzHas3d() ? 'translate3d('+data.translateY+','+data.translateX+',0px)' : 'translate('+data.translateY+','+data.translateX+')' ; + + current.push($translate); + } + + if( current.length > 0){ + + return current.join(' '); + + }else{ + + return false; + + } + + }else{ + + return data; + + } + + }; + +})(jQuery); diff --git a/assets/js/dev/ThzInfinity.js b/assets/js/dev/ThzInfinity.js new file mode 100644 index 0000000..4421ecf --- /dev/null +++ b/assets/js/dev/ThzInfinity.js @@ -0,0 +1,132 @@ +/** + * @package ThzInfinity + * @copyright Copyright(C) FT Web Studio Inc since 2015. All Rights Reserved. + * @author Themezly + * @license MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * @websites http://www.themezly.com | http://www.youjoomla.com + */ +(function($) { + + $.fn.ThzInfinity = function(options) { + + var defaults = { + duration: 60, + direction: 'up', + onmobile:0 + }; + var self = this, + options = $.extend({}, defaults, options), + Thz3d = ThzHas3d(); + + function Thzinit() { + + self.each(function(index, el) { + + var $this = $(el); + var $c_tr = $this.ThzGetTransform({ + current:true + }); + options.duration = $this.attr('data-thzinf-duration') ? $this.data('thzinf-duration') : options.duration; + options.direction = $this.attr('data-thzinf-direction') ? $this.data('thzinf-direction') : options.direction; + options.onmobile = $this.attr('data-thzinf-onmobile') ? $this.data('thzinf-onmobile') :options.onmobile; + options.c_tr = $c_tr ? ' ' + $c_tr : ''; + + // hide on mobiles | if set to 1 than show + if(navigator.userAgent.match(/Mobi/) && options.onmobile === 0) return; + + var direction = options.direction; + var current = 0; + var width = $this.outerWidth(); + var height = $this.outerHeight(); + + function bgscroll(){ + + if (!$this.parent().ThzIsVisible()) return; + + + if(direction == 'right' || direction == 'down'){ + current -= -1; + }else{ + current -= 1; + } + + var mutliplier = direction == 'left'|| direction == 'up' ? -1 : 1; + var pauseX = (width /2) * mutliplier; + var pauseY = (height / 2) * mutliplier; + var pause = direction == 'left'|| direction == 'right' ? pauseX : pauseY; + + + if(current == pause.toFixed(0)){ + current = 0; + } + + var operator = 'px'; + var tX = direction == 'left' || direction == 'right' ? current : 0; + var tY = direction == 'up' || direction == 'down' ? current : 0; + + + $this.css({ + 'transform': ThzTranslate(tX+operator,tY+operator) + options.c_tr + }); + + + } + + setInterval(bgscroll, options.duration); + + }); + + } + + // check for transform + function ThzHas3d() { + + if (!window.getComputedStyle) { + return false; + } + + var el = document.createElement('p'), + has3d, + transforms = { + 'webkitTransform':'-webkit-transform', + 'OTransform':'-o-transform', + 'msTransform':'-ms-transform', + 'MozTransform':'-moz-transform', + 'transform':'transform' + }; + + // Add it to the body to get the computed style. + document.body.insertBefore(el, null); + + for (var t in transforms) { + if (el.style[t] !== undefined) { + el.style[t] = "translate3d(1px,1px,1px)"; + has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); + } + } + + document.body.removeChild(el); + + return (has3d !== undefined && has3d.length > 0 && has3d !== "none"); + } + + + // translate based on transform check. fallback to 2d + function ThzTranslate(x,y){ + + if(Thz3d){ + return 'translate3d('+x+','+y+',0px)'; + } + + return 'translate('+x+','+y+')'; + + } + + + return Thzinit(); + + + }; + + +})(jQuery); diff --git a/assets/js/dev/ThzIsVisible.js b/assets/js/dev/ThzIsVisible.js new file mode 100644 index 0000000..1cad314 --- /dev/null +++ b/assets/js/dev/ThzIsVisible.js @@ -0,0 +1,18 @@ +/** + * @package Thz IsVisible + * @copyright Copyright(C) FT Web Studio Inc since 2015. All Rights Reserved. + * @author Themezly + * @license MIT + * @websites http://www.themezly.com | http://www.youjoomla.com + */ +(function($) { + $.fn.ThzIsVisible = function(add){ + + var element = this.get(0); + var bounds = element.getBoundingClientRect(); + + if(add == null || typeof add == 'undefined') add = 0; + + return bounds.top - add < window.innerHeight && bounds.bottom + add > 0; + } +})(jQuery); \ No newline at end of file diff --git a/assets/js/dev/ThzMasonry.js b/assets/js/dev/ThzMasonry.js new file mode 100644 index 0000000..b62fee0 --- /dev/null +++ b/assets/js/dev/ThzMasonry.js @@ -0,0 +1,739 @@ +/** + * @package ThzFramework + * @copyright Copyright(C) since 2007 Themezly.com. All Rights Reserved. + * @author Themezly + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 only + * @websites http://www.themezly.com | http://www.youjoomla.com + */ +;(function($, window, document, undefined) { + + "use strict"; + + var pluginName = "ThzMasonry", + defaults = { + + masonry: true + }; + + function Plugin(element, options) { + this.element = element; + + this.settings = $.extend({}, defaults, options); + this._defaults = defaults; + this._name = pluginName; + this.init(); + } + + $.extend(Plugin.prototype, { + init: function() { + + var self = this; + + this.grid = $(self.element).find('.thz-items-grid'); + + if (this.grid.length < 1) { + $(self.element).addClass('thz-items-grid-loaded thz-items-grid-missing'); + return; + } + + this.more_holder = $(self.element).find('.thz-items-more'); + this.more_link = this.more_holder.find('a'); + this.scroll_to = $(self.element).find('.thz-items-scrollto'); + this.pagination = this.grid.attr('data-pagination'); + this.display_mode = this.grid.attr('data-display-mode'); + this.layout_type = this.grid.attr('data-layout-type'); + this.layoutMode = this.grid.attr('data-isotope-mode') ? this.grid.attr('data-isotope-mode') :'packery'; + + this.loadAgain = true; + this.processing; + + + + self.ThzCheckCats(); + + if (self.settings.masonry === true) { + + self.ThzMasonryLoad(); + + }else{ + + self.ThzPozLoader(); + $(window).on('resize', function() { + self.ThzPozLoader(); + }); + + } + + self.ThzMasonryMore(); + self.ThzMasonryCats(); + self.ThzMasonryAjaxPagination(); + + }, + + ThzPozLoader: function (){ + + var self = this; + var $loading = $(self.element).find('.thz-items-loading'); + + if($loading.length > 0){ + + var height = $(self.element).outerHeight(); + var topmax = height - 200; + + $loading.css({ + 'bottom':'auto', + 'top':topmax + }); + } + + + }, + + ThzWindowSize: function () { + + var self = this; + + var e = window, + a = 'inner'; + if (!('innerWidth' in window)) { + a = 'client'; + e = document.documentElement || document.body; + } + return { + width: e[a + 'Width'], + height: e[a + 'Height'] + }; + }, + + ThzMasnorySizeItems: function($grid) { + + var self = this; + + + if($grid){ + + $grid = $grid; + + }else{ + + $grid = self.grid; + } + + var $window_w = self.ThzWindowSize().width; + var $container_w = $grid.outerWidth(); + var $sizer_w = $grid.find('.thz-items-sizer').outerWidth(); + var $columns = Math.round( $container_w / $sizer_w ); + var $minWidth = $grid.attr('data-minwidth') ? $grid.attr('data-minwidth') : false; + var layoutMode = $grid.attr('data-isotope-mode') ? $grid.attr('data-isotope-mode') :'packery'; + + if($minWidth && ( $sizer_w < $minWidth ) ){ + + $columns = Math.floor( $container_w / $minWidth); + + } + + if( layoutMode =='vertical' ){ + + $columns = 1; + } + + if($window_w < 980 && $window_w > 767){ + + $columns = $columns > 2 ? 2 : $columns; + + + } else if($window_w < 768){ + + $columns = $columns > 1 ? 1 : $columns; + + } + + var $items_w = Math.floor( $container_w / $columns ); + var $grid_diff = $container_w - ($items_w * $columns); + var $findslick = $grid.find('.thz-slick-active'); + + if($grid_diff > 0 && $('.thz-wrapper').hasClass('thz-layout-boxed')){ + $grid.css('left',$grid_diff / 2); + } + + + + $grid.find('.thz-grid-item').each(function(index, element) { + + var $this = $(this); + var $item_size = $items_w; + var $multiplier = $columns > 1 ? 2 : 1; + + if($this.hasClass('thz-item-metro-double') || $this.hasClass('thz-item-metro-landscape')){ + + $item_size = $items_w * $multiplier ; + } + + $this.css('width',$item_size); + + self.ThzAdjustMetros($grid,$this,$item_size,$columns); + + $this.find('.mejs-video,.mejs-audio').each(function() { + $(this).trigger('resize'); + }); + + if( !$this.hasClass('size-set') ){ + $this.addClass('size-set'); + } + + }); + + if($findslick.length > 0){ + setTimeout(function() { + $grid.isotope('layout'); + }, 400); + } + }, + + ThzAdjustMetros: function($grid,$item,$size,$columns){ + + var self = this; + + if( $grid.attr('data-layout-type') == 'metro' ){ + + var $item_in = $item.find('.thz-grid-item-in'); + var $media_h = $item.find('.thz-media-custom-size'); + var $intro_height = $item_in.outerHeight() - $media_h.outerHeight(); + var $new_height = $item_in.outerWidth(); + var $gap = parseInt( $item.css('padding-left') ); + var $multiplier = $columns > 1 ? 2 : 1; + + if( $item.hasClass('thz-item-metro-landscape') ){ + + $new_height = ( $new_height / $multiplier ) - ( $gap / 2 ); + } + + if( $item.hasClass('thz-item-metro-portrait') ){ + + $new_height = $new_height * $multiplier + $gap; + } + + $item_in.css('height',$new_height); + + $media_h.css({ + + 'height':$new_height - $intro_height, + 'padding-bottom':'0px' + + }); + + } + }, + + ThzMasonryLoad: function() { + + var self = this; + self.ThzMasnorySizeItems(); + Isotope.prototype.onresize = function() { + self.ThzMasnorySizeItems($(this.element)); + this.resize(); + }; + + self.grid.isotope({ + itemSelector: '.thz-grid-item', + layoutMode: self.layoutMode, + transitionDuration: '0.4s', + masonry: { + columnWidth: '.thz-items-sizer', + gutterWidth: 0, + }, + packery: { + gutter: 0 + }, + + hiddenStyle: { + opacity: 0 + }, + visibleStyle: { + opacity: 1 + }, + }); + + self.grid.on('arrangeComplete', function(event, filteredItems) { + + $(document).ThzSite('thzAnimations', self.grid.find('.thz-grid-item:not(.thz-animate-parent-done) .thz-isotope-animate')); + + }); + + if (self.layout_type == 'masonry') { + + self.grid.imagesLoaded().always(function() { + + self.grid.isotope('layout'); + + var runanimations = self.grid.find('.thz-isotope-animate:not(.thz-animate)'); + + if (runanimations.length > 0) { + runanimations.addClass('thz-animate'); + } + + $(self.element).addClass('thz-items-grid-loaded'); + + if (runanimations.length > 0) { + $(document).ThzSite('thzAnimations', runanimations); + } + + }); + + } else { + self.grid.imagesLoaded({ + background: '.thz-items-grid-image' + + }, function() { + + self.grid.isotope('layout'); + + var runanimations = self.grid.find('.thz-isotope-animate:not(.thz-animate)'); + + if (runanimations.length > 0) { + runanimations.addClass('thz-animate'); + } + + $(self.element).addClass('thz-items-grid-loaded'); + + if (runanimations.length > 0) { + $(document).ThzSite('thzAnimations', runanimations); + } + + }); + } + + }, + + ThzCheckCats: function() { + + + var self = this; + + $(self.element).find('.thz-items-grid-categories a').each(function(index, element) { + + + var $cat = $(element).attr('data-filter-value'); + + if ($cat != '.category_all') { + + if (self.grid.find('.thz-grid-item' + $cat).length == 0) { + + $(element).parent().addClass('hide-cat'); + + } else { + + $(element).parent().removeClass('hide-cat'); + } + } + + }); + + }, + + ThzMasonryCats: function() { + + var self = this; + + $(self.element).find('.thz-items-grid-categories a').on('click', function(e) { + + e.stopPropagation(); + e.preventDefault(); + + var $this = $(this); + if ($this.hasClass('active')) { + return; + } + var $selector = $this.attr('data-filter-value'); + var $catItems = self.grid.find($selector); + + if ($catItems.length < 1) { + return; + } + + $this.parents('.thz-items-grid-categories').find('a.active').removeClass('active'); + $this.addClass('active'); + + self.grid.isotope({ + filter: $selector + }).isotope('layout'); + + self.ThzMasnorySizeItems(); + self.grid.isotope('layout'); + + }); + + }, + + ThzMasonryAjaxPagination: function() { + + var self = this; + + + if (!$(self.element).hasClass('thz-posts-holder')) { + return; + } + + var $links = $(self.element).find("a.thz-pagination-button"); + var $id = $(self.element).attr('id'); + + $($links).on('click', function(e) { + e.preventDefault(); + + var $href = $(this).attr('href'); + + $('html, body').animate({ + scrollTop: $(self.element).offset().top, + }, 800, 'easeInOutCubic'); + + $(self.element).addClass('loading-items').find(".thz-items-loading").fadeIn(500,function(){ + $(this).css({ + 'bottom':'auto', + 'top':'40%' + }); + }); + + + $.ajax({ + url: $href + }).done(function(data) { + + var $newgrid = $('
').append($(data).find('#' + $id)).html(); + var newItems = $($newgrid).find('.thz-grid-item'); + var newPagination = $($newgrid).find('.thz-pagination-nav'); + var newFilter = $($newgrid).find('.thz-items-grid-categories'); + + + $(self.element).find('.thz-grid-item').addClass('thz-zoomOut'); + + setTimeout(function() { + + + if (self.grid.hasClass('thz-timeline-double')) { + + self.grid.find('.thz-timeline-left').html(''); + self.grid.find('.thz-timeline-right').html(''); + + }else{ + + $(self.grid).html('
'); + } + + self.ThzMasonryNewitems(newItems, 300); + + $(self.element).find('.thz-pagination-nav').replaceWith($(newPagination)); + + if (!self.grid.hasClass('thz-grid-timeline')) { + $(self.element).find('.thz-items-grid-categories').replaceWith($(newFilter)); + self.ThzMasonryCats(); + self.ThzCheckCats(); + } + + + self.ThzMasonryAjaxPagination(); + + $(self.element).find(".thz-items-loading").fadeOut(400,function(){ + $(self.element).removeClass('loading-items'); + }); + + + }, 280); + + + + }); + + }); + }, + + ThzMasonryMore: function() { + + var self = this; + + if (self.pagination == "click") { + self.more_link.on('click', function(e) { + e.preventDefault(); + + if ($(this).hasClass('loading-posts')) { + return; + } + self.ThzMasonryAjax(true); + $(this).addClass('loading-posts'); + $('body').removeClass('posts-loaded'); + + }); + } + if (self.pagination == "scroll") { + + $(document).scroll(function(e) { + + var $last = self.grid.find(".thz-grid-item:last"); + if (!self.processing && self.ThzLastInView($last)) { + self.processing = true; + self.ThzMasonryAjax(); + } + + }); + + } + + }, + + ThzLastInView: function(el) { + + var self = this; + var docViewTop = $(window).scrollTop(); + var docViewBottom = docViewTop + $(window).height(); + + var elTop = $(el).offset().top; + var elBottom = elTop + $(el).height(); + + return ((elBottom <= docViewBottom) && (elTop >= docViewTop)); + }, + + ThzMasonryAjax: function( load_by_cat ) { + + var self = this; + var maxpages = self.grid.attr('data-maxpages'); + + if (!self.loadAgain || maxpages < 2) { + + return; + } + + $(self.element).find(".thz-items-loading").fadeIn(500); + + var currentItems = $(self.element).find(".thz-grid-item").map(function() { + return $(this).data("itemid"); + }).get(); + + var catID = self.grid.attr('data-catid'); + var itemsLoad = self.grid.attr('data-itemsload'); + var active_cat = load_by_cat ? $(self.element).find('.thz-posts-filter-link.active').attr('data-filter-value') : false; + var postType = self.grid.attr('data-posttype'); + var taxOnomy = self.grid.attr('data-taxonomy'); + var order = self.grid.attr('data-order'); + var orderby = self.grid.attr('data-orderby'); + var layouthook = self.grid.attr('data-layouthook'); + var postauthor = self.grid.attr('data-postauthor'); + var sqlhook = self.grid.attr('data-sqlhook'); + var shortcodeid = self.grid.attr('data-shortcodeid'); + var objectid = self.grid.attr('data-objectid'); + var preview_atts = self.grid.data('atts') ? JSON.stringify(self.grid.data('atts')) : false; + var useaction = shortcodeid != undefined ? 'thz_shortcode_posts' : 'thz_get_posts_action'; + + return $.ajax({ + type: 'post', + url: thzsite.ajaxurl, + data: { + action: useaction, + nonce: thzsite.masonrynonce, + category: catID, + itemsload: itemsLoad, + posttype: postType, + taxonomy: taxOnomy, + order: order, + orderby: orderby, + current: JSON.stringify(currentItems), + layouttype: self.layout_type, + layouthook: layouthook, + postauthor: postauthor, + sqlhook: sqlhook, + shortcodeid: shortcodeid, + objectid: objectid, + preview_atts: preview_atts + }, + success: function(response) { + + var $items = $(response); + var $items_count = $items.find('.thz-grid-item-in').length; + + + + if (($items_count > itemsLoad) && itemsLoad != -1 ) { + + var $new_items = $items.not(':last'); + + } else { + + self.loadAgain = false; + var $new_items = $items; + self.more_holder.fadeOut(400); + + } + + + self.ThzMasonryNewitems($new_items, 0, active_cat); + self.ThzAddCats($new_items); + + $(self.element).find(".thz-items-loading").fadeOut(400); + + }, + complete: function() { + self.processing = false; + self.more_link.removeClass('loading-posts'); + $('body').addClass('posts-loaded'); + }, + + }); + + }, + + ThzMasonryItemsEffects: function(newItems, timeout) { + + var self = this; + + var newslick = newItems.find('.thz-slick-active'); + + if (newslick.length > 0) { + $(document).ThzSite('thzSlick', newslick); + } + + var inactiveslick = newItems.find('.thz-slick-inactive'); + + if (inactiveslick.length > 0) { + var medias = inactiveslick.find('.thz-slick-media'); + + + if (medias.length > 0) { + medias.mediaelementplayer(); + } + + } + + var newmedias = newItems.find('.thz-media'); + + if (newmedias.length > 0) { + newmedias.mediaelementplayer(); + } + + var hasanimaton = newItems.find('.thz-isotope-animate'); + + if (hasanimaton.length > 0) { + + hasanimaton.addClass('thz-animate'); + } + + if (self.settings.masonry === true) { + self.grid.isotope('layout'); + } + + $(document).ThzSite('thzGridItemEffects', newItems); + + + setTimeout(function() { + $(document).ThzSite('thzAnimations', hasanimaton); + }, timeout); + + self.ThzCheckCats(); + }, + + + + ThzAddCats : function (newItems){ + + var self = this; + + if( $('.thz-items-grid-categories').length < 1){ + return; + } + + newItems.each(function(index, element) { + + var $this = $(element); + var $get_data = $this.data('cats').replace(/("\;)/g,"\""); + + if($get_data.length > 0 ){ + + var $cat_data = JSON.parse( $get_data ); + + $.each($cat_data, function ($class,$title){ + + if( !$("[data-filter-value='." + $class + "']")[0] ){ + + var $li ='
  • '; + $li +=''; + $li += $title; + $li +=''; + $li +='
  • '; + + $('.thz-items-grid-categories').append($li); + + } + }); + } + + }); + + self.ThzMasonryCats(); + + }, + + + ThzMasonryNewitems: function(newItems, timeout, active_cat) { + + var self = this; + var current_category = active_cat ? active_cat.replace('.','') : false; + + if( active_cat && active_cat !='category_all' ){ + newItems = newItems.sort(function (a, b) { + return $(b).hasClass(current_category) - $(a).hasClass(current_category); + }); + } + + newItems.imagesLoaded(function() { + + newItems.find('.thz-grid-item-in').addClass('thz-new-grid-item'); + + if (self.settings.masonry === true) { + + self.grid.append(newItems).isotope('appended', newItems); + self.ThzMasnorySizeItems(); + + } else { + + if (self.grid.hasClass('thz-timeline-double')) { + + newItems.each(function(index, element) { + + if ($(element).hasClass('thz-timeline-item-left')) { + + self.grid.find('.thz-timeline-left').append(element); + + } else { + + self.grid.find('.thz-timeline-right').append(element); + + } + + }); + + } else { + + self.grid.append(newItems); + } + + self.ThzPozLoader(); + + } + self.ThzMasonryItemsEffects(newItems, timeout); + + + }); + }, + + + }); + + $.fn[pluginName] = function(options) { + return this.each(function() { + if (!$.data(this, 'plugin_' + pluginName)) { + $.data(this, 'plugin_' + pluginName, new Plugin(this, options)); + } else if (Plugin.prototype[options]) { + $.data(this, 'plugin_' + pluginName)[options](); + } + }); + } + + +})(jQuery, window, document); // JavaScript Document \ No newline at end of file diff --git a/assets/js/dev/ThzPanels.js b/assets/js/dev/ThzPanels.js new file mode 100644 index 0000000..7efccd0 --- /dev/null +++ b/assets/js/dev/ThzPanels.js @@ -0,0 +1,236 @@ + /** + * @plugin ThzPanels + * @version 1.0.0 + * @package Thz Framework + * @copyright Copyright(C) since 2015 Themezly.com. All Rights Reserved. + * @author Themezly + * @license MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * @websites http://www.themezly.com | http://www.youjoomla.com + */ +; +(function($, window, document, undefined) { + + "use strict"; + + var pluginName = "ThzPanels", + defaults = {}; + + function Plugin(element, options) { + this.element = element; + + this.settings = $.extend({}, defaults, options); + this._defaults = defaults; + this._name = pluginName; + this.init(); + } + + + $.extend(Plugin.prototype, { + init: function() { + + var self = this; + + + self.setPanel(); + + $(window).on('resize', function() { + self.panelResize(); + }); + + }, + + panelResize: function () { + + var self = this; + + $('#thz_toppanel:not(.panelOpen)').each(function () { + + var container = $(this).find('.thz-panel-content'); + $(this).css({ + 'height':container.height(), + 'top':-container.height() + }); + $(this).find('.thz-panel-sizer').css('height',container.height()); + + }); + + $('#thz_botpanel:not(.panelOpen)').each(function () { + + var container = $(this).find('.thz-panel-content'); + $(this).css({ + 'height':container.height(), + 'bottom':-container.height() + }); + $(this).find('.thz-panel-sizer').css('height',container.height()); + + }); + + $('.panelOpen:not(#thz_sidepanel)').each(function () { + + var container = $(this).find('.thz-panel-content'); + + $(this).stop(true).animate({ + height: container.height() + }); + + $(this).find('.thz-panel-sizer').stop(true).animate({ + height: container.height() + }); + }); + }, + + + setPanel: function () { + + var self = this; + + + $(document).on('click', function (event) { + event.stopImmediatePropagation(); + if ($(event.target).parents('.panelOpen').length == 0) { + $('.panelOpen').find('.thz-panel-open').trigger('click'); + } + + }); + + $('.thz-panel-open').each(function () { + + var panel = '#' +$(this).parent().attr('id'); + var getDirection = $(panel).data('direction'); + var tranSpeed = $(panel).data('speed'); + var panelHeight = $(panel).find('.thz-panel-content').height(); + var panelSizer = $(panel).find('.thz-panel-sizer'); + var openerWidth = $(this).outerWidth(); + var openerHeight = $(this).outerHeight(); + + + + + switch (panel) { + case '#thz_toppanel': + case '#thz_botpanel': + var side = getDirection == 'top' ? 'bottom':'top'; + $(this).css(side,- openerHeight); + + $(panel).css('height', panelHeight); + $(panel).css(getDirection, -panelHeight); + $(panelSizer).css('height', panelHeight); + break; + + case '#thz_sidepanel': + + var panelWidth = $(panel).data('width'); + $(panel).css('width', panelWidth); + + if(getDirection == 'left'){ + + $(panel).css('left', '-'+panelWidth+''); + + }else{ + + $(panel).css('right', '-'+panelWidth+''); + } + + var side = getDirection == 'left' ? 'right':'left'; + $(this).css(side,- openerWidth); + + break; + } + + $(this).click(function (e) { + + e.preventDefault(); + e.stopPropagation(); + var getPoz = parseInt($(panel).css(getDirection)); + switch (panel) { + + case '#thz_toppanel': + + if (getPoz < 0) { + + $(panel).addClass('panelOpen'); + $(panel).animate({ + 'top': 0 + }, tranSpeed); + + } else { + + $(panel).animate({ + 'top': -$(panelSizer).height() + }, tranSpeed); + + $(panel).removeClass('panelOpen'); + } + + break; + + case '#thz_botpanel': + + if (getPoz < 0) { + $(panel).addClass('panelOpen'); + $(panel).animate({ + 'bottom': 0 + }, tranSpeed); + } else { + + $(panel).animate({ + 'bottom': -$(panelSizer).height() + }, tranSpeed); + $(panel).removeClass('panelOpen'); + } + + break; + + case '#thz_sidepanel': + + if (getPoz < 0) { + $(panel).addClass('panelOpen'); + if(getDirection == 'right'){ + $(panel).animate({ + 'right': 0 + }, tranSpeed); + }else{ + $(panel).animate({ + 'left': 0 + }, tranSpeed); + + } + } else { + if(getDirection == 'right'){ + $(panel).animate({ + 'right': -$(panel).width() + }, tranSpeed); + }else{ + $(panel).animate({ + 'left': -$(panel).width() + }, tranSpeed); + } + $(panel).removeClass('panelOpen'); + } + + + break; + } + + }); + + }); + + } + + + + + }); + + $.fn[pluginName] = function(options) { + return this.each(function() { + if (!$.data(this, 'plugin_' + pluginName)) { + $.data(this, 'plugin_' + pluginName, new Plugin(this, options)); + } else if (Plugin.prototype[options]) { + $.data(this, 'plugin_' + pluginName)[options](); + } + }); + } + +})(jQuery, window, document); diff --git a/assets/js/dev/ThzParallax.js b/assets/js/dev/ThzParallax.js new file mode 100644 index 0000000..06052fb --- /dev/null +++ b/assets/js/dev/ThzParallax.js @@ -0,0 +1,374 @@ +/** + * @package Thz Parallax + * @copyright Copyright(C) FT Web Studio Inc since 2015. All Rights Reserved. + * @author Themezly + * @license MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * @websites http://www.themezly.com | http://www.youjoomla.com + */ +(function($) { + + var $window = $(window); + var windowHeight = document.documentElement.clientHeight; + var windowWidth = document.documentElement.clientWidth; + + $window.resize(function() { + windowHeight = document.documentElement.clientHeight; + windowWidth = document.documentElement.clientWidth; + }); + + $.fn.ThzParallax = function(options) { + + var defaults = { + velocity: 0.3, + direction: 'up', + scale: '', + onmobile:0, + size:'full' + }; + var self = this, + options = $.extend({}, defaults, options), + ThzParallaxes = [], // global array + scrollTopMin, + scrollTopMax, + moveMax, + Thz3d = ThzHas3d(); + + + function Thzinit() { + + if( self.length == 0){ + return; + } + + self.each(function(index, el) { + + var $this = $(el); + var $c_tr = $this.ThzGetTransform({ + current:true + }); + + options.velocity = $this.attr('data-thzplx-velocity') ? parseFloat($this.data('thzplx-velocity') / 10) : options.velocity; + options.direction = $this.attr('data-thzplx-direction') ? $this.data('thzplx-direction') : options.direction; + options.scale = $this.attr('data-thzplx-scale') ? $this.data('thzplx-scale') : options.scale; + options.onmobile = $this.attr('data-thzplx-onmobile') ? $this.data('thzplx-onmobile') :options.onmobile; + options.size = $this.attr('data-thzplx-size') ? $this.data('thzplx-size') :options.size; + options.in_sticky = $this.attr('data-thzplx-insticky') ? true : false; + + // hide on mobiles | if set to 1 than show + if(navigator.userAgent.match(/Mobi/) && options.onmobile === 0){ + $(el).addClass('thz-no-mobile-parallax'); + return; + + } + + // set widths and positions + + ThzSetDimensions(el, options, $c_tr); + + // push all info in to global array + var parallaxItem = {}; + + parallaxItem.element = $this; + parallaxItem.height = $this.outerHeight(); + parallaxItem.width = $this.outerWidth(); + parallaxItem.parentTop = $this.parent().offset().top; + parallaxItem.direction = options.direction; + parallaxItem.velocity = options.velocity; + parallaxItem.scale = options.scale; + parallaxItem.scrollTopMin = scrollTopMin; + parallaxItem.scrollTopMax = scrollTopMax; + parallaxItem.moveMax = moveMax; + parallaxItem.c_tr = $c_tr ? ' ' + $c_tr : ''; + + ThzParallaxes.push(parallaxItem); + + + }); + + } + + + // set dimensions + function ThzSetDimensions(el, options, current_transform) { + + var element = $(el); + var myparent = element.parent(); + var direction = options.direction; + var size = options.size; + var velocity = options.velocity; + var getWidth = isNaN(parseFloat(size)) ? myparent.outerWidth() : parseFloat(size) ; + var getHeight = myparent.outerHeight(); + var getTop = myparent.offset().top; + + + var upWidth = 250 * Math.abs(parseFloat(velocity)); + var upHeight = 350 * Math.abs(parseFloat(velocity)); + + // var setHeight = direction == 'down' || direction == 'fixed'? (getHeight + upHeight) * 1.3 : getHeight + upHeight; + var setWidth = direction == 'left' || direction == 'right' ? getWidth + upWidth : getWidth; + var setHeight = getHeight + upHeight; + + var setTop = direction == 'down' ? getHeight - setHeight : 0; + // var setTop = 0; + var setLeft = direction == 'right' ? getWidth - setWidth : 0; + + var scrollTopMinV = 0; + var scrollTopMaxV = getTop + getHeight; + + if (getTop > windowHeight) { + scrollTopMinV = getTop - windowHeight; + } + + moveMax = direction == 'left' || direction == 'right' ? setWidth - getWidth : setHeight - getHeight; + scrollTopMin = scrollTopMinV; + scrollTopMax = scrollTopMaxV; + elemDirection = direction; + elemVelocity = velocity; + + + if(size === 'custom') { + + element.addClass('thz-parallaxing'); + + }else{ + + element.css({ + + height: setHeight + 'px', + width: setWidth + 'px', + top: setTop + 'px', + left: setLeft + 'px', + 'transform': ThzTranslate('0px','0px') + current_transform + + }).addClass('thz-parallaxing'); + + } + + } + + // run parallax + function ThzRunParallax() { + + for (i = 0; i < ThzParallaxes.length; i++) { + ThzParallaxItems(ThzParallaxes[i]); + } + + } + + // on scroll + function ThzOnScroll() { + + for (var i = 0, len = ThzParallaxes.length; i < len; i++) { + + var $element = ThzParallaxes[i].element.parent(); + + // check if visible + if ($element.ThzIsVisible(200)) { + ThzParallaxItems(ThzParallaxes[i]); + } + + } + + } + + // check for transform + function ThzHas3d() { + + if (!window.getComputedStyle) { + return false; + } + + var el = document.createElement('p'), + has3d, + transforms = { + 'webkitTransform':'-webkit-transform', + 'OTransform':'-o-transform', + 'msTransform':'-ms-transform', + 'MozTransform':'-moz-transform', + 'transform':'transform' + }; + + // Add it to the body to get the computed style. + document.body.insertBefore(el, null); + + for (var t in transforms) { + if (el.style[t] !== undefined) { + el.style[t] = "translate3d(1px,1px,1px)"; + has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); + } + } + + document.body.removeChild(el); + + return (has3d !== undefined && has3d.length > 0 && has3d !== "none"); + } + + + // translate based on transform check. fallback to 2d + function ThzTranslate(x,y){ + + if(Thz3d){ + return 'translate3d('+x+','+y+',0px)'; + } + + return 'translate('+x+','+y+')'; + + } + + + // parallax + function ThzParallaxItems(el) { + + + var $element = $(el.element); + var scrollTop = $window.scrollTop(); + var velocity = el.velocity; + var direction = el.direction; + var current_transform = el.c_tr; + + if(options.in_sticky){ + if (direction === 'down' || direction === 'up') { + if(scrollTop > ($element.outerHeight() - el.moveMax)){ + return; + } + } + if (direction === 'left' || direction === 'right') { + + if(scrollTop > ($element.parent().outerHeight() - el.moveMax)){ + return; + } + + } + if(direction === 'fixed'){ + return; + } + } + + var scale = el.scale; + var elemScale = ThzParallaxScale(el, scrollTop); + + var scrollPercentage = (scrollTop - el.scrollTopMin) / (el.scrollTopMax - el.scrollTopMin); + + var elemMove = el.moveMax * scrollPercentage; + var mesunit = 'px'; + + if (direction === 'left' || direction === 'up') { + elemMove *= -1; + } + + elemMove = Math.round(elemMove); + + + var transform = elemScale + ThzTranslate('0px',elemMove + mesunit); + + if (direction === 'left' || direction === 'right') { + + transform = elemScale + ThzTranslate(elemMove + mesunit,'0px'); + } + + if(direction === 'fixed'){ + + elemMove = Math.round((el.parentTop - scrollTop)); + elemMove *= -1; + + transform = elemScale + ThzTranslate('0px',elemMove + mesunit); + } + + if ($element.hasClass('thz-animate')) { + + $element.off("thz:animation:done").on('thz:animation:done', function(e) { + + $element.addClass('thz-starting-parallax'); + + setTimeout(function (){ + $element.css({ + 'transform': transform + current_transform + }); + },1); + + setTimeout(function (){ + $element.removeClass('thz-starting-parallax'); + },401); + + }); + + }else{ + + $element.css({ + 'transform': transform + current_transform + }); + } + + + } + + + // scale + function ThzParallaxScale(el, scrollTop) { + + + var velocity = el.velocity; + var direction = el.direction; + var elemScale = ''; + + if(direction === 'fixed') return elemScale; + + + var scale = el.scale; + if (scale === 'up') { + var scaleCalc = 1 + (scrollTop * 0.0002); + if (scaleCalc < 1) { + scaleCalc = 1; + } + scaleCalc = scaleCalc + 0.001; + elemScale = 'scale3d(' + scaleCalc + ',' + scaleCalc + ',1) '; + } + + if (scale === 'down') { + var scaleCalc = 1 - (scrollTop * 0.0002); + if (scaleCalc > 1) { + scaleCalc = 1; + } + + //scaleCalc = scaleCalc - 0.01; + elemScale = 'scale3d(' + scaleCalc + ',' + scaleCalc + ',1) '; + } + + return elemScale; + } + + + var ThzWait = (function () { + var timers = {}; + return function (callback, ms, uniqueId) { + if (!uniqueId) { + uniqueId = "Don't call this twice without a uniqueId"; + } + if (timers[uniqueId]) { + clearTimeout (timers[uniqueId]); + } + timers[uniqueId] = setTimeout(callback, ms); + }; + })(); + + function ThzListeners() { + + $window.resize(function () { + ThzWait(function(){ + Thzinit(); + ThzRunParallax(); + }, 150, "thzparallax resized"); + }); + $window.on('scroll touchmove', function() { + requestAnimationFrame(ThzOnScroll); + }); + + } + + Thzinit(); + ThzRunParallax(); + ThzListeners(); + + }; + +})(jQuery); \ No newline at end of file diff --git a/assets/js/dev/ThzParallaxOver.js b/assets/js/dev/ThzParallaxOver.js new file mode 100644 index 0000000..92ee40b --- /dev/null +++ b/assets/js/dev/ThzParallaxOver.js @@ -0,0 +1,138 @@ +/** + * @plugin ThzParallaxOver + * @version 1.0.0 + * @package Thz Framework + * @copyright Copyright(C) since 2015 Themezly.com. All Rights Reserved. + * @author Themezly + * @license MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * @websites http://www.themezly.com | http://www.youjoomla.com + */ +(function($) { + + var $window = $(window); + var windowHeight = $window.height(); + + $window.resize(function() { + windowHeight = $window.height(); + }); + + $.fn.thz_parallax_over = function(effectSpeed, effectElement) { + + var $this = $(this); + + if( $this.length == 0 ){ + return; + } + + var Thz3d = ThzHas3d(); + + // check for transform + function ThzHas3d() { + + if (!window.getComputedStyle) { + return false; + } + + var el = document.createElement('p'), + has3d, + transforms = { + 'webkitTransform':'-webkit-transform', + 'OTransform':'-o-transform', + 'msTransform':'-ms-transform', + 'MozTransform':'-moz-transform', + 'transform':'transform' + }; + + // Add it to the body to get the computed style. + document.body.insertBefore(el, null); + + for (var t in transforms) { + if (el.style[t] !== undefined) { + el.style[t] = "translate3d(1px,1px,1px)"; + has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]); + } + } + + document.body.removeChild(el); + + return (has3d !== undefined && has3d.length > 0 && has3d !== "none"); + } + + + // translate based on transform check. fallback to 2d + function ThzTranslate(x,y){ + + if(Thz3d){ + return 'translate3d('+x+','+y+',0px)'; + } + + return 'translate('+x+','+y+')'; + + } + + function runEffect() { + + var windowScroll = $window.scrollTop(); + + $this.each(function(index, element) { + + var $element = $(this); + var $c_tr = $element.ThzGetTransform({ + current:true + }); + + if ($element.attr('data-parallaxspeed')) { + + effectSpeed = $element.attr('data-parallaxspeed'); + } + + var elementHeight = $element.outerHeight(); + var elementTop = $element.offset().top; + var elementPoz = elementTop - windowScroll; + var elementVisible = elementPoz + elementHeight; + var moveSpeed = effectSpeed != undefined ? effectSpeed : 40; + var speedCalc = moveSpeed / 100; + var elementMove = 0; + var moveContainer = effectElement != undefined ? effectElement : '.thz-container'; + var curr_transform = $c_tr ? ' ' + $c_tr : ''; + + if (elementVisible <= windowHeight && elementPoz <= 0) { + if (elementHeight > windowHeight) { + var elementMove = (windowHeight - elementVisible) * speedCalc; + } else { + var elementMove = -(elementPoz * speedCalc); + } + if (elementMove < 0) { + elementMove = 0; + } + } else { + elementMove = 0; + } + + var mesunit ='px'; + var transform = 'translate3d(0px,' + elementMove + mesunit + ',0px)'; + + $element.find(moveContainer).each(function(index, container) { + + $(container).css({ + // bottom: "-" + elementMove + "px" + 'transform': ThzTranslate('0px',elementMove + mesunit) + curr_transform + }); + + }); + + + }); + + } + $(window).on('scroll', function() { + requestAnimationFrame(runEffect); + }); + $(window).on('resize', function() { + requestAnimationFrame(runEffect); + }); + + + }; + +})(jQuery); diff --git a/assets/js/dev/ThzScrollFade.js b/assets/js/dev/ThzScrollFade.js new file mode 100644 index 0000000..9efbd06 --- /dev/null +++ b/assets/js/dev/ThzScrollFade.js @@ -0,0 +1,98 @@ + /** + * @plugin ThzScrollFade + * @version 1.0.0 + * @package Thz Framework + * @copyright Copyright(C) since 2015 Themezly.com. All Rights Reserved. + * @author Themezly + * @license MIT License (MIT) http://www.opensource.org/licenses/mit-license.php + * @websites http://www.themezly.com | http://www.youjoomla.com + */ +(function($) { + + var $window = $(window); + var windowHeight = $window.height(); + + $window.resize(function() { + windowHeight = $window.height(); + }); + + $.fn.thz_scroll_fade = function(startFadeAt) { + + var $this = $(this); + + if( $this.length == 0 ){ + return; + } + + function runEffect() { + + var windowScroll = $window.scrollTop(); + + $this.each(function(index, element) { + + var $element = $(this); + + if ($element.attr('data-fadestart')) { + + startFadeAt = $element.attr('data-fadestart'); + } + + var percentage = startFadeAt != undefined ? startFadeAt : 40; + var percentCalc = (100 - percentage) / 100; + var elementHeight = $element.outerHeight(); + var elementTop = $element.offset().top; + var elementPoz = elementTop - windowScroll; + var elementBottom = elementPoz + elementHeight; + var elementOpacity = 1; + var elementVisible = windowHeight - (windowHeight * percentCalc); + var setOpacity = (elementVisible - elementBottom) / elementVisible; + var effectElement = $element; + + if ($element.attr('data-whattofade')) { + + effectElement = $element.find($element.attr('data-whattofade')); + } + + if (setOpacity > 0){ + elementOpacity = 1 - setOpacity; + } + + var setOpacity = function(){ + + if (elementBottom <= elementVisible) { + if (elementOpacity < 0) { + elementOpacity = 0; + } else if (elementOpacity > 1) { + elementOpacity = 1; + } + effectElement.css({ + 'opacity': elementOpacity + }); + } else { + effectElement.css({ + 'opacity': elementOpacity + }); + } + + } + + if ($element.hasClass('thz-animate')) { + + $element.on('thz:animation:done', function(e) { + setOpacity(); + }); + + }else{ + setOpacity(); + } + + }); + + } + + $window.bind('scroll', runEffect).resize(runEffect); + runEffect(); + + }; + +})(jQuery); diff --git a/assets/js/dev/ThzSmoothScroll.js b/assets/js/dev/ThzSmoothScroll.js new file mode 100644 index 0000000..d707786 --- /dev/null +++ b/assets/js/dev/ThzSmoothScroll.js @@ -0,0 +1,765 @@ +ThzSmoothScroll = function($options) { + // + // SmoothScroll for websites v1.4.6 (Balazs Galambosi) + // http://www.smoothscroll.net/ + // + // Licensed under the terms of the MIT license. + // + // You may use it in your theme if you credit me. + // It is also free to use on any individual website. + // + // Exception: + // The only restriction is to not publish any + // extension for browsers or native application + // without getting a written permission first. + // + + (function () { + + + var extend = function(out) { + out = out || {}; + for (var i = 1; i < arguments.length; i++) { + if (!arguments[i]) + continue; + + for (var key in arguments[i]) { + if (arguments[i].hasOwnProperty(key)) + out[key] = arguments[i][key]; + } + } + return out; + }; + + + // Scroll Variables (tweakable) + var defaultOptions = { + + // Scrolling Core + frameRate : 150, // [Hz] + animationTime : 600, // [ms] + stepSize : 100, // [px] + + // Pulse (less tweakable) + // ratio of "tail" to "acceleration" + pulseAlgorithm : true, + pulseScale : 4, + pulseNormalize : 1, + + // Acceleration + accelerationDelta : 50, // 50 + accelerationMax : 3, // 3 + + // Keyboard Settings + keyboardSupport : true, // option + arrowScroll : 50, // [px] + + // Other + fixedBackground : true, + excluded : '' + }; + + var options = extend(defaultOptions, $options); + + // Other Variables + var isExcluded = false; + var isFrame = false; + var direction = { x: 0, y: 0 }; + var initDone = false; + var root = document.documentElement; + var activeElement; + var observer; + var refreshSize; + var deltaBuffer = []; + var isMac = /^Mac/.test(navigator.platform); + + var key = { left: 37, up: 38, right: 39, down: 40, spacebar: 32, + pageup: 33, pagedown: 34, end: 35, home: 36 }; + var arrowKeys = { 37: 1, 38: 1, 39: 1, 40: 1 }; + + /*********************************************** + * INITIALIZE + ***********************************************/ + + /** + * Tests if smooth scrolling is allowed. Shuts down everything if not. + */ + function initTest() { + if (options.keyboardSupport) { + addEvent('keydown', keydown); + } + } + + /** + * Sets up scrolls array, determines if frames are involved. + */ + function init() { + + if (initDone || !document.body) return; + + initDone = true; + + var body = document.body; + var html = document.documentElement; + var windowHeight = window.innerHeight; + var scrollHeight = body.scrollHeight; + + // check compat mode for root element + root = (document.compatMode.indexOf('CSS') >= 0) ? html : body; + activeElement = body; + + initTest(); + + // Checks if this script is running in a frame + if (top != self) { + isFrame = true; + } + + /** + * Safari 10 fixed it, Chrome fixed it in v45: + * This fixes a bug where the areas left and right to + * the content does not trigger the onmousewheel event + * on some pages. e.g.: html, body { height: 100% } + */ + else if (isOldSafari && + scrollHeight > windowHeight && + (body.offsetHeight <= windowHeight || + html.offsetHeight <= windowHeight)) { + + var fullPageElem = document.createElement('div'); + fullPageElem.style.cssText = 'position:absolute; z-index:-10000; ' + + 'top:0; left:0; right:0; height:' + + root.scrollHeight + 'px'; + document.body.appendChild(fullPageElem); + + // DOM changed (throttled) to fix height + var pendingRefresh; + refreshSize = function () { + if (pendingRefresh) return; // could also be: clearTimeout(pendingRefresh); + pendingRefresh = setTimeout(function () { + if (isExcluded) return; // could be running after cleanup + fullPageElem.style.height = '0'; + fullPageElem.style.height = root.scrollHeight + 'px'; + pendingRefresh = null; + }, 500); // act rarely to stay fast + }; + + setTimeout(refreshSize, 10); + + addEvent('resize', refreshSize); + + // TODO: attributeFilter? + var config = { + attributes: true, + childList: true, + characterData: false + // subtree: true + }; + + observer = new MutationObserver(refreshSize); + observer.observe(body, config); + + if (root.offsetHeight <= windowHeight) { + var clearfix = document.createElement('div'); + clearfix.style.clear = 'both'; + body.appendChild(clearfix); + } + } + + // disable fixed background + if (!options.fixedBackground && !isExcluded) { + body.style.backgroundAttachment = 'scroll'; + html.style.backgroundAttachment = 'scroll'; + } + } + + /** + * Removes event listeners and other traces left on the page. + */ + function cleanup() { + observer && observer.disconnect(); + removeEvent(wheelEvent, wheel); + removeEvent('mousedown', mousedown); + removeEvent('keydown', keydown); + removeEvent('resize', refreshSize); + removeEvent('load', init); + } + + + /************************************************ + * SCROLLING + ************************************************/ + + var que = []; + var pending = false; + var lastScroll = Date.now(); + + /** + * Pushes scroll actions to the scrolling queue. + */ + function scrollArray(elem, left, top) { + + directionCheck(left, top); + + if (options.accelerationMax != 1) { + var now = Date.now(); + var elapsed = now - lastScroll; + if (elapsed < options.accelerationDelta) { + var factor = (1 + (50 / elapsed)) / 2; + if (factor > 1) { + factor = Math.min(factor, options.accelerationMax); + left *= factor; + top *= factor; + } + } + lastScroll = Date.now(); + } + + // push a scroll command + que.push({ + x: left, + y: top, + lastX: (left < 0) ? 0.99 : -0.99, + lastY: (top < 0) ? 0.99 : -0.99, + start: Date.now() + }); + + // don't act if there's a pending queue + if (pending) { + return; + } + + var scrollWindow = (elem === document.body); + + var step = function (time) { + + var now = Date.now(); + var scrollX = 0; + var scrollY = 0; + + for (var i = 0; i < que.length; i++) { + + var item = que[i]; + var elapsed = now - item.start; + var finished = (elapsed >= options.animationTime); + + // scroll position: [0, 1] + var position = (finished) ? 1 : elapsed / options.animationTime; + + // easing [optional] + if (options.pulseAlgorithm) { + position = pulse(position); + } + + // only need the difference + var x = (item.x * position - item.lastX) >> 0; + var y = (item.y * position - item.lastY) >> 0; + + // add this to the total scrolling + scrollX += x; + scrollY += y; + + // update last values + item.lastX += x; + item.lastY += y; + + // delete and step back if it's over + if (finished) { + que.splice(i, 1); i--; + } + } + + // scroll left and top + if (scrollWindow) { + window.scrollBy(scrollX, scrollY); + } + else { + if (scrollX) elem.scrollLeft += scrollX; + if (scrollY) elem.scrollTop += scrollY; + } + + // clean up if there's nothing left to do + if (!left && !top) { + que = []; + } + + if (que.length) { + requestFrame(step, elem, (1000 / options.frameRate + 1)); + } else { + pending = false; + } + }; + + // start a new queue of actions + requestFrame(step, elem, 0); + pending = true; + } + + + /*********************************************** + * EVENTS + ***********************************************/ + + /** + * Mouse wheel handler. + * @param {Object} event + */ + function wheel(event) { + + if (!initDone) { + init(); + } + + var target = event.target; + + // leave early if default action is prevented + // or it's a zooming event with CTRL + if (event.defaultPrevented || event.ctrlKey) { + return true; + } + + // leave embedded content alone (flash & pdf) + if (isNodeName(activeElement, 'embed') || + (isNodeName(target, 'embed') && /\.pdf/i.test(target.src)) || + isNodeName(activeElement, 'object') || + target.shadowRoot) { + return true; + } + + var deltaX = -event.wheelDeltaX || event.deltaX || 0; + var deltaY = -event.wheelDeltaY || event.deltaY || 0; + + if (isMac) { + if (event.wheelDeltaX && isDivisible(event.wheelDeltaX, 120)) { + deltaX = -120 * (event.wheelDeltaX / Math.abs(event.wheelDeltaX)); + } + if (event.wheelDeltaY && isDivisible(event.wheelDeltaY, 120)) { + deltaY = -120 * (event.wheelDeltaY / Math.abs(event.wheelDeltaY)); + } + } + + // use wheelDelta if deltaX/Y is not available + if (!deltaX && !deltaY) { + deltaY = -event.wheelDelta || 0; + } + + // line based scrolling (Firefox mostly) + if (event.deltaMode === 1) { + deltaX *= 40; + deltaY *= 40; + } + + var overflowing = overflowingAncestor(target); + + // nothing to do if there's no element that's scrollable + if (!overflowing) { + // except Chrome iframes seem to eat wheel events, which we need to + // propagate up, if the iframe has nothing overflowing to scroll + if (isFrame && isChrome) { + // change target to iframe element itself for the parent frame + Object.defineProperty(event, "target", {value: window.frameElement}); + return parent.wheel(event); + } + return true; + } + + // check if it's a touchpad scroll that should be ignored + if (isTouchpad(deltaY)) { + return true; + } + + // scale by step size + // delta is 120 most of the time + // synaptics seems to send 1 sometimes + if (Math.abs(deltaX) > 1.2) { + deltaX *= options.stepSize / 120; + } + if (Math.abs(deltaY) > 1.2) { + deltaY *= options.stepSize / 120; + } + + scrollArray(overflowing, deltaX, deltaY); + event.preventDefault(); + scheduleClearCache(); + } + + /** + * Keydown event handler. + * @param {Object} event + */ + function keydown(event) { + + var target = event.target; + var modifier = event.ctrlKey || event.altKey || event.metaKey || + (event.shiftKey && event.keyCode !== key.spacebar); + + // our own tracked active element could've been removed from the DOM + if (!document.body.contains(activeElement)) { + activeElement = document.activeElement; + } + + // do nothing if user is editing text + // or using a modifier key (except shift) + // or in a dropdown + // or inside interactive elements + var inputNodeNames = /^(textarea|select|embed|object)$/i; + var buttonTypes = /^(button|submit|radio|checkbox|file|color|image)$/i; + if ( event.defaultPrevented || + inputNodeNames.test(target.nodeName) || + isNodeName(target, 'input') && !buttonTypes.test(target.type) || + isNodeName(activeElement, 'video') || + isInsideYoutubeVideo(event) || + target.isContentEditable || + modifier ) { + return true; + } + + // [spacebar] should trigger button press, leave it alone + if ((isNodeName(target, 'button') || + isNodeName(target, 'input') && buttonTypes.test(target.type)) && + event.keyCode === key.spacebar) { + return true; + } + + // [arrwow keys] on radio buttons should be left alone + if (isNodeName(target, 'input') && target.type == 'radio' && + arrowKeys[event.keyCode]) { + return true; + } + + var shift, x = 0, y = 0; + var overflowing = overflowingAncestor(activeElement); + + if (!overflowing) { + // Chrome iframes seem to eat key events, which we need to + // propagate up, if the iframe has nothing overflowing to scroll + return (isFrame && isChrome) ? parent.keydown(event) : true; + } + + var clientHeight = overflowing.clientHeight; + + if (overflowing == document.body) { + clientHeight = window.innerHeight; + } + + switch (event.keyCode) { + case key.up: + y = -options.arrowScroll; + break; + case key.down: + y = options.arrowScroll; + break; + case key.spacebar: // (+ shift) + shift = event.shiftKey ? 1 : -1; + y = -shift * clientHeight * 0.9; + break; + case key.pageup: + y = -clientHeight * 0.9; + break; + case key.pagedown: + y = clientHeight * 0.9; + break; + case key.home: + y = -overflowing.scrollTop; + break; + case key.end: + var scroll = overflowing.scrollHeight - overflowing.scrollTop; + var scrollRemaining = scroll - clientHeight; + y = (scrollRemaining > 0) ? scrollRemaining + 10 : 0; + break; + case key.left: + x = -options.arrowScroll; + break; + case key.right: + x = options.arrowScroll; + break; + default: + return true; // a key we don't care about + } + + scrollArray(overflowing, x, y); + event.preventDefault(); + scheduleClearCache(); + } + + /** + * Mousedown event only for updating activeElement + */ + function mousedown(event) { + activeElement = event.target; + } + + + /*********************************************** + * OVERFLOW + ***********************************************/ + + var uniqueID = (function () { + var i = 0; + return function (el) { + return el.uniqueID || (el.uniqueID = i++); + }; + })(); + + var cache = {}; // cleared out after a scrolling session + var clearCacheTimer; + + //setInterval(function () { cache = {}; }, 10 * 1000); + + function scheduleClearCache() { + clearTimeout(clearCacheTimer); + clearCacheTimer = setInterval(function () { cache = {}; }, 1*1000); + } + + function setCache(elems, overflowing) { + for (var i = elems.length; i--;) + cache[uniqueID(elems[i])] = overflowing; + return overflowing; + } + + // (body) (root) + // | hidden | visible | scroll | auto | + // hidden | no | no | YES | YES | + // visible | no | YES | YES | YES | + // scroll | no | YES | YES | YES | + // auto | no | YES | YES | YES | + + function overflowingAncestor(el) { + var elems = []; + var body = document.body; + var rootScrollHeight = root.scrollHeight; + do { + var cached = cache[uniqueID(el)]; + if (cached) { + return setCache(elems, cached); + } + elems.push(el); + if (rootScrollHeight === el.scrollHeight) { + var topOverflowsNotHidden = overflowNotHidden(root) && overflowNotHidden(body); + var isOverflowCSS = topOverflowsNotHidden || overflowAutoOrScroll(root); + if (isFrame && isContentOverflowing(root) || + !isFrame && isOverflowCSS) { + return setCache(elems, getScrollRoot()); + } + } else if (isContentOverflowing(el) && overflowAutoOrScroll(el)) { + return setCache(elems, el); + } + } while (el = el.parentElement); + } + + function isContentOverflowing(el) { + return (el.clientHeight + 10 < el.scrollHeight); + } + + // typically for and + function overflowNotHidden(el) { + var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y'); + return (overflow !== 'hidden'); + } + + // for all other elements + function overflowAutoOrScroll(el) { + var overflow = getComputedStyle(el, '').getPropertyValue('overflow-y'); + return (overflow === 'scroll' || overflow === 'auto'); + } + + + /*********************************************** + * HELPERS + ***********************************************/ + + function addEvent(type, fn) { + window.addEventListener(type, fn, false); + } + + function removeEvent(type, fn) { + window.removeEventListener(type, fn, false); + } + + function isNodeName(el, tag) { + return (el.nodeName||'').toLowerCase() === tag.toLowerCase(); + } + + function directionCheck(x, y) { + x = (x > 0) ? 1 : -1; + y = (y > 0) ? 1 : -1; + if (direction.x !== x || direction.y !== y) { + direction.x = x; + direction.y = y; + que = []; + lastScroll = 0; + } + } + + var deltaBufferTimer; + + if (window.localStorage && localStorage.SS_deltaBuffer) { + try { // #46 Safari throws in private browsing for localStorage + deltaBuffer = localStorage.SS_deltaBuffer.split(','); + } catch (e) { } + } + + function isTouchpad(deltaY) { + if (!deltaY) return; + if (!deltaBuffer.length) { + deltaBuffer = [deltaY, deltaY, deltaY]; + } + deltaY = Math.abs(deltaY); + deltaBuffer.push(deltaY); + deltaBuffer.shift(); + clearTimeout(deltaBufferTimer); + deltaBufferTimer = setTimeout(function () { + try { // #46 Safari throws in private browsing for localStorage + localStorage.SS_deltaBuffer = deltaBuffer.join(','); + } catch (e) { } + }, 1000); + return !allDeltasDivisableBy(120) && !allDeltasDivisableBy(100); + } + + function isDivisible(n, divisor) { + return (Math.floor(n / divisor) == n / divisor); + } + + function allDeltasDivisableBy(divisor) { + return (isDivisible(deltaBuffer[0], divisor) && + isDivisible(deltaBuffer[1], divisor) && + isDivisible(deltaBuffer[2], divisor)); + } + + function isInsideYoutubeVideo(event) { + var elem = event.target; + var isControl = false; + if (document.URL.indexOf ('www.youtube.com/watch') != -1) { + do { + isControl = (elem.classList && + elem.classList.contains('html5-video-controls')); + if (isControl) break; + } while (elem = elem.parentNode); + } + return isControl; + } + + var requestFrame = (function () { + return (window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + function (callback, element, delay) { + window.setTimeout(callback, delay || (1000/60)); + }); + })(); + + var MutationObserver = (window.MutationObserver || + window.WebKitMutationObserver || + window.MozMutationObserver); + + var getScrollRoot = (function() { + var SCROLL_ROOT; + return function() { + if (!SCROLL_ROOT) { + var dummy = document.createElement('div'); + dummy.style.cssText = 'height:10000px;width:1px;'; + document.body.appendChild(dummy); + var bodyScrollTop = document.body.scrollTop; + var docElScrollTop = document.documentElement.scrollTop; + window.scrollBy(0, 3); + if (document.body.scrollTop != bodyScrollTop) + (SCROLL_ROOT = document.body); + else + (SCROLL_ROOT = document.documentElement); + window.scrollBy(0, -3); + document.body.removeChild(dummy); + } + return SCROLL_ROOT; + }; + })(); + + + /*********************************************** + * PULSE (by Michael Herf) + ***********************************************/ + + /** + * Viscous fluid with a pulse for part and decay for the rest. + * - Applies a fixed force over an interval (a damped acceleration), and + * - Lets the exponential bleed away the velocity over a longer interval + * - Michael Herf, http://stereopsis.com/stopping/ + */ + function pulse_(x) { + var val, start, expx; + // test + x = x * options.pulseScale; + if (x < 1) { // acceleartion + val = x - (1 - Math.exp(-x)); + } else { // tail + // the previous animation ended here: + start = Math.exp(-1); + // simple viscous drag + x -= 1; + expx = 1 - Math.exp(-x); + val = start + (expx * (1 - start)); + } + return val * options.pulseNormalize; + } + + function pulse(x) { + if (x >= 1) return 1; + if (x <= 0) return 0; + + if (options.pulseNormalize == 1) { + options.pulseNormalize /= pulse_(1); + } + return pulse_(x); + } + + + /*********************************************** + * FIRST RUN + ***********************************************/ + + var userAgent = window.navigator.userAgent; + var isEdge = /Edge/.test(userAgent); // thank you MS + var isChrome = /chrome/i.test(userAgent) && !isEdge; + var isSafari = /safari/i.test(userAgent) && !isEdge; + var isMobile = /mobile/i.test(userAgent); + var isIEWin7 = /Windows NT 6.1/i.test(userAgent) && /rv:11/i.test(userAgent); + var isOldSafari = isSafari && (/Version\/8/i.test(userAgent) || /Version\/9/i.test(userAgent)); + var isEnabledForBrowser = (isChrome || isSafari || isIEWin7) && !isMobile; + + var wheelEvent; + if ('onwheel' in document.createElement('div')) + wheelEvent = 'wheel'; + else if ('onmousewheel' in document.createElement('div')) + wheelEvent = 'mousewheel'; + + if (wheelEvent && isEnabledForBrowser) { + addEvent(wheelEvent, wheel); + addEvent('mousedown', mousedown); + addEvent('load', init); + } + + + /*********************************************** + * PUBLIC INTERFACE + ***********************************************/ + + function SmoothScroll(optionsToSet) { + for (var key in optionsToSet) + if (defaultOptions.hasOwnProperty(key)) + options[key] = optionsToSet[key]; + } + SmoothScroll.destroy = cleanup; + + if (window.SmoothScrollOptions) // async API + SmoothScroll(window.SmoothScrollOptions); + + if (typeof define === 'function' && define.amd) + define(function() { + return SmoothScroll; + }); + else if ('object' == typeof exports) + module.exports = SmoothScroll; + else + window.SmoothScroll = SmoothScroll; + + })(); +}; \ No newline at end of file diff --git a/assets/js/dev/ThzTextRotator.js b/assets/js/dev/ThzTextRotator.js new file mode 100644 index 0000000..e52f9e9 --- /dev/null +++ b/assets/js/dev/ThzTextRotator.js @@ -0,0 +1,131 @@ +/** + * @package ThzTextRotator + * @copyright Copyright(C) since 2007 Themezly.com. All Rights Reserved. + * @author Themezly + * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 only + * @websites http://www.themezly.com | http://www.youjoomla.com + */ +; +(function($, window, document, undefined) { + + "use strict"; + + var pluginName = "ThzTextRotator", + defaults = { + start_delay: 200, + rotation_delay: 2e3, + }; + + function Plugin(element, options) { + this.element = element; + + this.settings = $.extend({}, defaults, options); + this._defaults = defaults; + this._name = pluginName; + this.init(); + } + + + $.extend(Plugin.prototype, { + init: function() { + + var self = this; + this.getlist = $(self.element).find('.text-string'); + + if (self.getlist.length > 0) { + + if ($(self.element).attr('data-start-delay')) { + self.settings.start_delay = parseFloat($(self.element).attr('data-start-delay')); + } + + if ($(self.element).attr('data-rotation-delay')) { + self.settings.rotation_delay = parseFloat($(self.element).attr('data-rotation-delay')); + } + + self.slideIn(self.getlist[0]); + $(self.element).addClass('isactive'); + } + + + }, + + resize: function(el) { + var self = this; + $(el).parent().css({ + width: $(el).width() + }); + }, + + slideIn: function(el) { + + var self = this; + + var $delay = self.settings.rotation_delay; + if ($(el).hasClass('first')) { + $delay = self.settings.start_delay; + } + + // resize area to sliding element + self.resize($(el)); + // add slide-in class + $(el).addClass('text-active'); + // after 'hold' duration slide-out current item + // then slide in next item + setTimeout(function() { + // check to see if loop should continue + if (stop === true) { + stop = false; + return; + } + // slide current element out + self.slideOut(el); + // slide in next element in queue + self.slideIn($(el).next()); + }, $delay); + }, + + slideOut: function(el) { + + var self = this; + // remove current class and add slide-out transition + $(el).removeClass('text-active').addClass('text-inactive') + .removeClass('first'); + // wait for slide tramsition to finish then + // call 'change' function + setTimeout(function() { + self.change(); + }, 600); + }, + + change: function() { + + var self = this; + // store last item index + var i = self.getlist.length - 1; + // detach element that has slide-out class + // put to the bottom of the list after + // the last item + //$(self.getlist).eq(i).after($('.slide-out').detach()); + + //console.log($(self.getlist).eq(i), $('.adj:eq(' + i + ')')); + var slideout = $(self.element).find('.text-inactive'); + $(self.element).find('.text-string:eq(' + i + ')').after(slideout.detach()); + // $('.adj:eq(' + i + ')').after($('.slide-out').detach()); + // remove class to send element back to original position + self.getlist.removeClass('text-inactive'); + }, + + + }); + + $.fn[pluginName] = function(options) { + return this.each(function() { + if (!$.data(this, 'plugin_' + pluginName)) { + $.data(this, 'plugin_' + pluginName, new Plugin(this, options)); + } else if (Plugin.prototype[options]) { + $.data(this, 'plugin_' + pluginName)[options](); + } + }); + } + +})(jQuery, window, document); \ No newline at end of file diff --git a/inc/includes/builder-templates/index.html b/assets/js/dev/index.html similarity index 100% rename from inc/includes/builder-templates/index.html rename to assets/js/dev/index.html diff --git a/assets/js/dev/vendors/bootstrap.tips-popover-extend.js b/assets/js/dev/vendors/bootstrap.tips-popover-extend.js new file mode 100644 index 0000000..d72986a --- /dev/null +++ b/assets/js/dev/vendors/bootstrap.tips-popover-extend.js @@ -0,0 +1,1041 @@ +/*! + * Bootstrap v3.4.1 (https://getbootstrap.com/) + * Copyright 2011-2019 Twitter, Inc. + * Licensed under the MIT license + */ +/*! + * Generated using the Bootstrap Customizer (https://getbootstrap.com/docs/3.4/customize/) + */ + +if (typeof jQuery === 'undefined') { + throw new Error('Bootstrap\'s JavaScript requires jQuery') +} ++function ($) { + 'use strict'; + var version = $.fn.jquery.split(' ')[0].split('.') + if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] > 3)) { + throw new Error('Bootstrap\'s JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4') + } +}(jQuery); + +/* ======================================================================== + * Bootstrap: tooltip.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#tooltip + * Inspired by the original jQuery.tipsy by Jason Frame + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn'] + + var uriAttrs = [ + 'background', + 'cite', + 'href', + 'itemtype', + 'longdesc', + 'poster', + 'src', + 'xlink:href' + ] + + var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i + + var DefaultWhitelist = { + // Global attributes allowed on any supplied element below. + '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], + a: ['target', 'href', 'title', 'rel'], + area: [], + b: [], + br: [], + col: [], + code: [], + div: [], + em: [], + hr: [], + h1: [], + h2: [], + h3: [], + h4: [], + h5: [], + h6: [], + i: [], + img: ['src', 'alt', 'title', 'width', 'height'], + li: [], + ol: [], + p: [], + pre: [], + s: [], + small: [], + span: [], + sub: [], + sup: [], + strong: [], + u: [], + ul: [] + } + + /** + * A pattern that recognizes a commonly useful subset of URLs that are safe. + * + * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts + */ + var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi + + /** + * A pattern that matches safe data URLs. Only matches image, video and audio types. + * + * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts + */ + var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i + + function allowedAttribute(attr, allowedAttributeList) { + var attrName = attr.nodeName.toLowerCase() + + if ($.inArray(attrName, allowedAttributeList) !== -1) { + if ($.inArray(attrName, uriAttrs) !== -1) { + return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)) + } + + return true + } + + var regExp = $(allowedAttributeList).filter(function (index, value) { + return value instanceof RegExp + }) + + // Check if a regular expression validates the attribute. + for (var i = 0, l = regExp.length; i < l; i++) { + if (attrName.match(regExp[i])) { + return true + } + } + + return false + } + + function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { + if (unsafeHtml.length === 0) { + return unsafeHtml + } + + if (sanitizeFn && typeof sanitizeFn === 'function') { + return sanitizeFn(unsafeHtml) + } + + // IE 8 and below don't support createHTMLDocument + if (!document.implementation || !document.implementation.createHTMLDocument) { + return unsafeHtml + } + + var createdDocument = document.implementation.createHTMLDocument('sanitization') + createdDocument.body.innerHTML = unsafeHtml + + var whitelistKeys = $.map(whiteList, function (el, i) { return i }) + var elements = $(createdDocument.body).find('*') + + for (var i = 0, len = elements.length; i < len; i++) { + var el = elements[i] + var elName = el.nodeName.toLowerCase() + + if ($.inArray(elName, whitelistKeys) === -1) { + el.parentNode.removeChild(el) + + continue + } + + var attributeList = $.map(el.attributes, function (el) { return el }) + var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []) + + for (var j = 0, len2 = attributeList.length; j < len2; j++) { + if (!allowedAttribute(attributeList[j], whitelistedAttributes)) { + el.removeAttribute(attributeList[j].nodeName) + } + } + } + + return createdDocument.body.innerHTML + } + // TOOLTIP PUBLIC CLASS DEFINITION + // =============================== + + var Tooltip = function (element, options) { + this.type = null + this.options = null + this.enabled = null + this.timeout = null + this.hoverState = null + this.$element = null + this.inState = null + + this.init('tooltip', element, options) + } + + Tooltip.VERSION = '3.3.7' + + Tooltip.TRANSITION_DURATION = 150 + + Tooltip.DEFAULTS = { + animation: true, + placement: 'top', + selector: false, + template: '', + trigger: 'hover focus', + title: '', + delay: 0, + html: false, + container: false, + viewport: { + selector: 'body', + padding: 0 + }, + sanitize : true, + sanitizeFn : null, + whiteList : DefaultWhitelist + } + + Tooltip.prototype.init = function (type, element, options) { + this.enabled = true + this.type = type + this.$element = $(element) + this.options = this.getOptions(options) + this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) + this.inState = { click: false, hover: false, focus: false } + + if (this.$element[0] instanceof document.constructor && !this.options.selector) { + throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') + } + + var triggers = this.options.trigger.split(' ') + + for (var i = triggers.length; i--;) { + var trigger = triggers[i] + + if (trigger == 'click') { + this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this)) + } else if (trigger != 'manual') { + var eventIn = trigger == 'hover' ? 'mouseenter' : 'focusin' + var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout' + + this.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this)) + this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this)) + } + } + + this.options.selector ? + (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) : + this.fixTitle() + } + + Tooltip.prototype.getDefaults = function () { + return Tooltip.DEFAULTS + } + + Tooltip.prototype.getOptions = function (options) { + options = $.extend({}, this.getDefaults(), this.$element.data(), options) + + if (options.delay && typeof options.delay == 'number') { + options.delay = { + show: options.delay, + hide: options.delay + } + } + + if (options.sanitize) { + options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn) + } + + return options + } + + Tooltip.prototype.getDelegateOptions = function () { + var options = {} + var defaults = this.getDefaults() + + this._options && $.each(this._options, function (key, value) { + if (defaults[key] != value) options[key] = value + }) + + return options + } + + + + Tooltip.prototype.enter = function (obj) { + var self = obj instanceof this.constructor ? + obj : $(obj.currentTarget).data('bs.' + this.type) + + if (!self) { + self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) + $(obj.currentTarget).data('bs.' + this.type, self) + } + + if (obj instanceof $.Event) { + self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true + } + + if (self.tip().hasClass('in') || self.hoverState == 'in') { + self.hoverState = 'in' + return + } + + clearTimeout(self.timeout) + + self.hoverState = 'in' + + if (!self.options.delay || !self.options.delay.show) return self.show() + + self.timeout = setTimeout(function () { + if (self.hoverState == 'in') self.show() + }, self.options.delay.show) + } + + Tooltip.prototype.isInStateTrue = function () { + for (var key in this.inState) { + if (this.inState[key]) return true + } + + return false + } + + Tooltip.prototype.leave = function (obj) { + var self = obj instanceof this.constructor ? + obj : $(obj.currentTarget).data('bs.' + this.type) + + if (!self) { + self = new this.constructor(obj.currentTarget, this.getDelegateOptions()) + $(obj.currentTarget).data('bs.' + this.type, self) + } + + if (obj instanceof $.Event) { + self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false + } + + if (self.isInStateTrue()) return + + clearTimeout(self.timeout) + + self.hoverState = 'out' + + if (!self.options.delay || !self.options.delay.hide) return self.hide() + + self.timeout = setTimeout(function () { + if (self.hoverState == 'out') self.hide() + }, self.options.delay.hide) + } + + Tooltip.prototype.show = function () { + var e = $.Event('show.bs.' + this.type) + + if (this.hasContent() && this.enabled) { + this.$element.trigger(e) + + var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) + if (e.isDefaultPrevented() || !inDom) return + var that = this + + var $tip = this.tip() + + var tipId = this.getUID(this.type) + + this.setContent() + $tip.attr('id', tipId) + this.$element.attr('aria-describedby', tipId) + + if (this.options.animation) $tip.addClass('tip-anim') + + var placement = typeof this.options.placement == 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement + + var autoToken = /\s?auto?\s?/i + var autoPlace = autoToken.test(placement) + if (autoPlace) placement = placement.replace(autoToken, '') || 'top' + + $tip + .detach() + .css({ top: 0, left: 0, display: 'block' }) + .addClass(placement) + .data('bs.' + this.type, this) + + this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) + this.$element.trigger('inserted.bs.' + this.type) + + var pos = this.getPosition() + var actualWidth = $tip[0].offsetWidth + var actualHeight = $tip[0].offsetHeight + + if (autoPlace) { + var orgPlacement = placement + var viewportDim = this.getPosition(this.$viewport) + + placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : + placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : + placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : + placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : + placement + + $tip + .removeClass(orgPlacement) + .addClass(placement) + } + + var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight) + + this.applyPlacement(calculatedOffset, placement) + + var complete = function () { + var prevHoverState = that.hoverState + that.$element.trigger('shown.bs.' + that.type) + that.hoverState = null + + if (prevHoverState == 'out') that.leave(that) + } + + $.support.transition && this.$tip.hasClass('tip-anim') ? + $tip + .one('bsTransitionEnd', complete) + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : + complete() + } + } + + Tooltip.prototype.applyPlacement = function (offset, placement) { + var $tip = this.tip() + var width = $tip[0].offsetWidth + var height = $tip[0].offsetHeight + + // manually read margins because getBoundingClientRect includes difference + var marginTop = parseInt($tip.css('margin-top'), 10) + var marginLeft = parseInt($tip.css('margin-left'), 10) + + // we must check for NaN for ie 8/9 + if (isNaN(marginTop)) marginTop = 0 + if (isNaN(marginLeft)) marginLeft = 0 + + offset.top += marginTop + offset.left += marginLeft + + // $.fn.offset doesn't round pixel values + // so we use setOffset directly with our own function B-0 + $.offset.setOffset($tip[0], $.extend({ + using: function (props) { + $tip.css({ + top: Math.round(props.top), + left: Math.round(props.left) + }) + } + }, offset), 0) + + $tip.removeClass('is-hidden').addClass('in') + + // check to see if placing tip in new offset caused the tip to resize itself + var actualWidth = $tip[0].offsetWidth + var actualHeight = $tip[0].offsetHeight + + if (placement == 'top' && actualHeight != height) { + offset.top = offset.top + height - actualHeight + } + + var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) + + if (delta.left) offset.left += delta.left + else offset.top += delta.top + + var isVertical = /top|bottom/.test(placement) + var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight + var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' + + $tip.offset(offset) + this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) + } + + Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { + this.arrow() + .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') + .css(isVertical ? 'top' : 'left', '') + } + + Tooltip.prototype.setContent = function () { + var $tip = this.tip() + var title = this.getTitle() + + if (this.options.html) { + if (this.options.sanitize) { + title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn) + } + + $tip.find('.thz-tip-inner').html(title) + } else { + $tip.find('.thz-tip-inner').text(title) + } + + $tip.removeClass('tip-anim in top bottom left right') + } + + Tooltip.prototype.hide = function (callback) { + var that = this + var $tip = $(this.$tip) + var e = $.Event('hide.bs.' + this.type) + + function complete() { + if (that.hoverState != 'in') /*$tip.detach()*/ + if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary. + that.$element + .removeAttr('aria-describedby') + .trigger('hidden.bs.' + that.type) + } + setTimeout(function(){ + $tip.addClass('is-hidden'); + },400); + callback && callback() + } + + this.$element.trigger(e) + + if (e.isDefaultPrevented()) return + + $tip.removeClass('in') + + $.support.transition && $tip.hasClass('tip-anim') ? + $tip + .one('bsTransitionEnd', complete) + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : + complete() + + this.hoverState = null + + return this + } + + Tooltip.prototype.fixTitle = function () { + var $e = this.$element + if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { + $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') + } + } + + Tooltip.prototype.hasContent = function () { + return this.getTitle() + } + + Tooltip.prototype.getPosition = function ($element) { + $element = $element || this.$element + + var el = $element[0] + var isBody = el.tagName == 'BODY' + + var elRect = el.getBoundingClientRect() + if (elRect.width == null) { + // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 + elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) + } + var isSvg = window.SVGElement && el instanceof window.SVGElement + // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3. + // See https://github.com/twbs/bootstrap/issues/20280 + var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset()) + var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } + var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null + + return $.extend({}, elRect, scroll, outerDims, elOffset) + } + + Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { + return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : + /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } + + } + + Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) { + var delta = { top: 0, left: 0 } + if (!this.$viewport) return delta + + var viewportPadding = this.options.viewport && this.options.viewport.padding || 0 + var viewportDimensions = this.getPosition(this.$viewport) + + if (/right|left/.test(placement)) { + var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll + var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight + if (topEdgeOffset < viewportDimensions.top) { // top overflow + delta.top = viewportDimensions.top - topEdgeOffset + } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow + delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset + } + } else { + var leftEdgeOffset = pos.left - viewportPadding + var rightEdgeOffset = pos.left + viewportPadding + actualWidth + if (leftEdgeOffset < viewportDimensions.left) { // left overflow + delta.left = viewportDimensions.left - leftEdgeOffset + } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow + delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset + } + } + + return delta + } + + Tooltip.prototype.getTitle = function () { + var title + var $e = this.$element + var o = this.options + + title = $e.attr('data-original-title') + || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title) + + return title + } + + Tooltip.prototype.getUID = function (prefix) { + do prefix += ~~(Math.random() * 1000000) + while (document.getElementById(prefix)) + return prefix + } + + Tooltip.prototype.tip = function () { + if (!this.$tip) { + this.$tip = $(this.options.template) + if (this.$tip.length != 1) { + throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') + } + } + return this.$tip + } + + Tooltip.prototype.arrow = function () { + return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) + } + + Tooltip.prototype.enable = function () { + this.enabled = true + } + + Tooltip.prototype.disable = function () { + this.enabled = false + } + + Tooltip.prototype.toggleEnabled = function () { + this.enabled = !this.enabled + } + + Tooltip.prototype.toggle = function (e) { + var self = this + if (e) { + self = $(e.currentTarget).data('bs.' + this.type) + if (!self) { + self = new this.constructor(e.currentTarget, this.getDelegateOptions()) + $(e.currentTarget).data('bs.' + this.type, self) + } + } + + if (e) { + self.inState.click = !self.inState.click + if (self.isInStateTrue()) self.enter(self) + else self.leave(self) + } else { + self.tip().hasClass('in') ? self.leave(self) : self.enter(self) + } + } + + Tooltip.prototype.destroy = function () { + var that = this + clearTimeout(this.timeout) + this.hide(function () { + that.$element.off('.' + that.type).removeData('bs.' + that.type) + if (that.$tip) { + that.$tip.detach() + } + that.$tip = null + that.$arrow = null + that.$viewport = null + that.$element = null + }) + } + + Tooltip.prototype.sanitizeHtml = function (unsafeHtml) { + return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn) + } + + + // TOOLTIP PLUGIN DEFINITION + // ========================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.tooltip') + var options = typeof option == 'object' && option + + if (!data && /destroy|hide/.test(option)) return + if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.tooltip + + $.fn.tooltip = Plugin + $.fn.tooltip.Constructor = Tooltip + + + // TOOLTIP NO CONFLICT + // =================== + + $.fn.tooltip.noConflict = function () { + $.fn.tooltip = old + return this + } + +}(jQuery); + +/* ======================================================================== + * Bootstrap: popover.js v3.4.1 + * https://getbootstrap.com/docs/3.4/javascript/#popovers + * ======================================================================== + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * ======================================================================== */ + + ++function ($) { + 'use strict'; + + // POPOVER PUBLIC CLASS DEFINITION + // =============================== + + var Popover = function (element, options) { + this.init('popover', element, options) + } + + if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') + + Popover.VERSION = '3.3.7' + + Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { + placement: 'right', + trigger: 'click', + content: '', + template: '' + }) + + + // NOTE: POPOVER EXTENDS tooltip.js + // ================================ + + Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype) + + Popover.prototype.constructor = Popover + + Popover.prototype.getDefaults = function () { + return Popover.DEFAULTS + } + + Popover.prototype.setContent = function () { + var $tip = this.tip() + var title = this.getTitle() + var content = this.getContent() + + if (this.options.sanitize) { + title = this.sanitizeHtml(title) + + if (typeContent === 'string') { + content = this.sanitizeHtml(content) + } + } + + $tip.find('.thz-popover-title')[this.options.html ? 'html' : 'text'](title) + $tip.find('.thz-popover-content').children().detach().end()[ // we use append for html objects to maintain js events + this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' + ](content) + + $tip.removeClass('tip-anim top bottom left right in') + + // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do + // this manually by checking the contents. + if (!$tip.find('.thz-popover-title').html()) $tip.find('.thz-popover-title').hide() + } + + Popover.prototype.hasContent = function () { + return this.getTitle() || this.getContent() + } + + Popover.prototype.getContent = function () { + var $e = this.$element + var o = this.options + + return $e.attr('data-content') + || (typeof o.content == 'function' ? + o.content.call($e[0]) : + o.content) + } + + Popover.prototype.arrow = function () { + return (this.$arrow = this.$arrow || this.tip().find('.arrow')) + } + + + // POPOVER PLUGIN DEFINITION + // ========================= + + function Plugin(option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.popover') + var options = typeof option == 'object' && option + + if (!data && /destroy|hide/.test(option)) return + if (!data) $this.data('bs.popover', (data = new Popover(this, options))) + if (typeof option == 'string') data[option]() + }) + } + + var old = $.fn.popover + + $.fn.popover = Plugin + $.fn.popover.Constructor = Popover + + + // POPOVER NO CONFLICT + // =================== + + $.fn.popover.noConflict = function () { + $.fn.popover = old + return this + } + +}(jQuery); + + + + + +/* =========================================================================== + * tips extend + * =========================================================================== +*/ + +!function ($) { + + "use strict"; // jshint ;_; + + + /* TOOLTIP-EXTENDED PUBLIC CLASS DEFINITION + * ======================================== */ + + // Save the original function object + var _old = $.fn.tooltip; + + // Create a new constructor + var TooltipExtended = function (element, options) { + this.init('tooltip', element, options) + } + + TooltipExtended.prototype = $.extend({}, _old.Constructor.prototype, { + + constructor: TooltipExtended + + + + , show: function () { + var $tip + , pos + , actualWidth + , actualHeight + , placement + , tp + , e = $.Event('show.bs.' + this.type) + + if (this.hasContent() && this.enabled) { + this.$element.trigger(e) + if (e.isDefaultPrevented()) return + $tip = this.tip() + this.setContent() + + if (this.options.animation) { + $tip.addClass('tip-anim') + } + + placement = typeof this.options.placement == 'function' ? + this.options.placement.call(this, $tip[0], this.$element[0]) : + this.options.placement + + // Detect if auto direction placement + var autoDirToken = /\s?auto-dir?\s?/i + var autoDirPlace = autoDirToken.test(placement) + if (autoDirPlace) placement = placement.replace(autoDirToken, '') || 'top' + + $tip + .detach() + .css({ top: 0, left: 0, display: 'block' }) + .addClass(placement) + + this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) + + pos = this.getPosition() + + actualWidth = $tip[0].offsetWidth + actualHeight = $tip[0].offsetHeight + + // Get the overall document direction + var isRTL = jQuery(document.querySelector("html")).attr('dir') === 'rtl' ? true : false + + // If auto-dir and the direction is RTL, the horizontal placement is reversed + if (autoDirPlace) { + var orgPlacement = placement + var xPlace = placement.replace(/bottom-|top-/g, '') || '' + var yPlace = placement.replace(/left|right/g, '') || '' + + placement = xPlace == 'left' && isRTL ? yPlace + 'right' : + xPlace == 'right' && isRTL ? yPlace + 'left' : + placement + + $tip + .removeClass(orgPlacement) + .addClass(placement) + } + + switch (placement) { + case 'bottom': + tp = {top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'top': + tp = {top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2} + break + case 'left': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth} + break + case 'right': + tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width} + break + // Additional positions + case 'bottom-left': + tp = {top: pos.top + pos.height, left: pos.left} + break + case 'bottom-right': + tp = {top: pos.top + pos.height, left: pos.left + pos.width - actualWidth} + break + case 'top-left': + tp = {top: pos.top - actualHeight, left: pos.left } + break + case 'top-right': + tp = {top: pos.top - actualHeight, left: pos.left + pos.width - actualWidth} + break + } + + this.applyPlacement(tp, placement) + + this.newArrow(placement, actualWidth, isRTL) + + this.$element.trigger('shown.bs') + } + } + + , applyPlacement: function (offset, placement) { + var $tip = this.tip() + var width = $tip[0].offsetWidth + var height = $tip[0].offsetHeight + + // manually read margins because getBoundingClientRect includes difference + var marginTop = parseInt($tip.css('margin-top'), 10) + var marginLeft = parseInt($tip.css('margin-left'), 10) + + // we must check for NaN for ie 8/9 + if (isNaN(marginTop)) marginTop = 0 + if (isNaN(marginLeft)) marginLeft = 0 + + offset.top += marginTop + offset.left += marginLeft + + // $.fn.offset doesn't round pixel values + // so we use setOffset directly with our own function B-0 + $.offset.setOffset($tip[0], $.extend({ + using: function (props) { + $tip.css({ + top: Math.round(props.top), + left: Math.round(props.left) + }) + } + }, offset), 0) + + $tip.removeClass('is-hidden').addClass('in') + + // check to see if placing tip in new offset caused the tip to resize itself + var actualWidth = $tip[0].offsetWidth + var actualHeight = $tip[0].offsetHeight + + if (placement == 'top' && actualHeight != height) { + offset.top = offset.top + height - actualHeight + } + + var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight) + + if (delta.left) offset.left += delta.left + else offset.top += delta.top + + var isVertical = /top|bottom/.test(placement) + var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight + var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' + + //$tip.offset(offset) + this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) + } + + , newArrow: function (placement, actualWidth, isRTL) { + var $arrow = this.tip().find('.thz-tip-arrow') + , arrow_width = parseInt($arrow.css('width'), 10) + , arrow_height = parseInt($arrow.css('height'), 10) + + var xPlace = placement.replace(/bottom-|top-/g, '') || '' + var yPlace = placement.replace(/left|right/g, '') || '' + + if ( yPlace && xPlace == 'left' && !isRTL ) $arrow.css("left", arrow_width / 2) + if ( yPlace && xPlace == 'left' && isRTL ) $arrow.css("right", actualWidth - arrow_width - arrow_width / 2) + if ( yPlace && xPlace == 'right' ) $arrow.css("left", actualWidth - arrow_width - arrow_width / 2) + if ( yPlace == 'bottom-' ) $arrow.css("top", arrow_height) + if ( yPlace == 'top-' ) $arrow.css("bottom", arrow_height) + }, + + tip: function () { + if (!this.$tip) { + this.$tip = $(this.options.template) + if (this.$tip.length != 1) { + throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') + } + } + return this.$tip + }, + }); + + + /* TOOLTIP-EXTENDED PLUGIN DEFINITION + * ================================== */ + + var old = $.fn.tooltip + + // Override the old initialization with the new constructor + $.fn.tooltip = $.extend(function ( option ) { + return this.each(function () { + var $this = $(this) + , data = $this.data('bs.tooltip') + , options = $.extend({}, TooltipExtended.defaults, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('bs.tooltip', (data = new TooltipExtended(this, options))) + if (typeof option == 'string') data[option]() + }) + }, $.fn.tooltip ) + + + /* TOOLTIP-EXTENDED NO CONFLICT + * ============================ */ + + $.fn.tooltip.noConflict = function () { + $.fn.tooltip = old + return this + }; + +}(window.jQuery); \ No newline at end of file diff --git a/assets/js/dev/vendors/cells-by-row.js b/assets/js/dev/vendors/cells-by-row.js new file mode 100644 index 0000000..bb9ec3a --- /dev/null +++ b/assets/js/dev/vendors/cells-by-row.js @@ -0,0 +1,66 @@ +/*! + * cellsByRows layout mode for Isotope + * v1.1.3 + * http://isotope.metafizzy.co/layout-modes/cellsbyrow.html + */ + +/*jshint browser: true, devel: false, strict: true, undef: true, unused: true */ + +( function( window, factory ) { + // universal module definition + /* jshint strict: false */ /*globals define, module, require */ + if ( typeof define === 'function' && define.amd ) { + // AMD + define( [ + 'isotope/js/layout-mode' + ], + factory ); + } else if ( typeof exports === 'object' ) { + // CommonJS + module.exports = factory( + require('isotope-layout/js/layout-mode') + ); + } else { + // browser global + factory( + window.Isotope.LayoutMode + ); + } + +}( window, function factory( LayoutMode ) { + 'use strict'; + + var CellsByRow = LayoutMode.create( 'cellsByRow' ); + var proto = CellsByRow.prototype; + + proto._resetLayout = function() { + // reset properties + this.itemIndex = 0; + // measurements + this.getColumnWidth(); + this.getRowHeight(); + // set cols + this.cols = Math.floor( this.isotope.size.innerWidth / this.columnWidth ); + this.cols = Math.max( this.cols, 1 ); + }; + + proto._getItemLayoutPosition = function( item ) { + item.getSize(); + var col = this.itemIndex % this.cols; + var row = Math.floor( this.itemIndex / this.cols ); + // center item within cell + var x = ( col + 0.5 ) * this.columnWidth - item.size.outerWidth / 2; + var y = ( row + 0.5 ) * this.rowHeight - item.size.outerHeight / 2; + this.itemIndex++; + return { x: x, y: y }; + }; + + proto._getContainerSize = function() { + return { + height: Math.ceil( this.itemIndex / this.cols ) * this.rowHeight + }; + }; + + return CellsByRow; + +})); diff --git a/assets/js/dev/vendors/circle-progress.js b/assets/js/dev/vendors/circle-progress.js new file mode 100644 index 0000000..051a0e8 --- /dev/null +++ b/assets/js/dev/vendors/circle-progress.js @@ -0,0 +1,560 @@ +/** + * jquery-circle-progress - jQuery Plugin to draw animated circular progress bars: + * {@link http://kottenator.github.io/jquery-circle-progress/} + * + * @author Rostyslav Bryzgunov + * @version 1.2.0 + * @licence MIT + * @preserve + */ +// UMD factory - https://github.com/umdjs/umd/blob/d31bb6ee7098715e019f52bdfe27b3e4bfd2b97e/templates/jqueryPlugin.js +// Uses CommonJS, AMD or browser globals to create a jQuery plugin. +(function(factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else if (typeof module === 'object' && module.exports) { + // Node/CommonJS + module.exports = function(root, jQuery) { + if (jQuery === undefined) { + // require('jQuery') returns a factory that requires window to + // build a jQuery instance, we normalize how we use modules + // that require this pattern but the window provided is a noop + // if it's defined (how jquery works) + if (typeof window !== 'undefined') { + jQuery = require('jquery'); + } else { + jQuery = require('jquery')(root); + } + } + factory(jQuery); + return jQuery; + }; + } else { + // Browser globals + factory(jQuery); + } +})(function($) { + /** + * Inner implementation of the circle progress bar. + * The class is not exposed _yet_ but you can create an instance through jQuery method call. + * + * @param {object} config - You can customize any class member (property or method). + * @class + * @alias CircleProgress + */ + function CircleProgress(config) { + this.init(config); + } + + CircleProgress.prototype = { + //--------------------------------------- public options --------------------------------------- + /** + * This is the only required option. It should be from `0.0` to `1.0`. + * @type {number} + * @default 0.0 + */ + value: 0.0, + + /** + * Size of the canvas in pixels. + * It's a square so we need only one dimension. + * @type {number} + * @default 100.0 + */ + size: 100.0, + + /** + * Initial angle for `0.0` value in radians. + * @type {number} + * @default -Math.PI + */ + startAngle: -Math.PI, + + /** + * Width of the arc in pixels. + * If it's `'auto'` - the value is calculated as `[this.size]{@link CircleProgress#size} / 14`. + * @type {number|string} + * @default 'auto' + */ + thickness: 'auto', + + /** + * Fill of the arc. You may set it to: + * + * - solid color: + * - `'#3aeabb'` + * - `{ color: '#3aeabb' }` + * - `{ color: 'rgba(255, 255, 255, .3)' }` + * - linear gradient _(left to right)_: + * - `{ gradient: ['#3aeabb', '#fdd250'], gradientAngle: Math.PI / 4 }` + * - `{ gradient: ['red', 'green', 'blue'], gradientDirection: [x0, y0, x1, y1] }` + * - `{ gradient: [["red", .2], ["green", .3], ["blue", .8]] }` + * - image: + * - `{ image: 'http://i.imgur.com/pT0i89v.png' }` + * - `{ image: imageObject }` + * - `{ color: 'lime', image: 'http://i.imgur.com/pT0i89v.png' }` - + * color displayed until the image is loaded + * + * @default {gradient: ['#3aeabb', '#fdd250']} + */ + fill: { + gradient: ['#3aeabb', '#fdd250'] + }, + + /** + * Color of the "empty" arc. Only a color fill supported by now. + * @type {string} + * @default 'rgba(0, 0, 0, .1)' + */ + emptyFill: 'rgba(0, 0, 0, .1)', + + /** + * jQuery Animation config. + * You can pass `false` to disable the animation. + * @see http://api.jquery.com/animate/ + * @type {object|boolean} + * @default {duration: 1200, easing: 'circleProgressEasing'} + */ + animation: { + duration: 1200, + easing: 'circleProgressEasing' + }, + + /** + * Default animation starts at `0.0` and ends at specified `value`. Let's call this _direct animation_. + * If you want to make _reversed animation_ - set `animationStartValue: 1.0`. + * Also you may specify any other value from `0.0` to `1.0`. + * @type {number} + * @default 0.0 + */ + animationStartValue: 0.0, + + /** + * Reverse animation and arc draw. + * By default, the arc is filled from `0.0` to `value`, _clockwise_. + * With `reverse: true` the arc is filled from `1.0` to `value`, _counter-clockwise_. + * @type {boolean} + * @default false + */ + reverse: false, + + /** + * Arc line cap: `'butt'`, `'round'` or `'square'` - + * [read more]{@link https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.lineCap}. + * @type {string} + * @default 'butt' + */ + lineCap: 'butt', + + /** + * Canvas insertion mode: append or prepend it into the parent element? + * @type {string} + * @default 'prepend' + */ + insertMode: 'prepend', + + //------------------------------ protected properties and methods ------------------------------ + /** + * Link to {@link CircleProgress} constructor. + * @protected + */ + constructor: CircleProgress, + + /** + * Container element. Should be passed into constructor config. + * @protected + * @type {jQuery} + */ + el: null, + + /** + * Canvas element. Automatically generated and prepended to [this.el]{@link CircleProgress#el}. + * @protected + * @type {HTMLCanvasElement} + */ + canvas: null, + + /** + * 2D-context of [this.canvas]{@link CircleProgress#canvas}. + * @protected + * @type {CanvasRenderingContext2D} + */ + ctx: null, + + /** + * Radius of the outer circle. Automatically calculated as `[this.size]{@link CircleProgress#size} / 2`. + * @protected + * @type {number} + */ + radius: 0.0, + + /** + * Fill of the main arc. Automatically calculated, depending on [this.fill]{@link CircleProgress#fill} option. + * @protected + * @type {string|CanvasGradient|CanvasPattern} + */ + arcFill: null, + + /** + * Last rendered frame value. + * @protected + * @type {number} + */ + lastFrameValue: 0.0, + + /** + * Init/re-init the widget. + * + * Throws a jQuery event: + * + * - `circle-inited(jqEvent)` + * + * @param {object} config - You can customize any class member (property or method). + */ + init: function(config) { + $.extend(this, config); + this.radius = this.size / 2; + this.initWidget(); + this.initFill(); + this.draw(); + this.el.trigger('circle-inited'); + }, + + /** + * Initialize ``. + * @protected + */ + initWidget: function() { + if (!this.canvas) + this.canvas = $('')[this.insertMode == 'prepend' ? 'prependTo' : 'appendTo'](this.el)[0]; + + var canvas = this.canvas; + canvas.width = this.size; + canvas.height = this.size; + this.ctx = canvas.getContext('2d'); + + if (window.devicePixelRatio > 1) { + var scaleBy = window.devicePixelRatio; + canvas.style.width = canvas.style.height = this.size + 'px'; + canvas.width = canvas.height = this.size * scaleBy; + this.ctx.scale(scaleBy, scaleBy); + } + }, + + /** + * This method sets [this.arcFill]{@link CircleProgress#arcFill}. + * It could do this async (on image load). + * @protected + */ + initFill: function() { + var self = this, + fill = this.fill, + ctx = this.ctx, + size = this.size; + + if (!fill) + throw Error("The fill is not specified!"); + + if (typeof fill == 'string') + fill = {color: fill}; + + if (fill.color) + this.arcFill = fill.color; + + if (fill.gradient) { + var gr = fill.gradient; + + if (gr.length == 1) { + this.arcFill = gr[0]; + } else if (gr.length > 1) { + var ga = fill.gradientAngle || 0, // gradient direction angle; 0 by default + gd = fill.gradientDirection || [ + size / 2 * (1 - Math.cos(ga)), // x0 + size / 2 * (1 + Math.sin(ga)), // y0 + size / 2 * (1 + Math.cos(ga)), // x1 + size / 2 * (1 - Math.sin(ga)) // y1 + ]; + + var lg = ctx.createLinearGradient.apply(ctx, gd); + + for (var i = 0; i < gr.length; i++) { + var color = gr[i], + pos = i / (gr.length - 1); + + if ($.isArray(color)) { + pos = color[1]; + color = color[0]; + } + + lg.addColorStop(pos, color); + } + + this.arcFill = lg; + } + } + + if (fill.image) { + var img; + + if (fill.image instanceof Image) { + img = fill.image; + } else { + img = new Image(); + img.src = fill.image; + } + + if (img.complete) + setImageFill(); + else + img.onload = setImageFill; + } + + function setImageFill() { + var bg = $('')[0]; + bg.width = self.size; + bg.height = self.size; + bg.getContext('2d').drawImage(img, 0, 0, size, size); + self.arcFill = self.ctx.createPattern(bg, 'no-repeat'); + self.drawFrame(self.lastFrameValue); + } + }, + + /** + * Draw the circle. + * @protected + */ + draw: function() { + if (this.animation) + this.drawAnimated(this.value); + else + this.drawFrame(this.value); + }, + + /** + * Draw a single animation frame. + * @protected + * @param {number} v - Frame value. + */ + drawFrame: function(v) { + this.lastFrameValue = v; + this.ctx.clearRect(0, 0, this.size, this.size); + this.drawEmptyArc(v); + this.drawArc(v); + }, + + /** + * Draw the arc (part of the circle). + * @protected + * @param {number} v - Frame value. + */ + drawArc: function(v) { + if (v === 0) + return; + + var ctx = this.ctx, + r = this.radius, + t = this.getThickness(), + a = this.startAngle; + + ctx.save(); + ctx.beginPath(); + + if (!this.reverse) { + ctx.arc(r, r, r - t / 2, a, a + Math.PI * 2 * v); + } else { + ctx.arc(r, r, r - t / 2, a - Math.PI * 2 * v, a); + } + + ctx.lineWidth = t; + ctx.lineCap = this.lineCap; + ctx.strokeStyle = this.arcFill; + ctx.stroke(); + ctx.restore(); + }, + + /** + * Draw the _empty (background)_ arc (part of the circle). + * @protected + * @param {number} v - Frame value. + */ + drawEmptyArc: function(v) { + var ctx = this.ctx, + r = this.radius, + t = this.getThickness(), + a = this.startAngle; + + if (v < 1) { + ctx.save(); + ctx.beginPath(); + + if (v <= 0) { + ctx.arc(r, r, r - t / 2, 0, Math.PI * 2); + } else { + if (!this.reverse) { + ctx.arc(r, r, r - t / 2, a + Math.PI * 2 * v, a); + } else { + ctx.arc(r, r, r - t / 2, a, a - Math.PI * 2 * v); + } + } + + ctx.lineWidth = t; + ctx.strokeStyle = this.emptyFill; + ctx.stroke(); + ctx.restore(); + } + }, + + /** + * Animate the progress bar. + * + * Throws 3 jQuery events: + * + * - `circle-animation-start(jqEvent)` + * - `circle-animation-progress(jqEvent, animationProgress, stepValue)` - multiple event + * animationProgress: from `0.0` to `1.0`; stepValue: from `0.0` to `value` + * - `circle-animation-end(jqEvent)` + * + * @protected + * @param {number} v - Final value. + */ + drawAnimated: function(v) { + var self = this, + el = this.el, + canvas = $(this.canvas); + + // stop previous animation before new "start" event is triggered + canvas.stop(true, false); + el.trigger('circle-animation-start'); + + canvas + .css({animationProgress: 0}) + .animate({animationProgress: 1}, $.extend({}, this.animation, { + step: function(animationProgress) { + var stepValue = self.animationStartValue * (1 - animationProgress) + v * animationProgress; + self.drawFrame(stepValue); + el.trigger('circle-animation-progress', [animationProgress, stepValue]); + } + })) + .promise() + .always(function() { + // trigger on both successful & failure animation end + el.trigger('circle-animation-end'); + }); + }, + + /** + * Get the circle thickness. + * @see CircleProgress#thickness + * @protected + * @returns {number} + */ + getThickness: function() { + return $.isNumeric(this.thickness) ? this.thickness : this.size / 14; + }, + + /** + * Get current value. + * @protected + * @return {number} + */ + getValue: function() { + return this.value; + }, + + /** + * Set current value (with smooth animation transition). + * @protected + * @param {number} newValue + */ + setValue: function(newValue) { + if (this.animation) + this.animationStartValue = this.lastFrameValue; + this.value = newValue; + this.draw(); + } + }; + + //----------------------------------- Initiating jQuery plugin ----------------------------------- + $.circleProgress = { + // Default options (you may override them) + defaults: CircleProgress.prototype + }; + + // ease-in-out-cubic + $.easing.circleProgressEasing = function(x, t, b, c, d) { + if ((t /= d / 2) < 1) + return c / 2 * t * t * t + b; + return c / 2 * ((t -= 2) * t * t + 2) + b; + }; + + /** + * Creates an instance of {@link CircleProgress}. + * Produces [init event]{@link CircleProgress#init} and [animation events]{@link CircleProgress#drawAnimated}. + * + * @param {object} [configOrCommand] - Config object or command name. + * + * Config example (you can specify any {@link CircleProgress} property): + * + * ```js + * { value: 0.75, size: 50, animation: false } + * ``` + * + * Commands: + * + * ```js + * el.circleProgress('widget'); // get the + * el.circleProgress('value'); // get the value + * el.circleProgress('value', newValue); // update the value + * el.circleProgress('redraw'); // redraw the circle + * el.circleProgress(); // the same as 'redraw' + * ``` + * + * @param {string} [commandArgument] - Some commands (like `'value'`) may require an argument. + * @see CircleProgress + * @alias "$(...).circleProgress" + */ + $.fn.circleProgress = function(configOrCommand, commandArgument) { + var dataName = 'circle-progress', + firstInstance = this.data(dataName); + + if (configOrCommand == 'widget') { + if (!firstInstance) + throw Error('Calling "widget" method on not initialized instance is forbidden'); + return firstInstance.canvas; + } + + if (configOrCommand == 'value') { + if (!firstInstance) + throw Error('Calling "value" method on not initialized instance is forbidden'); + if (typeof commandArgument == 'undefined') { + return firstInstance.getValue(); + } else { + var newValue = arguments[1]; + return this.each(function() { + $(this).data(dataName).setValue(newValue); + }); + } + } + + return this.each(function() { + var el = $(this), + instance = el.data(dataName), + config = $.isPlainObject(configOrCommand) ? configOrCommand : {}; + + if (instance) { + instance.init(config); + } else { + var initialConfig = $.extend({}, el.data()); + if (typeof initialConfig.fill == 'string') + initialConfig.fill = JSON.parse(initialConfig.fill); + if (typeof initialConfig.animation == 'string') + initialConfig.animation = JSON.parse(initialConfig.animation); + config = $.extend(initialConfig, config); + config.el = el; + instance = new CircleProgress(config); + el.data(dataName, instance); + } + }); + }; +}); diff --git a/assets/js/dev/vendors/hoverdir.js b/assets/js/dev/vendors/hoverdir.js new file mode 100644 index 0000000..7e8e354 --- /dev/null +++ b/assets/js/dev/vendors/hoverdir.js @@ -0,0 +1,275 @@ +/** + * jquery.hoverdir.js v1.1.2 + * http://www.codrops.com + * + * Licensed under the MIT license. + * http://www.opensource.org/licenses/mit-license.php + * + * Copyright 2012, Codrops + * http://www.codrops.com + */ +(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + define(['jquery'], factory); + } else if (typeof exports !== 'undefined') { + module.exports = factory(require('jquery')); + } else { + factory(jQuery); + } +})(function ($) { + 'use strict'; + + function Hoverdir(element, options) { + this.$el = $(element); + // set options + this.options = $.extend(true, {}, this.defaults, options); + // initialize visibility to false for show and hide method + this.isVisible = false; + // get the hover for this element + this.$hoverElem = this.$el.find(this.options.hoverElem); + // transition properties + this.transitionProp = 'all ' + this.options.speed + 'ms ' + this.options.easing; + // support for CSS transitions + this.support = this._supportsTransitions(); + // load the events + this._loadEvents(); + } + + Hoverdir.prototype = { + defaults: { + speed: 300, + easing: 'ease', + hoverDelay: 0, + inverse: false, + hoverElem: 'div' + }, + constructor: Hoverdir, + /** + * Detect if CSS transitions are supported + * + * @return {Boolean} + */ + _supportsTransitions: function () { + if (typeof Modernizr !== 'undefined') { + return Modernizr.csstransitions; + } else { + var b = document.body || document.documentElement, + s = b.style, + p = 'transition'; + + if (typeof s[p] === 'string') { + return true; + } + + // Tests for vendor specific prop + var v = ['Moz', 'webkit', 'Webkit', 'Khtml', 'O', 'ms']; + p = p.charAt(0).toUpperCase() + p.substr(1); + + for (var i = 0; i < v.length; i++) { + if (typeof s[v[i] + p] === 'string') { + return true; + } + } + + return false; + } + }, + /** + * Bind the events to the element + */ + _loadEvents: function () { + this.$el.on('mouseenter.hoverdir mouseleave.hoverdir', $.proxy(function (event) { + this.direction = this._getDir({x: event.pageX, y: event.pageY}); + + if (event.type === 'mouseenter') { + this._showHover(); + } + else { + this._hideHover(); + } + }, this)); + }, + /** + * Show the hover of the element + */ + _showHover: function () { + var styleCSS = this._getStyle(this.direction); + + if (this.support) { + this.$hoverElem.css('transition', ''); + } + + this.$hoverElem.hide().css(styleCSS.from); + clearTimeout(this.tmhover); + + this.tmhover = setTimeout($.proxy(function () { + this.$hoverElem.show(0, $.proxy(function () { + if (this.support) { + this.$hoverElem.css('transition', this.transitionProp); + } + this._applyAnimation(styleCSS.to); + + }, this)); + }, this), this.options.hoverDelay); + + this.isVisible = true; + }, + /** + * Hide the hover to the element + */ + _hideHover: function () { + var styleCSS = this._getStyle(this.direction); + if (this.support) { + this.$hoverElem.css('transition', this.transitionProp); + } + clearTimeout(this.tmhover); + this._applyAnimation(styleCSS.from); + this.isVisible = false; + }, + /** + * get the direction when the event is triggered + * credits : http://stackoverflow.com/a/3647634 + * + * @param {Object} coordinates + * @returns {Interger} + */ + _getDir: function (coordinates) { + // the width and height of the current div + var w = this.$el.width(), + h = this.$el.height(), + // calculate the x and y to get an angle to the center of the div from that x and y. + // gets the x value relative to the center of the DIV and "normalize" it + x = (coordinates.x - this.$el.offset().left - (w / 2)) * (w > h ? (h / w) : 1), + y = (coordinates.y - this.$el.offset().top - (h / 2)) * (h > w ? (w / h) : 1), + // the angle and the direction from where the mouse came in/went out clockwise (TRBL=0123); + // first calculate the angle of the point, + // add 180 deg to get rid of the negative values + // divide by 90 to get the quadrant + // add 3 and do a modulo by 4 to shift the quadrants to a proper clockwise TRBL (top/right/bottom/left) **/ + direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180) / 90) + 3) % 4; + return direction; + }, + /** + * get the style when the event is triggered + * + * @param {(Interger|String)} direction + * @returns {Object} + */ + _getStyle: function (direction) { + var fromStyle, toStyle, + slideFromTop = {'left': '0', 'top': '-100%'}, + slideFromBottom = {'left': '0', 'top': '100%'}, + slideFromLeft = {'left': '-100%', 'top': '0'}, + slideFromRight = {'left': '100%', 'top': '0'}, + slideTop = {'top': '0'}, + slideLeft = {'left': '0'}; + + switch (direction) { + case 0: + case 'top': + // from top + fromStyle = !this.options.inverse ? slideFromTop : slideFromBottom; + toStyle = slideTop; + break; + case 1: + case 'right': + // from right + fromStyle = !this.options.inverse ? slideFromRight : slideFromLeft; + toStyle = slideLeft; + break; + case 2: + case 'bottom': + // from bottom + fromStyle = !this.options.inverse ? slideFromBottom : slideFromTop; + toStyle = slideTop; + break; + case 3: + case 'left': + // from left + fromStyle = !this.options.inverse ? slideFromLeft : slideFromRight; + toStyle = slideLeft; + break; + } + + return {from: fromStyle, to: toStyle}; + }, + /** + * Apply a transition or fallback to jquery animate based on Modernizr.csstransitions support + * + * @param {Object} styleCSS + */ + _applyAnimation: function (styleCSS) { + $.fn.applyStyle = this.support ? $.fn.css : $.fn.animate; + this.$hoverElem.stop().applyStyle(styleCSS, $.extend(true, [], {duration: this.options.speed})); + }, + /** + * Show $hoverElem from the direction in argument + * + * @param {String} [direction=top] direction + */ + show: function (direction) { + this.$el.off('mouseenter.hoverdir mouseleave.hoverdir'); + if (!this.isVisible) { + this.direction = direction || 'top'; + this._showHover(); + } + }, + /** + * Hide $hoverElem from the direction in argument + * + * @param {String} [direction=bottom] direction + */ + hide: function (direction) { + this.rebuild(); + if (this.isVisible) { + this.direction = direction || 'bottom'; + this._hideHover(); + } + }, + setOptions: function (options) { + this.options = $.extend(true, {}, this.defaults, this.options, options); + }, + /** + * Unbinds the plugin. + */ + destroy: function () { + this.$el.off('mouseenter.hoverdir mouseleave.hoverdir'); + this.$el.data('hoverdir', null); + }, + /** + * Bind the plugin. + */ + rebuild: function (options) { + if (typeof options === 'object') { + this.setOptions(options); + } + this._loadEvents(); + } + }; + + $.fn.hoverdir = function (option, parameter) { + return this.each(function () { + var data = $(this).data('hoverdir'); + var options = typeof option === 'object' && option; + + // Initialize hoverdir. + if (!data) { + data = new Hoverdir(this, options); + + $(this).data('hoverdir', data); + } + + // Call hoverdir method. + if (typeof option === 'string') { + data[option](parameter); + + if (option === 'destroy') { + $(this).data('hoverdir', false); + } + } + }); + }; + + $.fn.hoverdir.Constructor = Hoverdir; +}); diff --git a/assets/js/dev/vendors/imagesloaded.pkgd.js b/assets/js/dev/vendors/imagesloaded.pkgd.js new file mode 100644 index 0000000..a230750 --- /dev/null +++ b/assets/js/dev/vendors/imagesloaded.pkgd.js @@ -0,0 +1,497 @@ +/*! + * imagesLoaded PACKAGED v4.1.4 + * JavaScript is all like "You images are done yet or what?" + * MIT License + */ + +/** + * EvEmitter v1.1.0 + * Lil' event emitter + * MIT License + */ + +/* jshint unused: true, undef: true, strict: true */ + +( function( global, factory ) { + // universal module definition + /* jshint strict: false */ /* globals define, module, window */ + if ( typeof define == 'function' && define.amd ) { + // AMD - RequireJS + define( 'ev-emitter/ev-emitter',factory ); + } else if ( typeof module == 'object' && module.exports ) { + // CommonJS - Browserify, Webpack + module.exports = factory(); + } else { + // Browser globals + global.EvEmitter = factory(); + } + +}( typeof window != 'undefined' ? window : this, function() { + + + +function EvEmitter() {} + +var proto = EvEmitter.prototype; + +proto.on = function( eventName, listener ) { + if ( !eventName || !listener ) { + return; + } + // set events hash + var events = this._events = this._events || {}; + // set listeners array + var listeners = events[ eventName ] = events[ eventName ] || []; + // only add once + if ( listeners.indexOf( listener ) == -1 ) { + listeners.push( listener ); + } + + return this; +}; + +proto.once = function( eventName, listener ) { + if ( !eventName || !listener ) { + return; + } + // add event + this.on( eventName, listener ); + // set once flag + // set onceEvents hash + var onceEvents = this._onceEvents = this._onceEvents || {}; + // set onceListeners object + var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {}; + // set flag + onceListeners[ listener ] = true; + + return this; +}; + +proto.off = function( eventName, listener ) { + var listeners = this._events && this._events[ eventName ]; + if ( !listeners || !listeners.length ) { + return; + } + var index = listeners.indexOf( listener ); + if ( index != -1 ) { + listeners.splice( index, 1 ); + } + + return this; +}; + +proto.emitEvent = function( eventName, args ) { + var listeners = this._events && this._events[ eventName ]; + if ( !listeners || !listeners.length ) { + return; + } + // copy over to avoid interference if .off() in listener + listeners = listeners.slice(0); + args = args || []; + // once stuff + var onceListeners = this._onceEvents && this._onceEvents[ eventName ]; + + for ( var i=0; i < listeners.length; i++ ) { + var listener = listeners[i] + var isOnce = onceListeners && onceListeners[ listener ]; + if ( isOnce ) { + // remove listener + // remove before trigger to prevent recursion + this.off( eventName, listener ); + // unset once flag + delete onceListeners[ listener ]; + } + // trigger listener + listener.apply( this, args ); + } + + return this; +}; + +proto.allOff = function() { + delete this._events; + delete this._onceEvents; +}; + +return EvEmitter; + +})); + +/*! + * imagesLoaded v4.1.4 + * JavaScript is all like "You images are done yet or what?" + * MIT License + */ + +( function( window, factory ) { 'use strict'; + // universal module definition + + /*global define: false, module: false, require: false */ + + if ( typeof define == 'function' && define.amd ) { + // AMD + define( [ + 'ev-emitter/ev-emitter' + ], function( EvEmitter ) { + return factory( window, EvEmitter ); + }); + } else if ( typeof module == 'object' && module.exports ) { + // CommonJS + module.exports = factory( + window, + require('ev-emitter') + ); + } else { + // browser global + window.imagesLoaded = factory( + window, + window.EvEmitter + ); + } + +})( typeof window !== 'undefined' ? window : this, + +// -------------------------- factory -------------------------- // + +function factory( window, EvEmitter ) { + + + +var $ = window.jQuery; +var console = window.console; + +// -------------------------- helpers -------------------------- // + +// extend objects +function extend( a, b ) { + for ( var prop in b ) { + a[ prop ] = b[ prop ]; + } + return a; +} + +var arraySlice = Array.prototype.slice; + +// turn element or nodeList into an array +function makeArray( obj ) { + if ( Array.isArray( obj ) ) { + // use object if already an array + return obj; + } + + var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number'; + if ( isArrayLike ) { + // convert nodeList to array + return arraySlice.call( obj ); + } + + // array of single index + return [ obj ]; +} + +// -------------------------- imagesLoaded -------------------------- // + +/** + * @param {Array, Element, NodeList, String} elem + * @param {Object or Function} options - if function, use as callback + * @param {Function} onAlways - callback function + */ +function ImagesLoaded( elem, options, onAlways ) { + // coerce ImagesLoaded() without new, to be new ImagesLoaded() + if ( !( this instanceof ImagesLoaded ) ) { + return new ImagesLoaded( elem, options, onAlways ); + } + // use elem as selector string + var queryElem = elem; + if ( typeof elem == 'string' ) { + queryElem = document.querySelectorAll( elem ); + } + // bail if bad element + if ( !queryElem ) { + console.error( 'Bad element for imagesLoaded ' + ( queryElem || elem ) ); + return; + } + + this.elements = makeArray( queryElem ); + this.options = extend( {}, this.options ); + // shift arguments if no options set + if ( typeof options == 'function' ) { + onAlways = options; + } else { + extend( this.options, options ); + } + + if ( onAlways ) { + this.on( 'always', onAlways ); + } + + this.getImages(); + + if ( $ ) { + // add jQuery Deferred object + this.jqDeferred = new $.Deferred(); + } + + // HACK check async to allow time to bind listeners + setTimeout( this.check.bind( this ) ); +} + +ImagesLoaded.prototype = Object.create( EvEmitter.prototype ); + +ImagesLoaded.prototype.options = {}; + +ImagesLoaded.prototype.getImages = function() { + this.images = []; + + // filter & find items if we have an item selector + this.elements.forEach( this.addElementImages, this ); +}; + +/** + * @param {Node} element + */ +ImagesLoaded.prototype.addElementImages = function( elem ) { + // filter siblings + if ( elem.nodeName == 'IMG' ) { + this.addImage( elem ); + } + // get background image on element + if ( this.options.background === true ) { + this.addElementBackgroundImages( elem ); + } + + // find children + // no non-element nodes, #143 + var nodeType = elem.nodeType; + if ( !nodeType || !elementNodeTypes[ nodeType ] ) { + return; + } + var childImgs = elem.querySelectorAll('img'); + // concat childElems to filterFound array + for ( var i=0; i < childImgs.length; i++ ) { + var img = childImgs[i]; + this.addImage( img ); + } + + // get child background images + if ( typeof this.options.background == 'string' ) { + var children = elem.querySelectorAll( this.options.background ); + for ( i=0; i < children.length; i++ ) { + var child = children[i]; + this.addElementBackgroundImages( child ); + } + } +}; + +var elementNodeTypes = { + 1: true, + 9: true, + 11: true +}; + +ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) { + var style = getComputedStyle( elem ); + if ( !style ) { + // Firefox returns null if in a hidden iframe https://bugzil.la/548397 + return; + } + // get url inside url("...") + var reURL = /url\((['"])?(.*?)\1\)/gi; + var matches = reURL.exec( style.backgroundImage ); + while ( matches !== null ) { + var url = matches && matches[2]; + if ( url ) { + this.addBackground( url, elem ); + } + matches = reURL.exec( style.backgroundImage ); + } +}; + +/** + * @param {Image} img + */ +ImagesLoaded.prototype.addImage = function( img ) { + var loadingImage = new LoadingImage( img ); + this.images.push( loadingImage ); +}; + +ImagesLoaded.prototype.addBackground = function( url, elem ) { + var background = new Background( url, elem ); + this.images.push( background ); +}; + +ImagesLoaded.prototype.check = function() { + var _this = this; + this.progressedCount = 0; + this.hasAnyBroken = false; + // complete if no images + if ( !this.images.length ) { + this.complete(); + return; + } + + function onProgress( image, elem, message ) { + // HACK - Chrome triggers event before object properties have changed. #83 + setTimeout( function() { + _this.progress( image, elem, message ); + }); + } + + this.images.forEach( function( loadingImage ) { + loadingImage.once( 'progress', onProgress ); + loadingImage.check(); + }); +}; + +ImagesLoaded.prototype.progress = function( image, elem, message ) { + this.progressedCount++; + this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded; + // progress event + this.emitEvent( 'progress', [ this, image, elem ] ); + if ( this.jqDeferred && this.jqDeferred.notify ) { + this.jqDeferred.notify( this, image ); + } + // check if completed + if ( this.progressedCount == this.images.length ) { + this.complete(); + } + + if ( this.options.debug && console ) { + console.log( 'progress: ' + message, image, elem ); + } +}; + +ImagesLoaded.prototype.complete = function() { + var eventName = this.hasAnyBroken ? 'fail' : 'done'; + this.isComplete = true; + this.emitEvent( eventName, [ this ] ); + this.emitEvent( 'always', [ this ] ); + if ( this.jqDeferred ) { + var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve'; + this.jqDeferred[ jqMethod ]( this ); + } +}; + +// -------------------------- -------------------------- // + +function LoadingImage( img ) { + this.img = img; +} + +LoadingImage.prototype = Object.create( EvEmitter.prototype ); + +LoadingImage.prototype.check = function() { + // If complete is true and browser supports natural sizes, + // try to check for image status manually. + var isComplete = this.getIsImageComplete(); + if ( isComplete ) { + // report based on naturalWidth + this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); + return; + } + + // If none of the checks above matched, simulate loading on detached element. + this.proxyImage = new Image(); + this.proxyImage.addEventListener( 'load', this ); + this.proxyImage.addEventListener( 'error', this ); + // bind to image as well for Firefox. #191 + this.img.addEventListener( 'load', this ); + this.img.addEventListener( 'error', this ); + this.proxyImage.src = this.img.src; +}; + +LoadingImage.prototype.getIsImageComplete = function() { + // check for non-zero, non-undefined naturalWidth + // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671 + return this.img.complete && this.img.naturalWidth; +}; + +LoadingImage.prototype.confirm = function( isLoaded, message ) { + this.isLoaded = isLoaded; + this.emitEvent( 'progress', [ this, this.img, message ] ); +}; + +// ----- events ----- // + +// trigger specified handler for event type +LoadingImage.prototype.handleEvent = function( event ) { + var method = 'on' + event.type; + if ( this[ method ] ) { + this[ method ]( event ); + } +}; + +LoadingImage.prototype.onload = function() { + this.confirm( true, 'onload' ); + this.unbindEvents(); +}; + +LoadingImage.prototype.onerror = function() { + this.confirm( false, 'onerror' ); + this.unbindEvents(); +}; + +LoadingImage.prototype.unbindEvents = function() { + this.proxyImage.removeEventListener( 'load', this ); + this.proxyImage.removeEventListener( 'error', this ); + this.img.removeEventListener( 'load', this ); + this.img.removeEventListener( 'error', this ); +}; + +// -------------------------- Background -------------------------- // + +function Background( url, element ) { + this.url = url; + this.element = element; + this.img = new Image(); +} + +// inherit LoadingImage prototype +Background.prototype = Object.create( LoadingImage.prototype ); + +Background.prototype.check = function() { + this.img.addEventListener( 'load', this ); + this.img.addEventListener( 'error', this ); + this.img.src = this.url; + // check if image is already complete + var isComplete = this.getIsImageComplete(); + if ( isComplete ) { + this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); + this.unbindEvents(); + } +}; + +Background.prototype.unbindEvents = function() { + this.img.removeEventListener( 'load', this ); + this.img.removeEventListener( 'error', this ); +}; + +Background.prototype.confirm = function( isLoaded, message ) { + this.isLoaded = isLoaded; + this.emitEvent( 'progress', [ this, this.element, message ] ); +}; + +// -------------------------- jQuery -------------------------- // + +ImagesLoaded.makeJQueryPlugin = function( jQuery ) { + jQuery = jQuery || window.jQuery; + if ( !jQuery ) { + return; + } + // set local variable + $ = jQuery; + // $().imagesLoaded() + $.fn.imagesLoaded = function( options, callback ) { + var instance = new ImagesLoaded( this, options, callback ); + return instance.jqDeferred.promise( $(this) ); + }; +}; +// try making plugin +ImagesLoaded.makeJQueryPlugin(); + +// -------------------------- -------------------------- // + +return ImagesLoaded; + +}); + diff --git a/inc/includes/builder-templates/static/index.html b/assets/js/dev/vendors/index.html similarity index 100% rename from inc/includes/builder-templates/static/index.html rename to assets/js/dev/vendors/index.html diff --git a/assets/js/dev/vendors/iscroll.js b/assets/js/dev/vendors/iscroll.js new file mode 100644 index 0000000..a277ff8 --- /dev/null +++ b/assets/js/dev/vendors/iscroll.js @@ -0,0 +1,2091 @@ +/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */ +(function (window, document, Math) { +var rAF = window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function (callback) { window.setTimeout(callback, 1000 / 60); }; + +var utils = (function () { + var me = {}; + + var _elementStyle = document.createElement('div').style; + var _vendor = (function () { + var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'], + transform, + i = 0, + l = vendors.length; + + for ( ; i < l; i++ ) { + transform = vendors[i] + 'ransform'; + if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1); + } + + return false; + })(); + + function _prefixStyle (style) { + if ( _vendor === false ) return false; + if ( _vendor === '' ) return style; + return _vendor + style.charAt(0).toUpperCase() + style.substr(1); + } + + me.getTime = Date.now || function getTime () { return new Date().getTime(); }; + + me.extend = function (target, obj) { + for ( var i in obj ) { + target[i] = obj[i]; + } + }; + + me.addEvent = function (el, type, fn, capture) { + el.addEventListener(type, fn, !!capture); + }; + + me.removeEvent = function (el, type, fn, capture) { + el.removeEventListener(type, fn, !!capture); + }; + + me.prefixPointerEvent = function (pointerEvent) { + return window.MSPointerEvent ? + 'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8): + pointerEvent; + }; + + me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) { + var distance = current - start, + speed = Math.abs(distance) / time, + destination, + duration; + + deceleration = deceleration === undefined ? 0.0006 : deceleration; + + destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 ); + duration = speed / deceleration; + + if ( destination < lowerMargin ) { + destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin; + distance = Math.abs(destination - current); + duration = distance / speed; + } else if ( destination > 0 ) { + destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; + distance = Math.abs(current) + destination; + duration = distance / speed; + } + + return { + destination: Math.round(destination), + duration: duration + }; + }; + + var _transform = _prefixStyle('transform'); + + me.extend(me, { + hasTransform: _transform !== false, + hasPerspective: _prefixStyle('perspective') in _elementStyle, + hasTouch: 'ontouchstart' in window, + hasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed + hasTransition: _prefixStyle('transition') in _elementStyle + }); + + /* + This should find all Android browsers lower than build 535.19 (both stock browser and webview) + - galaxy S2 is ok + - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1` + - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` + - galaxy S3 is badAndroid (stock brower, webview) + `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` + - galaxy S4 is badAndroid (stock brower, webview) + `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30` + - galaxy S5 is OK + `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` + - galaxy S6 is OK + `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)` + */ + me.isBadAndroid = (function() { + var appVersion = window.navigator.appVersion; + // Android browser is not a chrome browser. + if (/Android/.test(appVersion) && !(/Chrome\/\d/.test(appVersion))) { + var safariVersion = appVersion.match(/Safari\/(\d+.\d)/); + if(safariVersion && typeof safariVersion === "object" && safariVersion.length >= 2) { + return parseFloat(safariVersion[1]) < 535.19; + } else { + return true; + } + } else { + return false; + } + })(); + + me.extend(me.style = {}, { + transform: _transform, + transitionTimingFunction: _prefixStyle('transitionTimingFunction'), + transitionDuration: _prefixStyle('transitionDuration'), + transitionDelay: _prefixStyle('transitionDelay'), + transformOrigin: _prefixStyle('transformOrigin') + }); + + me.hasClass = function (e, c) { + var re = new RegExp("(^|\\s)" + c + "(\\s|$)"); + return re.test(e.className); + }; + + me.addClass = function (e, c) { + if ( me.hasClass(e, c) ) { + return; + } + + var newclass = e.className.split(' '); + newclass.push(c); + e.className = newclass.join(' '); + }; + + me.removeClass = function (e, c) { + if ( !me.hasClass(e, c) ) { + return; + } + + var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g'); + e.className = e.className.replace(re, ' '); + }; + + me.offset = function (el) { + var left = -el.offsetLeft, + top = -el.offsetTop; + + // jshint -W084 + while (el = el.offsetParent) { + left -= el.offsetLeft; + top -= el.offsetTop; + } + // jshint +W084 + + return { + left: left, + top: top + }; + }; + + me.preventDefaultException = function (el, exceptions) { + for ( var i in exceptions ) { + if ( exceptions[i].test(el[i]) ) { + return true; + } + } + + return false; + }; + + me.extend(me.eventType = {}, { + touchstart: 1, + touchmove: 1, + touchend: 1, + + mousedown: 2, + mousemove: 2, + mouseup: 2, + + pointerdown: 3, + pointermove: 3, + pointerup: 3, + + MSPointerDown: 3, + MSPointerMove: 3, + MSPointerUp: 3 + }); + + me.extend(me.ease = {}, { + quadratic: { + style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', + fn: function (k) { + return k * ( 2 - k ); + } + }, + circular: { + style: 'cubic-bezier(0.1, 0.57, 0.1, 1)', // Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 1) + fn: function (k) { + return Math.sqrt( 1 - ( --k * k ) ); + } + }, + back: { + style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', + fn: function (k) { + var b = 4; + return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1; + } + }, + bounce: { + style: '', + fn: function (k) { + if ( ( k /= 1 ) < ( 1 / 2.75 ) ) { + return 7.5625 * k * k; + } else if ( k < ( 2 / 2.75 ) ) { + return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75; + } else if ( k < ( 2.5 / 2.75 ) ) { + return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375; + } else { + return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375; + } + } + }, + elastic: { + style: '', + fn: function (k) { + var f = 0.22, + e = 0.4; + + if ( k === 0 ) { return 0; } + if ( k == 1 ) { return 1; } + + return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); + } + } + }); + + me.tap = function (e, eventName) { + var ev = document.createEvent('Event'); + ev.initEvent(eventName, true, true); + ev.pageX = e.pageX; + ev.pageY = e.pageY; + e.target.dispatchEvent(ev); + }; + + me.click = function (e) { + var target = e.target, + ev; + + if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) { + ev = document.createEvent('MouseEvents'); + ev.initMouseEvent('click', true, true, e.view, 1, + target.screenX, target.screenY, target.clientX, target.clientY, + e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, + 0, null); + + ev._constructed = true; + target.dispatchEvent(ev); + } + }; + + return me; +})(); +function IScroll (el, options) { + this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; + this.scroller = this.wrapper.children[0]; + this.scrollerStyle = this.scroller.style; // cache style for better performance + + this.options = { + + resizeScrollbars: true, + + mouseWheelSpeed: 20, + + snapThreshold: 0.334, + +// INSERT POINT: OPTIONS + disablePointer : !utils.hasPointer, + disableTouch : utils.hasPointer || !utils.hasTouch, + disableMouse : utils.hasPointer || utils.hasTouch, + startX: 0, + startY: 0, + scrollY: true, + directionLockThreshold: 5, + momentum: true, + + bounce: true, + bounceTime: 600, + bounceEasing: '', + + preventDefault: true, + preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ }, + + HWCompositing: true, + useTransition: true, + useTransform: true, + bindToWrapper: typeof window.onmousedown === "undefined" + }; + + for ( var i in options ) { + this.options[i] = options[i]; + } + + // Normalize options + this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : ''; + + this.options.useTransition = utils.hasTransition && this.options.useTransition; + this.options.useTransform = utils.hasTransform && this.options.useTransform; + + this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough; + this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault; + + // If you want eventPassthrough I have to lock one of the axes + this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY; + this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX; + + // With eventPassthrough we also need lockDirection mechanism + this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough; + this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold; + + this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing; + + this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling; + + if ( this.options.tap === true ) { + this.options.tap = 'tap'; + } + + if ( this.options.shrinkScrollbars == 'scale' ) { + this.options.useTransition = false; + } + + this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1; + +// INSERT POINT: NORMALIZATION + + // Some defaults + this.x = 0; + this.y = 0; + this.directionX = 0; + this.directionY = 0; + this._events = {}; + +// INSERT POINT: DEFAULTS + + this._init(); + this.refresh(); + + this.scrollTo(this.options.startX, this.options.startY); + this.enable(); +} + +IScroll.prototype = { + version: '5.2.0', + + _init: function () { + this._initEvents(); + + if ( this.options.scrollbars || this.options.indicators ) { + this._initIndicators(); + } + + if ( this.options.mouseWheel ) { + this._initWheel(); + } + + if ( this.options.snap ) { + this._initSnap(); + } + + if ( this.options.keyBindings ) { + this._initKeys(); + } + +// INSERT POINT: _init + + }, + + destroy: function () { + this._initEvents(true); + clearTimeout(this.resizeTimeout); + this.resizeTimeout = null; + this._execEvent('destroy'); + }, + + _transitionEnd: function (e) { + if ( e.target != this.scroller || !this.isInTransition ) { + return; + } + + this._transitionTime(); + if ( !this.resetPosition(this.options.bounceTime) ) { + this.isInTransition = false; + this._execEvent('scrollEnd'); + } + }, + + _start: function (e) { + // React to left mouse button only + if ( utils.eventType[e.type] != 1 ) { + // for button property + // http://unixpapa.com/js/mouse.html + var button; + if (!e.which) { + /* IE case */ + button = (e.button < 2) ? 0 : + ((e.button == 4) ? 1 : 2); + } else { + /* All others */ + button = e.button; + } + if ( button !== 0 ) { + return; + } + } + + if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) { + return; + } + + if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { + e.preventDefault(); + } + + var point = e.touches ? e.touches[0] : e, + pos; + + this.initiated = utils.eventType[e.type]; + this.moved = false; + this.distX = 0; + this.distY = 0; + this.directionX = 0; + this.directionY = 0; + this.directionLocked = 0; + + this.startTime = utils.getTime(); + + if ( this.options.useTransition && this.isInTransition ) { + this._transitionTime(); + this.isInTransition = false; + pos = this.getComputedPosition(); + this._translate(Math.round(pos.x), Math.round(pos.y)); + this._execEvent('scrollEnd'); + } else if ( !this.options.useTransition && this.isAnimating ) { + this.isAnimating = false; + this._execEvent('scrollEnd'); + } + + this.startX = this.x; + this.startY = this.y; + this.absStartX = this.x; + this.absStartY = this.y; + this.pointX = point.pageX; + this.pointY = point.pageY; + + this._execEvent('beforeScrollStart'); + }, + + _move: function (e) { + if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { + return; + } + + if ( this.options.preventDefault ) { // increases performance on Android? TODO: check! + e.preventDefault(); + } + + var point = e.touches ? e.touches[0] : e, + deltaX = point.pageX - this.pointX, + deltaY = point.pageY - this.pointY, + timestamp = utils.getTime(), + newX, newY, + absDistX, absDistY; + + this.pointX = point.pageX; + this.pointY = point.pageY; + + this.distX += deltaX; + this.distY += deltaY; + absDistX = Math.abs(this.distX); + absDistY = Math.abs(this.distY); + + // We need to move at least 10 pixels for the scrolling to initiate + if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) { + return; + } + + // If you are scrolling in one direction lock the other + if ( !this.directionLocked && !this.options.freeScroll ) { + if ( absDistX > absDistY + this.options.directionLockThreshold ) { + this.directionLocked = 'h'; // lock horizontally + } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) { + this.directionLocked = 'v'; // lock vertically + } else { + this.directionLocked = 'n'; // no lock + } + } + + if ( this.directionLocked == 'h' ) { + if ( this.options.eventPassthrough == 'vertical' ) { + e.preventDefault(); + } else if ( this.options.eventPassthrough == 'horizontal' ) { + this.initiated = false; + return; + } + + deltaY = 0; + } else if ( this.directionLocked == 'v' ) { + if ( this.options.eventPassthrough == 'horizontal' ) { + e.preventDefault(); + } else if ( this.options.eventPassthrough == 'vertical' ) { + this.initiated = false; + return; + } + + deltaX = 0; + } + + deltaX = this.hasHorizontalScroll ? deltaX : 0; + deltaY = this.hasVerticalScroll ? deltaY : 0; + + newX = this.x + deltaX; + newY = this.y + deltaY; + + // Slow down if outside of the boundaries + if ( newX > 0 || newX < this.maxScrollX ) { + newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX; + } + if ( newY > 0 || newY < this.maxScrollY ) { + newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY; + } + + this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0; + this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0; + + if ( !this.moved ) { + this._execEvent('scrollStart'); + } + + this.moved = true; + + this._translate(newX, newY); + +/* REPLACE START: _move */ + + if ( timestamp - this.startTime > 300 ) { + this.startTime = timestamp; + this.startX = this.x; + this.startY = this.y; + } + +/* REPLACE END: _move */ + + }, + + _end: function (e) { + if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { + return; + } + + if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) { + e.preventDefault(); + } + + var point = e.changedTouches ? e.changedTouches[0] : e, + momentumX, + momentumY, + duration = utils.getTime() - this.startTime, + newX = Math.round(this.x), + newY = Math.round(this.y), + distanceX = Math.abs(newX - this.startX), + distanceY = Math.abs(newY - this.startY), + time = 0, + easing = ''; + + this.isInTransition = 0; + this.initiated = 0; + this.endTime = utils.getTime(); + + // reset if we are outside of the boundaries + if ( this.resetPosition(this.options.bounceTime) ) { + return; + } + + this.scrollTo(newX, newY); // ensures that the last position is rounded + + // we scrolled less than 10 pixels + if ( !this.moved ) { + if ( this.options.tap ) { + utils.tap(e, this.options.tap); + } + + if ( this.options.click ) { + utils.click(e); + } + + this._execEvent('scrollCancel'); + return; + } + + if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) { + this._execEvent('flick'); + return; + } + + // start momentum animation if needed + if ( this.options.momentum && duration < 300 ) { + momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : { destination: newX, duration: 0 }; + momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { destination: newY, duration: 0 }; + newX = momentumX.destination; + newY = momentumY.destination; + time = Math.max(momentumX.duration, momentumY.duration); + this.isInTransition = 1; + } + + + if ( this.options.snap ) { + var snap = this._nearestSnap(newX, newY); + this.currentPage = snap; + time = this.options.snapSpeed || Math.max( + Math.max( + Math.min(Math.abs(newX - snap.x), 1000), + Math.min(Math.abs(newY - snap.y), 1000) + ), 300); + newX = snap.x; + newY = snap.y; + + this.directionX = 0; + this.directionY = 0; + easing = this.options.bounceEasing; + } + +// INSERT POINT: _end + + if ( newX != this.x || newY != this.y ) { + // change easing function when scroller goes out of the boundaries + if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) { + easing = utils.ease.quadratic; + } + + this.scrollTo(newX, newY, time, easing); + return; + } + + this._execEvent('scrollEnd'); + }, + + _resize: function () { + var that = this; + + clearTimeout(this.resizeTimeout); + + this.resizeTimeout = setTimeout(function () { + that.refresh(); + }, this.options.resizePolling); + }, + + resetPosition: function (time) { + var x = this.x, + y = this.y; + + time = time || 0; + + if ( !this.hasHorizontalScroll || this.x > 0 ) { + x = 0; + } else if ( this.x < this.maxScrollX ) { + x = this.maxScrollX; + } + + if ( !this.hasVerticalScroll || this.y > 0 ) { + y = 0; + } else if ( this.y < this.maxScrollY ) { + y = this.maxScrollY; + } + + if ( x == this.x && y == this.y ) { + return false; + } + + this.scrollTo(x, y, time, this.options.bounceEasing); + + return true; + }, + + disable: function () { + this.enabled = false; + }, + + enable: function () { + this.enabled = true; + }, + + refresh: function () { + var rf = this.wrapper.offsetHeight; // Force reflow + + this.wrapperWidth = this.wrapper.clientWidth; + this.wrapperHeight = this.wrapper.clientHeight; + +/* REPLACE START: refresh */ + + this.scrollerWidth = this.scroller.offsetWidth; + this.scrollerHeight = this.scroller.offsetHeight; + + this.maxScrollX = this.wrapperWidth - this.scrollerWidth; + this.maxScrollY = this.wrapperHeight - this.scrollerHeight; + +/* REPLACE END: refresh */ + + this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0; + this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0; + + if ( !this.hasHorizontalScroll ) { + this.maxScrollX = 0; + this.scrollerWidth = this.wrapperWidth; + } + + if ( !this.hasVerticalScroll ) { + this.maxScrollY = 0; + this.scrollerHeight = this.wrapperHeight; + } + + this.endTime = 0; + this.directionX = 0; + this.directionY = 0; + + this.wrapperOffset = utils.offset(this.wrapper); + + this._execEvent('refresh'); + + this.resetPosition(); + +// INSERT POINT: _refresh + + }, + + on: function (type, fn) { + if ( !this._events[type] ) { + this._events[type] = []; + } + + this._events[type].push(fn); + }, + + off: function (type, fn) { + if ( !this._events[type] ) { + return; + } + + var index = this._events[type].indexOf(fn); + + if ( index > -1 ) { + this._events[type].splice(index, 1); + } + }, + + _execEvent: function (type) { + if ( !this._events[type] ) { + return; + } + + var i = 0, + l = this._events[type].length; + + if ( !l ) { + return; + } + + for ( ; i < l; i++ ) { + this._events[type][i].apply(this, [].slice.call(arguments, 1)); + } + }, + + scrollBy: function (x, y, time, easing) { + x = this.x + x; + y = this.y + y; + time = time || 0; + + this.scrollTo(x, y, time, easing); + }, + + scrollTo: function (x, y, time, easing) { + easing = easing || utils.ease.circular; + + this.isInTransition = this.options.useTransition && time > 0; + var transitionType = this.options.useTransition && easing.style; + if ( !time || transitionType ) { + if(transitionType) { + this._transitionTimingFunction(easing.style); + this._transitionTime(time); + } + this._translate(x, y); + } else { + this._animate(x, y, time, easing.fn); + } + }, + + scrollToElement: function (el, time, offsetX, offsetY, easing) { + el = el.nodeType ? el : this.scroller.querySelector(el); + + if ( !el ) { + return; + } + + var pos = utils.offset(el); + + pos.left -= this.wrapperOffset.left; + pos.top -= this.wrapperOffset.top; + + // if offsetX/Y are true we center the element to the screen + if ( offsetX === true ) { + offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2); + } + if ( offsetY === true ) { + offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2); + } + + pos.left -= offsetX || 0; + pos.top -= offsetY || 0; + + pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left; + pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top; + + time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time; + + this.scrollTo(pos.left, pos.top, time, easing); + }, + + _transitionTime: function (time) { + time = time || 0; + + var durationProp = utils.style.transitionDuration; + this.scrollerStyle[durationProp] = time + 'ms'; + + if ( !time && utils.isBadAndroid ) { + this.scrollerStyle[durationProp] = '0.0001ms'; + // remove 0.0001ms + var self = this; + rAF(function() { + if(self.scrollerStyle[durationProp] === '0.0001ms') { + self.scrollerStyle[durationProp] = '0s'; + } + }); + } + + + if ( this.indicators ) { + for ( var i = this.indicators.length; i--; ) { + this.indicators[i].transitionTime(time); + } + } + + +// INSERT POINT: _transitionTime + + }, + + _transitionTimingFunction: function (easing) { + this.scrollerStyle[utils.style.transitionTimingFunction] = easing; + + + if ( this.indicators ) { + for ( var i = this.indicators.length; i--; ) { + this.indicators[i].transitionTimingFunction(easing); + } + } + + +// INSERT POINT: _transitionTimingFunction + + }, + + _translate: function (x, y) { + if ( this.options.useTransform ) { + +/* REPLACE START: _translate */ + + this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; + +/* REPLACE END: _translate */ + + } else { + x = Math.round(x); + y = Math.round(y); + this.scrollerStyle.left = x + 'px'; + this.scrollerStyle.top = y + 'px'; + } + + this.x = x; + this.y = y; + + + if ( this.indicators ) { + for ( var i = this.indicators.length; i--; ) { + this.indicators[i].updatePosition(); + } + } + + +// INSERT POINT: _translate + + }, + + _initEvents: function (remove) { + var eventType = remove ? utils.removeEvent : utils.addEvent, + target = this.options.bindToWrapper ? this.wrapper : window; + + eventType(window, 'orientationchange', this); + eventType(window, 'resize', this); + + if ( this.options.click ) { + eventType(this.wrapper, 'click', this, true); + } + + if ( !this.options.disableMouse ) { + eventType(this.wrapper, 'mousedown', this); + eventType(target, 'mousemove', this); + eventType(target, 'mousecancel', this); + eventType(target, 'mouseup', this); + } + + if ( utils.hasPointer && !this.options.disablePointer ) { + eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this); + eventType(target, utils.prefixPointerEvent('pointermove'), this); + eventType(target, utils.prefixPointerEvent('pointercancel'), this); + eventType(target, utils.prefixPointerEvent('pointerup'), this); + } + + if ( utils.hasTouch && !this.options.disableTouch ) { + eventType(this.wrapper, 'touchstart', this); + eventType(target, 'touchmove', this); + eventType(target, 'touchcancel', this); + eventType(target, 'touchend', this); + } + + eventType(this.scroller, 'transitionend', this); + eventType(this.scroller, 'webkitTransitionEnd', this); + eventType(this.scroller, 'oTransitionEnd', this); + eventType(this.scroller, 'MSTransitionEnd', this); + }, + + getComputedPosition: function () { + var matrix = window.getComputedStyle(this.scroller, null), + x, y; + + if ( this.options.useTransform ) { + matrix = matrix[utils.style.transform].split(')')[0].split(', '); + x = +(matrix[12] || matrix[4]); + y = +(matrix[13] || matrix[5]); + } else { + x = +matrix.left.replace(/[^-\d.]/g, ''); + y = +matrix.top.replace(/[^-\d.]/g, ''); + } + + return { x: x, y: y }; + }, + _initIndicators: function () { + var interactive = this.options.interactiveScrollbars, + customStyle = typeof this.options.scrollbars != 'string', + indicators = [], + indicator; + + var that = this; + + this.indicators = []; + + if ( this.options.scrollbars ) { + // Vertical scrollbar + if ( this.options.scrollY ) { + indicator = { + el: createDefaultScrollbar('v', interactive, this.options.scrollbars), + interactive: interactive, + defaultScrollbars: true, + customStyle: customStyle, + resize: this.options.resizeScrollbars, + shrink: this.options.shrinkScrollbars, + fade: this.options.fadeScrollbars, + listenX: false + }; + + this.wrapper.appendChild(indicator.el); + indicators.push(indicator); + } + + // Horizontal scrollbar + if ( this.options.scrollX ) { + indicator = { + el: createDefaultScrollbar('h', interactive, this.options.scrollbars), + interactive: interactive, + defaultScrollbars: true, + customStyle: customStyle, + resize: this.options.resizeScrollbars, + shrink: this.options.shrinkScrollbars, + fade: this.options.fadeScrollbars, + listenY: false + }; + + this.wrapper.appendChild(indicator.el); + indicators.push(indicator); + } + } + + if ( this.options.indicators ) { + // TODO: check concat compatibility + indicators = indicators.concat(this.options.indicators); + } + + for ( var i = indicators.length; i--; ) { + this.indicators.push( new Indicator(this, indicators[i]) ); + } + + // TODO: check if we can use array.map (wide compatibility and performance issues) + function _indicatorsMap (fn) { + if (that.indicators) { + for ( var i = that.indicators.length; i--; ) { + fn.call(that.indicators[i]); + } + } + } + + if ( this.options.fadeScrollbars ) { + this.on('scrollEnd', function () { + _indicatorsMap(function () { + this.fade(); + }); + }); + + this.on('scrollCancel', function () { + _indicatorsMap(function () { + this.fade(); + }); + }); + + this.on('scrollStart', function () { + _indicatorsMap(function () { + this.fade(1); + }); + }); + + this.on('beforeScrollStart', function () { + _indicatorsMap(function () { + this.fade(1, true); + }); + }); + } + + + this.on('refresh', function () { + _indicatorsMap(function () { + this.refresh(); + }); + }); + + this.on('destroy', function () { + _indicatorsMap(function () { + this.destroy(); + }); + + delete this.indicators; + }); + }, + + _initWheel: function () { + utils.addEvent(this.wrapper, 'wheel', this); + utils.addEvent(this.wrapper, 'mousewheel', this); + utils.addEvent(this.wrapper, 'DOMMouseScroll', this); + + this.on('destroy', function () { + clearTimeout(this.wheelTimeout); + this.wheelTimeout = null; + utils.removeEvent(this.wrapper, 'wheel', this); + utils.removeEvent(this.wrapper, 'mousewheel', this); + utils.removeEvent(this.wrapper, 'DOMMouseScroll', this); + }); + }, + + _wheel: function (e) { + if ( !this.enabled ) { + return; + } + + e.preventDefault(); + + var wheelDeltaX, wheelDeltaY, + newX, newY, + that = this; + + if ( this.wheelTimeout === undefined ) { + that._execEvent('scrollStart'); + } + + // Execute the scrollEnd event after 400ms the wheel stopped scrolling + clearTimeout(this.wheelTimeout); + this.wheelTimeout = setTimeout(function () { + if(!that.options.snap) { + that._execEvent('scrollEnd'); + } + that.wheelTimeout = undefined; + }, 400); + + if ( 'deltaX' in e ) { + if (e.deltaMode === 1) { + wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed; + wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed; + } else { + wheelDeltaX = -e.deltaX; + wheelDeltaY = -e.deltaY; + } + } else if ( 'wheelDeltaX' in e ) { + wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed; + wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed; + } else if ( 'wheelDelta' in e ) { + wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed; + } else if ( 'detail' in e ) { + wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed; + } else { + return; + } + + wheelDeltaX *= this.options.invertWheelDirection; + wheelDeltaY *= this.options.invertWheelDirection; + + if ( !this.hasVerticalScroll ) { + wheelDeltaX = wheelDeltaY; + wheelDeltaY = 0; + } + + if ( this.options.snap ) { + newX = this.currentPage.pageX; + newY = this.currentPage.pageY; + + if ( wheelDeltaX > 0 ) { + newX--; + } else if ( wheelDeltaX < 0 ) { + newX++; + } + + if ( wheelDeltaY > 0 ) { + newY--; + } else if ( wheelDeltaY < 0 ) { + newY++; + } + + this.goToPage(newX, newY); + + return; + } + + newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0); + newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0); + + this.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0; + this.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0; + + if ( newX > 0 ) { + newX = 0; + } else if ( newX < this.maxScrollX ) { + newX = this.maxScrollX; + } + + if ( newY > 0 ) { + newY = 0; + } else if ( newY < this.maxScrollY ) { + newY = this.maxScrollY; + } + + this.scrollTo(newX, newY, 0); + +// INSERT POINT: _wheel + }, + + _initSnap: function () { + this.currentPage = {}; + + if ( typeof this.options.snap == 'string' ) { + this.options.snap = this.scroller.querySelectorAll(this.options.snap); + } + + this.on('refresh', function () { + var i = 0, l, + m = 0, n, + cx, cy, + x = 0, y, + stepX = this.options.snapStepX || this.wrapperWidth, + stepY = this.options.snapStepY || this.wrapperHeight, + el; + + this.pages = []; + + if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) { + return; + } + + if ( this.options.snap === true ) { + cx = Math.round( stepX / 2 ); + cy = Math.round( stepY / 2 ); + + while ( x > -this.scrollerWidth ) { + this.pages[i] = []; + l = 0; + y = 0; + + while ( y > -this.scrollerHeight ) { + this.pages[i][l] = { + x: Math.max(x, this.maxScrollX), + y: Math.max(y, this.maxScrollY), + width: stepX, + height: stepY, + cx: x - cx, + cy: y - cy + }; + + y -= stepY; + l++; + } + + x -= stepX; + i++; + } + } else { + el = this.options.snap; + l = el.length; + n = -1; + + for ( ; i < l; i++ ) { + if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) { + m = 0; + n++; + } + + if ( !this.pages[m] ) { + this.pages[m] = []; + } + + x = Math.max(-el[i].offsetLeft, this.maxScrollX); + y = Math.max(-el[i].offsetTop, this.maxScrollY); + cx = x - Math.round(el[i].offsetWidth / 2); + cy = y - Math.round(el[i].offsetHeight / 2); + + this.pages[m][n] = { + x: x, + y: y, + width: el[i].offsetWidth, + height: el[i].offsetHeight, + cx: cx, + cy: cy + }; + + if ( x > this.maxScrollX ) { + m++; + } + } + } + + this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); + + // Update snap threshold if needed + if ( this.options.snapThreshold % 1 === 0 ) { + this.snapThresholdX = this.options.snapThreshold; + this.snapThresholdY = this.options.snapThreshold; + } else { + this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); + this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); + } + }); + + this.on('flick', function () { + var time = this.options.snapSpeed || Math.max( + Math.max( + Math.min(Math.abs(this.x - this.startX), 1000), + Math.min(Math.abs(this.y - this.startY), 1000) + ), 300); + + this.goToPage( + this.currentPage.pageX + this.directionX, + this.currentPage.pageY + this.directionY, + time + ); + }); + }, + + _nearestSnap: function (x, y) { + if ( !this.pages.length ) { + return { x: 0, y: 0, pageX: 0, pageY: 0 }; + } + + var i = 0, + l = this.pages.length, + m = 0; + + // Check if we exceeded the snap threshold + if ( Math.abs(x - this.absStartX) < this.snapThresholdX && + Math.abs(y - this.absStartY) < this.snapThresholdY ) { + return this.currentPage; + } + + if ( x > 0 ) { + x = 0; + } else if ( x < this.maxScrollX ) { + x = this.maxScrollX; + } + + if ( y > 0 ) { + y = 0; + } else if ( y < this.maxScrollY ) { + y = this.maxScrollY; + } + + for ( ; i < l; i++ ) { + if ( x >= this.pages[i][0].cx ) { + x = this.pages[i][0].x; + break; + } + } + + l = this.pages[i].length; + + for ( ; m < l; m++ ) { + if ( y >= this.pages[0][m].cy ) { + y = this.pages[0][m].y; + break; + } + } + + if ( i == this.currentPage.pageX ) { + i += this.directionX; + + if ( i < 0 ) { + i = 0; + } else if ( i >= this.pages.length ) { + i = this.pages.length - 1; + } + + x = this.pages[i][0].x; + } + + if ( m == this.currentPage.pageY ) { + m += this.directionY; + + if ( m < 0 ) { + m = 0; + } else if ( m >= this.pages[0].length ) { + m = this.pages[0].length - 1; + } + + y = this.pages[0][m].y; + } + + return { + x: x, + y: y, + pageX: i, + pageY: m + }; + }, + + goToPage: function (x, y, time, easing) { + easing = easing || this.options.bounceEasing; + + if ( x >= this.pages.length ) { + x = this.pages.length - 1; + } else if ( x < 0 ) { + x = 0; + } + + if ( y >= this.pages[x].length ) { + y = this.pages[x].length - 1; + } else if ( y < 0 ) { + y = 0; + } + + var posX = this.pages[x][y].x, + posY = this.pages[x][y].y; + + time = time === undefined ? this.options.snapSpeed || Math.max( + Math.max( + Math.min(Math.abs(posX - this.x), 1000), + Math.min(Math.abs(posY - this.y), 1000) + ), 300) : time; + + this.currentPage = { + x: posX, + y: posY, + pageX: x, + pageY: y + }; + + this.scrollTo(posX, posY, time, easing); + }, + + next: function (time, easing) { + var x = this.currentPage.pageX, + y = this.currentPage.pageY; + + x++; + + if ( x >= this.pages.length && this.hasVerticalScroll ) { + x = 0; + y++; + } + + this.goToPage(x, y, time, easing); + }, + + prev: function (time, easing) { + var x = this.currentPage.pageX, + y = this.currentPage.pageY; + + x--; + + if ( x < 0 && this.hasVerticalScroll ) { + x = 0; + y--; + } + + this.goToPage(x, y, time, easing); + }, + + _initKeys: function (e) { + // default key bindings + var keys = { + pageUp: 33, + pageDown: 34, + end: 35, + home: 36, + left: 37, + up: 38, + right: 39, + down: 40 + }; + var i; + + // if you give me characters I give you keycode + if ( typeof this.options.keyBindings == 'object' ) { + for ( i in this.options.keyBindings ) { + if ( typeof this.options.keyBindings[i] == 'string' ) { + this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0); + } + } + } else { + this.options.keyBindings = {}; + } + + for ( i in keys ) { + this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i]; + } + + utils.addEvent(window, 'keydown', this); + + this.on('destroy', function () { + utils.removeEvent(window, 'keydown', this); + }); + }, + + _key: function (e) { + if ( !this.enabled ) { + return; + } + + var snap = this.options.snap, // we are using this alot, better to cache it + newX = snap ? this.currentPage.pageX : this.x, + newY = snap ? this.currentPage.pageY : this.y, + now = utils.getTime(), + prevTime = this.keyTime || 0, + acceleration = 0.250, + pos; + + if ( this.options.useTransition && this.isInTransition ) { + pos = this.getComputedPosition(); + + this._translate(Math.round(pos.x), Math.round(pos.y)); + this.isInTransition = false; + } + + this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0; + + switch ( e.keyCode ) { + case this.options.keyBindings.pageUp: + if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { + newX += snap ? 1 : this.wrapperWidth; + } else { + newY += snap ? 1 : this.wrapperHeight; + } + break; + case this.options.keyBindings.pageDown: + if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { + newX -= snap ? 1 : this.wrapperWidth; + } else { + newY -= snap ? 1 : this.wrapperHeight; + } + break; + case this.options.keyBindings.end: + newX = snap ? this.pages.length-1 : this.maxScrollX; + newY = snap ? this.pages[0].length-1 : this.maxScrollY; + break; + case this.options.keyBindings.home: + newX = 0; + newY = 0; + break; + case this.options.keyBindings.left: + newX += snap ? -1 : 5 + this.keyAcceleration>>0; + break; + case this.options.keyBindings.up: + newY += snap ? 1 : 5 + this.keyAcceleration>>0; + break; + case this.options.keyBindings.right: + newX -= snap ? -1 : 5 + this.keyAcceleration>>0; + break; + case this.options.keyBindings.down: + newY -= snap ? 1 : 5 + this.keyAcceleration>>0; + break; + default: + return; + } + + if ( snap ) { + this.goToPage(newX, newY); + return; + } + + if ( newX > 0 ) { + newX = 0; + this.keyAcceleration = 0; + } else if ( newX < this.maxScrollX ) { + newX = this.maxScrollX; + this.keyAcceleration = 0; + } + + if ( newY > 0 ) { + newY = 0; + this.keyAcceleration = 0; + } else if ( newY < this.maxScrollY ) { + newY = this.maxScrollY; + this.keyAcceleration = 0; + } + + this.scrollTo(newX, newY, 0); + + this.keyTime = now; + }, + + _animate: function (destX, destY, duration, easingFn) { + var that = this, + startX = this.x, + startY = this.y, + startTime = utils.getTime(), + destTime = startTime + duration; + + function step () { + var now = utils.getTime(), + newX, newY, + easing; + + if ( now >= destTime ) { + that.isAnimating = false; + that._translate(destX, destY); + + if ( !that.resetPosition(that.options.bounceTime) ) { + that._execEvent('scrollEnd'); + } + + return; + } + + now = ( now - startTime ) / duration; + easing = easingFn(now); + newX = ( destX - startX ) * easing + startX; + newY = ( destY - startY ) * easing + startY; + that._translate(newX, newY); + + if ( that.isAnimating ) { + rAF(step); + } + } + + this.isAnimating = true; + step(); + }, + handleEvent: function (e) { + switch ( e.type ) { + case 'touchstart': + case 'pointerdown': + case 'MSPointerDown': + case 'mousedown': + this._start(e); + break; + case 'touchmove': + case 'pointermove': + case 'MSPointerMove': + case 'mousemove': + this._move(e); + break; + case 'touchend': + case 'pointerup': + case 'MSPointerUp': + case 'mouseup': + case 'touchcancel': + case 'pointercancel': + case 'MSPointerCancel': + case 'mousecancel': + this._end(e); + break; + case 'orientationchange': + case 'resize': + this._resize(); + break; + case 'transitionend': + case 'webkitTransitionEnd': + case 'oTransitionEnd': + case 'MSTransitionEnd': + this._transitionEnd(e); + break; + case 'wheel': + case 'DOMMouseScroll': + case 'mousewheel': + this._wheel(e); + break; + case 'keydown': + this._key(e); + break; + case 'click': + if ( this.enabled && !e._constructed ) { + e.preventDefault(); + e.stopPropagation(); + } + break; + } + } +}; +function createDefaultScrollbar (direction, interactive, type) { + var scrollbar = document.createElement('div'), + indicator = document.createElement('div'); + + if ( type === true ) { + scrollbar.style.cssText = 'position:absolute;z-index:9999'; + indicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px'; + } + + indicator.className = 'iScrollIndicator'; + + if ( direction == 'h' ) { + if ( type === true ) { + scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0'; + indicator.style.height = '100%'; + } + scrollbar.className = 'iScrollHorizontalScrollbar'; + } else { + if ( type === true ) { + scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px'; + indicator.style.width = '100%'; + } + scrollbar.className = 'iScrollVerticalScrollbar'; + } + + scrollbar.style.cssText += ';overflow:hidden'; + + if ( !interactive ) { + scrollbar.style.pointerEvents = 'none'; + } + + scrollbar.appendChild(indicator); + + return scrollbar; +} + +function Indicator (scroller, options) { + this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el; + this.wrapperStyle = this.wrapper.style; + this.indicator = this.wrapper.children[0]; + this.indicatorStyle = this.indicator.style; + this.scroller = scroller; + + this.options = { + listenX: true, + listenY: true, + interactive: false, + resize: true, + defaultScrollbars: false, + shrink: false, + fade: false, + speedRatioX: 0, + speedRatioY: 0 + }; + + for ( var i in options ) { + this.options[i] = options[i]; + } + + this.sizeRatioX = 1; + this.sizeRatioY = 1; + this.maxPosX = 0; + this.maxPosY = 0; + + if ( this.options.interactive ) { + if ( !this.options.disableTouch ) { + utils.addEvent(this.indicator, 'touchstart', this); + utils.addEvent(window, 'touchend', this); + } + if ( !this.options.disablePointer ) { + utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); + utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this); + } + if ( !this.options.disableMouse ) { + utils.addEvent(this.indicator, 'mousedown', this); + utils.addEvent(window, 'mouseup', this); + } + } + + if ( this.options.fade ) { + this.wrapperStyle[utils.style.transform] = this.scroller.translateZ; + var durationProp = utils.style.transitionDuration; + this.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms'; + // remove 0.0001ms + var self = this; + if(utils.isBadAndroid) { + rAF(function() { + if(self.wrapperStyle[durationProp] === '0.0001ms') { + self.wrapperStyle[durationProp] = '0s'; + } + }); + } + this.wrapperStyle.opacity = '0'; + } +} + +Indicator.prototype = { + handleEvent: function (e) { + switch ( e.type ) { + case 'touchstart': + case 'pointerdown': + case 'MSPointerDown': + case 'mousedown': + this._start(e); + break; + case 'touchmove': + case 'pointermove': + case 'MSPointerMove': + case 'mousemove': + this._move(e); + break; + case 'touchend': + case 'pointerup': + case 'MSPointerUp': + case 'mouseup': + case 'touchcancel': + case 'pointercancel': + case 'MSPointerCancel': + case 'mousecancel': + this._end(e); + break; + } + }, + + destroy: function () { + if ( this.options.fadeScrollbars ) { + clearTimeout(this.fadeTimeout); + this.fadeTimeout = null; + } + if ( this.options.interactive ) { + utils.removeEvent(this.indicator, 'touchstart', this); + utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this); + utils.removeEvent(this.indicator, 'mousedown', this); + + utils.removeEvent(window, 'touchmove', this); + utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); + utils.removeEvent(window, 'mousemove', this); + + utils.removeEvent(window, 'touchend', this); + utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this); + utils.removeEvent(window, 'mouseup', this); + } + + if ( this.options.defaultScrollbars ) { + this.wrapper.parentNode.removeChild(this.wrapper); + } + }, + + _start: function (e) { + var point = e.touches ? e.touches[0] : e; + + e.preventDefault(); + e.stopPropagation(); + + this.transitionTime(); + + this.initiated = true; + this.moved = false; + this.lastPointX = point.pageX; + this.lastPointY = point.pageY; + + this.startTime = utils.getTime(); + + if ( !this.options.disableTouch ) { + utils.addEvent(window, 'touchmove', this); + } + if ( !this.options.disablePointer ) { + utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this); + } + if ( !this.options.disableMouse ) { + utils.addEvent(window, 'mousemove', this); + } + + this.scroller._execEvent('beforeScrollStart'); + }, + + _move: function (e) { + var point = e.touches ? e.touches[0] : e, + deltaX, deltaY, + newX, newY, + timestamp = utils.getTime(); + + if ( !this.moved ) { + this.scroller._execEvent('scrollStart'); + } + + this.moved = true; + + deltaX = point.pageX - this.lastPointX; + this.lastPointX = point.pageX; + + deltaY = point.pageY - this.lastPointY; + this.lastPointY = point.pageY; + + newX = this.x + deltaX; + newY = this.y + deltaY; + + this._pos(newX, newY); + +// INSERT POINT: indicator._move + + e.preventDefault(); + e.stopPropagation(); + }, + + _end: function (e) { + if ( !this.initiated ) { + return; + } + + this.initiated = false; + + e.preventDefault(); + e.stopPropagation(); + + utils.removeEvent(window, 'touchmove', this); + utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this); + utils.removeEvent(window, 'mousemove', this); + + if ( this.scroller.options.snap ) { + var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y); + + var time = this.options.snapSpeed || Math.max( + Math.max( + Math.min(Math.abs(this.scroller.x - snap.x), 1000), + Math.min(Math.abs(this.scroller.y - snap.y), 1000) + ), 300); + + if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) { + this.scroller.directionX = 0; + this.scroller.directionY = 0; + this.scroller.currentPage = snap; + this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing); + } + } + + if ( this.moved ) { + this.scroller._execEvent('scrollEnd'); + } + }, + + transitionTime: function (time) { + time = time || 0; + var durationProp = utils.style.transitionDuration; + this.indicatorStyle[durationProp] = time + 'ms'; + + if ( !time && utils.isBadAndroid ) { + this.indicatorStyle[durationProp] = '0.0001ms'; + // remove 0.0001ms + var self = this; + rAF(function() { + if(self.indicatorStyle[durationProp] === '0.0001ms') { + self.indicatorStyle[durationProp] = '0s'; + } + }); + } + }, + + transitionTimingFunction: function (easing) { + this.indicatorStyle[utils.style.transitionTimingFunction] = easing; + }, + + refresh: function () { + this.transitionTime(); + + if ( this.options.listenX && !this.options.listenY ) { + this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none'; + } else if ( this.options.listenY && !this.options.listenX ) { + this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none'; + } else { + this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none'; + } + + if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) { + utils.addClass(this.wrapper, 'iScrollBothScrollbars'); + utils.removeClass(this.wrapper, 'iScrollLoneScrollbar'); + + if ( this.options.defaultScrollbars && this.options.customStyle ) { + if ( this.options.listenX ) { + this.wrapper.style.right = '8px'; + } else { + this.wrapper.style.bottom = '8px'; + } + } + } else { + utils.removeClass(this.wrapper, 'iScrollBothScrollbars'); + utils.addClass(this.wrapper, 'iScrollLoneScrollbar'); + + if ( this.options.defaultScrollbars && this.options.customStyle ) { + if ( this.options.listenX ) { + this.wrapper.style.right = '2px'; + } else { + this.wrapper.style.bottom = '2px'; + } + } + } + + var r = this.wrapper.offsetHeight; // force refresh + + if ( this.options.listenX ) { + this.wrapperWidth = this.wrapper.clientWidth; + if ( this.options.resize ) { + this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8); + this.indicatorStyle.width = this.indicatorWidth + 'px'; + } else { + this.indicatorWidth = this.indicator.clientWidth; + } + + this.maxPosX = this.wrapperWidth - this.indicatorWidth; + + if ( this.options.shrink == 'clip' ) { + this.minBoundaryX = -this.indicatorWidth + 8; + this.maxBoundaryX = this.wrapperWidth - 8; + } else { + this.minBoundaryX = 0; + this.maxBoundaryX = this.maxPosX; + } + + this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX)); + } + + if ( this.options.listenY ) { + this.wrapperHeight = this.wrapper.clientHeight; + if ( this.options.resize ) { + this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8); + this.indicatorStyle.height = this.indicatorHeight + 'px'; + } else { + this.indicatorHeight = this.indicator.clientHeight; + } + + this.maxPosY = this.wrapperHeight - this.indicatorHeight; + + if ( this.options.shrink == 'clip' ) { + this.minBoundaryY = -this.indicatorHeight + 8; + this.maxBoundaryY = this.wrapperHeight - 8; + } else { + this.minBoundaryY = 0; + this.maxBoundaryY = this.maxPosY; + } + + this.maxPosY = this.wrapperHeight - this.indicatorHeight; + this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY)); + } + + this.updatePosition(); + }, + + updatePosition: function () { + var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0, + y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0; + + if ( !this.options.ignoreBoundaries ) { + if ( x < this.minBoundaryX ) { + if ( this.options.shrink == 'scale' ) { + this.width = Math.max(this.indicatorWidth + x, 8); + this.indicatorStyle.width = this.width + 'px'; + } + x = this.minBoundaryX; + } else if ( x > this.maxBoundaryX ) { + if ( this.options.shrink == 'scale' ) { + this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8); + this.indicatorStyle.width = this.width + 'px'; + x = this.maxPosX + this.indicatorWidth - this.width; + } else { + x = this.maxBoundaryX; + } + } else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) { + this.width = this.indicatorWidth; + this.indicatorStyle.width = this.width + 'px'; + } + + if ( y < this.minBoundaryY ) { + if ( this.options.shrink == 'scale' ) { + this.height = Math.max(this.indicatorHeight + y * 3, 8); + this.indicatorStyle.height = this.height + 'px'; + } + y = this.minBoundaryY; + } else if ( y > this.maxBoundaryY ) { + if ( this.options.shrink == 'scale' ) { + this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8); + this.indicatorStyle.height = this.height + 'px'; + y = this.maxPosY + this.indicatorHeight - this.height; + } else { + y = this.maxBoundaryY; + } + } else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) { + this.height = this.indicatorHeight; + this.indicatorStyle.height = this.height + 'px'; + } + } + + this.x = x; + this.y = y; + + if ( this.scroller.options.useTransform ) { + this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ; + } else { + this.indicatorStyle.left = x + 'px'; + this.indicatorStyle.top = y + 'px'; + } + }, + + _pos: function (x, y) { + if ( x < 0 ) { + x = 0; + } else if ( x > this.maxPosX ) { + x = this.maxPosX; + } + + if ( y < 0 ) { + y = 0; + } else if ( y > this.maxPosY ) { + y = this.maxPosY; + } + + x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x; + y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y; + + this.scroller.scrollTo(x, y); + }, + + fade: function (val, hold) { + if ( hold && !this.visible ) { + return; + } + + clearTimeout(this.fadeTimeout); + this.fadeTimeout = null; + + var time = val ? 250 : 500, + delay = val ? 0 : 300; + + val = val ? '1' : '0'; + + this.wrapperStyle[utils.style.transitionDuration] = time + 'ms'; + + this.fadeTimeout = setTimeout((function (val) { + this.wrapperStyle.opacity = val; + this.visible = +val; + }).bind(this, val), delay); + } +}; + +IScroll.utils = utils; + +if ( typeof module != 'undefined' && module.exports ) { + module.exports = IScroll; +} else if ( typeof define == 'function' && define.amd ) { + define( function () { return IScroll; } ); +} else { + window.IScroll = IScroll; +} + +})(window, document, Math); diff --git a/assets/js/dev/vendors/isotope.pkgd.js b/assets/js/dev/vendors/isotope.pkgd.js new file mode 100644 index 0000000..40561c1 --- /dev/null +++ b/assets/js/dev/vendors/isotope.pkgd.js @@ -0,0 +1,4257 @@ +/*! + * Isotope PACKAGED v2.2.2 + * + * Licensed GPLv3 for open source use + * or Isotope Commercial License for commercial use + * + * http://isotope.metafizzy.co + * Copyright 2015 Metafizzy + */ + +/** + * Bridget makes jQuery widgets + * v1.1.0 + * MIT license + */ + +( function( window ) { + + + +// -------------------------- utils -------------------------- // + +var slice = Array.prototype.slice; + +function noop() {} + +// -------------------------- definition -------------------------- // + +function defineBridget( $ ) { + +// bail if no jQuery +if ( !$ ) { + return; +} + +// -------------------------- addOptionMethod -------------------------- // + +/** + * adds option method -> $().plugin('option', {...}) + * @param {Function} PluginClass - constructor class + */ +function addOptionMethod( PluginClass ) { + // don't overwrite original option method + if ( PluginClass.prototype.option ) { + return; + } + + // option setter + PluginClass.prototype.option = function( opts ) { + // bail out if not an object + if ( !$.isPlainObject( opts ) ){ + return; + } + this.options = $.extend( true, this.options, opts ); + }; +} + +// -------------------------- plugin bridge -------------------------- // + +// helper function for logging errors +// $.error breaks jQuery chaining +var logError = typeof console === 'undefined' ? noop : + function( message ) { + console.error( message ); + }; + +/** + * jQuery plugin bridge, access methods like $elem.plugin('method') + * @param {String} namespace - plugin name + * @param {Function} PluginClass - constructor class + */ +function bridge( namespace, PluginClass ) { + // add to jQuery fn namespace + $.fn[ namespace ] = function( options ) { + if ( typeof options === 'string' ) { + // call plugin method when first argument is a string + // get arguments for method + var args = slice.call( arguments, 1 ); + + for ( var i=0, len = this.length; i < len; i++ ) { + var elem = this[i]; + var instance = $.data( elem, namespace ); + if ( !instance ) { + logError( "cannot call methods on " + namespace + " prior to initialization; " + + "attempted to call '" + options + "'" ); + continue; + } + if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) { + logError( "no such method '" + options + "' for " + namespace + " instance" ); + continue; + } + + // trigger method with arguments + var returnValue = instance[ options ].apply( instance, args ); + + // break look and return first value if provided + if ( returnValue !== undefined ) { + return returnValue; + } + } + // return this if no return value + return this; + } else { + return this.each( function() { + var instance = $.data( this, namespace ); + if ( instance ) { + // apply options & init + instance.option( options ); + instance._init(); + } else { + // initialize new instance + instance = new PluginClass( this, options ); + $.data( this, namespace, instance ); + } + }); + } + }; + +} + +// -------------------------- bridget -------------------------- // + +/** + * converts a Prototypical class into a proper jQuery plugin + * the class must have a ._init method + * @param {String} namespace - plugin name, used in $().pluginName + * @param {Function} PluginClass - constructor class + */ +$.bridget = function( namespace, PluginClass ) { + addOptionMethod( PluginClass ); + bridge( namespace, PluginClass ); +}; + +return $.bridget; + +} + +// transport +if ( typeof define === 'function' && define.amd ) { + // AMD + define( 'jquery-bridget/jquery.bridget',[ 'jquery' ], defineBridget ); +} else if ( typeof exports === 'object' ) { + defineBridget( require('jquery') ); +} else { + // get jquery from browser global + defineBridget( window.jQuery ); +} + +})( window ); + +/*! + * eventie v1.0.6 + * event binding helper + * eventie.bind( elem, 'click', myFn ) + * eventie.unbind( elem, 'click', myFn ) + * MIT license + */ + +/*jshint browser: true, undef: true, unused: true */ +/*global define: false, module: false */ + +( function( window ) { + + + +var docElem = document.documentElement; + +var bind = function() {}; + +function getIEEvent( obj ) { + var event = window.event; + // add event.target + event.target = event.target || event.srcElement || obj; + return event; +} + +if ( docElem.addEventListener ) { + bind = function( obj, type, fn ) { + obj.addEventListener( type, fn, false ); + }; +} else if ( docElem.attachEvent ) { + bind = function( obj, type, fn ) { + obj[ type + fn ] = fn.handleEvent ? + function() { + var event = getIEEvent( obj ); + fn.handleEvent.call( fn, event ); + } : + function() { + var event = getIEEvent( obj ); + fn.call( obj, event ); + }; + obj.attachEvent( "on" + type, obj[ type + fn ] ); + }; +} + +var unbind = function() {}; + +if ( docElem.removeEventListener ) { + unbind = function( obj, type, fn ) { + obj.removeEventListener( type, fn, false ); + }; +} else if ( docElem.detachEvent ) { + unbind = function( obj, type, fn ) { + obj.detachEvent( "on" + type, obj[ type + fn ] ); + try { + delete obj[ type + fn ]; + } catch ( err ) { + // can't delete window object properties + obj[ type + fn ] = undefined; + } + }; +} + +var eventie = { + bind: bind, + unbind: unbind +}; + +// ----- module definition ----- // + +if ( typeof define === 'function' && define.amd ) { + // AMD + define( 'eventie/eventie',eventie ); +} else if ( typeof exports === 'object' ) { + // CommonJS + module.exports = eventie; +} else { + // browser global + window.eventie = eventie; +} + +})( window ); + +/*! + * EventEmitter v4.2.11 - git.io/ee + * Unlicense - http://unlicense.org/ + * Oliver Caldwell - http://oli.me.uk/ + * @preserve + */ + +;(function () { + 'use strict'; + + /** + * Class for managing events. + * Can be extended to provide event functionality in other classes. + * + * @class EventEmitter Manages event registering and emitting. + */ + function EventEmitter() {} + + // Shortcuts to improve speed and size + var proto = EventEmitter.prototype; + var exports = this; + var originalGlobalValue = exports.EventEmitter; + + /** + * Finds the index of the listener for the event in its storage array. + * + * @param {Function[]} listeners Array of listeners to search through. + * @param {Function} listener Method to look for. + * @return {Number} Index of the specified listener, -1 if not found + * @api private + */ + function indexOfListener(listeners, listener) { + var i = listeners.length; + while (i--) { + if (listeners[i].listener === listener) { + return i; + } + } + + return -1; + } + + /** + * Alias a method while keeping the context correct, to allow for overwriting of target method. + * + * @param {String} name The name of the target method. + * @return {Function} The aliased method + * @api private + */ + function alias(name) { + return function aliasClosure() { + return this[name].apply(this, arguments); + }; + } + + /** + * Returns the listener array for the specified event. + * Will initialise the event object and listener arrays if required. + * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. + * Each property in the object response is an array of listener functions. + * + * @param {String|RegExp} evt Name of the event to return the listeners from. + * @return {Function[]|Object} All listener functions for the event. + */ + proto.getListeners = function getListeners(evt) { + var events = this._getEvents(); + var response; + var key; + + // Return a concatenated array of all matching events if + // the selector is a regular expression. + if (evt instanceof RegExp) { + response = {}; + for (key in events) { + if (events.hasOwnProperty(key) && evt.test(key)) { + response[key] = events[key]; + } + } + } + else { + response = events[evt] || (events[evt] = []); + } + + return response; + }; + + /** + * Takes a list of listener objects and flattens it into a list of listener functions. + * + * @param {Object[]} listeners Raw listener objects. + * @return {Function[]} Just the listener functions. + */ + proto.flattenListeners = function flattenListeners(listeners) { + var flatListeners = []; + var i; + + for (i = 0; i < listeners.length; i += 1) { + flatListeners.push(listeners[i].listener); + } + + return flatListeners; + }; + + /** + * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. + * + * @param {String|RegExp} evt Name of the event to return the listeners from. + * @return {Object} All listener functions for an event in an object. + */ + proto.getListenersAsObject = function getListenersAsObject(evt) { + var listeners = this.getListeners(evt); + var response; + + if (listeners instanceof Array) { + response = {}; + response[evt] = listeners; + } + + return response || listeners; + }; + + /** + * Adds a listener function to the specified event. + * The listener will not be added if it is a duplicate. + * If the listener returns true then it will be removed after it is called. + * If you pass a regular expression as the event name then the listener will be added to all events that match it. + * + * @param {String|RegExp} evt Name of the event to attach the listener to. + * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addListener = function addListener(evt, listener) { + var listeners = this.getListenersAsObject(evt); + var listenerIsWrapped = typeof listener === 'object'; + var key; + + for (key in listeners) { + if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { + listeners[key].push(listenerIsWrapped ? listener : { + listener: listener, + once: false + }); + } + } + + return this; + }; + + /** + * Alias of addListener + */ + proto.on = alias('addListener'); + + /** + * Semi-alias of addListener. It will add a listener that will be + * automatically removed after its first execution. + * + * @param {String|RegExp} evt Name of the event to attach the listener to. + * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addOnceListener = function addOnceListener(evt, listener) { + return this.addListener(evt, { + listener: listener, + once: true + }); + }; + + /** + * Alias of addOnceListener. + */ + proto.once = alias('addOnceListener'); + + /** + * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. + * You need to tell it what event names should be matched by a regex. + * + * @param {String} evt Name of the event to create. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.defineEvent = function defineEvent(evt) { + this.getListeners(evt); + return this; + }; + + /** + * Uses defineEvent to define multiple events. + * + * @param {String[]} evts An array of event names to define. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.defineEvents = function defineEvents(evts) { + for (var i = 0; i < evts.length; i += 1) { + this.defineEvent(evts[i]); + } + return this; + }; + + /** + * Removes a listener function from the specified event. + * When passed a regular expression as the event name, it will remove the listener from all events that match it. + * + * @param {String|RegExp} evt Name of the event to remove the listener from. + * @param {Function} listener Method to remove from the event. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeListener = function removeListener(evt, listener) { + var listeners = this.getListenersAsObject(evt); + var index; + var key; + + for (key in listeners) { + if (listeners.hasOwnProperty(key)) { + index = indexOfListener(listeners[key], listener); + + if (index !== -1) { + listeners[key].splice(index, 1); + } + } + } + + return this; + }; + + /** + * Alias of removeListener + */ + proto.off = alias('removeListener'); + + /** + * Adds listeners in bulk using the manipulateListeners method. + * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. + * You can also pass it a regular expression to add the array of listeners to all events that match it. + * Yeah, this function does quite a bit. That's probably a bad thing. + * + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to add. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.addListeners = function addListeners(evt, listeners) { + // Pass through to manipulateListeners + return this.manipulateListeners(false, evt, listeners); + }; + + /** + * Removes listeners in bulk using the manipulateListeners method. + * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. + * You can also pass it an event name and an array of listeners to be removed. + * You can also pass it a regular expression to remove the listeners from all events that match it. + * + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to remove. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeListeners = function removeListeners(evt, listeners) { + // Pass through to manipulateListeners + return this.manipulateListeners(true, evt, listeners); + }; + + /** + * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. + * The first argument will determine if the listeners are removed (true) or added (false). + * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. + * You can also pass it an event name and an array of listeners to be added/removed. + * You can also pass it a regular expression to manipulate the listeners of all events that match it. + * + * @param {Boolean} remove True if you want to remove listeners, false if you want to add. + * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. + * @param {Function[]} [listeners] An optional array of listener functions to add/remove. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { + var i; + var value; + var single = remove ? this.removeListener : this.addListener; + var multiple = remove ? this.removeListeners : this.addListeners; + + // If evt is an object then pass each of its properties to this method + if (typeof evt === 'object' && !(evt instanceof RegExp)) { + for (i in evt) { + if (evt.hasOwnProperty(i) && (value = evt[i])) { + // Pass the single listener straight through to the singular method + if (typeof value === 'function') { + single.call(this, i, value); + } + else { + // Otherwise pass back to the multiple function + multiple.call(this, i, value); + } + } + } + } + else { + // So evt must be a string + // And listeners must be an array of listeners + // Loop over it and pass each one to the multiple method + i = listeners.length; + while (i--) { + single.call(this, evt, listeners[i]); + } + } + + return this; + }; + + /** + * Removes all listeners from a specified event. + * If you do not specify an event then all listeners will be removed. + * That means every event will be emptied. + * You can also pass a regex to remove all events that match it. + * + * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.removeEvent = function removeEvent(evt) { + var type = typeof evt; + var events = this._getEvents(); + var key; + + // Remove different things depending on the state of evt + if (type === 'string') { + // Remove all listeners for the specified event + delete events[evt]; + } + else if (evt instanceof RegExp) { + // Remove all events matching the regex. + for (key in events) { + if (events.hasOwnProperty(key) && evt.test(key)) { + delete events[key]; + } + } + } + else { + // Remove all listeners in all events + delete this._events; + } + + return this; + }; + + /** + * Alias of removeEvent. + * + * Added to mirror the node API. + */ + proto.removeAllListeners = alias('removeEvent'); + + /** + * Emits an event of your choice. + * When emitted, every listener attached to that event will be executed. + * If you pass the optional argument array then those arguments will be passed to every listener upon execution. + * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. + * So they will not arrive within the array on the other side, they will be separate. + * You can also pass a regular expression to emit to all events that match it. + * + * @param {String|RegExp} evt Name of the event to emit and execute listeners for. + * @param {Array} [args] Optional array of arguments to be passed to each listener. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.emitEvent = function emitEvent(evt, args) { + var listeners = this.getListenersAsObject(evt); + var listener; + var i; + var key; + var response; + + for (key in listeners) { + if (listeners.hasOwnProperty(key)) { + i = listeners[key].length; + + while (i--) { + // If the listener returns true then it shall be removed from the event + // The function is executed either with a basic call or an apply if there is an args array + listener = listeners[key][i]; + + if (listener.once === true) { + this.removeListener(evt, listener.listener); + } + + response = listener.listener.apply(this, args || []); + + if (response === this._getOnceReturnValue()) { + this.removeListener(evt, listener.listener); + } + } + } + } + + return this; + }; + + /** + * Alias of emitEvent + */ + proto.trigger = alias('emitEvent'); + + /** + * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. + * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. + * + * @param {String|RegExp} evt Name of the event to emit and execute listeners for. + * @param {...*} Optional additional arguments to be passed to each listener. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.emit = function emit(evt) { + var args = Array.prototype.slice.call(arguments, 1); + return this.emitEvent(evt, args); + }; + + /** + * Sets the current value to check against when executing listeners. If a + * listeners return value matches the one set here then it will be removed + * after execution. This value defaults to true. + * + * @param {*} value The new value to check for when executing listeners. + * @return {Object} Current instance of EventEmitter for chaining. + */ + proto.setOnceReturnValue = function setOnceReturnValue(value) { + this._onceReturnValue = value; + return this; + }; + + /** + * Fetches the current value to check against when executing listeners. If + * the listeners return value matches this one then it should be removed + * automatically. It will return true by default. + * + * @return {*|Boolean} The current value to check for or the default, true. + * @api private + */ + proto._getOnceReturnValue = function _getOnceReturnValue() { + if (this.hasOwnProperty('_onceReturnValue')) { + return this._onceReturnValue; + } + else { + return true; + } + }; + + /** + * Fetches the events object and creates one if required. + * + * @return {Object} The events storage object. + * @api private + */ + proto._getEvents = function _getEvents() { + return this._events || (this._events = {}); + }; + + /** + * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. + * + * @return {Function} Non conflicting EventEmitter class. + */ + EventEmitter.noConflict = function noConflict() { + exports.EventEmitter = originalGlobalValue; + return EventEmitter; + }; + + // Expose the class either via AMD, CommonJS or the global object + if (typeof define === 'function' && define.amd) { + define('eventEmitter/EventEmitter',[],function () { + return EventEmitter; + }); + } + else if (typeof module === 'object' && module.exports){ + module.exports = EventEmitter; + } + else { + exports.EventEmitter = EventEmitter; + } +}.call(this)); + +/*! + * getStyleProperty v1.0.4 + * original by kangax + * http://perfectionkills.com/feature-testing-css-properties/ + * MIT license + */ + +/*jshint browser: true, strict: true, undef: true */ +/*global define: false, exports: false, module: false */ + +( function( window ) { + + + +var prefixes = 'Webkit Moz ms Ms O'.split(' '); +var docElemStyle = document.documentElement.style; + +function getStyleProperty( propName ) { + if ( !propName ) { + return; + } + + // test standard property first + if ( typeof docElemStyle[ propName ] === 'string' ) { + return propName; + } + + // capitalize + propName = propName.charAt(0).toUpperCase() + propName.slice(1); + + // test vendor specific properties + var prefixed; + for ( var i=0, len = prefixes.length; i < len; i++ ) { + prefixed = prefixes[i] + propName; + if ( typeof docElemStyle[ prefixed ] === 'string' ) { + return prefixed; + } + } +} + +// transport +if ( typeof define === 'function' && define.amd ) { + // AMD + define( 'get-style-property/get-style-property',[],function() { + return getStyleProperty; + }); +} else if ( typeof exports === 'object' ) { + // CommonJS for Component + module.exports = getStyleProperty; +} else { + // browser global + window.getStyleProperty = getStyleProperty; +} + +})( window ); + +/*! + * getSize v1.2.2 + * measure size of elements + * MIT license + */ + +/*jshint browser: true, strict: true, undef: true, unused: true */ +/*global define: false, exports: false, require: false, module: false, console: false */ + +( function( window, undefined ) { + + + +// -------------------------- helpers -------------------------- // + +// get a number from a string, not a percentage +function getStyleSize( value ) { + var num = parseFloat( value ); + // not a percent like '100%', and a number + var isValid = value.indexOf('%') === -1 && !isNaN( num ); + return isValid && num; +} + +function noop() {} + +var logError = typeof console === 'undefined' ? noop : + function( message ) { + console.error( message ); + }; + +// -------------------------- measurements -------------------------- // + +var measurements = [ + 'paddingLeft', + 'paddingRight', + 'paddingTop', + 'paddingBottom', + 'marginLeft', + 'marginRight', + 'marginTop', + 'marginBottom', + 'borderLeftWidth', + 'borderRightWidth', + 'borderTopWidth', + 'borderBottomWidth' +]; + +function getZeroSize() { + var size = { + width: 0, + height: 0, + innerWidth: 0, + innerHeight: 0, + outerWidth: 0, + outerHeight: 0 + }; + for ( var i=0, len = measurements.length; i < len; i++ ) { + var measurement = measurements[i]; + size[ measurement ] = 0; + } + return size; +} + + + +function defineGetSize( getStyleProperty ) { + +// -------------------------- setup -------------------------- // + +var isSetup = false; + +var getStyle, boxSizingProp, isBoxSizeOuter; + +/** + * setup vars and functions + * do it on initial getSize(), rather than on script load + * For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397 + */ +function setup() { + // setup once + if ( isSetup ) { + return; + } + isSetup = true; + + var getComputedStyle = window.getComputedStyle; + getStyle = ( function() { + var getStyleFn = getComputedStyle ? + function( elem ) { + return getComputedStyle( elem, null ); + } : + function( elem ) { + return elem.currentStyle; + }; + + return function getStyle( elem ) { + var style = getStyleFn( elem ); + if ( !style ) { + logError( 'Style returned ' + style + + '. Are you running this code in a hidden iframe on Firefox? ' + + 'See http://bit.ly/getsizebug1' ); + } + return style; + }; + })(); + + // -------------------------- box sizing -------------------------- // + + boxSizingProp = getStyleProperty('boxSizing'); + + /** + * WebKit measures the outer-width on style.width on border-box elems + * IE & Firefox measures the inner-width + */ + if ( boxSizingProp ) { + var div = document.createElement('div'); + div.style.width = '200px'; + div.style.padding = '1px 2px 3px 4px'; + div.style.borderStyle = 'solid'; + div.style.borderWidth = '1px 2px 3px 4px'; + div.style[ boxSizingProp ] = 'border-box'; + + var body = document.body || document.documentElement; + body.appendChild( div ); + var style = getStyle( div ); + + isBoxSizeOuter = getStyleSize( style.width ) === 200; + body.removeChild( div ); + } + +} + +// -------------------------- getSize -------------------------- // + +function getSize( elem ) { + setup(); + + // use querySeletor if elem is string + if ( typeof elem === 'string' ) { + elem = document.querySelector( elem ); + } + + // do not proceed on non-objects + if ( !elem || typeof elem !== 'object' || !elem.nodeType ) { + return; + } + + var style = getStyle( elem ); + + // if hidden, everything is 0 + if ( style.display === 'none' ) { + return getZeroSize(); + } + + var size = {}; + size.width = elem.offsetWidth; + size.height = elem.offsetHeight; + + var isBorderBox = size.isBorderBox = !!( boxSizingProp && + style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' ); + + // get all measurements + for ( var i=0, len = measurements.length; i < len; i++ ) { + var measurement = measurements[i]; + var value = style[ measurement ]; + value = mungeNonPixel( elem, value ); + var num = parseFloat( value ); + // any 'auto', 'medium' value will be 0 + size[ measurement ] = !isNaN( num ) ? num : 0; + } + + var paddingWidth = size.paddingLeft + size.paddingRight; + var paddingHeight = size.paddingTop + size.paddingBottom; + var marginWidth = size.marginLeft + size.marginRight; + var marginHeight = size.marginTop + size.marginBottom; + var borderWidth = size.borderLeftWidth + size.borderRightWidth; + var borderHeight = size.borderTopWidth + size.borderBottomWidth; + + var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; + + // overwrite width and height if we can get it from style + var styleWidth = getStyleSize( style.width ); + if ( styleWidth !== false ) { + size.width = styleWidth + + // add padding and border unless it's already including it + ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); + } + + var styleHeight = getStyleSize( style.height ); + if ( styleHeight !== false ) { + size.height = styleHeight + + // add padding and border unless it's already including it + ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); + } + + size.innerWidth = size.width - ( paddingWidth + borderWidth ); + size.innerHeight = size.height - ( paddingHeight + borderHeight ); + + size.outerWidth = size.width + marginWidth; + size.outerHeight = size.height + marginHeight; + + return size; +} + +// IE8 returns percent values, not pixels +// taken from jQuery's curCSS +function mungeNonPixel( elem, value ) { + // IE8 and has percent value + if ( window.getComputedStyle || value.indexOf('%') === -1 ) { + return value; + } + var style = elem.style; + // Remember the original values + var left = style.left; + var rs = elem.runtimeStyle; + var rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = value; + value = style.pixelLeft; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + + return value; +} + +return getSize; + +} + +// transport +if ( typeof define === 'function' && define.amd ) { + // AMD for RequireJS + define( 'get-size/get-size',[ 'get-style-property/get-style-property' ], defineGetSize ); +} else if ( typeof exports === 'object' ) { + // CommonJS for Component + module.exports = defineGetSize( require('desandro-get-style-property') ); +} else { + // browser global + window.getSize = defineGetSize( window.getStyleProperty ); +} + +})( window ); + +/*! + * docReady v1.0.4 + * Cross browser DOMContentLoaded event emitter + * MIT license + */ + +/*jshint browser: true, strict: true, undef: true, unused: true*/ +/*global define: false, require: false, module: false */ + +( function( window ) { + + + +var document = window.document; +// collection of functions to be triggered on ready +var queue = []; + +function docReady( fn ) { + // throw out non-functions + if ( typeof fn !== 'function' ) { + return; + } + + if ( docReady.isReady ) { + // ready now, hit it + fn(); + } else { + // queue function when ready + queue.push( fn ); + } +} + +docReady.isReady = false; + +// triggered on various doc ready events +function onReady( event ) { + // bail if already triggered or IE8 document is not ready just yet + var isIE8NotReady = event.type === 'readystatechange' && document.readyState !== 'complete'; + if ( docReady.isReady || isIE8NotReady ) { + return; + } + + trigger(); +} + +function trigger() { + docReady.isReady = true; + // process queue + for ( var i=0, len = queue.length; i < len; i++ ) { + var fn = queue[i]; + fn(); + } +} + +function defineDocReady( eventie ) { + // trigger ready if page is ready + if ( document.readyState === 'complete' ) { + trigger(); + } else { + // listen for events + eventie.bind( document, 'DOMContentLoaded', onReady ); + eventie.bind( document, 'readystatechange', onReady ); + eventie.bind( window, 'load', onReady ); + } + + return docReady; +} + +// transport +if ( typeof define === 'function' && define.amd ) { + // AMD + define( 'doc-ready/doc-ready',[ 'eventie/eventie' ], defineDocReady ); +} else if ( typeof exports === 'object' ) { + module.exports = defineDocReady( require('eventie') ); +} else { + // browser global + window.docReady = defineDocReady( window.eventie ); +} + +})( window ); + +/** + * matchesSelector v1.0.3 + * matchesSelector( element, '.selector' ) + * MIT license + */ + +/*jshint browser: true, strict: true, undef: true, unused: true */ +/*global define: false, module: false */ + +( function( ElemProto ) { + + 'use strict'; + + var matchesMethod = ( function() { + // check for the standard method name first + if ( ElemProto.matches ) { + return 'matches'; + } + // check un-prefixed + if ( ElemProto.matchesSelector ) { + return 'matchesSelector'; + } + // check vendor prefixes + var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; + + for ( var i=0, len = prefixes.length; i < len; i++ ) { + var prefix = prefixes[i]; + var method = prefix + 'MatchesSelector'; + if ( ElemProto[ method ] ) { + return method; + } + } + })(); + + // ----- match ----- // + + function match( elem, selector ) { + return elem[ matchesMethod ]( selector ); + } + + // ----- appendToFragment ----- // + + function checkParent( elem ) { + // not needed if already has parent + if ( elem.parentNode ) { + return; + } + var fragment = document.createDocumentFragment(); + fragment.appendChild( elem ); + } + + // ----- query ----- // + + // fall back to using QSA + // thx @jonathantneal https://gist.github.com/3062955 + function query( elem, selector ) { + // append to fragment if no parent + checkParent( elem ); + + // match elem with all selected elems of parent + var elems = elem.parentNode.querySelectorAll( selector ); + for ( var i=0, len = elems.length; i < len; i++ ) { + // return true if match + if ( elems[i] === elem ) { + return true; + } + } + // otherwise return false + return false; + } + + // ----- matchChild ----- // + + function matchChild( elem, selector ) { + checkParent( elem ); + return match( elem, selector ); + } + + // ----- matchesSelector ----- // + + var matchesSelector; + + if ( matchesMethod ) { + // IE9 supports matchesSelector, but doesn't work on orphaned elems + // check for that + var div = document.createElement('div'); + var supportsOrphans = match( div, 'div' ); + matchesSelector = supportsOrphans ? match : matchChild; + } else { + matchesSelector = query; + } + + // transport + if ( typeof define === 'function' && define.amd ) { + // AMD + define( 'matches-selector/matches-selector',[],function() { + return matchesSelector; + }); + } else if ( typeof exports === 'object' ) { + module.exports = matchesSelector; + } + else { + // browser global + window.matchesSelector = matchesSelector; + } + +})( Element.prototype ); + +/** + * Fizzy UI utils v1.0.1 + * MIT license + */ + +/*jshint browser: true, undef: true, unused: true, strict: true */ + +( function( window, factory ) { + /*global define: false, module: false, require: false */ + 'use strict'; + // universal module definition + + if ( typeof define == 'function' && define.amd ) { + // AMD + define( 'fizzy-ui-utils/utils',[ + 'doc-ready/doc-ready', + 'matches-selector/matches-selector' + ], function( docReady, matchesSelector ) { + return factory( window, docReady, matchesSelector ); + }); + } else if ( typeof exports == 'object' ) { + // CommonJS + module.exports = factory( + window, + require('doc-ready'), + require('desandro-matches-selector') + ); + } else { + // browser global + window.fizzyUIUtils = factory( + window, + window.docReady, + window.matchesSelector + ); + } + +}( window, function factory( window, docReady, matchesSelector ) { + + + +var utils = {}; + +// ----- extend ----- // + +// extends objects +utils.extend = function( a, b ) { + for ( var prop in b ) { + a[ prop ] = b[ prop ]; + } + return a; +}; + +// ----- modulo ----- // + +utils.modulo = function( num, div ) { + return ( ( num % div ) + div ) % div; +}; + +// ----- isArray ----- // + +var objToString = Object.prototype.toString; +utils.isArray = function( obj ) { + return objToString.call( obj ) == '[object Array]'; +}; + +// ----- makeArray ----- // + +// turn element or nodeList into an array +utils.makeArray = function( obj ) { + var ary = []; + if ( utils.isArray( obj ) ) { + // use object if already an array + ary = obj; + } else if ( obj && typeof obj.length == 'number' ) { + // convert nodeList to array + for ( var i=0, len = obj.length; i < len; i++ ) { + ary.push( obj[i] ); + } + } else { + // array of single index + ary.push( obj ); + } + return ary; +}; + +// ----- indexOf ----- // + +// index of helper cause IE8 +utils.indexOf = Array.prototype.indexOf ? function( ary, obj ) { + return ary.indexOf( obj ); + } : function( ary, obj ) { + for ( var i=0, len = ary.length; i < len; i++ ) { + if ( ary[i] === obj ) { + return i; + } + } + return -1; + }; + +// ----- removeFrom ----- // + +utils.removeFrom = function( ary, obj ) { + var index = utils.indexOf( ary, obj ); + if ( index != -1 ) { + ary.splice( index, 1 ); + } +}; + +// ----- isElement ----- // + +// http://stackoverflow.com/a/384380/182183 +utils.isElement = ( typeof HTMLElement == 'function' || typeof HTMLElement == 'object' ) ? + function isElementDOM2( obj ) { + return obj instanceof HTMLElement; + } : + function isElementQuirky( obj ) { + return obj && typeof obj == 'object' && + obj.nodeType == 1 && typeof obj.nodeName == 'string'; + }; + +// ----- setText ----- // + +utils.setText = ( function() { + var setTextProperty; + function setText( elem, text ) { + // only check setTextProperty once + setTextProperty = setTextProperty || ( document.documentElement.textContent !== undefined ? 'textContent' : 'innerText' ); + elem[ setTextProperty ] = text; + } + return setText; +})(); + +// ----- getParent ----- // + +utils.getParent = function( elem, selector ) { + while ( elem != document.body ) { + elem = elem.parentNode; + if ( matchesSelector( elem, selector ) ) { + return elem; + } + } +}; + +// ----- getQueryElement ----- // + +// use element as selector string +utils.getQueryElement = function( elem ) { + if ( typeof elem == 'string' ) { + return document.querySelector( elem ); + } + return elem; +}; + +// ----- handleEvent ----- // + +// enable .ontype to trigger from .addEventListener( elem, 'type' ) +utils.handleEvent = function( event ) { + var method = 'on' + event.type; + if ( this[ method ] ) { + this[ method ]( event ); + } +}; + +// ----- filterFindElements ----- // + +utils.filterFindElements = function( elems, selector ) { + // make array of elems + elems = utils.makeArray( elems ); + var ffElems = []; + + for ( var i=0, len = elems.length; i < len; i++ ) { + var elem = elems[i]; + // check that elem is an actual element + if ( !utils.isElement( elem ) ) { + continue; + } + // filter & find items if we have a selector + if ( selector ) { + // filter siblings + if ( matchesSelector( elem, selector ) ) { + ffElems.push( elem ); + } + // find children + var childElems = elem.querySelectorAll( selector ); + // concat childElems to filterFound array + for ( var j=0, jLen = childElems.length; j < jLen; j++ ) { + ffElems.push( childElems[j] ); + } + } else { + ffElems.push( elem ); + } + } + + return ffElems; +}; + +// ----- debounceMethod ----- // + +utils.debounceMethod = function( _class, methodName, threshold ) { + // original method + var method = _class.prototype[ methodName ]; + var timeoutName = methodName + 'Timeout'; + + _class.prototype[ methodName ] = function() { + var timeout = this[ timeoutName ]; + if ( timeout ) { + clearTimeout( timeout ); + } + var args = arguments; + + var _this = this; + this[ timeoutName ] = setTimeout( function() { + method.apply( _this, args ); + delete _this[ timeoutName ]; + }, threshold || 100 ); + }; +}; + +// ----- htmlInit ----- // + +// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ +utils.toDashed = function( str ) { + return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { + return $1 + '-' + $2; + }).toLowerCase(); +}; + +var console = window.console; +/** + * allow user to initialize classes via .js-namespace class + * htmlInit( Widget, 'widgetName' ) + * options are parsed from data-namespace-option attribute + */ +utils.htmlInit = function( WidgetClass, namespace ) { + docReady( function() { + var dashedNamespace = utils.toDashed( namespace ); + var elems = document.querySelectorAll( '.js-' + dashedNamespace ); + var dataAttr = 'data-' + dashedNamespace + '-options'; + + for ( var i=0, len = elems.length; i < len; i++ ) { + var elem = elems[i]; + var attr = elem.getAttribute( dataAttr ); + var options; + try { + options = attr && JSON.parse( attr ); + } catch ( error ) { + // log error, do not initialize + if ( console ) { + console.error( 'Error parsing ' + dataAttr + ' on ' + + elem.nodeName.toLowerCase() + ( elem.id ? '#' + elem.id : '' ) + ': ' + + error ); + } + continue; + } + // initialize + var instance = new WidgetClass( elem, options ); + // make available via $().data('layoutname') + var jQuery = window.jQuery; + if ( jQuery ) { + jQuery.data( elem, namespace, instance ); + } + } + }); +}; + +// ----- ----- // + +return utils; + +})); + +/** + * Outlayer Item + */ + +( function( window, factory ) { + 'use strict'; + // universal module definition + if ( typeof define === 'function' && define.amd ) { + // AMD + define( 'outlayer/item',[ + 'eventEmitter/EventEmitter', + 'get-size/get-size', + 'get-style-property/get-style-property', + 'fizzy-ui-utils/utils' + ], + function( EventEmitter, getSize, getStyleProperty, utils ) { + return factory( window, EventEmitter, getSize, getStyleProperty, utils ); + } + ); + } else if (typeof exports === 'object') { + // CommonJS + module.exports = factory( + window, + require('wolfy87-eventemitter'), + require('get-size'), + require('desandro-get-style-property'), + require('fizzy-ui-utils') + ); + } else { + // browser global + window.Outlayer = {}; + window.Outlayer.Item = factory( + window, + window.EventEmitter, + window.getSize, + window.getStyleProperty, + window.fizzyUIUtils + ); + } + +}( window, function factory( window, EventEmitter, getSize, getStyleProperty, utils ) { +'use strict'; + +// ----- helpers ----- // + +var getComputedStyle = window.getComputedStyle; +var getStyle = getComputedStyle ? + function( elem ) { + return getComputedStyle( elem, null ); + } : + function( elem ) { + return elem.currentStyle; + }; + + +function isEmptyObj( obj ) { + for ( var prop in obj ) { + return false; + } + prop = null; + return true; +} + +// -------------------------- CSS3 support -------------------------- // + +var transitionProperty = getStyleProperty('transition'); +var transformProperty = getStyleProperty('transform'); +var supportsCSS3 = transitionProperty && transformProperty; +var is3d = !!getStyleProperty('perspective'); + +var transitionEndEvent = { + WebkitTransition: 'webkitTransitionEnd', + MozTransition: 'transitionend', + OTransition: 'otransitionend', + transition: 'transitionend' +}[ transitionProperty ]; + +// properties that could have vendor prefix +var prefixableProperties = [ + 'transform', + 'transition', + 'transitionDuration', + 'transitionProperty' +]; + +// cache all vendor properties +var vendorProperties = ( function() { + var cache = {}; + for ( var i=0, len = prefixableProperties.length; i < len; i++ ) { + var prop = prefixableProperties[i]; + var supportedProp = getStyleProperty( prop ); + if ( supportedProp && supportedProp !== prop ) { + cache[ prop ] = supportedProp; + } + } + return cache; +})(); + +// -------------------------- Item -------------------------- // + +function Item( element, layout ) { + if ( !element ) { + return; + } + + this.element = element; + // parent layout class, i.e. Masonry, Isotope, or Packery + this.layout = layout; + this.position = { + x: 0, + y: 0 + }; + + this._create(); +} + +// inherit EventEmitter +utils.extend( Item.prototype, EventEmitter.prototype ); + +Item.prototype._create = function() { + // transition objects + this._transn = { + ingProperties: {}, + clean: {}, + onEnd: {} + }; + + this.css({ + position: 'absolute' + }); +}; + +// trigger specified handler for event type +Item.prototype.handleEvent = function( event ) { + var method = 'on' + event.type; + if ( this[ method ] ) { + this[ method ]( event ); + } +}; + +Item.prototype.getSize = function() { + this.size = getSize( this.element ); +}; + +/** + * apply CSS styles to element + * @param {Object} style + */ +Item.prototype.css = function( style ) { + var elemStyle = this.element.style; + + for ( var prop in style ) { + // use vendor property if available + var supportedProp = vendorProperties[ prop ] || prop; + elemStyle[ supportedProp ] = style[ prop ]; + } +}; + + // measure position, and sets it +Item.prototype.getPosition = function() { + var style = getStyle( this.element ); + var layoutOptions = this.layout.options; + var isOriginLeft = layoutOptions.isOriginLeft; + var isOriginTop = layoutOptions.isOriginTop; + var xValue = style[ isOriginLeft ? 'left' : 'right' ]; + var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; + // convert percent to pixels + var layoutSize = this.layout.size; + var x = xValue.indexOf('%') != -1 ? + ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 ); + var y = yValue.indexOf('%') != -1 ? + ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 ); + + // clean up 'auto' or other non-integer values + x = isNaN( x ) ? 0 : x; + y = isNaN( y ) ? 0 : y; + // remove padding from measurement + x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; + y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; + + this.position.x = x; + this.position.y = y; +}; + +// set settled position, apply padding +Item.prototype.layoutPosition = function() { + var layoutSize = this.layout.size; + var layoutOptions = this.layout.options; + var style = {}; + + // x + var xPadding = layoutOptions.isOriginLeft ? 'paddingLeft' : 'paddingRight'; + var xProperty = layoutOptions.isOriginLeft ? 'left' : 'right'; + var xResetProperty = layoutOptions.isOriginLeft ? 'right' : 'left'; + + var x = this.position.x + layoutSize[ xPadding ]; + // set in percentage or pixels + style[ xProperty ] = this.getXValue( x ); + // reset other property + style[ xResetProperty ] = ''; + + // y + var yPadding = layoutOptions.isOriginTop ? 'paddingTop' : 'paddingBottom'; + var yProperty = layoutOptions.isOriginTop ? 'top' : 'bottom'; + var yResetProperty = layoutOptions.isOriginTop ? 'bottom' : 'top'; + + var y = this.position.y + layoutSize[ yPadding ]; + // set in percentage or pixels + style[ yProperty ] = this.getYValue( y ); + // reset other property + style[ yResetProperty ] = ''; + + this.css( style ); + this.emitEvent( 'layout', [ this ] ); +}; + +Item.prototype.getXValue = function( x ) { + var layoutOptions = this.layout.options; + return layoutOptions.percentPosition && !layoutOptions.isHorizontal ? + ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; +}; + +Item.prototype.getYValue = function( y ) { + var layoutOptions = this.layout.options; + return layoutOptions.percentPosition && layoutOptions.isHorizontal ? + ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; +}; + + +Item.prototype._transitionTo = function( x, y ) { + this.getPosition(); + // get current x & y from top/left + var curX = this.position.x; + var curY = this.position.y; + + var compareX = parseInt( x, 10 ); + var compareY = parseInt( y, 10 ); + var didNotMove = compareX === this.position.x && compareY === this.position.y; + + // save end position + this.setPosition( x, y ); + + // if did not move and not transitioning, just go to layout + if ( didNotMove && !this.isTransitioning ) { + this.layoutPosition(); + return; + } + + var transX = x - curX; + var transY = y - curY; + var transitionStyle = {}; + transitionStyle.transform = this.getTranslate( transX, transY ); + + this.transition({ + to: transitionStyle, + onTransitionEnd: { + transform: this.layoutPosition + }, + isCleaning: true + }); +}; + +Item.prototype.getTranslate = function( x, y ) { + // flip cooridinates if origin on right or bottom + var layoutOptions = this.layout.options; + x = layoutOptions.isOriginLeft ? x : -x; + y = layoutOptions.isOriginTop ? y : -y; + + if ( is3d ) { + return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; + } + + return 'translate(' + x + 'px, ' + y + 'px)'; +}; + +// non transition + transform support +Item.prototype.goTo = function( x, y ) { + this.setPosition( x, y ); + this.layoutPosition(); +}; + +// use transition and transforms if supported +Item.prototype.moveTo = supportsCSS3 ? + Item.prototype._transitionTo : Item.prototype.goTo; + +Item.prototype.setPosition = function( x, y ) { + this.position.x = parseInt( x, 10 ); + this.position.y = parseInt( y, 10 ); +}; + +// ----- transition ----- // + +/** + * @param {Object} style - CSS + * @param {Function} onTransitionEnd + */ + +// non transition, just trigger callback +Item.prototype._nonTransition = function( args ) { + this.css( args.to ); + if ( args.isCleaning ) { + this._removeStyles( args.to ); + } + for ( var prop in args.onTransitionEnd ) { + args.onTransitionEnd[ prop ].call( this ); + } +}; + +/** + * proper transition + * @param {Object} args - arguments + * @param {Object} to - style to transition to + * @param {Object} from - style to start transition from + * @param {Boolean} isCleaning - removes transition styles after transition + * @param {Function} onTransitionEnd - callback + */ +Item.prototype._transition = function( args ) { + // redirect to nonTransition if no transition duration + if ( !parseFloat( this.layout.options.transitionDuration ) ) { + this._nonTransition( args ); + return; + } + + var _transition = this._transn; + // keep track of onTransitionEnd callback by css property + for ( var prop in args.onTransitionEnd ) { + _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; + } + // keep track of properties that are transitioning + for ( prop in args.to ) { + _transition.ingProperties[ prop ] = true; + // keep track of properties to clean up when transition is done + if ( args.isCleaning ) { + _transition.clean[ prop ] = true; + } + } + + // set from styles + if ( args.from ) { + this.css( args.from ); + // force redraw. http://blog.alexmaccaw.com/css-transitions + var h = this.element.offsetHeight; + // hack for JSHint to hush about unused var + h = null; + } + // enable transition + this.enableTransition( args.to ); + // set styles that are transitioning + this.css( args.to ); + + this.isTransitioning = true; + +}; + +// dash before all cap letters, including first for +// WebkitTransform => -webkit-transform +function toDashedAll( str ) { + return str.replace( /([A-Z])/g, function( $1 ) { + return '-' + $1.toLowerCase(); + }); +} + +var transitionProps = 'opacity,' + + toDashedAll( vendorProperties.transform || 'transform' ); + +Item.prototype.enableTransition = function(/* style */) { + // HACK changing transitionProperty during a transition + // will cause transition to jump + if ( this.isTransitioning ) { + return; + } + + // make `transition: foo, bar, baz` from style object + // HACK un-comment this when enableTransition can work + // while a transition is happening + // var transitionValues = []; + // for ( var prop in style ) { + // // dash-ify camelCased properties like WebkitTransition + // prop = vendorProperties[ prop ] || prop; + // transitionValues.push( toDashedAll( prop ) ); + // } + // enable transition styles + this.css({ + transitionProperty: transitionProps, + transitionDuration: this.layout.options.transitionDuration + }); + // listen for transition end event + this.element.addEventListener( transitionEndEvent, this, false ); +}; + +Item.prototype.transition = Item.prototype[ transitionProperty ? '_transition' : '_nonTransition' ]; + +// ----- events ----- // + +Item.prototype.onwebkitTransitionEnd = function( event ) { + this.ontransitionend( event ); +}; + +Item.prototype.onotransitionend = function( event ) { + this.ontransitionend( event ); +}; + +// properties that I munge to make my life easier +var dashedVendorProperties = { + '-webkit-transform': 'transform', + '-moz-transform': 'transform', + '-o-transform': 'transform' +}; + +Item.prototype.ontransitionend = function( event ) { + // disregard bubbled events from children + if ( event.target !== this.element ) { + return; + } + var _transition = this._transn; + // get property name of transitioned property, convert to prefix-free + var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; + + // remove property that has completed transitioning + delete _transition.ingProperties[ propertyName ]; + // check if any properties are still transitioning + if ( isEmptyObj( _transition.ingProperties ) ) { + // all properties have completed transitioning + this.disableTransition(); + } + // clean style + if ( propertyName in _transition.clean ) { + // clean up style + this.element.style[ event.propertyName ] = ''; + delete _transition.clean[ propertyName ]; + } + // trigger onTransitionEnd callback + if ( propertyName in _transition.onEnd ) { + var onTransitionEnd = _transition.onEnd[ propertyName ]; + onTransitionEnd.call( this ); + delete _transition.onEnd[ propertyName ]; + } + + this.emitEvent( 'transitionEnd', [ this ] ); +}; + +Item.prototype.disableTransition = function() { + this.removeTransitionStyles(); + this.element.removeEventListener( transitionEndEvent, this, false ); + this.isTransitioning = false; +}; + +/** + * removes style property from element + * @param {Object} style +**/ +Item.prototype._removeStyles = function( style ) { + // clean up transition styles + var cleanStyle = {}; + for ( var prop in style ) { + cleanStyle[ prop ] = ''; + } + this.css( cleanStyle ); +}; + +var cleanTransitionStyle = { + transitionProperty: '', + transitionDuration: '' +}; + +Item.prototype.removeTransitionStyles = function() { + // remove transition + this.css( cleanTransitionStyle ); +}; + +// ----- show/hide/remove ----- // + +// remove element from DOM +Item.prototype.removeElem = function() { + this.element.parentNode.removeChild( this.element ); + // remove display: none + this.css({ display: '' }); + this.emitEvent( 'remove', [ this ] ); +}; + +Item.prototype.remove = function() { + // just remove element if no transition support or no transition + if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { + this.removeElem(); + return; + } + + // start transition + var _this = this; + this.once( 'transitionEnd', function() { + _this.removeElem(); + }); + this.hide(); +}; + +Item.prototype.reveal = function() { + delete this.isHidden; + // remove display: none + this.css({ display: '' }); + + var options = this.layout.options; + + var onTransitionEnd = {}; + var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); + onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; + + this.transition({ + from: options.hiddenStyle, + to: options.visibleStyle, + isCleaning: true, + onTransitionEnd: onTransitionEnd + }); +}; + +Item.prototype.onRevealTransitionEnd = function() { + // check if still visible + // during transition, item may have been hidden + if ( !this.isHidden ) { + this.emitEvent('reveal'); + } +}; + +/** + * get style property use for hide/reveal transition end + * @param {String} styleProperty - hiddenStyle/visibleStyle + * @returns {String} + */ +Item.prototype.getHideRevealTransitionEndProperty = function( styleProperty ) { + var optionStyle = this.layout.options[ styleProperty ]; + // use opacity + if ( optionStyle.opacity ) { + return 'opacity'; + } + // get first property + for ( var prop in optionStyle ) { + return prop; + } +}; + +Item.prototype.hide = function() { + // set flag + this.isHidden = true; + // remove display: none + this.css({ display: '' }); + + var options = this.layout.options; + + var onTransitionEnd = {}; + var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); + onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; + + this.transition({ + from: options.visibleStyle, + to: options.hiddenStyle, + // keep hidden stuff hidden + isCleaning: true, + onTransitionEnd: onTransitionEnd + }); +}; + +Item.prototype.onHideTransitionEnd = function() { + // check if still hidden + // during transition, item may have been un-hidden + if ( this.isHidden ) { + this.css({ display: 'none' }); + this.emitEvent('hide'); + } +}; + +Item.prototype.destroy = function() { + this.css({ + position: '', + left: '', + right: '', + top: '', + bottom: '', + transition: '', + transform: '' + }); +}; + +return Item; + +})); + +/*! + * Outlayer v1.4.2 + * the brains and guts of a layout library + * MIT license + */ + +( function( window, factory ) { + 'use strict'; + // universal module definition + + if ( typeof define == 'function' && define.amd ) { + // AMD + define( 'outlayer/outlayer',[ + 'eventie/eventie', + 'eventEmitter/EventEmitter', + 'get-size/get-size', + 'fizzy-ui-utils/utils', + './item' + ], + function( eventie, EventEmitter, getSize, utils, Item ) { + return factory( window, eventie, EventEmitter, getSize, utils, Item); + } + ); + } else if ( typeof exports == 'object' ) { + // CommonJS + module.exports = factory( + window, + require('eventie'), + require('wolfy87-eventemitter'), + require('get-size'), + require('fizzy-ui-utils'), + require('./item') + ); + } else { + // browser global + window.Outlayer = factory( + window, + window.eventie, + window.EventEmitter, + window.getSize, + window.fizzyUIUtils, + window.Outlayer.Item + ); + } + +}( window, function factory( window, eventie, EventEmitter, getSize, utils, Item ) { +'use strict'; + +// ----- vars ----- // + +var console = window.console; +var jQuery = window.jQuery; +var noop = function() {}; + +// -------------------------- Outlayer -------------------------- // + +// globally unique identifiers +var GUID = 0; +// internal store of all Outlayer intances +var instances = {}; + + +/** + * @param {Element, String} element + * @param {Object} options + * @constructor + */ +function Outlayer( element, options ) { + var queryElement = utils.getQueryElement( element ); + if ( !queryElement ) { + if ( console ) { + console.error( 'Bad element for ' + this.constructor.namespace + + ': ' + ( queryElement || element ) ); + } + return; + } + this.element = queryElement; + // add jQuery + if ( jQuery ) { + this.$element = jQuery( this.element ); + } + + // options + this.options = utils.extend( {}, this.constructor.defaults ); + this.option( options ); + + // add id for Outlayer.getFromElement + var id = ++GUID; + this.element.outlayerGUID = id; // expando + instances[ id ] = this; // associate via id + + // kick it off + this._create(); + + if ( this.options.isInitLayout ) { + this.layout(); + } +} + +// settings are for internal use only +Outlayer.namespace = 'outlayer'; +Outlayer.Item = Item; + +// default options +Outlayer.defaults = { + containerStyle: { + position: 'relative' + }, + isInitLayout: true, + isOriginLeft: true, + isOriginTop: true, + isResizeBound: true, + isResizingContainer: true, + // item options + transitionDuration: '0.4s', + hiddenStyle: { + opacity: 0, + transform: 'scale(0.001)' + }, + visibleStyle: { + opacity: 1, + transform: 'scale(1)' + } +}; + +// inherit EventEmitter +utils.extend( Outlayer.prototype, EventEmitter.prototype ); + +/** + * set options + * @param {Object} opts + */ +Outlayer.prototype.option = function( opts ) { + utils.extend( this.options, opts ); +}; + +Outlayer.prototype._create = function() { + // get items from children + this.reloadItems(); + // elements that affect layout, but are not laid out + this.stamps = []; + this.stamp( this.options.stamp ); + // set container style + utils.extend( this.element.style, this.options.containerStyle ); + + // bind resize method + if ( this.options.isResizeBound ) { + this.bindResize(); + } +}; + +// goes through all children again and gets bricks in proper order +Outlayer.prototype.reloadItems = function() { + // collection of item elements + this.items = this._itemize( this.element.children ); +}; + + +/** + * turn elements into Outlayer.Items to be used in layout + * @param {Array or NodeList or HTMLElement} elems + * @returns {Array} items - collection of new Outlayer Items + */ +Outlayer.prototype._itemize = function( elems ) { + + var itemElems = this._filterFindItemElements( elems ); + var Item = this.constructor.Item; + + // create new Outlayer Items for collection + var items = []; + for ( var i=0, len = itemElems.length; i < len; i++ ) { + var elem = itemElems[i]; + var item = new Item( elem, this ); + items.push( item ); + } + + return items; +}; + +/** + * get item elements to be used in layout + * @param {Array or NodeList or HTMLElement} elems + * @returns {Array} items - item elements + */ +Outlayer.prototype._filterFindItemElements = function( elems ) { + return utils.filterFindElements( elems, this.options.itemSelector ); +}; + +/** + * getter method for getting item elements + * @returns {Array} elems - collection of item elements + */ +Outlayer.prototype.getItemElements = function() { + var elems = []; + for ( var i=0, len = this.items.length; i < len; i++ ) { + elems.push( this.items[i].element ); + } + return elems; +}; + +// ----- init & layout ----- // + +/** + * lays out all items + */ +Outlayer.prototype.layout = function() { + this._resetLayout(); + this._manageStamps(); + + // don't animate first layout + var isInstant = this.options.isLayoutInstant !== undefined ? + this.options.isLayoutInstant : !this._isLayoutInited; + this.layoutItems( this.items, isInstant ); + + // flag for initalized + this._isLayoutInited = true; +}; + +// _init is alias for layout +Outlayer.prototype._init = Outlayer.prototype.layout; + +/** + * logic before any new layout + */ +Outlayer.prototype._resetLayout = function() { + this.getSize(); +}; + + +Outlayer.prototype.getSize = function() { + this.size = getSize( this.element ); +}; + +/** + * get measurement from option, for columnWidth, rowHeight, gutter + * if option is String -> get element from selector string, & get size of element + * if option is Element -> get size of element + * else use option as a number + * + * @param {String} measurement + * @param {String} size - width or height + * @private + */ +Outlayer.prototype._getMeasurement = function( measurement, size ) { + var option = this.options[ measurement ]; + var elem; + if ( !option ) { + // default to 0 + this[ measurement ] = 0; + } else { + // use option as an element + if ( typeof option === 'string' ) { + elem = this.element.querySelector( option ); + } else if ( utils.isElement( option ) ) { + elem = option; + } + // use size of element, if element + this[ measurement ] = elem ? getSize( elem )[ size ] : option; + } +}; + +/** + * layout a collection of item elements + * @api public + */ +Outlayer.prototype.layoutItems = function( items, isInstant ) { + items = this._getItemsForLayout( items ); + + this._layoutItems( items, isInstant ); + + this._postLayout(); +}; + +/** + * get the items to be laid out + * you may want to skip over some items + * @param {Array} items + * @returns {Array} items + */ +Outlayer.prototype._getItemsForLayout = function( items ) { + var layoutItems = []; + for ( var i=0, len = items.length; i < len; i++ ) { + var item = items[i]; + if ( !item.isIgnored ) { + layoutItems.push( item ); + } + } + return layoutItems; +}; + +/** + * layout items + * @param {Array} items + * @param {Boolean} isInstant + */ +Outlayer.prototype._layoutItems = function( items, isInstant ) { + this._emitCompleteOnItems( 'layout', items ); + + if ( !items || !items.length ) { + // no items, emit event with empty array + return; + } + + var queue = []; + + for ( var i=0, len = items.length; i < len; i++ ) { + var item = items[i]; + // get x/y object from method + var position = this._getItemLayoutPosition( item ); + // enqueue + position.item = item; + position.isInstant = isInstant || item.isLayoutInstant; + queue.push( position ); + } + + this._processLayoutQueue( queue ); +}; + +/** + * get item layout position + * @param {Outlayer.Item} item + * @returns {Object} x and y position + */ +Outlayer.prototype._getItemLayoutPosition = function( /* item */ ) { + return { + x: 0, + y: 0 + }; +}; + +/** + * iterate over array and position each item + * Reason being - separating this logic prevents 'layout invalidation' + * thx @paul_irish + * @param {Array} queue + */ +Outlayer.prototype._processLayoutQueue = function( queue ) { + for ( var i=0, len = queue.length; i < len; i++ ) { + var obj = queue[i]; + this._positionItem( obj.item, obj.x, obj.y, obj.isInstant ); + } +}; + +/** + * Sets position of item in DOM + * @param {Outlayer.Item} item + * @param {Number} x - horizontal position + * @param {Number} y - vertical position + * @param {Boolean} isInstant - disables transitions + */ +Outlayer.prototype._positionItem = function( item, x, y, isInstant ) { + if ( isInstant ) { + // if not transition, just set CSS + item.goTo( x, y ); + } else { + item.moveTo( x, y ); + } +}; + +/** + * Any logic you want to do after each layout, + * i.e. size the container + */ +Outlayer.prototype._postLayout = function() { + this.resizeContainer(); +}; + +Outlayer.prototype.resizeContainer = function() { + if ( !this.options.isResizingContainer ) { + return; + } + var size = this._getContainerSize(); + if ( size ) { + this._setContainerMeasure( size.width, true ); + this._setContainerMeasure( size.height, false ); + } +}; + +/** + * Sets width or height of container if returned + * @returns {Object} size + * @param {Number} width + * @param {Number} height + */ +Outlayer.prototype._getContainerSize = noop; + +/** + * @param {Number} measure - size of width or height + * @param {Boolean} isWidth + */ +Outlayer.prototype._setContainerMeasure = function( measure, isWidth ) { + if ( measure === undefined ) { + return; + } + + var elemSize = this.size; + // add padding and border width if border box + if ( elemSize.isBorderBox ) { + measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + + elemSize.borderLeftWidth + elemSize.borderRightWidth : + elemSize.paddingBottom + elemSize.paddingTop + + elemSize.borderTopWidth + elemSize.borderBottomWidth; + } + + measure = Math.max( measure, 0 ); + this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; +}; + +/** + * emit eventComplete on a collection of items events + * @param {String} eventName + * @param {Array} items - Outlayer.Items + */ +Outlayer.prototype._emitCompleteOnItems = function( eventName, items ) { + var _this = this; + function onComplete() { + _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); + } + + var count = items.length; + if ( !items || !count ) { + onComplete(); + return; + } + + var doneCount = 0; + function tick() { + doneCount++; + if ( doneCount === count ) { + onComplete(); + } + } + + // bind callback + for ( var i=0, len = items.length; i < len; i++ ) { + var item = items[i]; + item.once( eventName, tick ); + } +}; + +/** + * emits events via eventEmitter and jQuery events + * @param {String} type - name of event + * @param {Event} event - original event + * @param {Array} args - extra arguments + */ +Outlayer.prototype.dispatchEvent = function( type, event, args ) { + // add original event to arguments + var emitArgs = event ? [ event ].concat( args ) : args; + this.emitEvent( type, emitArgs ); + + if ( jQuery ) { + // set this.$element + this.$element = this.$element || jQuery( this.element ); + if ( event ) { + // create jQuery event + var $event = jQuery.Event( event ); + $event.type = type; + this.$element.trigger( $event, args ); + } else { + // just trigger with type if no event available + this.$element.trigger( type, args ); + } + } +}; + +// -------------------------- ignore & stamps -------------------------- // + + +/** + * keep item in collection, but do not lay it out + * ignored items do not get skipped in layout + * @param {Element} elem + */ +Outlayer.prototype.ignore = function( elem ) { + var item = this.getItem( elem ); + if ( item ) { + item.isIgnored = true; + } +}; + +/** + * return item to layout collection + * @param {Element} elem + */ +Outlayer.prototype.unignore = function( elem ) { + var item = this.getItem( elem ); + if ( item ) { + delete item.isIgnored; + } +}; + +/** + * adds elements to stamps + * @param {NodeList, Array, Element, or String} elems + */ +Outlayer.prototype.stamp = function( elems ) { + elems = this._find( elems ); + if ( !elems ) { + return; + } + + this.stamps = this.stamps.concat( elems ); + // ignore + for ( var i=0, len = elems.length; i < len; i++ ) { + var elem = elems[i]; + this.ignore( elem ); + } +}; + +/** + * removes elements to stamps + * @param {NodeList, Array, or Element} elems + */ +Outlayer.prototype.unstamp = function( elems ) { + elems = this._find( elems ); + if ( !elems ){ + return; + } + + for ( var i=0, len = elems.length; i < len; i++ ) { + var elem = elems[i]; + // filter out removed stamp elements + utils.removeFrom( this.stamps, elem ); + this.unignore( elem ); + } + +}; + +/** + * finds child elements + * @param {NodeList, Array, Element, or String} elems + * @returns {Array} elems + */ +Outlayer.prototype._find = function( elems ) { + if ( !elems ) { + return; + } + // if string, use argument as selector string + if ( typeof elems === 'string' ) { + elems = this.element.querySelectorAll( elems ); + } + elems = utils.makeArray( elems ); + return elems; +}; + +Outlayer.prototype._manageStamps = function() { + if ( !this.stamps || !this.stamps.length ) { + return; + } + + this._getBoundingRect(); + + for ( var i=0, len = this.stamps.length; i < len; i++ ) { + var stamp = this.stamps[i]; + this._manageStamp( stamp ); + } +}; + +// update boundingLeft / Top +Outlayer.prototype._getBoundingRect = function() { + // get bounding rect for container element + var boundingRect = this.element.getBoundingClientRect(); + var size = this.size; + this._boundingRect = { + left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, + top: boundingRect.top + size.paddingTop + size.borderTopWidth, + right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), + bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) + }; +}; + +/** + * @param {Element} stamp +**/ +Outlayer.prototype._manageStamp = noop; + +/** + * get x/y position of element relative to container element + * @param {Element} elem + * @returns {Object} offset - has left, top, right, bottom + */ +Outlayer.prototype._getElementOffset = function( elem ) { + var boundingRect = elem.getBoundingClientRect(); + var thisRect = this._boundingRect; + var size = getSize( elem ); + var offset = { + left: boundingRect.left - thisRect.left - size.marginLeft, + top: boundingRect.top - thisRect.top - size.marginTop, + right: thisRect.right - boundingRect.right - size.marginRight, + bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom + }; + return offset; +}; + +// -------------------------- resize -------------------------- // + +// enable event handlers for listeners +// i.e. resize -> onresize +Outlayer.prototype.handleEvent = function( event ) { + var method = 'on' + event.type; + if ( this[ method ] ) { + this[ method ]( event ); + } +}; + +/** + * Bind layout to window resizing + */ +Outlayer.prototype.bindResize = function() { + // bind just one listener + if ( this.isResizeBound ) { + return; + } + eventie.bind( window, 'resize', this ); + this.isResizeBound = true; +}; + +/** + * Unbind layout to window resizing + */ +Outlayer.prototype.unbindResize = function() { + if ( this.isResizeBound ) { + eventie.unbind( window, 'resize', this ); + } + this.isResizeBound = false; +}; + +// original debounce by John Hann +// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/ + +// this fires every resize +Outlayer.prototype.onresize = function() { + if ( this.resizeTimeout ) { + clearTimeout( this.resizeTimeout ); + } + + var _this = this; + function delayed() { + _this.resize(); + delete _this.resizeTimeout; + } + + this.resizeTimeout = setTimeout( delayed, 100 ); +}; + +// debounced, layout on resize +Outlayer.prototype.resize = function() { + // don't trigger if size did not change + // or if resize was unbound. See #9 + if ( !this.isResizeBound || !this.needsResizeLayout() ) { + return; + } + + this.layout(); +}; + +/** + * check if layout is needed post layout + * @returns Boolean + */ +Outlayer.prototype.needsResizeLayout = function() { + var size = getSize( this.element ); + // check that this.size and size are there + // IE8 triggers resize on body size change, so they might not be + var hasSizes = this.size && size; + return hasSizes && size.innerWidth !== this.size.innerWidth; +}; + +// -------------------------- methods -------------------------- // + +/** + * add items to Outlayer instance + * @param {Array or NodeList or Element} elems + * @returns {Array} items - Outlayer.Items +**/ +Outlayer.prototype.addItems = function( elems ) { + var items = this._itemize( elems ); + // add items to collection + if ( items.length ) { + this.items = this.items.concat( items ); + } + return items; +}; + +/** + * Layout newly-appended item elements + * @param {Array or NodeList or Element} elems + */ +Outlayer.prototype.appended = function( elems ) { + var items = this.addItems( elems ); + if ( !items.length ) { + return; + } + // layout and reveal just the new items + this.layoutItems( items, true ); + this.reveal( items ); +}; + +/** + * Layout prepended elements + * @param {Array or NodeList or Element} elems + */ +Outlayer.prototype.prepended = function( elems ) { + var items = this._itemize( elems ); + if ( !items.length ) { + return; + } + // add items to beginning of collection + var previousItems = this.items.slice(0); + this.items = items.concat( previousItems ); + // start new layout + this._resetLayout(); + this._manageStamps(); + // layout new stuff without transition + this.layoutItems( items, true ); + this.reveal( items ); + // layout previous items + this.layoutItems( previousItems ); +}; + +/** + * reveal a collection of items + * @param {Array of Outlayer.Items} items + */ +Outlayer.prototype.reveal = function( items ) { + this._emitCompleteOnItems( 'reveal', items ); + + var len = items && items.length; + for ( var i=0; len && i < len; i++ ) { + var item = items[i]; + item.reveal(); + } +}; + +/** + * hide a collection of items + * @param {Array of Outlayer.Items} items + */ +Outlayer.prototype.hide = function( items ) { + this._emitCompleteOnItems( 'hide', items ); + + var len = items && items.length; + for ( var i=0; len && i < len; i++ ) { + var item = items[i]; + item.hide(); + } +}; + +/** + * reveal item elements + * @param {Array}, {Element}, {NodeList} items + */ +Outlayer.prototype.revealItemElements = function( elems ) { + var items = this.getItems( elems ); + this.reveal( items ); +}; + +/** + * hide item elements + * @param {Array}, {Element}, {NodeList} items + */ +Outlayer.prototype.hideItemElements = function( elems ) { + var items = this.getItems( elems ); + this.hide( items ); +}; + +/** + * get Outlayer.Item, given an Element + * @param {Element} elem + * @param {Function} callback + * @returns {Outlayer.Item} item + */ +Outlayer.prototype.getItem = function( elem ) { + // loop through items to get the one that matches + for ( var i=0, len = this.items.length; i < len; i++ ) { + var item = this.items[i]; + if ( item.element === elem ) { + // return item + return item; + } + } +}; + +/** + * get collection of Outlayer.Items, given Elements + * @param {Array} elems + * @returns {Array} items - Outlayer.Items + */ +Outlayer.prototype.getItems = function( elems ) { + elems = utils.makeArray( elems ); + var items = []; + for ( var i=0, len = elems.length; i < len; i++ ) { + var elem = elems[i]; + var item = this.getItem( elem ); + if ( item ) { + items.push( item ); + } + } + + return items; +}; + +/** + * remove element(s) from instance and DOM + * @param {Array or NodeList or Element} elems + */ +Outlayer.prototype.remove = function( elems ) { + var removeItems = this.getItems( elems ); + + this._emitCompleteOnItems( 'remove', removeItems ); + + // bail if no items to remove + if ( !removeItems || !removeItems.length ) { + return; + } + + for ( var i=0, len = removeItems.length; i < len; i++ ) { + var item = removeItems[i]; + item.remove(); + // remove item from collection + utils.removeFrom( this.items, item ); + } +}; + +// ----- destroy ----- // + +// remove and disable Outlayer instance +Outlayer.prototype.destroy = function() { + // clean up dynamic styles + var style = this.element.style; + style.height = ''; + style.position = ''; + style.width = ''; + // destroy items + for ( var i=0, len = this.items.length; i < len; i++ ) { + var item = this.items[i]; + item.destroy(); + } + + this.unbindResize(); + + var id = this.element.outlayerGUID; + delete instances[ id ]; // remove reference to instance by id + delete this.element.outlayerGUID; + // remove data for jQuery + if ( jQuery ) { + jQuery.removeData( this.element, this.constructor.namespace ); + } + +}; + +// -------------------------- data -------------------------- // + +/** + * get Outlayer instance from element + * @param {Element} elem + * @returns {Outlayer} + */ +Outlayer.data = function( elem ) { + elem = utils.getQueryElement( elem ); + var id = elem && elem.outlayerGUID; + return id && instances[ id ]; +}; + + +// -------------------------- create Outlayer class -------------------------- // + +/** + * create a layout class + * @param {String} namespace + */ +Outlayer.create = function( namespace, options ) { + // sub-class Outlayer + function Layout() { + Outlayer.apply( this, arguments ); + } + // inherit Outlayer prototype, use Object.create if there + if ( Object.create ) { + Layout.prototype = Object.create( Outlayer.prototype ); + } else { + utils.extend( Layout.prototype, Outlayer.prototype ); + } + // set contructor, used for namespace and Item + Layout.prototype.constructor = Layout; + + Layout.defaults = utils.extend( {}, Outlayer.defaults ); + // apply new options + utils.extend( Layout.defaults, options ); + // keep prototype.settings for backwards compatibility (Packery v1.2.0) + Layout.prototype.settings = {}; + + Layout.namespace = namespace; + + Layout.data = Outlayer.data; + + // sub-class Item + Layout.Item = function LayoutItem() { + Item.apply( this, arguments ); + }; + + Layout.Item.prototype = new Item(); + + // -------------------------- declarative -------------------------- // + + utils.htmlInit( Layout, namespace ); + + // -------------------------- jQuery bridge -------------------------- // + + // make into jQuery plugin + if ( jQuery && jQuery.bridget ) { + jQuery.bridget( namespace, Layout ); + } + + return Layout; +}; + +// ----- fin ----- // + +// back in global +Outlayer.Item = Item; + +return Outlayer; + +})); + + +/** + * Isotope Item +**/ + +( function( window, factory ) { +'use strict'; + // universal module definition + if ( typeof define == 'function' && define.amd ) { + // AMD + define( 'isotope/js/item',[ + 'outlayer/outlayer' + ], + factory ); + } else if ( typeof exports == 'object' ) { + // CommonJS + module.exports = factory( + require('outlayer') + ); + } else { + // browser global + window.Isotope = window.Isotope || {}; + window.Isotope.Item = factory( + window.Outlayer + ); + } + +}( window, function factory( Outlayer ) { +'use strict'; + +// -------------------------- Item -------------------------- // + +// sub-class Outlayer Item +function Item() { + Outlayer.Item.apply( this, arguments ); +} + +Item.prototype = new Outlayer.Item(); + +Item.prototype._create = function() { + // assign id, used for original-order sorting + this.id = this.layout.itemGUID++; + Outlayer.Item.prototype._create.call( this ); + this.sortData = {}; +}; + +Item.prototype.updateSortData = function() { + if ( this.isIgnored ) { + return; + } + // default sorters + this.sortData.id = this.id; + // for backward compatibility + this.sortData['original-order'] = this.id; + this.sortData.random = Math.random(); + // go thru getSortData obj and apply the sorters + var getSortData = this.layout.options.getSortData; + var sorters = this.layout._sorters; + for ( var key in getSortData ) { + var sorter = sorters[ key ]; + this.sortData[ key ] = sorter( this.element, this ); + } +}; + +var _destroy = Item.prototype.destroy; +Item.prototype.destroy = function() { + // call super + _destroy.apply( this, arguments ); + // reset display, #741 + this.css({ + display: '' + }); +}; + +return Item; + +})); + +/** + * Isotope LayoutMode + */ + +( function( window, factory ) { + 'use strict'; + // universal module definition + + if ( typeof define == 'function' && define.amd ) { + // AMD + define( 'isotope/js/layout-mode',[ + 'get-size/get-size', + 'outlayer/outlayer' + ], + factory ); + } else if ( typeof exports == 'object' ) { + // CommonJS + module.exports = factory( + require('get-size'), + require('outlayer') + ); + } else { + // browser global + window.Isotope = window.Isotope || {}; + window.Isotope.LayoutMode = factory( + window.getSize, + window.Outlayer + ); + } + +}( window, function factory( getSize, Outlayer ) { + 'use strict'; + + // layout mode class + function LayoutMode( isotope ) { + this.isotope = isotope; + // link properties + if ( isotope ) { + this.options = isotope.options[ this.namespace ]; + this.element = isotope.element; + this.items = isotope.filteredItems; + this.size = isotope.size; + } + } + + /** + * some methods should just defer to default Outlayer method + * and reference the Isotope instance as `this` + **/ + ( function() { + var facadeMethods = [ + '_resetLayout', + '_getItemLayoutPosition', + '_manageStamp', + '_getContainerSize', + '_getElementOffset', + 'needsResizeLayout' + ]; + + for ( var i=0, len = facadeMethods.length; i < len; i++ ) { + var methodName = facadeMethods[i]; + LayoutMode.prototype[ methodName ] = getOutlayerMethod( methodName ); + } + + function getOutlayerMethod( methodName ) { + return function() { + return Outlayer.prototype[ methodName ].apply( this.isotope, arguments ); + }; + } + })(); + + // ----- ----- // + + // for horizontal layout modes, check vertical size + LayoutMode.prototype.needsVerticalResizeLayout = function() { + // don't trigger if size did not change + var size = getSize( this.isotope.element ); + // check that this.size and size are there + // IE8 triggers resize on body size change, so they might not be + var hasSizes = this.isotope.size && size; + return hasSizes && size.innerHeight != this.isotope.size.innerHeight; + }; + + // ----- measurements ----- // + + LayoutMode.prototype._getMeasurement = function() { + this.isotope._getMeasurement.apply( this, arguments ); + }; + + LayoutMode.prototype.getColumnWidth = function() { + this.getSegmentSize( 'column', 'Width' ); + }; + + LayoutMode.prototype.getRowHeight = function() { + this.getSegmentSize( 'row', 'Height' ); + }; + + /** + * get columnWidth or rowHeight + * segment: 'column' or 'row' + * size 'Width' or 'Height' + **/ + LayoutMode.prototype.getSegmentSize = function( segment, size ) { + var segmentName = segment + size; + var outerSize = 'outer' + size; + // columnWidth / outerWidth // rowHeight / outerHeight + this._getMeasurement( segmentName, outerSize ); + // got rowHeight or columnWidth, we can chill + if ( this[ segmentName ] ) { + return; + } + // fall back to item of first element + var firstItemSize = this.getFirstItemSize(); + this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] || + // or size of container + this.isotope.size[ 'inner' + size ]; + }; + + LayoutMode.prototype.getFirstItemSize = function() { + var firstItem = this.isotope.filteredItems[0]; + return firstItem && firstItem.element && getSize( firstItem.element ); + }; + + // ----- methods that should reference isotope ----- // + + LayoutMode.prototype.layout = function() { + this.isotope.layout.apply( this.isotope, arguments ); + }; + + LayoutMode.prototype.getSize = function() { + this.isotope.getSize(); + this.size = this.isotope.size; + }; + + // -------------------------- create -------------------------- // + + LayoutMode.modes = {}; + + LayoutMode.create = function( namespace, options ) { + + function Mode() { + LayoutMode.apply( this, arguments ); + } + + Mode.prototype = new LayoutMode(); + + // default options + if ( options ) { + Mode.options = options; + } + + Mode.prototype.namespace = namespace; + // register in Isotope + LayoutMode.modes[ namespace ] = Mode; + + return Mode; + }; + + return LayoutMode; + +})); + +/*! + * Masonry v3.3.1 + * Cascading grid layout library + * http://masonry.desandro.com + * MIT License + * by David DeSandro + */ + +( function( window, factory ) { + 'use strict'; + // universal module definition + if ( typeof define === 'function' && define.amd ) { + // AMD + define( 'masonry/masonry',[ + 'outlayer/outlayer', + 'get-size/get-size', + 'fizzy-ui-utils/utils' + ], + factory ); + } else if ( typeof exports === 'object' ) { + // CommonJS + module.exports = factory( + require('outlayer'), + require('get-size'), + require('fizzy-ui-utils') + ); + } else { + // browser global + window.Masonry = factory( + window.Outlayer, + window.getSize, + window.fizzyUIUtils + ); + } + +}( window, function factory( Outlayer, getSize, utils ) { + + + +// -------------------------- masonryDefinition -------------------------- // + + // create an Outlayer layout class + var Masonry = Outlayer.create('masonry'); + + Masonry.prototype._resetLayout = function() { + this.getSize(); + this._getMeasurement( 'columnWidth', 'outerWidth' ); + this._getMeasurement( 'gutter', 'outerWidth' ); + this.measureColumns(); + + // reset column Y + var i = this.cols; + this.colYs = []; + while (i--) { + this.colYs.push( 0 ); + } + + this.maxY = 0; + }; + + Masonry.prototype.measureColumns = function() { + this.getContainerWidth(); + // if columnWidth is 0, default to outerWidth of first item + if ( !this.columnWidth ) { + var firstItem = this.items[0]; + var firstItemElem = firstItem && firstItem.element; + // columnWidth fall back to item of first element + this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth || + // if first elem has no width, default to size of container + this.containerWidth; + } + + var columnWidth = this.columnWidth += this.gutter; + + // calculate columns + var containerWidth = this.containerWidth + this.gutter; + var cols = containerWidth / columnWidth; + // fix rounding errors, typically with gutters + var excess = columnWidth - containerWidth % columnWidth; + // if overshoot is less than a pixel, round up, otherwise floor it + var mathMethod = excess && excess < 1 ? 'round' : 'floor'; + cols = Math[ mathMethod ]( cols ); + this.cols = Math.max( cols, 1 ); + }; + + Masonry.prototype.getContainerWidth = function() { + // container is parent if fit width + var container = this.options.isFitWidth ? this.element.parentNode : this.element; + // check that this.size and size are there + // IE8 triggers resize on body size change, so they might not be + var size = getSize( container ); + this.containerWidth = size && size.innerWidth; + }; + + Masonry.prototype._getItemLayoutPosition = function( item ) { + item.getSize(); + // how many columns does this brick span + var remainder = item.size.outerWidth % this.columnWidth; + var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; + // round if off by 1 pixel, otherwise use ceil + var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); + colSpan = Math.min( colSpan, this.cols ); + + var colGroup = this._getColGroup( colSpan ); + // get the minimum Y value from the columns + var minimumY = Math.min.apply( Math, colGroup ); + var shortColIndex = utils.indexOf( colGroup, minimumY ); + + // position the brick + var position = { + x: this.columnWidth * shortColIndex, + y: minimumY + }; + + // apply setHeight to necessary columns + var setHeight = minimumY + item.size.outerHeight; + var setSpan = this.cols + 1 - colGroup.length; + for ( var i = 0; i < setSpan; i++ ) { + this.colYs[ shortColIndex + i ] = setHeight; + } + + return position; + }; + + /** + * @param {Number} colSpan - number of columns the element spans + * @returns {Array} colGroup + */ + Masonry.prototype._getColGroup = function( colSpan ) { + if ( colSpan < 2 ) { + // if brick spans only one column, use all the column Ys + return this.colYs; + } + + var colGroup = []; + // how many different places could this brick fit horizontally + var groupCount = this.cols + 1 - colSpan; + // for each group potential horizontal position + for ( var i = 0; i < groupCount; i++ ) { + // make an array of colY values for that one group + var groupColYs = this.colYs.slice( i, i + colSpan ); + // and get the max value of the array + colGroup[i] = Math.max.apply( Math, groupColYs ); + } + return colGroup; + }; + + Masonry.prototype._manageStamp = function( stamp ) { + var stampSize = getSize( stamp ); + var offset = this._getElementOffset( stamp ); + // get the columns that this stamp affects + var firstX = this.options.isOriginLeft ? offset.left : offset.right; + var lastX = firstX + stampSize.outerWidth; + var firstCol = Math.floor( firstX / this.columnWidth ); + firstCol = Math.max( 0, firstCol ); + var lastCol = Math.floor( lastX / this.columnWidth ); + // lastCol should not go over if multiple of columnWidth #425 + lastCol -= lastX % this.columnWidth ? 0 : 1; + lastCol = Math.min( this.cols - 1, lastCol ); + // set colYs to bottom of the stamp + var stampMaxY = ( this.options.isOriginTop ? offset.top : offset.bottom ) + + stampSize.outerHeight; + for ( var i = firstCol; i <= lastCol; i++ ) { + this.colYs[i] = Math.max( stampMaxY, this.colYs[i] ); + } + }; + + Masonry.prototype._getContainerSize = function() { + this.maxY = Math.max.apply( Math, this.colYs ); + var size = { + height: this.maxY + }; + + if ( this.options.isFitWidth ) { + size.width = this._getContainerFitWidth(); + } + + return size; + }; + + Masonry.prototype._getContainerFitWidth = function() { + var unusedCols = 0; + // count unused columns + var i = this.cols; + while ( --i ) { + if ( this.colYs[i] !== 0 ) { + break; + } + unusedCols++; + } + // fit container to columns that have been used + return ( this.cols - unusedCols ) * this.columnWidth - this.gutter; + }; + + Masonry.prototype.needsResizeLayout = function() { + var previousWidth = this.containerWidth; + this.getContainerWidth(); + return previousWidth !== this.containerWidth; + }; + + return Masonry; + +})); + +/*! + * Masonry layout mode + * sub-classes Masonry + * http://masonry.desandro.com + */ + +( function( window, factory ) { + 'use strict'; + // universal module definition + if ( typeof define == 'function' && define.amd ) { + // AMD + define( 'isotope/js/layout-modes/masonry',[ + '../layout-mode', + 'masonry/masonry' + ], + factory ); + } else if ( typeof exports == 'object' ) { + // CommonJS + module.exports = factory( + require('../layout-mode'), + require('masonry-layout') + ); + } else { + // browser global + factory( + window.Isotope.LayoutMode, + window.Masonry + ); + } + +}( window, function factory( LayoutMode, Masonry ) { +'use strict'; + +// -------------------------- helpers -------------------------- // + +// extend objects +function extend( a, b ) { + for ( var prop in b ) { + a[ prop ] = b[ prop ]; + } + return a; +} + +// -------------------------- masonryDefinition -------------------------- // + + // create an Outlayer layout class + var MasonryMode = LayoutMode.create('masonry'); + + // save on to these methods + var _getElementOffset = MasonryMode.prototype._getElementOffset; + var layout = MasonryMode.prototype.layout; + var _getMeasurement = MasonryMode.prototype._getMeasurement; + + // sub-class Masonry + extend( MasonryMode.prototype, Masonry.prototype ); + + // set back, as it was overwritten by Masonry + MasonryMode.prototype._getElementOffset = _getElementOffset; + MasonryMode.prototype.layout = layout; + MasonryMode.prototype._getMeasurement = _getMeasurement; + + var measureColumns = MasonryMode.prototype.measureColumns; + MasonryMode.prototype.measureColumns = function() { + // set items, used if measuring first item + this.items = this.isotope.filteredItems; + measureColumns.call( this ); + }; + + // HACK copy over isOriginLeft/Top options + var _manageStamp = MasonryMode.prototype._manageStamp; + MasonryMode.prototype._manageStamp = function() { + this.options.isOriginLeft = this.isotope.options.isOriginLeft; + this.options.isOriginTop = this.isotope.options.isOriginTop; + _manageStamp.apply( this, arguments ); + }; + + return MasonryMode; + +})); + +/** + * fitRows layout mode + */ + +( function( window, factory ) { + 'use strict'; + // universal module definition + if ( typeof define == 'function' && define.amd ) { + // AMD + define( 'isotope/js/layout-modes/fit-rows',[ + '../layout-mode' + ], + factory ); + } else if ( typeof exports == 'object' ) { + // CommonJS + module.exports = factory( + require('../layout-mode') + ); + } else { + // browser global + factory( + window.Isotope.LayoutMode + ); + } + +}( window, function factory( LayoutMode ) { +'use strict'; + +var FitRows = LayoutMode.create('fitRows'); + +FitRows.prototype._resetLayout = function() { + this.x = 0; + this.y = 0; + this.maxY = 0; + this._getMeasurement( 'gutter', 'outerWidth' ); +}; + +FitRows.prototype._getItemLayoutPosition = function( item ) { + item.getSize(); + + var itemWidth = item.size.outerWidth + this.gutter; + // if this element cannot fit in the current row + var containerWidth = this.isotope.size.innerWidth + this.gutter; + if ( this.x !== 0 && itemWidth + this.x > containerWidth ) { + this.x = 0; + this.y = this.maxY; + } + + var position = { + x: this.x, + y: this.y + }; + + this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight ); + this.x += itemWidth; + + return position; +}; + +FitRows.prototype._getContainerSize = function() { + return { height: this.maxY }; +}; + +return FitRows; + +})); + +/** + * vertical layout mode + */ + +( function( window, factory ) { + 'use strict'; + // universal module definition + if ( typeof define == 'function' && define.amd ) { + // AMD + define( 'isotope/js/layout-modes/vertical',[ + '../layout-mode' + ], + factory ); + } else if ( typeof exports == 'object' ) { + // CommonJS + module.exports = factory( + require('../layout-mode') + ); + } else { + // browser global + factory( + window.Isotope.LayoutMode + ); + } + +}( window, function factory( LayoutMode ) { +'use strict'; + +var Vertical = LayoutMode.create( 'vertical', { + horizontalAlignment: 0 +}); + +Vertical.prototype._resetLayout = function() { + this.y = 0; +}; + +Vertical.prototype._getItemLayoutPosition = function( item ) { + item.getSize(); + var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) * + this.options.horizontalAlignment; + var y = this.y; + this.y += item.size.outerHeight; + return { x: x, y: y }; +}; + +Vertical.prototype._getContainerSize = function() { + return { height: this.y }; +}; + +return Vertical; + +})); + +/*! + * Isotope v2.2.2 + * + * Licensed GPLv3 for open source use + * or Isotope Commercial License for commercial use + * + * http://isotope.metafizzy.co + * Copyright 2015 Metafizzy + */ + +( function( window, factory ) { + 'use strict'; + // universal module definition + + if ( typeof define == 'function' && define.amd ) { + // AMD + define( [ + 'outlayer/outlayer', + 'get-size/get-size', + 'matches-selector/matches-selector', + 'fizzy-ui-utils/utils', + 'isotope/js/item', + 'isotope/js/layout-mode', + // include default layout modes + 'isotope/js/layout-modes/masonry', + 'isotope/js/layout-modes/fit-rows', + 'isotope/js/layout-modes/vertical' + ], + function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) { + return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ); + }); + } else if ( typeof exports == 'object' ) { + // CommonJS + module.exports = factory( + window, + require('outlayer'), + require('get-size'), + require('desandro-matches-selector'), + require('fizzy-ui-utils'), + require('./item'), + require('./layout-mode'), + // include default layout modes + require('./layout-modes/masonry'), + require('./layout-modes/fit-rows'), + require('./layout-modes/vertical') + ); + } else { + // browser global + window.Isotope = factory( + window, + window.Outlayer, + window.getSize, + window.matchesSelector, + window.fizzyUIUtils, + window.Isotope.Item, + window.Isotope.LayoutMode + ); + } + +}( window, function factory( window, Outlayer, getSize, matchesSelector, utils, + Item, LayoutMode ) { + + + +// -------------------------- vars -------------------------- // + +var jQuery = window.jQuery; + +// -------------------------- helpers -------------------------- // + +var trim = String.prototype.trim ? + function( str ) { + return str.trim(); + } : + function( str ) { + return str.replace( /^\s+|\s+$/g, '' ); + }; + +var docElem = document.documentElement; + +var getText = docElem.textContent ? + function( elem ) { + return elem.textContent; + } : + function( elem ) { + return elem.innerText; + }; + +// -------------------------- isotopeDefinition -------------------------- // + + // create an Outlayer layout class + var Isotope = Outlayer.create( 'isotope', { + layoutMode: "masonry", + isJQueryFiltering: true, + sortAscending: true + }); + + Isotope.Item = Item; + Isotope.LayoutMode = LayoutMode; + + Isotope.prototype._create = function() { + this.itemGUID = 0; + // functions that sort items + this._sorters = {}; + this._getSorters(); + // call super + Outlayer.prototype._create.call( this ); + + // create layout modes + this.modes = {}; + // start filteredItems with all items + this.filteredItems = this.items; + // keep of track of sortBys + this.sortHistory = [ 'original-order' ]; + // create from registered layout modes + for ( var name in LayoutMode.modes ) { + this._initLayoutMode( name ); + } + }; + + Isotope.prototype.reloadItems = function() { + // reset item ID counter + this.itemGUID = 0; + // call super + Outlayer.prototype.reloadItems.call( this ); + }; + + Isotope.prototype._itemize = function() { + var items = Outlayer.prototype._itemize.apply( this, arguments ); + // assign ID for original-order + for ( var i=0, len = items.length; i < len; i++ ) { + var item = items[i]; + item.id = this.itemGUID++; + } + this._updateItemsSortData( items ); + return items; + }; + + + // -------------------------- layout -------------------------- // + + Isotope.prototype._initLayoutMode = function( name ) { + var Mode = LayoutMode.modes[ name ]; + // set mode options + // HACK extend initial options, back-fill in default options + var initialOpts = this.options[ name ] || {}; + this.options[ name ] = Mode.options ? + utils.extend( Mode.options, initialOpts ) : initialOpts; + // init layout mode instance + this.modes[ name ] = new Mode( this ); + }; + + + Isotope.prototype.layout = function() { + // if first time doing layout, do all magic + if ( !this._isLayoutInited && this.options.isInitLayout ) { + this.arrange(); + return; + } + this._layout(); + }; + + // private method to be used in layout() & magic() + Isotope.prototype._layout = function() { + // don't animate first layout + var isInstant = this._getIsInstant(); + // layout flow + this._resetLayout(); + this._manageStamps(); + this.layoutItems( this.filteredItems, isInstant ); + + // flag for initalized + this._isLayoutInited = true; + }; + + // filter + sort + layout + Isotope.prototype.arrange = function( opts ) { + // set any options pass + this.option( opts ); + this._getIsInstant(); + // filter, sort, and layout + + // filter + var filtered = this._filter( this.items ); + this.filteredItems = filtered.matches; + + var _this = this; + function hideReveal() { + _this.reveal( filtered.needReveal ); + _this.hide( filtered.needHide ); + } + + this._bindArrangeComplete(); + + if ( this._isInstant ) { + this._noTransition( hideReveal ); + } else { + hideReveal(); + } + + this._sort(); + this._layout(); + }; + // alias to _init for main plugin method + Isotope.prototype._init = Isotope.prototype.arrange; + + // HACK + // Don't animate/transition first layout + // Or don't animate/transition other layouts + Isotope.prototype._getIsInstant = function() { + var isInstant = this.options.isLayoutInstant !== undefined ? + this.options.isLayoutInstant : !this._isLayoutInited; + this._isInstant = isInstant; + return isInstant; + }; + + // listen for layoutComplete, hideComplete and revealComplete + // to trigger arrangeComplete + Isotope.prototype._bindArrangeComplete = function() { + // listen for 3 events to trigger arrangeComplete + var isLayoutComplete, isHideComplete, isRevealComplete; + var _this = this; + function arrangeParallelCallback() { + if ( isLayoutComplete && isHideComplete && isRevealComplete ) { + _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] ); + } + } + this.once( 'layoutComplete', function() { + isLayoutComplete = true; + arrangeParallelCallback(); + }); + this.once( 'hideComplete', function() { + isHideComplete = true; + arrangeParallelCallback(); + }); + this.once( 'revealComplete', function() { + isRevealComplete = true; + arrangeParallelCallback(); + }); + }; + + // -------------------------- filter -------------------------- // + + Isotope.prototype._filter = function( items ) { + var filter = this.options.filter; + filter = filter || '*'; + var matches = []; + var hiddenMatched = []; + var visibleUnmatched = []; + + var test = this._getFilterTest( filter ); + + // test each item + for ( var i=0, len = items.length; i < len; i++ ) { + var item = items[i]; + if ( item.isIgnored ) { + continue; + } + // add item to either matched or unmatched group + var isMatched = test( item ); + // item.isFilterMatched = isMatched; + // add to matches if its a match + if ( isMatched ) { + matches.push( item ); + } + // add to additional group if item needs to be hidden or revealed + if ( isMatched && item.isHidden ) { + hiddenMatched.push( item ); + } else if ( !isMatched && !item.isHidden ) { + visibleUnmatched.push( item ); + } + } + + // return collections of items to be manipulated + return { + matches: matches, + needReveal: hiddenMatched, + needHide: visibleUnmatched + }; + }; + + // get a jQuery, function, or a matchesSelector test given the filter + Isotope.prototype._getFilterTest = function( filter ) { + if ( jQuery && this.options.isJQueryFiltering ) { + // use jQuery + return function( item ) { + return jQuery( item.element ).is( filter ); + }; + } + if ( typeof filter == 'function' ) { + // use filter as function + return function( item ) { + return filter( item.element ); + }; + } + // default, use filter as selector string + return function( item ) { + return matchesSelector( item.element, filter ); + }; + }; + + // -------------------------- sorting -------------------------- // + + /** + * @params {Array} elems + * @public + */ + Isotope.prototype.updateSortData = function( elems ) { + // get items + var items; + if ( elems ) { + elems = utils.makeArray( elems ); + items = this.getItems( elems ); + } else { + // update all items if no elems provided + items = this.items; + } + + this._getSorters(); + this._updateItemsSortData( items ); + }; + + Isotope.prototype._getSorters = function() { + var getSortData = this.options.getSortData; + for ( var key in getSortData ) { + var sorter = getSortData[ key ]; + this._sorters[ key ] = mungeSorter( sorter ); + } + }; + + /** + * @params {Array} items - of Isotope.Items + * @private + */ + Isotope.prototype._updateItemsSortData = function( items ) { + // do not update if no items + var len = items && items.length; + + for ( var i=0; len && i < len; i++ ) { + var item = items[i]; + item.updateSortData(); + } + }; + + // ----- munge sorter ----- // + + // encapsulate this, as we just need mungeSorter + // other functions in here are just for munging + var mungeSorter = ( function() { + // add a magic layer to sorters for convienent shorthands + // `.foo-bar` will use the text of .foo-bar querySelector + // `[foo-bar]` will use attribute + // you can also add parser + // `.foo-bar parseInt` will parse that as a number + function mungeSorter( sorter ) { + // if not a string, return function or whatever it is + if ( typeof sorter != 'string' ) { + return sorter; + } + // parse the sorter string + var args = trim( sorter ).split(' '); + var query = args[0]; + // check if query looks like [an-attribute] + var attrMatch = query.match( /^\[(.+)\]$/ ); + var attr = attrMatch && attrMatch[1]; + var getValue = getValueGetter( attr, query ); + // use second argument as a parser + var parser = Isotope.sortDataParsers[ args[1] ]; + // parse the value, if there was a parser + sorter = parser ? function( elem ) { + return elem && parser( getValue( elem ) ); + } : + // otherwise just return value + function( elem ) { + return elem && getValue( elem ); + }; + + return sorter; + } + + // get an attribute getter, or get text of the querySelector + function getValueGetter( attr, query ) { + var getValue; + // if query looks like [foo-bar], get attribute + if ( attr ) { + getValue = function( elem ) { + return elem.getAttribute( attr ); + }; + } else { + // otherwise, assume its a querySelector, and get its text + getValue = function( elem ) { + var child = elem.querySelector( query ); + return child && getText( child ); + }; + } + return getValue; + } + + return mungeSorter; + })(); + + // parsers used in getSortData shortcut strings + Isotope.sortDataParsers = { + 'parseInt': function( val ) { + return parseInt( val, 10 ); + }, + 'parseFloat': function( val ) { + return parseFloat( val ); + } + }; + + // ----- sort method ----- // + + // sort filteredItem order + Isotope.prototype._sort = function() { + var sortByOpt = this.options.sortBy; + if ( !sortByOpt ) { + return; + } + // concat all sortBy and sortHistory + var sortBys = [].concat.apply( sortByOpt, this.sortHistory ); + // sort magic + var itemSorter = getItemSorter( sortBys, this.options.sortAscending ); + this.filteredItems.sort( itemSorter ); + // keep track of sortBy History + if ( sortByOpt != this.sortHistory[0] ) { + // add to front, oldest goes in last + this.sortHistory.unshift( sortByOpt ); + } + }; + + // returns a function used for sorting + function getItemSorter( sortBys, sortAsc ) { + return function sorter( itemA, itemB ) { + // cycle through all sortKeys + for ( var i = 0, len = sortBys.length; i < len; i++ ) { + var sortBy = sortBys[i]; + var a = itemA.sortData[ sortBy ]; + var b = itemB.sortData[ sortBy ]; + if ( a > b || a < b ) { + // if sortAsc is an object, use the value given the sortBy key + var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc; + var direction = isAscending ? 1 : -1; + return ( a > b ? 1 : -1 ) * direction; + } + } + return 0; + }; + } + + // -------------------------- methods -------------------------- // + + // get layout mode + Isotope.prototype._mode = function() { + var layoutMode = this.options.layoutMode; + var mode = this.modes[ layoutMode ]; + if ( !mode ) { + // TODO console.error + throw new Error( 'No layout mode: ' + layoutMode ); + } + // HACK sync mode's options + // any options set after init for layout mode need to be synced + mode.options = this.options[ layoutMode ]; + return mode; + }; + + Isotope.prototype._resetLayout = function() { + // trigger original reset layout + Outlayer.prototype._resetLayout.call( this ); + this._mode()._resetLayout(); + }; + + Isotope.prototype._getItemLayoutPosition = function( item ) { + return this._mode()._getItemLayoutPosition( item ); + }; + + Isotope.prototype._manageStamp = function( stamp ) { + this._mode()._manageStamp( stamp ); + }; + + Isotope.prototype._getContainerSize = function() { + return this._mode()._getContainerSize(); + }; + + Isotope.prototype.needsResizeLayout = function() { + return this._mode().needsResizeLayout(); + }; + + // -------------------------- adding & removing -------------------------- // + + // HEADS UP overwrites default Outlayer appended + Isotope.prototype.appended = function( elems ) { + var items = this.addItems( elems ); + if ( !items.length ) { + return; + } + // filter, layout, reveal new items + var filteredItems = this._filterRevealAdded( items ); + // add to filteredItems + this.filteredItems = this.filteredItems.concat( filteredItems ); + }; + + // HEADS UP overwrites default Outlayer prepended + Isotope.prototype.prepended = function( elems ) { + var items = this._itemize( elems ); + if ( !items.length ) { + return; + } + // start new layout + this._resetLayout(); + this._manageStamps(); + // filter, layout, reveal new items + var filteredItems = this._filterRevealAdded( items ); + // layout previous items + this.layoutItems( this.filteredItems ); + // add to items and filteredItems + this.filteredItems = filteredItems.concat( this.filteredItems ); + this.items = items.concat( this.items ); + }; + + Isotope.prototype._filterRevealAdded = function( items ) { + var filtered = this._filter( items ); + this.hide( filtered.needHide ); + // reveal all new items + this.reveal( filtered.matches ); + // layout new items, no transition + this.layoutItems( filtered.matches, true ); + return filtered.matches; + }; + + /** + * Filter, sort, and layout newly-appended item elements + * @param {Array or NodeList or Element} elems + */ + Isotope.prototype.insert = function( elems ) { + var items = this.addItems( elems ); + if ( !items.length ) { + return; + } + // append item elements + var i, item; + var len = items.length; + for ( i=0; i < len; i++ ) { + item = items[i]; + this.element.appendChild( item.element ); + } + // filter new stuff + var filteredInsertItems = this._filter( items ).matches; + // set flag + for ( i=0; i < len; i++ ) { + items[i].isLayoutInstant = true; + } + this.arrange(); + // reset flag + for ( i=0; i < len; i++ ) { + delete items[i].isLayoutInstant; + } + this.reveal( filteredInsertItems ); + }; + + var _remove = Isotope.prototype.remove; + Isotope.prototype.remove = function( elems ) { + elems = utils.makeArray( elems ); + var removeItems = this.getItems( elems ); + // do regular thing + _remove.call( this, elems ); + // bail if no items to remove + var len = removeItems && removeItems.length; + if ( !len ) { + return; + } + // remove elems from filteredItems + for ( var i=0; i < len; i++ ) { + var item = removeItems[i]; + // remove item from collection + utils.removeFrom( this.filteredItems, item ); + } + }; + + Isotope.prototype.shuffle = function() { + // update random sortData + for ( var i=0, len = this.items.length; i < len; i++ ) { + var item = this.items[i]; + item.sortData.random = Math.random(); + } + this.options.sortBy = 'random'; + this._sort(); + this._layout(); + }; + + /** + * trigger fn without transition + * kind of hacky to have this in the first place + * @param {Function} fn + * @returns ret + * @private + */ + Isotope.prototype._noTransition = function( fn ) { + // save transitionDuration before disabling + var transitionDuration = this.options.transitionDuration; + // disable transition + this.options.transitionDuration = 0; + // do it + var returnValue = fn.call( this ); + // re-enable transition for reveal + this.options.transitionDuration = transitionDuration; + return returnValue; + }; + + // ----- helper methods ----- // + + /** + * getter method for getting filtered item elements + * @returns {Array} elems - collection of item elements + */ + Isotope.prototype.getFilteredItemElements = function() { + var elems = []; + for ( var i=0, len = this.filteredItems.length; i < len; i++ ) { + elems.push( this.filteredItems[i].element ); + } + return elems; + }; + + // ----- ----- // + + return Isotope; + +})); + diff --git a/assets/js/dev/vendors/jquery.actual.js b/assets/js/dev/vendors/jquery.actual.js new file mode 100644 index 0000000..bb64d9f --- /dev/null +++ b/assets/js/dev/vendors/jquery.actual.js @@ -0,0 +1,107 @@ +/*! Copyright 2012, Ben Lin (http://dreamerslab.com/) + * Licensed under the MIT License (LICENSE.txt). + * + * Version: 1.0.19 + * + * Requires: jQuery >= 1.2.3 + */ +;( function ( factory ) { +if ( typeof define === 'function' && define.amd ) { + // AMD. Register module depending on jQuery using requirejs define. + define( ['jquery'], factory ); +} else { + // No AMD. + factory( jQuery ); +} +}( function ( $ ){ + $.fn.addBack = $.fn.addBack || $.fn.andSelf; + + $.fn.extend({ + + actual : function ( method, options ){ + // check if the jQuery method exist + if( !this[ method ]){ + throw '$.actual => The jQuery method "' + method + '" you called does not exist'; + } + + var defaults = { + absolute : false, + clone : false, + includeMargin : false, + display : 'block' + }; + + var configs = $.extend( defaults, options ); + + var $target = this.eq( 0 ); + var fix, restore; + + if( configs.clone === true ){ + fix = function (){ + var style = 'position: absolute !important; top: -1000 !important; '; + + // this is useful with css3pie + $target = $target. + clone(). + attr( 'style', style ). + appendTo( 'body' ); + }; + + restore = function (){ + // remove DOM element after getting the width + $target.remove(); + }; + }else{ + var tmp = []; + var style = ''; + var $hidden; + + fix = function (){ + // get all hidden parents + $hidden = $target.parents().addBack().filter( ':hidden' ); + style += 'visibility: hidden !important; display: ' + configs.display + ' !important; '; + + if( configs.absolute === true ) style += 'position: absolute !important; '; + + // save the origin style props + // set the hidden el css to be got the actual value later + $hidden.each( function (){ + // Save original style. If no style was set, attr() returns undefined + var $this = $( this ); + var thisStyle = $this.attr( 'style' ); + + tmp.push( thisStyle ); + // Retain as much of the original style as possible, if there is one + $this.attr( 'style', thisStyle ? thisStyle + ';' + style : style ); + }); + }; + + restore = function (){ + // restore origin style values + $hidden.each( function ( i ){ + var $this = $( this ); + var _tmp = tmp[ i ]; + + if( _tmp === undefined ){ + $this.removeAttr( 'style' ); + }else{ + $this.attr( 'style', _tmp ); + } + }); + }; + } + + fix(); + // get the actual value with user specific methed + // it can be 'width', 'height', 'outerWidth', 'innerWidth'... etc + // configs.includeMargin only works for 'outerWidth' and 'outerHeight' + var actual = /(outer)/.test( method ) ? + $target[ method ]( configs.includeMargin ) : + $target[ method ](); + + restore(); + // IMPORTANT, this plugin only return the value of the first element + return actual; + } + }); +})); diff --git a/assets/js/dev/vendors/jquery.easing.js b/assets/js/dev/vendors/jquery.easing.js new file mode 100644 index 0000000..f385b8f --- /dev/null +++ b/assets/js/dev/vendors/jquery.easing.js @@ -0,0 +1,168 @@ +/* + * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/ + * Open source under the 3-Clause BSD License. + * Copyright © 2008 George McGinley Smith + * All rights reserved. + * https://raw.github.com/gdsmith/jquery-easing/master/LICENSE +*/ + +(function (factory) { + if (typeof define === "function" && define.amd) { + define(['jquery'], function ($) { + return factory($); + }); + } else if (typeof module === "object" && typeof module.exports === "object") { + exports = factory(require('jquery')); + } else { + factory(jQuery); + } +})(function($){ + +// Preserve the original jQuery "swing" easing as "jswing" +if (typeof $.easing !== 'undefined') { + $.easing['jswing'] = $.easing['swing']; +} + +var pow = Math.pow, + sqrt = Math.sqrt, + sin = Math.sin, + cos = Math.cos, + PI = Math.PI, + c1 = 1.70158, + c2 = c1 * 1.525, + c3 = c1 + 1, + c4 = ( 2 * PI ) / 3, + c5 = ( 2 * PI ) / 4.5; + +// x is the fraction of animation progress, in the range 0..1 +function bounceOut(x) { + var n1 = 7.5625, + d1 = 2.75; + if ( x < 1/d1 ) { + return n1*x*x; + } else if ( x < 2/d1 ) { + return n1*(x-=(1.5/d1))*x + .75; + } else if ( x < 2.5/d1 ) { + return n1*(x-=(2.25/d1))*x + .9375; + } else { + return n1*(x-=(2.625/d1))*x + .984375; + } +} + +$.extend( $.easing, +{ + def: 'easeOutQuad', + swing: function (x) { + return $.easing[$.easing.def](x); + }, + easeInQuad: function (x) { + return x * x; + }, + easeOutQuad: function (x) { + return 1 - ( 1 - x ) * ( 1 - x ); + }, + easeInOutQuad: function (x) { + return x < 0.5 ? + 2 * x * x : + 1 - pow( -2 * x + 2, 2 ) / 2; + }, + easeInCubic: function (x) { + return x * x * x; + }, + easeOutCubic: function (x) { + return 1 - pow( 1 - x, 3 ); + }, + easeInOutCubic: function (x) { + return x < 0.5 ? + 4 * x * x * x : + 1 - pow( -2 * x + 2, 3 ) / 2; + }, + easeInQuart: function (x) { + return x * x * x * x; + }, + easeOutQuart: function (x) { + return 1 - pow( 1 - x, 4 ); + }, + easeInOutQuart: function (x) { + return x < 0.5 ? + 8 * x * x * x * x : + 1 - pow( -2 * x + 2, 4 ) / 2; + }, + easeInQuint: function (x) { + return x * x * x * x * x; + }, + easeOutQuint: function (x) { + return 1 - pow( 1 - x, 5 ); + }, + easeInOutQuint: function (x) { + return x < 0.5 ? + 16 * x * x * x * x * x : + 1 - pow( -2 * x + 2, 5 ) / 2; + }, + easeInSine: function (x) { + return 1 - cos( x * PI/2 ); + }, + easeOutSine: function (x) { + return sin( x * PI/2 ); + }, + easeInOutSine: function (x) { + return -( cos( PI * x ) - 1 ) / 2; + }, + easeInExpo: function (x) { + return x === 0 ? 0 : pow( 2, 10 * x - 10 ); + }, + easeOutExpo: function (x) { + return x === 1 ? 1 : 1 - pow( 2, -10 * x ); + }, + easeInOutExpo: function (x) { + return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? + pow( 2, 20 * x - 10 ) / 2 : + ( 2 - pow( 2, -20 * x + 10 ) ) / 2; + }, + easeInCirc: function (x) { + return 1 - sqrt( 1 - pow( x, 2 ) ); + }, + easeOutCirc: function (x) { + return sqrt( 1 - pow( x - 1, 2 ) ); + }, + easeInOutCirc: function (x) { + return x < 0.5 ? + ( 1 - sqrt( 1 - pow( 2 * x, 2 ) ) ) / 2 : + ( sqrt( 1 - pow( -2 * x + 2, 2 ) ) + 1 ) / 2; + }, + easeInElastic: function (x) { + return x === 0 ? 0 : x === 1 ? 1 : + -pow( 2, 10 * x - 10 ) * sin( ( x * 10 - 10.75 ) * c4 ); + }, + easeOutElastic: function (x) { + return x === 0 ? 0 : x === 1 ? 1 : + pow( 2, -10 * x ) * sin( ( x * 10 - 0.75 ) * c4 ) + 1; + }, + easeInOutElastic: function (x) { + return x === 0 ? 0 : x === 1 ? 1 : x < 0.5 ? + -( pow( 2, 20 * x - 10 ) * sin( ( 20 * x - 11.125 ) * c5 )) / 2 : + pow( 2, -20 * x + 10 ) * sin( ( 20 * x - 11.125 ) * c5 ) / 2 + 1; + }, + easeInBack: function (x) { + return c3 * x * x * x - c1 * x * x; + }, + easeOutBack: function (x) { + return 1 + c3 * pow( x - 1, 3 ) + c1 * pow( x - 1, 2 ); + }, + easeInOutBack: function (x) { + return x < 0.5 ? + ( pow( 2 * x, 2 ) * ( ( c2 + 1 ) * 2 * x - c2 ) ) / 2 : + ( pow( 2 * x - 2, 2 ) *( ( c2 + 1 ) * ( x * 2 - 2 ) + c2 ) + 2 ) / 2; + }, + easeInBounce: function (x) { + return 1 - bounceOut( 1 - x ); + }, + easeOutBounce: bounceOut, + easeInOutBounce: function (x) { + return x < 0.5 ? + ( 1 - bounceOut( 1 - 2 * x ) ) / 2 : + ( 1 + bounceOut( 2 * x - 1 ) ) / 2; + } +}); + +}); \ No newline at end of file diff --git a/assets/js/dev/vendors/jquery.magnific-popup.js b/assets/js/dev/vendors/jquery.magnific-popup.js new file mode 100644 index 0000000..725e19b --- /dev/null +++ b/assets/js/dev/vendors/jquery.magnific-popup.js @@ -0,0 +1,1860 @@ +/*! Magnific Popup - v1.1.0 - 2016-02-20 +* http://dimsemenov.com/plugins/magnific-popup/ +* Copyright (c) 2016 Dmitry Semenov; */ +;(function (factory) { +if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else if (typeof exports === 'object') { + // Node/CommonJS + factory(require('jquery')); + } else { + // Browser globals + factory(window.jQuery || window.Zepto); + } + }(function($) { + +/*>>core*/ +/** + * + * Magnific Popup Core JS file + * + */ + + +/** + * Private static constants + */ +var CLOSE_EVENT = 'Close', + BEFORE_CLOSE_EVENT = 'BeforeClose', + AFTER_CLOSE_EVENT = 'AfterClose', + BEFORE_APPEND_EVENT = 'BeforeAppend', + MARKUP_PARSE_EVENT = 'MarkupParse', + OPEN_EVENT = 'Open', + CHANGE_EVENT = 'Change', + NS = 'mfp', + EVENT_NS = '.' + NS, + READY_CLASS = 'mfp-ready', + REMOVING_CLASS = 'mfp-removing', + PREVENT_CLOSE_CLASS = 'mfp-prevent-close'; + + +/** + * Private vars + */ +/*jshint -W079 */ +var mfp, // As we have only one instance of MagnificPopup object, we define it locally to not to use 'this' + MagnificPopup = function(){}, + _isJQ = !!(window.jQuery), + _prevStatus, + _window = $(window), + _document, + _prevContentType, + _wrapClasses, + _currPopupType; + + +/** + * Private functions + */ +var _mfpOn = function(name, f) { + mfp.ev.on(NS + name + EVENT_NS, f); + }, + _getEl = function(className, appendTo, html, raw) { + var el = document.createElement('div'); + el.className = 'mfp-'+className; + if(html) { + el.innerHTML = html; + } + if(!raw) { + el = $(el); + if(appendTo) { + el.appendTo(appendTo); + } + } else if(appendTo) { + appendTo.appendChild(el); + } + return el; + }, + _mfpTrigger = function(e, data) { + mfp.ev.triggerHandler(NS + e, data); + + if(mfp.st.callbacks) { + // converts "mfpEventName" to "eventName" callback and triggers it if it's present + e = e.charAt(0).toLowerCase() + e.slice(1); + if(mfp.st.callbacks[e]) { + mfp.st.callbacks[e].apply(mfp, $.isArray(data) ? data : [data]); + } + } + }, + _getCloseBtn = function(type) { + if(type !== _currPopupType || !mfp.currTemplate.closeBtn) { + mfp.currTemplate.closeBtn = $( mfp.st.closeMarkup.replace('%title%', mfp.st.tClose ) ); + _currPopupType = type; + } + return mfp.currTemplate.closeBtn; + }, + // Initialize Magnific Popup only when called at least once + _checkInstance = function() { + if(!$.magnificPopup.instance) { + /*jshint -W020 */ + mfp = new MagnificPopup(); + mfp.init(); + $.magnificPopup.instance = mfp; + } + }, + // CSS transition detection, http://stackoverflow.com/questions/7264899/detect-css-transitions-using-javascript-and-without-modernizr + supportsTransitions = function() { + var s = document.createElement('p').style, // 's' for style. better to create an element if body yet to exist + v = ['ms','O','Moz','Webkit']; // 'v' for vendor + + if( s['transition'] !== undefined ) { + return true; + } + + while( v.length ) { + if( v.pop() + 'Transition' in s ) { + return true; + } + } + + return false; + }; + + + +/** + * Public functions + */ +MagnificPopup.prototype = { + + constructor: MagnificPopup, + + /** + * Initializes Magnific Popup plugin. + * This function is triggered only once when $.fn.magnificPopup or $.magnificPopup is executed + */ + init: function() { + var appVersion = navigator.appVersion; + mfp.isLowIE = mfp.isIE8 = document.all && !document.addEventListener; + mfp.isAndroid = (/android/gi).test(appVersion); + mfp.isIOS = (/iphone|ipad|ipod/gi).test(appVersion); + mfp.supportsTransition = supportsTransitions(); + + // We disable fixed positioned lightbox on devices that don't handle it nicely. + // If you know a better way of detecting this - let me know. + mfp.probablyMobile = (mfp.isAndroid || mfp.isIOS || /(Opera Mini)|Kindle|webOS|BlackBerry|(Opera Mobi)|(Windows Phone)|IEMobile/i.test(navigator.userAgent) ); + _document = $(document); + + mfp.popupsCache = {}; + }, + + /** + * Opens popup + * @param data [description] + */ + open: function(data) { + + var i; + + if(data.isObj === false) { + // convert jQuery collection to array to avoid conflicts later + mfp.items = data.items.toArray(); + + mfp.index = 0; + var items = data.items, + item; + for(i = 0; i < items.length; i++) { + item = items[i]; + if(item.parsed) { + item = item.el[0]; + } + if(item === data.el[0]) { + mfp.index = i; + break; + } + } + } else { + mfp.items = $.isArray(data.items) ? data.items : [data.items]; + mfp.index = data.index || 0; + } + + // if popup is already opened - we just update the content + if(mfp.isOpen) { + mfp.updateItemHTML(); + return; + } + + mfp.types = []; + _wrapClasses = ''; + if(data.mainEl && data.mainEl.length) { + mfp.ev = data.mainEl.eq(0); + } else { + mfp.ev = _document; + } + + if(data.key) { + if(!mfp.popupsCache[data.key]) { + mfp.popupsCache[data.key] = {}; + } + mfp.currTemplate = mfp.popupsCache[data.key]; + } else { + mfp.currTemplate = {}; + } + + + + mfp.st = $.extend(true, {}, $.magnificPopup.defaults, data ); + mfp.fixedContentPos = mfp.st.fixedContentPos === 'auto' ? !mfp.probablyMobile : mfp.st.fixedContentPos; + + if(mfp.st.modal) { + mfp.st.closeOnContentClick = false; + mfp.st.closeOnBgClick = false; + mfp.st.showCloseBtn = false; + mfp.st.enableEscapeKey = false; + } + + + // Building markup + // main containers are created only once + if(!mfp.bgOverlay) { + + // Dark overlay + mfp.bgOverlay = _getEl('bg').on('click'+EVENT_NS, function() { + mfp.close(); + }); + + mfp.wrap = _getEl('wrap').attr('tabindex', -1).on('click'+EVENT_NS, function(e) { + if(mfp._checkIfClose(e.target)) { + mfp.close(); + } + }); + + mfp.container = _getEl('container', mfp.wrap); + } + + mfp.contentContainer = _getEl('content'); + if(mfp.st.preloader) { + mfp.preloader = _getEl('preloader', mfp.container, mfp.st.tLoading); + } + + + // Initializing modules + var modules = $.magnificPopup.modules; + for(i = 0; i < modules.length; i++) { + var n = modules[i]; + n = n.charAt(0).toUpperCase() + n.slice(1); + mfp['init'+n].call(mfp); + } + _mfpTrigger('BeforeOpen'); + + + if(mfp.st.showCloseBtn) { + // Close button + if(!mfp.st.closeBtnInside) { + mfp.wrap.append( _getCloseBtn() ); + } else { + _mfpOn(MARKUP_PARSE_EVENT, function(e, template, values, item) { + values.close_replaceWith = _getCloseBtn(item.type); + }); + _wrapClasses += ' mfp-close-btn-in'; + } + } + + if(mfp.st.alignTop) { + _wrapClasses += ' mfp-align-top'; + } + + + + if(mfp.fixedContentPos) { + mfp.wrap.css({ + overflow: mfp.st.overflowY, + overflowX: 'hidden', + overflowY: mfp.st.overflowY + }); + } else { + mfp.wrap.css({ + top: _window.scrollTop(), + position: 'absolute' + }); + } + if( mfp.st.fixedBgPos === false || (mfp.st.fixedBgPos === 'auto' && !mfp.fixedContentPos) ) { + mfp.bgOverlay.css({ + height: _document.height(), + position: 'absolute' + }); + } + + + + if(mfp.st.enableEscapeKey) { + // Close on ESC key + _document.on('keyup' + EVENT_NS, function(e) { + if(e.keyCode === 27) { + mfp.close(); + } + }); + } + + _window.on('resize' + EVENT_NS, function() { + mfp.updateSize(); + }); + + + if(!mfp.st.closeOnContentClick) { + _wrapClasses += ' mfp-auto-cursor'; + } + + if(_wrapClasses) + mfp.wrap.addClass(_wrapClasses); + + + // this triggers recalculation of layout, so we get it once to not to trigger twice + var windowHeight = mfp.wH = _window.height(); + + + var windowStyles = {}; + + if( mfp.fixedContentPos ) { + if(mfp._hasScrollBar(windowHeight)){ + var s = mfp._getScrollbarSize(); + if(s) { + windowStyles.marginRight = s; + } + } + } + + if(mfp.fixedContentPos) { + if(!mfp.isIE7) { + windowStyles.overflow = 'hidden'; + } else { + // ie7 double-scroll bug + $('body, html').css('overflow', 'hidden'); + } + } + + + + var classesToadd = mfp.st.mainClass; + if(mfp.isIE7) { + classesToadd += ' mfp-ie7'; + } + if(classesToadd) { + mfp._addClassToMFP( classesToadd ); + } + + // add content + mfp.updateItemHTML(); + + _mfpTrigger('BuildControls'); + + // remove scrollbar, add margin e.t.c + $('html').css(windowStyles); + + // add everything to DOM + mfp.bgOverlay.add(mfp.wrap).prependTo( mfp.st.prependTo || $(document.body) ); + + // Save last focused element + mfp._lastFocusedEl = document.activeElement; + + // Wait for next cycle to allow CSS transition + setTimeout(function() { + + if(mfp.content) { + mfp._addClassToMFP(READY_CLASS); + mfp._setFocus(); + } else { + // if content is not defined (not loaded e.t.c) we add class only for BG + mfp.bgOverlay.addClass(READY_CLASS); + } + + // Trap the focus in popup + _document.on('focusin' + EVENT_NS, mfp._onFocusIn); + + }, 16); + + mfp.isOpen = true; + mfp.updateSize(windowHeight); + _mfpTrigger(OPEN_EVENT); + + return data; + }, + + /** + * Closes the popup + */ + close: function() { + if(!mfp.isOpen) return; + _mfpTrigger(BEFORE_CLOSE_EVENT); + + mfp.isOpen = false; + // for CSS3 animation + if(mfp.st.removalDelay && !mfp.isLowIE && mfp.supportsTransition ) { + mfp._addClassToMFP(REMOVING_CLASS); + setTimeout(function() { + mfp._close(); + }, mfp.st.removalDelay); + } else { + mfp._close(); + } + }, + + /** + * Helper for close() function + */ + _close: function() { + _mfpTrigger(CLOSE_EVENT); + + var classesToRemove = REMOVING_CLASS + ' ' + READY_CLASS + ' '; + + mfp.bgOverlay.detach(); + mfp.wrap.detach(); + mfp.container.empty(); + + if(mfp.st.mainClass) { + classesToRemove += mfp.st.mainClass + ' '; + } + + mfp._removeClassFromMFP(classesToRemove); + + if(mfp.fixedContentPos) { + var windowStyles = {marginRight: ''}; + if(mfp.isIE7) { + $('body, html').css('overflow', ''); + } else { + windowStyles.overflow = ''; + } + $('html').css(windowStyles); + } + + _document.off('keyup' + EVENT_NS + ' focusin' + EVENT_NS); + mfp.ev.off(EVENT_NS); + + // clean up DOM elements that aren't removed + mfp.wrap.attr('class', 'mfp-wrap').removeAttr('style'); + mfp.bgOverlay.attr('class', 'mfp-bg'); + mfp.container.attr('class', 'mfp-container'); + + // remove close button from target element + if(mfp.st.showCloseBtn && + (!mfp.st.closeBtnInside || mfp.currTemplate[mfp.currItem.type] === true)) { + if(mfp.currTemplate.closeBtn) + mfp.currTemplate.closeBtn.detach(); + } + + + if(mfp.st.autoFocusLast && mfp._lastFocusedEl) { + $(mfp._lastFocusedEl).focus(); // put tab focus back + } + mfp.currItem = null; + mfp.content = null; + mfp.currTemplate = null; + mfp.prevHeight = 0; + + _mfpTrigger(AFTER_CLOSE_EVENT); + }, + + updateSize: function(winHeight) { + + if(mfp.isIOS) { + // fixes iOS nav bars https://github.com/dimsemenov/Magnific-Popup/issues/2 + var zoomLevel = document.documentElement.clientWidth / window.innerWidth; + var height = window.innerHeight * zoomLevel; + mfp.wrap.css('height', height); + mfp.wH = height; + } else { + mfp.wH = winHeight || _window.height(); + } + // Fixes #84: popup incorrectly positioned with position:relative on body + if(!mfp.fixedContentPos) { + mfp.wrap.css('height', mfp.wH); + } + + _mfpTrigger('Resize'); + + }, + + /** + * Set content of popup based on current index + */ + updateItemHTML: function() { + var item = mfp.items[mfp.index]; + + // Detach and perform modifications + mfp.contentContainer.detach(); + + if(mfp.content) + mfp.content.detach(); + + if(!item.parsed) { + item = mfp.parseEl( mfp.index ); + } + + var type = item.type; + + _mfpTrigger('BeforeChange', [mfp.currItem ? mfp.currItem.type : '', type]); + // BeforeChange event works like so: + // _mfpOn('BeforeChange', function(e, prevType, newType) { }); + + mfp.currItem = item; + + if(!mfp.currTemplate[type]) { + var markup = mfp.st[type] ? mfp.st[type].markup : false; + + // allows to modify markup + _mfpTrigger('FirstMarkupParse', markup); + + if(markup) { + mfp.currTemplate[type] = $(markup); + } else { + // if there is no markup found we just define that template is parsed + mfp.currTemplate[type] = true; + } + } + + if(_prevContentType && _prevContentType !== item.type) { + mfp.container.removeClass('mfp-'+_prevContentType+'-holder'); + } + + var newContent = mfp['get' + type.charAt(0).toUpperCase() + type.slice(1)](item, mfp.currTemplate[type]); + mfp.appendContent(newContent, type); + + item.preloaded = true; + + _mfpTrigger(CHANGE_EVENT, item); + _prevContentType = item.type; + + // Append container back after its content changed + mfp.container.prepend(mfp.contentContainer); + + _mfpTrigger('AfterChange'); + }, + + + /** + * Set HTML content of popup + */ + appendContent: function(newContent, type) { + mfp.content = newContent; + + if(newContent) { + if(mfp.st.showCloseBtn && mfp.st.closeBtnInside && + mfp.currTemplate[type] === true) { + // if there is no markup, we just append close button element inside + if(!mfp.content.find('.mfp-close').length) { + mfp.content.append(_getCloseBtn()); + } + } else { + mfp.content = newContent; + } + } else { + mfp.content = ''; + } + + _mfpTrigger(BEFORE_APPEND_EVENT); + mfp.container.addClass('mfp-'+type+'-holder'); + + mfp.contentContainer.prepend(mfp.content); + }, + + + /** + * Creates Magnific Popup data object based on given data + * @param {int} index Index of item to parse + */ + parseEl: function(index) { + var item = mfp.items[index], + type; + + if(item.tagName) { + item = { el: $(item) }; + } else { + type = item.type; + item = { data: item, src: item.src }; + } + + if(item.el) { + var types = mfp.types; + + // check for 'mfp-TYPE' class + for(var i = 0; i < types.length; i++) { + if( item.el.hasClass('mfp-'+types[i]) ) { + type = types[i]; + break; + } + } + + item.src = item.el.attr('data-mfp-src'); + if(!item.src) { + item.src = item.el.attr('href'); + } + } + + item.type = type || mfp.st.type || 'inline'; + item.index = index; + item.parsed = true; + mfp.items[index] = item; + _mfpTrigger('ElementParse', item); + + return mfp.items[index]; + }, + + + /** + * Initializes single popup or a group of popups + */ + addGroup: function(el, options) { + var eHandler = function(e) { + e.mfpEl = this; + mfp._openClick(e, el, options); + }; + + if(!options) { + options = {}; + } + + var eName = 'click.magnificPopup'; + options.mainEl = el; + + if(options.items) { + options.isObj = true; + el.off(eName).on(eName, eHandler); + } else { + options.isObj = false; + if(options.delegate) { + el.off(eName).on(eName, options.delegate , eHandler); + } else { + options.items = el; + el.off(eName).on(eName, eHandler); + } + } + }, + _openClick: function(e, el, options) { + var midClick = options.midClick !== undefined ? options.midClick : $.magnificPopup.defaults.midClick; + + + if(!midClick && ( e.which === 2 || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey ) ) { + return; + } + + var disableOn = options.disableOn !== undefined ? options.disableOn : $.magnificPopup.defaults.disableOn; + + if(disableOn) { + if($.isFunction(disableOn)) { + if( !disableOn.call(mfp) ) { + return true; + } + } else { // else it's number + if( _window.width() < disableOn ) { + return true; + } + } + } + + if(e.type) { + e.preventDefault(); + + // This will prevent popup from closing if element is inside and popup is already opened + if(mfp.isOpen) { + e.stopPropagation(); + } + } + + options.el = $(e.mfpEl); + if(options.delegate) { + options.items = el.find(options.delegate); + } + mfp.open(options); + }, + + + /** + * Updates text on preloader + */ + updateStatus: function(status, text) { + + if(mfp.preloader) { + if(_prevStatus !== status) { + mfp.container.removeClass('mfp-s-'+_prevStatus); + } + + if(!text && status === 'loading') { + text = mfp.st.tLoading; + } + + var data = { + status: status, + text: text + }; + // allows to modify status + _mfpTrigger('UpdateStatus', data); + + status = data.status; + text = data.text; + + mfp.preloader.html(text); + + mfp.preloader.find('a').on('click', function(e) { + e.stopImmediatePropagation(); + }); + + mfp.container.addClass('mfp-s-'+status); + _prevStatus = status; + } + }, + + + /* + "Private" helpers that aren't private at all + */ + // Check to close popup or not + // "target" is an element that was clicked + _checkIfClose: function(target) { + + if($(target).hasClass(PREVENT_CLOSE_CLASS)) { + return; + } + + var closeOnContent = mfp.st.closeOnContentClick; + var closeOnBg = mfp.st.closeOnBgClick; + + if(closeOnContent && closeOnBg) { + return true; + } else { + + // We close the popup if click is on close button or on preloader. Or if there is no content. + if(!mfp.content || $(target).hasClass('mfp-close') || (mfp.preloader && target === mfp.preloader[0]) ) { + return true; + } + + // if click is outside the content + if( (target !== mfp.content[0] && !$.contains(mfp.content[0], target)) ) { + if(closeOnBg) { + // last check, if the clicked element is in DOM, (in case it's removed onclick) + if( $.contains(document, target) ) { + return true; + } + } + } else if(closeOnContent) { + return true; + } + + } + return false; + }, + _addClassToMFP: function(cName) { + mfp.bgOverlay.addClass(cName); + mfp.wrap.addClass(cName); + }, + _removeClassFromMFP: function(cName) { + this.bgOverlay.removeClass(cName); + mfp.wrap.removeClass(cName); + }, + _hasScrollBar: function(winHeight) { + return ( (mfp.isIE7 ? _document.height() : document.body.scrollHeight) > (winHeight || _window.height()) ); + }, + _setFocus: function() { + (mfp.st.focus ? mfp.content.find(mfp.st.focus).eq(0) : mfp.wrap).focus(); + }, + _onFocusIn: function(e) { + if( e.target !== mfp.wrap[0] && !$.contains(mfp.wrap[0], e.target) ) { + mfp._setFocus(); + return false; + } + }, + _parseMarkup: function(template, values, item) { + var arr; + if(item.data) { + values = $.extend(item.data, values); + } + _mfpTrigger(MARKUP_PARSE_EVENT, [template, values, item] ); + + $.each(values, function(key, value) { + if(value === undefined || value === false) { + return true; + } + arr = key.split('_'); + if(arr.length > 1) { + var el = template.find(EVENT_NS + '-'+arr[0]); + + if(el.length > 0) { + var attr = arr[1]; + if(attr === 'replaceWith') { + if(el[0] !== value[0]) { + el.replaceWith(value); + } + } else if(attr === 'img') { + if(el.is('img')) { + el.attr('src', value); + } else { + el.replaceWith( $('').attr('src', value).attr('class', el.attr('class')) ); + } + } else { + el.attr(arr[1], value); + } + } + + } else { + template.find(EVENT_NS + '-'+key).html(value); + } + }); + }, + + _getScrollbarSize: function() { + // thx David + if(mfp.scrollbarSize === undefined) { + var scrollDiv = document.createElement("div"); + scrollDiv.style.cssText = 'width: 99px; height: 99px; overflow: scroll; position: absolute; top: -9999px;'; + document.body.appendChild(scrollDiv); + mfp.scrollbarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth; + document.body.removeChild(scrollDiv); + } + return mfp.scrollbarSize; + } + +}; /* MagnificPopup core prototype end */ + + + + +/** + * Public static functions + */ +$.magnificPopup = { + instance: null, + proto: MagnificPopup.prototype, + modules: [], + + open: function(options, index) { + _checkInstance(); + + if(!options) { + options = {}; + } else { + options = $.extend(true, {}, options); + } + + options.isObj = true; + options.index = index || 0; + return this.instance.open(options); + }, + + close: function() { + return $.magnificPopup.instance && $.magnificPopup.instance.close(); + }, + + registerModule: function(name, module) { + if(module.options) { + $.magnificPopup.defaults[name] = module.options; + } + $.extend(this.proto, module.proto); + this.modules.push(name); + }, + + defaults: { + + // Info about options is in docs: + // http://dimsemenov.com/plugins/magnific-popup/documentation.html#options + + disableOn: 0, + + key: null, + + midClick: false, + + mainClass: '', + + preloader: true, + + focus: '', // CSS selector of input to focus after popup is opened + + closeOnContentClick: false, + + closeOnBgClick: true, + + closeBtnInside: true, + + showCloseBtn: true, + + enableEscapeKey: true, + + modal: false, + + alignTop: false, + + removalDelay: 0, + + prependTo: null, + + fixedContentPos: 'auto', + + fixedBgPos: 'auto', + + overflowY: 'auto', + + closeMarkup: '', + + tClose: 'Close (Esc)', + + tLoading: 'Loading...', + + autoFocusLast: true + + } +}; + + + +$.fn.magnificPopup = function(options) { + _checkInstance(); + + var jqEl = $(this); + + // We call some API method of first param is a string + if (typeof options === "string" ) { + + if(options === 'open') { + var items, + itemOpts = _isJQ ? jqEl.data('magnificPopup') : jqEl[0].magnificPopup, + index = parseInt(arguments[1], 10) || 0; + + if(itemOpts.items) { + items = itemOpts.items[index]; + } else { + items = jqEl; + if(itemOpts.delegate) { + items = items.find(itemOpts.delegate); + } + items = items.eq( index ); + } + mfp._openClick({mfpEl:items}, jqEl, itemOpts); + } else { + if(mfp.isOpen) + mfp[options].apply(mfp, Array.prototype.slice.call(arguments, 1)); + } + + } else { + // clone options obj + options = $.extend(true, {}, options); + + /* + * As Zepto doesn't support .data() method for objects + * and it works only in normal browsers + * we assign "options" object directly to the DOM element. FTW! + */ + if(_isJQ) { + jqEl.data('magnificPopup', options); + } else { + jqEl[0].magnificPopup = options; + } + + mfp.addGroup(jqEl, options); + + } + return jqEl; +}; + +/*>>core*/ + +/*>>inline*/ + +var INLINE_NS = 'inline', + _hiddenClass, + _inlinePlaceholder, + _lastInlineElement, + _putInlineElementsBack = function() { + if(_lastInlineElement) { + _inlinePlaceholder.after( _lastInlineElement.addClass(_hiddenClass) ).detach(); + _lastInlineElement = null; + } + }; + +$.magnificPopup.registerModule(INLINE_NS, { + options: { + hiddenClass: 'hide', // will be appended with `mfp-` prefix + markup: '', + tNotFound: 'Content not found' + }, + proto: { + + initInline: function() { + mfp.types.push(INLINE_NS); + + _mfpOn(CLOSE_EVENT+'.'+INLINE_NS, function() { + _putInlineElementsBack(); + }); + }, + + getInline: function(item, template) { + + _putInlineElementsBack(); + + if(item.src) { + var inlineSt = mfp.st.inline, + el = $(item.src); + + if(el.length) { + + // If target element has parent - we replace it with placeholder and put it back after popup is closed + var parent = el[0].parentNode; + if(parent && parent.tagName) { + if(!_inlinePlaceholder) { + _hiddenClass = inlineSt.hiddenClass; + _inlinePlaceholder = _getEl(_hiddenClass); + _hiddenClass = 'mfp-'+_hiddenClass; + } + // replace target inline element with placeholder + _lastInlineElement = el.after(_inlinePlaceholder).detach().removeClass(_hiddenClass); + } + + mfp.updateStatus('ready'); + } else { + mfp.updateStatus('error', inlineSt.tNotFound); + el = $('
    '); + } + + item.inlineElement = el; + return el; + } + + mfp.updateStatus('ready'); + mfp._parseMarkup(template, {}, item); + return template; + } + } +}); + +/*>>inline*/ + +/*>>ajax*/ +var AJAX_NS = 'ajax', + _ajaxCur, + _removeAjaxCursor = function() { + if(_ajaxCur) { + $(document.body).removeClass(_ajaxCur); + } + }, + _destroyAjaxRequest = function() { + _removeAjaxCursor(); + if(mfp.req) { + mfp.req.abort(); + } + }; + +$.magnificPopup.registerModule(AJAX_NS, { + + options: { + settings: null, + cursor: 'mfp-ajax-cur', + tError: 'The content could not be loaded.' + }, + + proto: { + initAjax: function() { + mfp.types.push(AJAX_NS); + _ajaxCur = mfp.st.ajax.cursor; + + _mfpOn(CLOSE_EVENT+'.'+AJAX_NS, _destroyAjaxRequest); + _mfpOn('BeforeChange.' + AJAX_NS, _destroyAjaxRequest); + }, + getAjax: function(item) { + + if(_ajaxCur) { + $(document.body).addClass(_ajaxCur); + } + + mfp.updateStatus('loading'); + + var opts = $.extend({ + url: item.src, + success: function(data, textStatus, jqXHR) { + var temp = { + data:data, + xhr:jqXHR + }; + + _mfpTrigger('ParseAjax', temp); + + mfp.appendContent( $(temp.data), AJAX_NS ); + + item.finished = true; + + _removeAjaxCursor(); + + mfp._setFocus(); + + setTimeout(function() { + mfp.wrap.addClass(READY_CLASS); + }, 16); + + mfp.updateStatus('ready'); + + _mfpTrigger('AjaxContentAdded'); + }, + error: function() { + _removeAjaxCursor(); + item.finished = item.loadError = true; + mfp.updateStatus('error', mfp.st.ajax.tError.replace('%url%', item.src)); + } + }, mfp.st.ajax.settings); + + mfp.req = $.ajax(opts); + + return ''; + } + } +}); + +/*>>ajax*/ + +/*>>image*/ +var _imgInterval, + _getTitle = function(item) { + if(item.data && item.data.title !== undefined) + return item.data.title; + + var src = mfp.st.image.titleSrc; + + if(src) { + if($.isFunction(src)) { + return src.call(mfp, item); + } else if(item.el) { + return item.el.attr(src) || ''; + } + } + return ''; + }; + +$.magnificPopup.registerModule('image', { + + options: { + markup: '
    '+ + '
    '+ + '
    '+ + '
    '+ + '
    '+ + '
    '+ + '
    '+ + '
    '+ + '
    '+ + '
    '+ + '
    '+ + '
    ', + cursor: 'mfp-zoom-out-cur', + titleSrc: 'title', + verticalFit: true, + tError: 'The image could not be loaded.' + }, + + proto: { + initImage: function() { + var imgSt = mfp.st.image, + ns = '.image'; + + mfp.types.push('image'); + + _mfpOn(OPEN_EVENT+ns, function() { + if(mfp.currItem.type === 'image' && imgSt.cursor) { + $(document.body).addClass(imgSt.cursor); + } + }); + + _mfpOn(CLOSE_EVENT+ns, function() { + if(imgSt.cursor) { + $(document.body).removeClass(imgSt.cursor); + } + _window.off('resize' + EVENT_NS); + }); + + _mfpOn('Resize'+ns, mfp.resizeImage); + if(mfp.isLowIE) { + _mfpOn('AfterChange', mfp.resizeImage); + } + }, + resizeImage: function() { + var item = mfp.currItem; + if(!item || !item.img) return; + + if(mfp.st.image.verticalFit) { + var decr = 0; + // fix box-sizing in ie7/8 + if(mfp.isLowIE) { + decr = parseInt(item.img.css('padding-top'), 10) + parseInt(item.img.css('padding-bottom'),10); + } + item.img.css('max-height', mfp.wH-decr); + } + }, + _onImageHasSize: function(item) { + if(item.img) { + + item.hasSize = true; + + if(_imgInterval) { + clearInterval(_imgInterval); + } + + item.isCheckingImgSize = false; + + _mfpTrigger('ImageHasSize', item); + + if(item.imgHidden) { + if(mfp.content) + mfp.content.removeClass('mfp-loading'); + + item.imgHidden = false; + } + + } + }, + + /** + * Function that loops until the image has size to display elements that rely on it asap + */ + findImageSize: function(item) { + + var counter = 0, + img = item.img[0], + mfpSetInterval = function(delay) { + + if(_imgInterval) { + clearInterval(_imgInterval); + } + // decelerating interval that checks for size of an image + _imgInterval = setInterval(function() { + if(img.naturalWidth > 0) { + mfp._onImageHasSize(item); + return; + } + + if(counter > 200) { + clearInterval(_imgInterval); + } + + counter++; + if(counter === 3) { + mfpSetInterval(10); + } else if(counter === 40) { + mfpSetInterval(50); + } else if(counter === 100) { + mfpSetInterval(500); + } + }, delay); + }; + + mfpSetInterval(1); + }, + + getImage: function(item, template) { + + var guard = 0, + + // image load complete handler + onLoadComplete = function() { + if(item) { + if (item.img[0].complete) { + item.img.off('.mfploader'); + + if(item === mfp.currItem){ + mfp._onImageHasSize(item); + + mfp.updateStatus('ready'); + } + + item.hasSize = true; + item.loaded = true; + + _mfpTrigger('ImageLoadComplete'); + + } + else { + // if image complete check fails 200 times (20 sec), we assume that there was an error. + guard++; + if(guard < 200) { + setTimeout(onLoadComplete,100); + } else { + onLoadError(); + } + } + } + }, + + // image error handler + onLoadError = function() { + if(item) { + item.img.off('.mfploader'); + if(item === mfp.currItem){ + mfp._onImageHasSize(item); + mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) ); + } + + item.hasSize = true; + item.loaded = true; + item.loadError = true; + } + }, + imgSt = mfp.st.image; + + + var el = template.find('.mfp-img'); + if(el.length) { + var img = document.createElement('img'); + img.className = 'mfp-img'; + if(item.el && item.el.find('img').length) { + img.alt = item.el.find('img').attr('alt'); + } + item.img = $(img).on('load.mfploader', onLoadComplete).on('error.mfploader', onLoadError); + img.src = item.src; + + // without clone() "error" event is not firing when IMG is replaced by new IMG + // TODO: find a way to avoid such cloning + if(el.is('img')) { + item.img = item.img.clone(); + } + + img = item.img[0]; + if(img.naturalWidth > 0) { + item.hasSize = true; + } else if(!img.width) { + item.hasSize = false; + } + } + + mfp._parseMarkup(template, { + title: _getTitle(item), + img_replaceWith: item.img + }, item); + + mfp.resizeImage(); + + if(item.hasSize) { + if(_imgInterval) clearInterval(_imgInterval); + + if(item.loadError) { + template.addClass('mfp-loading'); + mfp.updateStatus('error', imgSt.tError.replace('%url%', item.src) ); + } else { + template.removeClass('mfp-loading'); + mfp.updateStatus('ready'); + } + return template; + } + + mfp.updateStatus('loading'); + item.loading = true; + + if(!item.hasSize) { + item.imgHidden = true; + template.addClass('mfp-loading'); + mfp.findImageSize(item); + } + + return template; + } + } +}); + +/*>>image*/ + +/*>>zoom*/ +var hasMozTransform, + getHasMozTransform = function() { + if(hasMozTransform === undefined) { + hasMozTransform = document.createElement('p').style.MozTransform !== undefined; + } + return hasMozTransform; + }; + +$.magnificPopup.registerModule('zoom', { + + options: { + enabled: false, + easing: 'ease-in-out', + duration: 300, + opener: function(element) { + return element.is('img') ? element : element.find('img'); + } + }, + + proto: { + + initZoom: function() { + var zoomSt = mfp.st.zoom, + ns = '.zoom', + image; + + if(!zoomSt.enabled || !mfp.supportsTransition) { + return; + } + + var duration = zoomSt.duration, + getElToAnimate = function(image) { + var newImg = image.clone().removeAttr('style').removeAttr('class').addClass('mfp-animated-image'), + transition = 'all '+(zoomSt.duration/1000)+'s ' + zoomSt.easing, + cssObj = { + position: 'fixed', + zIndex: 9999, + left: 0, + top: 0, + '-webkit-backface-visibility': 'hidden' + }, + t = 'transition'; + + cssObj['-webkit-'+t] = cssObj['-moz-'+t] = cssObj['-o-'+t] = cssObj[t] = transition; + + newImg.css(cssObj); + return newImg; + }, + showMainContent = function() { + mfp.content.css('visibility', 'visible'); + }, + openTimeout, + animatedImg; + + _mfpOn('BuildControls'+ns, function() { + if(mfp._allowZoom()) { + + clearTimeout(openTimeout); + mfp.content.css('visibility', 'hidden'); + + // Basically, all code below does is clones existing image, puts in on top of the current one and animated it + + image = mfp._getItemToZoom(); + + if(!image) { + showMainContent(); + return; + } + + animatedImg = getElToAnimate(image); + + animatedImg.css( mfp._getOffset() ); + + mfp.wrap.append(animatedImg); + + openTimeout = setTimeout(function() { + animatedImg.css( mfp._getOffset( true ) ); + openTimeout = setTimeout(function() { + + showMainContent(); + + setTimeout(function() { + animatedImg.remove(); + image = animatedImg = null; + _mfpTrigger('ZoomAnimationEnded'); + }, 16); // avoid blink when switching images + + }, duration); // this timeout equals animation duration + + }, 16); // by adding this timeout we avoid short glitch at the beginning of animation + + + // Lots of timeouts... + } + }); + _mfpOn(BEFORE_CLOSE_EVENT+ns, function() { + if(mfp._allowZoom()) { + + clearTimeout(openTimeout); + + mfp.st.removalDelay = duration; + + if(!image) { + image = mfp._getItemToZoom(); + if(!image) { + return; + } + animatedImg = getElToAnimate(image); + } + + animatedImg.css( mfp._getOffset(true) ); + mfp.wrap.append(animatedImg); + mfp.content.css('visibility', 'hidden'); + + setTimeout(function() { + animatedImg.css( mfp._getOffset() ); + }, 16); + } + + }); + + _mfpOn(CLOSE_EVENT+ns, function() { + if(mfp._allowZoom()) { + showMainContent(); + if(animatedImg) { + animatedImg.remove(); + } + image = null; + } + }); + }, + + _allowZoom: function() { + return mfp.currItem.type === 'image'; + }, + + _getItemToZoom: function() { + if(mfp.currItem.hasSize) { + return mfp.currItem.img; + } else { + return false; + } + }, + + // Get element postion relative to viewport + _getOffset: function(isLarge) { + var el; + if(isLarge) { + el = mfp.currItem.img; + } else { + el = mfp.st.zoom.opener(mfp.currItem.el || mfp.currItem); + } + + var offset = el.offset(); + var paddingTop = parseInt(el.css('padding-top'),10); + var paddingBottom = parseInt(el.css('padding-bottom'),10); + offset.top -= ( $(window).scrollTop() - paddingTop ); + + + /* + + Animating left + top + width/height looks glitchy in Firefox, but perfect in Chrome. And vice-versa. + + */ + var obj = { + width: el.width(), + // fix Zepto height+padding issue + height: (_isJQ ? el.innerHeight() : el[0].offsetHeight) - paddingBottom - paddingTop + }; + + // I hate to do this, but there is no another option + if( getHasMozTransform() ) { + obj['-moz-transform'] = obj['transform'] = 'translate(' + offset.left + 'px,' + offset.top + 'px)'; + } else { + obj.left = offset.left; + obj.top = offset.top; + } + return obj; + } + + } +}); + + + +/*>>zoom*/ + +/*>>iframe*/ + +var IFRAME_NS = 'iframe', + _emptyPage = '//about:blank', + + _fixIframeBugs = function(isShowing) { + if(mfp.currTemplate[IFRAME_NS]) { + var el = mfp.currTemplate[IFRAME_NS].find('iframe'); + if(el.length) { + // reset src after the popup is closed to avoid "video keeps playing after popup is closed" bug + if(!isShowing) { + el[0].src = _emptyPage; + } + + // IE8 black screen bug fix + if(mfp.isIE8) { + el.css('display', isShowing ? 'block' : 'none'); + } + } + } + }; + +$.magnificPopup.registerModule(IFRAME_NS, { + + options: { + markup: '
    '+ + '
    '+ + ''+ + '
    ', + + srcAction: 'iframe_src', + + // we don't care and support only one default type of URL by default + patterns: { + youtube: { + index: 'youtube.com', + id: 'v=', + src: '//www.youtube.com/embed/%id%?autoplay=1' + }, + vimeo: { + index: 'vimeo.com/', + id: '/', + src: '//player.vimeo.com/video/%id%?autoplay=1' + }, + gmaps: { + index: '//maps.google.', + src: '%id%&output=embed' + } + } + }, + + proto: { + initIframe: function() { + mfp.types.push(IFRAME_NS); + + _mfpOn('BeforeChange', function(e, prevType, newType) { + if(prevType !== newType) { + if(prevType === IFRAME_NS) { + _fixIframeBugs(); // iframe if removed + } else if(newType === IFRAME_NS) { + _fixIframeBugs(true); // iframe is showing + } + }// else { + // iframe source is switched, don't do anything + //} + }); + + _mfpOn(CLOSE_EVENT + '.' + IFRAME_NS, function() { + _fixIframeBugs(); + }); + }, + + getIframe: function(item, template) { + var embedSrc = item.src; + var iframeSt = mfp.st.iframe; + + $.each(iframeSt.patterns, function() { + if(embedSrc.indexOf( this.index ) > -1) { + if(this.id) { + if(typeof this.id === 'string') { + embedSrc = embedSrc.substr(embedSrc.lastIndexOf(this.id)+this.id.length, embedSrc.length); + } else { + embedSrc = this.id.call( this, embedSrc ); + } + } + embedSrc = this.src.replace('%id%', embedSrc ); + return false; // break; + } + }); + + var dataObj = {}; + if(iframeSt.srcAction) { + dataObj[iframeSt.srcAction] = embedSrc; + } + mfp._parseMarkup(template, dataObj, item); + + mfp.updateStatus('ready'); + + return template; + } + } +}); + + + +/*>>iframe*/ + +/*>>gallery*/ +/** + * Get looped index depending on number of slides + */ +var _getLoopedId = function(index) { + var numSlides = mfp.items.length; + if(index > numSlides - 1) { + return index - numSlides; + } else if(index < 0) { + return numSlides + index; + } + return index; + }, + _replaceCurrTotal = function(text, curr, total) { + return text.replace(/%curr%/gi, curr + 1).replace(/%total%/gi, total); + }; + +$.magnificPopup.registerModule('gallery', { + + options: { + enabled: false, + arrowMarkup: '', + preload: [0,2], + navigateByImgClick: true, + arrows: true, + + tPrev: 'Previous (Left arrow key)', + tNext: 'Next (Right arrow key)', + tCounter: '%curr% of %total%' + }, + + proto: { + initGallery: function() { + + var gSt = mfp.st.gallery, + ns = '.mfp-gallery'; + + mfp.direction = true; // true - next, false - prev + + if(!gSt || !gSt.enabled ) return false; + + _wrapClasses += ' mfp-gallery'; + + _mfpOn(OPEN_EVENT+ns, function() { + + if(gSt.navigateByImgClick) { + mfp.wrap.on('click'+ns, '.mfp-img', function() { + if(mfp.items.length > 1) { + mfp.next(); + return false; + } + }); + } + + _document.on('keydown'+ns, function(e) { + if (e.keyCode === 37) { + mfp.prev(); + } else if (e.keyCode === 39) { + mfp.next(); + } + }); + }); + + _mfpOn('UpdateStatus'+ns, function(e, data) { + if(data.text) { + data.text = _replaceCurrTotal(data.text, mfp.currItem.index, mfp.items.length); + } + }); + + _mfpOn(MARKUP_PARSE_EVENT+ns, function(e, element, values, item) { + var l = mfp.items.length; + values.counter = l > 1 ? _replaceCurrTotal(gSt.tCounter, item.index, l) : ''; + }); + + _mfpOn('BuildControls' + ns, function() { + if(mfp.items.length > 1 && gSt.arrows && !mfp.arrowLeft) { + var markup = gSt.arrowMarkup, + arrowLeft = mfp.arrowLeft = $( markup.replace(/%title%/gi, gSt.tPrev).replace(/%dir%/gi, 'left') ).addClass(PREVENT_CLOSE_CLASS), + arrowRight = mfp.arrowRight = $( markup.replace(/%title%/gi, gSt.tNext).replace(/%dir%/gi, 'right') ).addClass(PREVENT_CLOSE_CLASS); + + arrowLeft.click(function() { + mfp.prev(); + }); + arrowRight.click(function() { + mfp.next(); + }); + + mfp.container.append(arrowLeft.add(arrowRight)); + } + }); + + _mfpOn(CHANGE_EVENT+ns, function() { + if(mfp._preloadTimeout) clearTimeout(mfp._preloadTimeout); + + mfp._preloadTimeout = setTimeout(function() { + mfp.preloadNearbyImages(); + mfp._preloadTimeout = null; + }, 16); + }); + + + _mfpOn(CLOSE_EVENT+ns, function() { + _document.off(ns); + mfp.wrap.off('click'+ns); + mfp.arrowRight = mfp.arrowLeft = null; + }); + + }, + next: function() { + mfp.direction = true; + mfp.index = _getLoopedId(mfp.index + 1); + mfp.updateItemHTML(); + }, + prev: function() { + mfp.direction = false; + mfp.index = _getLoopedId(mfp.index - 1); + mfp.updateItemHTML(); + }, + goTo: function(newIndex) { + mfp.direction = (newIndex >= mfp.index); + mfp.index = newIndex; + mfp.updateItemHTML(); + }, + preloadNearbyImages: function() { + var p = mfp.st.gallery.preload, + preloadBefore = Math.min(p[0], mfp.items.length), + preloadAfter = Math.min(p[1], mfp.items.length), + i; + + for(i = 1; i <= (mfp.direction ? preloadAfter : preloadBefore); i++) { + mfp._preloadItem(mfp.index+i); + } + for(i = 1; i <= (mfp.direction ? preloadBefore : preloadAfter); i++) { + mfp._preloadItem(mfp.index-i); + } + }, + _preloadItem: function(index) { + index = _getLoopedId(index); + + if(mfp.items[index].preloaded) { + return; + } + + var item = mfp.items[index]; + if(!item.parsed) { + item = mfp.parseEl( index ); + } + + _mfpTrigger('LazyLoad', item); + + if(item.type === 'image') { + item.img = $('').on('load.mfploader', function() { + item.hasSize = true; + }).on('error.mfploader', function() { + item.hasSize = true; + item.loadError = true; + _mfpTrigger('LazyLoadError', item); + }).attr('src', item.src); + } + + + item.preloaded = true; + } + } +}); + +/*>>gallery*/ + +/*>>retina*/ + +var RETINA_NS = 'retina'; + +$.magnificPopup.registerModule(RETINA_NS, { + options: { + replaceSrc: function(item) { + return item.src.replace(/\.\w+$/, function(m) { return '@2x' + m; }); + }, + ratio: 1 // Function or number. Set to 1 to disable. + }, + proto: { + initRetina: function() { + if(window.devicePixelRatio > 1) { + + var st = mfp.st.retina, + ratio = st.ratio; + + ratio = !isNaN(ratio) ? ratio : ratio(); + + if(ratio > 1) { + _mfpOn('ImageHasSize' + '.' + RETINA_NS, function(e, item) { + item.img.css({ + 'max-width': item.img[0].naturalWidth / ratio, + 'width': '100%' + }); + }); + _mfpOn('ElementParse' + '.' + RETINA_NS, function(e, item) { + item.src = st.replaceSrc(item, ratio); + }); + } + } + + } + } +}); + +/*>>retina*/ + _checkInstance(); })); \ No newline at end of file diff --git a/assets/js/dev/vendors/jquery.visible.js b/assets/js/dev/vendors/jquery.visible.js new file mode 100644 index 0000000..37072b4 --- /dev/null +++ b/assets/js/dev/vendors/jquery.visible.js @@ -0,0 +1,83 @@ +(function($){ + + /** + * Copyright 2012, Digital Fusion + * Licensed under the MIT license. + * http://teamdf.com/jquery-plugins/license/ + * + * @author Sam Sehnert + * @desc A small plugin that checks whether elements are within + * the user visible viewport of a web browser. + * only accounts for vertical position, not horizontal. + */ + var $w=$(window); + $.fn.visible = function(partial,hidden,direction,container){ + + if (this.length < 1) + return; + + // Set direction default to 'both'. + direction = direction || 'both'; + + var $t = this.length > 1 ? this.eq(0) : this, + isContained = typeof container !== 'undefined' && container !== null, + $c = isContained ? $(container) : $w, + wPosition = isContained ? $c.position() : 0, + t = $t.get(0), + vpWidth = $c.outerWidth(), + vpHeight = $c.outerHeight(), + clientSize = hidden === true ? t.offsetWidth * t.offsetHeight : true; + + if (typeof t.getBoundingClientRect === 'function'){ + + // Use this native browser method, if available. + var rec = t.getBoundingClientRect(), + tViz = isContained ? + rec.top - wPosition.top >= 0 && rec.top < vpHeight + wPosition.top : + rec.top >= 0 && rec.top < vpHeight, + bViz = isContained ? + rec.bottom - wPosition.top > 0 && rec.bottom <= vpHeight + wPosition.top : + rec.bottom > 0 && rec.bottom <= vpHeight, + lViz = isContained ? + rec.left - wPosition.left >= 0 && rec.left < vpWidth + wPosition.left : + rec.left >= 0 && rec.left < vpWidth, + rViz = isContained ? + rec.right - wPosition.left > 0 && rec.right < vpWidth + wPosition.left : + rec.right > 0 && rec.right <= vpWidth, + vVisible = partial ? tViz || bViz : tViz && bViz, + hVisible = partial ? lViz || rViz : lViz && rViz, + vVisible = (rec.top < 0 && rec.bottom > vpHeight) ? true : vVisible, + hVisible = (rec.left < 0 && rec.right > vpWidth) ? true : hVisible; + + if(direction === 'both') + return clientSize && vVisible && hVisible; + else if(direction === 'vertical') + return clientSize && vVisible; + else if(direction === 'horizontal') + return clientSize && hVisible; + } else { + + var viewTop = isContained ? 0 : wPosition, + viewBottom = viewTop + vpHeight, + viewLeft = $c.scrollLeft(), + viewRight = viewLeft + vpWidth, + position = $t.position(), + _top = position.top, + _bottom = _top + $t.height(), + _left = position.left, + _right = _left + $t.width(), + compareTop = partial === true ? _bottom : _top, + compareBottom = partial === true ? _top : _bottom, + compareLeft = partial === true ? _right : _left, + compareRight = partial === true ? _left : _right; + + if(direction === 'both') + return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop)) && ((compareRight <= viewRight) && (compareLeft >= viewLeft)); + else if(direction === 'vertical') + return !!clientSize && ((compareBottom <= viewBottom) && (compareTop >= viewTop)); + else if(direction === 'horizontal') + return !!clientSize && ((compareRight <= viewRight) && (compareLeft >= viewLeft)); + } + }; + +})(jQuery); diff --git a/assets/js/dev/vendors/js.cookie.js b/assets/js/dev/vendors/js.cookie.js new file mode 100644 index 0000000..12fa0ee --- /dev/null +++ b/assets/js/dev/vendors/js.cookie.js @@ -0,0 +1,156 @@ +/*! + * JavaScript Cookie v2.1.3 + * https://github.com/js-cookie/js-cookie + * + * Copyright 2006, 2015 Klaus Hartl & Fagner Brack + * Released under the MIT license + */ +;(function (factory) { + var registeredInModuleLoader = false; + if (typeof define === 'function' && define.amd) { + define(factory); + registeredInModuleLoader = true; + } + if (typeof exports === 'object') { + module.exports = factory(); + registeredInModuleLoader = true; + } + if (!registeredInModuleLoader) { + var OldCookies = window.Cookies; + var api = window.Cookies = factory(); + api.noConflict = function () { + window.Cookies = OldCookies; + return api; + }; + } +}(function () { + function extend () { + var i = 0; + var result = {}; + for (; i < arguments.length; i++) { + var attributes = arguments[ i ]; + for (var key in attributes) { + result[key] = attributes[key]; + } + } + return result; + } + + function init (converter) { + function api (key, value, attributes) { + var result; + if (typeof document === 'undefined') { + return; + } + + // Write + + if (arguments.length > 1) { + attributes = extend({ + path: '/' + }, api.defaults, attributes); + + if (typeof attributes.expires === 'number') { + var expires = new Date(); + expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5); + attributes.expires = expires; + } + + try { + result = JSON.stringify(value); + if (/^[\{\[]/.test(result)) { + value = result; + } + } catch (e) {} + + if (!converter.write) { + value = encodeURIComponent(String(value)) + .replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); + } else { + value = converter.write(value, key); + } + + key = encodeURIComponent(String(key)); + key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent); + key = key.replace(/[\(\)]/g, escape); + + return (document.cookie = [ + key, '=', value, + attributes.expires ? '; expires=' + attributes.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE + attributes.path ? '; path=' + attributes.path : '', + attributes.domain ? '; domain=' + attributes.domain : '', + attributes.secure ? '; secure' : '' + ].join('')); + } + + // Read + + if (!key) { + result = {}; + } + + // To prevent the for loop in the first place assign an empty array + // in case there are no cookies at all. Also prevents odd result when + // calling "get()" + var cookies = document.cookie ? document.cookie.split('; ') : []; + var rdecode = /(%[0-9A-Z]{2})+/g; + var i = 0; + + for (; i < cookies.length; i++) { + var parts = cookies[i].split('='); + var cookie = parts.slice(1).join('='); + + if (cookie.charAt(0) === '"') { + cookie = cookie.slice(1, -1); + } + + try { + var name = parts[0].replace(rdecode, decodeURIComponent); + cookie = converter.read ? + converter.read(cookie, name) : converter(cookie, name) || + cookie.replace(rdecode, decodeURIComponent); + + if (this.json) { + try { + cookie = JSON.parse(cookie); + } catch (e) {} + } + + if (key === name) { + result = cookie; + break; + } + + if (!key) { + result[name] = cookie; + } + } catch (e) {} + } + + return result; + } + + api.set = api; + api.get = function (key) { + return api.call(api, key); + }; + api.getJSON = function () { + return api.apply({ + json: true + }, [].slice.call(arguments)); + }; + api.defaults = {}; + + api.remove = function (key, attributes) { + api(key, '', extend(attributes, { + expires: -1 + })); + }; + + api.withConverter = init; + + return api; + } + + return init(function () {}); +})); diff --git a/assets/js/dev/vendors/noframework.waypoints.js b/assets/js/dev/vendors/noframework.waypoints.js new file mode 100644 index 0000000..a735441 --- /dev/null +++ b/assets/js/dev/vendors/noframework.waypoints.js @@ -0,0 +1,758 @@ +/*! +Waypoints - 4.0.1 +Copyright © 2011-2016 Caleb Troughton +Licensed under the MIT license. +https://github.com/imakewebthings/waypoints/blob/master/licenses.txt +*/ +(function() { + 'use strict' + + var keyCounter = 0 + var allWaypoints = {} + + /* http://imakewebthings.com/waypoints/api/waypoint */ + function Waypoint(options) { + if (!options) { + throw new Error('No options passed to Waypoint constructor') + } + if (!options.element) { + throw new Error('No element option passed to Waypoint constructor') + } + if (!options.handler) { + throw new Error('No handler option passed to Waypoint constructor') + } + + this.key = 'waypoint-' + keyCounter + this.options = Waypoint.Adapter.extend({}, Waypoint.defaults, options) + this.element = this.options.element + this.adapter = new Waypoint.Adapter(this.element) + this.callback = options.handler + this.axis = this.options.horizontal ? 'horizontal' : 'vertical' + this.enabled = this.options.enabled + this.triggerPoint = null + this.group = Waypoint.Group.findOrCreate({ + name: this.options.group, + axis: this.axis + }) + this.context = Waypoint.Context.findOrCreateByElement(this.options.context) + + if (Waypoint.offsetAliases[this.options.offset]) { + this.options.offset = Waypoint.offsetAliases[this.options.offset] + } + this.group.add(this) + this.context.add(this) + allWaypoints[this.key] = this + keyCounter += 1 + } + + /* Private */ + Waypoint.prototype.queueTrigger = function(direction) { + this.group.queueTrigger(this, direction) + } + + /* Private */ + Waypoint.prototype.trigger = function(args) { + if (!this.enabled) { + return + } + if (this.callback) { + this.callback.apply(this, args) + } + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/destroy */ + Waypoint.prototype.destroy = function() { + this.context.remove(this) + this.group.remove(this) + delete allWaypoints[this.key] + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/disable */ + Waypoint.prototype.disable = function() { + this.enabled = false + return this + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/enable */ + Waypoint.prototype.enable = function() { + this.context.refresh() + this.enabled = true + return this + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/next */ + Waypoint.prototype.next = function() { + return this.group.next(this) + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/previous */ + Waypoint.prototype.previous = function() { + return this.group.previous(this) + } + + /* Private */ + Waypoint.invokeAll = function(method) { + var allWaypointsArray = [] + for (var waypointKey in allWaypoints) { + allWaypointsArray.push(allWaypoints[waypointKey]) + } + for (var i = 0, end = allWaypointsArray.length; i < end; i++) { + allWaypointsArray[i][method]() + } + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/destroy-all */ + Waypoint.destroyAll = function() { + Waypoint.invokeAll('destroy') + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/disable-all */ + Waypoint.disableAll = function() { + Waypoint.invokeAll('disable') + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/enable-all */ + Waypoint.enableAll = function() { + Waypoint.Context.refreshAll() + for (var waypointKey in allWaypoints) { + allWaypoints[waypointKey].enabled = true + } + return this + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/refresh-all */ + Waypoint.refreshAll = function() { + Waypoint.Context.refreshAll() + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/viewport-height */ + Waypoint.viewportHeight = function() { + return window.innerHeight || document.documentElement.clientHeight + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/viewport-width */ + Waypoint.viewportWidth = function() { + return document.documentElement.clientWidth + } + + Waypoint.adapters = [] + + Waypoint.defaults = { + context: window, + continuous: true, + enabled: true, + group: 'default', + horizontal: false, + offset: 0 + } + + Waypoint.offsetAliases = { + 'bottom-in-view': function() { + return this.context.innerHeight() - this.adapter.outerHeight() + }, + 'right-in-view': function() { + return this.context.innerWidth() - this.adapter.outerWidth() + } + } + + window.Waypoint = Waypoint +}()) +;(function() { + 'use strict' + + function requestAnimationFrameShim(callback) { + window.setTimeout(callback, 1000 / 60) + } + + var keyCounter = 0 + var contexts = {} + var Waypoint = window.Waypoint + var oldWindowLoad = window.onload + + /* http://imakewebthings.com/waypoints/api/context */ + function Context(element) { + this.element = element + this.Adapter = Waypoint.Adapter + this.adapter = new this.Adapter(element) + this.key = 'waypoint-context-' + keyCounter + this.didScroll = false + this.didResize = false + this.oldScroll = { + x: this.adapter.scrollLeft(), + y: this.adapter.scrollTop() + } + this.waypoints = { + vertical: {}, + horizontal: {} + } + + element.waypointContextKey = this.key + contexts[element.waypointContextKey] = this + keyCounter += 1 + if (!Waypoint.windowContext) { + Waypoint.windowContext = true + Waypoint.windowContext = new Context(window) + } + + this.createThrottledScrollHandler() + this.createThrottledResizeHandler() + } + + /* Private */ + Context.prototype.add = function(waypoint) { + var axis = waypoint.options.horizontal ? 'horizontal' : 'vertical' + this.waypoints[axis][waypoint.key] = waypoint + this.refresh() + } + + /* Private */ + Context.prototype.checkEmpty = function() { + var horizontalEmpty = this.Adapter.isEmptyObject(this.waypoints.horizontal) + var verticalEmpty = this.Adapter.isEmptyObject(this.waypoints.vertical) + var isWindow = this.element == this.element.window + if (horizontalEmpty && verticalEmpty && !isWindow) { + this.adapter.off('.waypoints') + delete contexts[this.key] + } + } + + /* Private */ + Context.prototype.createThrottledResizeHandler = function() { + var self = this + + function resizeHandler() { + self.handleResize() + self.didResize = false + } + + this.adapter.on('resize.waypoints', function() { + if (!self.didResize) { + self.didResize = true + Waypoint.requestAnimationFrame(resizeHandler) + } + }) + } + + /* Private */ + Context.prototype.createThrottledScrollHandler = function() { + var self = this + function scrollHandler() { + self.handleScroll() + self.didScroll = false + } + + this.adapter.on('scroll.waypoints', function() { + if (!self.didScroll || Waypoint.isTouch) { + self.didScroll = true + Waypoint.requestAnimationFrame(scrollHandler) + } + }) + } + + /* Private */ + Context.prototype.handleResize = function() { + Waypoint.Context.refreshAll() + } + + /* Private */ + Context.prototype.handleScroll = function() { + var triggeredGroups = {} + var axes = { + horizontal: { + newScroll: this.adapter.scrollLeft(), + oldScroll: this.oldScroll.x, + forward: 'right', + backward: 'left' + }, + vertical: { + newScroll: this.adapter.scrollTop(), + oldScroll: this.oldScroll.y, + forward: 'down', + backward: 'up' + } + } + + for (var axisKey in axes) { + var axis = axes[axisKey] + var isForward = axis.newScroll > axis.oldScroll + var direction = isForward ? axis.forward : axis.backward + + for (var waypointKey in this.waypoints[axisKey]) { + var waypoint = this.waypoints[axisKey][waypointKey] + if (waypoint.triggerPoint === null) { + continue + } + var wasBeforeTriggerPoint = axis.oldScroll < waypoint.triggerPoint + var nowAfterTriggerPoint = axis.newScroll >= waypoint.triggerPoint + var crossedForward = wasBeforeTriggerPoint && nowAfterTriggerPoint + var crossedBackward = !wasBeforeTriggerPoint && !nowAfterTriggerPoint + if (crossedForward || crossedBackward) { + waypoint.queueTrigger(direction) + triggeredGroups[waypoint.group.id] = waypoint.group + } + } + } + + for (var groupKey in triggeredGroups) { + triggeredGroups[groupKey].flushTriggers() + } + + this.oldScroll = { + x: axes.horizontal.newScroll, + y: axes.vertical.newScroll + } + } + + /* Private */ + Context.prototype.innerHeight = function() { + /*eslint-disable eqeqeq */ + if (this.element == this.element.window) { + return Waypoint.viewportHeight() + } + /*eslint-enable eqeqeq */ + return this.adapter.innerHeight() + } + + /* Private */ + Context.prototype.remove = function(waypoint) { + delete this.waypoints[waypoint.axis][waypoint.key] + this.checkEmpty() + } + + /* Private */ + Context.prototype.innerWidth = function() { + /*eslint-disable eqeqeq */ + if (this.element == this.element.window) { + return Waypoint.viewportWidth() + } + /*eslint-enable eqeqeq */ + return this.adapter.innerWidth() + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/context-destroy */ + Context.prototype.destroy = function() { + var allWaypoints = [] + for (var axis in this.waypoints) { + for (var waypointKey in this.waypoints[axis]) { + allWaypoints.push(this.waypoints[axis][waypointKey]) + } + } + for (var i = 0, end = allWaypoints.length; i < end; i++) { + allWaypoints[i].destroy() + } + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/context-refresh */ + Context.prototype.refresh = function() { + /*eslint-disable eqeqeq */ + var isWindow = this.element == this.element.window + /*eslint-enable eqeqeq */ + var contextOffset = isWindow ? undefined : this.adapter.offset() + var triggeredGroups = {} + var axes + + this.handleScroll() + axes = { + horizontal: { + contextOffset: isWindow ? 0 : contextOffset.left, + contextScroll: isWindow ? 0 : this.oldScroll.x, + contextDimension: this.innerWidth(), + oldScroll: this.oldScroll.x, + forward: 'right', + backward: 'left', + offsetProp: 'left' + }, + vertical: { + contextOffset: isWindow ? 0 : contextOffset.top, + contextScroll: isWindow ? 0 : this.oldScroll.y, + contextDimension: this.innerHeight(), + oldScroll: this.oldScroll.y, + forward: 'down', + backward: 'up', + offsetProp: 'top' + } + } + + for (var axisKey in axes) { + var axis = axes[axisKey] + for (var waypointKey in this.waypoints[axisKey]) { + var waypoint = this.waypoints[axisKey][waypointKey] + var adjustment = waypoint.options.offset + var oldTriggerPoint = waypoint.triggerPoint + var elementOffset = 0 + var freshWaypoint = oldTriggerPoint == null + var contextModifier, wasBeforeScroll, nowAfterScroll + var triggeredBackward, triggeredForward + + if (waypoint.element !== waypoint.element.window) { + elementOffset = waypoint.adapter.offset()[axis.offsetProp] + } + + if (typeof adjustment === 'function') { + adjustment = adjustment.apply(waypoint) + } + else if (typeof adjustment === 'string') { + adjustment = parseFloat(adjustment) + if (waypoint.options.offset.indexOf('%') > - 1) { + adjustment = Math.ceil(axis.contextDimension * adjustment / 100) + } + } + + contextModifier = axis.contextScroll - axis.contextOffset + waypoint.triggerPoint = Math.floor(elementOffset + contextModifier - adjustment) + wasBeforeScroll = oldTriggerPoint < axis.oldScroll + nowAfterScroll = waypoint.triggerPoint >= axis.oldScroll + triggeredBackward = wasBeforeScroll && nowAfterScroll + triggeredForward = !wasBeforeScroll && !nowAfterScroll + + if (!freshWaypoint && triggeredBackward) { + waypoint.queueTrigger(axis.backward) + triggeredGroups[waypoint.group.id] = waypoint.group + } + else if (!freshWaypoint && triggeredForward) { + waypoint.queueTrigger(axis.forward) + triggeredGroups[waypoint.group.id] = waypoint.group + } + else if (freshWaypoint && axis.oldScroll >= waypoint.triggerPoint) { + waypoint.queueTrigger(axis.forward) + triggeredGroups[waypoint.group.id] = waypoint.group + } + } + } + + Waypoint.requestAnimationFrame(function() { + for (var groupKey in triggeredGroups) { + triggeredGroups[groupKey].flushTriggers() + } + }) + + return this + } + + /* Private */ + Context.findOrCreateByElement = function(element) { + return Context.findByElement(element) || new Context(element) + } + + /* Private */ + Context.refreshAll = function() { + for (var contextId in contexts) { + contexts[contextId].refresh() + } + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/context-find-by-element */ + Context.findByElement = function(element) { + return contexts[element.waypointContextKey] + } + + window.onload = function() { + if (oldWindowLoad) { + oldWindowLoad() + } + Context.refreshAll() + } + + + Waypoint.requestAnimationFrame = function(callback) { + var requestFn = window.requestAnimationFrame || + window.mozRequestAnimationFrame || + window.webkitRequestAnimationFrame || + requestAnimationFrameShim + requestFn.call(window, callback) + } + Waypoint.Context = Context +}()) +;(function() { + 'use strict' + + function byTriggerPoint(a, b) { + return a.triggerPoint - b.triggerPoint + } + + function byReverseTriggerPoint(a, b) { + return b.triggerPoint - a.triggerPoint + } + + var groups = { + vertical: {}, + horizontal: {} + } + var Waypoint = window.Waypoint + + /* http://imakewebthings.com/waypoints/api/group */ + function Group(options) { + this.name = options.name + this.axis = options.axis + this.id = this.name + '-' + this.axis + this.waypoints = [] + this.clearTriggerQueues() + groups[this.axis][this.name] = this + } + + /* Private */ + Group.prototype.add = function(waypoint) { + this.waypoints.push(waypoint) + } + + /* Private */ + Group.prototype.clearTriggerQueues = function() { + this.triggerQueues = { + up: [], + down: [], + left: [], + right: [] + } + } + + /* Private */ + Group.prototype.flushTriggers = function() { + for (var direction in this.triggerQueues) { + var waypoints = this.triggerQueues[direction] + var reverse = direction === 'up' || direction === 'left' + waypoints.sort(reverse ? byReverseTriggerPoint : byTriggerPoint) + for (var i = 0, end = waypoints.length; i < end; i += 1) { + var waypoint = waypoints[i] + if (waypoint.options.continuous || i === waypoints.length - 1) { + waypoint.trigger([direction]) + } + } + } + this.clearTriggerQueues() + } + + /* Private */ + Group.prototype.next = function(waypoint) { + this.waypoints.sort(byTriggerPoint) + var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) + var isLast = index === this.waypoints.length - 1 + return isLast ? null : this.waypoints[index + 1] + } + + /* Private */ + Group.prototype.previous = function(waypoint) { + this.waypoints.sort(byTriggerPoint) + var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) + return index ? this.waypoints[index - 1] : null + } + + /* Private */ + Group.prototype.queueTrigger = function(waypoint, direction) { + this.triggerQueues[direction].push(waypoint) + } + + /* Private */ + Group.prototype.remove = function(waypoint) { + var index = Waypoint.Adapter.inArray(waypoint, this.waypoints) + if (index > -1) { + this.waypoints.splice(index, 1) + } + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/first */ + Group.prototype.first = function() { + return this.waypoints[0] + } + + /* Public */ + /* http://imakewebthings.com/waypoints/api/last */ + Group.prototype.last = function() { + return this.waypoints[this.waypoints.length - 1] + } + + /* Private */ + Group.findOrCreate = function(options) { + return groups[options.axis][options.name] || new Group(options) + } + + Waypoint.Group = Group +}()) +;(function() { + 'use strict' + + var Waypoint = window.Waypoint + + function isWindow(element) { + return element === element.window + } + + function getWindow(element) { + if (isWindow(element)) { + return element + } + return element.defaultView + } + + function NoFrameworkAdapter(element) { + this.element = element + this.handlers = {} + } + + NoFrameworkAdapter.prototype.innerHeight = function() { + var isWin = isWindow(this.element) + return isWin ? this.element.innerHeight : this.element.clientHeight + } + + NoFrameworkAdapter.prototype.innerWidth = function() { + var isWin = isWindow(this.element) + return isWin ? this.element.innerWidth : this.element.clientWidth + } + + NoFrameworkAdapter.prototype.off = function(event, handler) { + function removeListeners(element, listeners, handler) { + for (var i = 0, end = listeners.length - 1; i < end; i++) { + var listener = listeners[i] + if (!handler || handler === listener) { + element.removeEventListener(listener) + } + } + } + + var eventParts = event.split('.') + var eventType = eventParts[0] + var namespace = eventParts[1] + var element = this.element + + if (namespace && this.handlers[namespace] && eventType) { + removeListeners(element, this.handlers[namespace][eventType], handler) + this.handlers[namespace][eventType] = [] + } + else if (eventType) { + for (var ns in this.handlers) { + removeListeners(element, this.handlers[ns][eventType] || [], handler) + this.handlers[ns][eventType] = [] + } + } + else if (namespace && this.handlers[namespace]) { + for (var type in this.handlers[namespace]) { + removeListeners(element, this.handlers[namespace][type], handler) + } + this.handlers[namespace] = {} + } + } + + /* Adapted from jQuery 1.x offset() */ + NoFrameworkAdapter.prototype.offset = function() { + if (!this.element.ownerDocument) { + return null + } + + var documentElement = this.element.ownerDocument.documentElement + var win = getWindow(this.element.ownerDocument) + var rect = { + top: 0, + left: 0 + } + + if (this.element.getBoundingClientRect) { + rect = this.element.getBoundingClientRect() + } + + return { + top: rect.top + win.pageYOffset - documentElement.clientTop, + left: rect.left + win.pageXOffset - documentElement.clientLeft + } + } + + NoFrameworkAdapter.prototype.on = function(event, handler) { + var eventParts = event.split('.') + var eventType = eventParts[0] + var namespace = eventParts[1] || '__default' + var nsHandlers = this.handlers[namespace] = this.handlers[namespace] || {} + var nsTypeList = nsHandlers[eventType] = nsHandlers[eventType] || [] + + nsTypeList.push(handler) + this.element.addEventListener(eventType, handler) + } + + NoFrameworkAdapter.prototype.outerHeight = function(includeMargin) { + var height = this.innerHeight() + var computedStyle + + if (includeMargin && !isWindow(this.element)) { + computedStyle = window.getComputedStyle(this.element) + height += parseInt(computedStyle.marginTop, 10) + height += parseInt(computedStyle.marginBottom, 10) + } + + return height + } + + NoFrameworkAdapter.prototype.outerWidth = function(includeMargin) { + var width = this.innerWidth() + var computedStyle + + if (includeMargin && !isWindow(this.element)) { + computedStyle = window.getComputedStyle(this.element) + width += parseInt(computedStyle.marginLeft, 10) + width += parseInt(computedStyle.marginRight, 10) + } + + return width + } + + NoFrameworkAdapter.prototype.scrollLeft = function() { + var win = getWindow(this.element) + return win ? win.pageXOffset : this.element.scrollLeft + } + + NoFrameworkAdapter.prototype.scrollTop = function() { + var win = getWindow(this.element) + return win ? win.pageYOffset : this.element.scrollTop + } + + NoFrameworkAdapter.extend = function() { + var args = Array.prototype.slice.call(arguments) + + function merge(target, obj) { + if (typeof target === 'object' && typeof obj === 'object') { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + target[key] = obj[key] + } + } + } + + return target + } + + for (var i = 1, end = args.length; i < end; i++) { + merge(args[0], args[i]) + } + return args[0] + } + + NoFrameworkAdapter.inArray = function(element, array, i) { + return array == null ? -1 : array.indexOf(element, i) + } + + NoFrameworkAdapter.isEmptyObject = function(obj) { + /* eslint no-unused-vars: 0 */ + for (var name in obj) { + return false + } + return true + } + + Waypoint.adapters.push({ + name: 'noframework', + Adapter: NoFrameworkAdapter + }) + Waypoint.Adapter = NoFrameworkAdapter +}()) +; \ No newline at end of file diff --git a/assets/js/dev/vendors/numerator.js b/assets/js/dev/vendors/numerator.js new file mode 100644 index 0000000..7a9c9dd --- /dev/null +++ b/assets/js/dev/vendors/numerator.js @@ -0,0 +1,137 @@ +/* + * jQuery Numerator Plugin 0.2.1 + * https://github.com/garethdn/jquery-numerator + * + * Copyright 2015, Gareth Nolan + * http://ie.linkedin.com/in/garethnolan/ + + * Based on jQuery Boilerplate by Zeno Rocha with the help of Addy Osmani + * http://jqueryboilerplate.com + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +;(function (factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // AMD is used - Register as an anonymous module. + define(['jquery'], factory); + } else if (typeof exports === 'object') { + factory(require('jquery')); + } else { + // Neither AMD nor CommonJS used. Use global variables. + if (typeof jQuery === 'undefined') { + throw 'jquery-numerator requires jQuery to be loaded first'; + } + factory(jQuery); + } +}(function ($) { + + var pluginName = "numerator", + defaults = { + easing: 'swing', + duration: 500, + delimiter: undefined, + rounding: 0, + toValue: undefined, + fromValue: undefined, + queue: false, + onStart: function(){}, + onStep: function(){}, + onProgress: function(){}, + onComplete: function(){} + }; + + function Plugin ( element, options ) { + this.element = element; + this.settings = $.extend( {}, defaults, options ); + this._defaults = defaults; + this._name = pluginName; + this.init(); + } + + Plugin.prototype = { + + init: function () { + this.parseElement(); + this.setValue(); + }, + + parseElement: function () { + var elText = $.trim($(this.element).text()); + + this.settings.fromValue = this.settings.fromValue || this.format(elText); + }, + + setValue: function() { + var self = this; + + $({value: self.settings.fromValue}).animate({value: self.settings.toValue}, { + + duration: parseInt(self.settings.duration, 10), + + easing: self.settings.easing, + + start: self.settings.onStart, + + step: function(now, fx) { + $(self.element).text(self.format(now)); + // accepts two params - (now, fx) + self.settings.onStep(now, fx); + }, + + // accepts three params - (animation object, progress ratio, time remaining(ms)) + progress: self.settings.onProgress, + + complete: self.settings.onComplete + }); + }, + + format: function(value){ + var self = this; + + if ( parseInt(this.settings.rounding ) < 1) { + value = parseInt(value, 10); + } else { + value = parseFloat(value).toFixed( parseInt(this.settings.rounding) ); + } + + if (self.settings.delimiter) { + return this.delimit(value) + } else { + return value; + } + }, + + // TODO: Add comments to this function + delimit: function(value){ + var self = this; + + value = value.toString(); + + if (self.settings.rounding && parseInt(self.settings.rounding, 10) > 0) { + var decimals = value.substring( (value.length - (self.settings.rounding + 1)), value.length ), + wholeValue = value.substring( 0, (value.length - (self.settings.rounding + 1))); + + return self.addDelimiter(wholeValue) + decimals; + } else { + return self.addDelimiter(value); + } + }, + + addDelimiter: function(value){ + return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, this.settings.delimiter); + } + }; + + $.fn[ pluginName ] = function ( options ) { + return this.each(function() { + if ( $.data( this, "plugin_" + pluginName ) ) { + $.data(this, 'plugin_' + pluginName, null); + } + $.data( this, "plugin_" + pluginName, new Plugin( this, options ) ); + }); + }; + +})); diff --git a/assets/js/dev/vendors/packery-mode.pkgd.js b/assets/js/dev/vendors/packery-mode.pkgd.js new file mode 100644 index 0000000..dcc88f8 --- /dev/null +++ b/assets/js/dev/vendors/packery-mode.pkgd.js @@ -0,0 +1,1200 @@ +/*! + * Packery layout mode PACKAGED v1.1.3 + * sub-classes Packery + * http://packery.metafizzy.co + */ + +/*! + * classie v1.0.1 + * class helper functions + * from bonzo https://github.com/ded/bonzo + * MIT license + * + * classie.has( elem, 'my-class' ) -> true/false + * classie.add( elem, 'my-new-class' ) + * classie.remove( elem, 'my-unwanted-class' ) + * classie.toggle( elem, 'my-class' ) + */ + +/*jshint browser: true, strict: true, undef: true, unused: true */ +/*global define: false, module: false */ + +( function( window ) { + + + +// class helper functions from bonzo https://github.com/ded/bonzo + +function classReg( className ) { + return new RegExp("(^|\\s+)" + className + "(\\s+|$)"); +} + +// classList support for class management +// altho to be fair, the api sucks because it won't accept multiple classes at once +var hasClass, addClass, removeClass; + +if ( 'classList' in document.documentElement ) { + hasClass = function( elem, c ) { + return elem.classList.contains( c ); + }; + addClass = function( elem, c ) { + elem.classList.add( c ); + }; + removeClass = function( elem, c ) { + elem.classList.remove( c ); + }; +} +else { + hasClass = function( elem, c ) { + return classReg( c ).test( elem.className ); + }; + addClass = function( elem, c ) { + if ( !hasClass( elem, c ) ) { + elem.className = elem.className + ' ' + c; + } + }; + removeClass = function( elem, c ) { + elem.className = elem.className.replace( classReg( c ), ' ' ); + }; +} + +function toggleClass( elem, c ) { + var fn = hasClass( elem, c ) ? removeClass : addClass; + fn( elem, c ); +} + +var classie = { + // full names + hasClass: hasClass, + addClass: addClass, + removeClass: removeClass, + toggleClass: toggleClass, + // short names + has: hasClass, + add: addClass, + remove: removeClass, + toggle: toggleClass +}; + +// transport +if ( typeof define === 'function' && define.amd ) { + // AMD + define( 'classie/classie',classie ); +} else if ( typeof exports === 'object' ) { + // CommonJS + module.exports = classie; +} else { + // browser global + window.classie = classie; +} + +})( window ); + +/** + * Rect + * low-level utility class for basic geometry + */ + +( function( window, factory ) { + + // universal module definition + if ( typeof define == 'function' && define.amd ) { + // AMD + define( 'packery/js/rect',factory ); + } else if ( typeof exports == 'object' ) { + // CommonJS + module.exports = factory(); + } else { + // browser global + window.Packery = window.Packery || {}; + window.Packery.Rect = factory(); + } + +}( window, function factory() { + + +// -------------------------- Packery -------------------------- // + +// global namespace +var Packery = window.Packery = function() {}; + +// -------------------------- Rect -------------------------- // + +function Rect( props ) { + // extend properties from defaults + for ( var prop in Rect.defaults ) { + this[ prop ] = Rect.defaults[ prop ]; + } + + for ( prop in props ) { + this[ prop ] = props[ prop ]; + } + +} + +// make available +Packery.Rect = Rect; + +Rect.defaults = { + x: 0, + y: 0, + width: 0, + height: 0 +}; + +/** + * Determines whether or not this rectangle wholly encloses another rectangle or point. + * @param {Rect} rect + * @returns {Boolean} +**/ +Rect.prototype.contains = function( rect ) { + // points don't have width or height + var otherWidth = rect.width || 0; + var otherHeight = rect.height || 0; + return this.x <= rect.x && + this.y <= rect.y && + this.x + this.width >= rect.x + otherWidth && + this.y + this.height >= rect.y + otherHeight; +}; + +/** + * Determines whether or not the rectangle intersects with another. + * @param {Rect} rect + * @returns {Boolean} +**/ +Rect.prototype.overlaps = function( rect ) { + var thisRight = this.x + this.width; + var thisBottom = this.y + this.height; + var rectRight = rect.x + rect.width; + var rectBottom = rect.y + rect.height; + + // http://stackoverflow.com/a/306332 + return this.x < rectRight && + thisRight > rect.x && + this.y < rectBottom && + thisBottom > rect.y; +}; + +/** + * @param {Rect} rect - the overlapping rect + * @returns {Array} freeRects - rects representing the area around the rect +**/ +Rect.prototype.getMaximalFreeRects = function( rect ) { + + // if no intersection, return false + if ( !this.overlaps( rect ) ) { + return false; + } + + var freeRects = []; + var freeRect; + + var thisRight = this.x + this.width; + var thisBottom = this.y + this.height; + var rectRight = rect.x + rect.width; + var rectBottom = rect.y + rect.height; + + // top + if ( this.y < rect.y ) { + freeRect = new Rect({ + x: this.x, + y: this.y, + width: this.width, + height: rect.y - this.y + }); + freeRects.push( freeRect ); + } + + // right + if ( thisRight > rectRight ) { + freeRect = new Rect({ + x: rectRight, + y: this.y, + width: thisRight - rectRight, + height: this.height + }); + freeRects.push( freeRect ); + } + + // bottom + if ( thisBottom > rectBottom ) { + freeRect = new Rect({ + x: this.x, + y: rectBottom, + width: this.width, + height: thisBottom - rectBottom + }); + freeRects.push( freeRect ); + } + + // left + if ( this.x < rect.x ) { + freeRect = new Rect({ + x: this.x, + y: this.y, + width: rect.x - this.x, + height: this.height + }); + freeRects.push( freeRect ); + } + + return freeRects; +}; + +Rect.prototype.canFit = function( rect ) { + return this.width >= rect.width && this.height >= rect.height; +}; + +return Rect; + +})); + +/** + * Packer + * bin-packing algorithm + */ + +( function( window, factory ) { + + // universal module definition + if ( typeof define == 'function' && define.amd ) { + // AMD + define( 'packery/js/packer',[ './rect' ], factory ); + } else if ( typeof exports == 'object' ) { + // CommonJS + module.exports = factory( + require('./rect') + ); + } else { + // browser global + var Packery = window.Packery = window.Packery || {}; + Packery.Packer = factory( Packery.Rect ); + } + +}( window, function factory( Rect ) { + + +// -------------------------- Packer -------------------------- // + +/** + * @param {Number} width + * @param {Number} height + * @param {String} sortDirection + * topLeft for vertical, leftTop for horizontal + */ +function Packer( width, height, sortDirection ) { + this.width = width || 0; + this.height = height || 0; + this.sortDirection = sortDirection || 'downwardLeftToRight'; + + this.reset(); +} + +Packer.prototype.reset = function() { + this.spaces = []; + this.newSpaces = []; + + var initialSpace = new Rect({ + x: 0, + y: 0, + width: this.width, + height: this.height + }); + + this.spaces.push( initialSpace ); + // set sorter + this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight; +}; + +// change x and y of rect to fit with in Packer's available spaces +Packer.prototype.pack = function( rect ) { + for ( var i=0, len = this.spaces.length; i < len; i++ ) { + var space = this.spaces[i]; + if ( space.canFit( rect ) ) { + this.placeInSpace( rect, space ); + break; + } + } +}; + +Packer.prototype.placeInSpace = function( rect, space ) { + // place rect in space + rect.x = space.x; + rect.y = space.y; + + this.placed( rect ); +}; + +// update spaces with placed rect +Packer.prototype.placed = function( rect ) { + // update spaces + var revisedSpaces = []; + for ( var i=0, len = this.spaces.length; i < len; i++ ) { + var space = this.spaces[i]; + var newSpaces = space.getMaximalFreeRects( rect ); + // add either the original space or the new spaces to the revised spaces + if ( newSpaces ) { + revisedSpaces.push.apply( revisedSpaces, newSpaces ); + } else { + revisedSpaces.push( space ); + } + } + + this.spaces = revisedSpaces; + + this.mergeSortSpaces(); +}; + +Packer.prototype.mergeSortSpaces = function() { + // remove redundant spaces + Packer.mergeRects( this.spaces ); + this.spaces.sort( this.sorter ); +}; + +// add a space back +Packer.prototype.addSpace = function( rect ) { + this.spaces.push( rect ); + this.mergeSortSpaces(); +}; + +// -------------------------- utility functions -------------------------- // + +/** + * Remove redundant rectangle from array of rectangles + * @param {Array} rects: an array of Rects + * @returns {Array} rects: an array of Rects +**/ +Packer.mergeRects = function( rects ) { + for ( var i=0, len = rects.length; i < len; i++ ) { + var rect = rects[i]; + // skip over this rect if it was already removed + if ( !rect ) { + continue; + } + // clone rects we're testing, remove this rect + var compareRects = rects.slice(0); + // do not compare with self + compareRects.splice( i, 1 ); + // compare this rect with others + var removedCount = 0; + for ( var j=0, jLen = compareRects.length; j < jLen; j++ ) { + var compareRect = compareRects[j]; + // if this rect contains another, + // remove that rect from test collection + var indexAdjust = i > j ? 0 : 1; + if ( rect.contains( compareRect ) ) { + // console.log( 'current test rects:' + testRects.length, testRects ); + // console.log( i, j, indexAdjust, rect, compareRect ); + rects.splice( j + indexAdjust - removedCount, 1 ); + removedCount++; + } + } + } + + return rects; +}; + + +// -------------------------- sorters -------------------------- // + +// functions for sorting rects in order +var sorters = { + // top down, then left to right + downwardLeftToRight: function( a, b ) { + return a.y - b.y || a.x - b.x; + }, + // left to right, then top down + rightwardTopToBottom: function( a, b ) { + return a.x - b.x || a.y - b.y; + } +}; + + +// -------------------------- -------------------------- // + +return Packer; + +})); +/** + * Packery Item Element +**/ + +( function( window, factory ) { + + // universal module definition + + if ( typeof define == 'function' && define.amd ) { + // AMD + define( 'packery/js/item',[ + 'get-style-property/get-style-property', + 'outlayer/outlayer', + './rect' + ], + factory ); + } else if ( typeof exports == 'object' ) { + // CommonJS + module.exports = factory( + require('desandro-get-style-property'), + require('outlayer'), + require('./rect') + ); + } else { + // browser global + window.Packery.Item = factory( + window.getStyleProperty, + window.Outlayer, + window.Packery.Rect + ); + } + +}( window, function factory( getStyleProperty, Outlayer, Rect ) { + + +// -------------------------- Item -------------------------- // + +var transformProperty = getStyleProperty('transform'); + +// sub-class Item +var Item = function PackeryItem() { + Outlayer.Item.apply( this, arguments ); +}; + +Item.prototype = new Outlayer.Item(); + +var protoCreate = Item.prototype._create; +Item.prototype._create = function() { + // call default _create logic + protoCreate.call( this ); + this.rect = new Rect(); + // rect used for placing, in drag or Packery.fit() + this.placeRect = new Rect(); +}; + +// -------------------------- drag -------------------------- // + +Item.prototype.dragStart = function() { + this.getPosition(); + this.removeTransitionStyles(); + // remove transform property from transition + if ( this.isTransitioning && transformProperty ) { + this.element.style[ transformProperty ] = 'none'; + } + this.getSize(); + // create place rect, used for position when dragged then dropped + // or when positioning + this.isPlacing = true; + this.needsPositioning = false; + this.positionPlaceRect( this.position.x, this.position.y ); + this.isTransitioning = false; + this.didDrag = false; +}; + +/** + * handle item when it is dragged + * @param {Number} x - horizontal position of dragged item + * @param {Number} y - vertical position of dragged item + */ +Item.prototype.dragMove = function( x, y ) { + this.didDrag = true; + var packerySize = this.layout.size; + x -= packerySize.paddingLeft; + y -= packerySize.paddingTop; + this.positionPlaceRect( x, y ); +}; + +Item.prototype.dragStop = function() { + this.getPosition(); + var isDiffX = this.position.x != this.placeRect.x; + var isDiffY = this.position.y != this.placeRect.y; + // set post-drag positioning flag + this.needsPositioning = isDiffX || isDiffY; + // reset flag + this.didDrag = false; +}; + +// -------------------------- placing -------------------------- // + +/** + * position a rect that will occupy space in the packer + * @param {Number} x + * @param {Number} y + * @param {Boolean} isMaxYContained + */ +Item.prototype.positionPlaceRect = function( x, y, isMaxYOpen ) { + this.placeRect.x = this.getPlaceRectCoord( x, true ); + this.placeRect.y = this.getPlaceRectCoord( y, false, isMaxYOpen ); +}; + +/** + * get x/y coordinate for place rect + * @param {Number} coord - x or y + * @param {Boolean} isX + * @param {Boolean} isMaxOpen - does not limit value to outer bound + * @returns {Number} coord - processed x or y + */ +Item.prototype.getPlaceRectCoord = function( coord, isX, isMaxOpen ) { + var measure = isX ? 'Width' : 'Height'; + var size = this.size[ 'outer' + measure ]; + var segment = this.layout[ isX ? 'columnWidth' : 'rowHeight' ]; + var parentSize = this.layout.size[ 'inner' + measure ]; + + // additional parentSize calculations for Y + if ( !isX ) { + parentSize = Math.max( parentSize, this.layout.maxY ); + // prevent gutter from bumping up height when non-vertical grid + if ( !this.layout.rowHeight ) { + parentSize -= this.layout.gutter; + } + } + + var max; + + if ( segment ) { + segment += this.layout.gutter; + // allow for last column to reach the edge + parentSize += isX ? this.layout.gutter : 0; + // snap to closest segment + coord = Math.round( coord / segment ); + // contain to outer bound + // contain non-growing bound, allow growing bound to grow + var mathMethod; + if ( this.layout.options.isHorizontal ) { + mathMethod = !isX ? 'floor' : 'ceil'; + } else { + mathMethod = isX ? 'floor' : 'ceil'; + } + var maxSegments = Math[ mathMethod ]( parentSize / segment ); + maxSegments -= Math.ceil( size / segment ); + max = maxSegments; + } else { + max = parentSize - size; + } + + coord = isMaxOpen ? coord : Math.min( coord, max ); + coord *= segment || 1; + + return Math.max( 0, coord ); +}; + +Item.prototype.copyPlaceRectPosition = function() { + this.rect.x = this.placeRect.x; + this.rect.y = this.placeRect.y; +}; + +// ----- ----- // + +// remove element from DOM +Item.prototype.removeElem = function() { + this.element.parentNode.removeChild( this.element ); + // add space back to packer + this.layout.packer.addSpace( this.rect ); + this.emitEvent( 'remove', [ this ] ); +}; + +// ----- ----- // + +return Item; + +})); + +/*! + * Packery v1.4.1 + * bin-packing layout library + * + * Licensed GPLv3 for open source use + * or Flickity Commercial License for commercial use + * + * http://packery.metafizzy.co + * Copyright 2015 Metafizzy + */ + +( function( window, factory ) { + + // universal module definition + if ( typeof define == 'function' && define.amd ) { + // AMD + define( 'packery/js/packery',[ + 'classie/classie', + 'get-size/get-size', + 'outlayer/outlayer', + './rect', + './packer', + './item' + ], + factory ); + } else if ( typeof exports == 'object' ) { + // CommonJS + module.exports = factory( + require('desandro-classie'), + require('get-size'), + require('outlayer'), + require('./rect'), + require('./packer'), + require('./item') + ); + } else { + // browser global + window.Packery = factory( + window.classie, + window.getSize, + window.Outlayer, + window.Packery.Rect, + window.Packery.Packer, + window.Packery.Item + ); + } + +}( window, function factory( classie, getSize, Outlayer, Rect, Packer, Item ) { + + +// ----- Rect ----- // + +// allow for pixel rounding errors IE8-IE11 & Firefox; #227 +Rect.prototype.canFit = function( rect ) { + return this.width >= rect.width - 1 && this.height >= rect.height - 1; +}; + +// -------------------------- Packery -------------------------- // + +// create an Outlayer layout class +var Packery = Outlayer.create('packery'); +Packery.Item = Item; + +Packery.prototype._create = function() { + // call super + Outlayer.prototype._create.call( this ); + + // initial properties + this.packer = new Packer(); + + // Left over from v1.0 + this.stamp( this.options.stamped ); + + // create drag handlers + var _this = this; + this.handleDraggabilly = { + dragStart: function() { + _this.itemDragStart( this.element ); + }, + dragMove: function() { + _this.itemDragMove( this.element, this.position.x, this.position.y ); + }, + dragEnd: function() { + _this.itemDragEnd( this.element ); + } + }; + + this.handleUIDraggable = { + start: function handleUIDraggableStart( event ) { + _this.itemDragStart( event.currentTarget ); + }, + drag: function handleUIDraggableDrag( event, ui ) { + _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top ); + }, + stop: function handleUIDraggableStop( event ) { + _this.itemDragEnd( event.currentTarget ); + } + }; + +}; + + +// ----- init & layout ----- // + +/** + * logic before any new layout + */ +Packery.prototype._resetLayout = function() { + this.getSize(); + + this._getMeasurements(); + + // reset packer + var packer = this.packer; + // packer settings, if horizontal or vertical + if ( this.options.isHorizontal ) { + packer.width = Number.POSITIVE_INFINITY; + packer.height = this.size.innerHeight + this.gutter; + packer.sortDirection = 'rightwardTopToBottom'; + } else { + packer.width = this.size.innerWidth + this.gutter; + packer.height = Number.POSITIVE_INFINITY; + packer.sortDirection = 'downwardLeftToRight'; + } + + packer.reset(); + + // layout + this.maxY = 0; + this.maxX = 0; +}; + +/** + * update columnWidth, rowHeight, & gutter + * @private + */ +Packery.prototype._getMeasurements = function() { + this._getMeasurement( 'columnWidth', 'width' ); + this._getMeasurement( 'rowHeight', 'height' ); + this._getMeasurement( 'gutter', 'width' ); +}; + +Packery.prototype._getItemLayoutPosition = function( item ) { + this._packItem( item ); + return item.rect; +}; + + +/** + * layout item in packer + * @param {Packery.Item} item + */ +Packery.prototype._packItem = function( item ) { + this._setRectSize( item.element, item.rect ); + // pack the rect in the packer + this.packer.pack( item.rect ); + this._setMaxXY( item.rect ); +}; + +/** + * set max X and Y value, for size of container + * @param {Packery.Rect} rect + * @private + */ +Packery.prototype._setMaxXY = function( rect ) { + this.maxX = Math.max( rect.x + rect.width, this.maxX ); + this.maxY = Math.max( rect.y + rect.height, this.maxY ); +}; + +/** + * set the width and height of a rect, applying columnWidth and rowHeight + * @param {Element} elem + * @param {Packery.Rect} rect + */ +Packery.prototype._setRectSize = function( elem, rect ) { + var size = getSize( elem ); + var w = size.outerWidth; + var h = size.outerHeight; + // size for columnWidth and rowHeight, if available + // only check if size is non-zero, #177 + if ( w || h ) { + w = this._applyGridGutter( w, this.columnWidth ); + h = this._applyGridGutter( h, this.rowHeight ); + } + // rect must fit in packer + rect.width = Math.min( w, this.packer.width ); + rect.height = Math.min( h, this.packer.height ); +}; + +/** + * fits item to columnWidth/rowHeight and adds gutter + * @param {Number} measurement - item width or height + * @param {Number} gridSize - columnWidth or rowHeight + * @returns measurement + */ +Packery.prototype._applyGridGutter = function( measurement, gridSize ) { + // just add gutter if no gridSize + if ( !gridSize ) { + return measurement + this.gutter; + } + gridSize += this.gutter; + // fit item to columnWidth/rowHeight + var remainder = measurement % gridSize; + var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; + measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize; + return measurement; +}; + +Packery.prototype._getContainerSize = function() { + if ( this.options.isHorizontal ) { + return { + width: this.maxX - this.gutter + }; + } else { + return { + height: this.maxY - this.gutter + }; + } +}; + + +// -------------------------- stamp -------------------------- // + +/** + * makes space for element + * @param {Element} elem + */ +Packery.prototype._manageStamp = function( elem ) { + + var item = this.getItem( elem ); + var rect; + if ( item && item.isPlacing ) { + rect = item.placeRect; + } else { + var offset = this._getElementOffset( elem ); + rect = new Rect({ + x: this.options.isOriginLeft ? offset.left : offset.right, + y: this.options.isOriginTop ? offset.top : offset.bottom + }); + } + + this._setRectSize( elem, rect ); + // save its space in the packer + this.packer.placed( rect ); + this._setMaxXY( rect ); +}; + +// -------------------------- methods -------------------------- // + +function verticalSorter( a, b ) { + return a.position.y - b.position.y || a.position.x - b.position.x; +} + +function horizontalSorter( a, b ) { + return a.position.x - b.position.x || a.position.y - b.position.y; +} + +Packery.prototype.sortItemsByPosition = function() { + var sorter = this.options.isHorizontal ? horizontalSorter : verticalSorter; + this.items.sort( sorter ); +}; + +/** + * Fit item element in its current position + * Packery will position elements around it + * useful for expanding elements + * + * @param {Element} elem + * @param {Number} x - horizontal destination position, optional + * @param {Number} y - vertical destination position, optional + */ +Packery.prototype.fit = function( elem, x, y ) { + var item = this.getItem( elem ); + if ( !item ) { + return; + } + + // prepare internal properties + this._getMeasurements(); + + // stamp item to get it out of layout + this.stamp( item.element ); + // required for positionPlaceRect + item.getSize(); + // set placing flag + item.isPlacing = true; + // fall back to current position for fitting + x = x === undefined ? item.rect.x: x; + y = y === undefined ? item.rect.y: y; + + // position it best at its destination + item.positionPlaceRect( x, y, true ); + + this._bindFitEvents( item ); + item.moveTo( item.placeRect.x, item.placeRect.y ); + // layout everything else + this.layout(); + + // return back to regularly scheduled programming + this.unstamp( item.element ); + this.sortItemsByPosition(); + // un set placing flag, back to normal + item.isPlacing = false; + // copy place rect position + item.copyPlaceRectPosition(); +}; + +/** + * emit event when item is fit and other items are laid out + * @param {Packery.Item} item + * @private + */ +Packery.prototype._bindFitEvents = function( item ) { + var _this = this; + var ticks = 0; + function tick() { + ticks++; + if ( ticks != 2 ) { + return; + } + _this.emitEvent( 'fitComplete', [ item ] ); + } + // when item is laid out + item.on( 'layout', function() { + tick(); + return true; + }); + // when all items are laid out + this.on( 'layoutComplete', function() { + tick(); + return true; + }); +}; + +// -------------------------- resize -------------------------- // + +// debounced, layout on resize +Packery.prototype.resize = function() { + // don't trigger if size did not change + var size = getSize( this.element ); + // check that this.size and size are there + // IE8 triggers resize on body size change, so they might not be + var hasSizes = this.size && size; + var innerSize = this.options.isHorizontal ? 'innerHeight' : 'innerWidth'; + if ( hasSizes && size[ innerSize ] == this.size[ innerSize ] ) { + return; + } + + this.layout(); +}; + +// -------------------------- drag -------------------------- // + +/** + * handle an item drag start event + * @param {Element} elem + */ +Packery.prototype.itemDragStart = function( elem ) { + this.stamp( elem ); + var item = this.getItem( elem ); + if ( item ) { + item.dragStart(); + } +}; + +/** + * handle an item drag move event + * @param {Element} elem + * @param {Number} x - horizontal change in position + * @param {Number} y - vertical change in position + */ +Packery.prototype.itemDragMove = function( elem, x, y ) { + var item = this.getItem( elem ); + if ( item ) { + item.dragMove( x, y ); + } + + // debounce + var _this = this; + // debounce triggering layout + function delayed() { + _this.layout(); + delete _this.dragTimeout; + } + + this.clearDragTimeout(); + + this.dragTimeout = setTimeout( delayed, 40 ); +}; + +Packery.prototype.clearDragTimeout = function() { + if ( this.dragTimeout ) { + clearTimeout( this.dragTimeout ); + } +}; + +/** + * handle an item drag end event + * @param {Element} elem + */ +Packery.prototype.itemDragEnd = function( elem ) { + var item = this.getItem( elem ); + var itemDidDrag; + if ( item ) { + itemDidDrag = item.didDrag; + item.dragStop(); + } + // if elem didn't move, or if it doesn't need positioning + // unignore and unstamp and call it a day + if ( !item || ( !itemDidDrag && !item.needsPositioning ) ) { + this.unstamp( elem ); + return; + } + // procced with dragged item + + classie.add( item.element, 'is-positioning-post-drag' ); + + // save this var, as it could get reset in dragStart + var onLayoutComplete = this._getDragEndLayoutComplete( elem, item ); + + if ( item.needsPositioning ) { + item.on( 'layout', onLayoutComplete ); + item.moveTo( item.placeRect.x, item.placeRect.y ); + } else if ( item ) { + // item didn't need placement + item.copyPlaceRectPosition(); + } + + this.clearDragTimeout(); + this.on( 'layoutComplete', onLayoutComplete ); + this.layout(); + +}; + +/** + * get drag end callback + * @param {Element} elem + * @param {Packery.Item} item + * @returns {Function} onLayoutComplete + */ +Packery.prototype._getDragEndLayoutComplete = function( elem, item ) { + var itemNeedsPositioning = item && item.needsPositioning; + var completeCount = 0; + var asyncCount = itemNeedsPositioning ? 2 : 1; + var _this = this; + + return function onLayoutComplete() { + completeCount++; + // don't proceed if not complete + if ( completeCount != asyncCount ) { + return true; + } + // reset item + if ( item ) { + classie.remove( item.element, 'is-positioning-post-drag' ); + item.isPlacing = false; + item.copyPlaceRectPosition(); + } + + _this.unstamp( elem ); + // only sort when item moved + _this.sortItemsByPosition(); + + // emit item drag event now that everything is done + if ( itemNeedsPositioning ) { + _this.emitEvent( 'dragItemPositioned', [ item ] ); + } + // listen once + return true; + }; +}; + +/** + * binds Draggabilly events + * @param {Draggabilly} draggie + */ +Packery.prototype.bindDraggabillyEvents = function( draggie ) { + draggie.on( 'dragStart', this.handleDraggabilly.dragStart ); + draggie.on( 'dragMove', this.handleDraggabilly.dragMove ); + draggie.on( 'dragEnd', this.handleDraggabilly.dragEnd ); +}; + +/** + * binds jQuery UI Draggable events + * @param {jQuery} $elems + */ +Packery.prototype.bindUIDraggableEvents = function( $elems ) { + $elems + .on( 'dragstart', this.handleUIDraggable.start ) + .on( 'drag', this.handleUIDraggable.drag ) + .on( 'dragstop', this.handleUIDraggable.stop ); +}; + +Packery.Rect = Rect; +Packery.Packer = Packer; + +return Packery; + +})); + +/*! + * Packery layout mode v1.1.3 + * sub-classes Packery + * http://packery.metafizzy.co + */ + +/*jshint browser: true, strict: true, undef: true, unused: true */ + +( function( window, factory ) { + + // universal module definition + if ( typeof define == 'function' && define.amd ) { + // AMD + define( [ + 'isotope/js/layout-mode', + 'packery/js/packery', + 'get-size/get-size' + ], + factory ); + } else if ( typeof exports == 'object' ) { + // CommonJS + module.exports = factory( + require('isotope-layout/js/layout-mode'), + require('packery'), + require('get-size') + ); + } else { + // browser global + factory( + window.Isotope.LayoutMode, + window.Packery, + window.getSize + ); + } + +}( window, function factor( LayoutMode, Packery, getSize ) { + + +// -------------------------- helpers -------------------------- // + +// extend objects +function extend( a, b ) { + for ( var prop in b ) { + a[ prop ] = b[ prop ]; + } + return a; +} + +// -------------------------- masonryDefinition -------------------------- // + + // create an Outlayer layout class + var PackeryMode = LayoutMode.create('packery'); + + // save on to these methods + var _getElementOffset = PackeryMode.prototype._getElementOffset; + // var layout = PackeryMode.prototype.layout; + var _getMeasurement = PackeryMode.prototype._getMeasurement; + + // sub-class Masonry + extend( PackeryMode.prototype, Packery.prototype ); + + // set back, as it was overwritten by Packery + PackeryMode.prototype._getElementOffset = _getElementOffset; + // PackeryMode.prototype.layout = layout; + PackeryMode.prototype._getMeasurement = _getMeasurement; + + // set packery in _resetLayout + var _resetLayout = PackeryMode.prototype._resetLayout; + PackeryMode.prototype._resetLayout = function() { + this.packer = this.packer || new Packery.Packer(); + _resetLayout.apply( this, arguments ); + }; + + var _getItemLayoutPosition = PackeryMode.prototype._getItemLayoutPosition; + PackeryMode.prototype._getItemLayoutPosition = function( item ) { + // set packery rect + item.rect = item.rect || new Packery.Rect(); + return _getItemLayoutPosition.call( this, item ); + }; + + // HACK copy over isOriginLeft/Top options + var _manageStamp = PackeryMode.prototype._manageStamp; + PackeryMode.prototype._manageStamp = function() { + this.options.isOriginLeft = this.isotope.options.isOriginLeft; + this.options.isOriginTop = this.isotope.options.isOriginTop; + _manageStamp.apply( this, arguments ); + }; + + PackeryMode.prototype.needsResizeLayout = function() { + // don't trigger if size did not change + var size = getSize( this.element ); + // check that this.size and size are there + // IE8 triggers resize on body size change, so they might not be + var hasSizes = this.size && size; + var innerSize = this.options.isHorizontal ? 'innerHeight' : 'innerWidth'; + return hasSizes && size[ innerSize ] != this.size[ innerSize ]; + }; + + return PackeryMode; +})); + diff --git a/assets/js/dev/vendors/particles.js b/assets/js/dev/vendors/particles.js new file mode 100644 index 0000000..325d834 --- /dev/null +++ b/assets/js/dev/vendors/particles.js @@ -0,0 +1,1541 @@ +/* ----------------------------------------------- +/* Author : Vincent Garreau - vincentgarreau.com +/* MIT license: http://opensource.org/licenses/MIT +/* Demo / Generator : vincentgarreau.com/particles.js +/* GitHub : github.com/VincentGarreau/particles.js +/* How to use? : Check the GitHub README +/* v2.0.0 +/* ----------------------------------------------- */ + +var pJS = function(tag_id, params){ + + var canvas_el = document.querySelector('#'+tag_id+' > .particles-js-canvas-el'); + + /* particles.js variables with default values */ + this.pJS = { + canvas: { + el: canvas_el, + w: canvas_el.offsetWidth, + h: canvas_el.offsetHeight + }, + particles: { + number: { + value: 400, + density: { + enable: true, + value_area: 800 + } + }, + color: { + value: '#fff' + }, + shape: { + type: 'circle', + stroke: { + width: 0, + color: '#ff0000' + }, + polygon: { + nb_sides: 5 + }, + image: { + src: '', + width: 100, + height: 100 + } + }, + opacity: { + value: 1, + random: false, + anim: { + enable: false, + speed: 2, + opacity_min: 0, + sync: false + } + }, + size: { + value: 20, + random: false, + anim: { + enable: false, + speed: 20, + size_min: 0, + sync: false + } + }, + line_linked: { + enable: true, + distance: 100, + color: '#fff', + opacity: 1, + width: 1 + }, + move: { + enable: true, + speed: 2, + direction: 'none', + random: false, + straight: false, + out_mode: 'out', + bounce: false, + attract: { + enable: false, + rotateX: 3000, + rotateY: 3000 + } + }, + array: [] + }, + interactivity: { + detect_on: 'canvas', + events: { + onhover: { + enable: true, + mode: 'grab' + }, + onclick: { + enable: true, + mode: 'push' + }, + resize: true + }, + modes: { + grab:{ + distance: 100, + line_linked:{ + opacity: 1 + } + }, + bubble:{ + distance: 200, + size: 80, + duration: 0.4 + }, + repulse:{ + distance: 200, + duration: 0.4 + }, + push:{ + particles_nb: 4 + }, + remove:{ + particles_nb: 2 + } + }, + mouse:{} + }, + retina_detect: false, + fn: { + interact: {}, + modes: {}, + vendors:{} + }, + tmp: {} + }; + + var pJS = this.pJS; + + /* params settings */ + if(params){ + Object.deepExtend(pJS, params); + } + + pJS.tmp.obj = { + size_value: pJS.particles.size.value, + size_anim_speed: pJS.particles.size.anim.speed, + move_speed: pJS.particles.move.speed, + line_linked_distance: pJS.particles.line_linked.distance, + line_linked_width: pJS.particles.line_linked.width, + mode_grab_distance: pJS.interactivity.modes.grab.distance, + mode_bubble_distance: pJS.interactivity.modes.bubble.distance, + mode_bubble_size: pJS.interactivity.modes.bubble.size, + mode_repulse_distance: pJS.interactivity.modes.repulse.distance + }; + + + pJS.fn.retinaInit = function(){ + + if(pJS.retina_detect && window.devicePixelRatio > 1){ + pJS.canvas.pxratio = window.devicePixelRatio; + pJS.tmp.retina = true; + } + else{ + pJS.canvas.pxratio = 1; + pJS.tmp.retina = false; + } + + pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio; + pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio; + + pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio; + pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio; + pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio; + pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio; + pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio; + pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio; + pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio; + pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio; + pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio; + + }; + + + + /* ---------- pJS functions - canvas ------------ */ + + pJS.fn.canvasInit = function(){ + pJS.canvas.ctx = pJS.canvas.el.getContext('2d'); + }; + + pJS.fn.canvasSize = function(){ + + pJS.canvas.el.width = pJS.canvas.w; + pJS.canvas.el.height = pJS.canvas.h; + + if(pJS && pJS.interactivity.events.resize){ + + window.addEventListener('resize', function(){ + + pJS.canvas.w = pJS.canvas.el.offsetWidth; + pJS.canvas.h = pJS.canvas.el.offsetHeight; + + /* resize canvas */ + if(pJS.tmp.retina){ + pJS.canvas.w *= pJS.canvas.pxratio; + pJS.canvas.h *= pJS.canvas.pxratio; + } + + pJS.canvas.el.width = pJS.canvas.w; + pJS.canvas.el.height = pJS.canvas.h; + + /* repaint canvas on anim disabled */ + if(!pJS.particles.move.enable){ + pJS.fn.particlesEmpty(); + pJS.fn.particlesCreate(); + pJS.fn.particlesDraw(); + pJS.fn.vendors.densityAutoParticles(); + } + + /* density particles enabled */ + pJS.fn.vendors.densityAutoParticles(); + + }); + + } + + }; + + + pJS.fn.canvasPaint = function(){ + pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h); + }; + + pJS.fn.canvasClear = function(){ + pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h); + }; + + + /* --------- pJS functions - particles ----------- */ + + pJS.fn.particle = function(color, opacity, position){ + + /* size */ + this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value; + if(pJS.particles.size.anim.enable){ + this.size_status = false; + this.vs = pJS.particles.size.anim.speed / 100; + if(!pJS.particles.size.anim.sync){ + this.vs = this.vs * Math.random(); + } + } + + /* position */ + this.x = position ? position.x : Math.random() * pJS.canvas.w; + this.y = position ? position.y : Math.random() * pJS.canvas.h; + + /* check position - into the canvas */ + if(this.x > pJS.canvas.w - this.radius*2) this.x = this.x - this.radius; + else if(this.x < this.radius*2) this.x = this.x + this.radius; + if(this.y > pJS.canvas.h - this.radius*2) this.y = this.y - this.radius; + else if(this.y < this.radius*2) this.y = this.y + this.radius; + + /* check position - avoid overlap */ + if(pJS.particles.move.bounce){ + pJS.fn.vendors.checkOverlap(this, position); + } + + /* color */ + this.color = {}; + if(typeof(color.value) == 'object'){ + + if(color.value instanceof Array){ + var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)]; + this.color.rgb = hexToRgb(color_selected); + }else{ + if(color.value.r != undefined && color.value.g != undefined && color.value.b != undefined){ + this.color.rgb = { + r: color.value.r, + g: color.value.g, + b: color.value.b + } + } + if(color.value.h != undefined && color.value.s != undefined && color.value.l != undefined){ + this.color.hsl = { + h: color.value.h, + s: color.value.s, + l: color.value.l + } + } + } + + } + else if(color.value == 'random'){ + this.color.rgb = { + r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0), + g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0), + b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0) + } + } + else if(typeof(color.value) == 'string'){ + this.color = color; + this.color.rgb = hexToRgb(this.color.value); + } + + /* opacity */ + this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value; + if(pJS.particles.opacity.anim.enable){ + this.opacity_status = false; + this.vo = pJS.particles.opacity.anim.speed / 100; + if(!pJS.particles.opacity.anim.sync){ + this.vo = this.vo * Math.random(); + } + } + + /* animation - velocity for speed */ + var velbase = {} + switch(pJS.particles.move.direction){ + case 'top': + velbase = { x:0, y:-1 }; + break; + case 'top-right': + velbase = { x:0.5, y:-0.5 }; + break; + case 'right': + velbase = { x:1, y:-0 }; + break; + case 'bottom-right': + velbase = { x:0.5, y:0.5 }; + break; + case 'bottom': + velbase = { x:0, y:1 }; + break; + case 'bottom-left': + velbase = { x:-0.5, y:1 }; + break; + case 'left': + velbase = { x:-1, y:0 }; + break; + case 'top-left': + velbase = { x:-0.5, y:-0.5 }; + break; + default: + velbase = { x:0, y:0 }; + break; + } + + if(pJS.particles.move.straight){ + this.vx = velbase.x; + this.vy = velbase.y; + if(pJS.particles.move.random){ + this.vx = this.vx * (Math.random()); + this.vy = this.vy * (Math.random()); + } + }else{ + this.vx = velbase.x + Math.random()-0.5; + this.vy = velbase.y + Math.random()-0.5; + } + + // var theta = 2.0 * Math.PI * Math.random(); + // this.vx = Math.cos(theta); + // this.vy = Math.sin(theta); + + this.vx_i = this.vx; + this.vy_i = this.vy; + + + + /* if shape is image */ + + var shape_type = pJS.particles.shape.type; + if(typeof(shape_type) == 'object'){ + if(shape_type instanceof Array){ + var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)]; + this.shape = shape_selected; + } + }else{ + this.shape = shape_type; + } + + if(this.shape == 'image'){ + var sh = pJS.particles.shape; + this.img = { + src: sh.image.src, + ratio: sh.image.width / sh.image.height + } + if(!this.img.ratio) this.img.ratio = 1; + if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined){ + pJS.fn.vendors.createSvgImg(this); + if(pJS.tmp.pushing){ + this.img.loaded = false; + } + } + } + + + + }; + + + pJS.fn.particle.prototype.draw = function() { + + var p = this; + + if(p.radius_bubble != undefined){ + var radius = p.radius_bubble; + }else{ + var radius = p.radius; + } + + if(p.opacity_bubble != undefined){ + var opacity = p.opacity_bubble; + }else{ + var opacity = p.opacity; + } + + if(p.color.rgb){ + var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+opacity+')'; + }else{ + var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+opacity+')'; + } + + pJS.canvas.ctx.fillStyle = color_value; + pJS.canvas.ctx.beginPath(); + + switch(p.shape){ + + case 'circle': + pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false); + break; + + case 'edge': + pJS.canvas.ctx.rect(p.x-radius, p.y-radius, radius*2, radius*2); + break; + + case 'triangle': + pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x-radius, p.y+radius / 1.66, radius*2, 3, 2); + break; + + case 'polygon': + pJS.fn.vendors.drawShape( + pJS.canvas.ctx, + p.x - radius / (pJS.particles.shape.polygon.nb_sides/3.5), // startX + p.y - radius / (2.66/3.5), // startY + radius*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength + pJS.particles.shape.polygon.nb_sides, // sideCountNumerator + 1 // sideCountDenominator + ); + break; + + case 'star': + pJS.fn.vendors.drawShape( + pJS.canvas.ctx, + p.x - radius*2 / (pJS.particles.shape.polygon.nb_sides/4), // startX + p.y - radius / (2*2.66/3.5), // startY + radius*2*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength + pJS.particles.shape.polygon.nb_sides, // sideCountNumerator + 2 // sideCountDenominator + ); + break; + + case 'image': + + function draw(){ + pJS.canvas.ctx.drawImage( + img_obj, + p.x-radius, + p.y-radius, + radius*2, + radius*2 / p.img.ratio + ); + } + + if(pJS.tmp.img_type == 'svg'){ + var img_obj = p.img.obj; + }else{ + var img_obj = pJS.tmp.img_obj; + } + + if(img_obj){ + draw(); + } + + break; + + } + + pJS.canvas.ctx.closePath(); + + if(pJS.particles.shape.stroke.width > 0){ + pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color; + pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width; + pJS.canvas.ctx.stroke(); + } + + pJS.canvas.ctx.fill(); + + }; + + + pJS.fn.particlesCreate = function(){ + for(var i = 0; i < pJS.particles.number.value; i++) { + pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value)); + } + }; + + pJS.fn.particlesUpdate = function(){ + + for(var i = 0; i < pJS.particles.array.length; i++){ + + /* the particle */ + var p = pJS.particles.array[i]; + + // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy; + // var f = -BANG_SIZE / d; + // if ( d < BANG_SIZE ) { + // var t = Math.atan2( dy, dx ); + // p.vx = f * Math.cos(t); + // p.vy = f * Math.sin(t); + // } + + /* move the particle */ + if(pJS.particles.move.enable){ + var ms = pJS.particles.move.speed/2; + p.x += p.vx * ms; + p.y += p.vy * ms; + } + + /* change opacity status */ + if(pJS.particles.opacity.anim.enable) { + if(p.opacity_status == true) { + if(p.opacity >= pJS.particles.opacity.value) p.opacity_status = false; + p.opacity += p.vo; + }else { + if(p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true; + p.opacity -= p.vo; + } + if(p.opacity < 0) p.opacity = 0; + } + + /* change size */ + if(pJS.particles.size.anim.enable){ + if(p.size_status == true){ + if(p.radius >= pJS.particles.size.value) p.size_status = false; + p.radius += p.vs; + }else{ + if(p.radius <= pJS.particles.size.anim.size_min) p.size_status = true; + p.radius -= p.vs; + } + if(p.radius < 0) p.radius = 0; + } + + /* change particle position if it is out of canvas */ + if(pJS.particles.move.out_mode == 'bounce'){ + var new_pos = { + x_left: p.radius, + x_right: pJS.canvas.w, + y_top: p.radius, + y_bottom: pJS.canvas.h + } + }else{ + var new_pos = { + x_left: -p.radius, + x_right: pJS.canvas.w + p.radius, + y_top: -p.radius, + y_bottom: pJS.canvas.h + p.radius + } + } + + if(p.x - p.radius > pJS.canvas.w){ + p.x = new_pos.x_left; + p.y = Math.random() * pJS.canvas.h; + } + else if(p.x + p.radius < 0){ + p.x = new_pos.x_right; + p.y = Math.random() * pJS.canvas.h; + } + if(p.y - p.radius > pJS.canvas.h){ + p.y = new_pos.y_top; + p.x = Math.random() * pJS.canvas.w; + } + else if(p.y + p.radius < 0){ + p.y = new_pos.y_bottom; + p.x = Math.random() * pJS.canvas.w; + } + + /* out of canvas modes */ + switch(pJS.particles.move.out_mode){ + case 'bounce': + if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx; + else if (p.x - p.radius < 0) p.vx = -p.vx; + if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy; + else if (p.y - p.radius < 0) p.vy = -p.vy; + break; + } + + /* events */ + if(isInArray('grab', pJS.interactivity.events.onhover.mode)){ + pJS.fn.modes.grabParticle(p); + } + + if(isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)){ + pJS.fn.modes.bubbleParticle(p); + } + + if(isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)){ + pJS.fn.modes.repulseParticle(p); + } + + /* interaction auto between particles */ + if(pJS.particles.line_linked.enable || pJS.particles.move.attract.enable){ + for(var j = i + 1; j < pJS.particles.array.length; j++){ + var p2 = pJS.particles.array[j]; + + /* link particles */ + if(pJS.particles.line_linked.enable){ + pJS.fn.interact.linkParticles(p,p2); + } + + /* attract particles */ + if(pJS.particles.move.attract.enable){ + pJS.fn.interact.attractParticles(p,p2); + } + + /* bounce particles */ + if(pJS.particles.move.bounce){ + pJS.fn.interact.bounceParticles(p,p2); + } + + } + } + + + } + + }; + + pJS.fn.particlesDraw = function(){ + + /* clear canvas */ + pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h); + + /* update each particles param */ + pJS.fn.particlesUpdate(); + + /* draw each particle */ + for(var i = 0; i < pJS.particles.array.length; i++){ + var p = pJS.particles.array[i]; + p.draw(); + } + + }; + + pJS.fn.particlesEmpty = function(){ + pJS.particles.array = []; + }; + + pJS.fn.particlesRefresh = function(){ + + /* init all */ + cancelRequestAnimFrame(pJS.fn.checkAnimFrame); + cancelRequestAnimFrame(pJS.fn.drawAnimFrame); + pJS.tmp.source_svg = undefined; + pJS.tmp.img_obj = undefined; + pJS.tmp.count_svg = 0; + pJS.fn.particlesEmpty(); + pJS.fn.canvasClear(); + + /* restart */ + pJS.fn.vendors.start(); + + }; + + + /* ---------- pJS functions - particles interaction ------------ */ + + pJS.fn.interact.linkParticles = function(p1, p2){ + + var dx = p1.x - p2.x, + dy = p1.y - p2.y, + dist = Math.sqrt(dx*dx + dy*dy); + + /* draw a line between p1 and p2 if the distance between them is under the config distance */ + if(dist <= pJS.particles.line_linked.distance){ + + var opacity_line = pJS.particles.line_linked.opacity - (dist / (1/pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance; + + if(opacity_line > 0){ + + /* style */ + var color_line = pJS.particles.line_linked.color_rgb_line; + pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')'; + pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width; + //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */ + + /* path */ + pJS.canvas.ctx.beginPath(); + pJS.canvas.ctx.moveTo(p1.x, p1.y); + pJS.canvas.ctx.lineTo(p2.x, p2.y); + pJS.canvas.ctx.stroke(); + pJS.canvas.ctx.closePath(); + + } + + } + + }; + + + pJS.fn.interact.attractParticles = function(p1, p2){ + + /* condensed particles */ + var dx = p1.x - p2.x, + dy = p1.y - p2.y, + dist = Math.sqrt(dx*dx + dy*dy); + + if(dist <= pJS.particles.line_linked.distance){ + + var ax = dx/(pJS.particles.move.attract.rotateX*1000), + ay = dy/(pJS.particles.move.attract.rotateY*1000); + + p1.vx -= ax; + p1.vy -= ay; + + p2.vx += ax; + p2.vy += ay; + + } + + + } + + + pJS.fn.interact.bounceParticles = function(p1, p2){ + + var dx = p1.x - p2.x, + dy = p1.y - p2.y, + dist = Math.sqrt(dx*dx + dy*dy), + dist_p = p1.radius+p2.radius; + + if(dist <= dist_p){ + p1.vx = -p1.vx; + p1.vy = -p1.vy; + + p2.vx = -p2.vx; + p2.vy = -p2.vy; + } + + } + + + /* ---------- pJS functions - modes events ------------ */ + + pJS.fn.modes.pushParticles = function(nb, pos){ + + pJS.tmp.pushing = true; + + for(var i = 0; i < nb; i++){ + pJS.particles.array.push( + new pJS.fn.particle( + pJS.particles.color, + pJS.particles.opacity.value, + { + 'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w, + 'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h + } + ) + ) + if(i == nb-1){ + if(!pJS.particles.move.enable){ + pJS.fn.particlesDraw(); + } + pJS.tmp.pushing = false; + } + } + + }; + + + pJS.fn.modes.removeParticles = function(nb){ + + pJS.particles.array.splice(0, nb); + if(!pJS.particles.move.enable){ + pJS.fn.particlesDraw(); + } + + }; + + + pJS.fn.modes.bubbleParticle = function(p){ + + /* on hover event */ + if(pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)){ + + var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, + dy_mouse = p.y - pJS.interactivity.mouse.pos_y, + dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse), + ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance; + + function init(){ + p.opacity_bubble = p.opacity; + p.radius_bubble = p.radius; + } + + /* mousemove - check ratio */ + if(dist_mouse <= pJS.interactivity.modes.bubble.distance){ + + if(ratio >= 0 && pJS.interactivity.status == 'mousemove'){ + + /* size */ + if(pJS.interactivity.modes.bubble.size != pJS.particles.size.value){ + + if(pJS.interactivity.modes.bubble.size > pJS.particles.size.value){ + var size = p.radius + (pJS.interactivity.modes.bubble.size*ratio); + if(size >= 0){ + p.radius_bubble = size; + } + }else{ + var dif = p.radius - pJS.interactivity.modes.bubble.size, + size = p.radius - (dif*ratio); + if(size > 0){ + p.radius_bubble = size; + }else{ + p.radius_bubble = 0; + } + } + + } + + /* opacity */ + if(pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value){ + + if(pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value){ + var opacity = pJS.interactivity.modes.bubble.opacity*ratio; + if(opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity){ + p.opacity_bubble = opacity; + } + }else{ + var opacity = p.opacity - (pJS.particles.opacity.value-pJS.interactivity.modes.bubble.opacity)*ratio; + if(opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity){ + p.opacity_bubble = opacity; + } + } + + } + + } + + }else{ + init(); + } + + + /* mouseleave */ + if(pJS.interactivity.status == 'mouseleave'){ + init(); + } + + } + + /* on click event */ + else if(pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)){ + + + if(pJS.tmp.bubble_clicking){ + var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x, + dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y, + dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse), + time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time)/1000; + + if(time_spent > pJS.interactivity.modes.bubble.duration){ + pJS.tmp.bubble_duration_end = true; + } + + if(time_spent > pJS.interactivity.modes.bubble.duration*2){ + pJS.tmp.bubble_clicking = false; + pJS.tmp.bubble_duration_end = false; + } + } + + + function process(bubble_param, particles_param, p_obj_bubble, p_obj, id){ + + if(bubble_param != particles_param){ + + if(!pJS.tmp.bubble_duration_end){ + if(dist_mouse <= pJS.interactivity.modes.bubble.distance){ + if(p_obj_bubble != undefined) var obj = p_obj_bubble; + else var obj = p_obj; + if(obj != bubble_param){ + var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration); + if(id == 'size') p.radius_bubble = value; + if(id == 'opacity') p.opacity_bubble = value; + } + }else{ + if(id == 'size') p.radius_bubble = undefined; + if(id == 'opacity') p.opacity_bubble = undefined; + } + }else{ + if(p_obj_bubble != undefined){ + var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration), + dif = bubble_param - value_tmp; + value = bubble_param + dif; + if(id == 'size') p.radius_bubble = value; + if(id == 'opacity') p.opacity_bubble = value; + } + } + + } + + } + + if(pJS.tmp.bubble_clicking){ + /* size */ + process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size'); + /* opacity */ + process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity'); + } + + } + + }; + + + pJS.fn.modes.repulseParticle = function(p){ + + if(pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') { + + var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, + dy_mouse = p.y - pJS.interactivity.mouse.pos_y, + dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse); + + var normVec = {x: dx_mouse/dist_mouse, y: dy_mouse/dist_mouse}, + repulseRadius = pJS.interactivity.modes.repulse.distance, + velocity = 100, + repulseFactor = clamp((1/repulseRadius)*(-1*Math.pow(dist_mouse/repulseRadius,2)+1)*repulseRadius*velocity, 0, 50); + + var pos = { + x: p.x + normVec.x * repulseFactor, + y: p.y + normVec.y * repulseFactor + } + + if(pJS.particles.move.out_mode == 'bounce'){ + if(pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x; + if(pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y; + }else{ + p.x = pos.x; + p.y = pos.y; + } + + } + + + else if(pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) { + + if(!pJS.tmp.repulse_finish){ + pJS.tmp.repulse_count++; + if(pJS.tmp.repulse_count == pJS.particles.array.length){ + pJS.tmp.repulse_finish = true; + } + } + + if(pJS.tmp.repulse_clicking){ + + var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance/6, 3); + + var dx = pJS.interactivity.mouse.click_pos_x - p.x, + dy = pJS.interactivity.mouse.click_pos_y - p.y, + d = dx*dx + dy*dy; + + var force = -repulseRadius / d * 1; + + function process(){ + + var f = Math.atan2(dy,dx); + p.vx = force * Math.cos(f); + p.vy = force * Math.sin(f); + + if(pJS.particles.move.out_mode == 'bounce'){ + var pos = { + x: p.x + p.vx, + y: p.y + p.vy + } + if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx; + else if (pos.x - p.radius < 0) p.vx = -p.vx; + if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy; + else if (pos.y - p.radius < 0) p.vy = -p.vy; + } + + } + + // default + if(d <= repulseRadius){ + process(); + } + + // bang - slow motion mode + // if(!pJS.tmp.repulse_finish){ + // if(d <= repulseRadius){ + // process(); + // } + // }else{ + // process(); + // } + + + }else{ + + if(pJS.tmp.repulse_clicking == false){ + + p.vx = p.vx_i; + p.vy = p.vy_i; + + } + + } + + } + + } + + + pJS.fn.modes.grabParticle = function(p){ + + if(pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove'){ + + var dx_mouse = p.x - pJS.interactivity.mouse.pos_x, + dy_mouse = p.y - pJS.interactivity.mouse.pos_y, + dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse); + + /* draw a line between the cursor and the particle if the distance between them is under the config distance */ + if(dist_mouse <= pJS.interactivity.modes.grab.distance){ + + var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1/pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance; + + if(opacity_line > 0){ + + /* style */ + var color_line = pJS.particles.line_linked.color_rgb_line; + pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')'; + pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width; + //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */ + + /* path */ + pJS.canvas.ctx.beginPath(); + pJS.canvas.ctx.moveTo(p.x, p.y); + pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y); + pJS.canvas.ctx.stroke(); + pJS.canvas.ctx.closePath(); + + } + + } + + } + + }; + + + + /* ---------- pJS functions - vendors ------------ */ + + pJS.fn.vendors.eventsListeners = function(){ + + /* events target element */ + if(pJS.interactivity.detect_on == 'window'){ + pJS.interactivity.el = window; + }else{ + pJS.interactivity.el = pJS.canvas.el; + } + + + /* detect mouse pos - on hover / click event */ + if(pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable){ + + /* el on mousemove */ + pJS.interactivity.el.addEventListener('mousemove', function(e){ + + if(pJS.interactivity.el == window){ + var pos_x = e.clientX, + pos_y = e.clientY; + } + else{ + var pos_x = e.offsetX || e.clientX, + pos_y = e.offsetY || e.clientY; + } + + pJS.interactivity.mouse.pos_x = pos_x; + pJS.interactivity.mouse.pos_y = pos_y; + + if(pJS.tmp.retina){ + pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio; + pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio; + } + + pJS.interactivity.status = 'mousemove'; + + }); + + /* el on onmouseleave */ + pJS.interactivity.el.addEventListener('mouseleave', function(e){ + + pJS.interactivity.mouse.pos_x = null; + pJS.interactivity.mouse.pos_y = null; + pJS.interactivity.status = 'mouseleave'; + + }); + + } + + /* on click event */ + if(pJS.interactivity.events.onclick.enable){ + + pJS.interactivity.el.addEventListener('click', function(){ + + pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x; + pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y; + pJS.interactivity.mouse.click_time = new Date().getTime(); + + if(pJS.interactivity.events.onclick.enable){ + + switch(pJS.interactivity.events.onclick.mode){ + + case 'push': + if(pJS.particles.move.enable){ + pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse); + }else{ + if(pJS.interactivity.modes.push.particles_nb == 1){ + pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse); + } + else if(pJS.interactivity.modes.push.particles_nb > 1){ + pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb); + } + } + break; + + case 'remove': + pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb); + break; + + case 'bubble': + pJS.tmp.bubble_clicking = true; + break; + + case 'repulse': + pJS.tmp.repulse_clicking = true; + pJS.tmp.repulse_count = 0; + pJS.tmp.repulse_finish = false; + setTimeout(function(){ + pJS.tmp.repulse_clicking = false; + }, pJS.interactivity.modes.repulse.duration*1000) + break; + + } + + } + + }); + + } + + + }; + + pJS.fn.vendors.densityAutoParticles = function(){ + + if(pJS.particles.number.density.enable){ + + /* calc area */ + var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000; + if(pJS.tmp.retina){ + area = area/(pJS.canvas.pxratio*2); + } + + /* calc number of particles based on density area */ + var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area; + + /* add or remove X particles */ + var missing_particles = pJS.particles.array.length - nb_particles; + if(missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles)); + else pJS.fn.modes.removeParticles(missing_particles); + + } + + }; + + + pJS.fn.vendors.checkOverlap = function(p1, position){ + for(var i = 0; i < pJS.particles.array.length; i++){ + var p2 = pJS.particles.array[i]; + + var dx = p1.x - p2.x, + dy = p1.y - p2.y, + dist = Math.sqrt(dx*dx + dy*dy); + + if(dist <= p1.radius + p2.radius){ + p1.x = position ? position.x : Math.random() * pJS.canvas.w; + p1.y = position ? position.y : Math.random() * pJS.canvas.h; + pJS.fn.vendors.checkOverlap(p1); + } + } + }; + + + pJS.fn.vendors.createSvgImg = function(p){ + + /* set color to svg element */ + var svgXml = pJS.tmp.source_svg, + rgbHex = /#([0-9A-F]{3,6})/gi, + coloredSvgXml = svgXml.replace(rgbHex, function (m, r, g, b) { + if(p.color.rgb){ + var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+p.opacity+')'; + }else{ + var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+p.opacity+')'; + } + return color_value; + }); + + /* prepare to create img with colored svg */ + var svg = new Blob([coloredSvgXml], {type: 'image/svg+xml;charset=utf-8'}), + DOMURL = window.URL || window.webkitURL || window, + url = DOMURL.createObjectURL(svg); + + /* create particle img obj */ + var img = new Image(); + img.addEventListener('load', function(){ + p.img.obj = img; + p.img.loaded = true; + DOMURL.revokeObjectURL(url); + pJS.tmp.count_svg++; + }); + img.src = url; + + }; + + + pJS.fn.vendors.destroypJS = function(){ + cancelAnimationFrame(pJS.fn.drawAnimFrame); + canvas_el.remove(); + pJSDom = null; + }; + + + pJS.fn.vendors.drawShape = function(c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator){ + + // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/ + var sideCount = sideCountNumerator * sideCountDenominator; + var decimalSides = sideCountNumerator / sideCountDenominator; + var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides; + var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians + c.save(); + c.beginPath(); + c.translate(startX, startY); + c.moveTo(0,0); + for (var i = 0; i < sideCount; i++) { + c.lineTo(sideLength,0); + c.translate(sideLength,0); + c.rotate(interiorAngle); + } + //c.stroke(); + c.fill(); + c.restore(); + + }; + + pJS.fn.vendors.exportImg = function(){ + window.open(pJS.canvas.el.toDataURL('image/png'), '_blank'); + }; + + + pJS.fn.vendors.loadImg = function(type){ + + pJS.tmp.img_error = undefined; + + if(pJS.particles.shape.image.src != ''){ + + if(type == 'svg'){ + + var xhr = new XMLHttpRequest(); + xhr.open('GET', pJS.particles.shape.image.src); + xhr.onreadystatechange = function (data) { + if(xhr.readyState == 4){ + if(xhr.status == 200){ + pJS.tmp.source_svg = data.currentTarget.response; + pJS.fn.vendors.checkBeforeDraw(); + }else{ + console.log('Error pJS - Image not found'); + pJS.tmp.img_error = true; + } + } + } + xhr.send(); + + }else{ + + var img = new Image(); + img.addEventListener('load', function(){ + pJS.tmp.img_obj = img; + pJS.fn.vendors.checkBeforeDraw(); + }); + img.src = pJS.particles.shape.image.src; + + } + + }else{ + console.log('Error pJS - No image.src'); + pJS.tmp.img_error = true; + } + + }; + + + pJS.fn.vendors.draw = function(){ + + if(pJS.particles.shape.type == 'image'){ + + if(pJS.tmp.img_type == 'svg'){ + + if(pJS.tmp.count_svg >= pJS.particles.number.value){ + pJS.fn.particlesDraw(); + if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); + else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + }else{ + //console.log('still loading...'); + if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + } + + }else{ + + if(pJS.tmp.img_obj != undefined){ + pJS.fn.particlesDraw(); + if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); + else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + }else{ + if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + } + + } + + }else{ + pJS.fn.particlesDraw(); + if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame); + else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw); + } + + }; + + + pJS.fn.vendors.checkBeforeDraw = function(){ + + // if shape is image + if(pJS.particles.shape.type == 'image'){ + + if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined){ + pJS.tmp.checkAnimFrame = requestAnimFrame(check); + }else{ + //console.log('images loaded! cancel check'); + cancelRequestAnimFrame(pJS.tmp.checkAnimFrame); + if(!pJS.tmp.img_error){ + pJS.fn.vendors.init(); + pJS.fn.vendors.draw(); + } + + } + + }else{ + pJS.fn.vendors.init(); + pJS.fn.vendors.draw(); + } + + }; + + + pJS.fn.vendors.init = function(){ + + /* init canvas + particles */ + pJS.fn.retinaInit(); + pJS.fn.canvasInit(); + pJS.fn.canvasSize(); + pJS.fn.canvasPaint(); + pJS.fn.particlesCreate(); + pJS.fn.vendors.densityAutoParticles(); + + /* particles.line_linked - convert hex colors to rgb */ + pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color); + + }; + + + pJS.fn.vendors.start = function(){ + + if(isInArray('image', pJS.particles.shape.type)){ + pJS.tmp.img_type = pJS.particles.shape.image.src.substr(pJS.particles.shape.image.src.length - 3); + pJS.fn.vendors.loadImg(pJS.tmp.img_type); + }else{ + pJS.fn.vendors.checkBeforeDraw(); + } + + }; + + + + + /* ---------- pJS - start ------------ */ + + + pJS.fn.vendors.eventsListeners(); + + pJS.fn.vendors.start(); + + + +}; + +/* ---------- global functions - vendors ------------ */ + +Object.deepExtend = function(destination, source) { + for (var property in source) { + if (source[property] && source[property].constructor && + source[property].constructor === Object) { + destination[property] = destination[property] || {}; + arguments.callee(destination[property], source[property]); + } else { + destination[property] = source[property]; + } + } + return destination; +}; + +window.requestAnimFrame = (function(){ + return window.requestAnimationFrame || + window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || + window.oRequestAnimationFrame || + window.msRequestAnimationFrame || + function(callback){ + window.setTimeout(callback, 1000 / 60); + }; +})(); + +window.cancelRequestAnimFrame = ( function() { + return window.cancelAnimationFrame || + window.webkitCancelRequestAnimationFrame || + window.mozCancelRequestAnimationFrame || + window.oCancelRequestAnimationFrame || + window.msCancelRequestAnimationFrame || + clearTimeout +} )(); + +function hexToRgb(hex){ + // By Tim Down - http://stackoverflow.com/a/5624139/3493650 + // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") + var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; + hex = hex.replace(shorthandRegex, function(m, r, g, b) { + return r + r + g + g + b + b; + }); + var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : null; +}; + +function clamp(number, min, max) { + return Math.min(Math.max(number, min), max); +}; + +function isInArray(value, array) { + return array.indexOf(value) > -1; +} + + +/* ---------- particles.js functions - start ------------ */ + +window.pJSDom = []; + +window.particlesJS = function(tag_id, params){ + + //console.log(params); + + /* no string id? so it's object params, and set the id with default id */ + if(typeof(tag_id) != 'string'){ + params = tag_id; + tag_id = 'particles-js'; + } + + /* no id? set the id to default id */ + if(!tag_id){ + tag_id = 'particles-js'; + } + + /* pJS elements */ + var pJS_tag = document.getElementById(tag_id), + pJS_canvas_class = 'particles-js-canvas-el', + exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class); + + /* remove canvas if exists into the pJS target tag */ + if(exist_canvas.length){ + while(exist_canvas.length > 0){ + pJS_tag.removeChild(exist_canvas[0]); + } + } + + /* create canvas element */ + var canvas_el = document.createElement('canvas'); + canvas_el.className = pJS_canvas_class; + + /* set size canvas */ + canvas_el.style.width = "100%"; + canvas_el.style.height = "100%"; + + /* append canvas */ + var canvas = document.getElementById(tag_id).appendChild(canvas_el); + + /* launch particle.js */ + if(canvas != null){ + pJSDom.push(new pJS(tag_id, params)); + } + +}; + +window.particlesJS.load = function(tag_id, path_config_json, callback){ + + /* load json config */ + var xhr = new XMLHttpRequest(); + xhr.open('GET', path_config_json); + xhr.onreadystatechange = function (data) { + if(xhr.readyState == 4){ + if(xhr.status == 200){ + var params = JSON.parse(data.currentTarget.response); + window.particlesJS(tag_id, params); + if(callback) callback(); + }else{ + console.log('Error pJS - XMLHttpRequest status: '+xhr.status); + console.log('Error pJS - File config not found'); + } + } + }; + xhr.send(); + +}; \ No newline at end of file diff --git a/assets/js/dev/vendors/prettify.js b/assets/js/dev/vendors/prettify.js new file mode 100644 index 0000000..8c1cb28 --- /dev/null +++ b/assets/js/dev/vendors/prettify.js @@ -0,0 +1,1031 @@ +// Copyright (C) 2006 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview + * some functions for browser-side pretty printing of code contained in html. + * + *

    + * For a fairly comprehensive set of languages see the + * README + * file that came with this source. At a minimum, the lexer should work on a + * number of languages including C and friends, Java, Python, Bash, SQL, HTML, + * XML, CSS, Javascript, and Makefiles. It works passably on Ruby, PHP and Awk + * and a subset of Perl, but, because of commenting conventions, doesn't work on + * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class. + *

    + * Usage:

      + *
    1. include this source file in an html page via + * {@code } + *
    2. define style rules. See the example page for examples. + *
    3. mark the {@code
      } and {@code } tags in your source with
      + *    {@code class=prettyprint.}
      + *    You can also use the (html deprecated) {@code } tag, but the pretty
      + *    printer needs to do more substantial DOM manipulations to support that, so
      + *    some css styles may not be preserved.
      + * </ol>
      + * That's it.  I wanted to keep the API as simple as possible, so there's no
      + * need to specify which language the code is in, but if you wish, you can add
      + * another class to the {@code <pre>} or {@code <code>} element to specify the
      + * language, as in {@code <pre class="prettyprint lang-java">}.  Any class that
      + * starts with "lang-" followed by a file extension, specifies the file type.
      + * See the "lang-*.js" files in this directory for code that implements
      + * per-language file handlers.
      + * <p>
      + * Change log:<br>
      + * cbeust, 2006/08/22
      + * <blockquote>
      + *   Java annotations (start with "@") are now captured as literals ("lit")
      + * </blockquote>
      + * @requires console
      + */
      +
      +// JSLint declarations
      +/*global console, document, navigator, setTimeout, window, define */
      +
      +/** @define {boolean} */
      +var IN_GLOBAL_SCOPE = true;
      +
      +/**
      + * Split {@code prettyPrint} into multiple timeouts so as not to interfere with
      + * UI events.
      + * If set to {@code false}, {@code prettyPrint()} is synchronous.
      + */
      +window['PR_SHOULD_USE_CONTINUATION'] = true;
      +
      +/**
      + * Pretty print a chunk of code.
      + * @param {string} sourceCodeHtml The HTML to pretty print.
      + * @param {string} opt_langExtension The language name to use.
      + *     Typically, a filename extension like 'cpp' or 'java'.
      + * @param {number|boolean} opt_numberLines True to number lines,
      + *     or the 1-indexed number of the first line in sourceCodeHtml.
      + * @return {string} code as html, but prettier
      + */
      +var prettyPrintOne;
      +/**
      + * Find all the {@code <pre>} and {@code <code>} tags in the DOM with
      + * {@code class=prettyprint} and prettify them.
      + *
      + * @param {Function} opt_whenDone called when prettifying is done.
      + * @param {HTMLElement|HTMLDocument} opt_root an element or document
      + *   containing all the elements to pretty print.
      + *   Defaults to {@code document.body}.
      + */
      +var prettyPrint;
      +
      +
      +(function () {
      +  var win = window;
      +  // Keyword lists for various languages.
      +  // We use things that coerce to strings to make them compact when minified
      +  // and to defeat aggressive optimizers that fold large string constants.
      +  var FLOW_CONTROL_KEYWORDS = ["break,continue,do,else,for,if,return,while"];
      +  var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,"auto,case,char,const,default," + 
      +      "double,enum,extern,float,goto,inline,int,long,register,short,signed," +
      +      "sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];
      +  var COMMON_KEYWORDS = [C_KEYWORDS,"catch,class,delete,false,import," +
      +      "new,operator,private,protected,public,this,throw,true,try,typeof"];
      +  var CPP_KEYWORDS = [COMMON_KEYWORDS,"alignof,align_union,asm,axiom,bool," +
      +      "concept,concept_map,const_cast,constexpr,decltype,delegate," +
      +      "dynamic_cast,explicit,export,friend,generic,late_check," +
      +      "mutable,namespace,nullptr,property,reinterpret_cast,static_assert," +
      +      "static_cast,template,typeid,typename,using,virtual,where"];
      +  var JAVA_KEYWORDS = [COMMON_KEYWORDS,
      +      "abstract,assert,boolean,byte,extends,final,finally,implements,import," +
      +      "instanceof,interface,null,native,package,strictfp,super,synchronized," +
      +      "throws,transient"];
      +  var CSHARP_KEYWORDS = [JAVA_KEYWORDS,
      +      "as,base,by,checked,decimal,delegate,descending,dynamic,event," +
      +      "fixed,foreach,from,group,implicit,in,internal,into,is,let," +
      +      "lock,object,out,override,orderby,params,partial,readonly,ref,sbyte," +
      +      "sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort," +
      +      "var,virtual,where"];
      +  var COFFEE_KEYWORDS = "all,and,by,catch,class,else,extends,false,finally," +
      +      "for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then," +
      +      "throw,true,try,unless,until,when,while,yes";
      +  var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,
      +      "debugger,eval,export,function,get,null,set,undefined,var,with," +
      +      "Infinity,NaN"];
      +  var PERL_KEYWORDS = "caller,delete,die,do,dump,elsif,eval,exit,foreach,for," +
      +      "goto,if,import,last,local,my,next,no,our,print,package,redo,require," +
      +      "sub,undef,unless,until,use,wantarray,while,BEGIN,END";
      +  var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "and,as,assert,class,def,del," +
      +      "elif,except,exec,finally,from,global,import,in,is,lambda," +
      +      "nonlocal,not,or,pass,print,raise,try,with,yield," +
      +      "False,True,None"];
      +  var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "alias,and,begin,case,class," +
      +      "def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo," +
      +      "rescue,retry,self,super,then,true,undef,unless,until,when,yield," +
      +      "BEGIN,END"];
      +   var RUST_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "as,assert,const,copy,drop," +
      +      "enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv," +
      +      "pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"];
      +  var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "case,done,elif,esac,eval,fi," +
      +      "function,in,local,set,then,until"];
      +  var ALL_KEYWORDS = [
      +      CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS,
      +      PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];
      +  var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/;
      +
      +  // token style names.  correspond to css classes
      +  /**
      +   * token style for a string literal
      +   * @const
      +   */
      +  var PR_STRING = 'str';
      +  /**
      +   * token style for a keyword
      +   * @const
      +   */
      +  var PR_KEYWORD = 'kwd';
      +  /**
      +   * token style for a comment
      +   * @const
      +   */
      +  var PR_COMMENT = 'com';
      +  /**
      +   * token style for a type
      +   * @const
      +   */
      +  var PR_TYPE = 'typ';
      +  /**
      +   * token style for a literal value.  e.g. 1, null, true.
      +   * @const
      +   */
      +  var PR_LITERAL = 'lit';
      +  /**
      +   * token style for a punctuation string.
      +   * @const
      +   */
      +  var PR_PUNCTUATION = 'pun';
      +  /**
      +   * token style for plain text.
      +   * @const
      +   */
      +  var PR_PLAIN = 'pln';
      +
      +  /**
      +   * token style for an sgml tag.
      +   * @const
      +   */
      +  var PR_TAG = 'tag';
      +  /**
      +   * token style for a markup declaration such as a DOCTYPE.
      +   * @const
      +   */
      +  var PR_DECLARATION = 'dec';
      +  /**
      +   * token style for embedded source.
      +   * @const
      +   */
      +  var PR_SOURCE = 'src';
      +  /**
      +   * token style for an sgml attribute name.
      +   * @const
      +   */
      +  var PR_ATTRIB_NAME = 'atn';
      +  /**
      +   * token style for an sgml attribute value.
      +   * @const
      +   */
      +  var PR_ATTRIB_VALUE = 'atv';
      +
      +  /**
      +   * A class that indicates a section of markup that is not code, e.g. to allow
      +   * embedding of line numbers within code listings.
      +   * @const
      +   */
      +  var PR_NOCODE = 'nocode';
      +
      +  include("regexpPrecederPatterns.pl");
      +
      +  include("combinePrefixPatterns.js");
      +
      +  include("extractSourceSpans.js");
      +
      +  /**
      +   * Apply the given language handler to sourceCode and add the resulting
      +   * decorations to out.
      +   * @param {number} basePos the index of sourceCode within the chunk of source
      +   *    whose decorations are already present on out.
      +   */
      +  function appendDecorations(basePos, sourceCode, langHandler, out) {
      +    if (!sourceCode) { return; }
      +    var job = {
      +      sourceCode: sourceCode,
      +      basePos: basePos
      +    };
      +    langHandler(job);
      +    out.push.apply(out, job.decorations);
      +  }
      +
      +  var notWs = /\S/;
      +
      +  /**
      +   * Given an element, if it contains only one child element and any text nodes
      +   * it contains contain only space characters, return the sole child element.
      +   * Otherwise returns undefined.
      +   * <p>
      +   * This is meant to return the CODE element in {@code <pre><code ...>} when
      +   * there is a single child element that contains all the non-space textual
      +   * content, but not to return anything where there are multiple child elements
      +   * as in {@code <pre><code>...</code><code>...</code></pre>} or when there
      +   * is textual content.
      +   */
      +  function childContentWrapper(element) {
      +    var wrapper = undefined;
      +    for (var c = element.firstChild; c; c = c.nextSibling) {
      +      var type = c.nodeType;
      +      wrapper = (type === 1)  // Element Node
      +          ? (wrapper ? element : c)
      +          : (type === 3)  // Text Node
      +          ? (notWs.test(c.nodeValue) ? element : wrapper)
      +          : wrapper;
      +    }
      +    return wrapper === element ? undefined : wrapper;
      +  }
      +
      +  /** Given triples of [style, pattern, context] returns a lexing function,
      +    * The lexing function interprets the patterns to find token boundaries and
      +    * returns a decoration list of the form
      +    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]
      +    * where index_n is an index into the sourceCode, and style_n is a style
      +    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to
      +    * all characters in sourceCode[index_n-1:index_n].
      +    *
      +    * The stylePatterns is a list whose elements have the form
      +    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].
      +    *
      +    * Style is a style constant like PR_PLAIN, or can be a string of the
      +    * form 'lang-FOO', where FOO is a language extension describing the
      +    * language of the portion of the token in $1 after pattern executes.
      +    * E.g., if style is 'lang-lisp', and group 1 contains the text
      +    * '(hello (world))', then that portion of the token will be passed to the
      +    * registered lisp handler for formatting.
      +    * The text before and after group 1 will be restyled using this decorator
      +    * so decorators should take care that this doesn't result in infinite
      +    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks
      +    * something like ['lang-js', /<[s]cript>(.+?)<\/script>/].  This may match
      +    * '<script>foo()<\/script>', which would cause the current decorator to
      +    * be called with '<script>' which would not match the same rule since
      +    * group 1 must not be empty, so it would be instead styled as PR_TAG by
      +    * the generic tag rule.  The handler registered for the 'js' extension would
      +    * then be called with 'foo()', and finally, the current decorator would
      +    * be called with '<\/script>' which would not match the original rule and
      +    * so the generic tag rule would identify it as a tag.
      +    *
      +    * Pattern must only match prefixes, and if it matches a prefix, then that
      +    * match is considered a token with the same style.
      +    *
      +    * Context is applied to the last non-whitespace, non-comment token
      +    * recognized.
      +    *
      +    * Shortcut is an optional string of characters, any of which, if the first
      +    * character, gurantee that this pattern and only this pattern matches.
      +    *
      +    * @param {Array} shortcutStylePatterns patterns that always start with
      +    *   a known character.  Must have a shortcut string.
      +    * @param {Array} fallthroughStylePatterns patterns that will be tried in
      +    *   order if the shortcut ones fail.  May have shortcuts.
      +    *
      +    * @return {function (Object)} a
      +    *   function that takes source code and returns a list of decorations.
      +    */
      +  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {
      +    var shortcuts = {};
      +    var tokenizer;
      +    (function () {
      +      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);
      +      var allRegexs = [];
      +      var regexKeys = {};
      +      for (var i = 0, n = allPatterns.length; i < n; ++i) {
      +        var patternParts = allPatterns[i];
      +        var shortcutChars = patternParts[3];
      +        if (shortcutChars) {
      +          for (var c = shortcutChars.length; --c >= 0;) {
      +            shortcuts[shortcutChars.charAt(c)] = patternParts;
      +          }
      +        }
      +        var regex = patternParts[1];
      +        var k = '' + regex;
      +        if (!regexKeys.hasOwnProperty(k)) {
      +          allRegexs.push(regex);
      +          regexKeys[k] = null;
      +        }
      +      }
      +      allRegexs.push(/[\0-\uffff]/);
      +      tokenizer = combinePrefixPatterns(allRegexs);
      +    })();
      +
      +    var nPatterns = fallthroughStylePatterns.length;
      +
      +    /**
      +     * Lexes job.sourceCode and produces an output array job.decorations of
      +     * style classes preceded by the position at which they start in
      +     * job.sourceCode in order.
      +     *
      +     * @param {Object} job an object like <pre>{
      +     *    sourceCode: {string} sourceText plain text,
      +     *    basePos: {int} position of job.sourceCode in the larger chunk of
      +     *        sourceCode.
      +     * }</pre>
      +     */
      +    var decorate = function (job) {
      +      var sourceCode = job.sourceCode, basePos = job.basePos;
      +      /** Even entries are positions in source in ascending order.  Odd enties
      +        * are style markers (e.g., PR_COMMENT) that run from that position until
      +        * the end.
      +        * @type {Array.<number|string>}
      +        */
      +      var decorations = [basePos, PR_PLAIN];
      +      var pos = 0;  // index into sourceCode
      +      var tokens = sourceCode.match(tokenizer) || [];
      +      var styleCache = {};
      +
      +      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {
      +        var token = tokens[ti];
      +        var style = styleCache[token];
      +        var match = void 0;
      +
      +        var isEmbedded;
      +        if (typeof style === 'string') {
      +          isEmbedded = false;
      +        } else {
      +          var patternParts = shortcuts[token.charAt(0)];
      +          if (patternParts) {
      +            match = token.match(patternParts[1]);
      +            style = patternParts[0];
      +          } else {
      +            for (var i = 0; i < nPatterns; ++i) {
      +              patternParts = fallthroughStylePatterns[i];
      +              match = token.match(patternParts[1]);
      +              if (match) {
      +                style = patternParts[0];
      +                break;
      +              }
      +            }
      +
      +            if (!match) {  // make sure that we make progress
      +              style = PR_PLAIN;
      +            }
      +          }
      +
      +          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);
      +          if (isEmbedded && !(match && typeof match[1] === 'string')) {
      +            isEmbedded = false;
      +            style = PR_SOURCE;
      +          }
      +
      +          if (!isEmbedded) { styleCache[token] = style; }
      +        }
      +
      +        var tokenStart = pos;
      +        pos += token.length;
      +
      +        if (!isEmbedded) {
      +          decorations.push(basePos + tokenStart, style);
      +        } else {  // Treat group 1 as an embedded block of source code.
      +          var embeddedSource = match[1];
      +          var embeddedSourceStart = token.indexOf(embeddedSource);
      +          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;
      +          if (match[2]) {
      +            // If embeddedSource can be blank, then it would match at the
      +            // beginning which would cause us to infinitely recurse on the
      +            // entire token, so we catch the right context in match[2].
      +            embeddedSourceEnd = token.length - match[2].length;
      +            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;
      +          }
      +          var lang = style.substring(5);
      +          // Decorate the left of the embedded source
      +          appendDecorations(
      +              basePos + tokenStart,
      +              token.substring(0, embeddedSourceStart),
      +              decorate, decorations);
      +          // Decorate the embedded source
      +          appendDecorations(
      +              basePos + tokenStart + embeddedSourceStart,
      +              embeddedSource,
      +              langHandlerForExtension(lang, embeddedSource),
      +              decorations);
      +          // Decorate the right of the embedded section
      +          appendDecorations(
      +              basePos + tokenStart + embeddedSourceEnd,
      +              token.substring(embeddedSourceEnd),
      +              decorate, decorations);
      +        }
      +      }
      +      job.decorations = decorations;
      +    };
      +    return decorate;
      +  }
      +
      +  /** returns a function that produces a list of decorations from source text.
      +    *
      +    * This code treats ", ', and ` as string delimiters, and \ as a string
      +    * escape.  It does not recognize perl's qq() style strings.
      +    * It has no special handling for double delimiter escapes as in basic, or
      +    * the tripled delimiters used in python, but should work on those regardless
      +    * although in those cases a single string literal may be broken up into
      +    * multiple adjacent string literals.
      +    *
      +    * It recognizes C, C++, and shell style comments.
      +    *
      +    * @param {Object} options a set of optional parameters.
      +    * @return {function (Object)} a function that examines the source code
      +    *     in the input job and builds the decoration list.
      +    */
      +  function sourceDecorator(options) {
      +    var shortcutStylePatterns = [], fallthroughStylePatterns = [];
      +    if (options['tripleQuotedStrings']) {
      +      // '''multi-line-string''', 'single-line-string', and double-quoted
      +      shortcutStylePatterns.push(
      +          [PR_STRING,  /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
      +           null, '\'"']);
      +    } else if (options['multiLineStrings']) {
      +      // 'multi-line-string', "multi-line-string"
      +      shortcutStylePatterns.push(
      +          [PR_STRING,  /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
      +           null, '\'"`']);
      +    } else {
      +      // 'single-line-string', "single-line-string"
      +      shortcutStylePatterns.push(
      +          [PR_STRING,
      +           /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
      +           null, '"\'']);
      +    }
      +    if (options['verbatimStrings']) {
      +      // verbatim-string-literal production from the C# grammar.  See issue 93.
      +      fallthroughStylePatterns.push(
      +          [PR_STRING, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]);
      +    }
      +    var hc = options['hashComments'];
      +    if (hc) {
      +      if (options['cStyleComments']) {
      +        if (hc > 1) {  // multiline hash comments
      +          shortcutStylePatterns.push(
      +              [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);
      +        } else {
      +          // Stop C preprocessor declarations at an unclosed open comment
      +          shortcutStylePatterns.push(
      +              [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,
      +               null, '#']);
      +        }
      +        // #include <stdio.h>
      +        fallthroughStylePatterns.push(
      +            [PR_STRING,
      +             /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,
      +             null]);
      +      } else {
      +        shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']);
      +      }
      +    }
      +    if (options['cStyleComments']) {
      +      fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]);
      +      fallthroughStylePatterns.push(
      +          [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]);
      +    }
      +    if (options['regexLiterals']) {
      +      /**
      +       * @const
      +       */
      +      var REGEX_LITERAL = (
      +          // A regular expression literal starts with a slash that is
      +          // not followed by * or / so that it is not confused with
      +          // comments.
      +          '/(?=[^/*])'
      +          // and then contains any number of raw characters,
      +          + '(?:[^/\\x5B\\x5C]'
      +          // escape sequences (\x5C),
      +          +    '|\\x5C[\\s\\S]'
      +          // or non-nesting character sets (\x5B\x5D);
      +          +    '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+'
      +          // finally closed by a /.
      +          + '/');
      +      fallthroughStylePatterns.push(
      +          ['lang-regex',
      +           new RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')
      +           ]);
      +    }
      +
      +    var types = options['types'];
      +    if (types) {
      +      fallthroughStylePatterns.push([PR_TYPE, types]);
      +    }
      +
      +    var keywords = ("" + options['keywords']).replace(/^ | $/g, '');
      +    if (keywords.length) {
      +      fallthroughStylePatterns.push(
      +          [PR_KEYWORD,
      +           new RegExp('^(?:' + keywords.replace(/[\s,]+/g, '|') + ')\\b'),
      +           null]);
      +    }
      +
      +    shortcutStylePatterns.push([PR_PLAIN,       /^\s+/, null, ' \r\n\t\xA0']);
      +
      +    var punctuation =
      +      // The Bash man page says
      +
      +      // A word is a sequence of characters considered as a single
      +      // unit by GRUB. Words are separated by metacharacters,
      +      // which are the following plus space, tab, and newline: { }
      +      // | & $ ; < >
      +      // ...
      +      
      +      // A word beginning with # causes that word and all remaining
      +      // characters on that line to be ignored.
      +
      +      // which means that only a '#' after /(?:^|[{}|&$;<>\s])/ starts a
      +      // comment but empirically
      +      // $ echo {#}
      +      // {#}
      +      // $ echo \$#
      +      // $#
      +      // $ echo }#
      +      // }#
      +
      +      // so /(?:^|[|&;<>\s])/ is more appropriate.
      +
      +      // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3
      +      // suggests that this definition is compatible with a
      +      // default mode that tries to use a single token definition
      +      // to recognize both bash/python style comments and C
      +      // preprocessor directives.
      +
      +      // This definition of punctuation does not include # in the list of
      +      // follow-on exclusions, so # will not be broken before if preceeded
      +      // by a punctuation character.  We could try to exclude # after
      +      // [|&;<>] but that doesn't seem to cause many major problems.
      +      // If that does turn out to be a problem, we should change the below
      +      // when hc is truthy to include # in the run of punctuation characters
      +      // only when not followint [|&;<>].
      +      /^.[^\s\w\.$@\'\"\`\/\\]*/;
      +
      +    fallthroughStylePatterns.push(
      +        // TODO(mikesamuel): recognize non-latin letters and numerals in idents
      +        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],
      +        [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null],
      +        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],
      +        [PR_LITERAL,
      +         new RegExp(
      +             '^(?:'
      +             // A hex number
      +             + '0x[a-f0-9]+'
      +             // or an octal or decimal number,
      +             + '|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)'
      +             // possibly in scientific notation
      +             + '(?:e[+\\-]?\\d+)?'
      +             + ')'
      +             // with an optional modifier like UL for unsigned long
      +             + '[a-z]*', 'i'),
      +         null, '0123456789'],
      +        // Don't treat escaped quotes in bash as starting strings.  See issue 144.
      +        [PR_PLAIN,       /^\\[\s\S]?/, null],
      +        [PR_PUNCTUATION, punctuation, null]);
      +
      +    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);
      +  }
      +
      +  var decorateSource = sourceDecorator({
      +        'keywords': ALL_KEYWORDS,
      +        'hashComments': true,
      +        'cStyleComments': true,
      +        'multiLineStrings': true,
      +        'regexLiterals': true
      +      });
      +
      +  include("numberLines.js");
      +
      +  include("recombineTagsAndDecorations.js");
      +
      +  /** Maps language-specific file extensions to handlers. */
      +  var langHandlerRegistry = {};
      +  /** Register a language handler for the given file extensions.
      +    * @param {function (Object)} handler a function from source code to a list
      +    *      of decorations.  Takes a single argument job which describes the
      +    *      state of the computation.   The single parameter has the form
      +    *      {@code {
      +    *        sourceCode: {string} as plain text.
      +    *        decorations: {Array.<number|string>} an array of style classes
      +    *                     preceded by the position at which they start in
      +    *                     job.sourceCode in order.
      +    *                     The language handler should assigned this field.
      +    *        basePos: {int} the position of source in the larger source chunk.
      +    *                 All positions in the output decorations array are relative
      +    *                 to the larger source chunk.
      +    *      } }
      +    * @param {Array.<string>} fileExtensions
      +    */
      +  function registerLangHandler(handler, fileExtensions) {
      +    for (var i = fileExtensions.length; --i >= 0;) {
      +      var ext = fileExtensions[i];
      +      if (!langHandlerRegistry.hasOwnProperty(ext)) {
      +        langHandlerRegistry[ext] = handler;
      +      } else if (win['console']) {
      +        console['warn']('cannot override language handler %s', ext);
      +      }
      +    }
      +  }
      +  function langHandlerForExtension(extension, source) {
      +    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {
      +      // Treat it as markup if the first non whitespace character is a < and
      +      // the last non-whitespace character is a >.
      +      extension = /^\s*</.test(source)
      +          ? 'default-markup'
      +          : 'default-code';
      +    }
      +    return langHandlerRegistry[extension];
      +  }
      +  registerLangHandler(decorateSource, ['default-code']);
      +  registerLangHandler(
      +      createSimpleLexer(
      +          [],
      +          [
      +           [PR_PLAIN,       /^[^<?]+/],
      +           [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/],
      +           [PR_COMMENT,     /^<\!--[\s\S]*?(?:-\->|$)/],
      +           // Unescaped content in an unknown language
      +           ['lang-',        /^<\?([\s\S]+?)(?:\?>|$)/],
      +           ['lang-',        /^<%([\s\S]+?)(?:%>|$)/],
      +           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],
      +           ['lang-',        /^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],
      +           // Unescaped content in javascript.  (Or possibly vbscript).
      +           ['lang-js',      /^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],
      +           // Contains unescaped stylesheet content
      +           ['lang-css',     /^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],
      +           ['lang-in.tag',  /^(<\/?[a-z][^<>]*>)/i]
      +          ]),
      +      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);
      +  registerLangHandler(
      +      createSimpleLexer(
      +          [
      +           [PR_PLAIN,        /^[\s]+/, null, ' \t\r\n'],
      +           [PR_ATTRIB_VALUE, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, '\"\'']
      +           ],
      +          [
      +           [PR_TAG,          /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],
      +           [PR_ATTRIB_NAME,  /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],
      +           ['lang-uq.val',   /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
      +           [PR_PUNCTUATION,  /^[=<>\/]+/],
      +           ['lang-js',       /^on\w+\s*=\s*\"([^\"]+)\"/i],
      +           ['lang-js',       /^on\w+\s*=\s*\'([^\']+)\'/i],
      +           ['lang-js',       /^on\w+\s*=\s*([^\"\'>\s]+)/i],
      +           ['lang-css',      /^style\s*=\s*\"([^\"]+)\"/i],
      +           ['lang-css',      /^style\s*=\s*\'([^\']+)\'/i],
      +           ['lang-css',      /^style\s*=\s*([^\"\'>\s]+)/i]
      +           ]),
      +      ['in.tag']);
      +  registerLangHandler(
      +      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\s\S]+/]]), ['uq.val']);
      +  registerLangHandler(sourceDecorator({
      +          'keywords': CPP_KEYWORDS,
      +          'hashComments': true,
      +          'cStyleComments': true,
      +          'types': C_TYPES
      +        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);
      +  registerLangHandler(sourceDecorator({
      +          'keywords': 'null,true,false'
      +        }), ['json']);
      +  registerLangHandler(sourceDecorator({
      +          'keywords': CSHARP_KEYWORDS,
      +          'hashComments': true,
      +          'cStyleComments': true,
      +          'verbatimStrings': true,
      +          'types': C_TYPES
      +        }), ['cs']);
      +  registerLangHandler(sourceDecorator({
      +          'keywords': JAVA_KEYWORDS,
      +          'cStyleComments': true
      +        }), ['java']);
      +  registerLangHandler(sourceDecorator({
      +          'keywords': SH_KEYWORDS,
      +          'hashComments': true,
      +          'multiLineStrings': true
      +        }), ['bash', 'bsh', 'csh', 'sh']);
      +  registerLangHandler(sourceDecorator({
      +          'keywords': PYTHON_KEYWORDS,
      +          'hashComments': true,
      +          'multiLineStrings': true,
      +          'tripleQuotedStrings': true
      +        }), ['cv', 'py', 'python']);
      +  registerLangHandler(sourceDecorator({
      +          'keywords': PERL_KEYWORDS,
      +          'hashComments': true,
      +          'multiLineStrings': true,
      +          'regexLiterals': true
      +        }), ['perl', 'pl', 'pm']);
      +  registerLangHandler(sourceDecorator({
      +          'keywords': RUBY_KEYWORDS,
      +          'hashComments': true,
      +          'multiLineStrings': true,
      +          'regexLiterals': true
      +        }), ['rb', 'ruby']);
      +  registerLangHandler(sourceDecorator({
      +          'keywords': JSCRIPT_KEYWORDS,
      +          'cStyleComments': true,
      +          'regexLiterals': true
      +        }), ['javascript', 'js']);
      +  registerLangHandler(sourceDecorator({
      +          'keywords': COFFEE_KEYWORDS,
      +          'hashComments': 3,  // ### style block comments
      +          'cStyleComments': true,
      +          'multilineStrings': true,
      +          'tripleQuotedStrings': true,
      +          'regexLiterals': true
      +        }), ['coffee']);
      +  registerLangHandler(sourceDecorator({
      +          'keywords': RUST_KEYWORDS,
      +          'cStyleComments': true,
      +          'multilineStrings': true
      +        }), ['rc', 'rs', 'rust']);
      +  registerLangHandler(
      +      createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
      +
      +  function applyDecorator(job) {
      +    var opt_langExtension = job.langExtension;
      +
      +    try {
      +      // Extract tags, and convert the source code to plain text.
      +      var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);
      +      /** Plain text. @type {string} */
      +      var source = sourceAndSpans.sourceCode;
      +      job.sourceCode = source;
      +      job.spans = sourceAndSpans.spans;
      +      job.basePos = 0;
      +
      +      // Apply the appropriate language handler
      +      langHandlerForExtension(opt_langExtension, source)(job);
      +
      +      // Integrate the decorations and tags back into the source code,
      +      // modifying the sourceNode in place.
      +      recombineTagsAndDecorations(job);
      +    } catch (e) {
      +      if (win['console']) {
      +        console['log'](e && e['stack'] || e);
      +      }
      +    }
      +  }
      +
      +  /**
      +   * Pretty print a chunk of code.
      +   * @param sourceCodeHtml {string} The HTML to pretty print.
      +   * @param opt_langExtension {string} The language name to use.
      +   *     Typically, a filename extension like 'cpp' or 'java'.
      +   * @param opt_numberLines {number|boolean} True to number lines,
      +   *     or the 1-indexed number of the first line in sourceCodeHtml.
      +   */
      +  function $prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {
      +    var container = document.createElement('div');
      +    // This could cause images to load and onload listeners to fire.
      +    // E.g. <img onerror="alert(1337)" src="nosuchimage.png">.
      +    // We assume that the inner HTML is from a trusted source.
      +    // The pre-tag is required for IE8 which strips newlines from innerHTML
      +    // when it is injected into a <pre> tag.
      +    // http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie
      +    // http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript
      +    container.innerHTML = '<pre>' + sourceCodeHtml + '</pre>';
      +    container = container.firstChild;
      +    if (opt_numberLines) {
      +      numberLines(container, opt_numberLines, true);
      +    }
      +
      +    var job = {
      +      langExtension: opt_langExtension,
      +      numberLines: opt_numberLines,
      +      sourceNode: container,
      +      pre: 1
      +    };
      +    applyDecorator(job);
      +    return container.innerHTML;
      +  }
      +
      +   /**
      +    * Find all the {@code <pre>} and {@code <code>} tags in the DOM with
      +    * {@code class=prettyprint} and prettify them.
      +    *
      +    * @param {Function} opt_whenDone called when prettifying is done.
      +    * @param {HTMLElement|HTMLDocument} opt_root an element or document
      +    *   containing all the elements to pretty print.
      +    *   Defaults to {@code document.body}.
      +    */
      +  function $prettyPrint(opt_whenDone, opt_root) {
      +    var root = opt_root || document.body;
      +    var doc = root.ownerDocument || document;
      +    function byTagName(tn) { return root.getElementsByTagName(tn); }
      +    // fetch a list of nodes to rewrite
      +    var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];
      +    var elements = [];
      +    for (var i = 0; i < codeSegments.length; ++i) {
      +      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {
      +        elements.push(codeSegments[i][j]);
      +      }
      +    }
      +    codeSegments = null;
      +
      +    var clock = Date;
      +    if (!clock['now']) {
      +      clock = { 'now': function () { return +(new Date); } };
      +    }
      +
      +    // The loop is broken into a series of continuations to make sure that we
      +    // don't make the browser unresponsive when rewriting a large page.
      +    var k = 0;
      +    var prettyPrintingJob;
      +
      +    var langExtensionRe = /\blang(?:uage)?-([\w.]+)(?!\S)/;
      +    var prettyPrintRe = /\bprettyprint\b/;
      +    var prettyPrintedRe = /\bprettyprinted\b/;
      +    var preformattedTagNameRe = /pre|xmp/i;
      +    var codeRe = /^code$/i;
      +    var preCodeXmpRe = /^(?:pre|code|xmp)$/i;
      +    var EMPTY = {};
      +
      +    function doWork() {
      +      var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?
      +                     clock['now']() + 250 /* ms */ :
      +                     Infinity);
      +      for (; k < elements.length && clock['now']() < endTime; k++) {
      +        var cs = elements[k];
      +
      +        // Look for a preceding comment like
      +        // <?prettify lang="..." linenums="..."?>
      +        var attrs = EMPTY;
      +        {
      +          for (var preceder = cs; (preceder = preceder.previousSibling);) {
      +            var nt = preceder.nodeType;
      +            // <?foo?> is parsed by HTML 5 to a comment node (8)
      +            // like <!--?foo?-->, but in XML is a processing instruction
      +            var value = (nt === 7 || nt === 8) && preceder.nodeValue;
      +            if (value
      +                ? !/^\??prettify\b/.test(value)
      +                : (nt !== 3 || /\S/.test(preceder.nodeValue))) {
      +              // Skip over white-space text nodes but not others.
      +              break;
      +            }
      +            if (value) {
      +              attrs = {};
      +              value.replace(
      +                  /\b(\w+)=([\w:.%+-]+)/g,
      +                function (_, name, value) { attrs[name] = value; });
      +              break;
      +            }
      +          }
      +        }
      +
      +        var className = cs.className;
      +        if ((attrs !== EMPTY || prettyPrintRe.test(className))
      +            // Don't redo this if we've already done it.
      +            // This allows recalling pretty print to just prettyprint elements
      +            // that have been added to the page since last call.
      +            && !prettyPrintedRe.test(className)) {
      +
      +          // make sure this is not nested in an already prettified element
      +          var nested = false;
      +          for (var p = cs.parentNode; p; p = p.parentNode) {
      +            var tn = p.tagName;
      +            if (preCodeXmpRe.test(tn)
      +                && p.className && prettyPrintRe.test(p.className)) {
      +              nested = true;
      +              break;
      +            }
      +          }
      +          if (!nested) {
      +            // Mark done.  If we fail to prettyprint for whatever reason,
      +            // we shouldn't try again.
      +            cs.className += ' prettyprinted';
      +
      +            // If the classes includes a language extensions, use it.
      +            // Language extensions can be specified like
      +            //     <pre class="prettyprint lang-cpp">
      +            // the language extension "cpp" is used to find a language handler
      +            // as passed to PR.registerLangHandler.
      +            // HTML5 recommends that a language be specified using "language-"
      +            // as the prefix instead.  Google Code Prettify supports both.
      +            // http://dev.w3.org/html5/spec-author-view/the-code-element.html
      +            var langExtension = attrs['lang'];
      +            if (!langExtension) {
      +              langExtension = className.match(langExtensionRe);
      +              // Support <pre class="prettyprint"><code class="language-c">
      +              var wrapper;
      +              if (!langExtension && (wrapper = childContentWrapper(cs))
      +                  && codeRe.test(wrapper.tagName)) {
      +                langExtension = wrapper.className.match(langExtensionRe);
      +              }
      +
      +              if (langExtension) { langExtension = langExtension[1]; }
      +            }
      +
      +            var preformatted;
      +            if (preformattedTagNameRe.test(cs.tagName)) {
      +              preformatted = 1;
      +            } else {
      +              var currentStyle = cs['currentStyle'];
      +              var defaultView = doc.defaultView;
      +              var whitespace = (
      +                  currentStyle
      +                  ? currentStyle['whiteSpace']
      +                  : (defaultView
      +                     && defaultView.getComputedStyle)
      +                  ? defaultView.getComputedStyle(cs, null)
      +                  .getPropertyValue('white-space')
      +                  : 0);
      +              preformatted = whitespace
      +                  && 'pre' === whitespace.substring(0, 3);
      +            }
      +
      +            // Look for a class like linenums or linenums:<n> where <n> is the
      +            // 1-indexed number of the first line.
      +            var lineNums = attrs['linenums'];
      +            if (!(lineNums = lineNums === 'true' || +lineNums)) {
      +              lineNums = className.match(/\blinenums\b(?::(\d+))?/);
      +              lineNums =
      +                lineNums
      +                ? lineNums[1] && lineNums[1].length
      +                  ? +lineNums[1] : true
      +                : false;
      +            }
      +            if (lineNums) { numberLines(cs, lineNums, preformatted); }
      +
      +            // do the pretty printing
      +            prettyPrintingJob = {
      +              langExtension: langExtension,
      +              sourceNode: cs,
      +              numberLines: lineNums,
      +              pre: preformatted
      +            };
      +            applyDecorator(prettyPrintingJob);
      +          }
      +        }
      +      }
      +      if (k < elements.length) {
      +        // finish up in a continuation
      +        setTimeout(doWork, 250);
      +      } else if ('function' === typeof opt_whenDone) {
      +        opt_whenDone();
      +      }
      +    }
      +
      +    doWork();
      +  }
      +
      +  /**
      +   * Contains functions for creating and registering new language handlers.
      +   * @type {Object}
      +   */
      +  var PR = win['PR'] = {
      +        'createSimpleLexer': createSimpleLexer,
      +        'registerLangHandler': registerLangHandler,
      +        'sourceDecorator': sourceDecorator,
      +        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,
      +        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,
      +        'PR_COMMENT': PR_COMMENT,
      +        'PR_DECLARATION': PR_DECLARATION,
      +        'PR_KEYWORD': PR_KEYWORD,
      +        'PR_LITERAL': PR_LITERAL,
      +        'PR_NOCODE': PR_NOCODE,
      +        'PR_PLAIN': PR_PLAIN,
      +        'PR_PUNCTUATION': PR_PUNCTUATION,
      +        'PR_SOURCE': PR_SOURCE,
      +        'PR_STRING': PR_STRING,
      +        'PR_TAG': PR_TAG,
      +        'PR_TYPE': PR_TYPE,
      +        'prettyPrintOne':
      +           IN_GLOBAL_SCOPE
      +             ? (win['prettyPrintOne'] = $prettyPrintOne)
      +             : (prettyPrintOne = $prettyPrintOne),
      +        'prettyPrint': prettyPrint =
      +           IN_GLOBAL_SCOPE
      +             ? (win['prettyPrint'] = $prettyPrint)
      +             : (prettyPrint = $prettyPrint)
      +      };
      +
      +  // Make PR available via the Asynchronous Module Definition (AMD) API.
      +  // Per https://github.com/amdjs/amdjs-api/wiki/AMD:
      +  // The Asynchronous Module Definition (AMD) API specifies a
      +  // mechanism for defining modules such that the module and its
      +  // dependencies can be asynchronously loaded.
      +  // ...
      +  // To allow a clear indicator that a global define function (as
      +  // needed for script src browser loading) conforms to the AMD API,
      +  // any global define function SHOULD have a property called "amd"
      +  // whose value is an object. This helps avoid conflict with any
      +  // other existing JavaScript code that could have defined a define()
      +  // function that does not conform to the AMD API.
      +  if (typeof define === "function" && define['amd']) {
      +    define("google-code-prettify", [], function () {
      +      return PR; 
      +    });
      +  }
      +})();
      diff --git a/assets/js/dev/vendors/scrollify.js b/assets/js/dev/vendors/scrollify.js
      new file mode 100644
      index 0000000..84ac69b
      --- /dev/null
      +++ b/assets/js/dev/vendors/scrollify.js
      @@ -0,0 +1,971 @@
      +/*!
      + * jQuery Scrollify
      + * Version 1.0.19 - L662:L664 modified by themezly https://github.com/lukehaas/Scrollify/issues/330
      + * added settings.delay .delay(settings.delay)
      + *
      + * Requires:
      + * - jQuery 1.7 or higher
      + *
      + * https://github.com/lukehaas/Scrollify
      + *
      + * Copyright 2016, Luke Haas
      + * Permission is hereby granted, free of charge, to any person obtaining a copy of
      + * this software and associated documentation files (the "Software"), to deal in
      + * the Software without restriction, including without limitation the rights to
      + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
      + * the Software, and to permit persons to whom the Software is furnished to do so,
      + * subject to the following conditions:
      + *
      + * The above copyright notice and this permission notice shall be included in all
      + * copies or substantial portions of the Software.
      + *
      + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
      + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
      + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
      + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
      + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      +
      +
      +
      +if touchScroll is false - update index
      +
      + */
      +(function (global,factory) {
      +  "use strict";
      +  if (typeof define === 'function' && define.amd) {
      +    // AMD. Register as an anonymous module.
      +    define(['jquery'], function($) {
      +      return factory($, global, global.document);
      +    });
      +  } else if (typeof module === 'object' && module.exports) {
      +    // Node/CommonJS
      +    module.exports = factory(require('jquery'), global, global.document);
      +  } else {
      +    // Browser globals
      +    factory(jQuery, global, global.document);
      +  }
      +}(typeof window !== 'undefined' ? window : this, function ($, window, document, undefined) {
      +  "use strict";
      +  var heights = [],
      +    names = [],
      +    elements = [],
      +    overflow = [],
      +    index = 0,
      +    currentIndex = 0,
      +    interstitialIndex = 1,
      +    hasLocation = false,
      +    timeoutId,
      +    timeoutId2,
      +    $window = $(window),
      +    portHeight,
      +    top = $window.scrollTop(),
      +    scrollable = false,
      +    locked = false,
      +    scrolled = false,
      +    manualScroll,
      +    swipeScroll,
      +    util,
      +    disabled = false,
      +    scrollSamples = [],
      +    scrollTime = new Date().getTime(),
      +    firstLoad = true,
      +    initialised = false,
      +    destination = 0,
      +    wheelEvent = 'onwheel' in document ? 'wheel' : document.onmousewheel !== undefined ? 'mousewheel' : 'DOMMouseScroll',
      +    settings = {
      +      //section should be an identifier that is the same for each section
      +      section: ".section",
      +      sectionName: "section-name",
      +      interstitialSection: "",
      +      easing: "easeOutExpo",
      +      scrollSpeed: 1100,
      +      offset: 0,
      +      scrollbars: true,
      +      target:"html,body",
      +      standardScrollElements: false,
      +      setHeights: true,
      +      overflowScroll:true,
      +      updateHash: true,
      +      touchScroll:true,
      +	  delay:0,
      +      before:function() {},
      +      after:function() {},
      +      afterResize:function() {},
      +      afterRender:function() {}
      +    };
      +  function getportHeight() {
      +    return ($window.height() + settings.offset);
      +  }
      +  function animateScroll(index,instant,callbacks,toTop) {
      +    if(currentIndex===index) {
      +      callbacks = false;
      +    }
      +    if(disabled===true) {
      +      return true;
      +    }
      +    if(names[index]) {
      +      scrollable = false;
      +      if(firstLoad===true) {
      +        settings.afterRender();
      +        firstLoad = false;
      +      }
      +      if(callbacks) {
      +        if( typeof settings.before == 'function' && settings.before(index,elements) === false ){
      +          return true;
      +        }
      +      }
      +      interstitialIndex = 1;
      +      destination = heights[index];
      +      if(firstLoad===false && currentIndex>index && toTop===false) {
      +        //We're going backwards
      +        if(overflow[index]) {
      +          portHeight = getportHeight();
      +
      +          interstitialIndex = parseInt(elements[index].outerHeight()/portHeight);
      +
      +          destination = parseInt(heights[index])+(elements[index].outerHeight()-portHeight);
      +        }
      +      }
      +
      +
      +      if(settings.updateHash && settings.sectionName && !(firstLoad===true && index===0)) {
      +        if(history.pushState) {
      +            try {
      +              history.replaceState(null, null, names[index]);
      +            } catch (e) {
      +              if(window.console) {
      +                console.warn("Scrollify warning: Page must be hosted to manipulate the hash value.");
      +              }
      +            }
      +
      +        } else {
      +          window.location.hash = names[index];
      +        }
      +      }
      +
      +      currentIndex = index;
      +      if(instant) {
      +        $(settings.target).stop().scrollTop(destination);
      +        if(callbacks) {
      +          settings.after(index,elements);
      +        }
      +      } else {
      +        locked = true;
      +        if( $().velocity ) {
      +          $(settings.target).stop().delay(settings.delay).velocity('scroll', {
      +            duration: settings.scrollSpeed,
      +            easing: settings.easing,
      +            offset: destination,
      +            mobileHA: false
      +          });
      +        } else {
      +			
      +          $(settings.target).stop().delay(settings.delay).animate({
      +            scrollTop: destination
      +          }, settings.scrollSpeed,settings.easing);
      +        }
      +
      +/*        if(window.location.hash.length && settings.sectionName && window.console) {
      +          try {
      +            if($(window.location.hash).length) {
      +              console.warn("Scrollify warning: ID matches hash value - this will cause the page to anchor.");
      +            }
      +          } catch (e) {}
      +        }*/
      +		
      +/*		if( overScroll(index,elements,true) ){
      +			return false;
      +		}*/
      +//		console.log(index,currentIndex);
      +/*		if( settings.overflowScroll && ( elements[index].find('> div').outerHeight() > getportHeight() ) ){
      +			
      +			var $over = $(elements[index]).attr('id');
      +				
      +			var overScroll = new IScroll('#'+ $over, {
      +				scrollbars: true,
      +				mouseWheel: true,
      +				interactiveScrollbars: true,
      +				shrinkScrollbars: 'scale',
      +				fadeScrollbars: true,
      +				scrollbars:'custom',
      +				probeType:2,
      +
      +			});	
      +
      +			overScroll.on('scroll', function(){
      +				
      +				if( this.y == 0 || this.maxScrollY == this.y){
      +					$(settings.target).promise().done(function(){
      +					  locked = false;
      +					  firstLoad = false;
      +					  
      +					  if(overScroll){
      +						overScroll.destroy();
      +						overScroll = null;
      +					  }
      +					  
      +					  if(callbacks) {
      +						settings.after(index,elements);
      +					  }
      +					});					
      +				}
      +			});
      +			
      +			return;
      +			
      +		}*/
      +		
      +        $(settings.target).promise().done(function(){
      +          locked = false;
      +          firstLoad = false;
      +          if(callbacks) {
      +            settings.after(index,elements);
      +          }
      +        });
      +      }
      +
      +    }
      +  }
      +  
      +  
      +  
      +  function overScrollAnimate(index, instant, callbacks, toTop, direction){
      +	  
      +	  
      +	   if( direction == undefined ){
      +		   animateScroll(index, instant, callbacks, toTop);
      +	   }
      +
      +		var $prev  		= $.scrollify.current().prev('.thz-full-page-row');
      +		var $next  		= $.scrollify.current().next('.thz-full-page-row');
      +		var $elm 		= direction == 'down' ? $prev : $next;
      +		
      +		
      +		if($elm.length < 1){
      +			animateScroll(index, instant, callbacks, toTop);
      +		}
      +
      +		if( settings.overflowScroll && ( $elm.find('> div').outerHeight() > getportHeight() ) ){
      +			
      +			var $over = $elm.attr('id');
      +			
      +			var overScroll = new IScroll('#'+ $over, {
      +				mouseWheel: true,
      +				interactiveScrollbars: true,
      +				shrinkScrollbars: 'scale',
      +				fadeScrollbars: true,
      +				scrollbars:'custom',
      +				probeType:2,
      +				keyBindings: true
      +			});	
      +
      +			overScroll.on('scroll', function(){
      +				
      +				if( this.y == 0 || this.maxScrollY == this.y){
      +				
      +					if(overScroll){
      +						overScroll.destroy();
      +						overScroll = null;
      +					}
      +					
      +					animateScroll(index, instant, callbacks, toTop);	
      +					
      +					setTimeout(function (){
      +						$elm.find('.thz-section-holder').css({
      +							'transform' : '',
      +						});
      +					},settings.scrollSpeed);				  
      +				
      +						
      +				}
      +			});
      +			
      +		}else{
      +			
      +			animateScroll(index, instant, callbacks, toTop);
      +			
      +		}
      +	
      +  }
      +
      +  function isAccelerating(samples) {
      +    function average(num) {
      +      var sum = 0;
      +
      +      var lastElements = samples.slice(Math.max(samples.length - num, 1));
      +
      +      for(var i = 0; i < lastElements.length; i++){
      +          sum += lastElements[i];
      +      }
      +
      +      return Math.ceil(sum/num);
      +    }
      +
      +    var avEnd = average(10);
      +    var avMiddle = average(70);
      +
      +    if(avEnd >= avMiddle) {
      +      return true;
      +    } else {
      +      return false;
      +    }
      +  }
      +  var scrollify = function(options) {
      +    initialised = true;
      +    $.easing['easeOutExpo'] = function(x, t, b, c, d) {
      +      return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
      +    };
      +
      +    manualScroll = {
      +      handleMousedown:function() {
      +        if(disabled===true) {
      +          return true;
      +        }
      +        scrollable = false;
      +        scrolled = false;
      +      },
      +      handleMouseup:function() {
      +        if(disabled===true) {
      +          return true;
      +        }
      +        scrollable = true;
      +        if(scrolled) {
      +          //instant,callbacks
      +          manualScroll.calculateNearest(false,true);
      +        }
      +      },
      +      handleScroll:function() {
      +        if(disabled===true) {
      +          return true;
      +        }
      +        if(timeoutId){
      +          clearTimeout(timeoutId);
      +        }
      +
      +        timeoutId = setTimeout(function(){
      +          scrolled = true;
      +          if(scrollable===false) {
      +            return false;
      +          }
      +          scrollable = false;
      +          //instant,callbacks
      +          manualScroll.calculateNearest(false,true);
      +        }, 200);
      +      },
      +      calculateNearest:function(instant,callbacks) {
      +        top = $window.scrollTop();
      +        var i =1,
      +          max = heights.length,
      +          closest = 0,
      +          prev = Math.abs(heights[0] - top),
      +          diff;
      +        for(;i<max;i++) {
      +          diff = Math.abs(heights[i] - top);
      +
      +          if(diff < prev) {
      +            prev = diff;
      +            closest = i;
      +          }
      +        }
      +        if((atBottom() && closest>index) || atTop()) {
      +          index = closest;
      +          //index, instant, callbacks, toTop
      +          overScrollAnimate(closest,instant,callbacks,false);
      +        }
      +      },
      +      wheelHandler:function(e) {
      +		  
      +        if(disabled===true) {
      +          return true;
      +        } else if(settings.standardScrollElements) {
      +          if($(e.target).is(settings.standardScrollElements) || $(e.target).closest(settings.standardScrollElements).length) {
      +            return true;
      +          }
      +        }
      +        if(!overflow[index]) {
      +          e.preventDefault();
      +        }
      +        var currentScrollTime = new Date().getTime();
      +
      +
      +        e = e || window.event;
      +        var value = e.originalEvent.wheelDelta || -e.originalEvent.deltaY || -e.originalEvent.detail;
      +        var delta = Math.max(-1, Math.min(1, value));
      +
      +        //delta = delta || -e.originalEvent.detail / 3 || e.originalEvent.wheelDelta / 120;
      +
      +        if(scrollSamples.length > 149){
      +          scrollSamples.shift();
      +        }
      +        //scrollSamples.push(Math.abs(delta*10));
      +        scrollSamples.push(Math.abs(value));
      +
      +        if((currentScrollTime-scrollTime) > 200){
      +          scrollSamples = [];
      +        }
      +        scrollTime = currentScrollTime;
      +
      +
      +        if(locked) {
      +          return false;
      +        }
      +        if(delta<0) {
      +          if(index<heights.length-1) {
      +            if(atBottom()) {
      +              if(isAccelerating(scrollSamples)) {
      +                e.preventDefault();
      +                index++;
      +                locked = true;
      +                //index, instant, callbacks, toTop
      +               // animateScroll(index,false,true, false);
      +				overScrollAnimate(index,false,true, false,'down');
      +              } else {
      +                return false;
      +              }
      +            }
      +          }
      +        } else if(delta>0) {
      +          if(index>0) {
      +            if(atTop()) {
      +              if(isAccelerating(scrollSamples)) {
      +                e.preventDefault();
      +                index--;
      +                locked = true;
      +                //index, instant, callbacks, toTop
      +               // animateScroll(index,false,true, false);
      +			   overScrollAnimate(index,false,true, false,'up');
      +              } else {
      +                return false
      +              }
      +            }
      +          }
      +        }
      +
      +      },
      +      keyHandler:function(e) {
      +        if(disabled===true || document.activeElement.readOnly===false) {
      +          return true;
      +        } else if(settings.standardScrollElements) {
      +          if($(e.target).is(settings.standardScrollElements) || $(e.target).closest(settings.standardScrollElements).length) {
      +            return true;
      +          }
      +        }
      +        if(locked===true) {
      +          return false;
      +        }
      +        if(e.keyCode==38 || e.keyCode==33) {
      +          if(index>0) {
      +            if(atTop()) {
      +              e.preventDefault();
      +              index--;
      +              //index, instant, callbacks, toTop
      +              overScrollAnimate(index,false,true,false,'up');
      +            }
      +          }
      +        } else if(e.keyCode==40 || e.keyCode==34) {
      +          if(index<heights.length-1) {
      +            if(atBottom()) {
      +              e.preventDefault();
      +              index++;
      +              //index, instant, callbacks, toTop
      +              overScrollAnimate(index,false,true,false,'down');
      +            }
      +          }
      +        }
      +      },
      +      init:function() {
      +        if(settings.scrollbars) {
      +          $window.on('mousedown', manualScroll.handleMousedown);
      +          $window.on('mouseup', manualScroll.handleMouseup);
      +          $window.on('scroll', manualScroll.handleScroll);
      +        } else {
      +          $("body").css({"overflow":"hidden"});
      +        }
      +        $window.on(wheelEvent,manualScroll.wheelHandler);
      +        //$(document).bind(wheelEvent,manualScroll.wheelHandler);
      +        $window.on('keydown', manualScroll.keyHandler);
      +      }
      +    };
      +
      +    swipeScroll = {
      +      touches : {
      +        "touchstart": {"y":-1,"x":-1},
      +        "touchmove" : {"y":-1,"x":-1},
      +        "touchend"  : false,
      +        "direction" : "undetermined"
      +      },
      +      options:{
      +        "distance" : 30,
      +        "timeGap" : 800,
      +        "timeStamp" : new Date().getTime()
      +      },
      +      touchHandler: function(event) {
      +        if(disabled===true) {
      +          return true;
      +        } else if(settings.standardScrollElements) {
      +          if($(event.target).is(settings.standardScrollElements) || $(event.target).closest(settings.standardScrollElements).length) {
      +            return true;
      +          }
      +        }
      +        var touch;
      +        if (typeof event !== 'undefined'){
      +          if (typeof event.touches !== 'undefined') {
      +            touch = event.touches[0];
      +            switch (event.type) {
      +              case 'touchstart':
      +                swipeScroll.touches.touchstart.y = touch.pageY;
      +                swipeScroll.touches.touchmove.y = -1;
      +
      +                swipeScroll.touches.touchstart.x = touch.pageX;
      +                swipeScroll.touches.touchmove.x = -1;
      +
      +                swipeScroll.options.timeStamp = new Date().getTime();
      +                swipeScroll.touches.touchend = false;
      +              case 'touchmove':
      +                swipeScroll.touches.touchmove.y = touch.pageY;
      +                swipeScroll.touches.touchmove.x = touch.pageX;
      +                if(swipeScroll.touches.touchstart.y!==swipeScroll.touches.touchmove.y && (Math.abs(swipeScroll.touches.touchstart.y-swipeScroll.touches.touchmove.y)>Math.abs(swipeScroll.touches.touchstart.x-swipeScroll.touches.touchmove.x))) {
      +                  //if(!overflow[index]) {
      +                    event.preventDefault();
      +                  //}
      +                  swipeScroll.touches.direction = "y";
      +                  if((swipeScroll.options.timeStamp+swipeScroll.options.timeGap)<(new Date().getTime()) && swipeScroll.touches.touchend == false) {
      +
      +                    swipeScroll.touches.touchend = true;
      +                    if (swipeScroll.touches.touchstart.y > -1) {
      +
      +                      if(Math.abs(swipeScroll.touches.touchmove.y-swipeScroll.touches.touchstart.y)>swipeScroll.options.distance) {
      +                        if(swipeScroll.touches.touchstart.y < swipeScroll.touches.touchmove.y) {
      +
      +                          swipeScroll.up();
      +
      +                        } else {
      +                          swipeScroll.down();
      +
      +                        }
      +                      }
      +                    }
      +                  }
      +                }
      +                break;
      +              case 'touchend':
      +                if(swipeScroll.touches[event.type]===false) {
      +                  swipeScroll.touches[event.type] = true;
      +                  if (swipeScroll.touches.touchstart.y > -1 && swipeScroll.touches.touchmove.y > -1 && swipeScroll.touches.direction==="y") {
      +
      +                    if(Math.abs(swipeScroll.touches.touchmove.y-swipeScroll.touches.touchstart.y)>swipeScroll.options.distance) {
      +                      if(swipeScroll.touches.touchstart.y < swipeScroll.touches.touchmove.y) {
      +                        swipeScroll.up();
      +
      +                      } else {
      +                        swipeScroll.down();
      +
      +                      }
      +                    }
      +                    swipeScroll.touches.touchstart.y = -1;
      +                    swipeScroll.touches.touchstart.x = -1;
      +                    swipeScroll.touches.direction = "undetermined";
      +                  }
      +                }
      +              default:
      +                break;
      +            }
      +          }
      +        }
      +      },
      +      down: function() {
      +
      +        if(index<heights.length) {
      +
      +          if(atBottom() && index<heights.length-1) {
      +
      +            index++;
      +            //index, instant, callbacks, toTop
      +            overScrollAnimate(index,false,true,false,'down');
      +          } else {
      +            portHeight = getportHeight();
      +            if(Math.floor(elements[index].height()/portHeight)>interstitialIndex) {
      +
      +              interstitialScroll(parseInt(heights[index])+(portHeight*interstitialIndex));
      +              interstitialIndex += 1;
      +
      +            } else {
      +              interstitialScroll(parseInt(heights[index])+(elements[index].outerHeight()-portHeight));
      +            }
      +
      +          }
      +        }
      +      },
      +      up: function() {
      +        if(index>=0) {
      +          if(atTop() && index>0) {
      +
      +            index--;
      +            //index, instant, callbacks, toTop
      +            overScrollAnimate(index,false,true,false,'up');
      +          } else {
      +
      +            if(interstitialIndex>2) {
      +              portHeight = getportHeight();
      +
      +              interstitialIndex -= 1;
      +              interstitialScroll(parseInt(heights[index])+(portHeight*interstitialIndex));
      +
      +            } else {
      +
      +              interstitialIndex = 1;
      +              interstitialScroll(parseInt(heights[index]));
      +            }
      +          }
      +
      +        }
      +      },
      +      init: function() {
      +        if (document.addEventListener && settings.touchScroll) {
      +          var eventListenerOptions = {
      +            passive: false
      +          };
      +          document.addEventListener('touchstart', swipeScroll.touchHandler, eventListenerOptions);
      +          document.addEventListener('touchmove', swipeScroll.touchHandler, eventListenerOptions);
      +          document.addEventListener('touchend', swipeScroll.touchHandler, eventListenerOptions);
      +        }
      +      }
      +    };
      +
      +
      +    util = {
      +      refresh:function(withCallback,scroll) {
      +        clearTimeout(timeoutId2);
      +        timeoutId2 = setTimeout(function() {
      +          //retain position
      +          sizePanels(true);
      +          //scroll, firstLoad
      +          calculatePositions(scroll,false);
      +          if(withCallback) {
      +              settings.afterResize();
      +          }
      +        },400);
      +      },
      +      handleUpdate:function() {
      +        //callbacks, scroll
      +        //changed from false,true to false,false
      +        util.refresh(false,false);
      +      },
      +      handleResize:function() {
      +        //callbacks, scroll
      +        util.refresh(true,false);
      +      },
      +      handleOrientation:function() {
      +        //callbacks, scroll
      +        util.refresh(true,true);
      +      }
      +    };
      +    settings = $.extend(settings, options);
      +
      +    //retain position
      +    sizePanels(false);
      +
      +    calculatePositions(false,true);
      +
      +    if(true===hasLocation) {
      +      //index, instant, callbacks, toTop
      +      overScrollAnimate(index,false,true,true);
      +    } else {
      +      setTimeout(function() {
      +        //instant,callbacks
      +        manualScroll.calculateNearest(true,false);
      +      },200);
      +    }
      +    if(heights.length) {
      +      manualScroll.init();
      +      swipeScroll.init();
      +
      +      $window.on("resize",util.handleResize);
      +      if (document.addEventListener) {
      +        window.addEventListener("orientationchange", util.handleOrientation, false);
      +      }
      +    }
      +    function interstitialScroll(pos) {
      +      if( $().velocity ) {
      +        $(settings.target).stop().velocity('scroll', {
      +          duration: settings.scrollSpeed,
      +          easing: settings.easing,
      +          offset: pos,
      +          mobileHA: false
      +        });
      +      } else {
      +        $(settings.target).stop().animate({
      +          scrollTop: pos
      +        }, settings.scrollSpeed,settings.easing);
      +      }
      +    }
      +
      +    function sizePanels(keepPosition) {
      +      if(keepPosition) {
      +        top = $window.scrollTop();
      +      }
      +
      +      var selector = settings.section;
      +      overflow = [];
      +      if(settings.interstitialSection.length) {
      +        selector += "," + settings.interstitialSection;
      +      }
      +      if(settings.scrollbars===false) {
      +       // settings.overflowScroll = false;
      +      }
      +      portHeight = getportHeight();
      +      $(selector).each(function(i) {
      +        var $this = $(this);
      +
      +        if(settings.setHeights) {
      +          if($this.is(settings.interstitialSection)) {
      +            overflow[i] = false;
      +          } else {
      +            if(($this.css("height","auto").outerHeight()<portHeight) || $this.css("overflow")==="hidden") {
      +              $this.css({"height":portHeight});
      +
      +              overflow[i] = false;
      +            } else {
      +
      +              $this.css({"height":$this.height()});
      +
      +              if(settings.overflowScroll) {
      +                overflow[i] = true;
      +              } else {
      +                overflow[i] = false;
      +              }
      +            }
      +
      +          }
      +
      +        } else {
      +
      +          if(($this.outerHeight()<portHeight) || (settings.overflowScroll===false)) {
      +            overflow[i] = false;
      +          } else {
      +            overflow[i] = true;
      +          }
      +        }
      +      });
      +      if(keepPosition) {
      +        $window.scrollTop(top);
      +      }
      +    }
      +    function calculatePositions(scroll,firstLoad) {
      +      var selector = settings.section;
      +      if(settings.interstitialSection.length) {
      +        selector += "," + settings.interstitialSection;
      +      }
      +      heights = [];
      +      names = [];
      +      elements = [];
      +      $(selector).each(function(i){
      +          var $this = $(this);
      +          if(i>0) {
      +            
      +			heights[i] = parseInt($this.offset().top) + settings.offset;
      +			
      +          } else {
      +			  
      +            //themezly
      +			var $htmlspace = parseInt($('html').css('margin-top'));
      +			
      +		    heights[i] = parseInt($this.offset().top - $htmlspace);
      +
      +			
      +          }
      +          if(settings.sectionName && $this.data(settings.sectionName)) {
      +            names[i] = "#" + $this.data(settings.sectionName).toString().replace(/ /g,"-");
      +          } else {
      +            if($this.is(settings.interstitialSection)===false) {
      +              names[i] = "#" + (i + 1);
      +            } else {
      +              names[i] = "#";
      +              if(i===$(selector).length-1 && i>1) {
      +                heights[i] = heights[i-1] + (parseInt($($(selector)[i-1]).outerHeight()) - parseInt($(window).height())) + parseInt($this.outerHeight());
      +              }
      +            }
      +          }
      +          elements[i] = $this;
      +          try {
      +            if($(names[i]).length && window.console) {
      +              console.warn("Scrollify warning: Section names can't match IDs - this will cause the browser to anchor.");
      +            }
      +          } catch (e) {}
      +
      +          if(window.location.hash===names[i]) {
      +            index = i;
      +            hasLocation = true;
      +          }
      +
      +      });
      +
      +      if(true===scroll) {
      +        //index, instant, callbacks, toTop
      +        overScrollAnimate(index,false,false,false);
      +      }
      +    }
      +
      +    function atTop() {
      +      if(!overflow[index]) {
      +        return true;
      +      }
      +      top = $window.scrollTop();
      +      if(top>parseInt(heights[index])) {
      +        return false;
      +      } else {
      +        return true;
      +      }
      +    }
      +    function atBottom() {
      +      if(!overflow[index]) {
      +        return true;
      +      }
      +      top = $window.scrollTop();
      +      portHeight = getportHeight() + 32;
      +
      +      if(top<parseInt(heights[index])+(elements[index].outerHeight()-portHeight)-28) {
      +
      +        return false;
      +
      +      } else {
      +        return true;
      +      }
      +    }
      +  }
      +
      +  function move(panel,instant) {
      +    var z = names.length;
      +	var current = scrollify.currentIndex();
      +
      +    for(;z>=0;z--) {
      +      if(typeof panel === 'string') {
      +		  
      +        if (names[z]===panel) {
      +          index = z;
      +		  var direction = index > current ? 'down' :'up';
      +          //index, instant, callbacks, toTop
      +          overScrollAnimate(z,instant,true,true,direction);
      +        }
      +      } else {
      +        if(z===panel) {
      +          index = z;
      +		  var direction = index > current ? 'down' :'up';
      +          //index, instant, callbacks, toTop
      +          overScrollAnimate(z,instant,true,true,direction);
      +        }
      +      }
      +    }
      +  }
      +  
      +  scrollify.move = function(panel) {
      +    if(panel===undefined) {
      +      return false;
      +    }
      +    if(panel.originalEvent) {
      +      panel = $(this).attr("href");
      +    }
      +    move(panel,false);
      +  };
      +  scrollify.instantMove = function(panel) {
      +    if(panel===undefined) {
      +      return false;
      +    }
      +    move(panel,true);
      +  };
      +  scrollify.next = function() {
      +    if(index<names.length) {
      +      index += 1;
      +      //index, instant, callbacks, toTop
      +      overScrollAnimate(index,false,true,true);
      +    }
      +  };
      +  scrollify.previous = function() {
      +    if(index>0) {
      +      index -= 1;
      +      //index, instant, callbacks, toTop
      +      overScrollAnimate(index,false,true,true);
      +    }
      +  };
      +  scrollify.instantNext = function() {
      +    if(index<names.length) {
      +      index += 1;
      +      //index, instant, callbacks, toTop
      +      overScrollAnimate(index,true,true,true);
      +    }
      +  };
      +  scrollify.instantPrevious = function() {
      +    if(index>0) {
      +      index -= 1;
      +      //index, instant, callbacks, toTop
      +      overScrollAnimate(index,true,true,true);
      +    }
      +  };
      +  scrollify.destroy = function() {
      +    if(!initialised) {
      +      return false;
      +    }
      +    if(settings.setHeights) {
      +      $(settings.section).each(function() {
      +        $(this).css("height","auto");
      +      });
      +    }
      +    $window.off("resize",util.handleResize);
      +    if(settings.scrollbars) {
      +      $window.off('mousedown', manualScroll.handleMousedown);
      +      $window.off('mouseup', manualScroll.handleMouseup);
      +      $window.off('scroll', manualScroll.handleScroll);
      +    }
      +    $window.off(wheelEvent,manualScroll.wheelHandler);
      +    $window.off('keydown', manualScroll.keyHandler);
      +
      +    if (document.addEventListener && settings.touchScroll) {
      +      document.removeEventListener('touchstart', swipeScroll.touchHandler, false);
      +      document.removeEventListener('touchmove', swipeScroll.touchHandler, false);
      +      document.removeEventListener('touchend', swipeScroll.touchHandler, false);
      +    }
      +    heights = [];
      +    names = [];
      +    elements = [];
      +    overflow = [];
      +  };
      +  scrollify.update = function() {
      +    if(!initialised) {
      +      return false;
      +    }
      +    util.handleUpdate();
      +  };
      +  scrollify.current = function() {
      +    return elements[index];
      +  };
      +  scrollify.currentIndex = function() {
      +    return index;
      +  };
      +  scrollify.disable = function() {
      +    disabled = true;
      +  };
      +  scrollify.enable = function() {
      +    disabled = false;
      +    if (initialised) {
      +      //instant,callbacks
      +      manualScroll.calculateNearest(false,false);
      +    }
      +  };
      +  scrollify.isDisabled = function() {
      +    return disabled;
      +  };
      +  scrollify.setOptions = function(updatedOptions) {
      +    if(!initialised) {
      +      return false;
      +    }
      +    if(typeof updatedOptions === "object") {
      +      settings = $.extend(settings, updatedOptions);
      +      util.handleUpdate();
      +    } else if(window.console) {
      +      console.warn("Scrollify warning: setOptions expects an object.");
      +    }
      +  };
      +  $.scrollify = scrollify;
      +  return scrollify;
      +}));
      \ No newline at end of file
      diff --git a/assets/js/dev/vendors/slick.js b/assets/js/dev/vendors/slick.js
      new file mode 100644
      index 0000000..19b337b
      --- /dev/null
      +++ b/assets/js/dev/vendors/slick.js
      @@ -0,0 +1,3314 @@
      +/*
      +     _ _      _       _
      + ___| (_) ___| | __  (_)___
      +/ __| | |/ __| |/ /  | / __|
      +\__ \ | | (__|   < _ | \__ \
      +|___/_|_|\___|_|\_(_)/ |___/
      +                   |__/
      +
      + Version: 1.8.1
      +  Author: Ken Wheeler
      + Website: http://kenwheeler.github.io
      +    Docs: http://kenwheeler.github.io/slick
      +    Repo: http://github.com/kenwheeler/slick
      +  Issues: http://github.com/kenwheeler/slick/issues
      +  thz_modifications 0.02: 
      +  custom setDimensions  https://github.com/kenwheeler/slick/issues/2167,
      +  custom swipeDirection,https://github.com/kenwheeler/slick/pull/2719
      +  custom getLeft https://github.com/kenwheeler/slick/pull/2719
      +  removed id removal from setupInfinite
      + */
      +/* global window, document, define, jQuery, setInterval, clearInterval */
      +;(function(factory) {
      +    'use strict';
      +    if (typeof define === 'function' && define.amd) {
      +        define(['jquery'], factory);
      +    } else if (typeof exports !== 'undefined') {
      +        module.exports = factory(require('jquery'));
      +    } else {
      +        factory(jQuery);
      +    }
      +
      +}(function($) {
      +    'use strict';
      +    var Slick = window.Slick || {};
      +
      +    Slick = (function() {
      +
      +        var instanceUid = 0;
      +
      +        function Slick(element, settings) {
      +
      +            var _ = this, dataSettings;
      +
      +            _.defaults = {
      +                accessibility: true,
      +                adaptiveHeight: false,
      +                appendArrows: $(element),
      +                appendDots: $(element),
      +                arrows: true,
      +                asNavFor: null,
      +                prevArrow: '<button class="slick-prev" aria-label="Previous" type="button">Previous</button>',
      +                nextArrow: '<button class="slick-next" aria-label="Next" type="button">Next</button>',
      +                autoplay: false,
      +                autoplaySpeed: 3000,
      +                centerMode: false,
      +                centerPadding: '50px',
      +                cssEase: 'ease',
      +                customPaging: function(slider, i) {
      +                    return $('<button type="button" />').text(i + 1);
      +                },
      +                dots: false,
      +                dotsClass: 'slick-dots',
      +                draggable: true,
      +                easing: 'linear',
      +                edgeFriction: 0.35,
      +                fade: false,
      +                focusOnSelect: false,
      +                focusOnChange: false,
      +                infinite: true,
      +                initialSlide: 0,
      +                lazyLoad: 'ondemand',
      +                mobileFirst: false,
      +                pauseOnHover: true,
      +                pauseOnFocus: true,
      +                pauseOnDotsHover: false,
      +                respondTo: 'window',
      +                responsive: null,
      +                rows: 1,
      +                rtl: false,
      +                slide: '',
      +                slidesPerRow: 1,
      +                slidesToShow: 1,
      +                slidesToScroll: 1,
      +                speed: 500,
      +                swipe: true,
      +                swipeToSlide: false,
      +                touchMove: true,
      +                touchThreshold: 5,
      +                useCSS: true,
      +                useTransform: true,
      +                variableWidth: false,
      +                vertical: false,
      +                verticalSwiping: false,
      +				verticalReverse: false,
      +                waitForAnimate: true,
      +                zIndex: 1000
      +            };
      +
      +            _.initials = {
      +                animating: false,
      +                dragging: false,
      +                autoPlayTimer: null,
      +                currentDirection: 0,
      +                currentLeft: null,
      +                currentSlide: 0,
      +                direction: 1,
      +                $dots: null,
      +                listWidth: null,
      +                listHeight: null,
      +                loadIndex: 0,
      +                $nextArrow: null,
      +                $prevArrow: null,
      +                scrolling: false,
      +                slideCount: null,
      +                slideWidth: null,
      +                $slideTrack: null,
      +                $slides: null,
      +                sliding: false,
      +                slideOffset: 0,
      +                swipeLeft: null,
      +                swiping: false,
      +                $list: null,
      +                touchObject: {},
      +                transformsEnabled: false,
      +                unslicked: false
      +            };
      +
      +            $.extend(_, _.initials);
      +
      +            _.activeBreakpoint = null;
      +            _.animType = null;
      +            _.animProp = null;
      +            _.breakpoints = [];
      +            _.breakpointSettings = [];
      +            _.cssTransitions = false;
      +            _.focussed = false;
      +            _.interrupted = false;
      +            _.hidden = 'hidden';
      +            _.paused = true;
      +            _.positionProp = null;
      +            _.respondTo = null;
      +            _.rowCount = 1;
      +            _.shouldClick = true;
      +            _.$slider = $(element);
      +            _.$slidesCache = null;
      +            _.transformType = null;
      +            _.transitionType = null;
      +            _.visibilityChange = 'visibilitychange';
      +            _.windowWidth = 0;
      +            _.windowTimer = null;
      +
      +            dataSettings = $(element).data('slick') || {};
      +
      +            _.options = $.extend({}, _.defaults, settings, dataSettings);
      +
      +            _.currentSlide = _.options.initialSlide;
      +
      +            _.originalSettings = _.options;
      +
      +            if (typeof document.mozHidden !== 'undefined') {
      +                _.hidden = 'mozHidden';
      +                _.visibilityChange = 'mozvisibilitychange';
      +            } else if (typeof document.webkitHidden !== 'undefined') {
      +                _.hidden = 'webkitHidden';
      +                _.visibilityChange = 'webkitvisibilitychange';
      +            }
      +
      +            _.autoPlay = $.proxy(_.autoPlay, _);
      +            _.autoPlayClear = $.proxy(_.autoPlayClear, _);
      +            _.autoPlayIterator = $.proxy(_.autoPlayIterator, _);
      +            _.changeSlide = $.proxy(_.changeSlide, _);
      +            _.clickHandler = $.proxy(_.clickHandler, _);
      +            _.selectHandler = $.proxy(_.selectHandler, _);
      +            _.setPosition = $.proxy(_.setPosition, _);
      +            _.swipeHandler = $.proxy(_.swipeHandler, _);
      +            _.dragHandler = $.proxy(_.dragHandler, _);
      +            _.keyHandler = $.proxy(_.keyHandler, _);
      +
      +            _.instanceUid = instanceUid++;
      +
      +            // A simple way to check for HTML strings
      +            // Strict HTML recognition (must start with <)
      +            // Extracted from jQuery v1.11 source
      +            _.htmlExpr = /^(?:\s*(<[\w\W]+>)[^>]*)$/;
      +
      +
      +            _.registerBreakpoints();
      +            _.init(true);
      +
      +        }
      +
      +        return Slick;
      +
      +    }());
      +
      +    Slick.prototype.activateADA = function() {
      +        var _ = this;
      +
      +        _.$slideTrack.find('.slick-active').attr({
      +            'aria-hidden': 'false'
      +        }).find('a, input, button, select').attr({
      +            'tabindex': '0'
      +        });
      +
      +    };
      +
      +    Slick.prototype.addSlide = Slick.prototype.slickAdd = function(markup, index, addBefore) {
      +
      +        var _ = this;
      +
      +        if (typeof(index) === 'boolean') {
      +            addBefore = index;
      +            index = null;
      +        } else if (index < 0 || (index >= _.slideCount)) {
      +            return false;
      +        }
      +
      +        _.unload();
      +
      +        if (typeof(index) === 'number') {
      +            if (index === 0 && _.$slides.length === 0) {
      +                $(markup).appendTo(_.$slideTrack);
      +            } else if (addBefore) {
      +                $(markup).insertBefore(_.$slides.eq(index));
      +            } else {
      +                $(markup).insertAfter(_.$slides.eq(index));
      +            }
      +        } else {
      +            if (addBefore === true) {
      +                $(markup).prependTo(_.$slideTrack);
      +            } else {
      +                $(markup).appendTo(_.$slideTrack);
      +            }
      +        }
      +
      +        _.$slides = _.$slideTrack.children(this.options.slide);
      +
      +        _.$slideTrack.children(this.options.slide).detach();
      +
      +        _.$slideTrack.append(_.$slides);
      +
      +        _.$slides.each(function(index, element) {
      +            $(element).attr('data-slick-index', index);
      +        });
      +
      +        _.$slidesCache = _.$slides;
      +
      +        _.reinit();
      +
      +    };
      +
      +    Slick.prototype.animateHeight = function() {
      +        var _ = this;
      +        if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {
      +            var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);
      +            _.$list.animate({
      +                height: targetHeight
      +            }, _.options.speed);
      +        }
      +    };
      +
      +    Slick.prototype.animateSlide = function(targetLeft, callback) {
      +
      +        var animProps = {},
      +            _ = this;
      +
      +        _.animateHeight();
      +
      +        if (_.options.rtl === true && _.options.vertical === false) {
      +            targetLeft = -targetLeft;
      +        }
      +        if (_.transformsEnabled === false) {
      +            if (_.options.vertical === false) {
      +                _.$slideTrack.animate({
      +                    left: targetLeft
      +                }, _.options.speed, _.options.easing, callback);
      +            } else {
      +                _.$slideTrack.animate({
      +                    top: targetLeft
      +                }, _.options.speed, _.options.easing, callback);
      +            }
      +
      +        } else {
      +
      +            if (_.cssTransitions === false) {
      +                if (_.options.rtl === true) {
      +                    _.currentLeft = -(_.currentLeft);
      +                }
      +                $({
      +                    animStart: _.currentLeft
      +                }).animate({
      +                    animStart: targetLeft
      +                }, {
      +                    duration: _.options.speed,
      +                    easing: _.options.easing,
      +                    step: function(now) {
      +                        now = Math.ceil(now);
      +                        if (_.options.vertical === false) {
      +                            animProps[_.animType] = 'translate(' +
      +                                now + 'px, 0px)';
      +                            _.$slideTrack.css(animProps);
      +                        } else {
      +                            animProps[_.animType] = 'translate(0px,' +
      +                                now + 'px)';
      +                            _.$slideTrack.css(animProps);
      +                        }
      +                    },
      +                    complete: function() {
      +                        if (callback) {
      +                            callback.call();
      +                        }
      +                    }
      +                });
      +
      +            } else {
      +
      +                _.applyTransition();
      +                targetLeft = Math.ceil(targetLeft);
      +
      +                if (_.options.vertical === false) {
      +                    animProps[_.animType] = 'translate3d(' + targetLeft + 'px, 0px, 0px)';
      +                } else {
      +                    animProps[_.animType] = 'translate3d(0px,' + targetLeft + 'px, 0px)';
      +                }
      +                _.$slideTrack.css(animProps);
      +
      +                if (callback) {
      +                    setTimeout(function() {
      +
      +                        _.disableTransition();
      +
      +                        callback.call();
      +                    }, _.options.speed);
      +                }
      +
      +            }
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.getNavTarget = function() {
      +
      +        var _ = this,
      +            asNavFor = _.options.asNavFor;
      +
      +        if ( asNavFor && asNavFor !== null ) {
      +            asNavFor = $(asNavFor).not(_.$slider);
      +        }
      +
      +        return asNavFor;
      +
      +    };
      +
      +    Slick.prototype.asNavFor = function(index) {
      +
      +        var _ = this,
      +            asNavFor = _.getNavTarget();
      +
      +        if ( asNavFor !== null && typeof asNavFor === 'object' ) {
      +            asNavFor.each(function() {
      +                var target = $(this).slick('getSlick');
      +                if(!target.unslicked) {
      +                    target.slideHandler(index, true);
      +                }
      +            });
      +        }
      +
      +    };
      +
      +    Slick.prototype.applyTransition = function(slide) {
      +
      +        var _ = this,
      +            transition = {};
      +
      +        if (_.options.fade === false) {
      +            transition[_.transitionType] = _.transformType + ' ' + _.options.speed + 'ms ' + _.options.cssEase;
      +        } else {
      +            transition[_.transitionType] = 'opacity ' + _.options.speed + 'ms ' + _.options.cssEase;
      +        }
      +
      +        if (_.options.fade === false) {
      +            _.$slideTrack.css(transition);
      +        } else {
      +            _.$slides.eq(slide).css(transition);
      +        }
      +
      +    };
      +
      +    Slick.prototype.autoPlay = function() {
      +
      +        var _ = this;
      +
      +        _.autoPlayClear();
      +
      +        if ( _.slideCount > _.options.slidesToShow ) {
      +            _.autoPlayTimer = setInterval( _.autoPlayIterator, _.options.autoplaySpeed );
      +        }
      +
      +    };
      +
      +    Slick.prototype.autoPlayClear = function() {
      +
      +        var _ = this;
      +
      +        if (_.autoPlayTimer) {
      +            clearInterval(_.autoPlayTimer);
      +        }
      +
      +    };
      +
      +    Slick.prototype.autoPlayIterator = function() {
      +
      +        var _ = this,
      +            slideTo = _.currentSlide + _.options.slidesToScroll;
      +
      +        if ( !_.paused && !_.interrupted && !_.focussed ) {
      +
      +            if ( _.options.infinite === false ) {
      +
      +                if ( _.direction === 1 && ( _.currentSlide + 1 ) === ( _.slideCount - 1 )) {
      +                    _.direction = 0;
      +                }
      +
      +                else if ( _.direction === 0 ) {
      +
      +                    slideTo = _.currentSlide - _.options.slidesToScroll;
      +
      +                    if ( _.currentSlide - 1 === 0 ) {
      +                        _.direction = 1;
      +                    }
      +
      +                }
      +
      +            }
      +
      +            _.slideHandler( slideTo );
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.buildArrows = function() {
      +
      +        var _ = this;
      +
      +        if (_.options.arrows === true ) {
      +
      +            _.$prevArrow = $(_.options.prevArrow).addClass('slick-arrow');
      +            _.$nextArrow = $(_.options.nextArrow).addClass('slick-arrow');
      +
      +            if( _.slideCount > _.options.slidesToShow ) {
      +
      +                _.$prevArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex');
      +                _.$nextArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex');
      +
      +                if (_.htmlExpr.test(_.options.prevArrow)) {
      +                    _.$prevArrow.prependTo(_.options.appendArrows);
      +                }
      +
      +                if (_.htmlExpr.test(_.options.nextArrow)) {
      +                    _.$nextArrow.appendTo(_.options.appendArrows);
      +                }
      +
      +                if (_.options.infinite !== true) {
      +                    _.$prevArrow
      +                        .addClass('slick-disabled')
      +                        .attr('aria-disabled', 'true');
      +                }
      +
      +            } else {
      +
      +                _.$prevArrow.add( _.$nextArrow )
      +
      +                    .addClass('slick-hidden')
      +                    .attr({
      +                        'aria-disabled': 'true',
      +                        'tabindex': '-1'
      +                    });
      +
      +            }
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.buildDots = function() {
      +
      +        var _ = this,
      +            i, dot;
      +
      +        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
      +
      +            _.$slider.addClass('slick-dotted');
      +
      +            dot = $('<ul />').addClass(_.options.dotsClass);
      +
      +            for (i = 0; i <= _.getDotCount(); i += 1) {
      +                dot.append($('<li />').append(_.options.customPaging.call(this, _, i)));
      +            }
      +
      +            _.$dots = dot.appendTo(_.options.appendDots);
      +
      +            _.$dots.find('li').first().addClass('slick-active');
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.buildOut = function() {
      +
      +        var _ = this;
      +
      +        _.$slides =
      +            _.$slider
      +                .children( _.options.slide + ':not(.slick-cloned)')
      +                .addClass('slick-slide');
      +
      +        _.slideCount = _.$slides.length;
      +
      +        _.$slides.each(function(index, element) {
      +            $(element)
      +                .attr('data-slick-index', index)
      +                .data('originalStyling', $(element).attr('style') || '');
      +        });
      +
      +        _.$slider.addClass('slick-slider');
      +
      +        _.$slideTrack = (_.slideCount === 0) ?
      +            $('<div class="slick-track"/>').appendTo(_.$slider) :
      +            _.$slides.wrapAll('<div class="slick-track"/>').parent();
      +
      +        _.$list = _.$slideTrack.wrap(
      +            '<div class="slick-list"/>').parent();
      +        _.$slideTrack.css('opacity', 0);
      +
      +        if (_.options.centerMode === true || _.options.swipeToSlide === true) {
      +            _.options.slidesToScroll = 1;
      +        }
      +
      +        $('img[data-lazy]', _.$slider).not('[src]').addClass('slick-loading');
      +
      +        _.setupInfinite();
      +
      +        _.buildArrows();
      +
      +        _.buildDots();
      +
      +        _.updateDots();
      +
      +
      +        _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0);
      +
      +        if (_.options.draggable === true) {
      +            _.$list.addClass('draggable');
      +        }
      +
      +    };
      +
      +    Slick.prototype.buildRows = function() {
      +
      +        var _ = this, a, b, c, newSlides, numOfSlides, originalSlides,slidesPerSection;
      +
      +        newSlides = document.createDocumentFragment();
      +        originalSlides = _.$slider.children();
      +
      +        if(_.options.rows > 0) {
      +
      +            slidesPerSection = _.options.slidesPerRow * _.options.rows;
      +            numOfSlides = Math.ceil(
      +                originalSlides.length / slidesPerSection
      +            );
      +
      +            for(a = 0; a < numOfSlides; a++){
      +                var slide = document.createElement('div');
      +                for(b = 0; b < _.options.rows; b++) {
      +                    var row = document.createElement('div');
      +                    for(c = 0; c < _.options.slidesPerRow; c++) {
      +                        var target = (a * slidesPerSection + ((b * _.options.slidesPerRow) + c));
      +                        if (originalSlides.get(target)) {
      +                            row.appendChild(originalSlides.get(target));
      +                        }
      +                    }
      +                    slide.appendChild(row);
      +                }
      +                newSlides.appendChild(slide);
      +            }
      +
      +            _.$slider.empty().append(newSlides);
      +            _.$slider.children().children().children()
      +                .css({
      +                    'width':(100 / _.options.slidesPerRow) + '%',
      +                    'display': 'inline-block'
      +                });
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.checkResponsive = function(initial, forceUpdate) {
      +
      +        var _ = this,
      +            breakpoint, targetBreakpoint, respondToWidth, triggerBreakpoint = false;
      +        var sliderWidth = _.$slider.width();
      +        var windowWidth = window.innerWidth || $(window).width();
      +
      +        if (_.respondTo === 'window') {
      +            respondToWidth = windowWidth;
      +        } else if (_.respondTo === 'slider') {
      +            respondToWidth = sliderWidth;
      +        } else if (_.respondTo === 'min') {
      +            respondToWidth = Math.min(windowWidth, sliderWidth);
      +        }
      +
      +        if ( _.options.responsive &&
      +            _.options.responsive.length &&
      +            _.options.responsive !== null) {
      +
      +            targetBreakpoint = null;
      +
      +            for (breakpoint in _.breakpoints) {
      +                if (_.breakpoints.hasOwnProperty(breakpoint)) {
      +                    if (_.originalSettings.mobileFirst === false) {
      +                        if (respondToWidth < _.breakpoints[breakpoint]) {
      +                            targetBreakpoint = _.breakpoints[breakpoint];
      +                        }
      +                    } else {
      +                        if (respondToWidth > _.breakpoints[breakpoint]) {
      +                            targetBreakpoint = _.breakpoints[breakpoint];
      +                        }
      +                    }
      +                }
      +            }
      +
      +            if (targetBreakpoint !== null) {
      +                if (_.activeBreakpoint !== null) {
      +                    if (targetBreakpoint !== _.activeBreakpoint || forceUpdate) {
      +                        _.activeBreakpoint =
      +                            targetBreakpoint;
      +                        if (_.breakpointSettings[targetBreakpoint] === 'unslick') {
      +                            _.unslick(targetBreakpoint);
      +                        } else {
      +                            _.options = $.extend({}, _.originalSettings,
      +                                _.breakpointSettings[
      +                                    targetBreakpoint]);
      +                            if (initial === true) {
      +                                _.currentSlide = _.options.initialSlide;
      +                            }
      +                            _.refresh(initial);
      +                        }
      +                        triggerBreakpoint = targetBreakpoint;
      +                    }
      +                } else {
      +                    _.activeBreakpoint = targetBreakpoint;
      +                    if (_.breakpointSettings[targetBreakpoint] === 'unslick') {
      +                        _.unslick(targetBreakpoint);
      +                    } else {
      +                        _.options = $.extend({}, _.originalSettings,
      +                            _.breakpointSettings[
      +                                targetBreakpoint]);
      +                        if (initial === true) {
      +                            _.currentSlide = _.options.initialSlide;
      +                        }
      +                        _.refresh(initial);
      +                    }
      +                    triggerBreakpoint = targetBreakpoint;
      +                }
      +            } else {
      +                if (_.activeBreakpoint !== null) {
      +                    _.activeBreakpoint = null;
      +                    _.options = _.originalSettings;
      +                    if (initial === true) {
      +                        _.currentSlide = _.options.initialSlide;
      +                    }
      +                    _.refresh(initial);
      +                    triggerBreakpoint = targetBreakpoint;
      +                }
      +            }
      +
      +            // only trigger breakpoints during an actual break. not on initialize.
      +            if( !initial && triggerBreakpoint !== false ) {
      +                _.$slider.trigger('breakpoint', [_, triggerBreakpoint]);
      +            }
      +        }
      +
      +    };
      +
      +    Slick.prototype.changeSlide = function(event, dontAnimate) {
      +
      +        var _ = this,
      +            $target = $(event.currentTarget),
      +            indexOffset, slideOffset, unevenOffset;
      +
      +        // If target is a link, prevent default action.
      +        if($target.is('a')) {
      +            event.preventDefault();
      +        }
      +
      +        // If target is not the <li> element (ie: a child), find the <li>.
      +        if(!$target.is('li')) {
      +            $target = $target.closest('li');
      +        }
      +
      +        unevenOffset = (_.slideCount % _.options.slidesToScroll !== 0);
      +        indexOffset = unevenOffset ? 0 : (_.slideCount - _.currentSlide) % _.options.slidesToScroll;
      +
      +        switch (event.data.message) {
      +
      +            case 'previous':
      +                slideOffset = indexOffset === 0 ? _.options.slidesToScroll : _.options.slidesToShow - indexOffset;
      +                if (_.slideCount > _.options.slidesToShow) {
      +                    _.slideHandler(_.currentSlide - slideOffset, false, dontAnimate);
      +                }
      +                break;
      +
      +            case 'next':
      +                slideOffset = indexOffset === 0 ? _.options.slidesToScroll : indexOffset;
      +                if (_.slideCount > _.options.slidesToShow) {
      +                    _.slideHandler(_.currentSlide + slideOffset, false, dontAnimate);
      +                }
      +                break;
      +
      +            case 'index':
      +                var index = event.data.index === 0 ? 0 :
      +                    event.data.index || $target.index() * _.options.slidesToScroll;
      +
      +                _.slideHandler(_.checkNavigable(index), false, dontAnimate);
      +                $target.children().trigger('focus');
      +                break;
      +
      +            default:
      +                return;
      +        }
      +
      +    };
      +
      +    Slick.prototype.checkNavigable = function(index) {
      +
      +        var _ = this,
      +            navigables, prevNavigable;
      +
      +        navigables = _.getNavigableIndexes();
      +        prevNavigable = 0;
      +        if (index > navigables[navigables.length - 1]) {
      +            index = navigables[navigables.length - 1];
      +        } else {
      +            for (var n in navigables) {
      +                if (index < navigables[n]) {
      +                    index = prevNavigable;
      +                    break;
      +                }
      +                prevNavigable = navigables[n];
      +            }
      +        }
      +
      +        return index;
      +    };
      +
      +    Slick.prototype.cleanUpEvents = function() {
      +
      +        var _ = this;
      +
      +        if (_.options.dots && _.$dots !== null) {
      +
      +            $('li', _.$dots)
      +                .off('click.slick', _.changeSlide)
      +                .off('mouseenter.slick', $.proxy(_.interrupt, _, true))
      +                .off('mouseleave.slick', $.proxy(_.interrupt, _, false));
      +
      +            if (_.options.accessibility === true) {
      +                _.$dots.off('keydown.slick', _.keyHandler);
      +            }
      +        }
      +
      +        _.$slider.off('focus.slick blur.slick');
      +
      +        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
      +            _.$prevArrow && _.$prevArrow.off('click.slick', _.changeSlide);
      +            _.$nextArrow && _.$nextArrow.off('click.slick', _.changeSlide);
      +
      +            if (_.options.accessibility === true) {
      +                _.$prevArrow && _.$prevArrow.off('keydown.slick', _.keyHandler);
      +                _.$nextArrow && _.$nextArrow.off('keydown.slick', _.keyHandler);
      +            }
      +        }
      +
      +        _.$list.off('touchstart.slick mousedown.slick', _.swipeHandler);
      +        _.$list.off('touchmove.slick mousemove.slick', _.swipeHandler);
      +        _.$list.off('touchend.slick mouseup.slick', _.swipeHandler);
      +        _.$list.off('touchcancel.slick mouseleave.slick', _.swipeHandler);
      +
      +        _.$list.off('click.slick', _.clickHandler);
      +
      +        $(document).off(_.visibilityChange, _.visibility);
      +
      +        _.cleanUpSlideEvents();
      +
      +        if (_.options.accessibility === true) {
      +            _.$list.off('keydown.slick', _.keyHandler);
      +        }
      +
      +        if (_.options.focusOnSelect === true) {
      +            $(_.$slideTrack).children().off('click.slick', _.selectHandler);
      +        }
      +
      +        $(window).off('orientationchange.slick.slick-' + _.instanceUid, _.orientationChange);
      +
      +        $(window).off('resize.slick.slick-' + _.instanceUid, _.resize);
      +
      +        $('[draggable!=true]', _.$slideTrack).off('dragstart', _.preventDefault);
      +
      +        $(window).off('load.slick.slick-' + _.instanceUid, _.setPosition);
      +
      +    };
      +
      +    Slick.prototype.cleanUpSlideEvents = function() {
      +
      +        var _ = this;
      +
      +        _.$list.off('mouseenter.slick', $.proxy(_.interrupt, _, true));
      +        _.$list.off('mouseleave.slick', $.proxy(_.interrupt, _, false));
      +
      +    };
      +
      +    Slick.prototype.cleanUpRows = function() {
      +
      +        var _ = this, originalSlides;
      +
      +        if(_.options.rows > 0) {
      +            originalSlides = _.$slides.children().children();
      +            originalSlides.removeAttr('style');
      +            _.$slider.empty().append(originalSlides);
      +        }
      +
      +    };
      +
      +    Slick.prototype.clickHandler = function(event) {
      +
      +        var _ = this;
      +
      +        if (_.shouldClick === false) {
      +            event.stopImmediatePropagation();
      +            event.stopPropagation();
      +            event.preventDefault();
      +        }
      +
      +    };
      +
      +    Slick.prototype.destroy = function(refresh) {
      +
      +        var _ = this;
      +
      +        _.autoPlayClear();
      +
      +        _.touchObject = {};
      +
      +        _.cleanUpEvents();
      +
      +        $('.slick-cloned', _.$slider).detach();
      +
      +        if (_.$dots) {
      +            _.$dots.remove();
      +        }
      +
      +        if ( _.$prevArrow && _.$prevArrow.length ) {
      +
      +            _.$prevArrow
      +                .removeClass('slick-disabled slick-arrow slick-hidden')
      +                .removeAttr('aria-hidden aria-disabled tabindex')
      +                .css('display','');
      +
      +            if ( _.htmlExpr.test( _.options.prevArrow )) {
      +                _.$prevArrow.remove();
      +            }
      +        }
      +
      +        if ( _.$nextArrow && _.$nextArrow.length ) {
      +
      +            _.$nextArrow
      +                .removeClass('slick-disabled slick-arrow slick-hidden')
      +                .removeAttr('aria-hidden aria-disabled tabindex')
      +                .css('display','');
      +
      +            if ( _.htmlExpr.test( _.options.nextArrow )) {
      +                _.$nextArrow.remove();
      +            }
      +        }
      +
      +
      +        if (_.$slides) {
      +
      +            _.$slides
      +                .removeClass('slick-slide slick-active slick-center slick-visible slick-current')
      +                .removeAttr('aria-hidden')
      +                .removeAttr('data-slick-index')
      +                .each(function(){
      +                    $(this).attr('style', $(this).data('originalStyling'));
      +                });
      +
      +            _.$slideTrack.children(this.options.slide).detach();
      +
      +            _.$slideTrack.detach();
      +
      +            _.$list.detach();
      +
      +            _.$slider.append(_.$slides);
      +        }
      +
      +        _.cleanUpRows();
      +
      +        _.$slider.removeClass('slick-slider');
      +        _.$slider.removeClass('slick-initialized');
      +        _.$slider.removeClass('slick-dotted');
      +
      +        _.unslicked = true;
      +
      +        if(!refresh) {
      +            _.$slider.trigger('destroy', [_]);
      +        }
      +
      +    };
      +
      +    Slick.prototype.disableTransition = function(slide) {
      +
      +        var _ = this,
      +            transition = {};
      +
      +        transition[_.transitionType] = '';
      +
      +        if (_.options.fade === false) {
      +            _.$slideTrack.css(transition);
      +        } else {
      +            _.$slides.eq(slide).css(transition);
      +        }
      +
      +    };
      +
      +    Slick.prototype.fadeSlide = function(slideIndex, callback) {
      +
      +        var _ = this;
      +
      +        if (_.cssTransitions === false) {
      +
      +            _.$slides.eq(slideIndex).css({
      +                zIndex: _.options.zIndex
      +            });
      +
      +            _.$slides.eq(slideIndex).animate({
      +                opacity: 1
      +            }, _.options.speed, _.options.easing, callback);
      +
      +        } else {
      +
      +            _.applyTransition(slideIndex);
      +
      +            _.$slides.eq(slideIndex).css({
      +                opacity: 1,
      +                zIndex: _.options.zIndex
      +            });
      +
      +            if (callback) {
      +                setTimeout(function() {
      +
      +                    _.disableTransition(slideIndex);
      +
      +                    callback.call();
      +                }, _.options.speed);
      +            }
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.fadeSlideOut = function(slideIndex) {
      +
      +        var _ = this;
      +
      +        if (_.cssTransitions === false) {
      +
      +            _.$slides.eq(slideIndex).animate({
      +                opacity: 0,
      +                zIndex: _.options.zIndex - 2
      +            }, _.options.speed, _.options.easing);
      +
      +        } else {
      +
      +            _.applyTransition(slideIndex);
      +
      +            _.$slides.eq(slideIndex).css({
      +                opacity: 0,
      +                zIndex: _.options.zIndex - 2
      +            });
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.filterSlides = Slick.prototype.slickFilter = function(filter) {
      +
      +        var _ = this;
      +
      +        if (filter !== null) {
      +
      +            _.$slidesCache = _.$slides;
      +
      +            _.unload();
      +
      +            _.$slideTrack.children(this.options.slide).detach();
      +
      +            _.$slidesCache.filter(filter).appendTo(_.$slideTrack);
      +
      +            _.reinit();
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.focusHandler = function() {
      +
      +        var _ = this;
      +
      +        _.$slider
      +            .off('focus.slick blur.slick')
      +            .on('focus.slick blur.slick', '*', function(event) {
      +
      +            event.stopImmediatePropagation();
      +            var $sf = $(this);
      +
      +            setTimeout(function() {
      +
      +                if( _.options.pauseOnFocus ) {
      +                    _.focussed = $sf.is(':focus');
      +                    _.autoPlay();
      +                }
      +
      +            }, 0);
      +
      +        });
      +    };
      +
      +    Slick.prototype.getCurrent = Slick.prototype.slickCurrentSlide = function() {
      +
      +        var _ = this;
      +        return _.currentSlide;
      +
      +    };
      +
      +    Slick.prototype.getDotCount = function() {
      +
      +        var _ = this;
      +
      +        var breakPoint = 0;
      +        var counter = 0;
      +        var pagerQty = 0;
      +
      +        if (_.options.infinite === true) {
      +            if (_.slideCount <= _.options.slidesToShow) {
      +                 ++pagerQty;
      +            } else {
      +                while (breakPoint < _.slideCount) {
      +                    ++pagerQty;
      +                    breakPoint = counter + _.options.slidesToScroll;
      +                    counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
      +                }
      +            }
      +        } else if (_.options.centerMode === true) {
      +            pagerQty = _.slideCount;
      +        } else if(!_.options.asNavFor) {
      +            pagerQty = 1 + Math.ceil((_.slideCount - _.options.slidesToShow) / _.options.slidesToScroll);
      +        }else {
      +            while (breakPoint < _.slideCount) {
      +                ++pagerQty;
      +                breakPoint = counter + _.options.slidesToScroll;
      +                counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
      +            }
      +        }
      +
      +        return pagerQty - 1;
      +
      +    };
      +
      +/*    Slick.prototype.getLeft = function(slideIndex) {
      +
      +        var _ = this,
      +            targetLeft,
      +            verticalHeight,
      +            verticalOffset = 0,
      +            targetSlide,
      +            coef;
      +
      +        _.slideOffset = 0;
      +        verticalHeight = _.$slides.first().outerHeight(true);
      +
      +        if (_.options.infinite === true) {
      +            if (_.slideCount > _.options.slidesToShow) {
      +                _.slideOffset = (_.slideWidth * _.options.slidesToShow) * -1;
      +                coef = -1
      +
      +                if (_.options.vertical === true && _.options.centerMode === true) {
      +                    if (_.options.slidesToShow === 2) {
      +                        coef = -1.5;
      +                    } else if (_.options.slidesToShow === 1) {
      +                        coef = -2
      +                    }
      +                }
      +                verticalOffset = (verticalHeight * _.options.slidesToShow) * coef;
      +            }
      +            if (_.slideCount % _.options.slidesToScroll !== 0) {
      +                if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) {
      +                    if (slideIndex > _.slideCount) {
      +                        _.slideOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * _.slideWidth) * -1;
      +                        verticalOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * verticalHeight) * -1;
      +                    } else {
      +                        _.slideOffset = ((_.slideCount % _.options.slidesToScroll) * _.slideWidth) * -1;
      +                        verticalOffset = ((_.slideCount % _.options.slidesToScroll) * verticalHeight) * -1;
      +                    }
      +                }
      +            }
      +        } else {
      +            if (slideIndex + _.options.slidesToShow > _.slideCount) {
      +                _.slideOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * _.slideWidth;
      +                verticalOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * verticalHeight;
      +            }
      +        }
      +
      +        if (_.slideCount <= _.options.slidesToShow) {
      +            _.slideOffset = 0;
      +            verticalOffset = 0;
      +        }
      +
      +        if (_.options.centerMode === true && _.slideCount <= _.options.slidesToShow) {
      +            _.slideOffset = ((_.slideWidth * Math.floor(_.options.slidesToShow)) / 2) - ((_.slideWidth * _.slideCount) / 2);
      +        } else if (_.options.centerMode === true && _.options.infinite === true) {
      +            _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2) - _.slideWidth;
      +        } else if (_.options.centerMode === true) {
      +            _.slideOffset = 0;
      +            _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2);
      +        }
      +
      +        if (_.options.vertical === false) {
      +            targetLeft = ((slideIndex * _.slideWidth) * -1) + _.slideOffset;
      +        } else {
      +            targetLeft = ((slideIndex * verticalHeight) * -1) + verticalOffset;
      +        }
      +
      +        if (_.options.variableWidth === true) {
      +
      +            if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) {
      +                targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);
      +            } else {
      +                targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow);
      +            }
      +
      +            if (_.options.rtl === true) {
      +                if (targetSlide[0]) {
      +                    targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1;
      +                } else {
      +                    targetLeft =  0;
      +                }
      +            } else {
      +                targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
      +            }
      +
      +            if (_.options.centerMode === true) {
      +                if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) {
      +                    targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);
      +                } else {
      +                    targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow + 1);
      +                }
      +
      +                if (_.options.rtl === true) {
      +                    if (targetSlide[0]) {
      +                        targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1;
      +                    } else {
      +                        targetLeft =  0;
      +                    }
      +                } else {
      +                    targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
      +                }
      +
      +                targetLeft += (_.$list.width() - targetSlide.outerWidth()) / 2;
      +            }
      +        }
      +
      +        return targetLeft;
      +
      +    };*/
      +	
      +    Slick.prototype.getLeft = function(slideIndex) {
      +
      +        var _ = this,
      +            targetLeft,
      +            verticalHeight,
      +            verticalOffset = 0,
      +            targetSlide,
      +            coef;
      +
      +        _.slideOffset = 0;
      +        verticalHeight = _.$slides.first().outerHeight(true);
      +
      +        if (_.options.infinite === true) {
      +            if (_.slideCount > _.options.slidesToShow) {
      +                _.slideOffset = (_.slideWidth * _.options.slidesToShow) * -1;
      +                coef = -1
      +
      +                if (_.options.vertical === true && _.options.centerMode === true) {
      +                    if (_.options.slidesToShow === 2) {
      +                        coef = -1.5;
      +                    } else if (_.options.slidesToShow === 1) {
      +                        coef = -2
      +                    }
      +                }
      +                verticalOffset = (verticalHeight * _.options.slidesToShow) * coef;
      +            }
      +            if (_.slideCount % _.options.slidesToScroll !== 0) {
      +                if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) {
      +                    if (slideIndex > _.slideCount) {
      +                        _.slideOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * _.slideWidth) * -1;
      +                        verticalOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * verticalHeight) * -1;
      +                    } else {
      +                        _.slideOffset = ((_.slideCount % _.options.slidesToScroll) * _.slideWidth) * -1;
      +                        verticalOffset = ((_.slideCount % _.options.slidesToScroll) * verticalHeight) * -1;
      +                    }
      +                }
      +            }
      +        } else {
      +            if (slideIndex + _.options.slidesToShow > _.slideCount) {
      +                _.slideOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * _.slideWidth;
      +                verticalOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * verticalHeight;
      +            }
      +        }
      +
      +        if (_.slideCount <= _.options.slidesToShow) {
      +            _.slideOffset = 0;
      +            verticalOffset = 0;
      +        }
      +
      +        if (_.options.centerMode === true && _.slideCount <= _.options.slidesToShow) {
      +            _.slideOffset = ((_.slideWidth * Math.floor(_.options.slidesToShow)) / 2) - ((_.slideWidth * _.slideCount) / 2);
      +        } else if (_.options.centerMode === true && _.options.infinite === true) {
      +            _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2) - _.slideWidth;
      +        } else if (_.options.centerMode === true) {
      +            _.slideOffset = 0;
      +            _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2);
      +
      +
      +        }
      +
      +        if (_.options.vertical === false) {
      +            targetLeft = ((slideIndex * _.slideWidth) * -1) + _.slideOffset;
      +        } else {
      +			
      +			if (_.options.verticalReverse === false) {
      +			
      +            	targetLeft = ((slideIndex * verticalHeight) * -1) + verticalOffset;
      +			
      +			}else{
      +				
      +				//_.$slideTrack.css({"display": "flex", "flex-direction": "column-reverse"});
      +            	targetLeft = ((_.slideCount * verticalHeight) * -1) + (slideIndex * - verticalOffset) / _.options.slidesToShow;
      +			
      +			}
      +        }
      +
      +        if (_.options.variableWidth === true) {
      +
      +            if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) {
      +                targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);
      +            } else {
      +                targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow);
      +            }
      +
      +            if (_.options.rtl === true) {
      +                if (targetSlide[0]) {
      +                    targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1;
      +                } else {
      +                    targetLeft =  0;
      +                }
      +            } else {
      +                targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
      +            }
      +
      +            if (_.options.centerMode === true) {
      +                if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) {
      +                    targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);
      +                } else {
      +                    targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow + 1);
      +                }
      +
      +                if (_.options.rtl === true) {
      +                    if (targetSlide[0]) {
      +                        targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1;
      +                    } else {
      +                        targetLeft =  0;
      +                    }
      +                } else {
      +                    targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
      +                }
      +
      +                targetLeft += (_.$list.width() - targetSlide.outerWidth()) / 2;
      +            }
      +        }
      +
      +        return targetLeft;
      +
      +    };
      +
      +    Slick.prototype.getOption = Slick.prototype.slickGetOption = function(option) {
      +
      +        var _ = this;
      +
      +        return _.options[option];
      +
      +    };
      +
      +    Slick.prototype.getNavigableIndexes = function() {
      +
      +        var _ = this,
      +            breakPoint = 0,
      +            counter = 0,
      +            indexes = [],
      +            max;
      +
      +        if (_.options.infinite === false) {
      +            max = _.slideCount;
      +        } else {
      +            breakPoint = _.options.slidesToScroll * -1;
      +            counter = _.options.slidesToScroll * -1;
      +            max = _.slideCount * 2;
      +        }
      +
      +        while (breakPoint < max) {
      +            indexes.push(breakPoint);
      +            breakPoint = counter + _.options.slidesToScroll;
      +            counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
      +        }
      +
      +        return indexes;
      +
      +    };
      +
      +    Slick.prototype.getSlick = function() {
      +
      +        return this;
      +
      +    };
      +
      +    Slick.prototype.getSlideCount = function() {
      +
      +        var _ = this,
      +            slidesTraversed, swipedSlide, centerOffset;
      +
      +        centerOffset = _.options.centerMode === true ? _.slideWidth * Math.floor(_.options.slidesToShow / 2) : 0;
      +
      +        if (_.options.swipeToSlide === true) {
      +            _.$slideTrack.find('.slick-slide').each(function(index, slide) {
      +                if (slide.offsetLeft - centerOffset + ($(slide).outerWidth() / 2) > (_.swipeLeft * -1)) {
      +                    swipedSlide = slide;
      +                    return false;
      +                }
      +            });
      +
      +            slidesTraversed = Math.abs($(swipedSlide).attr('data-slick-index') - _.currentSlide) || 1;
      +
      +            return slidesTraversed;
      +
      +        } else {
      +            return _.options.slidesToScroll;
      +        }
      +
      +    };
      +
      +    Slick.prototype.goTo = Slick.prototype.slickGoTo = function(slide, dontAnimate) {
      +
      +        var _ = this;
      +
      +        _.changeSlide({
      +            data: {
      +                message: 'index',
      +                index: parseInt(slide)
      +            }
      +        }, dontAnimate);
      +
      +    };
      +
      +    Slick.prototype.init = function(creation) {
      +
      +        var _ = this;
      +
      +        if (!$(_.$slider).hasClass('slick-initialized')) {
      +
      +            $(_.$slider).addClass('slick-initialized');
      +
      +            _.buildRows();
      +            _.buildOut();
      +            _.setProps();
      +            _.startLoad();
      +            _.loadSlider();
      +            _.initializeEvents();
      +            _.updateArrows();
      +            _.updateDots();
      +            _.checkResponsive(true);
      +            _.focusHandler();
      +
      +        }
      +
      +        if (creation) {
      +            _.$slider.trigger('init', [_]);
      +        }
      +
      +        if (_.options.accessibility === true) {
      +            _.initADA();
      +        }
      +
      +        if ( _.options.autoplay ) {
      +
      +            _.paused = false;
      +            _.autoPlay();
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.initADA = function() {
      +        var _ = this,
      +                numDotGroups = Math.ceil(_.slideCount / _.options.slidesToShow),
      +                tabControlIndexes = _.getNavigableIndexes().filter(function(val) {
      +                    return (val >= 0) && (val < _.slideCount);
      +                });
      +
      +        _.$slides.add(_.$slideTrack.find('.slick-cloned')).attr({
      +            'aria-hidden': 'true',
      +            'tabindex': '-1'
      +        }).find('a, input, button, select').attr({
      +            'tabindex': '-1'
      +        });
      +
      +        if (_.$dots !== null) {
      +            _.$slides.not(_.$slideTrack.find('.slick-cloned')).each(function(i) {
      +                var slideControlIndex = tabControlIndexes.indexOf(i);
      +
      +                $(this).attr({
      +                    'role': 'tabpanel',
      +                    'id': 'slick-slide' + _.instanceUid + i,
      +                    'tabindex': -1
      +                });
      +
      +                if (slideControlIndex !== -1) {
      +                   var ariaButtonControl = 'slick-slide-control' + _.instanceUid + slideControlIndex
      +                   if ($('#' + ariaButtonControl).length) {
      +                     $(this).attr({
      +                         'aria-describedby': ariaButtonControl
      +                     });
      +                   }
      +                }
      +            });
      +
      +            _.$dots.attr('role', 'tablist').find('li').each(function(i) {
      +                var mappedSlideIndex = tabControlIndexes[i];
      +
      +                $(this).attr({
      +                    'role': 'presentation'
      +                });
      +
      +                $(this).find('button').first().attr({
      +                    'role': 'tab',
      +                    'id': 'slick-slide-control' + _.instanceUid + i,
      +                    'aria-controls': 'slick-slide' + _.instanceUid + mappedSlideIndex,
      +                    'aria-label': (i + 1) + ' of ' + numDotGroups,
      +                    'aria-selected': null,
      +                    'tabindex': '-1'
      +                });
      +
      +            }).eq(_.currentSlide).find('button').attr({
      +                'aria-selected': 'true',
      +                'tabindex': '0'
      +            }).end();
      +        }
      +
      +        for (var i=_.currentSlide, max=i+_.options.slidesToShow; i < max; i++) {
      +          if (_.options.focusOnChange) {
      +            _.$slides.eq(i).attr({'tabindex': '0'});
      +          } else {
      +            _.$slides.eq(i).removeAttr('tabindex');
      +          }
      +        }
      +
      +        _.activateADA();
      +
      +    };
      +
      +    Slick.prototype.initArrowEvents = function() {
      +
      +        var _ = this;
      +
      +        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
      +            _.$prevArrow
      +               .off('click.slick')
      +               .on('click.slick', {
      +                    message: 'previous'
      +               }, _.changeSlide);
      +            _.$nextArrow
      +               .off('click.slick')
      +               .on('click.slick', {
      +                    message: 'next'
      +               }, _.changeSlide);
      +
      +            if (_.options.accessibility === true) {
      +                _.$prevArrow.on('keydown.slick', _.keyHandler);
      +                _.$nextArrow.on('keydown.slick', _.keyHandler);
      +            }
      +        }
      +
      +    };
      +
      +    Slick.prototype.initDotEvents = function() {
      +
      +        var _ = this;
      +
      +        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
      +            $('li', _.$dots).on('click.slick', {
      +                message: 'index'
      +            }, _.changeSlide);
      +
      +            if (_.options.accessibility === true) {
      +                _.$dots.on('keydown.slick', _.keyHandler);
      +            }
      +        }
      +
      +        if (_.options.dots === true && _.options.pauseOnDotsHover === true && _.slideCount > _.options.slidesToShow) {
      +
      +            $('li', _.$dots)
      +                .on('mouseenter.slick', $.proxy(_.interrupt, _, true))
      +                .on('mouseleave.slick', $.proxy(_.interrupt, _, false));
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.initSlideEvents = function() {
      +
      +        var _ = this;
      +
      +        if ( _.options.pauseOnHover ) {
      +
      +            _.$list.on('mouseenter.slick', $.proxy(_.interrupt, _, true));
      +            _.$list.on('mouseleave.slick', $.proxy(_.interrupt, _, false));
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.initializeEvents = function() {
      +
      +        var _ = this;
      +
      +        _.initArrowEvents();
      +
      +        _.initDotEvents();
      +        _.initSlideEvents();
      +
      +        _.$list.on('touchstart.slick mousedown.slick', {
      +            action: 'start'
      +        }, _.swipeHandler);
      +        _.$list.on('touchmove.slick mousemove.slick', {
      +            action: 'move'
      +        }, _.swipeHandler);
      +        _.$list.on('touchend.slick mouseup.slick', {
      +            action: 'end'
      +        }, _.swipeHandler);
      +        _.$list.on('touchcancel.slick mouseleave.slick', {
      +            action: 'end'
      +        }, _.swipeHandler);
      +
      +        _.$list.on('click.slick', _.clickHandler);
      +
      +        $(document).on(_.visibilityChange, $.proxy(_.visibility, _));
      +
      +        if (_.options.accessibility === true) {
      +            _.$list.on('keydown.slick', _.keyHandler);
      +        }
      +
      +        if (_.options.focusOnSelect === true) {
      +            $(_.$slideTrack).children().on('click.slick', _.selectHandler);
      +        }
      +
      +        $(window).on('orientationchange.slick.slick-' + _.instanceUid, $.proxy(_.orientationChange, _));
      +
      +        $(window).on('resize.slick.slick-' + _.instanceUid, $.proxy(_.resize, _));
      +
      +        $('[draggable!=true]', _.$slideTrack).on('dragstart', _.preventDefault);
      +
      +        $(window).on('load.slick.slick-' + _.instanceUid, _.setPosition);
      +        $(_.setPosition);
      +
      +    };
      +
      +    Slick.prototype.initUI = function() {
      +
      +        var _ = this;
      +
      +        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
      +
      +            _.$prevArrow.show();
      +            _.$nextArrow.show();
      +
      +        }
      +
      +        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
      +
      +            _.$dots.show();
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.keyHandler = function(event) {
      +
      +        var _ = this;
      +         //Dont slide if the cursor is inside the form fields and arrow keys are pressed
      +        if(!event.target.tagName.match('TEXTAREA|INPUT|SELECT')) {
      +            if (event.keyCode === 37 && _.options.accessibility === true) {
      +                _.changeSlide({
      +                    data: {
      +                        message: _.options.rtl === true ? 'next' :  'previous'
      +                    }
      +                });
      +            } else if (event.keyCode === 39 && _.options.accessibility === true) {
      +                _.changeSlide({
      +                    data: {
      +                        message: _.options.rtl === true ? 'previous' : 'next'
      +                    }
      +                });
      +            }
      +        }
      +
      +    };
      +
      +    Slick.prototype.lazyLoad = function() {
      +
      +        var _ = this,
      +            loadRange, cloneRange, rangeStart, rangeEnd;
      +
      +        function loadImages(imagesScope) {
      +
      +            $('img[data-lazy]', imagesScope).each(function() {
      +
      +                var image = $(this),
      +                    imageSource = $(this).attr('data-lazy'),
      +                    imageSrcSet = $(this).attr('data-srcset'),
      +                    imageSizes  = $(this).attr('data-sizes') || _.$slider.attr('data-sizes'),
      +                    imageToLoad = document.createElement('img');
      +
      +                imageToLoad.onload = function() {
      +
      +                    image
      +                        .animate({ opacity: 0 }, 100, function() {
      +
      +                            if (imageSrcSet) {
      +                                image
      +                                    .attr('srcset', imageSrcSet );
      +
      +                                if (imageSizes) {
      +                                    image
      +                                        .attr('sizes', imageSizes );
      +                                }
      +                            }
      +
      +                            image
      +                                .attr('src', imageSource)
      +                                .animate({ opacity: 1 }, 200, function() {
      +                                    image
      +                                        .removeAttr('data-lazy data-srcset data-sizes')
      +                                        .removeClass('slick-loading');
      +                                });
      +                            _.$slider.trigger('lazyLoaded', [_, image, imageSource]);
      +                        });
      +
      +                };
      +
      +                imageToLoad.onerror = function() {
      +
      +                    image
      +                        .removeAttr( 'data-lazy' )
      +                        .removeClass( 'slick-loading' )
      +                        .addClass( 'slick-lazyload-error' );
      +
      +                    _.$slider.trigger('lazyLoadError', [ _, image, imageSource ]);
      +
      +                };
      +
      +                imageToLoad.src = imageSource;
      +
      +            });
      +
      +        }
      +
      +        if (_.options.centerMode === true) {
      +            if (_.options.infinite === true) {
      +                rangeStart = _.currentSlide + (_.options.slidesToShow / 2 + 1);
      +                rangeEnd = rangeStart + _.options.slidesToShow + 2;
      +            } else {
      +                rangeStart = Math.max(0, _.currentSlide - (_.options.slidesToShow / 2 + 1));
      +                rangeEnd = 2 + (_.options.slidesToShow / 2 + 1) + _.currentSlide;
      +            }
      +        } else {
      +            rangeStart = _.options.infinite ? _.options.slidesToShow + _.currentSlide : _.currentSlide;
      +            rangeEnd = Math.ceil(rangeStart + _.options.slidesToShow);
      +            if (_.options.fade === true) {
      +                if (rangeStart > 0) rangeStart--;
      +                if (rangeEnd <= _.slideCount) rangeEnd++;
      +            }
      +        }
      +
      +        loadRange = _.$slider.find('.slick-slide').slice(rangeStart, rangeEnd);
      +
      +        if (_.options.lazyLoad === 'anticipated') {
      +            var prevSlide = rangeStart - 1,
      +                nextSlide = rangeEnd,
      +                $slides = _.$slider.find('.slick-slide');
      +
      +            for (var i = 0; i < _.options.slidesToScroll; i++) {
      +                if (prevSlide < 0) prevSlide = _.slideCount - 1;
      +                loadRange = loadRange.add($slides.eq(prevSlide));
      +                loadRange = loadRange.add($slides.eq(nextSlide));
      +                prevSlide--;
      +                nextSlide++;
      +            }
      +        }
      +
      +        loadImages(loadRange);
      +
      +        if (_.slideCount <= _.options.slidesToShow) {
      +            cloneRange = _.$slider.find('.slick-slide');
      +            loadImages(cloneRange);
      +        } else
      +        if (_.currentSlide >= _.slideCount - _.options.slidesToShow) {
      +            cloneRange = _.$slider.find('.slick-cloned').slice(0, _.options.slidesToShow);
      +            loadImages(cloneRange);
      +        } else if (_.currentSlide === 0) {
      +            cloneRange = _.$slider.find('.slick-cloned').slice(_.options.slidesToShow * -1);
      +            loadImages(cloneRange);
      +        }
      +
      +    };
      +
      +    Slick.prototype.loadSlider = function() {
      +
      +        var _ = this;
      +
      +        _.setPosition();
      +
      +        _.$slideTrack.css({
      +            opacity: 1
      +        });
      +
      +        _.$slider.removeClass('slick-loading');
      +
      +        _.initUI();
      +
      +        if (_.options.lazyLoad === 'progressive') {
      +            _.progressiveLazyLoad();
      +        }
      +
      +    };
      +
      +    Slick.prototype.next = Slick.prototype.slickNext = function() {
      +
      +        var _ = this;
      +
      +        _.changeSlide({
      +            data: {
      +                message: 'next'
      +            }
      +        });
      +
      +    };
      +
      +    Slick.prototype.orientationChange = function() {
      +
      +        var _ = this;
      +
      +        _.checkResponsive();
      +        _.setPosition();
      +
      +    };
      +
      +    Slick.prototype.pause = Slick.prototype.slickPause = function() {
      +
      +        var _ = this;
      +
      +        _.autoPlayClear();
      +        _.paused = true;
      +
      +    };
      +
      +    Slick.prototype.play = Slick.prototype.slickPlay = function() {
      +
      +        var _ = this;
      +
      +        _.autoPlay();
      +        _.options.autoplay = true;
      +        _.paused = false;
      +        _.focussed = false;
      +        _.interrupted = false;
      +
      +    };
      +
      +    Slick.prototype.postSlide = function(index) {
      +
      +        var _ = this;
      +
      +        if( !_.unslicked ) {
      +
      +            _.$slider.trigger('afterChange', [_, index]);
      +
      +            _.animating = false;
      +
      +            if (_.slideCount > _.options.slidesToShow) {
      +                _.setPosition();
      +            }
      +
      +            _.swipeLeft = null;
      +
      +            if ( _.options.autoplay ) {
      +                _.autoPlay();
      +            }
      +
      +            if (_.options.accessibility === true) {
      +                _.initADA();
      +
      +                if (_.options.focusOnChange) {
      +                    var $currentSlide = $(_.$slides.get(_.currentSlide));
      +                    $currentSlide.attr('tabindex', 0).focus();
      +                }
      +            }
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.prev = Slick.prototype.slickPrev = function() {
      +
      +        var _ = this;
      +
      +        _.changeSlide({
      +            data: {
      +                message: 'previous'
      +            }
      +        });
      +
      +    };
      +
      +    Slick.prototype.preventDefault = function(event) {
      +
      +        event.preventDefault();
      +
      +    };
      +
      +    Slick.prototype.progressiveLazyLoad = function( tryCount ) {
      +
      +        tryCount = tryCount || 1;
      +
      +        var _ = this,
      +            $imgsToLoad = $( 'img[data-lazy]', _.$slider ),
      +            image,
      +            imageSource,
      +            imageSrcSet,
      +            imageSizes,
      +            imageToLoad;
      +
      +        if ( $imgsToLoad.length ) {
      +
      +            image = $imgsToLoad.first();
      +            imageSource = image.attr('data-lazy');
      +            imageSrcSet = image.attr('data-srcset');
      +            imageSizes  = image.attr('data-sizes') || _.$slider.attr('data-sizes');
      +            imageToLoad = document.createElement('img');
      +
      +            imageToLoad.onload = function() {
      +
      +                if (imageSrcSet) {
      +                    image
      +                        .attr('srcset', imageSrcSet );
      +
      +                    if (imageSizes) {
      +                        image
      +                            .attr('sizes', imageSizes );
      +                    }
      +                }
      +
      +                image
      +                    .attr( 'src', imageSource )
      +                    .removeAttr('data-lazy data-srcset data-sizes')
      +                    .removeClass('slick-loading');
      +
      +                if ( _.options.adaptiveHeight === true ) {
      +                    _.setPosition();
      +                }
      +
      +                _.$slider.trigger('lazyLoaded', [ _, image, imageSource ]);
      +                _.progressiveLazyLoad();
      +
      +            };
      +
      +            imageToLoad.onerror = function() {
      +
      +                if ( tryCount < 3 ) {
      +
      +                    /**
      +                     * try to load the image 3 times,
      +                     * leave a slight delay so we don't get
      +                     * servers blocking the request.
      +                     */
      +                    setTimeout( function() {
      +                        _.progressiveLazyLoad( tryCount + 1 );
      +                    }, 500 );
      +
      +                } else {
      +
      +                    image
      +                        .removeAttr( 'data-lazy' )
      +                        .removeClass( 'slick-loading' )
      +                        .addClass( 'slick-lazyload-error' );
      +
      +                    _.$slider.trigger('lazyLoadError', [ _, image, imageSource ]);
      +
      +                    _.progressiveLazyLoad();
      +
      +                }
      +
      +            };
      +
      +            imageToLoad.src = imageSource;
      +
      +        } else {
      +
      +            _.$slider.trigger('allImagesLoaded', [ _ ]);
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.refresh = function( initializing ) {
      +
      +        var _ = this, currentSlide, lastVisibleIndex;
      +
      +        lastVisibleIndex = _.slideCount - _.options.slidesToShow;
      +
      +        // in non-infinite sliders, we don't want to go past the
      +        // last visible index.
      +        if( !_.options.infinite && ( _.currentSlide > lastVisibleIndex )) {
      +            _.currentSlide = lastVisibleIndex;
      +        }
      +
      +        // if less slides than to show, go to start.
      +        if ( _.slideCount <= _.options.slidesToShow ) {
      +            _.currentSlide = 0;
      +
      +        }
      +
      +        currentSlide = _.currentSlide;
      +
      +        _.destroy(true);
      +
      +        $.extend(_, _.initials, { currentSlide: currentSlide });
      +
      +        _.init();
      +
      +        if( !initializing ) {
      +
      +            _.changeSlide({
      +                data: {
      +                    message: 'index',
      +                    index: currentSlide
      +                }
      +            }, false);
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.registerBreakpoints = function() {
      +
      +        var _ = this, breakpoint, currentBreakpoint, l,
      +            responsiveSettings = _.options.responsive || null;
      +
      +        if ( $.type(responsiveSettings) === 'array' && responsiveSettings.length ) {
      +
      +            _.respondTo = _.options.respondTo || 'window';
      +
      +            for ( breakpoint in responsiveSettings ) {
      +
      +                l = _.breakpoints.length-1;
      +
      +                if (responsiveSettings.hasOwnProperty(breakpoint)) {
      +                    currentBreakpoint = responsiveSettings[breakpoint].breakpoint;
      +
      +                    // loop through the breakpoints and cut out any existing
      +                    // ones with the same breakpoint number, we don't want dupes.
      +                    while( l >= 0 ) {
      +                        if( _.breakpoints[l] && _.breakpoints[l] === currentBreakpoint ) {
      +                            _.breakpoints.splice(l,1);
      +                        }
      +                        l--;
      +                    }
      +
      +                    _.breakpoints.push(currentBreakpoint);
      +                    _.breakpointSettings[currentBreakpoint] = responsiveSettings[breakpoint].settings;
      +
      +                }
      +
      +            }
      +
      +            _.breakpoints.sort(function(a, b) {
      +                return ( _.options.mobileFirst ) ? a-b : b-a;
      +            });
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.reinit = function() {
      +
      +        var _ = this;
      +
      +        _.$slides =
      +            _.$slideTrack
      +                .children(_.options.slide)
      +                .addClass('slick-slide');
      +
      +        _.slideCount = _.$slides.length;
      +
      +        if (_.currentSlide >= _.slideCount && _.currentSlide !== 0) {
      +            _.currentSlide = _.currentSlide - _.options.slidesToScroll;
      +        }
      +
      +        if (_.slideCount <= _.options.slidesToShow) {
      +            _.currentSlide = 0;
      +        }
      +
      +        _.registerBreakpoints();
      +
      +        _.setProps();
      +        _.setupInfinite();
      +        _.buildArrows();
      +        _.updateArrows();
      +        _.initArrowEvents();
      +        _.buildDots();
      +        _.updateDots();
      +        _.initDotEvents();
      +        _.cleanUpSlideEvents();
      +        _.initSlideEvents();
      +
      +        _.checkResponsive(false, true);
      +
      +        if (_.options.focusOnSelect === true) {
      +            $(_.$slideTrack).children().on('click.slick', _.selectHandler);
      +        }
      +
      +        _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0);
      +
      +        _.setPosition();
      +        _.focusHandler();
      +
      +        _.paused = !_.options.autoplay;
      +        _.autoPlay();
      +
      +        _.$slider.trigger('reInit', [_]);
      +
      +    };
      +
      +    Slick.prototype.resize = function() {
      +
      +        var _ = this;
      +
      +        if ($(window).width() !== _.windowWidth) {
      +            clearTimeout(_.windowDelay);
      +            _.windowDelay = window.setTimeout(function() {
      +                _.windowWidth = $(window).width();
      +                _.checkResponsive();
      +                if( !_.unslicked ) { _.setPosition(); }
      +            }, 50);
      +        }
      +    };
      +
      +    Slick.prototype.removeSlide = Slick.prototype.slickRemove = function(index, removeBefore, removeAll) {
      +
      +        var _ = this;
      +
      +        if (typeof(index) === 'boolean') {
      +            removeBefore = index;
      +            index = removeBefore === true ? 0 : _.slideCount - 1;
      +        } else {
      +            index = removeBefore === true ? --index : index;
      +        }
      +
      +        if (_.slideCount < 1 || index < 0 || index > _.slideCount - 1) {
      +            return false;
      +        }
      +
      +        _.unload();
      +
      +        if (removeAll === true) {
      +            _.$slideTrack.children().remove();
      +        } else {
      +            _.$slideTrack.children(this.options.slide).eq(index).remove();
      +        }
      +
      +        _.$slides = _.$slideTrack.children(this.options.slide);
      +
      +        _.$slideTrack.children(this.options.slide).detach();
      +
      +        _.$slideTrack.append(_.$slides);
      +
      +        _.$slidesCache = _.$slides;
      +
      +        _.reinit();
      +
      +    };
      +
      +    Slick.prototype.setCSS = function(position) {
      +
      +        var _ = this,
      +            positionProps = {},
      +            x, y;
      +
      +        if (_.options.rtl === true) {
      +            position = -position;
      +        }
      +        x = _.positionProp == 'left' ? Math.ceil(position) + 'px' : '0px';
      +        y = _.positionProp == 'top' ? Math.ceil(position) + 'px' : '0px';
      +
      +        positionProps[_.positionProp] = position;
      +
      +        if (_.transformsEnabled === false) {
      +            _.$slideTrack.css(positionProps);
      +        } else {
      +            positionProps = {};
      +            if (_.cssTransitions === false) {
      +                positionProps[_.animType] = 'translate(' + x + ', ' + y + ')';
      +                _.$slideTrack.css(positionProps);
      +            } else {
      +                positionProps[_.animType] = 'translate3d(' + x + ', ' + y + ', 0px)';
      +                _.$slideTrack.css(positionProps);
      +            }
      +        }
      +
      +    };
      +
      +/*    Slick.prototype.setDimensions = function() {
      +
      +        var _ = this;
      +
      +        if (_.options.vertical === false) {
      +            if (_.options.centerMode === true) {
      +                _.$list.css({
      +                    padding: ('0px ' + _.options.centerPadding)
      +                });
      +            }
      +        } else {
      +            _.$list.height(_.$slides.first().outerHeight(true) * _.options.slidesToShow);
      +            if (_.options.centerMode === true) {
      +                _.$list.css({
      +                    padding: (_.options.centerPadding + ' 0px')
      +                });
      +            }
      +        }
      +
      +        _.listWidth = _.$list.width();
      +        _.listHeight = _.$list.height();
      +
      +
      +        if (_.options.vertical === false && _.options.variableWidth === false) {
      +            _.slideWidth = Math.ceil(_.listWidth / _.options.slidesToShow);
      +            _.$slideTrack.width(Math.ceil((_.slideWidth * _.$slideTrack.children('.slick-slide').length)));
      +
      +        } else if (_.options.variableWidth === true) {
      +            _.$slideTrack.width(5000 * _.slideCount);
      +        } else {
      +            _.slideWidth = Math.ceil(_.listWidth);
      +            _.$slideTrack.height(Math.ceil((_.$slides.first().outerHeight(true) * _.$slideTrack.children('.slick-slide').length)));
      +        }
      +
      +        var offset = _.$slides.first().outerWidth(true) - _.$slides.first().width();
      +        if (_.options.variableWidth === false) _.$slideTrack.children('.slick-slide').width(_.slideWidth - offset);
      +
      +    };*/
      +	
      +    Slick.prototype.setDimensions = function() {
      +
      +        var _ = this;
      +
      +        if (_.options.vertical === false) {
      +            if (_.options.centerMode === true) {
      +                _.$list.css({
      +                    padding: ('0px ' + _.options.centerPadding)
      +                });
      +            }
      +        } else {
      +            _.$list.height(_.$slides.first().outerHeight(true) * _.options.slidesToShow);
      +            if (_.options.centerMode === true) {
      +                _.$list.css({
      +                    padding: (_.options.centerPadding + ' 0px')
      +                });
      +            }
      +        }
      +
      +		var $space 			= _.options.thzSpace != undefined ? _.options.thzSpace : 0;
      +		var $slidesToShow 	= _.options.slidesToShow;
      +
      +		if ( $space > 0 ) {
      +			
      +			
      +			if(_.options.vertical === false){
      +			
      +				_.$slideTrack.children('.slick-slide').css({
      +					paddingRight: $space + 'px',
      +				});
      +	
      +				_.$list.css({
      +					marginRight: - Math.abs( $space  ) + 'px',
      +				});
      +				
      +			}else{
      +				
      +				_.$slideTrack.children('.slick-slide').css({
      +					paddingBottom: $space + 'px',
      +				});
      +	
      +				_.$list.css({
      +					marginBottom: - Math.abs( $space  ) + 'px',
      +				});				
      +				
      +			}
      +		}
      +		
      +		var $floorSize		= Math.floor( ( _.$slider.parent().outerWidth() + $space ) / $slidesToShow );
      +		var $difference 	= ( _.$slider.parent().outerWidth() + $space ) - ( $floorSize * $slidesToShow );
      +		
      +		if($difference > 0){
      +			_.$slider.css({
      +				borderRight: $difference + 'px solid transparent',
      +			});
      +		}else{
      +			_.$slider.css({
      +				borderRight: '',
      +			});
      +			
      +		}
      +
      +        _.listWidth = _.$list.width();
      +        _.listHeight = _.$list.height();
      +
      +
      +	     if (_.options.vertical === false && _.options.variableWidth === false) {
      +            _.slideWidth = Math.floor(_.listWidth / _.options.slidesToShow);
      +            _.$slideTrack.width(Math.floor((_.slideWidth * _.$slideTrack.children('.slick-slide').length)));
      +
      +        } else if (_.options.variableWidth === true) {
      +			
      +            _.$slideTrack.width(5000 * _.slideCount);
      +			
      +	    } else {
      +           
      +		    _.slideWidth = Math.floor(_.listWidth);
      +			
      +			if (_.options.verticalReverse === false) {
      +            
      +				_.$slideTrack.height(Math.floor((_.$slides.first().outerHeight(true) * _.$slideTrack.children('.slick-slide').length)));
      +			
      +			}
      +        }
      +
      +        var offset = _.$slides.first().outerWidth(true) - _.$slides.first().width();
      +        if (_.options.variableWidth === false) _.$slideTrack.children('.slick-slide').width(_.slideWidth - offset);
      +
      +    };
      +
      +    Slick.prototype.setFade = function() {
      +
      +        var _ = this,
      +            targetLeft;
      +
      +        _.$slides.each(function(index, element) {
      +            targetLeft = (_.slideWidth * index) * -1;
      +            if (_.options.rtl === true) {
      +                $(element).css({
      +                    position: 'relative',
      +                    right: targetLeft,
      +                    top: 0,
      +                    zIndex: _.options.zIndex - 2,
      +                    opacity: 0
      +                });
      +            } else {
      +                $(element).css({
      +                    position: 'relative',
      +                    left: targetLeft,
      +                    top: 0,
      +                    zIndex: _.options.zIndex - 2,
      +                    opacity: 0
      +                });
      +            }
      +        });
      +
      +        _.$slides.eq(_.currentSlide).css({
      +            zIndex: _.options.zIndex - 1,
      +            opacity: 1
      +        });
      +
      +    };
      +
      +    Slick.prototype.setHeight = function() {
      +
      +        var _ = this;
      +
      +        if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {
      +            var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);
      +            _.$list.css('height', targetHeight);
      +        }
      +
      +    };
      +
      +    Slick.prototype.setOption =
      +    Slick.prototype.slickSetOption = function() {
      +
      +        /**
      +         * accepts arguments in format of:
      +         *
      +         *  - for changing a single option's value:
      +         *     .slick("setOption", option, value, refresh )
      +         *
      +         *  - for changing a set of responsive options:
      +         *     .slick("setOption", 'responsive', [{}, ...], refresh )
      +         *
      +         *  - for updating multiple values at once (not responsive)
      +         *     .slick("setOption", { 'option': value, ... }, refresh )
      +         */
      +
      +        var _ = this, l, item, option, value, refresh = false, type;
      +
      +        if( $.type( arguments[0] ) === 'object' ) {
      +
      +            option =  arguments[0];
      +            refresh = arguments[1];
      +            type = 'multiple';
      +
      +        } else if ( $.type( arguments[0] ) === 'string' ) {
      +
      +            option =  arguments[0];
      +            value = arguments[1];
      +            refresh = arguments[2];
      +
      +            if ( arguments[0] === 'responsive' && $.type( arguments[1] ) === 'array' ) {
      +
      +                type = 'responsive';
      +
      +            } else if ( typeof arguments[1] !== 'undefined' ) {
      +
      +                type = 'single';
      +
      +            }
      +
      +        }
      +
      +        if ( type === 'single' ) {
      +
      +            _.options[option] = value;
      +
      +
      +        } else if ( type === 'multiple' ) {
      +
      +            $.each( option , function( opt, val ) {
      +
      +                _.options[opt] = val;
      +
      +            });
      +
      +
      +        } else if ( type === 'responsive' ) {
      +
      +            for ( item in value ) {
      +
      +                if( $.type( _.options.responsive ) !== 'array' ) {
      +
      +                    _.options.responsive = [ value[item] ];
      +
      +                } else {
      +
      +                    l = _.options.responsive.length-1;
      +
      +                    // loop through the responsive object and splice out duplicates.
      +                    while( l >= 0 ) {
      +
      +                        if( _.options.responsive[l].breakpoint === value[item].breakpoint ) {
      +
      +                            _.options.responsive.splice(l,1);
      +
      +                        }
      +
      +                        l--;
      +
      +                    }
      +
      +                    _.options.responsive.push( value[item] );
      +
      +                }
      +
      +            }
      +
      +        }
      +
      +        if ( refresh ) {
      +
      +            _.unload();
      +            _.reinit();
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.setPosition = function() {
      +
      +        var _ = this;
      +
      +        _.setDimensions();
      +
      +        _.setHeight();
      +
      +        if (_.options.fade === false) {
      +            _.setCSS(_.getLeft(_.currentSlide));
      +        } else {
      +            _.setFade();
      +        }
      +
      +        _.$slider.trigger('setPosition', [_]);
      +
      +    };
      +
      +    Slick.prototype.setProps = function() {
      +
      +        var _ = this,
      +            bodyStyle = document.body.style;
      +
      +        _.positionProp = _.options.vertical === true ? 'top' : 'left';
      +
      +        if (_.positionProp === 'top') {
      +            _.$slider.addClass('slick-vertical');
      +        } else {
      +            _.$slider.removeClass('slick-vertical');
      +        }
      +
      +        if (bodyStyle.WebkitTransition !== undefined ||
      +            bodyStyle.MozTransition !== undefined ||
      +            bodyStyle.msTransition !== undefined) {
      +            if (_.options.useCSS === true) {
      +                _.cssTransitions = true;
      +            }
      +        }
      +
      +        if ( _.options.fade ) {
      +            if ( typeof _.options.zIndex === 'number' ) {
      +                if( _.options.zIndex < 3 ) {
      +                    _.options.zIndex = 3;
      +                }
      +            } else {
      +                _.options.zIndex = _.defaults.zIndex;
      +            }
      +        }
      +
      +        if (bodyStyle.OTransform !== undefined) {
      +            _.animType = 'OTransform';
      +            _.transformType = '-o-transform';
      +            _.transitionType = 'OTransition';
      +            if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;
      +        }
      +        if (bodyStyle.MozTransform !== undefined) {
      +            _.animType = 'MozTransform';
      +            _.transformType = '-moz-transform';
      +            _.transitionType = 'MozTransition';
      +            if (bodyStyle.perspectiveProperty === undefined && bodyStyle.MozPerspective === undefined) _.animType = false;
      +        }
      +        if (bodyStyle.webkitTransform !== undefined) {
      +            _.animType = 'webkitTransform';
      +            _.transformType = '-webkit-transform';
      +            _.transitionType = 'webkitTransition';
      +            if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;
      +        }
      +        if (bodyStyle.msTransform !== undefined) {
      +            _.animType = 'msTransform';
      +            _.transformType = '-ms-transform';
      +            _.transitionType = 'msTransition';
      +            if (bodyStyle.msTransform === undefined) _.animType = false;
      +        }
      +        if (bodyStyle.transform !== undefined && _.animType !== false) {
      +            _.animType = 'transform';
      +            _.transformType = 'transform';
      +            _.transitionType = 'transition';
      +        }
      +        _.transformsEnabled = _.options.useTransform && (_.animType !== null && _.animType !== false);
      +    };
      +
      +
      +    Slick.prototype.setSlideClasses = function(index) {
      +
      +        var _ = this,
      +            centerOffset, allSlides, indexOffset, remainder;
      +
      +        allSlides = _.$slider
      +            .find('.slick-slide')
      +            .removeClass('slick-active slick-center slick-current')
      +            .attr('aria-hidden', 'true');
      +
      +        _.$slides
      +            .eq(index)
      +            .addClass('slick-current');
      +
      +        if (_.options.centerMode === true) {
      +
      +            var evenCoef = _.options.slidesToShow % 2 === 0 ? 1 : 0;
      +
      +            centerOffset = Math.floor(_.options.slidesToShow / 2);
      +
      +            if (_.options.infinite === true) {
      +
      +                if (index >= centerOffset && index <= (_.slideCount - 1) - centerOffset) {
      +                    _.$slides
      +                        .slice(index - centerOffset + evenCoef, index + centerOffset + 1)
      +                        .addClass('slick-active')
      +                        .attr('aria-hidden', 'false');
      +
      +                } else {
      +
      +                    indexOffset = _.options.slidesToShow + index;
      +                    allSlides
      +                        .slice(indexOffset - centerOffset + 1 + evenCoef, indexOffset + centerOffset + 2)
      +                        .addClass('slick-active')
      +                        .attr('aria-hidden', 'false');
      +
      +                }
      +
      +                if (index === 0) {
      +
      +                    allSlides
      +                        .eq(allSlides.length - 1 - _.options.slidesToShow)
      +                        .addClass('slick-center');
      +
      +                } else if (index === _.slideCount - 1) {
      +
      +                    allSlides
      +                        .eq(_.options.slidesToShow)
      +                        .addClass('slick-center');
      +
      +                }
      +
      +            }
      +
      +            _.$slides
      +                .eq(index)
      +                .addClass('slick-center');
      +
      +        } else {
      +
      +            if (index >= 0 && index <= (_.slideCount - _.options.slidesToShow)) {
      +
      +                _.$slides
      +                    .slice(index, index + _.options.slidesToShow)
      +                    .addClass('slick-active')
      +                    .attr('aria-hidden', 'false');
      +
      +            } else if (allSlides.length <= _.options.slidesToShow) {
      +
      +                allSlides
      +                    .addClass('slick-active')
      +                    .attr('aria-hidden', 'false');
      +
      +            } else {
      +
      +                remainder = _.slideCount % _.options.slidesToShow;
      +                indexOffset = _.options.infinite === true ? _.options.slidesToShow + index : index;
      +
      +                if (_.options.slidesToShow == _.options.slidesToScroll && (_.slideCount - index) < _.options.slidesToShow) {
      +
      +                    allSlides
      +                        .slice(indexOffset - (_.options.slidesToShow - remainder), indexOffset + remainder)
      +                        .addClass('slick-active')
      +                        .attr('aria-hidden', 'false');
      +
      +                } else {
      +
      +                    allSlides
      +                        .slice(indexOffset, indexOffset + _.options.slidesToShow)
      +                        .addClass('slick-active')
      +                        .attr('aria-hidden', 'false');
      +
      +                }
      +
      +            }
      +
      +        }
      +
      +        if (_.options.lazyLoad === 'ondemand' || _.options.lazyLoad === 'anticipated') {
      +            _.lazyLoad();
      +        }
      +    };
      +
      +/*    Slick.prototype.setupInfinite = function() {
      +
      +        var _ = this,
      +            i, slideIndex, infiniteCount;
      +
      +        if (_.options.fade === true) {
      +            _.options.centerMode = false;
      +        }
      +
      +        if (_.options.infinite === true && _.options.fade === false) {
      +
      +            slideIndex = null;
      +
      +            if (_.slideCount > _.options.slidesToShow) {
      +
      +                if (_.options.centerMode === true) {
      +                    infiniteCount = _.options.slidesToShow + 1;
      +                } else {
      +                    infiniteCount = _.options.slidesToShow;
      +                }
      +
      +                for (i = _.slideCount; i > (_.slideCount -
      +                        infiniteCount); i -= 1) {
      +                    slideIndex = i - 1;
      +                    $(_.$slides[slideIndex]).clone(true).attr('id', '')
      +                        .attr('data-slick-index', slideIndex - _.slideCount)
      +                        .prependTo(_.$slideTrack).addClass('slick-cloned');
      +                }
      +                for (i = 0; i < infiniteCount  + _.slideCount; i += 1) {
      +                    slideIndex = i;
      +                    $(_.$slides[slideIndex]).clone(true).attr('id', '')
      +                        .attr('data-slick-index', slideIndex + _.slideCount)
      +                        .appendTo(_.$slideTrack).addClass('slick-cloned');
      +                }
      +                _.$slideTrack.find('.slick-cloned').find('[id]').each(function() {
      +                    $(this).attr('id', '');
      +                });
      +
      +            }
      +
      +        }
      +
      +    };*/
      +
      +    Slick.prototype.setupInfinite = function() {
      +
      +        var _ = this,
      +            i, slideIndex, infiniteCount;
      +
      +        if (_.options.fade === true) {
      +            _.options.centerMode = false;
      +        }
      +
      +        if (_.options.infinite === true && _.options.fade === false) {
      +
      +            slideIndex = null;
      +
      +            if (_.slideCount > _.options.slidesToShow) {
      +
      +                if (_.options.centerMode === true) {
      +                    infiniteCount = _.options.slidesToShow + 1;
      +                } else {
      +                    infiniteCount = _.options.slidesToShow;
      +                }
      +
      +                for (i = _.slideCount; i > (_.slideCount -
      +                        infiniteCount); i -= 1) {
      +                    slideIndex = i - 1;
      +                    $(_.$slides[slideIndex]).clone(true)
      +                        .attr('data-slick-index', slideIndex - _.slideCount)
      +                        .prependTo(_.$slideTrack).addClass('slick-cloned');
      +                }
      +                for (i = 0; i < infiniteCount; i += 1) {
      +                    slideIndex = i;
      +                    $(_.$slides[slideIndex]).clone(true)
      +                        .attr('data-slick-index', slideIndex + _.slideCount)
      +                        .appendTo(_.$slideTrack).addClass('slick-cloned');
      +                }
      +
      +            }
      +
      +        }
      +
      +    };
      +	
      +    Slick.prototype.interrupt = function( toggle ) {
      +
      +        var _ = this;
      +
      +        if( !toggle ) {
      +            _.autoPlay();
      +        }
      +        _.interrupted = toggle;
      +
      +    };
      +
      +    Slick.prototype.selectHandler = function(event) {
      +
      +        var _ = this;
      +
      +        var targetElement =
      +            $(event.target).is('.slick-slide') ?
      +                $(event.target) :
      +                $(event.target).parents('.slick-slide');
      +
      +        var index = parseInt(targetElement.attr('data-slick-index'));
      +
      +        if (!index) index = 0;
      +
      +        if (_.slideCount <= _.options.slidesToShow) {
      +
      +            _.slideHandler(index, false, true);
      +            return;
      +
      +        }
      +
      +        _.slideHandler(index);
      +
      +    };
      +
      +    Slick.prototype.slideHandler = function(index, sync, dontAnimate) {
      +
      +        var targetSlide, animSlide, oldSlide, slideLeft, targetLeft = null,
      +            _ = this, navTarget;
      +
      +        sync = sync || false;
      +
      +        if (_.animating === true && _.options.waitForAnimate === true) {
      +            return;
      +        }
      +
      +        if (_.options.fade === true && _.currentSlide === index) {
      +            return;
      +        }
      +
      +        if (sync === false) {
      +            _.asNavFor(index);
      +        }
      +
      +        targetSlide = index;
      +        targetLeft = _.getLeft(targetSlide);
      +        slideLeft = _.getLeft(_.currentSlide);
      +
      +        _.currentLeft = _.swipeLeft === null ? slideLeft : _.swipeLeft;
      +
      +        if (_.options.infinite === false && _.options.centerMode === false && (index < 0 || index > _.getDotCount() * _.options.slidesToScroll)) {
      +            if (_.options.fade === false) {
      +                targetSlide = _.currentSlide;
      +                if (dontAnimate !== true && _.slideCount > _.options.slidesToShow) {
      +                    _.animateSlide(slideLeft, function() {
      +                        _.postSlide(targetSlide);
      +                    });
      +                } else {
      +                    _.postSlide(targetSlide);
      +                }
      +            }
      +            return;
      +        } else if (_.options.infinite === false && _.options.centerMode === true && (index < 0 || index > (_.slideCount - _.options.slidesToScroll))) {
      +            if (_.options.fade === false) {
      +                targetSlide = _.currentSlide;
      +                if (dontAnimate !== true && _.slideCount > _.options.slidesToShow) {
      +                    _.animateSlide(slideLeft, function() {
      +                        _.postSlide(targetSlide);
      +                    });
      +                } else {
      +                    _.postSlide(targetSlide);
      +                }
      +            }
      +            return;
      +        }
      +
      +        if ( _.options.autoplay ) {
      +            clearInterval(_.autoPlayTimer);
      +        }
      +
      +        if (targetSlide < 0) {
      +            if (_.slideCount % _.options.slidesToScroll !== 0) {
      +                animSlide = _.slideCount - (_.slideCount % _.options.slidesToScroll);
      +            } else {
      +                animSlide = _.slideCount + targetSlide;
      +            }
      +        } else if (targetSlide >= _.slideCount) {
      +            if (_.slideCount % _.options.slidesToScroll !== 0) {
      +                animSlide = 0;
      +            } else {
      +                animSlide = targetSlide - _.slideCount;
      +            }
      +        } else {
      +            animSlide = targetSlide;
      +        }
      +
      +        _.animating = true;
      +
      +        _.$slider.trigger('beforeChange', [_, _.currentSlide, animSlide]);
      +
      +        oldSlide = _.currentSlide;
      +        _.currentSlide = animSlide;
      +
      +        _.setSlideClasses(_.currentSlide);
      +
      +        if ( _.options.asNavFor ) {
      +
      +            navTarget = _.getNavTarget();
      +            navTarget = navTarget.slick('getSlick');
      +
      +            if ( navTarget.slideCount <= navTarget.options.slidesToShow ) {
      +                navTarget.setSlideClasses(_.currentSlide);
      +            }
      +
      +        }
      +
      +        _.updateDots();
      +        _.updateArrows();
      +
      +        if (_.options.fade === true) {
      +            if (dontAnimate !== true) {
      +
      +                _.fadeSlideOut(oldSlide);
      +
      +                _.fadeSlide(animSlide, function() {
      +                    _.postSlide(animSlide);
      +                });
      +
      +            } else {
      +                _.postSlide(animSlide);
      +            }
      +            _.animateHeight();
      +            return;
      +        }
      +
      +        if (dontAnimate !== true && _.slideCount > _.options.slidesToShow) {
      +            _.animateSlide(targetLeft, function() {
      +                _.postSlide(animSlide);
      +            });
      +        } else {
      +            _.postSlide(animSlide);
      +        }
      +
      +    };
      +
      +    Slick.prototype.startLoad = function() {
      +
      +        var _ = this;
      +
      +        if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
      +
      +            _.$prevArrow.hide();
      +            _.$nextArrow.hide();
      +
      +        }
      +
      +        if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
      +
      +            _.$dots.hide();
      +
      +        }
      +
      +        _.$slider.addClass('slick-loading');
      +
      +    };
      +
      +/*    Slick.prototype.swipeDirection = function() {
      +
      +        var xDist, yDist, r, swipeAngle, _ = this;
      +
      +        xDist = _.touchObject.startX - _.touchObject.curX;
      +        yDist = _.touchObject.startY - _.touchObject.curY;
      +        r = Math.atan2(yDist, xDist);
      +
      +        swipeAngle = Math.round(r * 180 / Math.PI);
      +        if (swipeAngle < 0) {
      +            swipeAngle = 360 - Math.abs(swipeAngle);
      +        }
      +
      +        if ((swipeAngle <= 45) && (swipeAngle >= 0)) {
      +            return (_.options.rtl === false ? 'left' : 'right');
      +        }
      +        if ((swipeAngle <= 360) && (swipeAngle >= 315)) {
      +            return (_.options.rtl === false ? 'left' : 'right');
      +        }
      +        if ((swipeAngle >= 135) && (swipeAngle <= 225)) {
      +            return (_.options.rtl === false ? 'right' : 'left');
      +        }
      +        if (_.options.verticalSwiping === true) {
      +            if ((swipeAngle >= 35) && (swipeAngle <= 135)) {
      +                return 'down';
      +            } else {
      +                return 'up';
      +            }
      +        }
      +
      +        return 'vertical';
      +
      +    };*/
      +	
      +    Slick.prototype.swipeDirection = function() {
      +
      +        var xDist, yDist, r, swipeAngle, _ = this;
      +
      +        xDist = _.touchObject.startX - _.touchObject.curX;
      +        yDist = _.touchObject.startY - _.touchObject.curY;
      +        r = Math.atan2(yDist, xDist);
      +
      +        swipeAngle = Math.round(r * 180 / Math.PI);
      +        if (swipeAngle < 0) {
      +            swipeAngle = 360 - Math.abs(swipeAngle);
      +        }
      +
      +        if ((swipeAngle <= 45) && (swipeAngle >= 0)) {
      +            return (_.options.rtl === false ? 'left' : 'right');
      +        }
      +        if ((swipeAngle <= 360) && (swipeAngle >= 315)) {
      +            return (_.options.rtl === false ? 'left' : 'right');
      +        }
      +        if ((swipeAngle >= 135) && (swipeAngle <= 225)) {
      +            return (_.options.rtl === false ? 'right' : 'left');
      +        }
      +        if (_.options.verticalSwiping === true) {
      +			
      +			if (_.options.verticalReverse === false) {
      +			
      +				if ((swipeAngle >= 35) && (swipeAngle <= 135)) {
      +					return 'down';
      +				} else {
      +					return 'up';
      +				}
      +			
      +			}else{
      +				
      +				if ((swipeAngle >= 35) && (swipeAngle <= 135)) {
      +					return 'up';
      +				} else {
      +					return 'down';
      +				}				
      +				
      +			}
      +        }
      +
      +        return 'vertical';
      +
      +    };
      +	
      +    Slick.prototype.swipeEnd = function(event) {
      +
      +        var _ = this,
      +            slideCount,
      +            direction;
      +
      +        _.dragging = false;
      +        _.swiping = false;
      +
      +        if (_.scrolling) {
      +            _.scrolling = false;
      +            return false;
      +        }
      +
      +        _.interrupted = false;
      +        _.shouldClick = ( _.touchObject.swipeLength > 10 ) ? false : true;
      +
      +        if ( _.touchObject.curX === undefined ) {
      +            return false;
      +        }
      +
      +        if ( _.touchObject.edgeHit === true ) {
      +            _.$slider.trigger('edge', [_, _.swipeDirection() ]);
      +        }
      +
      +        if ( _.touchObject.swipeLength >= _.touchObject.minSwipe ) {
      +
      +            direction = _.swipeDirection();
      +
      +            switch ( direction ) {
      +
      +                case 'left':
      +                case 'down':
      +
      +                    slideCount =
      +                        _.options.swipeToSlide ?
      +                            _.checkNavigable( _.currentSlide + _.getSlideCount() ) :
      +                            _.currentSlide + _.getSlideCount();
      +
      +                    _.currentDirection = 0;
      +
      +                    break;
      +
      +                case 'right':
      +                case 'up':
      +
      +                    slideCount =
      +                        _.options.swipeToSlide ?
      +                            _.checkNavigable( _.currentSlide - _.getSlideCount() ) :
      +                            _.currentSlide - _.getSlideCount();
      +
      +                    _.currentDirection = 1;
      +
      +                    break;
      +
      +                default:
      +
      +
      +            }
      +
      +            if( direction != 'vertical' ) {
      +
      +                _.slideHandler( slideCount );
      +                _.touchObject = {};
      +                _.$slider.trigger('swipe', [_, direction ]);
      +
      +            }
      +
      +        } else {
      +
      +            if ( _.touchObject.startX !== _.touchObject.curX ) {
      +
      +                _.slideHandler( _.currentSlide );
      +                _.touchObject = {};
      +
      +            }
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.swipeHandler = function(event) {
      +
      +        var _ = this;
      +
      +        if ((_.options.swipe === false) || ('ontouchend' in document && _.options.swipe === false)) {
      +            return;
      +        } else if (_.options.draggable === false && event.type.indexOf('mouse') !== -1) {
      +            return;
      +        }
      +
      +        _.touchObject.fingerCount = event.originalEvent && event.originalEvent.touches !== undefined ?
      +            event.originalEvent.touches.length : 1;
      +
      +        _.touchObject.minSwipe = _.listWidth / _.options
      +            .touchThreshold;
      +
      +        if (_.options.verticalSwiping === true) {
      +            _.touchObject.minSwipe = _.listHeight / _.options
      +                .touchThreshold;
      +        }
      +
      +        switch (event.data.action) {
      +
      +            case 'start':
      +                _.swipeStart(event);
      +                break;
      +
      +            case 'move':
      +                _.swipeMove(event);
      +                break;
      +
      +            case 'end':
      +                _.swipeEnd(event);
      +                break;
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.swipeMove = function(event) {
      +
      +        var _ = this,
      +            edgeWasHit = false,
      +            curLeft, swipeDirection, swipeLength, positionOffset, touches, verticalSwipeLength;
      +
      +        touches = event.originalEvent !== undefined ? event.originalEvent.touches : null;
      +
      +        if (!_.dragging || _.scrolling || touches && touches.length !== 1) {
      +            return false;
      +        }
      +
      +        curLeft = _.getLeft(_.currentSlide);
      +
      +        _.touchObject.curX = touches !== undefined ? touches[0].pageX : event.clientX;
      +        _.touchObject.curY = touches !== undefined ? touches[0].pageY : event.clientY;
      +
      +        _.touchObject.swipeLength = Math.round(Math.sqrt(
      +            Math.pow(_.touchObject.curX - _.touchObject.startX, 2)));
      +
      +        verticalSwipeLength = Math.round(Math.sqrt(
      +            Math.pow(_.touchObject.curY - _.touchObject.startY, 2)));
      +
      +        if (!_.options.verticalSwiping && !_.swiping && verticalSwipeLength > 4) {
      +            _.scrolling = true;
      +            return false;
      +        }
      +
      +        if (_.options.verticalSwiping === true) {
      +            _.touchObject.swipeLength = verticalSwipeLength;
      +        }
      +
      +        swipeDirection = _.swipeDirection();
      +
      +        if (event.originalEvent !== undefined && _.touchObject.swipeLength > 4) {
      +            _.swiping = true;
      +            event.preventDefault();
      +        }
      +
      +        positionOffset = (_.options.rtl === false ? 1 : -1) * (_.touchObject.curX > _.touchObject.startX ? 1 : -1);
      +        if (_.options.verticalSwiping === true) {
      +            positionOffset = _.touchObject.curY > _.touchObject.startY ? 1 : -1;
      +        }
      +
      +
      +        swipeLength = _.touchObject.swipeLength;
      +
      +        _.touchObject.edgeHit = false;
      +
      +        if (_.options.infinite === false) {
      +            if ((_.currentSlide === 0 && swipeDirection === 'right') || (_.currentSlide >= _.getDotCount() && swipeDirection === 'left')) {
      +                swipeLength = _.touchObject.swipeLength * _.options.edgeFriction;
      +                _.touchObject.edgeHit = true;
      +            }
      +        }
      +
      +        if (_.options.vertical === false) {
      +            _.swipeLeft = curLeft + swipeLength * positionOffset;
      +        } else {
      +            _.swipeLeft = curLeft + (swipeLength * (_.$list.height() / _.listWidth)) * positionOffset;
      +        }
      +        if (_.options.verticalSwiping === true) {
      +            _.swipeLeft = curLeft + swipeLength * positionOffset;
      +        }
      +
      +        if (_.options.fade === true || _.options.touchMove === false) {
      +            return false;
      +        }
      +
      +        if (_.animating === true) {
      +            _.swipeLeft = null;
      +            return false;
      +        }
      +
      +        _.setCSS(_.swipeLeft);
      +
      +    };
      +
      +    Slick.prototype.swipeStart = function(event) {
      +
      +        var _ = this,
      +            touches;
      +
      +        _.interrupted = true;
      +
      +        if (_.touchObject.fingerCount !== 1 || _.slideCount <= _.options.slidesToShow) {
      +            _.touchObject = {};
      +            return false;
      +        }
      +
      +        if (event.originalEvent !== undefined && event.originalEvent.touches !== undefined) {
      +            touches = event.originalEvent.touches[0];
      +        }
      +
      +
      +        _.touchObject.startX = _.touchObject.curX = touches !== undefined ? touches.pageX : event.clientX;
      +        _.touchObject.startY = _.touchObject.curY = touches !== undefined ? touches.pageY : event.clientY;
      +
      +        _.dragging = true;
      +
      +    };
      +
      +    Slick.prototype.unfilterSlides = Slick.prototype.slickUnfilter = function() {
      +
      +        var _ = this;
      +
      +        if (_.$slidesCache !== null) {
      +
      +            _.unload();
      +
      +            _.$slideTrack.children(this.options.slide).detach();
      +
      +            _.$slidesCache.appendTo(_.$slideTrack);
      +
      +            _.reinit();
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.unload = function() {
      +
      +        var _ = this;
      +
      +        $('.slick-cloned', _.$slider).remove();
      +
      +        if (_.$dots) {
      +            _.$dots.remove();
      +        }
      +
      +        if (_.$prevArrow && _.htmlExpr.test(_.options.prevArrow)) {
      +            _.$prevArrow.remove();
      +        }
      +
      +        if (_.$nextArrow && _.htmlExpr.test(_.options.nextArrow)) {
      +            _.$nextArrow.remove();
      +        }
      +
      +        _.$slides
      +            .removeClass('slick-slide slick-active slick-visible slick-current')
      +            .attr('aria-hidden', 'true')
      +            .css('width', '');
      +
      +    };
      +
      +    Slick.prototype.unslick = function(fromBreakpoint) {
      +
      +        var _ = this;
      +        _.$slider.trigger('unslick', [_, fromBreakpoint]);
      +        _.destroy();
      +
      +    };
      +
      +    Slick.prototype.updateArrows = function() {
      +
      +        var _ = this,
      +            centerOffset;
      +
      +        centerOffset = Math.floor(_.options.slidesToShow / 2);
      +
      +        if ( _.options.arrows === true &&
      +            _.slideCount > _.options.slidesToShow &&
      +            !_.options.infinite ) {
      +
      +            _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
      +            _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
      +
      +            if (_.currentSlide === 0) {
      +
      +                _.$prevArrow.addClass('slick-disabled').attr('aria-disabled', 'true');
      +                _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
      +
      +            } else if (_.currentSlide >= _.slideCount - _.options.slidesToShow && _.options.centerMode === false) {
      +
      +                _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true');
      +                _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
      +
      +            } else if (_.currentSlide >= _.slideCount - 1 && _.options.centerMode === true) {
      +
      +                _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true');
      +                _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
      +
      +            }
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.updateDots = function() {
      +
      +        var _ = this;
      +
      +        if (_.$dots !== null) {
      +
      +            _.$dots
      +                .find('li')
      +                    .removeClass('slick-active')
      +                    .end();
      +
      +            _.$dots
      +                .find('li')
      +                .eq(Math.floor(_.currentSlide / _.options.slidesToScroll))
      +                .addClass('slick-active');
      +
      +        }
      +
      +    };
      +
      +    Slick.prototype.visibility = function() {
      +
      +        var _ = this;
      +
      +        if ( _.options.autoplay ) {
      +
      +            if ( document[_.hidden] ) {
      +
      +                _.interrupted = true;
      +
      +            } else {
      +
      +                _.interrupted = false;
      +
      +            }
      +
      +        }
      +
      +    };
      +
      +    $.fn.slick = function() {
      +        var _ = this,
      +            opt = arguments[0],
      +            args = Array.prototype.slice.call(arguments, 1),
      +            l = _.length,
      +            i,
      +            ret;
      +        for (i = 0; i < l; i++) {
      +            if (typeof opt == 'object' || typeof opt == 'undefined')
      +                _[i].slick = new Slick(_[i], opt);
      +            else
      +                ret = _[i].slick[opt].apply(_[i].slick, args);
      +            if (typeof ret != 'undefined') return ret;
      +        }
      +        return _;
      +    };
      +
      +}));
      diff --git a/assets/js/dev/vendors/sticky-kit.js b/assets/js/dev/vendors/sticky-kit.js
      new file mode 100644
      index 0000000..376d771
      --- /dev/null
      +++ b/assets/js/dev/vendors/sticky-kit.js
      @@ -0,0 +1,265 @@
      +// Generated by CoffeeScript 1.10.0
      +
      +/**
      +@license Sticky-kit v1.1.3 | MIT | Leaf Corcoran 2015 | http://leafo.net
      + */
      +
      +(function() {
      +  var $, win;
      +
      +  $ = window.jQuery;
      +
      +  win = $(window);
      +
      +  $.fn.stick_in_parent = function(opts) {
      +    var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
      +    if (opts == null) {
      +      opts = {};
      +    }
      +    sticky_class = opts.sticky_class, inner_scrolling = opts.inner_scrolling, recalc_every = opts.recalc_every, parent_selector = opts.parent, offset_top = opts.offset_top, manual_spacer = opts.spacer, enable_bottoming = opts.bottoming;
      +    if (offset_top == null) {
      +      offset_top = 0;
      +    }
      +    if (parent_selector == null) {
      +      parent_selector = void 0;
      +    }
      +    if (inner_scrolling == null) {
      +      inner_scrolling = true;
      +    }
      +    if (sticky_class == null) {
      +      sticky_class = "is_stuck";
      +    }
      +    doc = $(document);
      +    if (enable_bottoming == null) {
      +      enable_bottoming = true;
      +    }
      +    outer_width = function(el) {
      +      var _el, computed, w;
      +      if (window.getComputedStyle) {
      +        _el = el[0];
      +        computed = window.getComputedStyle(el[0]);
      +        w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
      +        if (computed.getPropertyValue("box-sizing") !== "border-box") {
      +          w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
      +        }
      +        return w;
      +      } else {
      +        return el.outerWidth(true);
      +      }
      +    };
      +    fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
      +      var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
      +      if (elm.data("sticky_kit")) {
      +        return;
      +      }
      +      elm.data("sticky_kit", true);
      +      last_scroll_height = doc.height();
      +      parent = elm.parent();
      +      if (parent_selector != null) {
      +        parent = parent.closest(parent_selector);
      +      }
      +      if (!parent.length) {
      +        throw "failed to find stick parent";
      +      }
      +      fixed = false;
      +      bottomed = false;
      +      spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
      +      if (spacer) {
      +        spacer.css('position', elm.css('position'));
      +      }
      +      recalc = function() {
      +        var border_top, padding_top, restore;
      +        if (detached) {
      +          return;
      +        }
      +        last_scroll_height = doc.height();
      +        border_top = parseInt(parent.css("border-top-width"), 10);
      +        padding_top = parseInt(parent.css("padding-top"), 10);
      +        padding_bottom = parseInt(parent.css("padding-bottom"), 10);
      +        parent_top = parent.offset().top + border_top + padding_top;
      +        parent_height = parent.height();
      +        if (fixed) {
      +          fixed = false;
      +          bottomed = false;
      +          if (manual_spacer == null) {
      +            elm.insertAfter(spacer);
      +            spacer.detach();
      +          }
      +          elm.css({
      +            position: "",
      +            top: "",
      +            width: "",
      +            bottom: ""
      +          }).removeClass(sticky_class);
      +          restore = true;
      +        }
      +        top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
      +        height = elm.outerHeight(true);
      +        el_float = elm.css("float");
      +        if (spacer) {
      +          spacer.css({
      +            width: outer_width(elm),
      +            height: height,
      +            display: elm.css("display"),
      +            "vertical-align": elm.css("vertical-align"),
      +            "float": el_float
      +          });
      +        }
      +        if (restore) {
      +          return tick();
      +        }
      +      };
      +      recalc();
      +      if (height === parent_height) {
      +        return;
      +      }
      +      last_pos = void 0;
      +      offset = offset_top;
      +      recalc_counter = recalc_every;
      +      tick = function() {
      +        var css, delta, recalced, scroll, will_bottom, win_height;
      +        if (detached) {
      +          return;
      +        }
      +        recalced = false;
      +        if (recalc_counter != null) {
      +          recalc_counter -= 1;
      +          if (recalc_counter <= 0) {
      +            recalc_counter = recalc_every;
      +            recalc();
      +            recalced = true;
      +          }
      +        }
      +        if (!recalced && doc.height() !== last_scroll_height) {
      +          recalc();
      +          recalced = true;
      +        }
      +        scroll = win.scrollTop();
      +        if (last_pos != null) {
      +          delta = scroll - last_pos;
      +        }
      +        last_pos = scroll;
      +        if (fixed) {
      +          if (enable_bottoming) {
      +            will_bottom = scroll + height + offset > parent_height + parent_top;
      +            if (bottomed && !will_bottom) {
      +              bottomed = false;
      +              elm.css({
      +                position: "fixed",
      +                bottom: "",
      +                top: offset
      +              }).trigger("sticky_kit:unbottom");
      +            }
      +          }
      +          if (scroll < top) {
      +            fixed = false;
      +            offset = offset_top;
      +            if (manual_spacer == null) {
      +              if (el_float === "left" || el_float === "right") {
      +                elm.insertAfter(spacer);
      +              }
      +              spacer.detach();
      +            }
      +            css = {
      +              position: "",
      +              width: "",
      +              top: ""
      +            };
      +            elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
      +          }
      +          if (inner_scrolling) {
      +            win_height = win.height();
      +            if (height + offset_top > win_height) {
      +              if (!bottomed) {
      +                offset -= delta;
      +                offset = Math.max(win_height - height, offset);
      +                offset = Math.min(offset_top, offset);
      +                if (fixed) {
      +                  elm.css({
      +                    top: offset + "px"
      +                  });
      +                }
      +              }
      +            }
      +          }
      +        } else {
      +          if (scroll > top) {
      +            fixed = true;
      +            css = {
      +              position: "fixed",
      +              top: offset
      +            };
      +            css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
      +            elm.css(css).addClass(sticky_class);
      +            if (manual_spacer == null) {
      +              elm.after(spacer);
      +              if (el_float === "left" || el_float === "right") {
      +                spacer.append(elm);
      +              }
      +            }
      +            elm.trigger("sticky_kit:stick");
      +          }
      +        }
      +        if (fixed && enable_bottoming) {
      +          if (will_bottom == null) {
      +            will_bottom = scroll + height + offset > parent_height + parent_top;
      +          }
      +          if (!bottomed && will_bottom) {
      +            bottomed = true;
      +            if (parent.css("position") === "static") {
      +              parent.css({
      +                position: "relative"
      +              });
      +            }
      +            return elm.css({
      +              position: "absolute",
      +              bottom: padding_bottom,
      +              top: "auto"
      +            }).trigger("sticky_kit:bottom");
      +          }
      +        }
      +      };
      +      recalc_and_tick = function() {
      +        recalc();
      +        return tick();
      +      };
      +      detach = function() {
      +        detached = true;
      +        win.off("touchmove", tick);
      +        win.off("scroll", tick);
      +        win.off("resize", recalc_and_tick);
      +        $(document.body).off("sticky_kit:recalc", recalc_and_tick);
      +        elm.off("sticky_kit:detach", detach);
      +        elm.removeData("sticky_kit");
      +        elm.css({
      +          position: "",
      +          bottom: "",
      +          top: "",
      +          width: ""
      +        });
      +        parent.position("position", "");
      +        if (fixed) {
      +          if (manual_spacer == null) {
      +            if (el_float === "left" || el_float === "right") {
      +              elm.insertAfter(spacer);
      +            }
      +            spacer.remove();
      +          }
      +          return elm.removeClass(sticky_class);
      +        }
      +      };
      +      win.on("touchmove", tick);
      +      win.on("scroll", tick);
      +      win.on("resize", recalc_and_tick);
      +      $(document.body).on("sticky_kit:recalc", recalc_and_tick);
      +      elm.on("sticky_kit:detach", detach);
      +      return setTimeout(tick, 0);
      +    };
      +    for (i = 0, len = this.length; i < len; i++) {
      +      elm = this[i];
      +      fn($(elm));
      +    }
      +    return this;
      +  };
      +
      +}).call(this);
      \ No newline at end of file
      diff --git a/assets/js/dev/vendors/twentytwenty.js b/assets/js/dev/vendors/twentytwenty.js
      new file mode 100644
      index 0000000..65712e5
      --- /dev/null
      +++ b/assets/js/dev/vendors/twentytwenty.js
      @@ -0,0 +1,843 @@
      +// jquery.event.move
      +//
      +// 1.3.6
      +//
      +// Stephen Band
      +//
      +// Triggers 'movestart', 'move' and 'moveend' events after
      +// mousemoves following a mousedown cross a distance threshold,
      +// similar to the native 'dragstart', 'drag' and 'dragend' events.
      +// Move events are throttled to animation frames. Move event objects
      +// have the properties:
      +//
      +// pageX:
      +// pageY:   Page coordinates of pointer.
      +// startX:
      +// startY:  Page coordinates of pointer at movestart.
      +// distX:
      +// distY:  Distance the pointer has moved since movestart.
      +// deltaX:
      +// deltaY:  Distance the finger has moved since last event.
      +// velocityX:
      +// velocityY:  Average velocity over last few events.
      +
      +
      +(function (module) {
      +	if (typeof define === 'function' && define.amd) {
      +		// AMD. Register as an anonymous module.
      +		define(['jquery'], module);
      +	} else {
      +		// Browser globals
      +		module(jQuery);
      +	}
      +})(function(jQuery, undefined){
      +
      +	var // Number of pixels a pressed pointer travels before movestart
      +	    // event is fired.
      +	    threshold = 6,
      +	
      +	    add = jQuery.event.add,
      +	
      +	    remove = jQuery.event.remove,
      +
      +	    // Just sugar, so we can have arguments in the same order as
      +	    // add and remove.
      +	    trigger = function(node, type, data) {
      +	    	jQuery.event.trigger(type, data, node);
      +	    },
      +
      +	    // Shim for requestAnimationFrame, falling back to timer. See:
      +	    // see http://paulirish.com/2011/requestanimationframe-for-smart-animating/
      +	    requestFrame = (function(){
      +	    	return (
      +	    		window.requestAnimationFrame ||
      +	    		window.webkitRequestAnimationFrame ||
      +	    		window.mozRequestAnimationFrame ||
      +	    		window.oRequestAnimationFrame ||
      +	    		window.msRequestAnimationFrame ||
      +	    		function(fn, element){
      +	    			return window.setTimeout(function(){
      +	    				fn();
      +	    			}, 25);
      +	    		}
      +	    	);
      +	    })(),
      +	    
      +	    ignoreTags = {
      +	    	textarea: true,
      +	    	input: true,
      +	    	select: true,
      +	    	button: true
      +	    },
      +	    
      +	    mouseevents = {
      +	    	move: 'mousemove',
      +	    	cancel: 'mouseup dragstart',
      +	    	end: 'mouseup'
      +	    },
      +	    
      +	    touchevents = {
      +	    	move: 'touchmove',
      +	    	cancel: 'touchend',
      +	    	end: 'touchend'
      +	    };
      +
      +
      +	// Constructors
      +	
      +	function Timer(fn){
      +		var callback = fn,
      +		    active = false,
      +		    running = false;
      +		
      +		function trigger(time) {
      +			if (active){
      +				callback();
      +				requestFrame(trigger);
      +				running = true;
      +				active = false;
      +			}
      +			else {
      +				running = false;
      +			}
      +		}
      +		
      +		this.kick = function(fn) {
      +			active = true;
      +			if (!running) { trigger(); }
      +		};
      +		
      +		this.end = function(fn) {
      +			var cb = callback;
      +			
      +			if (!fn) { return; }
      +			
      +			// If the timer is not running, simply call the end callback.
      +			if (!running) {
      +				fn();
      +			}
      +			// If the timer is running, and has been kicked lately, then
      +			// queue up the current callback and the end callback, otherwise
      +			// just the end callback.
      +			else {
      +				callback = active ?
      +					function(){ cb(); fn(); } : 
      +					fn ;
      +				
      +				active = true;
      +			}
      +		};
      +	}
      +
      +
      +	// Functions
      +	
      +	function returnTrue() {
      +		return true;
      +	}
      +	
      +	function returnFalse() {
      +		return false;
      +	}
      +	
      +	function preventDefault(e) {
      +		e.preventDefault();
      +	}
      +	
      +	function preventIgnoreTags(e) {
      +		// Don't prevent interaction with form elements.
      +		if (ignoreTags[ e.target.tagName.toLowerCase() ]) { return; }
      +		
      +		e.preventDefault();
      +	}
      +
      +	function isLeftButton(e) {
      +		// Ignore mousedowns on any button other than the left (or primary)
      +		// mouse button, or when a modifier key is pressed.
      +		return (e.which === 1 && !e.ctrlKey && !e.altKey);
      +	}
      +
      +	function identifiedTouch(touchList, id) {
      +		var i, l;
      +
      +		if (touchList.identifiedTouch) {
      +			return touchList.identifiedTouch(id);
      +		}
      +		
      +		// touchList.identifiedTouch() does not exist in
      +		// webkit yet… we must do the search ourselves...
      +		
      +		i = -1;
      +		l = touchList.length;
      +		
      +		while (++i < l) {
      +			if (touchList[i].identifier === id) {
      +				return touchList[i];
      +			}
      +		}
      +	}
      +
      +	function changedTouch(e, event) {
      +		var touch = identifiedTouch(e.changedTouches, event.identifier);
      +
      +		// This isn't the touch you're looking for.
      +		if (!touch) { return; }
      +
      +		// Chrome Android (at least) includes touches that have not
      +		// changed in e.changedTouches. That's a bit annoying. Check
      +		// that this touch has changed.
      +		if (touch.pageX === event.pageX && touch.pageY === event.pageY) { return; }
      +
      +		return touch;
      +	}
      +
      +
      +	// Handlers that decide when the first movestart is triggered
      +	
      +	function mousedown(e){
      +		var data;
      +
      +		if (!isLeftButton(e)) { return; }
      +
      +		data = {
      +			target: e.target,
      +			startX: e.pageX,
      +			startY: e.pageY,
      +			timeStamp: e.timeStamp
      +		};
      +
      +		add(document, mouseevents.move, mousemove, data);
      +		add(document, mouseevents.cancel, mouseend, data);
      +	}
      +
      +	function mousemove(e){
      +		var data = e.data;
      +
      +		checkThreshold(e, data, e, removeMouse);
      +	}
      +
      +	function mouseend(e) {
      +		removeMouse();
      +	}
      +
      +	function removeMouse() {
      +		remove(document, mouseevents.move, mousemove);
      +		remove(document, mouseevents.cancel, mouseend);
      +	}
      +
      +	function touchstart(e) {
      +		var touch, template;
      +
      +		// Don't get in the way of interaction with form elements.
      +		if (ignoreTags[ e.target.tagName.toLowerCase() ]) { return; }
      +
      +		touch = e.changedTouches[0];
      +		
      +		// iOS live updates the touch objects whereas Android gives us copies.
      +		// That means we can't trust the touchstart object to stay the same,
      +		// so we must copy the data. This object acts as a template for
      +		// movestart, move and moveend event objects.
      +		template = {
      +			target: touch.target,
      +			startX: touch.pageX,
      +			startY: touch.pageY,
      +			timeStamp: e.timeStamp,
      +			identifier: touch.identifier
      +		};
      +
      +		// Use the touch identifier as a namespace, so that we can later
      +		// remove handlers pertaining only to this touch.
      +		add(document, touchevents.move + '.' + touch.identifier, touchmove, template);
      +		add(document, touchevents.cancel + '.' + touch.identifier, touchend, template);
      +	}
      +
      +	function touchmove(e){
      +		var data = e.data,
      +		    touch = changedTouch(e, data);
      +
      +		if (!touch) { return; }
      +
      +		checkThreshold(e, data, touch, removeTouch);
      +	}
      +
      +	function touchend(e) {
      +		var template = e.data,
      +		    touch = identifiedTouch(e.changedTouches, template.identifier);
      +
      +		if (!touch) { return; }
      +
      +		removeTouch(template.identifier);
      +	}
      +
      +	function removeTouch(identifier) {
      +		remove(document, '.' + identifier, touchmove);
      +		remove(document, '.' + identifier, touchend);
      +	}
      +
      +
      +	// Logic for deciding when to trigger a movestart.
      +
      +	function checkThreshold(e, template, touch, fn) {
      +		var distX = touch.pageX - template.startX,
      +		    distY = touch.pageY - template.startY;
      +
      +		// Do nothing if the threshold has not been crossed.
      +		if ((distX * distX) + (distY * distY) < (threshold * threshold)) { return; }
      +
      +		triggerStart(e, template, touch, distX, distY, fn);
      +	}
      +
      +	function handled() {
      +		// this._handled should return false once, and after return true.
      +		this._handled = returnTrue;
      +		return false;
      +	}
      +
      +	function flagAsHandled(e) {
      +		e._handled();
      +	}
      +
      +	function triggerStart(e, template, touch, distX, distY, fn) {
      +		var node = template.target,
      +		    touches, time;
      +
      +		touches = e.targetTouches;
      +		time = e.timeStamp - template.timeStamp;
      +
      +		// Create a movestart object with some special properties that
      +		// are passed only to the movestart handlers.
      +		template.type = 'movestart';
      +		template.distX = distX;
      +		template.distY = distY;
      +		template.deltaX = distX;
      +		template.deltaY = distY;
      +		template.pageX = touch.pageX;
      +		template.pageY = touch.pageY;
      +		template.velocityX = distX / time;
      +		template.velocityY = distY / time;
      +		template.targetTouches = touches;
      +		template.finger = touches ?
      +			touches.length :
      +			1 ;
      +
      +		// The _handled method is fired to tell the default movestart
      +		// handler that one of the move events is bound.
      +		template._handled = handled;
      +			
      +		// Pass the touchmove event so it can be prevented if or when
      +		// movestart is handled.
      +		template._preventTouchmoveDefault = function() {
      +			e.preventDefault();
      +		};
      +
      +		// Trigger the movestart event.
      +		trigger(template.target, template);
      +
      +		// Unbind handlers that tracked the touch or mouse up till now.
      +		fn(template.identifier);
      +	}
      +
      +
      +	// Handlers that control what happens following a movestart
      +
      +	function activeMousemove(e) {
      +		var timer = e.data.timer;
      +
      +		e.data.touch = e;
      +		e.data.timeStamp = e.timeStamp;
      +		timer.kick();
      +	}
      +
      +	function activeMouseend(e) {
      +		var event = e.data.event,
      +		    timer = e.data.timer;
      +		
      +		removeActiveMouse();
      +
      +		endEvent(event, timer, function() {
      +			// Unbind the click suppressor, waiting until after mouseup
      +			// has been handled.
      +			setTimeout(function(){
      +				remove(event.target, 'click', returnFalse);
      +			}, 0);
      +		});
      +	}
      +
      +	function removeActiveMouse(event) {
      +		remove(document, mouseevents.move, activeMousemove);
      +		remove(document, mouseevents.end, activeMouseend);
      +	}
      +
      +	function activeTouchmove(e) {
      +		var event = e.data.event,
      +		    timer = e.data.timer,
      +		    touch = changedTouch(e, event);
      +
      +		if (!touch) { return; }
      +
      +		// Stop the interface from gesturing
      +		e.preventDefault();
      +
      +		event.targetTouches = e.targetTouches;
      +		e.data.touch = touch;
      +		e.data.timeStamp = e.timeStamp;
      +		timer.kick();
      +	}
      +
      +	function activeTouchend(e) {
      +		var event = e.data.event,
      +		    timer = e.data.timer,
      +		    touch = identifiedTouch(e.changedTouches, event.identifier);
      +
      +		// This isn't the touch you're looking for.
      +		if (!touch) { return; }
      +
      +		removeActiveTouch(event);
      +		endEvent(event, timer);
      +	}
      +
      +	function removeActiveTouch(event) {
      +		remove(document, '.' + event.identifier, activeTouchmove);
      +		remove(document, '.' + event.identifier, activeTouchend);
      +	}
      +
      +
      +	// Logic for triggering move and moveend events
      +
      +	function updateEvent(event, touch, timeStamp, timer) {
      +		var time = timeStamp - event.timeStamp;
      +
      +		event.type = 'move';
      +		event.distX =  touch.pageX - event.startX;
      +		event.distY =  touch.pageY - event.startY;
      +		event.deltaX = touch.pageX - event.pageX;
      +		event.deltaY = touch.pageY - event.pageY;
      +		
      +		// Average the velocity of the last few events using a decay
      +		// curve to even out spurious jumps in values.
      +		event.velocityX = 0.3 * event.velocityX + 0.7 * event.deltaX / time;
      +		event.velocityY = 0.3 * event.velocityY + 0.7 * event.deltaY / time;
      +		event.pageX =  touch.pageX;
      +		event.pageY =  touch.pageY;
      +	}
      +
      +	function endEvent(event, timer, fn) {
      +		timer.end(function(){
      +			event.type = 'moveend';
      +
      +			trigger(event.target, event);
      +			
      +			return fn && fn();
      +		});
      +	}
      +
      +
      +	// jQuery special event definition
      +
      +	function setup(data, namespaces, eventHandle) {
      +		// Stop the node from being dragged
      +		//add(this, 'dragstart.move drag.move', preventDefault);
      +		
      +		// Prevent text selection and touch interface scrolling
      +		//add(this, 'mousedown.move', preventIgnoreTags);
      +		
      +		// Tell movestart default handler that we've handled this
      +		add(this, 'movestart.move', flagAsHandled);
      +
      +		// Don't bind to the DOM. For speed.
      +		return true;
      +	}
      +	
      +	function teardown(namespaces) {
      +		remove(this, 'dragstart drag', preventDefault);
      +		remove(this, 'mousedown touchstart', preventIgnoreTags);
      +		remove(this, 'movestart', flagAsHandled);
      +		
      +		// Don't bind to the DOM. For speed.
      +		return true;
      +	}
      +	
      +	function addMethod(handleObj) {
      +		// We're not interested in preventing defaults for handlers that
      +		// come from internal move or moveend bindings
      +		if (handleObj.namespace === "move" || handleObj.namespace === "moveend") {
      +			return;
      +		}
      +		
      +		// Stop the node from being dragged
      +		add(this, 'dragstart.' + handleObj.guid + ' drag.' + handleObj.guid, preventDefault, undefined, handleObj.selector);
      +		
      +		// Prevent text selection and touch interface scrolling
      +		add(this, 'mousedown.' + handleObj.guid, preventIgnoreTags, undefined, handleObj.selector);
      +	}
      +	
      +	function removeMethod(handleObj) {
      +		if (handleObj.namespace === "move" || handleObj.namespace === "moveend") {
      +			return;
      +		}
      +		
      +		remove(this, 'dragstart.' + handleObj.guid + ' drag.' + handleObj.guid);
      +		remove(this, 'mousedown.' + handleObj.guid);
      +	}
      +	
      +	jQuery.event.special.movestart = {
      +		setup: setup,
      +		teardown: teardown,
      +		add: addMethod,
      +		remove: removeMethod,
      +
      +		_default: function(e) {
      +			var event, data;
      +			
      +			// If no move events were bound to any ancestors of this
      +			// target, high tail it out of here.
      +			if (!e._handled()) { return; }
      +
      +			function update(time) {
      +				updateEvent(event, data.touch, data.timeStamp);
      +				trigger(e.target, event);
      +			}
      +
      +			event = {
      +				target: e.target,
      +				startX: e.startX,
      +				startY: e.startY,
      +				pageX: e.pageX,
      +				pageY: e.pageY,
      +				distX: e.distX,
      +				distY: e.distY,
      +				deltaX: e.deltaX,
      +				deltaY: e.deltaY,
      +				velocityX: e.velocityX,
      +				velocityY: e.velocityY,
      +				timeStamp: e.timeStamp,
      +				identifier: e.identifier,
      +				targetTouches: e.targetTouches,
      +				finger: e.finger
      +			};
      +
      +			data = {
      +				event: event,
      +				timer: new Timer(update),
      +				touch: undefined,
      +				timeStamp: undefined
      +			};
      +			
      +			if (e.identifier === undefined) {
      +				// We're dealing with a mouse
      +				// Stop clicks from propagating during a move
      +				add(e.target, 'click', returnFalse);
      +				add(document, mouseevents.move, activeMousemove, data);
      +				add(document, mouseevents.end, activeMouseend, data);
      +			}
      +			else {
      +				// We're dealing with a touch. Stop touchmove doing
      +				// anything defaulty.
      +				e._preventTouchmoveDefault();
      +				add(document, touchevents.move + '.' + e.identifier, activeTouchmove, data);
      +				add(document, touchevents.end + '.' + e.identifier, activeTouchend, data);
      +			}
      +		}
      +	};
      +
      +	jQuery.event.special.move = {
      +		setup: function() {
      +			// Bind a noop to movestart. Why? It's the movestart
      +			// setup that decides whether other move events are fired.
      +			add(this, 'movestart.move', jQuery.noop);
      +		},
      +		
      +		teardown: function() {
      +			remove(this, 'movestart.move', jQuery.noop);
      +		}
      +	};
      +	
      +	jQuery.event.special.moveend = {
      +		setup: function() {
      +			// Bind a noop to movestart. Why? It's the movestart
      +			// setup that decides whether other move events are fired.
      +			add(this, 'movestart.moveend', jQuery.noop);
      +		},
      +		
      +		teardown: function() {
      +			remove(this, 'movestart.moveend', jQuery.noop);
      +		}
      +	};
      +
      +	add(document, 'mousedown.move', mousedown);
      +	add(document, 'touchstart.move', touchstart);
      +
      +	// Make jQuery copy touch event properties over to the jQuery event
      +	// object, if they are not already listed. But only do the ones we
      +	// really need. IE7/8 do not have Array#indexOf(), but nor do they
      +	// have touch events, so let's assume we can ignore them.
      +	if (typeof Array.prototype.indexOf === 'function') {
      +		(function(jQuery, undefined){
      +			var props = ["changedTouches", "targetTouches"],
      +			    l = props.length;
      +			
      +			while (l--) {
      +				if (jQuery.event.props.indexOf(props[l]) === -1) {
      +					jQuery.event.props.push(props[l]);
      +				}
      +			}
      +		})(jQuery);
      +	};
      +});
      +
      +
      +(function($) {
      +
      +    $.fn.twentytwenty = function(options) {
      +        var options = $.extend({
      +            default_offset_pct: 0.5,
      +            orientation: 'horizontal',
      +            overlay: true,
      +            transition_in: false
      +        }, options);
      +        return this.each(function() {
      +
      +            var container 			= $(this);
      +            var sliderPct 			= container.attr('data-percent') ? parseInt(container.attr('data-percent')) / 100 : options.default_offset_pct;
      +            var sliderOrientation 	= container.attr('data-orientation') ? container.attr('data-orientation') : options.orientation;
      +			var overlay 			= container.attr('data-overlay') ? Number(container.attr('data-overlay')) : options.overlay;
      +			var transition_in 		= container.attr('data-transition') ? Number(container.attr('data-transition')) : options.transition_in;
      +            var beforeDirection 	= (sliderOrientation === 'vertical') ? 'down' : 'left';
      +            var afterDirection 		= (sliderOrientation === 'vertical') ? 'up' : 'right';
      +
      +            container.wrap("<div class='twentytwenty-wrapper twentytwenty-" + sliderOrientation + "'></div>");
      +            if (overlay) {
      +                container.append("<div class='twentytwenty-overlay'></div>");
      +            }
      +            var beforeImg = container.find("img:first");
      +            var afterImg = container.find("img:last");
      +            container.append("<div class='twentytwenty-handle'></div>");
      +            var slider = container.find(".twentytwenty-handle");
      +            slider.append("<span class='twentytwenty-" + beforeDirection + "-arrow arrows'></span>");
      +            slider.append("<span class='twentytwenty-" + afterDirection + "-arrow arrows'></span>");
      +            container.addClass("twentytwenty-container");
      +            beforeImg.addClass("twentytwenty-before");
      +            afterImg.addClass("twentytwenty-after");
      +
      +            if (overlay) {
      +                var overlay = container.find(".twentytwenty-overlay");
      +                overlay.append("<div class='twentytwenty-before-label labels'></div>");
      +                overlay.append("<div class='twentytwenty-after-label labels'></div>");
      +            }
      +
      +            var calcOffset = function(dimensionPct) {
      +                var w = beforeImg.width();
      +                var h = beforeImg.height();
      +                return {
      +                    w: w + "px",
      +                    h: h + "px",
      +                    cw: (dimensionPct * w) + "px",
      +                    ch: (dimensionPct * h) + "px"
      +                };
      +            };
      +
      +            var adjustContainer = function(offset) {
      +                if (sliderOrientation === 'vertical') {
      +                    beforeImg.css("clip", "rect(0," + offset.w + "," + offset.ch + ",0)");
      +                } else {
      +                    beforeImg.css("clip", "rect(0," + offset.cw + "," + offset.h + ",0)");
      +                }
      +                container.css("height", offset.h);
      +            };
      +
      +            var adjustSlider = function(pct) {
      +                var offset = calcOffset(pct);
      +                slider.css((sliderOrientation === "vertical") ? "top" : "left", (sliderOrientation === "vertical") ? offset.ch : offset.cw);
      +                adjustContainer(offset);
      +            }
      +
      +            $(window).on("resize.twentytwenty", function(e) {
      +                adjustSlider(sliderPct);
      +            });
      +
      +            var offsetX = 0;
      +            var imgWidth = 0;
      +
      +            slider.on("movestart", function(e) {
      +                if (((e.distX > e.distY && e.distX < -e.distY) || (e.distX < e.distY && e.distX > -e.distY)) && sliderOrientation !== 'vertical') {
      +                    e.preventDefault();
      +                } else if (((e.distX < e.distY && e.distX < -e.distY) || (e.distX > e.distY && e.distX > -e.distY)) && sliderOrientation === 'vertical') {
      +                    e.preventDefault();
      +                }
      +                container.addClass("active");
      +                offsetX = container.offset().left;
      +                offsetY = container.offset().top;
      +                imgWidth = beforeImg.width();
      +                imgHeight = beforeImg.height();
      +            });
      +
      +            slider.on("moveend", function(e) {
      +                container.removeClass("active");
      +            });
      +
      +            slider.on("move", function(e) {
      +                if (container.hasClass("active")) {
      +                    sliderPct = (sliderOrientation === 'vertical') ? (e.pageY - offsetY) / imgHeight : (e.pageX - offsetX) / imgWidth;
      +                    if (sliderPct < 0) {
      +                        sliderPct = 0;
      +                    }
      +                    if (sliderPct > 1) {
      +                        sliderPct = 1;
      +                    }
      +                    adjustSlider(sliderPct);
      +                }
      +            });
      +
      +            container.find("img").on("mousedown", function(event) {
      +                event.preventDefault();
      +            });
      +
      +            container.on('goTo.twentytwenty', function(e, pos) {
      +                adjustSlider(pos);
      +            });
      +
      +            if (transition_in) {
      +				
      +				if(sliderOrientation == 'horizontal'){
      +					
      +                	var before = container.find('.twentytwenty-before').css('clip', 'rect(0px ' + beforeImg.width() + 'px ' + beforeImg.height() + 'px  0px)');
      +                	var handle = container.find('.twentytwenty-handle').css('left', beforeImg.width());
      +					
      +				}else{
      +					
      +                	var before = container.find('.twentytwenty-before').css('clip', 'rect(0px ' + beforeImg.width() + 'px ' + beforeImg.height() + 'px 0px )');
      +                	var handle = container.find('.twentytwenty-handle').css('top',beforeImg.height());					
      +					
      +				}
      +
      +                setTimeout(function() {
      +                    before.add(handle)
      +                        .on('transitionEnd oTransitionEnd msTransitionEnd transitionend webkitTransitionEnd', function() {
      +                            container.find('.twentytwenty-handle,.twentytwenty-before').css({
      +                                'transition': 'none'
      +                            });
      +                        })
      +                        .css({
      +                            '-webkit-transition': 'all 1.5s ease',
      +                            '-moz-transition': 'all 1.5s ease',
      +                            'transition': 'all 1.5s ease'
      +                        });
      +
      +                    $(window).trigger("resize.twentytwenty");
      +                });
      +            } else {
      +                $(window).trigger("resize.twentytwenty");
      +            }
      +
      +            container.trigger('init.twentytwenty', [container]);
      +
      +        });
      +    };
      +
      +})(jQuery);
      +
      +/*(function($){
      +
      +  $.fn.twentytwenty = function(options) {
      +    var options = $.extend({default_offset_pct: 0.5, orientation: 'horizontal'}, options);
      +    return this.each(function() {
      +
      +      var container = $(this);
      +	  var sliderPct = container.attr('data-percent') ? parseInt(container.attr('data-percent')) : options.default_offset_pct;
      +      var sliderOrientation = container.attr('data-orientation') ? container.attr('data-orientation') : options.orientation;
      +      var beforeDirection = (sliderOrientation === 'vertical') ? 'down' : 'left';
      +      var afterDirection = (sliderOrientation === 'vertical') ? 'up' : 'right';
      +      
      +      
      +      container.wrap("<div class='twentytwenty-wrapper twentytwenty-" + sliderOrientation + "'></div>");
      +      container.append("<div class='twentytwenty-overlay'></div>");
      +      var beforeImg = container.find("img:first");
      +      var afterImg = container.find("img:last");
      +      container.append("<div class='twentytwenty-handle'></div>");
      +      var slider = container.find(".twentytwenty-handle");
      +      slider.append("<span class='twentytwenty-" + beforeDirection + "-arrow'></span>");
      +      slider.append("<span class='twentytwenty-" + afterDirection + "-arrow'></span>");
      +      container.addClass("twentytwenty-container");
      +      beforeImg.addClass("twentytwenty-before");
      +      afterImg.addClass("twentytwenty-after");
      +      
      +      var overlay = container.find(".twentytwenty-overlay");
      +      overlay.append("<div class='twentytwenty-before-label'></div>");
      +      overlay.append("<div class='twentytwenty-after-label'></div>");
      +
      +      var calcOffset = function(dimensionPct) {
      +        var w = beforeImg.width();
      +        var h = beforeImg.height();
      +        return {
      +          w: w+"px",
      +          h: h+"px",
      +          cw: (dimensionPct*w)+"px",
      +          ch: (dimensionPct*h)+"px"
      +        };
      +      };
      +
      +      var adjustContainer = function(offset) {
      +      	if (sliderOrientation === 'vertical') {
      +      	  beforeImg.css("clip", "rect(0,"+offset.w+","+offset.ch+",0)");
      +      	}
      +      	else {
      +          beforeImg.css("clip", "rect(0,"+offset.cw+","+offset.h+",0)");
      +    	}
      +        container.css("height", offset.h);
      +      };
      +
      +      var adjustSlider = function(pct) {
      +        var offset = calcOffset(pct);
      +        slider.css((sliderOrientation==="vertical") ? "top" : "left", (sliderOrientation==="vertical") ? offset.ch : offset.cw);
      +        adjustContainer(offset);
      +      }
      +
      +      $(window).on("resize.twentytwenty", function(e) {
      +        adjustSlider(sliderPct);
      +      });
      +
      +      var offsetX = 0;
      +      var offsetY = 0;
      +      var imgWidth = 0;
      +      var imgHeight = 0;
      +      
      +      slider.on("movestart", function(e) {
      +        if (((e.distX > e.distY && e.distX < -e.distY) || (e.distX < e.distY && e.distX > -e.distY)) && sliderOrientation !== 'vertical') {
      +          e.preventDefault();
      +        }
      +        else if (((e.distX < e.distY && e.distX < -e.distY) || (e.distX > e.distY && e.distX > -e.distY)) && sliderOrientation === 'vertical') {
      +          e.preventDefault();
      +        }
      +        container.addClass("active");
      +        offsetX = container.offset().left;
      +        offsetY = container.offset().top;
      +        imgWidth = beforeImg.width(); 
      +        imgHeight = beforeImg.height();          
      +      });
      +
      +      slider.on("moveend", function(e) {
      +        container.removeClass("active");
      +      });
      +
      +      slider.on("move", function(e) {
      +        if (container.hasClass("active")) {
      +          sliderPct = (sliderOrientation === 'vertical') ? (e.pageY-offsetY)/imgHeight : (e.pageX-offsetX)/imgWidth;
      +          if (sliderPct < 0) {
      +            sliderPct = 0;
      +          }
      +          if (sliderPct > 1) {
      +            sliderPct = 1;
      +          }
      +          adjustSlider(sliderPct);
      +        }
      +      });
      +
      +      container.find("img").on("mousedown", function(event) {
      +        event.preventDefault();
      +      });
      +
      +      $(window).trigger("resize.twentytwenty");
      +    });
      +  };
      +
      +})(jQuery);*/
      \ No newline at end of file
      diff --git a/assets/js/dev/vendors/typed.js b/assets/js/dev/vendors/typed.js
      new file mode 100644
      index 0000000..6f15ee7
      --- /dev/null
      +++ b/assets/js/dev/vendors/typed.js
      @@ -0,0 +1,1036 @@
      +/*!
      + * 
      + *   typed.js - A JavaScript Typing Animation Library
      + *   Author: Matt Boldt <me@mattboldt.com>
      + *   Version: v2.0.6
      + *   Url: https://github.com/mattboldt/typed.js
      + *   License(s): MIT
      + * 
      + */
      +(function webpackUniversalModuleDefinition(root, factory) {
      +	if(typeof exports === 'object' && typeof module === 'object')
      +		module.exports = factory();
      +	else if(typeof define === 'function' && define.amd)
      +		define([], factory);
      +	else if(typeof exports === 'object')
      +		exports["Typed"] = factory();
      +	else
      +		root["Typed"] = factory();
      +})(this, function() {
      +return /******/ (function(modules) { // webpackBootstrap
      +/******/ 	// The module cache
      +/******/ 	var installedModules = {};
      +/******/
      +/******/ 	// The require function
      +/******/ 	function __webpack_require__(moduleId) {
      +/******/
      +/******/ 		// Check if module is in cache
      +/******/ 		if(installedModules[moduleId])
      +/******/ 			return installedModules[moduleId].exports;
      +/******/
      +/******/ 		// Create a new module (and put it into the cache)
      +/******/ 		var module = installedModules[moduleId] = {
      +/******/ 			exports: {},
      +/******/ 			id: moduleId,
      +/******/ 			loaded: false
      +/******/ 		};
      +/******/
      +/******/ 		// Execute the module function
      +/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
      +/******/
      +/******/ 		// Flag the module as loaded
      +/******/ 		module.loaded = true;
      +/******/
      +/******/ 		// Return the exports of the module
      +/******/ 		return module.exports;
      +/******/ 	}
      +/******/
      +/******/
      +/******/ 	// expose the modules object (__webpack_modules__)
      +/******/ 	__webpack_require__.m = modules;
      +/******/
      +/******/ 	// expose the module cache
      +/******/ 	__webpack_require__.c = installedModules;
      +/******/
      +/******/ 	// __webpack_public_path__
      +/******/ 	__webpack_require__.p = "";
      +/******/
      +/******/ 	// Load entry module and return exports
      +/******/ 	return __webpack_require__(0);
      +/******/ })
      +/************************************************************************/
      +/******/ ([
      +/* 0 */
      +/***/ (function(module, exports, __webpack_require__) {
      +
      +	'use strict';
      +	
      +	Object.defineProperty(exports, '__esModule', {
      +	  value: true
      +	});
      +	
      +	var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
      +	
      +	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
      +	
      +	var _initializerJs = __webpack_require__(1);
      +	
      +	var _htmlParserJs = __webpack_require__(3);
      +	
      +	/**
      +	 * Welcome to Typed.js!
      +	 * @param {string} elementId HTML element ID _OR_ HTML element
      +	 * @param {object} options options object
      +	 * @returns {object} a new Typed object
      +	 */
      +	
      +	var Typed = (function () {
      +	  function Typed(elementId, options) {
      +	    _classCallCheck(this, Typed);
      +	
      +	    // Initialize it up
      +	    _initializerJs.initializer.load(this, options, elementId);
      +	    // All systems go!
      +	    this.begin();
      +	  }
      +	
      +	  /**
      +	   * Toggle start() and stop() of the Typed instance
      +	   * @public
      +	   */
      +	
      +	  _createClass(Typed, [{
      +	    key: 'toggle',
      +	    value: function toggle() {
      +	      this.pause.status ? this.start() : this.stop();
      +	    }
      +	
      +	    /**
      +	     * Stop typing / backspacing and enable cursor blinking
      +	     * @public
      +	     */
      +	  }, {
      +	    key: 'stop',
      +	    value: function stop() {
      +	      if (this.typingComplete) return;
      +	      if (this.pause.status) return;
      +	      this.toggleBlinking(true);
      +	      this.pause.status = true;
      +	      this.options.onStop(this.arrayPos, this);
      +	    }
      +	
      +	    /**
      +	     * Start typing / backspacing after being stopped
      +	     * @public
      +	     */
      +	  }, {
      +	    key: 'start',
      +	    value: function start() {
      +	      if (this.typingComplete) return;
      +	      if (!this.pause.status) return;
      +	      this.pause.status = false;
      +	      if (this.pause.typewrite) {
      +	        this.typewrite(this.pause.curString, this.pause.curStrPos);
      +	      } else {
      +	        this.backspace(this.pause.curString, this.pause.curStrPos);
      +	      }
      +	      this.options.onStart(this.arrayPos, this);
      +	    }
      +	
      +	    /**
      +	     * Destroy this instance of Typed
      +	     * @public
      +	     */
      +	  }, {
      +	    key: 'destroy',
      +	    value: function destroy() {
      +	      this.reset(false);
      +	      this.options.onDestroy(this);
      +	    }
      +	
      +	    /**
      +	     * Reset Typed and optionally restarts
      +	     * @param {boolean} restart
      +	     * @public
      +	     */
      +	  }, {
      +	    key: 'reset',
      +	    value: function reset() {
      +	      var restart = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0];
      +	
      +	      clearInterval(this.timeout);
      +	      this.replaceText('');
      +	      if (this.cursor && this.cursor.parentNode) {
      +	        this.cursor.parentNode.removeChild(this.cursor);
      +	        this.cursor = null;
      +	      }
      +	      this.strPos = 0;
      +	      this.arrayPos = 0;
      +	      this.curLoop = 0;
      +	      if (restart) {
      +	        this.insertCursor();
      +	        this.options.onReset(this);
      +	        this.begin();
      +	      }
      +	    }
      +	
      +	    /**
      +	     * Begins the typing animation
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'begin',
      +	    value: function begin() {
      +	      var _this = this;
      +	
      +	      this.typingComplete = false;
      +	      this.shuffleStringsIfNeeded(this);
      +	      this.insertCursor();
      +	      if (this.bindInputFocusEvents) this.bindFocusEvents();
      +	      this.timeout = setTimeout(function () {
      +	        // Check if there is some text in the element, if yes start by backspacing the default message
      +	        if (!_this.currentElContent || _this.currentElContent.length === 0) {
      +	          _this.typewrite(_this.strings[_this.sequence[_this.arrayPos]], _this.strPos);
      +	        } else {
      +	          // Start typing
      +	          _this.backspace(_this.currentElContent, _this.currentElContent.length);
      +	        }
      +	      }, this.startDelay);
      +	    }
      +	
      +	    /**
      +	     * Called for each character typed
      +	     * @param {string} curString the current string in the strings array
      +	     * @param {number} curStrPos the current position in the curString
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'typewrite',
      +	    value: function typewrite(curString, curStrPos) {
      +	      var _this2 = this;
      +	
      +	      if (this.fadeOut && this.el.classList.contains(this.fadeOutClass)) {
      +	        this.el.classList.remove(this.fadeOutClass);
      +	        if (this.cursor) this.cursor.classList.remove(this.fadeOutClass);
      +	      }
      +	
      +	      var humanize = this.humanizer(this.typeSpeed);
      +	      var numChars = 1;
      +	
      +	      if (this.pause.status === true) {
      +	        this.setPauseStatus(curString, curStrPos, true);
      +	        return;
      +	      }
      +	
      +	      // contain typing function in a timeout humanize'd delay
      +	      this.timeout = setTimeout(function () {
      +	        // skip over any HTML chars
      +	        curStrPos = _htmlParserJs.htmlParser.typeHtmlChars(curString, curStrPos, _this2);
      +	
      +	        var pauseTime = 0;
      +	        var substr = curString.substr(curStrPos);
      +	        // check for an escape character before a pause value
      +	        // format: \^\d+ .. eg: ^1000 .. should be able to print the ^ too using ^^
      +	        // single ^ are removed from string
      +	        if (substr.charAt(0) === '^') {
      +	          if (/^\^\d+/.test(substr)) {
      +	            var skip = 1; // skip at least 1
      +	            substr = /\d+/.exec(substr)[0];
      +	            skip += substr.length;
      +	            pauseTime = parseInt(substr);
      +	            _this2.temporaryPause = true;
      +	            _this2.options.onTypingPaused(_this2.arrayPos, _this2);
      +	            // strip out the escape character and pause value so they're not printed
      +	            curString = curString.substring(0, curStrPos) + curString.substring(curStrPos + skip);
      +	            _this2.toggleBlinking(true);
      +	          }
      +	        }
      +	
      +	        // check for skip characters formatted as
      +	        // "this is a `string to print NOW` ..."
      +	        if (substr.charAt(0) === '`') {
      +	          while (curString.substr(curStrPos + numChars).charAt(0) !== '`') {
      +	            numChars++;
      +	            if (curStrPos + numChars > curString.length) break;
      +	          }
      +	          // strip out the escape characters and append all the string in between
      +	          var stringBeforeSkip = curString.substring(0, curStrPos);
      +	          var stringSkipped = curString.substring(stringBeforeSkip.length + 1, curStrPos + numChars);
      +	          var stringAfterSkip = curString.substring(curStrPos + numChars + 1);
      +	          curString = stringBeforeSkip + stringSkipped + stringAfterSkip;
      +	          numChars--;
      +	        }
      +	
      +	        // timeout for any pause after a character
      +	        _this2.timeout = setTimeout(function () {
      +	          // Accounts for blinking while paused
      +	          _this2.toggleBlinking(false);
      +	
      +	          // We're done with this sentence!
      +	          if (curStrPos === curString.length) {
      +	            _this2.doneTyping(curString, curStrPos);
      +	          } else {
      +	            _this2.keepTyping(curString, curStrPos, numChars);
      +	          }
      +	          // end of character pause
      +	          if (_this2.temporaryPause) {
      +	            _this2.temporaryPause = false;
      +	            _this2.options.onTypingResumed(_this2.arrayPos, _this2);
      +	          }
      +	        }, pauseTime);
      +	
      +	        // humanized value for typing
      +	      }, humanize);
      +	    }
      +	
      +	    /**
      +	     * Continue to the next string & begin typing
      +	     * @param {string} curString the current string in the strings array
      +	     * @param {number} curStrPos the current position in the curString
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'keepTyping',
      +	    value: function keepTyping(curString, curStrPos, numChars) {
      +	      // call before functions if applicable
      +	      if (curStrPos === 0) {
      +	        this.toggleBlinking(false);
      +	        this.options.preStringTyped(this.arrayPos, this);
      +	      }
      +	      // start typing each new char into existing string
      +	      // curString: arg, this.el.html: original text inside element
      +	      curStrPos += numChars;
      +	      var nextString = curString.substr(0, curStrPos);
      +	      this.replaceText(nextString);
      +	      // loop the function
      +	      this.typewrite(curString, curStrPos);
      +	    }
      +	
      +	    /**
      +	     * We're done typing all strings
      +	     * @param {string} curString the current string in the strings array
      +	     * @param {number} curStrPos the current position in the curString
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'doneTyping',
      +	    value: function doneTyping(curString, curStrPos) {
      +	      var _this3 = this;
      +	
      +	      // fires callback function
      +	      this.options.onStringTyped(this.arrayPos, this);
      +	      this.toggleBlinking(true);
      +	      // is this the final string
      +	      if (this.arrayPos === this.strings.length - 1) {
      +	        // callback that occurs on the last typed string
      +	        this.complete();
      +	        // quit if we wont loop back
      +	        if (this.loop === false || this.curLoop === this.loopCount) {
      +	          return;
      +	        }
      +	      }
      +	      this.timeout = setTimeout(function () {
      +	        _this3.backspace(curString, curStrPos);
      +	      }, this.backDelay);
      +	    }
      +	
      +	    /**
      +	     * Backspaces 1 character at a time
      +	     * @param {string} curString the current string in the strings array
      +	     * @param {number} curStrPos the current position in the curString
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'backspace',
      +	    value: function backspace(curString, curStrPos) {
      +	      var _this4 = this;
      +	
      +	      if (this.pause.status === true) {
      +	        this.setPauseStatus(curString, curStrPos, true);
      +	        return;
      +	      }
      +	      if (this.fadeOut) return this.initFadeOut();
      +	
      +	      this.toggleBlinking(false);
      +	      var humanize = this.humanizer(this.backSpeed);
      +	
      +	      this.timeout = setTimeout(function () {
      +	        curStrPos = _htmlParserJs.htmlParser.backSpaceHtmlChars(curString, curStrPos, _this4);
      +	        // replace text with base text + typed characters
      +	        var curStringAtPosition = curString.substr(0, curStrPos);
      +	        _this4.replaceText(curStringAtPosition);
      +	
      +	        // if smartBack is enabled
      +	        if (_this4.smartBackspace) {
      +	          // the remaining part of the current string is equal of the same part of the new string
      +	          var nextString = _this4.strings[_this4.arrayPos + 1];
      +	          if (nextString && curStringAtPosition === nextString.substr(0, curStrPos)) {
      +	            _this4.stopNum = curStrPos;
      +	          } else {
      +	            _this4.stopNum = 0;
      +	          }
      +	        }
      +	
      +	        // if the number (id of character in current string) is
      +	        // less than the stop number, keep going
      +	        if (curStrPos > _this4.stopNum) {
      +	          // subtract characters one by one
      +	          curStrPos--;
      +	          // loop the function
      +	          _this4.backspace(curString, curStrPos);
      +	        } else if (curStrPos <= _this4.stopNum) {
      +	          // if the stop number has been reached, increase
      +	          // array position to next string
      +	          _this4.arrayPos++;
      +	          // When looping, begin at the beginning after backspace complete
      +	          if (_this4.arrayPos === _this4.strings.length) {
      +	            _this4.arrayPos = 0;
      +	            _this4.options.onLastStringBackspaced();
      +	            _this4.shuffleStringsIfNeeded();
      +	            _this4.begin();
      +	          } else {
      +	            _this4.typewrite(_this4.strings[_this4.sequence[_this4.arrayPos]], curStrPos);
      +	          }
      +	        }
      +	        // humanized value for typing
      +	      }, humanize);
      +	    }
      +	
      +	    /**
      +	     * Full animation is complete
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'complete',
      +	    value: function complete() {
      +	      this.options.onComplete(this);
      +	      if (this.loop) {
      +	        this.curLoop++;
      +	      } else {
      +	        this.typingComplete = true;
      +	      }
      +	    }
      +	
      +	    /**
      +	     * Has the typing been stopped
      +	     * @param {string} curString the current string in the strings array
      +	     * @param {number} curStrPos the current position in the curString
      +	     * @param {boolean} isTyping
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'setPauseStatus',
      +	    value: function setPauseStatus(curString, curStrPos, isTyping) {
      +	      this.pause.typewrite = isTyping;
      +	      this.pause.curString = curString;
      +	      this.pause.curStrPos = curStrPos;
      +	    }
      +	
      +	    /**
      +	     * Toggle the blinking cursor
      +	     * @param {boolean} isBlinking
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'toggleBlinking',
      +	    value: function toggleBlinking(isBlinking) {
      +	      if (!this.cursor) return;
      +	      // if in paused state, don't toggle blinking a 2nd time
      +	      if (this.pause.status) return;
      +	      if (this.cursorBlinking === isBlinking) return;
      +	      this.cursorBlinking = isBlinking;
      +	      var status = isBlinking ? 'infinite' : 0;
      +	      this.cursor.style.animationIterationCount = status;
      +	    }
      +	
      +	    /**
      +	     * Speed in MS to type
      +	     * @param {number} speed
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'humanizer',
      +	    value: function humanizer(speed) {
      +	      return Math.round(Math.random() * speed / 2) + speed;
      +	    }
      +	
      +	    /**
      +	     * Shuffle the sequence of the strings array
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'shuffleStringsIfNeeded',
      +	    value: function shuffleStringsIfNeeded() {
      +	      if (!this.shuffle) return;
      +	      this.sequence = this.sequence.sort(function () {
      +	        return Math.random() - 0.5;
      +	      });
      +	    }
      +	
      +	    /**
      +	     * Adds a CSS class to fade out current string
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'initFadeOut',
      +	    value: function initFadeOut() {
      +	      var _this5 = this;
      +	
      +	      this.el.className += ' ' + this.fadeOutClass;
      +	      if (this.cursor) this.cursor.className += ' ' + this.fadeOutClass;
      +	      return setTimeout(function () {
      +	        _this5.arrayPos++;
      +	        _this5.replaceText('');
      +	
      +	        // Resets current string if end of loop reached
      +	        if (_this5.strings.length > _this5.arrayPos) {
      +	          _this5.typewrite(_this5.strings[_this5.sequence[_this5.arrayPos]], 0);
      +	        } else {
      +	          _this5.typewrite(_this5.strings[0], 0);
      +	          _this5.arrayPos = 0;
      +	        }
      +	      }, this.fadeOutDelay);
      +	    }
      +	
      +	    /**
      +	     * Replaces current text in the HTML element
      +	     * depending on element type
      +	     * @param {string} str
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'replaceText',
      +	    value: function replaceText(str) {
      +	      if (this.attr) {
      +	        this.el.setAttribute(this.attr, str);
      +	      } else {
      +	        if (this.isInput) {
      +	          this.el.value = str;
      +	        } else if (this.contentType === 'html') {
      +	          this.el.innerHTML = str;
      +	        } else {
      +	          this.el.textContent = str;
      +	        }
      +	      }
      +	    }
      +	
      +	    /**
      +	     * If using input elements, bind focus in order to
      +	     * start and stop the animation
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'bindFocusEvents',
      +	    value: function bindFocusEvents() {
      +	      var _this6 = this;
      +	
      +	      if (!this.isInput) return;
      +	      this.el.addEventListener('focus', function (e) {
      +	        _this6.stop();
      +	      });
      +	      this.el.addEventListener('blur', function (e) {
      +	        if (_this6.el.value && _this6.el.value.length !== 0) {
      +	          return;
      +	        }
      +	        _this6.start();
      +	      });
      +	    }
      +	
      +	    /**
      +	     * On init, insert the cursor element
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'insertCursor',
      +	    value: function insertCursor() {
      +	      if (!this.showCursor) return;
      +	      if (this.cursor) return;
      +	      this.cursor = document.createElement('span');
      +	      this.cursor.className = 'typed-cursor';
      +	      this.cursor.innerHTML = this.cursorChar;
      +	      this.el.parentNode && this.el.parentNode.insertBefore(this.cursor, this.el.nextSibling);
      +	    }
      +	  }]);
      +	
      +	  return Typed;
      +	})();
      +	
      +	exports['default'] = Typed;
      +	module.exports = exports['default'];
      +
      +/***/ }),
      +/* 1 */
      +/***/ (function(module, exports, __webpack_require__) {
      +
      +	'use strict';
      +	
      +	Object.defineProperty(exports, '__esModule', {
      +	  value: true
      +	});
      +	
      +	var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
      +	
      +	var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
      +	
      +	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
      +	
      +	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
      +	
      +	var _defaultsJs = __webpack_require__(2);
      +	
      +	var _defaultsJs2 = _interopRequireDefault(_defaultsJs);
      +	
      +	/**
      +	 * Initialize the Typed object
      +	 */
      +	
      +	var Initializer = (function () {
      +	  function Initializer() {
      +	    _classCallCheck(this, Initializer);
      +	  }
      +	
      +	  _createClass(Initializer, [{
      +	    key: 'load',
      +	
      +	    /**
      +	     * Load up defaults & options on the Typed instance
      +	     * @param {Typed} self instance of Typed
      +	     * @param {object} options options object
      +	     * @param {string} elementId HTML element ID _OR_ instance of HTML element
      +	     * @private
      +	     */
      +	
      +	    value: function load(self, options, elementId) {
      +	      // chosen element to manipulate text
      +	      if (typeof elementId === 'string') {
      +	        self.el = document.querySelector(elementId);
      +	      } else {
      +	        self.el = elementId;
      +	      }
      +	
      +	      self.options = _extends({}, _defaultsJs2['default'], options);
      +	
      +	      // attribute to type into
      +	      self.isInput = self.el.tagName.toLowerCase() === 'input';
      +	      self.attr = self.options.attr;
      +	      self.bindInputFocusEvents = self.options.bindInputFocusEvents;
      +	
      +	      // show cursor
      +	      self.showCursor = self.isInput ? false : self.options.showCursor;
      +	
      +	      // custom cursor
      +	      self.cursorChar = self.options.cursorChar;
      +	
      +	      // Is the cursor blinking
      +	      self.cursorBlinking = true;
      +	
      +	      // text content of element
      +	      self.elContent = self.attr ? self.el.getAttribute(self.attr) : self.el.textContent;
      +	
      +	      // html or plain text
      +	      self.contentType = self.options.contentType;
      +	
      +	      // typing speed
      +	      self.typeSpeed = self.options.typeSpeed;
      +	
      +	      // add a delay before typing starts
      +	      self.startDelay = self.options.startDelay;
      +	
      +	      // backspacing speed
      +	      self.backSpeed = self.options.backSpeed;
      +	
      +	      // only backspace what doesn't match the previous string
      +	      self.smartBackspace = self.options.smartBackspace;
      +	
      +	      // amount of time to wait before backspacing
      +	      self.backDelay = self.options.backDelay;
      +	
      +	      // Fade out instead of backspace
      +	      self.fadeOut = self.options.fadeOut;
      +	      self.fadeOutClass = self.options.fadeOutClass;
      +	      self.fadeOutDelay = self.options.fadeOutDelay;
      +	
      +	      // variable to check whether typing is currently paused
      +	      self.isPaused = false;
      +	
      +	      // input strings of text
      +	      self.strings = self.options.strings.map(function (s) {
      +	        return s.trim();
      +	      });
      +	
      +	      // div containing strings
      +	      if (typeof self.options.stringsElement === 'string') {
      +	        self.stringsElement = document.querySelector(self.options.stringsElement);
      +	      } else {
      +	        self.stringsElement = self.options.stringsElement;
      +	      }
      +	
      +	      if (self.stringsElement) {
      +	        self.strings = [];
      +	        self.stringsElement.style.display = 'none';
      +	        var strings = Array.prototype.slice.apply(self.stringsElement.children);
      +	        var stringsLength = strings.length;
      +	
      +	        if (stringsLength) {
      +	          for (var i = 0; i < stringsLength; i += 1) {
      +	            var stringEl = strings[i];
      +	            self.strings.push(stringEl.innerHTML.trim());
      +	          }
      +	        }
      +	      }
      +	
      +	      // character number position of current string
      +	      self.strPos = 0;
      +	
      +	      // current array position
      +	      self.arrayPos = 0;
      +	
      +	      // index of string to stop backspacing on
      +	      self.stopNum = 0;
      +	
      +	      // Looping logic
      +	      self.loop = self.options.loop;
      +	      self.loopCount = self.options.loopCount;
      +	      self.curLoop = 0;
      +	
      +	      // shuffle the strings
      +	      self.shuffle = self.options.shuffle;
      +	      // the order of strings
      +	      self.sequence = [];
      +	
      +	      self.pause = {
      +	        status: false,
      +	        typewrite: true,
      +	        curString: '',
      +	        curStrPos: 0
      +	      };
      +	
      +	      // When the typing is complete (when not looped)
      +	      self.typingComplete = false;
      +	
      +	      // Set the order in which the strings are typed
      +	      for (var i in self.strings) {
      +	        self.sequence[i] = i;
      +	      }
      +	
      +	      // If there is some text in the element
      +	      self.currentElContent = this.getCurrentElContent(self);
      +	
      +	      self.autoInsertCss = self.options.autoInsertCss;
      +	
      +	      this.appendAnimationCss(self);
      +	    }
      +	  }, {
      +	    key: 'getCurrentElContent',
      +	    value: function getCurrentElContent(self) {
      +	      var elContent = '';
      +	      if (self.attr) {
      +	        elContent = self.el.getAttribute(self.attr);
      +	      } else if (self.isInput) {
      +	        elContent = self.el.value;
      +	      } else if (self.contentType === 'html') {
      +	        elContent = self.el.innerHTML;
      +	      } else {
      +	        elContent = self.el.textContent;
      +	      }
      +	      return elContent;
      +	    }
      +	  }, {
      +	    key: 'appendAnimationCss',
      +	    value: function appendAnimationCss(self) {
      +	      if (!self.autoInsertCss) {
      +	        return;
      +	      }
      +	      if (!self.showCursor || !self.fadeOut) {
      +	        return;
      +	      }
      +	
      +	      var css = document.createElement('style');
      +	      css.type = 'text/css';
      +	      var innerCss = '';
      +	      if (self.showCursor) {
      +	        innerCss += '\n        .typed-cursor{\n          opacity: 1;\n          animation: typedjsBlink 0.7s infinite;\n          -webkit-animation: typedjsBlink 0.7s infinite;\n                  animation: typedjsBlink 0.7s infinite;\n        }\n        @keyframes typedjsBlink{\n          50% { opacity: 0.0; }\n        }\n        @-webkit-keyframes typedjsBlink{\n          0% { opacity: 1; }\n          50% { opacity: 0.0; }\n          100% { opacity: 1; }\n        }\n      ';
      +	      }
      +	      if (self.fadeOut) {
      +	        innerCss += '\n        .typed-fade-out{\n          opacity: 0;\n          transition: opacity .25s;\n          -webkit-animation: 0;\n                  animation: 0;\n        }\n      ';
      +	      }
      +	      if (css.length === 0) {
      +	        return;
      +	      }
      +	      css.innerHTML = innerCss;
      +	      document.head.appendChild(css);
      +	    }
      +	  }]);
      +	
      +	  return Initializer;
      +	})();
      +	
      +	exports['default'] = Initializer;
      +	var initializer = new Initializer();
      +	exports.initializer = initializer;
      +
      +/***/ }),
      +/* 2 */
      +/***/ (function(module, exports) {
      +
      +	/**
      +	 * Defaults & options
      +	 * @returns {object} Typed defaults & options
      +	 * @public
      +	 */
      +	
      +	'use strict';
      +	
      +	Object.defineProperty(exports, '__esModule', {
      +	  value: true
      +	});
      +	var defaults = {
      +	  /**
      +	   * @property {array} strings strings to be typed
      +	   * @property {string} stringsElement ID of element containing string children
      +	   */
      +	  strings: ['These are the default values...', 'You know what you should do?', 'Use your own!', 'Have a great day!'],
      +	  stringsElement: null,
      +	
      +	  /**
      +	   * @property {number} typeSpeed type speed in milliseconds
      +	   */
      +	  typeSpeed: 0,
      +	
      +	  /**
      +	   * @property {number} startDelay time before typing starts in milliseconds
      +	   */
      +	  startDelay: 0,
      +	
      +	  /**
      +	   * @property {number} backSpeed backspacing speed in milliseconds
      +	   */
      +	  backSpeed: 0,
      +	
      +	  /**
      +	   * @property {boolean} smartBackspace only backspace what doesn't match the previous string
      +	   */
      +	  smartBackspace: true,
      +	
      +	  /**
      +	   * @property {boolean} shuffle shuffle the strings
      +	   */
      +	  shuffle: false,
      +	
      +	  /**
      +	   * @property {number} backDelay time before backspacing in milliseconds
      +	   */
      +	  backDelay: 700,
      +	
      +	  /**
      +	   * @property {boolean} fadeOut Fade out instead of backspace
      +	   * @property {string} fadeOutClass css class for fade animation
      +	   * @property {boolean} fadeOutDelay Fade out delay in milliseconds
      +	   */
      +	  fadeOut: false,
      +	  fadeOutClass: 'typed-fade-out',
      +	  fadeOutDelay: 500,
      +	
      +	  /**
      +	   * @property {boolean} loop loop strings
      +	   * @property {number} loopCount amount of loops
      +	   */
      +	  loop: false,
      +	  loopCount: Infinity,
      +	
      +	  /**
      +	   * @property {boolean} showCursor show cursor
      +	   * @property {string} cursorChar character for cursor
      +	   * @property {boolean} autoInsertCss insert CSS for cursor and fadeOut into HTML <head>
      +	   */
      +	  showCursor: true,
      +	  cursorChar: '|',
      +	  autoInsertCss: true,
      +	
      +	  /**
      +	   * @property {string} attr attribute for typing
      +	   * Ex: input placeholder, value, or just HTML text
      +	   */
      +	  attr: null,
      +	
      +	  /**
      +	   * @property {boolean} bindInputFocusEvents bind to focus and blur if el is text input
      +	   */
      +	  bindInputFocusEvents: false,
      +	
      +	  /**
      +	   * @property {string} contentType 'html' or 'null' for plaintext
      +	   */
      +	  contentType: 'html',
      +	
      +	  /**
      +	   * All typing is complete
      +	   * @param {Typed} self
      +	   */
      +	  onComplete: function onComplete(self) {},
      +	
      +	  /**
      +	   * Before each string is typed
      +	   * @param {number} arrayPos
      +	   * @param {Typed} self
      +	   */
      +	  preStringTyped: function preStringTyped(arrayPos, self) {},
      +	
      +	  /**
      +	   * After each string is typed
      +	   * @param {number} arrayPos
      +	   * @param {Typed} self
      +	   */
      +	  onStringTyped: function onStringTyped(arrayPos, self) {},
      +	
      +	  /**
      +	   * During looping, after last string is typed
      +	   * @param {Typed} self
      +	   */
      +	  onLastStringBackspaced: function onLastStringBackspaced(self) {},
      +	
      +	  /**
      +	   * Typing has been stopped
      +	   * @param {number} arrayPos
      +	   * @param {Typed} self
      +	   */
      +	  onTypingPaused: function onTypingPaused(arrayPos, self) {},
      +	
      +	  /**
      +	   * Typing has been started after being stopped
      +	   * @param {number} arrayPos
      +	   * @param {Typed} self
      +	   */
      +	  onTypingResumed: function onTypingResumed(arrayPos, self) {},
      +	
      +	  /**
      +	   * After reset
      +	   * @param {Typed} self
      +	   */
      +	  onReset: function onReset(self) {},
      +	
      +	  /**
      +	   * After stop
      +	   * @param {number} arrayPos
      +	   * @param {Typed} self
      +	   */
      +	  onStop: function onStop(arrayPos, self) {},
      +	
      +	  /**
      +	   * After start
      +	   * @param {number} arrayPos
      +	   * @param {Typed} self
      +	   */
      +	  onStart: function onStart(arrayPos, self) {},
      +	
      +	  /**
      +	   * After destroy
      +	   * @param {Typed} self
      +	   */
      +	  onDestroy: function onDestroy(self) {}
      +	};
      +	
      +	exports['default'] = defaults;
      +	module.exports = exports['default'];
      +
      +/***/ }),
      +/* 3 */
      +/***/ (function(module, exports) {
      +
      +	
      +	/**
      +	 * TODO: These methods can probably be combined somehow
      +	 * Parse HTML tags & HTML Characters
      +	 */
      +	
      +	'use strict';
      +	
      +	Object.defineProperty(exports, '__esModule', {
      +	  value: true
      +	});
      +	
      +	var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
      +	
      +	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
      +	
      +	var HTMLParser = (function () {
      +	  function HTMLParser() {
      +	    _classCallCheck(this, HTMLParser);
      +	  }
      +	
      +	  _createClass(HTMLParser, [{
      +	    key: 'typeHtmlChars',
      +	
      +	    /**
      +	     * Type HTML tags & HTML Characters
      +	     * @param {string} curString Current string
      +	     * @param {number} curStrPos Position in current string
      +	     * @param {Typed} self instance of Typed
      +	     * @returns {number} a new string position
      +	     * @private
      +	     */
      +	
      +	    value: function typeHtmlChars(curString, curStrPos, self) {
      +	      if (self.contentType !== 'html') return curStrPos;
      +	      var curChar = curString.substr(curStrPos).charAt(0);
      +	      if (curChar === '<' || curChar === '&') {
      +	        var endTag = '';
      +	        if (curChar === '<') {
      +	          endTag = '>';
      +	        } else {
      +	          endTag = ';';
      +	        }
      +	        while (curString.substr(curStrPos + 1).charAt(0) !== endTag) {
      +	          curStrPos++;
      +	          if (curStrPos + 1 > curString.length) {
      +	            break;
      +	          }
      +	        }
      +	        curStrPos++;
      +	      }
      +	      return curStrPos;
      +	    }
      +	
      +	    /**
      +	     * Backspace HTML tags and HTML Characters
      +	     * @param {string} curString Current string
      +	     * @param {number} curStrPos Position in current string
      +	     * @param {Typed} self instance of Typed
      +	     * @returns {number} a new string position
      +	     * @private
      +	     */
      +	  }, {
      +	    key: 'backSpaceHtmlChars',
      +	    value: function backSpaceHtmlChars(curString, curStrPos, self) {
      +	      if (self.contentType !== 'html') return curStrPos;
      +	      var curChar = curString.substr(curStrPos).charAt(0);
      +	      if (curChar === '>' || curChar === ';') {
      +	        var endTag = '';
      +	        if (curChar === '>') {
      +	          endTag = '<';
      +	        } else {
      +	          endTag = '&';
      +	        }
      +	        while (curString.substr(curStrPos - 1).charAt(0) !== endTag) {
      +	          curStrPos--;
      +	          if (curStrPos < 0) {
      +	            break;
      +	          }
      +	        }
      +	        curStrPos--;
      +	      }
      +	      return curStrPos;
      +	    }
      +	  }]);
      +	
      +	  return HTMLParser;
      +	})();
      +	
      +	exports['default'] = HTMLParser;
      +	var htmlParser = new HTMLParser();
      +	exports.htmlParser = htmlParser;
      +
      +/***/ })
      +/******/ ])
      +});
      +;
      \ No newline at end of file
      diff --git a/assets/js/dev/vendors/vivus.js b/assets/js/dev/vendors/vivus.js
      new file mode 100644
      index 0000000..ad3ddba
      --- /dev/null
      +++ b/assets/js/dev/vendors/vivus.js
      @@ -0,0 +1,1105 @@
      +/**
      + * vivus - JavaScript library to make drawing animation on SVG
      + * @version v0.4.4
      + * @link https://github.com/maxwellito/vivus
      + * @license MIT
      + */
      +
      +'use strict';
      +
      +(function () {
      +
      +  'use strict';
      +
      +/**
      + * Pathformer
      + * Beta version
      + *
      + * Take any SVG version 1.1 and transform
      + * child elements to 'path' elements
      + *
      + * This code is purely forked from
      + * https://github.com/Waest/SVGPathConverter
      + */
      +
      +/**
      + * Class constructor
      + *
      + * @param {DOM|String} element Dom element of the SVG or id of it
      + */
      +function Pathformer(element) {
      +  // Test params
      +  if (typeof element === 'undefined') {
      +    throw new Error('Pathformer [constructor]: "element" parameter is required');
      +  }
      +
      +  // Set the element
      +  if (element.constructor === String) {
      +    element = document.getElementById(element);
      +    if (!element) {
      +      throw new Error('Pathformer [constructor]: "element" parameter is not related to an existing ID');
      +    }
      +  }
      +  if (element instanceof window.SVGElement || 
      +      element instanceof window.SVGGElement ||
      +      /^svg$/i.test(element.nodeName)) {
      +    this.el = element;
      +  } else {
      +    throw new Error('Pathformer [constructor]: "element" parameter must be a string or a SVGelement');
      +  }
      +
      +  // Start
      +  this.scan(element);
      +}
      +
      +/**
      + * List of tags which can be transformed
      + * to path elements
      + *
      + * @type {Array}
      + */
      +Pathformer.prototype.TYPES = ['line', 'ellipse', 'circle', 'polygon', 'polyline', 'rect'];
      +
      +/**
      + * List of attribute names which contain
      + * data. This array list them to check if
      + * they contain bad values, like percentage.
      + *
      + * @type {Array}
      + */
      +Pathformer.prototype.ATTR_WATCH = ['cx', 'cy', 'points', 'r', 'rx', 'ry', 'x', 'x1', 'x2', 'y', 'y1', 'y2'];
      +
      +/**
      + * Finds the elements compatible for transform
      + * and apply the liked method
      + *
      + * @param  {object} options Object from the constructor
      + */
      +Pathformer.prototype.scan = function (svg) {
      +  var fn, element, pathData, pathDom,
      +      elements = svg.querySelectorAll(this.TYPES.join(','));
      +
      +  for (var i = 0; i < elements.length; i++) {
      +    element = elements[i];
      +    fn = this[element.tagName.toLowerCase() + 'ToPath'];
      +    pathData = fn(this.parseAttr(element.attributes));
      +    pathDom = this.pathMaker(element, pathData);
      +    element.parentNode.replaceChild(pathDom, element);
      +  }
      +};
      +
      +
      +/**
      + * Read `line` element to extract and transform
      + * data, to make it ready for a `path` object.
      + *
      + * @param  {DOMelement} element Line element to transform
      + * @return {object}             Data for a `path` element
      + */
      +Pathformer.prototype.lineToPath = function (element) {
      +  var newElement = {},
      +      x1 = element.x1 || 0,
      +      y1 = element.y1 || 0,
      +      x2 = element.x2 || 0,
      +      y2 = element.y2 || 0;
      +
      +  newElement.d = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
      +  return newElement;
      +};
      +
      +/**
      + * Read `rect` element to extract and transform
      + * data, to make it ready for a `path` object.
      + * The radius-border is not taken in charge yet.
      + * (your help is more than welcomed)
      + *
      + * @param  {DOMelement} element Rect element to transform
      + * @return {object}             Data for a `path` element
      + */
      +Pathformer.prototype.rectToPath = function (element) {
      +  var newElement = {},
      +      x      = parseFloat(element.x)      || 0,
      +      y      = parseFloat(element.y)      || 0,
      +      width  = parseFloat(element.width)  || 0,
      +      height = parseFloat(element.height) || 0;
      +
      +  if (element.rx || element.ry) {
      +    var rx = parseInt(element.rx, 10) || -1,
      +        ry = parseInt(element.ry, 10) || -1;
      +    rx = Math.min(Math.max(rx < 0 ? ry : rx, 0), width/2);
      +    ry = Math.min(Math.max(ry < 0 ? rx : ry, 0), height/2);
      +
      +    newElement.d = 'M ' + (x + rx) + ',' + y + ' ' +
      +                   'L ' + (x + width - rx) + ',' + y + ' ' +
      +                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width) + ',' + (y + ry) + ' ' +
      +                   'L ' + (x + width) + ',' + (y + height - ry) + ' ' +
      +                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + width - rx) + ',' + (y + height) + ' ' +
      +                   'L ' + (x + rx) + ',' + (y + height) + ' ' +
      +                   'A ' + rx + ',' + ry + ',0,0,1,' + x + ',' + (y + height - ry) + ' ' +
      +                   'L ' + x + ',' + (y + ry) + ' ' +
      +                   'A ' + rx + ',' + ry + ',0,0,1,' + (x + rx) + ',' + y;
      +  }
      +  else {
      +    newElement.d = 'M' + x + ' ' + y + ' ' +
      +                   'L' + (x + width) + ' ' + y + ' ' +
      +                   'L' + (x + width) + ' ' + (y + height) + ' ' +
      +                   'L' + x + ' ' + (y + height) + ' Z';
      +  }
      +  return newElement;
      +};
      +
      +/**
      + * Read `polyline` element to extract and transform
      + * data, to make it ready for a `path` object.
      + *
      + * @param  {DOMelement} element Polyline element to transform
      + * @return {object}             Data for a `path` element
      + */
      +Pathformer.prototype.polylineToPath = function (element) {
      +  var newElement = {},
      +      points = element.points.trim().split(' '),
      +      i, path;
      +
      +  // Reformatting if points are defined without commas
      +  if (element.points.indexOf(',') === -1) {
      +    var formattedPoints = [];
      +    for (i = 0; i < points.length; i+=2) {
      +      formattedPoints.push(points[i] + ',' + points[i+1]);
      +    }
      +    points = formattedPoints;
      +  }
      +
      +  // Generate the path.d value
      +  path = 'M' + points[0];
      +  for(i = 1; i < points.length; i++) {
      +    if (points[i].indexOf(',') !== -1) {
      +      path += 'L' + points[i];
      +    }
      +  }
      +  newElement.d = path;
      +  return newElement;
      +};
      +
      +/**
      + * Read `polygon` element to extract and transform
      + * data, to make it ready for a `path` object.
      + * This method rely on polylineToPath, because the
      + * logic is similar. The path created is just closed,
      + * so it needs an 'Z' at the end.
      + *
      + * @param  {DOMelement} element Polygon element to transform
      + * @return {object}             Data for a `path` element
      + */
      +Pathformer.prototype.polygonToPath = function (element) {
      +  var newElement = Pathformer.prototype.polylineToPath(element);
      +
      +  newElement.d += 'Z';
      +  return newElement;
      +};
      +
      +/**
      + * Read `ellipse` element to extract and transform
      + * data, to make it ready for a `path` object.
      + *
      + * @param  {DOMelement} element ellipse element to transform
      + * @return {object}             Data for a `path` element
      + */
      +Pathformer.prototype.ellipseToPath = function (element) {
      +  var newElement = {},
      +      rx = parseFloat(element.rx) || 0,
      +      ry = parseFloat(element.ry) || 0,
      +      cx = parseFloat(element.cx) || 0,
      +      cy = parseFloat(element.cy) || 0,
      +      startX = cx - rx,
      +      startY = cy,
      +      endX = parseFloat(cx) + parseFloat(rx),
      +      endY = cy;
      +
      +  newElement.d = 'M' + startX + ',' + startY +
      +                 'A' + rx + ',' + ry + ' 0,1,1 ' + endX + ',' + endY +
      +                 'A' + rx + ',' + ry + ' 0,1,1 ' + startX + ',' + endY;
      +  return newElement;
      +};
      +
      +/**
      + * Read `circle` element to extract and transform
      + * data, to make it ready for a `path` object.
      + *
      + * @param  {DOMelement} element Circle element to transform
      + * @return {object}             Data for a `path` element
      + */
      +Pathformer.prototype.circleToPath = function (element) {
      +  var newElement = {},
      +      r  = parseFloat(element.r)  || 0,
      +      cx = parseFloat(element.cx) || 0,
      +      cy = parseFloat(element.cy) || 0,
      +      startX = cx - r,
      +      startY = cy,
      +      endX = parseFloat(cx) + parseFloat(r),
      +      endY = cy;
      +      
      +  newElement.d =  'M' + startX + ',' + startY +
      +                  'A' + r + ',' + r + ' 0,1,1 ' + endX + ',' + endY +
      +                  'A' + r + ',' + r + ' 0,1,1 ' + startX + ',' + endY;
      +  return newElement;
      +};
      +
      +/**
      + * Create `path` elements form original element
      + * and prepared objects
      + *
      + * @param  {DOMelement} element  Original element to transform
      + * @param  {object} pathData     Path data (from `toPath` methods)
      + * @return {DOMelement}          Path element
      + */
      +Pathformer.prototype.pathMaker = function (element, pathData) {
      +  var i, attr, pathTag = document.createElementNS('http://www.w3.org/2000/svg','path');
      +  for(i = 0; i < element.attributes.length; i++) {
      +    attr = element.attributes[i];
      +    if (this.ATTR_WATCH.indexOf(attr.name) === -1) {
      +      pathTag.setAttribute(attr.name, attr.value);
      +    }
      +  }
      +  for(i in pathData) {
      +    pathTag.setAttribute(i, pathData[i]);
      +  }
      +  return pathTag;
      +};
      +
      +/**
      + * Parse attributes of a DOM element to
      + * get an object of attribute => value
      + *
      + * @param  {NamedNodeMap} attributes Attributes object from DOM element to parse
      + * @return {object}                  Object of attributes
      + */
      +Pathformer.prototype.parseAttr = function (element) {
      +  var attr, output = {};
      +  for (var i = 0; i < element.length; i++) {
      +    attr = element[i];
      +    // Check if no data attribute contains '%', or the transformation is impossible
      +    if (this.ATTR_WATCH.indexOf(attr.name) !== -1 && attr.value.indexOf('%') !== -1) {
      +      throw new Error('Pathformer [parseAttr]: a SVG shape got values in percentage. This cannot be transformed into \'path\' tags. Please use \'viewBox\'.');
      +    }
      +    output[attr.name] = attr.value;
      +  }
      +  return output;
      +};
      +
      +  'use strict';
      +
      +var setupEnv, requestAnimFrame, cancelAnimFrame, parsePositiveInt;
      +
      +/**
      + * Vivus
      + * Beta version
      + *
      + * Take any SVG and make the animation
      + * to give give the impression of live drawing
      + *
      + * This in more than just inspired from codrops
      + * At that point, it's a pure fork.
      + */
      +
      +/**
      + * Class constructor
      + * option structure
      + *   type: 'delayed'|'sync'|'oneByOne'|'script' (to know if the items must be drawn synchronously or not, default: delayed)
      + *   duration: <int> (in frames)
      + *   start: 'inViewport'|'manual'|'autostart' (start automatically the animation, default: inViewport)
      + *   delay: <int> (delay between the drawing of first and last path)
      + *   dashGap <integer> whitespace extra margin between dashes
      + *   pathTimingFunction <function> timing animation function for each path element of the SVG
      + *   animTimingFunction <function> timing animation function for the complete SVG
      + *   forceRender <boolean> force the browser to re-render all updated path items
      + *   selfDestroy <boolean> removes all extra styling on the SVG, and leaves it as original
      + *
      + * The attribute 'type' is by default on 'delayed'.
      + *  - 'delayed'
      + *    all paths are draw at the same time but with a
      + *    little delay between them before start
      + *  - 'sync'
      + *    all path are start and finish at the same time
      + *  - 'oneByOne'
      + *    only one path is draw at the time
      + *    the end of the first one will trigger the draw
      + *    of the next one
      + *
      + * All these values can be overwritten individually
      + * for each path item in the SVG
      + * The value of frames will always take the advantage of
      + * the duration value.
      + * If you fail somewhere, an error will be thrown.
      + * Good luck.
      + *
      + * @constructor
      + * @this {Vivus}
      + * @param {DOM|String}   element  Dom element of the SVG or id of it
      + * @param {Object}       options  Options about the animation
      + * @param {Function}     callback Callback for the end of the animation
      + */
      +function Vivus (element, options, callback) {
      +
      +  setupEnv();
      +
      +  // Setup
      +  this.isReady = false;
      +  this.setElement(element, options);
      +  this.setOptions(options);
      +  this.setCallback(callback);
      +
      +  if (this.isReady) {
      +    this.init();
      +  }
      +}
      +
      +/**
      + * Timing functions
      + **************************************
      + *
      + * Default functions to help developers.
      + * It always take a number as parameter (between 0 to 1) then
      + * return a number (between 0 and 1)
      + */
      +Vivus.LINEAR          = function (x) {return x;};
      +Vivus.EASE            = function (x) {return -Math.cos(x * Math.PI) / 2 + 0.5;};
      +Vivus.EASE_OUT        = function (x) {return 1 - Math.pow(1-x, 3);};
      +Vivus.EASE_IN         = function (x) {return Math.pow(x, 3);};
      +Vivus.EASE_OUT_BOUNCE = function (x) {
      +  var base = -Math.cos(x * (0.5 * Math.PI)) + 1,
      +    rate = Math.pow(base,1.5),
      +    rateR = Math.pow(1 - x, 2),
      +    progress = -Math.abs(Math.cos(rate * (2.5 * Math.PI) )) + 1;
      +  return (1- rateR) + (progress * rateR);
      +};
      +
      +
      +/**
      + * Setters
      + **************************************
      + */
      +
      +/**
      + * Check and set the element in the instance
      + * The method will not return anything, but will throw an
      + * error if the parameter is invalid
      + *
      + * @param {DOM|String}   element  SVG Dom element or id of it
      + */
      +Vivus.prototype.setElement = function (element, options) {
      +  var onLoad, self;
      +
      +  // Basic check
      +  if (typeof element === 'undefined') {
      +    throw new Error('Vivus [constructor]: "element" parameter is required');
      +  }
      +
      +  // Set the element
      +  if (element.constructor === String) {
      +    element = document.getElementById(element);
      +    if (!element) {
      +      throw new Error('Vivus [constructor]: "element" parameter is not related to an existing ID');
      +    }
      +  }
      +  this.parentEl = element;
      +
      +  // Load the SVG with XMLHttpRequest and extract the SVG
      +  if (options && options.file) {
      +    var self = this;
      +    onLoad = function (e) {
      +      var domSandbox = document.createElement('div');
      +      domSandbox.innerHTML = this.responseText;
      +
      +      var svgTag = domSandbox.querySelector('svg');
      +      if (!svgTag) {
      +        throw new Error('Vivus [load]: Cannot find the SVG in the loaded file : ' + options.file);
      +      }
      +
      +      self.el = svgTag
      +      self.el.setAttribute('width', '100%');
      +      self.el.setAttribute('height', '100%');
      +      self.parentEl.appendChild(self.el)
      +      self.isReady = true;
      +      self.init();
      +      self = null;
      +    }
      +    
      +    var oReq = new window.XMLHttpRequest();
      +    oReq.addEventListener('load', onLoad);
      +    oReq.open('GET', options.file);
      +    oReq.send();
      +    return;
      +  }
      +
      +  switch (element.constructor) {
      +  case window.SVGSVGElement:
      +  case window.SVGElement:
      +  case window.SVGGElement:
      +    this.el = element;
      +    this.isReady = true;
      +    break;
      +
      +  case window.HTMLObjectElement:
      +    self = this;
      +    onLoad = function (e) {
      +      if (self.isReady) {
      +        return;
      +      }
      +      self.el = element.contentDocument && element.contentDocument.querySelector('svg');
      +      if (!self.el && e) {
      +        throw new Error('Vivus [constructor]: object loaded does not contain any SVG');
      +      }
      +      else if (self.el) {
      +        if (element.getAttribute('built-by-vivus')) {
      +          self.parentEl.insertBefore(self.el, element);
      +          self.parentEl.removeChild(element);
      +          self.el.setAttribute('width', '100%');
      +          self.el.setAttribute('height', '100%');
      +        }
      +        self.isReady = true;
      +        self.init();
      +        self = null;
      +      }
      +    };
      +
      +    if (!onLoad()) {
      +      element.addEventListener('load', onLoad);
      +    }
      +    break;
      +
      +  default:
      +    throw new Error('Vivus [constructor]: "element" parameter is not valid (or miss the "file" attribute)');
      +  }
      +};
      +
      +/**
      + * Set up user option to the instance
      + * The method will not return anything, but will throw an
      + * error if the parameter is invalid
      + *
      + * @param  {object} options Object from the constructor
      + */
      +Vivus.prototype.setOptions = function (options) {
      +  var allowedTypes = ['delayed', 'sync', 'async', 'nsync', 'oneByOne', 'scenario', 'scenario-sync'];
      +  var allowedStarts =  ['inViewport', 'manual', 'autostart'];
      +
      +  // Basic check
      +  if (options !== undefined && options.constructor !== Object) {
      +    throw new Error('Vivus [constructor]: "options" parameter must be an object');
      +  }
      +  else {
      +    options = options || {};
      +  }
      +
      +  // Set the animation type
      +  if (options.type && allowedTypes.indexOf(options.type) === -1) {
      +    throw new Error('Vivus [constructor]: ' + options.type + ' is not an existing animation `type`');
      +  }
      +  else {
      +    this.type = options.type || allowedTypes[0];
      +  }
      +
      +  // Set the start type
      +  if (options.start && allowedStarts.indexOf(options.start) === -1) {
      +    throw new Error('Vivus [constructor]: ' + options.start + ' is not an existing `start` option');
      +  }
      +  else {
      +    this.start = options.start || allowedStarts[0];
      +  }
      +
      +  this.isIE         = (window.navigator.userAgent.indexOf('MSIE') !== -1 || window.navigator.userAgent.indexOf('Trident/') !== -1 || window.navigator.userAgent.indexOf('Edge/') !== -1 );
      +  this.duration     = parsePositiveInt(options.duration, 120);
      +  this.delay        = parsePositiveInt(options.delay, null);
      +  this.dashGap      = parsePositiveInt(options.dashGap, 1);
      +  this.forceRender  = options.hasOwnProperty('forceRender') ? !!options.forceRender : this.isIE;
      +  this.reverseStack = !!options.reverseStack;
      +  this.selfDestroy  = !!options.selfDestroy;
      +  this.onReady      = options.onReady;
      +  this.map          = [];
      +  this.frameLength  = this.currentFrame = this.delayUnit = this.speed = this.handle = null;
      +
      +  this.ignoreInvisible = options.hasOwnProperty('ignoreInvisible') ? !!options.ignoreInvisible : false;
      +
      +  this.animTimingFunction = options.animTimingFunction || Vivus.LINEAR;
      +  this.pathTimingFunction = options.pathTimingFunction || Vivus.LINEAR;
      +
      +  if (this.delay >= this.duration) {
      +    throw new Error('Vivus [constructor]: delay must be shorter than duration');
      +  }
      +};
      +
      +/**
      + * Set up callback to the instance
      + * The method will not return enything, but will throw an
      + * error if the parameter is invalid
      + *
      + * @param  {Function} callback Callback for the animation end
      + */
      +Vivus.prototype.setCallback = function (callback) {
      +  // Basic check
      +  if (!!callback && callback.constructor !== Function) {
      +    throw new Error('Vivus [constructor]: "callback" parameter must be a function');
      +  }
      +  this.callback = callback || function () {};
      +};
      +
      +
      +/**
      + * Core
      + **************************************
      + */
      +
      +/**
      + * Map the svg, path by path.
      + * The method return nothing, it just fill the
      + * `map` array. Each item in this array represent
      + * a path element from the SVG, with informations for
      + * the animation.
      + *
      + * ```
      + * [
      + *   {
      + *     el: <DOMobj> the path element
      + *     length: <number> length of the path line
      + *     startAt: <number> time start of the path animation (in frames)
      + *     duration: <number> path animation duration (in frames)
      + *   },
      + *   ...
      + * ]
      + * ```
      + *
      + */
      +Vivus.prototype.mapping = function () {
      +  var i, paths, path, pAttrs, pathObj, totalLength, lengthMeter, timePoint;
      +  timePoint = totalLength = lengthMeter = 0;
      +  paths = this.el.querySelectorAll('path');
      +
      +  for (i = 0; i < paths.length; i++) {
      +    path = paths[i];
      +    if (this.isInvisible(path)) {
      +      continue;
      +    }
      +    pathObj = {
      +      el: path,
      +      length: Math.ceil(path.getTotalLength())
      +    };
      +    // Test if the path length is correct
      +    if (isNaN(pathObj.length)) {
      +      if (window.console && console.warn) {
      +        console.warn('Vivus [mapping]: cannot retrieve a path element length', path);
      +      }
      +      continue;
      +    }
      +    this.map.push(pathObj);
      +    path.style.strokeDasharray  = pathObj.length + ' ' + (pathObj.length + this.dashGap * 2);
      +    path.style.strokeDashoffset = pathObj.length + this.dashGap;
      +    pathObj.length += this.dashGap;
      +    totalLength += pathObj.length;
      +
      +    this.renderPath(i);
      +  }
      +
      +  totalLength = totalLength === 0 ? 1 : totalLength;
      +  this.delay = this.delay === null ? this.duration / 3 : this.delay;
      +  this.delayUnit = this.delay / (paths.length > 1 ? paths.length - 1 : 1);
      +
      +  // Reverse stack if asked
      +  if (this.reverseStack) {
      +    this.map.reverse();
      +  }
      +
      +  for (i = 0; i < this.map.length; i++) {
      +    pathObj = this.map[i];
      +
      +    switch (this.type) {
      +    case 'delayed':
      +      pathObj.startAt = this.delayUnit * i;
      +      pathObj.duration = this.duration - this.delay;
      +      break;
      +
      +    case 'oneByOne':
      +      pathObj.startAt = lengthMeter / totalLength * this.duration;
      +      pathObj.duration = pathObj.length / totalLength * this.duration;
      +      break;
      +
      +    case 'sync':
      +    case 'async':
      +    case 'nsync':
      +      pathObj.startAt = 0;
      +      pathObj.duration = this.duration;
      +      break;
      +
      +    case 'scenario-sync':
      +      path = pathObj.el;
      +      pAttrs = this.parseAttr(path);
      +      pathObj.startAt = timePoint + (parsePositiveInt(pAttrs['data-delay'], this.delayUnit) || 0);
      +      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
      +      timePoint = pAttrs['data-async'] !== undefined ? pathObj.startAt : pathObj.startAt + pathObj.duration;
      +      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
      +      break;
      +
      +    case 'scenario':
      +      path = pathObj.el;
      +      pAttrs = this.parseAttr(path);
      +      pathObj.startAt = parsePositiveInt(pAttrs['data-start'], this.delayUnit) || 0;
      +      pathObj.duration = parsePositiveInt(pAttrs['data-duration'], this.duration);
      +      this.frameLength = Math.max(this.frameLength, (pathObj.startAt + pathObj.duration));
      +      break;
      +    }
      +    lengthMeter += pathObj.length;
      +    this.frameLength = this.frameLength || this.duration;
      +  }
      +};
      +
      +/**
      + * Interval method to draw the SVG from current
      + * position of the animation. It update the value of
      + * `currentFrame` and re-trace the SVG.
      + *
      + * It use this.handle to store the requestAnimationFrame
      + * and clear it one the animation is stopped. So this
      + * attribute can be used to know if the animation is
      + * playing.
      + *
      + * Once the animation at the end, this method will
      + * trigger the Vivus callback.
      + *
      + */
      +Vivus.prototype.drawer = function () {
      +  var self = this;
      +  this.currentFrame += this.speed;
      +
      +  if (this.currentFrame <= 0) {
      +    this.stop();
      +    this.reset();
      +  } else if (this.currentFrame >= this.frameLength) {
      +    this.stop();
      +    this.currentFrame = this.frameLength;
      +    this.trace();
      +    if (this.selfDestroy) {
      +      this.destroy();
      +    }
      +  } else {
      +    this.trace();
      +    this.handle = requestAnimFrame(function () {
      +      self.drawer();
      +    });
      +    return;
      +  }
      +
      +  this.callback(this);
      +  if (this.instanceCallback) {
      +    this.instanceCallback(this);
      +    this.instanceCallback = null;
      +  }
      +};
      +
      +/**
      + * Draw the SVG at the current instant from the
      + * `currentFrame` value. Here is where most of the magic is.
      + * The trick is to use the `strokeDashoffset` style property.
      + *
      + * For optimisation reasons, a new property called `progress`
      + * is added in each item of `map`. This one contain the current
      + * progress of the path element. Only if the new value is different
      + * the new value will be applied to the DOM element. This
      + * method save a lot of resources to re-render the SVG. And could
      + * be improved if the animation couldn't be played forward.
      + *
      + */
      +Vivus.prototype.trace = function () {
      +  var i, progress, path, currentFrame;
      +  currentFrame = this.animTimingFunction(this.currentFrame / this.frameLength) * this.frameLength;
      +  for (i = 0; i < this.map.length; i++) {
      +    path = this.map[i];
      +    progress = (currentFrame - path.startAt) / path.duration;
      +    progress = this.pathTimingFunction(Math.max(0, Math.min(1, progress)));
      +    if (path.progress !== progress) {
      +      path.progress = progress;
      +      path.el.style.strokeDashoffset = Math.floor(path.length * (1 - progress));
      +      this.renderPath(i);
      +    }
      +  }
      +};
      +
      +/**
      + * Method forcing the browser to re-render a path element
      + * from it's index in the map. Depending on the `forceRender`
      + * value.
      + * The trick is to replace the path element by it's clone.
      + * This practice is not recommended because it's asking more
      + * ressources, too much DOM manupulation..
      + * but it's the only way to let the magic happen on IE.
      + * By default, this fallback is only applied on IE.
      + *
      + * @param  {Number} index Path index
      + */
      +Vivus.prototype.renderPath = function (index) {
      +  if (this.forceRender && this.map && this.map[index]) {
      +    var pathObj = this.map[index],
      +        newPath = pathObj.el.cloneNode(true);
      +    pathObj.el.parentNode.replaceChild(newPath, pathObj.el);
      +    pathObj.el = newPath;
      +  }
      +};
      +
      +/**
      + * When the SVG object is loaded and ready,
      + * this method will continue the initialisation.
      + *
      + * This this mainly due to the case of passing an
      + * object tag in the constructor. It will wait
      + * the end of the loading to initialise.
      + *
      + */
      +Vivus.prototype.init = function () {
      +  // Set object variables
      +  this.frameLength = 0;
      +  this.currentFrame = 0;
      +  this.map = [];
      +
      +  // Start
      +  new Pathformer(this.el);
      +  this.mapping();
      +  this.starter();
      +
      +  if (this.onReady) {
      +    this.onReady(this);
      +  }
      +};
      +
      +/**
      + * Trigger to start of the animation.
      + * Depending on the `start` value, a different script
      + * will be applied.
      + *
      + * If the `start` value is not valid, an error will be thrown.
      + * Even if technically, this is impossible.
      + *
      + */
      +Vivus.prototype.starter = function () {
      +  switch (this.start) {
      +  case 'manual':
      +    return;
      +
      +  case 'autostart':
      +    this.play();
      +    break;
      +
      +  case 'inViewport':
      +    var self = this,
      +    listener = function () {
      +      if (self.isInViewport(self.parentEl, 1)) {
      +        self.play();
      +        window.removeEventListener('scroll', listener);
      +      }
      +    };
      +    window.addEventListener('scroll', listener);
      +    listener();
      +    break;
      +  }
      +};
      +
      +
      +/**
      + * Controls
      + **************************************
      + */
      +
      +/**
      + * Get the current status of the animation between
      + * three different states: 'start', 'progress', 'end'.
      + * @return {string} Instance status
      + */
      +Vivus.prototype.getStatus = function () {
      +  return this.currentFrame === 0 ? 'start' : this.currentFrame === this.frameLength ? 'end' : 'progress';
      +};
      +
      +/**
      + * Reset the instance to the initial state : undraw
      + * Be careful, it just reset the animation, if you're
      + * playing the animation, this won't stop it. But just
      + * make it start from start.
      + *
      + */
      +Vivus.prototype.reset = function () {
      +  return this.setFrameProgress(0);
      +};
      +
      +/**
      + * Set the instance to the final state : drawn
      + * Be careful, it just set the animation, if you're
      + * playing the animation on rewind, this won't stop it.
      + * But just make it start from the end.
      + *
      + */
      +Vivus.prototype.finish = function () {
      +  return this.setFrameProgress(1);
      +};
      +
      +/**
      + * Set the level of progress of the drawing.
      + *
      + * @param {number} progress Level of progress to set
      + */
      +Vivus.prototype.setFrameProgress = function (progress) {
      +  progress = Math.min(1, Math.max(0, progress));
      +  this.currentFrame = Math.round(this.frameLength * progress);
      +  this.trace();
      +  return this;
      +};
      +
      +/**
      + * Play the animation at the desired speed.
      + * Speed must be a valid number (no zero).
      + * By default, the speed value is 1.
      + * But a negative value is accepted to go forward.
      + *
      + * And works with float too.
      + * But don't forget we are in JavaScript, se be nice
      + * with him and give him a 1/2^x value.
      + *
      + * @param  {number} speed Animation speed [optional]
      + */
      +Vivus.prototype.play = function (speed, callback) {
      +  this.instanceCallback = null;
      +
      +  if (speed && typeof speed === 'function') {
      +    this.instanceCallback = speed; // first parameter is actually the callback function
      +    speed = null;
      +  }
      +  else if (speed && typeof speed !== 'number') {
      +    throw new Error('Vivus [play]: invalid speed');
      +  }
      +  // if the first parameter wasn't the callback, check if the seconds was
      +  if (callback && typeof(callback) === 'function' && !this.instanceCallback) {
      +    this.instanceCallback = callback;
      +  }
      +
      +
      +  this.speed = speed || 1;
      +  if (!this.handle) {
      +    this.drawer();
      +  }
      +  return this;
      +};
      +
      +/**
      + * Stop the current animation, if on progress.
      + * Should not trigger any error.
      + *
      + */
      +Vivus.prototype.stop = function () {
      +  if (this.handle) {
      +    cancelAnimFrame(this.handle);
      +    this.handle = null;
      +  }
      +  return this;
      +};
      +
      +/**
      + * Destroy the instance.
      + * Remove all bad styling attributes on all
      + * path tags
      + *
      + */
      +Vivus.prototype.destroy = function () {
      +  this.stop();
      +  var i, path;
      +  for (i = 0; i < this.map.length; i++) {
      +    path = this.map[i];
      +    path.el.style.strokeDashoffset = null;
      +    path.el.style.strokeDasharray = null;
      +    this.renderPath(i);
      +  }
      +};
      +
      +
      +/**
      + * Utils methods
      + * include methods from Codrops
      + **************************************
      + */
      +
      +/**
      + * Method to best guess if a path should added into
      + * the animation or not.
      + *
      + * 1. Use the `data-vivus-ignore` attribute if set
      + * 2. Check if the instance must ignore invisible paths
      + * 3. Check if the path is visible
      + *
      + * For now the visibility checking is unstable.
      + * It will be used for a beta phase.
      + *
      + * Other improvments are planned. Like detecting
      + * is the path got a stroke or a valid opacity.
      + */
      +Vivus.prototype.isInvisible = function (el) {
      +  var rect,
      +    ignoreAttr = el.getAttribute('data-ignore');
      +
      +  if (ignoreAttr !== null) {
      +    return ignoreAttr !== 'false';
      +  }
      +
      +  if (this.ignoreInvisible) {
      +    rect = el.getBoundingClientRect();
      +    return !rect.width && !rect.height;
      +  }
      +  else {
      +    return false;
      +  }
      +};
      +
      +/**
      + * Parse attributes of a DOM element to
      + * get an object of {attributeName => attributeValue}
      + *
      + * @param  {object} element DOM element to parse
      + * @return {object}         Object of attributes
      + */
      +Vivus.prototype.parseAttr = function (element) {
      +  var attr, output = {};
      +  if (element && element.attributes) {
      +    for (var i = 0; i < element.attributes.length; i++) {
      +      attr = element.attributes[i];
      +      output[attr.name] = attr.value;
      +    }
      +  }
      +  return output;
      +};
      +
      +/**
      + * Reply if an element is in the page viewport
      + *
      + * @param  {object} el Element to observe
      + * @param  {number} h  Percentage of height
      + * @return {boolean}
      + */
      +Vivus.prototype.isInViewport = function (el, h) {
      +  var scrolled   = this.scrollY(),
      +    viewed       = scrolled + this.getViewportH(),
      +    elBCR        = el.getBoundingClientRect(),
      +    elHeight     = elBCR.height,
      +    elTop        = scrolled + elBCR.top,
      +    elBottom     = elTop + elHeight;
      +
      +  // if 0, the element is considered in the viewport as soon as it enters.
      +  // if 1, the element is considered in the viewport only when it's fully inside
      +  // value in percentage (1 >= h >= 0)
      +  h = h || 0;
      +
      +  return (elTop + elHeight * h) <= viewed && (elBottom) >= scrolled;
      +};
      +
      +
      +/**
      + * Get the viewport height in pixels
      + *
      + * @return {integer} Viewport height
      + */
      +Vivus.prototype.getViewportH = function () {
      +  var client = this.docElem.clientHeight,
      +    inner = window.innerHeight;
      +
      +  if (client < inner) {
      +    return inner;
      +  }
      +  else {
      +    return client;
      +  }
      +};
      +
      +/**
      + * Get the page Y offset
      + *
      + * @return {integer} Page Y offset
      + */
      +Vivus.prototype.scrollY = function () {
      +  return window.pageYOffset || this.docElem.scrollTop;
      +};
      +
      +setupEnv = function () {
      +
      +  if (Vivus.prototype.docElem) {
      +    return;
      +  }
      +
      +  /**
      +   * Alias for document element
      +   *
      +   * @type {DOMelement}
      +   */
      +  Vivus.prototype.docElem = window.document.documentElement;
      +
      +  /**
      +   * Alias for `requestAnimationFrame` or
      +   * `setTimeout` function for deprecated browsers.
      +   *
      +   */
      +  requestAnimFrame = (function () {
      +    return (
      +      window.requestAnimationFrame       ||
      +      window.webkitRequestAnimationFrame ||
      +      window.mozRequestAnimationFrame    ||
      +      window.oRequestAnimationFrame      ||
      +      window.msRequestAnimationFrame     ||
      +      function(/* function */ callback){
      +        return window.setTimeout(callback, 1000 / 60);
      +      }
      +    );
      +  })();
      +
      +  /**
      +   * Alias for `cancelAnimationFrame` or
      +   * `cancelTimeout` function for deprecated browsers.
      +   *
      +   */
      +  cancelAnimFrame = (function () {
      +    return (
      +      window.cancelAnimationFrame       ||
      +      window.webkitCancelAnimationFrame ||
      +      window.mozCancelAnimationFrame    ||
      +      window.oCancelAnimationFrame      ||
      +      window.msCancelAnimationFrame     ||
      +      function(id){
      +        return window.clearTimeout(id);
      +      }
      +    );
      +  })();
      +};
      +
      +/**
      + * Parse string to integer.
      + * If the number is not positive or null
      + * the method will return the default value
      + * or 0 if undefined
      + *
      + * @param {string} value String to parse
      + * @param {*} defaultValue Value to return if the result parsed is invalid
      + * @return {number}
      + *
      + */
      +parsePositiveInt = function (value, defaultValue) {
      +  var output = parseInt(value, 10);
      +  return (output >= 0) ? output : defaultValue;
      +};
      +
      +
      +  if (typeof define === 'function' && define.amd) {
      +    // AMD. Register as an anonymous module.
      +    define([], function() {
      +      return Vivus;
      +    });
      +  } else if (typeof exports === 'object') {
      +    // Node. Does not work with strict CommonJS, but
      +    // only CommonJS-like environments that support module.exports,
      +    // like Node.
      +    module.exports = Vivus;
      +  } else {
      +    // Browser globals
      +    window.Vivus = Vivus;
      +  }
      +
      +}());
      diff --git a/assets/js/dev/vendors/wallpaper.js b/assets/js/dev/vendors/wallpaper.js
      new file mode 100644
      index 0000000..46421eb
      --- /dev/null
      +++ b/assets/js/dev/vendors/wallpaper.js
      @@ -0,0 +1,954 @@
      +/* 
      + * Wallpaper v3.1.19 - 2015-04-04 
      + * A jQuery plugin for smooth-scaling image and video backgrounds. Part of the Formstone Library. 
      + * https://github.com/FormstoneClassic/Wallpaper/blob/master/jquery.fs.wallpaper.js
      + * 
      + * Copyright 2015 Ben Plum; MIT Licensed 
      + */ 
      +
      +;(function ($, window) {
      +	"use strict";
      +
      +	var $window = $(window),
      +		$body,
      +		$responders = null,
      +		nativeSupport = ("backgroundSize" in document.documentElement.style),
      +		guid = 0,
      +		youTubeReady = false,
      +		youTubeQueue = [],
      +		UA = (window.navigator.userAgent||window.navigator.vendor||window.opera),
      +		isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i.test(UA),
      +		isSafari = (UA.toLowerCase().indexOf('safari') >= 0) && (UA.toLowerCase().indexOf('chrome') < 0),
      +		transitionEvent,
      +		transitionSupported,
      +		respondTimer;
      +
      +	/**
      +	 * @options
      +	 * @param autoPlay [boolean] <true> "Autoplay video"
      +	 * @param embedRatio [number] <1.777777> "Video / embed ratio (16/9)"
      +	 * @param hoverPlay [boolean] <false> "Play video on hover"
      +	 * @param loop [boolean] <true> "Loop video"
      +	 * @param mute [boolean] <true> "Mute video"
      +	 * @param onLoad [function] <$.noop> "On load callback"
      +	 * @param onReady [function] <$.noop> "On ready callback"
      +	 * @param source [string | object] <null> "Source image (string or object) or video (object) or YouTube (object)"
      +	 */
      +	var options = {
      +		autoPlay: true,
      +		embedRatio: 1.777777,
      +		hoverPlay: false,
      +		loop: true,
      +		mute: true,
      +		onLoad: $.noop,
      +		onReady: $.noop,
      +		source: null
      +	};
      +
      +	/**
      +	 * @events
      +	 * @event wallpaper.loaded "Source media loaded"
      +	 */
      +
      +	var pub = {
      +
      +		/**
      +		 * @method
      +		 * @name defaults
      +		 * @description Sets default plugin options
      +		 * @param opts [object] <{}> "Options object"
      +		 * @example $.wallpaper("defaults", opts);
      +		 */
      +		defaults: function(opts) {
      +			options = $.extend(options, opts || {});
      +			return (typeof this === 'object') ? $(this) : true;
      +		},
      +
      +		/**
      +		 * @method
      +		 * @name destroy
      +		 * @description Removes instance of plugin
      +		 * @example $(".target").wallpaper("destroy");
      +		 */
      +		destroy: function() {
      +			var $targets = $(this).each(function() {
      +				var data = $(this).data("wallpaper");
      +
      +				if (data) {
      +					data.$container.remove();
      +					data.$target.removeClass("wallpaper")
      +								.off(".boxer")
      +								.data("wallpaper", null);
      +				}
      +			});
      +
      +			if (typeof $body !== "undefined" && typeof $window !== "undefined" && $(".wallpaper").length < 1) {
      +				$body.removeClass("wallpaper-inititalized");
      +				$window.off(".wallpaper");
      +			}
      +
      +			return $targets;
      +		},
      +
      +		/**
      +		 * @method
      +		 * @name load
      +		 * @description Loads source media
      +		 * @param source [string | object] "Source image (string) or video (object) or YouTube (object); { source: { poster: <"">, video: <"" or {}>  } }"
      +		 * @example $(".target").wallpaper("load", "path/to/image.jpg");
      +		 */
      +		load: function(source) {
      +			return $(this).each(function() {
      +				var data = $(this).data("wallpaper");
      +
      +				if (data) {
      +					_loadMedia(source, data);
      +				}
      +			});
      +		},
      +
      +		/**
      +		 * @method
      +		 * @name pause
      +		 * @description Pauses target video
      +		 * @example $(".target").wallpaper("stop");
      +		 */
      +		pause: function() {
      +			return $(this).each(function() {
      +				var data = $(this).data("wallpaper");
      +
      +				if (data) {
      +					if (data.isYouTube && data.playerReady) {
      +						data.player.pauseVideo();
      +					} else {
      +						var $video = data.$container.find("video");
      +
      +						if ($video.length) {
      +							$video[0].pause();
      +						}
      +					}
      +				}
      +			});
      +		},
      +
      +		/**
      +		 * @method
      +		 * @name play
      +		 * @description Plays target video
      +		 * @example $(".target").wallpaper("play");
      +		 */
      +		play: function() {
      +			return $(this).each(function() {
      +				var data = $(this).data("wallpaper");
      +
      +				if (data) {
      +					if (data.isYouTube && data.playerReady) {
      +						data.player.playVideo();
      +					} else {
      +						var $video = data.$container.find("video");
      +
      +						if ($video.length) {
      +							$video[0].play();
      +						}
      +					}
      +				}
      +			});
      +		},
      +
      +		/**
      +		 * @method private
      +		 * @name stop
      +		 * @description Deprecated; Aliased to "pause"
      +		 * @example $(".target").wallpaper("stop");
      +		 */
      +		stop: function() {
      +			pub.pause.apply(this);
      +		},
      +
      +		/**
      +		 * @method
      +		 * @name unload
      +		 * @description Unloads current media
      +		 * @example $(".target").wallpaper("unload");
      +		 */
      +		unload: function() {
      +			return $(this).each(function() {
      +				var data = $(this).data("wallpaper");
      +
      +				if (data) {
      +					_unloadMedia(data);
      +				}
      +			});
      +		}
      +	};
      +
      +	/**
      +	 * @method private
      +	 * @name _init
      +	 * @description Initializes plugin instances
      +	 * @param opts [object] "Initialization options"
      +	 */
      +	function _init(opts) {
      +		var data = $.extend({}, options, opts);
      +
      +		$body = $("body");
      +		transitionEvent = _getTransitionEvent();
      +		transitionSupported = (transitionEvent !== false);
      +
      +		// no transitions :(
      +		if (!transitionSupported) {
      +			transitionEvent = "transitionend.wallpaper";
      +		}
      +
      +		// Apply to each
      +		var $targets = $(this);
      +		for (var i = 0, count = $targets.length; i < count; i++) {
      +			_build.apply($targets.eq(i), [ $.extend({}, data) ]);
      +		}
      +
      +		// Global events
      +		if (!$body.hasClass("wallpaper-inititalized")) {
      +			$body.addClass("wallpaper-inititalized");
      +			$window.on("resize.wallpaper", data, _onResizeAll);
      +		}
      +
      +		// Maintain chainability
      +		return $targets;
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _build
      +	 * @description Builds each instance
      +	 * @param data [object] "Instance data"
      +	 */
      +	function _build(data) {
      +		var $target = $(this);
      +		if (!$target.hasClass("wallpaper")) {
      +			$.extend(data, $target.data("wallpaper-options"));
      +
      +			$target.addClass("wallpaper")
      +				   .append('<div class="wallpaper-container"></div>');
      +
      +			data.guid = "wallpaper-" + (guid++);
      +			data.youTubeGuid = 0;
      +			data.$target = $target;
      +			data.$container = data.$target.find(".wallpaper-container");
      +
      +			// Bind data & events
      +			data.$target.data("wallpaper", data)
      +						.on("resize.wallpaper", data, _onResize);
      +
      +			var source = data.source;
      +			data.source = null;
      +
      +			_loadMedia(source, data, true);
      +
      +			data.onReady.call();
      +		}
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _loadMedia
      +	 * @description Determines how to handle source media
      +	 * @param source [string | object] "Source image (string) or video (object)"
      +	 * @param data [object] "Instance data"
      +	 * @param firstLoad [boolean] "Flag for first load"
      +	 */
      +	function _loadMedia(source, data, firstLoad) {
      +		// Check if the source is new
      +		if (source !== data.source) {
      +			data.source = source;
      +			data.isYouTube = false;
      +
      +			// Check YouTube
      +			if (typeof source === "object" && typeof source.video === "string") {
      +				// var parts = source.match( /^.*(?:youtu.be\/|v\/|e\/|u\/\w+\/|embed\/|v=)([^#\&\?]*).*/ );
      +				var parts = source.video.match( /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i );
      +				if (parts && parts.length >= 1) {
      +					data.isYouTube = true;
      +					data.videoId = parts[1];
      +				}
      +			}
      +
      +			if (data.isYouTube) {
      +				// youtube video
      +				data.playing = false;
      +				data.playerReady = false;
      +				data.posterLoaded = false;
      +
      +				_loadYouTube(source, data, firstLoad);
      +			} else if (typeof source === "object" && !source.hasOwnProperty("fallback")) {
      +				// html5 video
      +				_loadVideo(source, data, firstLoad);
      +			} else {
      +				// regular old image
      +				if (data.responsiveSource) {
      +					for (var i in data.responsiveSource) {
      +						if (data.responsiveSource.hasOwnProperty(i)) {
      +							data.responsiveSource[i].mq.removeListener(_onRespond);
      +						}
      +					}
      +				}
      +
      +				data.responsive = false;
      +				data.responsiveSource = null;
      +
      +				// Responsive image handling
      +				if (typeof source === "object") {
      +					var sources = [],
      +						newSource;
      +
      +					for (var j in source) {
      +						if (source.hasOwnProperty(j)) {
      +							var media = (j === "fallback") ? "(min-width: 0px)" : j;
      +
      +							if (media) {
      +								var _mq = window.matchMedia(media.replace(Infinity, "100000px"));
      +								_mq.addListener(_onRespond);
      +								sources.push({
      +									mq: _mq,
      +									source: source[j]
      +								});
      +
      +								if (_mq.matches) {
      +									newSource = source[j];
      +								}
      +							}
      +						}
      +					}
      +
      +					data.responsive = true;
      +					data.responsiveSource = sources;
      +					source = newSource;
      +				}
      +
      +				// single or responsive set
      +				_loadImage(source, data, false, firstLoad);
      +			}
      +		} else {
      +			data.$target.trigger("wallpaper.loaded");
      +			data.onLoad.call(data.$target);
      +		}
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _loadImage
      +	 * @description Loads source image
      +	 * @param source [string] "Source image"
      +	 * @param data [object] "Instance data",
      +	 * @param poster [boolean] "Flag for video poster"
      +	 */
      +	function _loadImage(source, data, poster, firstLoad) {
      +		
      +		var $position = data.source.poster_position ? data.source.poster_position :'thz-center-top';
      +		
      +		var $imgContainer = $('<div class="wallpaper-media wallpaper-image '+$position+' ' + ((firstLoad !== true) ? ' animated' : '') + '"><img alt="" /></div>'),
      +			$img = $imgContainer.find("img"),
      +			newSource = source;
      +
      +		// Load image
      +		$img.one("load.wallpaper", function() {
      +			if (nativeSupport) {
      +				$imgContainer.addClass("native")
      +							 .css({ backgroundImage: "url('" + newSource + "')" });
      +			}
      +
      +			// Append
      +			$imgContainer.on(transitionEvent, function(e) {
      +				_killEvent(e);
      +
      +				if ($(e.target).is($imgContainer)) {
      +					$imgContainer.off(transitionEvent);
      +
      +					if (!poster) {
      +						_cleanMedia(data);
      +					}
      +				}
      +			});
      +
      +			setTimeout( function() {
      +				$imgContainer.css({ opacity: 1 });
      +
      +				if (data.responsive && firstLoad) {
      +					_cleanMedia(data);
      +				}
      +			}, 0);
      +
      +			// Resize
      +			_onResize({ data: data });
      +
      +			if (!poster || firstLoad) {
      +				data.$target.trigger("wallpaper.loaded");
      +				data.onLoad.call(data.$target);
      +			}
      +
      +			// caches responsive images
      +			$responders = $(".wallpaper-responsive");
      +		}).attr("src", newSource);
      +
      +		if (data.responsive) {
      +			$imgContainer.addClass("wallpaper-responsive");
      +		}
      +
      +		data.$container.append($imgContainer);
      +
      +		// Check if image is cached
      +		if ($img[0].complete || $img[0].readyState === 4) {
      +			$img.trigger("load.wallpaper");
      +		}
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _loadVideo
      +	 * @description Loads source video
      +	 * @param source [object] "Source video"
      +	 * @param data [object] "Instance data"
      +	 */
      +	function _loadVideo(source, data, firstLoad) {
      +		
      +		if (data.source.poster) {
      +			_loadImage(data.source.poster, data, true, true);
      +
      +			firstLoad = false;
      +		}
      +
      +		if (!isMobile) {
      +			var html = '<div class="wallpaper-media wallpaper-video' + ((firstLoad !== true) ? ' animated' : '') +'">';
      +			html += '<video';
      +			if (data.loop) {
      +				html += ' loop';
      +			}
      +			if (data.mute) {
      +				html += ' muted';
      +			}
      +			html += '>';
      +			if (data.source.webm) {
      +				html += '<source src="' + data.source.webm + '" type="video/webm" />';
      +			}
      +			if (data.source.mp4) {
      +				html += '<source src="' + data.source.mp4 + '" type="video/mp4" />';
      +			}
      +			if (data.source.ogg) {
      +				html += '<source src="' + data.source.ogg + '" type="video/ogg" />';
      +			}
      +			html += '</video>';
      +			html += '</div>';
      +
      +			var $videoContainer = $(html),
      +				$video = $videoContainer.find("video");
      +
      +			$video.one("loadedmetadata.wallpaper", function(e) {
      +				$videoContainer.on(transitionEvent, function(e) {
      +					_killEvent(e);
      +
      +					if ($(e.target).is($videoContainer)) {
      +						$videoContainer.off(transitionEvent);
      +
      +						_cleanMedia(data);
      +					}
      +				});
      +				
      +				var $delay = 0;
      +				if(data.source.poster && $videoContainer.parents('.thz-parallax').length > 0){
      +					$delay = 800;
      +				}
      +				
      +				setTimeout( function() { 
      +					$videoContainer.css({ opacity: 1 }); 
      +				}, $delay);
      +
      +				// Resize
      +				_onResize({ data: data });
      +
      +				data.$target.trigger("wallpaper.loaded");
      +				data.onLoad.call(data.$target);
      +
      +				// Events
      +				if (data.hoverPlay) {
      +					data.$target.on("mouseover.boxer", pub.play)
      +								.on("mouseout.boxer", pub.pause);
      +				} else if (data.autoPlay) {
      +					this.play();
      +				}
      +			});
      +			
      +			if( data.source.poster && !data.loop ){
      +				$video.on("ended", function() {
      +					$videoContainer.css({ opacity: 0 });
      +				});
      +			}
      +
      +			data.$container.append($videoContainer);
      +		}
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _loadYouTube
      +	 * @description Loads YouTube video
      +	 * @param source [string] "YouTube URL"
      +	 * @param data [object] "Instance data"
      +	 */
      +	function _loadYouTube(source, data, firstLoad) {
      +		if (!data.videoId) {
      +			var parts = source.match( /^.*(?:youtu.be\/|v\/|e\/|u\/\w+\/|embed\/|v=)([^#\&\?]*).*/ );
      +			data.videoId = parts[1];
      +		}
      +
      +		if (!data.posterLoaded) {
      +			if (!data.source.poster) {
      +				// data.source.poster = "http://img.youtube.com/vi/" + data.videoId + "/maxresdefault.jpg";
      +				data.source.poster = "http://img.youtube.com/vi/" + data.videoId + "/0.jpg";
      +			}
      +
      +			data.posterLoaded = true;
      +			_loadImage(data.source.poster, data, true, firstLoad);
      +
      +			firstLoad = false;
      +		}
      +
      +
      +		var $start = 0;
      +		
      +		if(source.video.indexOf('t=') != - 1){
      +			
      +			var $split = source.video.split('t=');
      +			var hms = $split[1].replace('h',':').replace('m',':').replace('s','');
      +			var a = hms.split(':');
      +			
      +			if (a.length == 1){
      +			 	
      +				$start = a[0]; 
      +			
      +			} else if (a.length == 2){
      +			 	
      +				$start = (+a[0]) * 60 + (+a[1]); 
      +				
      +			} else if (a.length == 3){
      +			 	
      +				$start = (+a[0]) * 60 * 60 + (+a[1]) * 60 + (+a[2]); 
      +				
      +			}
      +			
      +		}
      +		
      +		if (!isMobile) {
      +			if (!$("script[src*='youtube.com/iframe_api']").length) {
      +				$("head").append('<script src="//www.youtube.com/iframe_api"></script>');
      +			}
      +
      +			if (!youTubeReady) {
      +				youTubeQueue.push({
      +					source: source,
      +					data: data
      +				});
      +			} else {
      +				var guid = data.guid + "_" + (data.youTubeGuid++),
      +					html = '';
      +
      +				html += '<div class="wallpaper-media wallpaper-embed' + ((firstLoad !== true) ? ' animated' : '') + '">';
      +				html += '<div id="' + guid + '"></div>';
      +				html += '</div>';
      +
      +				var $embedContainer = $(html);
      +				data.$container.append($embedContainer);
      +
      +				if (data.player) {
      +					data.oldPlayer = data.player;
      +					data.player = null;
      +				}
      +
      +				data.player = new window.YT.Player(guid, {
      +					videoId: data.videoId,
      +					playerVars: {
      +						controls: 0,
      +						rel: 0,
      +						showinfo: 0,
      +						start:$start,
      +						wmode: "transparent",
      +						enablejsapi: 1,
      +						version: 3,
      +						playerapiid: guid,
      +						loop: (data.loop) ? 1 : 0,
      +						autoplay: 1,
      +						origin: window.location.protocol + "//" + window.location.host
      +					},
      +					events: {
      +						onReady: function (e) {
      +							/* console.log("onReady", e); */
      +
      +							data.playerReady = true;
      +							/* data.player.setPlaybackQuality("highres"); */
      +
      +							if (data.mute) {
      +								data.player.mute();
      +							}
      +
      +							if (data.hoverPlay) {
      +								data.$target.on("mouseover.boxer", pub.play)
      +											.on("mouseout.boxer", pub.pause);
      +							} else if (data.autoPlay) {
      +								// make sure the video plays
      +								data.player.playVideo();
      +							}
      +						},
      +						onStateChange: function (e) {
      +							/* console.log("onStateChange", e); */
      +
      +							if (!data.playing && e.data === window.YT.PlayerState.PLAYING) {
      +								data.playing = true;
      +
      +								if (data.hoverPlay || !data.autoPlay) {
      +									data.player.pauseVideo();
      +								}
      +
      +								data.$target.trigger("wallpaper.loaded");
      +								data.onLoad.call(data.$target);
      +
      +								$embedContainer.on(transitionEvent, function(e) {
      +									_killEvent(e);
      +
      +									if ($(e.target).is($embedContainer)) {
      +										$embedContainer.off(transitionEvent);
      +
      +										_cleanMedia(data);
      +									}
      +								});
      +
      +								$embedContainer.css({ opacity: 1 });
      +							} else if (data.loop && data.playing && e.data === window.YT.PlayerState.ENDED) {
      +								
      +								if( $start != 0 ){
      +									//data.player.loadVideoById(data.videoId);
      +/*									e.target.loadVideoById({
      +										videoId: data.videoId,
      +										startSeconds: $start,
      +									});*/
      +									data.player.seekTo($start);
      +								}
      +								
      +								// fix looping option
      +								data.player.playVideo();
      +								
      +							} else if ( data.source.poster && !data.loop && data.playing && e.data === window.YT.PlayerState.ENDED ) {
      +								// show preview image
      +								$embedContainer.css({ opacity: 0 });
      +							}
      +
      +							/* if (!isSafari) { */
      +								// Fix for Safari's overly secure security settings...
      +								data.$target.find(".wallpaper-embed").addClass("ready");
      +							/* } */
      +						},
      +						onPlaybackQualityChange: function(e) {
      +							/* console.log("onPlaybackQualityChange", e); */
      +						},
      +						onPlaybackRateChange: function(e) {
      +							/* console.log("onPlaybackRateChange", e); */
      +						},
      +						onError: function(e) {
      +							/* console.log("onError", e); */
      +						},
      +						onApiChange: function(e) {
      +							/* console.log("onApiChange", e); */
      +						}
      +					}
      +		        });
      +
      +				// Resize
      +				_onResize({ data: data });
      +			}
      +		}
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _cleanMedia
      +	 * @description Cleans up old media
      +	 * @param data [object] "Instance data"
      +	 */
      +	function _cleanMedia(data) {
      +		var $mediaContainer = data.$container.find(".wallpaper-media");
      +
      +		if ($mediaContainer.length >= 1) {
      +			$mediaContainer.not(":last").remove();
      +			data.oldPlayer = null;
      +		}
      +
      +		$responders = $(".wallpaper-responsive");
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _uploadMedia
      +	 * @description Unloads current media
      +	 * @param data [object] "Instance data"
      +	 */
      +	function _unloadMedia(data) {
      +		var $mediaContainer = data.$container.find(".wallpaper-media");
      +
      +		if ($mediaContainer.length >= 1) {
      +			$mediaContainer.on(transitionEvent, function(e) {
      +				_killEvent(e);
      +
      +				if ($(e.target).is($mediaContainer)) {
      +					$(this).remove();
      +
      +					delete data.source;
      +				}
      +			}).css({ opacity: 0 });
      +		}
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _onResize
      +	 * @description Resize target instance
      +	 * @param e [object] "Event data"
      +	 */
      +	function _onResize(e) {
      +		_killEvent(e);
      +
      +		var data = e.data;
      +		
      +		if(data == undefined){
      +			return;
      +		}
      +		
      +		// Target all media
      +		var $mediaContainers = data.$container.find(".wallpaper-media");
      +
      +		for (var i = 0, count = $mediaContainers.length; i < count; i++) {
      +			var $mediaContainer = $mediaContainers.eq(i),
      +				type = (data.isYouTube) ? "iframe" : ($mediaContainer.find("video").length ? "video" : "img"),
      +				$media = $mediaContainer.find(type);
      +
      +			// If media found and scaling is not natively support
      +			if ($media.length && !(type === "img" && data.nativeSupport)) {
      +				var frameWidth = data.$target.outerWidth(),
      +					frameHeight = data.$target.outerHeight(),
      +					frameRatio = frameWidth / frameHeight,
      +					naturalSize = _naturalSize(data, $media);
      +
      +				data.width = naturalSize.naturalWidth;
      +				data.height = naturalSize.naturalHeight;
      +				data.left = 0;
      +				data.top = 0;
      +
      +				var mediaRatio = (data.isYouTube) ? data.embedRatio : (data.width / data.height);
      +
      +				// First check the height
      +				data.height = frameHeight;
      +				data.width = data.height * mediaRatio;
      +
      +				// Next check the width
      +				if (data.width < frameWidth) {
      +					data.width = frameWidth;
      +					data.height = data.width / mediaRatio;
      +				}
      +
      +				// Position the media
      +				data.left = -(data.width - frameWidth) / 2;
      +				data.top = -(data.height - frameHeight) / 2;
      +
      +				$mediaContainer.css({
      +					height: data.height,
      +					width: data.width,
      +					left: data.left,
      +					top: data.top
      +				});
      +			}
      +		}
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _onResizeAll
      +	 * @description Resizes all target instances
      +	 */
      +	function _onResizeAll() {
      +		$(".wallpaper").each(function() {
      +			var data = $(this).data("wallpaper");
      +			_onResize({ data: data });
      +		});
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _onRespond
      +	 * @description Handle media query changes
      +	 */
      +	function _onRespond() {
      +		respondTimer = _startTimer(respondTimer, 5, _doRespond);
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _doRespond
      +	 * @description Handle media query changes
      +	 */
      +	function _doRespond() {
      +		_clearTimer(respondTimer);
      +
      +		$responders.each(function() {
      +			var $target = $(this),
      +				$image = $target.find("img"),
      +				data = $target.parents(".wallpaper").data("wallpaper"),
      +				sources = data.responsiveSource,
      +				index = 0;
      +
      +			for (var i = 0, count = sources.length; i < count; i++) {
      +				if (sources.hasOwnProperty(i)) {
      +					var match = sources[i].mq;
      +
      +					if (match && match.matches) {
      +						index = i;
      +					}
      +				}
      +			}
      +
      +			_loadImage(sources[index].source, data, false, true);
      +
      +			$target.trigger("change.wallpaper");
      +		});
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _startTimer
      +	 * @description Starts an internal timer
      +	 * @param timer [int] "Timer ID"
      +	 * @param time [int] "Time until execution"
      +	 * @param callback [int] "Function to execute"
      +	 * @param interval [boolean] "Flag for recurring interval"
      +	 */
      +	function _startTimer(timer, time, func, interval) {
      +		_clearTimer(timer, interval);
      +		return setTimeout(func, time);
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _clearTimer
      +	 * @description Clears an internal timer
      +	 * @param timer [int] "Timer ID"
      +	 */
      +	function _clearTimer(timer) {
      +		if (timer !== null) {
      +			clearInterval(timer);
      +			timer = null;
      +		}
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _naturalSize
      +	 * @description Determines natural size of target media
      +	 * @param data [object] "Instance data"
      +	 * @param $media [jQuery object] "Source media object"
      +	 * @return [object | boolean] "Object containing natural height and width values or false"
      +	 */
      +	function _naturalSize(data, $media) {
      +		if (data.isYouTube) {
      +			return {
      +				naturalHeight: 500,
      +				naturalWidth:  500 / data.embedRatio
      +			};
      +		} else if ($media.is("img")) {
      +			var node = $media[0];
      +
      +			if (typeof node.naturalHeight !== "undefined") {
      +				return {
      +					naturalHeight: node.naturalHeight,
      +					naturalWidth:  node.naturalWidth
      +				};
      +			} else {
      +				var img = new Image();
      +				img.src = node.src;
      +				return {
      +					naturalHeight: img.height,
      +					naturalWidth:  img.width
      +				};
      +			}
      +		} else {
      +			return {
      +				naturalHeight: $media[0].videoHeight,
      +				naturalWidth:  $media[0].videoWidth
      +			};
      +		}
      +		return false;
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _killEvent
      +	 * @description Prevents default and stops propagation on event
      +	 * @param e [object] "Event data"
      +	 */
      +	function _killEvent(e) {
      +		if (e.preventDefault) {
      +			e.stopPropagation();
      +			e.preventDefault();
      +		}
      +	}
      +
      +	/**
      +	 * @method private
      +	 * @name _getTransitionEvent
      +	 * @description Retuns a properly prefixed transitionend event
      +	 * @return [string] "Properly prefixed event"
      +	 */
      +	function _getTransitionEvent() {
      +		var transitions = {
      +				'WebkitTransition': 'webkitTransitionEnd',
      +				'MozTransition':    'transitionend',
      +				'OTransition':      'oTransitionEnd',
      +				'transition':       'transitionend'
      +			},
      +			test = document.createElement('div');
      +
      +		for (var type in transitions) {
      +			if (transitions.hasOwnProperty(type) && type in test.style) {
      +				return transitions[type] + ".wallpaper";
      +			}
      +		}
      +
      +		return false;
      +	}
      +
      +	/**
      +	 * @method global
      +	 * @name window.onYouTubeIframeAPIReady
      +	 * @description Attaches YouTube players to active instances
      +	 */
      +	window.onYouTubeIframeAPIReady = function() {
      +		youTubeReady = true;
      +
      +		for (var i in youTubeQueue) {
      +			if (youTubeQueue.hasOwnProperty(i)) {
      +				_loadYouTube(youTubeQueue[i].source, youTubeQueue[i].data);
      +			}
      +		}
      +
      +		youTubeQueue = [];
      +	};
      +
      +	$.fn.wallpaper = function(method) {
      +		if (pub[method]) {
      +			return pub[method].apply(this, Array.prototype.slice.call(arguments, 1));
      +		} else if (typeof method === 'object' || !method) {
      +			return _init.apply(this, arguments);
      +		}
      +		return this;
      +	};
      +
      +	$.wallpaper = function(method) {
      +		if (method === "defaults") {
      +			pub.defaults.apply(this, Array.prototype.slice.call(arguments, 1));
      +		}
      +	};
      +})(jQuery, window);
      \ No newline at end of file
      diff --git a/assets/js/dev/vendors/waypoints.inview.js b/assets/js/dev/vendors/waypoints.inview.js
      new file mode 100644
      index 0000000..2d5c1b0
      --- /dev/null
      +++ b/assets/js/dev/vendors/waypoints.inview.js
      @@ -0,0 +1,120 @@
      +/*!
      +Waypoints Inview Shortcut - 4.0.1
      +Copyright © 2011-2016 Caleb Troughton
      +Licensed under the MIT license.
      +https://github.com/imakewebthings/waypoints/blob/master/licenses.txt
      +*/
      +(function() {
      +  'use strict'
      +
      +  function noop() {}
      +
      +  var Waypoint = window.Waypoint
      +
      +  /* http://imakewebthings.com/waypoints/shortcuts/inview */
      +  function Inview(options) {
      +    this.options = Waypoint.Adapter.extend({}, Inview.defaults, options)
      +    this.axis = this.options.horizontal ? 'horizontal' : 'vertical'
      +    this.waypoints = []
      +    this.element = this.options.element
      +    this.createWaypoints()
      +  }
      +
      +  /* Private */
      +  Inview.prototype.createWaypoints = function() {
      +    var configs = {
      +      vertical: [{
      +        down: 'enter',
      +        up: 'exited',
      +        offset: '100%'
      +      }, {
      +        down: 'entered',
      +        up: 'exit',
      +        offset: 'bottom-in-view'
      +      }, {
      +        down: 'exit',
      +        up: 'entered',
      +        offset: 0
      +      }, {
      +        down: 'exited',
      +        up: 'enter',
      +        offset: function() {
      +          return -this.adapter.outerHeight()
      +        }
      +      }],
      +      horizontal: [{
      +        right: 'enter',
      +        left: 'exited',
      +        offset: '100%'
      +      }, {
      +        right: 'entered',
      +        left: 'exit',
      +        offset: 'right-in-view'
      +      }, {
      +        right: 'exit',
      +        left: 'entered',
      +        offset: 0
      +      }, {
      +        right: 'exited',
      +        left: 'enter',
      +        offset: function() {
      +          return -this.adapter.outerWidth()
      +        }
      +      }]
      +    }
      +
      +    for (var i = 0, end = configs[this.axis].length; i < end; i++) {
      +      var config = configs[this.axis][i]
      +      this.createWaypoint(config)
      +    }
      +  }
      +
      +  /* Private */
      +  Inview.prototype.createWaypoint = function(config) {
      +    var self = this
      +    this.waypoints.push(new Waypoint({
      +      context: this.options.context,
      +      element: this.options.element,
      +      enabled: this.options.enabled,
      +      handler: (function(config) {
      +        return function(direction) {
      +          self.options[config[direction]].call(self, direction)
      +        }
      +      }(config)),
      +      offset: config.offset,
      +      horizontal: this.options.horizontal
      +    }))
      +  }
      +
      +  /* Public */
      +  Inview.prototype.destroy = function() {
      +    for (var i = 0, end = this.waypoints.length; i < end; i++) {
      +      this.waypoints[i].destroy()
      +    }
      +    this.waypoints = []
      +  }
      +
      +  Inview.prototype.disable = function() {
      +    for (var i = 0, end = this.waypoints.length; i < end; i++) {
      +      this.waypoints[i].disable()
      +    }
      +  }
      +
      +  Inview.prototype.enable = function() {
      +    for (var i = 0, end = this.waypoints.length; i < end; i++) {
      +      this.waypoints[i].enable()
      +    }
      +  }
      +
      +  Inview.defaults = {
      +    context: window,
      +    enabled: true,
      +    enter: noop,
      +    entered: noop,
      +    exit: noop,
      +    exited: noop
      +  }
      +
      +  Waypoint.Inview = Inview
      +}())
      +;
      \ No newline at end of file
      diff --git a/assets/js/thz.site.plugins.js b/assets/js/thz.site.plugins.js
      index 76e1d32..ecb0304 100644
      --- a/assets/js/thz.site.plugins.js
      +++ b/assets/js/thz.site.plugins.js
      @@ -27,7 +27,7 @@
       
       /*
        * jQuery Easing v1.4.1 - http://gsgd.co.uk/sandbox/jquery/easing/
      - * Open source under the BSD License.
      + * Open source under the 3-Clause BSD License.
        * Copyright © 2008 George McGinley Smith
        * All rights reserved.
        * https://raw.github.com/gdsmith/jquery-easing/master/LICENSE
      @@ -108,7 +108,7 @@ c(d.prototype,b.prototype),d.prototype._getElementOffset=e,d.prototype.layout=f,
       
       /*!
        * jQuery Scrollify
      - * Version 1.0.19 - L662:L664 modified by themezly https://github.com/lukehaas/Scrollify/issues/330
      + * Version 1.0.19 - L658:L659 modified by themezly https://github.com/lukehaas/Scrollify/issues/330
        * added settings.delay .delay(settings.delay)
        *
        * Requires:
      @@ -305,6 +305,7 @@ window.ThzSetTimeout = function(fn, delay) {
        * @package		Thz Get Transform Decompose Matrix
        * @copyright	Copyright(C) FT Web Studio Inc since 2015. All Rights Reserved.
        * @author		Themezly
      + * @license		MIT License (MIT) http://www.opensource.org/licenses/mit-license.php
        * @websites	http://www.themezly.com | http://www.youjoomla.com
        */
       jQuery.fn.ThzGetTransform=function(t){var a=this.is(":visible")?this.css("transform"):this.actual("transform");if("none"!=a){var e=a.split("(")[1].split(")")[0].split(","),r=Math.atan2(e[1],e[0]),s=Math.pow(e[0],2)+Math.pow(e[1],2),n=Math.sqrt(s),o=(e[0]*e[3]-e[2]*e[1])/n,l=Math.atan2(e[0]*e[2]+e[1]*e[3],s),i={angle:r/(Math.PI/180),scaleX:n,scaleY:o,skewX:l/(Math.PI/180),skewY:0,translateX:e[4],translateY:e[5]};if(t.current){var m=[];if(0!=i.angle&&m.push("rotate("+i.angle+"deg)"),2!=(parseFloat(i.scaleX)+parseFloat(i.scaleY)).toFixed(2)&&m.push("scale("+i.scaleX+","+i.scaleY+")"),0!=parseFloat(i.skewX)+parseFloat(i.skewY)&&m.push("skew("+i.skewX+","+i.skewY+")"),0!=i.translateX||0!=i.translateY){var f=function(){if(!window.getComputedStyle)return!1;var t,a=document.createElement("p"),e={webkitTransform:"-webkit-transform",OTransform:"-o-transform",msTransform:"-ms-transform",MozTransform:"-moz-transform",transform:"transform"};for(var r in document.body.insertBefore(a,null),e)void 0!==a.style[r]&&(a.style[r]="translate3d(1px,1px,1px)",t=window.getComputedStyle(a).getPropertyValue(e[r]));return document.body.removeChild(a),void 0!==t&&0<t.length&&"none"!==t}()?"translate3d("+i.translateY+","+i.translateX+",0px)":"translate("+i.translateY+","+i.translateX+")";m.push(f)}return 0<m.length&&m.join(" ")}return i}};
      @@ -314,6 +315,7 @@ jQuery.fn.ThzGetTransform=function(t){var a=this.is(":visible")?this.css("transf
        * @package		Thz Parallax
        * @copyright	Copyright(C) FT Web Studio Inc since 2015. All Rights Reserved.
        * @author		Themezly
      + * @license		MIT License (MIT) http://www.opensource.org/licenses/mit-license.php
        * @websites	http://www.themezly.com | http://www.youjoomla.com
        */
       !function(b){var u=b(window),w=document.documentElement.clientHeight;document.documentElement.clientWidth;u.resize(function(){w=document.documentElement.clientHeight,document.documentElement.clientWidth}),b.fn.ThzParallax=function(c){var z,g,y,t=this,r=(c=b.extend({},{velocity:.3,direction:"up",scale:"",onmobile:0,size:"full"},c),[]),o=function(){if(!window.getComputedStyle)return!1;var t,e=document.createElement("p"),o={webkitTransform:"-webkit-transform",OTransform:"-o-transform",msTransform:"-ms-transform",MozTransform:"-moz-transform",transform:"transform"};for(var a in document.body.insertBefore(e,null),o)void 0!==e.style[a]&&(e.style[a]="translate3d(1px,1px,1px)",t=window.getComputedStyle(e).getPropertyValue(o[a]));return document.body.removeChild(e),void 0!==t&&0<t.length&&"none"!==t}();function e(){0!=t.length&&t.each(function(t,e){var o=b(e),a=o.ThzGetTransform({current:!0});if(c.velocity=o.attr("data-thzplx-velocity")?parseFloat(o.data("thzplx-velocity")/10):c.velocity,c.direction=o.attr("data-thzplx-direction")?o.data("thzplx-direction"):c.direction,c.scale=o.attr("data-thzplx-scale")?o.data("thzplx-scale"):c.scale,c.onmobile=o.attr("data-thzplx-onmobile")?o.data("thzplx-onmobile"):c.onmobile,c.size=o.attr("data-thzplx-size")?o.data("thzplx-size"):c.size,c.in_sticky=!!o.attr("data-thzplx-insticky"),navigator.userAgent.match(/Mobi/)&&0===c.onmobile)b(e).addClass("thz-no-mobile-parallax");else{!function(t,e,o){var a=b(t),n=a.parent(),i=e.direction,r=e.size,l=e.velocity,s=isNaN(parseFloat(r))?n.outerWidth():parseFloat(r),c=n.outerHeight(),d=n.offset().top,u=250*Math.abs(parseFloat(l)),m=350*Math.abs(parseFloat(l)),p="left"==i||"right"==i?s+u:s,f=c+m,h="down"==i?c-f:0,x="right"==i?s-p:0,v=0;w<d&&(v=d-w);y="left"==i||"right"==i?p-s:f-c,z=v,g=d+c,elemDirection=i,elemVelocity=l,"custom"===r?a.addClass("thz-parallaxing"):a.css({height:f+"px",width:p+"px",top:h+"px",left:x+"px",transform:T("0px","0px")+o}).addClass("thz-parallaxing")}(e,c,a);var n={};n.element=o,n.height=o.outerHeight(),n.width=o.outerWidth(),n.parentTop=o.parent().offset().top,n.direction=c.direction,n.velocity=c.velocity,n.scale=c.scale,n.scrollTopMin=z,n.scrollTopMax=g,n.moveMax=y,n.c_tr=a?" "+a:"",r.push(n)}})}function a(){for(i=0;i<r.length;i++)l(r[i])}function n(){for(var t=0,e=r.length;t<e;t++){r[t].element.parent().ThzIsVisible(200)&&l(r[t])}}function T(t,e){return o?"translate3d("+t+","+e+",0px)":"translate("+t+","+e+")"}function l(t){var e=b(t.element),o=u.scrollTop(),a=(t.velocity,t.direction),n=t.c_tr;if(c.in_sticky){if(("down"===a||"up"===a)&&o>e.outerHeight()-t.moveMax)return;if(("left"===a||"right"===a)&&o>e.parent().outerHeight()-t.moveMax)return;if("fixed"===a)return}t.scale;var i=function(t,e){t.velocity;var o=t.direction,a="";if("fixed"===o)return a;var n=t.scale;if("up"===n){var i=1+2e-4*e;i<1&&(i=1),a="scale3d("+(i+=.001)+","+i+",1) "}if("down"===n){var i=1-2e-4*e;1<i&&(i=1),a="scale3d("+i+","+i+",1) "}return a}(t,o),r=(o-t.scrollTopMin)/(t.scrollTopMax-t.scrollTopMin),l=t.moveMax*r;"left"!==a&&"up"!==a||(l*=-1);var s=i+T("0px",(l=Math.round(l))+"px");"left"!==a&&"right"!==a||(s=i+T(l+"px","0px")),"fixed"===a&&(l=Math.round(t.parentTop-o),s=i+T("0px",(l*=-1)+"px")),e.hasClass("thz-animate")?e.off("thz:animation:done").on("thz:animation:done",function(t){e.addClass("thz-starting-parallax"),setTimeout(function(){e.css({transform:s+n})},1),setTimeout(function(){e.removeClass("thz-starting-parallax")},401)}):e.css({transform:s+n})}var s,d=(s={},function(t,e,o){o||(o="Don't call this twice without a uniqueId"),s[o]&&clearTimeout(s[o]),s[o]=setTimeout(t,e)});e(),a(),u.resize(function(){d(function(){e(),a()},150,"thzparallax resized")}),u.on("scroll touchmove",function(){requestAnimationFrame(n)})}}(jQuery);
      @@ -322,6 +324,7 @@ jQuery.fn.ThzGetTransform=function(t){var a=this.is(":visible")?this.css("transf
        * @package		ThzInfinity
        * @copyright	Copyright(C) FT Web Studio Inc since 2015. All Rights Reserved.
        * @author		Themezly
      + * @license		MIT License (MIT) http://www.opensource.org/licenses/mit-license.php
        * @websites	http://www.themezly.com | http://www.youjoomla.com
        */
       !function(o){o.fn.ThzInfinity=function(u){var t=this,s=(u=o.extend({},{duration:60,direction:"up",onmobile:0},u),function(){if(!window.getComputedStyle)return!1;var t,r=document.createElement("p"),n={webkitTransform:"-webkit-transform",OTransform:"-o-transform",msTransform:"-ms-transform",MozTransform:"-moz-transform",transform:"transform"};for(var o in document.body.insertBefore(r,null),n)void 0!==r.style[o]&&(r.style[o]="translate3d(1px,1px,1px)",t=window.getComputedStyle(r).getPropertyValue(n[o]));return document.body.removeChild(r),void 0!==t&&0<t.length&&"none"!==t}());t.each(function(t,r){var i=o(r),n=i.ThzGetTransform({current:!0});if(u.duration=i.attr("data-thzinf-duration")?i.data("thzinf-duration"):u.duration,u.direction=i.attr("data-thzinf-direction")?i.data("thzinf-direction"):u.direction,u.onmobile=i.attr("data-thzinf-onmobile")?i.data("thzinf-onmobile"):u.onmobile,u.c_tr=n?" "+n:"",!navigator.userAgent.match(/Mobi/)||0!==u.onmobile){var a=u.direction,d=0,f=i.outerWidth(),m=i.outerHeight();setInterval(function(){if(i.parent().ThzIsVisible()){var t="left"==a||"up"==a?-1:1;(d-="right"==a||"down"==a?-1:1)==("left"==a||"right"==a?f/2*t:m/2*t).toFixed(0)&&(d=0);var r="left"==a||"right"==a?d:0,n="up"==a||"down"==a?d:0;i.css({transform:(o=r+"px",e=n+"px",(s?"translate3d("+o+","+e+",0px)":"translate("+o+","+e+")")+u.c_tr)})}var o,e},u.duration)}})}}(jQuery);
      @@ -348,7 +351,11 @@ jQuery.fn.ThzGetTransform=function(t){var a=this.is(":visible")?this.css("transf
        */
       jQuery.fn.ThzIsVisible=function(n){var t=this.get(0).getBoundingClientRect();return null!=n&&void 0!==n||(n=0),t.top-n<window.innerHeight&&0<t.bottom+n};
       
      -
      +/**
      + * @package		ThzSmoothScroll
      + * @copyright 	Balazs Galambosi.
      + * @license		MIT
      + */
       ThzSmoothScroll=function(ee){!function(){var u,l,c,o={frameRate:150,animationTime:600,stepSize:100,pulseAlgorithm:!0,pulseScale:4,pulseNormalize:1,accelerationDelta:50,accelerationMax:3,keyboardSupport:!0,arrowScroll:50,fixedBackground:!0,excluded:""},p=function(e){e=e||{};for(var t=1;t<arguments.length;t++)if(arguments[t])for(var o in arguments[t])arguments[t].hasOwnProperty(o)&&(e[o]=arguments[t][o]);return e}(o,ee),d=!1,s=!1,r={x:0,y:0},f=!1,m=document.documentElement,a=[],i=/^Mac/.test(navigator.platform),h={left:37,up:38,right:39,down:40,spacebar:32,pageup:33,pagedown:34,end:35,home:36},w={37:1,38:1,39:1,40:1};function v(){if(!f&&document.body){f=!0;var e=document.body,t=document.documentElement,o=window.innerHeight,n=e.scrollHeight;if(m=0<=document.compatMode.indexOf("CSS")?t:e,u=e,p.keyboardSupport&&X("keydown",x),top!=self)s=!0;else if(J&&o<n&&(e.offsetHeight<=o||t.offsetHeight<=o)){var r,a=document.createElement("div");a.style.cssText="position:absolute; z-index:-10000; top:0; left:0; right:0; height:"+m.scrollHeight+"px",document.body.appendChild(a),c=function(){r||(r=setTimeout(function(){d||(a.style.height="0",a.style.height=m.scrollHeight+"px",r=null)},500))},setTimeout(c,10),X("resize",c);if((l=new R(c)).observe(e,{attributes:!0,childList:!0,characterData:!1}),m.offsetHeight<=o){var i=document.createElement("div");i.style.clear="both",e.appendChild(i)}}p.fixedBackground||d||(e.style.backgroundAttachment="scroll",t.style.backgroundAttachment="scroll")}}var y=[],b=!1,g=Date.now();function S(s,f,m){var e,t;if(e=0<(e=f)?1:-1,t=0<(t=m)?1:-1,(r.x!==e||r.y!==t)&&(r.x=e,r.y=t,y=[],g=0),1!=p.accelerationMax){var o=Date.now()-g;if(o<p.accelerationDelta){var n=(1+50/o)/2;1<n&&(n=Math.min(n,p.accelerationMax),f*=n,m*=n)}g=Date.now()}if(y.push({x:f,y:m,lastX:f<0?.99:-.99,lastY:m<0?.99:-.99,start:Date.now()}),!b){var h=s===document.body,w=function(e){for(var t=Date.now(),o=0,n=0,r=0;r<y.length;r++){var a=y[r],i=t-a.start,l=i>=p.animationTime,c=l?1:i/p.animationTime;p.pulseAlgorithm&&(c=V(c));var u=a.x*c-a.lastX>>0,d=a.y*c-a.lastY>>0;o+=u,n+=d,a.lastX+=u,a.lastY+=d,l&&(y.splice(r,1),r--)}h?window.scrollBy(o,n):(o&&(s.scrollLeft+=o),n&&(s.scrollTop+=n)),f||m||(y=[]),y.length?P(w,s,1e3/p.frameRate+1):b=!1};P(w,s,0),b=!0}}function e(e){f||v();var t=e.target;if(e.defaultPrevented||e.ctrlKey)return!0;if(A(u,"embed")||A(t,"embed")&&/\.pdf/i.test(t.src)||A(u,"object")||t.shadowRoot)return!0;var o=-e.wheelDeltaX||e.deltaX||0,n=-e.wheelDeltaY||e.deltaY||0;i&&(e.wheelDeltaX&&B(e.wheelDeltaX,120)&&(o=e.wheelDeltaX/Math.abs(e.wheelDeltaX)*-120),e.wheelDeltaY&&B(e.wheelDeltaY,120)&&(n=e.wheelDeltaY/Math.abs(e.wheelDeltaY)*-120)),o||n||(n=-e.wheelDelta||0),1===e.deltaMode&&(o*=40,n*=40);var r=H(t);return r?!!function(e){if(!e)return;a.length||(a=[e,e,e]);return e=Math.abs(e),a.push(e),a.shift(),clearTimeout(D),D=setTimeout(function(){try{localStorage.SS_deltaBuffer=a.join(",")}catch(e){}},1e3),!N(120)&&!N(100)}(n)||(1.2<Math.abs(o)&&(o*=p.stepSize/120),1.2<Math.abs(n)&&(n*=p.stepSize/120),S(r,o,n),e.preventDefault(),void E()):!s||!W||(Object.defineProperty(e,"target",{value:window.frameElement}),parent.wheel(e))}function x(e){var t=e.target,o=e.ctrlKey||e.altKey||e.metaKey||e.shiftKey&&e.keyCode!==h.spacebar;document.body.contains(u)||(u=document.activeElement);var n=/^(button|submit|radio|checkbox|file|color|image)$/i;if(e.defaultPrevented||/^(textarea|select|embed|object)$/i.test(t.nodeName)||A(t,"input")&&!n.test(t.type)||A(u,"video")||function(e){var t=e.target,o=!1;if(-1!=document.URL.indexOf("www.youtube.com/watch"))do{if(o=t.classList&&t.classList.contains("html5-video-controls"))break}while(t=t.parentNode);return o}(e)||t.isContentEditable||o)return!0;if((A(t,"button")||A(t,"input")&&n.test(t.type))&&e.keyCode===h.spacebar)return!0;if(A(t,"input")&&"radio"==t.type&&w[e.keyCode])return!0;var r=0,a=0,i=H(u);if(!i)return!s||!W||parent.keydown(e);var l=i.clientHeight;switch(i==document.body&&(l=window.innerHeight),e.keyCode){case h.up:a=-p.arrowScroll;break;case h.down:a=p.arrowScroll;break;case h.spacebar:a=-(e.shiftKey?1:-1)*l*.9;break;case h.pageup:a=.9*-l;break;case h.pagedown:a=.9*l;break;case h.home:a=-i.scrollTop;break;case h.end:var c=i.scrollHeight-i.scrollTop-l;a=0<c?c+10:0;break;case h.left:r=-p.arrowScroll;break;case h.right:r=p.arrowScroll;break;default:return!0}S(i,r,a),e.preventDefault(),E()}function t(e){u=e.target}var n,k,D,M=(n=0,function(e){return e.uniqueID||(e.uniqueID=n++)}),T={};function E(){clearTimeout(k),k=setInterval(function(){T={}},1e3)}function C(e,t){for(var o=e.length;o--;)T[M(e[o])]=t;return t}function H(e){var t=[],o=document.body,n=m.scrollHeight;do{var r=T[M(e)];if(r)return C(t,r);if(t.push(e),n===e.scrollHeight){var a=O(m)&&O(o)||L(m);if(s&&z(m)||!s&&a)return C(t,j())}else if(z(e)&&L(e))return C(t,e)}while(e=e.parentElement)}function z(e){return e.clientHeight+10<e.scrollHeight}function O(e){return"hidden"!==getComputedStyle(e,"").getPropertyValue("overflow-y")}function L(e){var t=getComputedStyle(e,"").getPropertyValue("overflow-y");return"scroll"===t||"auto"===t}function X(e,t){window.addEventListener(e,t,!1)}function Y(e,t){window.removeEventListener(e,t,!1)}function A(e,t){return(e.nodeName||"").toLowerCase()===t.toLowerCase()}if(window.localStorage&&localStorage.SS_deltaBuffer)try{a=localStorage.SS_deltaBuffer.split(",")}catch(e){}function B(e,t){return Math.floor(e/t)==e/t}function N(e){return B(a[0],e)&&B(a[1],e)&&B(a[2],e)}var K,P=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(e,t,o){window.setTimeout(e,o||1e3/60)},R=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver,j=function(){if(!K){var e=document.createElement("div");e.style.cssText="height:10000px;width:1px;",document.body.appendChild(e);var t=document.body.scrollTop;document.documentElement.scrollTop,window.scrollBy(0,3),K=document.body.scrollTop!=t?document.body:document.documentElement,window.scrollBy(0,-3),document.body.removeChild(e)}return K};function q(e){var t,o;return(e*=p.pulseScale)<1?t=e-(1-Math.exp(-e)):(e-=1,t=(o=Math.exp(-1))+(1-Math.exp(-e))*(1-o)),t*p.pulseNormalize}function V(e){return 1<=e?1:e<=0?0:(1==p.pulseNormalize&&(p.pulseNormalize/=q(1)),q(e))}var F,I=window.navigator.userAgent,_=/Edge/.test(I),W=/chrome/i.test(I)&&!_,$=/safari/i.test(I)&&!_,U=/mobile/i.test(I),G=/Windows NT 6.1/i.test(I)&&/rv:11/i.test(I),J=$&&(/Version\/8/i.test(I)||/Version\/9/i.test(I)),Q=(W||$||G)&&!U;function Z(e){for(var t in e)o.hasOwnProperty(t)&&(p[t]=e[t])}"onwheel"in document.createElement("div")?F="wheel":"onmousewheel"in document.createElement("div")&&(F="mousewheel"),F&&Q&&(X(F,e),X("mousedown",t),X("load",v)),Z.destroy=function(){l&&l.disconnect(),Y(F,e),Y("mousedown",t),Y("keydown",x),Y("resize",c),Y("load",v)},window.SmoothScrollOptions&&Z(window.SmoothScrollOptions),"function"==typeof define&&define.amd?define(function(){return Z}):"object"==typeof exports?module.exports=Z:window.SmoothScroll=Z}()};
       
       /* 
      diff --git a/inc/fonts-utility.php b/inc/fonts-utility.php
      index 38204ca..5052f28 100644
      --- a/inc/fonts-utility.php
      +++ b/inc/fonts-utility.php
      @@ -10,646 +10,6 @@
       	exit; // No direct access
       }
       
      -/**
      - * Get Typekit user fonts
      - * @return array
      - */	
      -function thz_get_typekit_fonts($tyk_token = false,$tykit_ids = array()) {
      -		
      -	if($tyk_token && !empty($tykit_ids)){
      -		
      -		$tyk_fonts			= array();
      -		
      -		foreach($tykit_ids as $kit_id){
      -		
      -			$url = "https://typekit.com/api/v1/json/kits/" . $kit_id;
      -			$args = array(
      -				'sslverify' => false,
      -				'timeout' => 20000,
      -			);
      -			$response = wp_remote_request($url."?token=$tyk_token", $args);		
      -			
      -			
      -			if (!is_wp_error($response)) {
      -				
      -				$response = wp_remote_retrieve_body($response);
      -				$response = json_decode($response,true);	
      -							
      -				if(isset($response['kit'])){
      -					
      -					// set typekit data
      -					$tyk_fonts['kits_data'][$kit_id] = array(
      -						'name' => $response['kit']['name'],
      -					);
      -					
      -					foreach( $response['kit']['families'] as $fam => $family ){
      -						
      -						foreach( $family['variations'] as $v => $variation ){
      -							
      -							$response['kit']['families'][$fam]['variations'][$v] = thz_set_typekit_variation($variation);
      -							
      -						}
      -						
      -						// set fonts data
      -						$slug = thz_typekit_slug($family['css_stack']);
      -						$tyk_fonts['fonts_data'][$slug] = array(
      -							
      -							'name' => $family['name'],
      -							'kitid' => $kit_id,
      -							'variations' => $response['kit']['families'][$fam]['variations'],
      -							'slug' => $family['slug'],
      -							'css_stack' => $family['css_stack'],
      -						
      -						);
      -
      -					}
      -					
      -					// build select for typography option
      -					$tyk_fonts['select'] = thz_buld_typekit_select_list( $response['kit']['families'],$kit_id );
      -					//$tyk_fonts[$kit_id] = $response;
      -				}
      -				
      -			}
      -			
      -			unset($kit_id,$response);
      -		}
      -		
      -		unset($tykit_ids);
      -		
      -		
      -		if(!empty($tyk_fonts)){
      -			
      -			return $tyk_fonts;
      -			
      -		}else{
      -			
      -			return false;
      -			
      -		}
      -		
      -	}
      -	
      -	return false;
      -		
      -}
      -
      -/**
      - * Create custom Typekit font slug to be used by options
      - * @return string
      - */
      -function thz_typekit_slug($css_stack){
      -	
      -	$slug 		= explode(',',$css_stack);
      -	$slug 		= str_replace(array('"',"'"),'',$slug[0]);
      -	
      -	return $slug;	
      -}
      -
      -/**
      - * Replace Typekit font weights to match the typography option
      - * @return string
      - */
      -function thz_set_typekit_variation($variation) {
      -	
      -	$variation = str_replace('n','',$variation);
      -	$variation = str_replace($variation,$variation.'00',$variation);		
      -	
      -	if(thz_contains($variation,'i')){
      -		$variation = str_replace('i','',$variation);
      -		$variation = str_replace($variation,$variation.'italic',$variation);
      -	}
      -	
      -	return $variation;
      -}
      -
      -
      -/**
      - * Build Typekit user fonts list for import fonts option
      - * @return string
      - */	
      -function thz_build_typekit_list($data) {
      -		
      -	if(!$data){
      -		
      -		return;
      -	}
      -	
      -	$kits_data = $data['kits_data'];
      -	$fonts_data = $data['fonts_data'];
      -	
      -	$html ='';
      -	foreach($kits_data as $k => $kitid){
      -
      -		$html .= '<div class="thz-typekit-wrapper">';
      -		$html .= '<span class="thz-typekit-name">'.esc_html('Project name','creatus').': '.$kitid['name'].'</span>';
      -		$html .= '<span class="thz-typekit-families">'.esc_html('Font families','creatus').':</span>';
      -		$html .= '<ul>';
      -		foreach($fonts_data as $fontfamily){
      -			
      -			$html .= '<li>';
      -			$html .= '<a href="https://typekit.com/fonts/'.$fontfamily['slug'].'" target="_blank">';
      -			$html .= $fontfamily['name'];
      -			$html .= '</a>';
      -			$html .= '</li>';
      -		}
      -		
      -		$html .= '</ul>';
      -		$html .= '</div>';
      -		
      -		unset($kitid);
      -	}
      -	unset($data,$kits_data,$fonts_data);
      -	
      -	return $html;
      -}
      -
      -
      -/**
      - * Build Typekit select list for typography option
      - * @return string
      - */
      -function thz_buld_typekit_select_list($families, $kit_id ) {
      -
      -	$select = '';
      -	$fonts = array();
      -	
      -	foreach( $families as $family ){
      -		
      -		$fonts[$family['slug']] = $family;
      -		
      -		unset($family);
      -	}
      -	
      -	unset($families);
      -	
      -	foreach( $fonts as $font ){
      -		
      -		$font_variants 	= implode(',',$font['variations']);
      -		$css_stack = str_replace('"', "'",$font['css_stack']);
      -		$select .='<option value="'.(string) $css_stack.'" data-type="typekit" data-kitid="'.$kit_id.'" data-variants="'.$font_variants.'" data-subsets="'.$font['subset'].'">';
      -		$select .= $font['name'];
      -		$select .='</option>';		
      -		
      -	}
      -	
      -	
      -	return $select;
      -}
      -
      -
      -
      -/**
      - * Get Fontsquirrel fonts
      - * @return json
      - */	
      -function thz_get_fsq_fonts() {
      -		
      -	$saved_data = get_option( 'thz_fontsquirrel_fonts', false );
      -	
      -	$ttl        = 7 * DAY_IN_SECONDS;
      -	
      -	if (
      -		false === $saved_data
      -		||
      -		( $saved_data['last_update'] + $ttl < time() )
      -	) {
      -		$response = wp_remote_get( apply_filters( 'thz_fontsquirrel_webfonts_url',
      -			'https://www.fontsquirrel.com/api/fontlist/all' ) );
      -		$body     = wp_remote_retrieve_body( $response );
      -		if (
      -			200 === wp_remote_retrieve_response_code( $response )
      -			&&
      -			! is_wp_error( $body ) && ! empty( $body )
      -		) {
      -			update_option( 'thz_fontsquirrel_fonts',
      -				array(
      -					'last_update' => time(),
      -					'fonts'       => $body
      -				),
      -				false );
      -			return $body;
      -		} else {
      -			if ( empty( $saved_data['fonts'] ) ) {
      -				$saved_data['fonts'] = json_encode( array() );
      -			}
      -			update_option( 'thz_fontsquirrel_fonts',
      -				array(
      -					'last_update' => time() - $ttl + MINUTE_IN_SECONDS,
      -					'fonts'       => $saved_data['fonts']
      -				),
      -				false );
      -		}
      -	}
      -	return $saved_data['fonts'];
      -		
      -}
      -
      -/**
      - * Get Fontsquirrel classifications
      - * @return json
      - */	
      -function thz_get_fsq_classifications() {
      -		
      -	$saved_data = get_option( 'thz_fontsquirrel_classifications', false );
      -	
      -	$ttl        = 7 * DAY_IN_SECONDS;
      -	
      -	if (
      -		false === $saved_data
      -		||
      -		( $saved_data['last_update'] + $ttl < time() )
      -	) {
      -		$response = wp_remote_get( apply_filters( 'thz_fontsquirrel_classifications_url',
      -			'https://www.fontsquirrel.com/api/classifications' ) );
      -		$body     = wp_remote_retrieve_body( $response );
      -		if (
      -			200 === wp_remote_retrieve_response_code( $response )
      -			&&
      -			! is_wp_error( $body ) && ! empty( $body )
      -		) {
      -			update_option( 'thz_fontsquirrel_classifications',
      -				array(
      -					'last_update' => time(),
      -					'classifications'  => $body
      -				),
      -				false );
      -			return $body;
      -		} else {
      -			if ( empty( $saved_data['classifications'] ) ) {
      -				$saved_data['classifications'] = json_encode( array() );
      -			}
      -			update_option( 'thz_fontsquirrel_classifications',
      -				array(
      -					'last_update' => time() - $ttl + MINUTE_IN_SECONDS,
      -					'classifications'       => $saved_data['classifications']
      -				),
      -				false );
      -		}
      -	}
      -	
      -	return $saved_data['classifications'];
      -		
      -}
      -
      -/**
      - * Build Fontsquirrel fonts list
      - * @return string
      - */	
      -function thz_build_fsq_list() {
      -		
      -	
      -	$fonts = json_decode( thz_get_fsq_fonts() , true );
      -	
      -	if(!is_array($fonts) || empty($fonts)){
      -		
      -		return;
      -	}
      -	
      -	
      -	$imported = get_option('thz_imported_fonts');
      -
      -	$classifications = json_decode( thz_get_fsq_classifications() , true ); 
      -
      -	$html = '<div class="thz-fontsquirrel-wrapper">';
      -	$html .= '<div class="downloaded-fonts"></div>';
      -	$html .= '<div class="fsearch-container">';
      -	$html .= '<input name="search" class="fsearch" placeholder="'.esc_html('Quick search','creatus').'" type="text" data-list=".fonts">';
      -	$html .= '<a href="#" class="dashicons dashicons-dismiss clear-fsearch"></a>';
      -	$html .= '</div>';
      -	
      -	$html .= '<ul class="categories">';
      -	
      -	foreach($classifications as $cat){
      -		
      -		$name =  urldecode($cat['name']);
      -		$class = '.cat_'.strtolower(str_replace(' ','_',$name));
      -		$html .= '<li class="'.$name.'">';
      -		$html .= '<a class="category-link" href="#" data-filter="'.$class.'">';
      -		$html .= $name. ' ('.$cat['count'].')';
      -		$html .= '</a>';
      -		$html .= '</li>';
      -		
      -		unset($cat);
      -	}
      -	unset($classifications);
      -	
      -	$html .= '</ul>';
      -	
      -	$html .= '<ul class="fonts">';
      -	foreach($fonts as $font){
      -		
      -		$cat 		=  urldecode($font['classification']);
      -		$class 		= 'cat_'.strtolower(str_replace(' ','_',$cat)).' '.$font['family_urlname'];
      -		$hide_del 	= ' hide-icon';
      -		$hide_down 	= '';
      -		
      -		if($cat != 'Blackletter'){
      -			$class .=' inactive';
      -		}
      -		
      -	
      -		if(isset($imported['fsqfonts'][$font['family_urlname']])){
      -
      -			$hide_del 	= '';
      -			$hide_down 	= ' hide-icon';	
      -			$class		.= ' is-down';	
      -		}
      -		
      -		$html .= '<li class="'.$class.'" data-name="'.$font['family_name'].'">';
      -		$html .= '<span class="font-title">'.$font['family_name'].'</span>';
      -		$html .= '<a class="delete-font'.$hide_del.'" href="#" data-font="'.$font['family_urlname'].'">';
      -		$html .= '<span class="mati mati-cancel"></span>';
      -		$html .= '</a>';
      -		$html .= '<a class="download-font'.$hide_down.'" href="#" data-font="'.$font['family_urlname'].'">';
      -		$html .= '<span class="thzicon thzicon-cloud-download3"></span>';
      -		$html .= '</a>';
      -		$html .= '<a class="preview-font" href="https://www.fontsquirrel.com/fonts/'.$font['family_urlname'].'" target="_blank">';
      -		$html .= '<span class="thzicon thzicon-eye2"></span>';
      -		$html .= '</a>';
      -		$html .= '</li>';
      -
      -		unset($font);
      -	}
      -	$html .= '</ul>';
      -	
      -	
      -	$html .= '</div>';
      -	
      -	unset($fonts);
      -	
      -	return $html;
      -}
      -
      -
      -/**
      - * Get Fontsquirrel family info
      - * @return array
      - */	
      -function thz_get_fsq_familyinfo($family_urlname) {
      -		
      -	if($family_urlname){
      -		
      -		$fsq_font	= array();
      -		
      -		$url = "https://www.fontsquirrel.com/api/familyinfo/" . $family_urlname;
      -		$args = array(
      -			'sslverify' => false,
      -			'timeout' => 20000,
      -		);
      -		
      -		$response = wp_remote_request($url, $args);		
      -		
      -		if (!is_wp_error($response)) {
      -
      -			$response = wp_remote_retrieve_body($response);
      -			$response = json_decode($response,true);	
      -						
      -			if(!empty($response)){
      -				$fsq_font[$family_urlname] = $response;
      -			}
      -			
      -		}
      -		
      -		if(!empty($fsq_font)){
      -			
      -			return $fsq_font;
      -			
      -		}else{
      -			
      -			return false;
      -			
      -		}
      -		
      -	}
      -	
      -	return false;
      -		
      -}
      -
      -
      -/**
      - * Build Fontsquirrel font data
      - * @return array
      - */	
      -function thz_build_fsq_font_data($family_urlname) {
      -	
      -	$imported = get_option('thz_imported_fonts');
      -	
      -	if(isset($imported['fsqfonts'][$family_urlname])){
      -		
      -		return $imported['fsqfonts'][$family_urlname];
      -		
      -	}else{
      -	
      -		$data = thz_get_fsq_familyinfo($family_urlname);
      -		
      -		if(!$data){
      -			
      -			return;
      -		}
      -		
      -		$font_info 	=  array();
      -		$dirs 		= wp_upload_dir();
      -		$baseurl 	= $dirs['baseurl'];	
      -		$f_url 		= $baseurl.'/'.THEME_NAME.'/f/'.$family_urlname.'/';
      -		
      -		foreach($data[$family_urlname] as $variant){
      -			
      -			$info 		= pathinfo($variant['filename']);
      -			$ff 		= $variant['fontface_name'];
      -			$name 		= $variant['family_name'].' '.$variant['style_name'];
      -			$font_file 	= $f_url.$info['filename'].'-webfont.woff';
      -	
      -			$font_info[$family_urlname][$ff]['name'] = $name;
      -			$font_info[$family_urlname][$ff]['font_family'] = $ff;
      -			$font_info[$family_urlname][$ff]['font_file'] = $font_file;
      -			$font_info[$family_urlname][$ff]['css'] = thz_build_fsq_font_face_css( $ff, $font_file );
      -			
      -			unset($variant);
      -		}
      -		
      -		unset($data);
      -		
      -		$imported['fsqfonts'][$family_urlname] = $font_info[$family_urlname];
      -		
      -		update_option( 'thz_imported_fonts', $imported );
      -		
      -		return $font_info;
      -	
      -	}
      -}
      -
      -/**
      - * Build Fontsquirrel @font-face CSS
      - * @return string
      - */	
      -function thz_build_fsq_font_face_css( $font_family,$font_file ) {
      -	
      -	$css = '@font-face {';
      -	$css .= 'font-family: \''.$font_family.'\';';
      -	$css .= 'src: url(\''.$font_file.'\') format(\'woff\');';
      -	$css .= 'font-weight: normal;';
      -	$css .= 'font-style: normal;';
      -	$css .= '}';
      -		
      -	return $css;
      -}
      -
      -/**
      - * Get Fontsquirrel fontface kit
      - * @return array
      - */	
      -function thz_get_fsq_fontfacekit( $family_urlname ) {
      -	
      -	$thz_fs 	= thz_wp_file_system();
      -	$dirs 		= wp_upload_dir();
      -	$basedir 	= $dirs['basedir'];	
      -	$path 		= $basedir.THZDS.THEME_NAME.THZDS;
      -	$f_path		= $path.'f'.THZDS;
      -			
      -	if($thz_fs->is_dir( $f_path . $family_urlname)){
      -		
      -		return thz_build_fsq_font_data($family_urlname);
      -		
      -	}
      -	
      -	if($family_urlname){
      -		
      -		$url = 'https://www.fontsquirrel.com/fontfacekit/'. $family_urlname;
      -		
      -		$args = array(
      -			'sslverify' => false,
      -			'timeout' => 20000,
      -		);
      -
      -		$response = wp_remote_request($url,$args);
      -		
      -		// we got the response let's dance :)
      -		if (!is_wp_error($response)) {
      -			
      -			$zip_file 	= wp_remote_retrieve_body($response);
      -			$zip_name	= $family_urlname.'-fontfacekit.zip';
      -			$zip_path	= $f_path.$zip_name;
      -
      -			if (!is_dir( $f_path ) ){
      -				
      -				if (wp_mkdir_p($f_path)) {
      -					
      -					$thz_fs->put_contents($f_path.THZDS.'index.html','');
      -				
      -				}else{
      -					
      -					return;
      -					
      -				}
      -			}
      -			
      -			// zip the response and save it in uploads/creatus/f/font_name folder
      -			if ( $thz_fs->put_contents($zip_path, $zip_file, FS_CHMOD_FILE) && is_dir( $f_path ) ){
      -				
      -				// now unzip the file
      -				if( unzip_file($zip_path, $f_path.$family_urlname)){
      -					
      -					//is unziped, remove downloaded zip
      -					$thz_fs->delete($zip_path);
      -					
      -					// add index.html in font folder
      -					$thz_fs->put_contents($f_path.$family_urlname.THZDS.'index.html','');
      -					
      -					$dirs = $thz_fs->dirlist($f_path.$family_urlname.THZDS.'web fonts');
      -					
      -					// loop trough web fonts folder to get variants
      -					foreach($dirs as $name => $dir){
      -						
      -						$files_list = $thz_fs->dirlist($f_path.$family_urlname.THZDS.'web fonts'.THZDS.$name.THZDS);
      -						
      -						// loop trough variant folder to get files
      -						foreach ( $files_list as $f_name => $file ){
      -							
      -							$info = pathinfo($f_name);
      -							
      -							// only get woff files
      -							if (isset($info['extension']) && $info['extension'] == 'woff'){
      -								
      -								$file_path 	= $f_path.$family_urlname.THZDS.'web fonts'.THZDS.$name.THZDS.$f_name;
      -								$new_path	= $f_path.$family_urlname.THZDS.$f_name;
      -								
      -								// move the file from variant folder to main folder
      -								$thz_fs->move( $file_path, $new_path);
      -
      -							}
      -							unset($file);
      -						}
      -						unset($files_list,$dir);
      -					}
      -					unset($dirs);
      -					
      -					// delete web font folder and all sub folders
      -					if( $thz_fs->delete($f_path.$family_urlname.THZDS.'web fonts'.THZDS, true)){
      -						
      -						// delete how to use font html
      -						$thz_fs->delete($f_path.$family_urlname.THZDS.'How_to_use_webfonts.html');
      -						
      -						return thz_build_fsq_font_data($family_urlname);
      -					}
      -					
      -				}
      -			}
      -
      -		}
      -
      -	}
      -	
      -	return false;	
      -	
      -}
      -
      -/**
      - * Delete Fontsquirrel fontface kit
      - * @return array
      - */	
      -function thz_delete_fsq_fontfacekit( $family_urlname ) {
      -	
      -	$thz_fs 	= thz_wp_file_system();
      -	$dirs 		= wp_upload_dir();
      -	$basedir 	= $dirs['basedir'];	
      -	$path 		= $basedir.THZDS.THEME_NAME.THZDS;
      -	$f_path		= $path.'f'.THZDS;
      -	
      -	if( $thz_fs->delete($f_path.$family_urlname,true) ){
      -		
      -		$imported 	= get_option('thz_imported_fonts');
      -		
      -		if(isset($imported['fsqfonts'][$family_urlname])){
      -			unset( $imported['fsqfonts'][$family_urlname] );
      -			update_option('thz_imported_fonts', $imported);
      -		}	
      -		
      -		return true;	
      -	}
      -	
      -	return false;
      -}
      -
      -
      -
      -/**
      - * Get Fontsquirrel fontface CSS
      - * @return string
      - */	
      -function thz_get_fsq_css( $family, $variant ) {
      -	
      -	$imported 	= get_option('thz_imported_fonts');
      -	
      -	$css = thz_akg('fsqfonts/'.$family.'/'.$variant.'/css',$imported, false);
      -	
      -	if($css){
      -		return $css;
      -	}
      -	
      -	return false;
      -}
      -
       /**
        * Get Fontface kits list
        * @return array
      diff --git a/inc/helpers.php b/inc/helpers.php
      index a1db344..523e278 100644
      --- a/inc/helpers.php
      +++ b/inc/helpers.php
      @@ -50,6 +50,17 @@ function thz_core(){
       	return defined('THZHELPERS');
       	
       }
      +
      +/**
      + * Check if Creatus Extended is active
      + * @internal
      + */
      +function thz_creatus_extended(){
      +	
      +	return defined('CREATUSEXTENDED');
      +	
      +}
      +
       /**
        * Check if page is using page builder
        * @internal
      @@ -3170,7 +3181,17 @@ function thz_pageblocks_positions_list($id = ''){
        * Load hero section template
        */
       function thz_hero_section( $location ) {
      -	
      +
      +	if( !thz_fw_active() && 'under' == $location ){
      +		if ( 
      +		( 'page' == get_option( 'show_on_front' ) && is_front_page() && !is_home() ) || 
      +		( 'posts' == get_option( 'show_on_front' ) && is_home() && is_front_page() )
      +		){
      +			get_template_part( 'template-parts/customizer-hero', 'section' );
      +			return;
      +		}
      +	}
      +		
       	$hero = thz_get_hero_options();
       
       	if ( empty( $hero ) ) {
      @@ -3689,6 +3710,15 @@ function thz_page_info_check( $assigned_pages = array() ) {
        * @return bool
        */
       function thz_global_page_title() {
      +	
      +	if( !thz_fw_active() ){
      +		if ( 
      +		( 'page' == get_option( 'show_on_front' ) && is_front_page() && !is_home() ) || 
      +		( 'posts' == get_option( 'show_on_front' ) && is_home() && is_front_page() )
      +		){
      +			return false;
      +		}
      +	}
       
       	$show_on           = thz_get_theme_option( 'pt_show_on', null );
       	$show_title        = thz_page_info_check( $show_on );
      @@ -5275,6 +5305,17 @@ function thz_print_branding( $echo = true ) {
       			)
       		);
       
      +		if( !thz_fw_active() ){
      +			
      +			$branding_link 	= get_option('creatus_branding_link',false);
      +			$branding_text 	= get_option('creatus_branding_text',false);			
      +			
      +			if( $branding_link || $branding_text ){
      +				
      +				$branding = thz_current_year( '<span class="thz-copyright">Copyright &copy; {year} <a href="'.$branding_link.'" target="_blank">'.$branding_text.'</a>.</span>');
      +			}
      +		}
      +		
       		$html = '<div class="thz-bradning-holder">' . wp_kses( $branding, $allowed_html ) . '</div>';
       
       		if ( $echo ) {
      diff --git a/inc/hooks.php b/inc/hooks.php
      index 37d130f..49d1c28 100644
      --- a/inc/hooks.php
      +++ b/inc/hooks.php
      @@ -330,12 +330,11 @@ function _thz_get_tgmpa_plugins_list(){
       			'required'  => false,
       			'version'   => '1.0.0', 
       		),
      -		'thz-core'=> array(
      -			'name'               => 'Thz Core', // The plugin name.
      -			'slug'               => 'thz-core', // The plugin slug (typically the folder name).
      -			'source'             => esc_url('https://updates.themezly.io/plugins/thz-core.zip'), // The plugin source.
      +		'creatus-extended'=> array(
      +			'name'               => 'Creatus Extended', // The plugin name.
      +			'slug'               => 'creatus-extended', // The plugin slug (typically the folder name).
       			'required'           => false, // If false, the plugin is only 'recommended' instead of required.
      -			'version'            => '1.5.1', // E.g. 1.0.0. If set, the active plugin must be this version or higher.
      +			'version'            => '1.0.0', // E.g. 1.0.0. If set, the active plugin must be this version or higher.
       		),
       		'assign-widgets'=> array(
       			'name'               => 'Assign Widgets', // The plugin name.
      @@ -412,119 +411,6 @@ function _thz_get_demos_plugins_list () {
       	);
       }
       
      -/**
      - * List of full demos
      - */
      -function _thz_get_demos_list(){
      -	
      -	$ThzDemos = ThzDemos::getInstance();
      -	return $ThzDemos->demos_list();
      -
      -}
      -
      -/**
      - * @param FW_Ext_Backups_Demo[] $demos
      - * @return FW_Ext_Backups_Demo[] 
      - * http://manual.unyson.io/en/latest/extension/backups/#create-demos
      - */
      -function _thz_filter_theme_fw_ext_backups_demos($demos) {
      -	
      -	$demos_list  = _thz_get_demos_list();
      -	
      -	if(!$demos_list){
      -		
      -		return $demos;
      -	}
      -	
      -	$download_url = apply_filters( '_thz_filter_demos_download_url', 'https://updates.themezly.io/demos/' );
      -
      -    foreach ($demos_list as $id => $data) {
      -        $demo = new FW_Ext_Backups_Demo($id, 'piecemeal', array(
      -            'url' => $download_url,
      -            'file_id' => $id,
      -        ));
      -        $demo->set_title($data['title']);
      -        $demo->set_screenshot($data['screenshot']);
      -        $demo->set_preview_link($data['preview_link']);
      -		
      -		if( isset($data['extra'])){
      -			$demo->set_extra($data['extra']);
      -		}
      -		
      -        $demos[ $demo->get_id() ] = $demo;
      -
      -        unset($demo);
      -    }
      -
      -    return $demos;
      -}
      -
      -add_filter('fw:ext:backups-demo:demos', '_thz_filter_theme_fw_ext_backups_demos');
      -
      -
      -/**
      - * Disable demo image sizes restore
      - * https://github.com/ThemeFuse/Unyson-Backups-Extension/issues/15
      - * https://github.com/ThemeFuse/Unyson-Backups-Extension/issues/30
      - */
      -if ( ! function_exists( '_thz_filter_disable_demo_img_sizes_restore' ) ) {
      -	function _thz_filter_disable_demo_img_sizes_restore( $do, FW_Ext_Backups_Task_Collection $collection ) {
      -		
      -		$demos_list = _thz_get_demos_list();
      -		
      -		if (
      -			$collection->get_id() === 'demo-content-install'
      -			&&
      -			($task = $collection->get_task('demo:demo-download'))
      -			&&
      -			($task_args = $task->get_args())
      -			&&
      -			isset($task_args['demo_id'])
      -			&&
      -			isset($demos_list[$task_args['demo_id']]['sizes_removal'])
      -			&&
      -			$demos_list[$task_args['demo_id']]['sizes_removal'] === false
      -		) {
      -			$do = false;
      -		}
      -	
      -		return $do;
      -	}
      -}
      -add_filter('fw:ext:backups:add-restore-task:image-sizes-restore', '_thz_filter_disable_demo_img_sizes_restore', 10, 2);
      -
      -
      -/**
      - * Disable Unyson update 
      - * if new update is bigger than max version
      -*/
      -
      -function _thz_filter_disable_unyson_update( $updates ) {
      -
      -   $requirements = defined('FW') ? fw()->theme->manifest->get('requirements') : false;
      -   
      -   if($requirements && isset($updates->response) && isset($requirements['framework']['max_version'])){
      -	   
      -	   $response = $updates->response;
      -	   
      -	   if(isset($response['unyson/unyson.php']) ){
      -	   	 
      -		 $new_version = $response['unyson/unyson.php']->new_version;
      -		 $max_version = $requirements['framework']['max_version'];
      -		 
      -		 if (version_compare($new_version, $max_version, ">")) {
      -			 
      -			unset( $updates->response['unyson/unyson.php'] );
      -		 }
      -		
      -	   }
      -   }
      -   
      -   return $updates;
      -}
      -
      -add_filter( 'site_transient_update_plugins', '_thz_filter_disable_unyson_update' );
      -
       
       /**
        * Get passed var
      @@ -2086,20 +1972,6 @@ function _thz_filter_get_archives_link( $output ) {
       add_filter( 'get_archives_link', '_thz_filter_get_archives_link', 10, 6 ); 
       
       
      -
      -/*
      - * Load page builder templates
      -*/
      -function _thz_action_load_builder_templates() {
      -	
      -	require_once get_template_directory().'/inc/includes/builder-templates/init.php';
      -	
      -}
      -
      -add_action('fw_init', '_thz_action_load_builder_templates');
      -
      -
      -
       /*
        * Load fonts import page
       */
      diff --git a/inc/includes/auto-setup/class-thz-auto-install.php b/inc/includes/auto-setup/class-thz-auto-install.php
      index 0b2feac..4ff3a52 100644
      --- a/inc/includes/auto-setup/class-thz-auto-install.php
      +++ b/inc/includes/auto-setup/class-thz-auto-install.php
      @@ -2,8 +2,6 @@
       	die( 'Direct access forbidden.' );
       }
       
      -require('class-thz-plugins-install.php');
      -
       class Thz_Simple_Auto_Install {
       	private $page_slug = 'creatus_auto_setup';
       	private $file_uri;
      @@ -653,11 +651,9 @@ public function send_response( $response, $error = false ) {
       }
       
       class Thz_Super_Admin_Auto_Install extends Thz_Admin_Auto_Install {
      -	private $child_theme_source;
       
       	public function __construct() {
       		parent::__construct();
      -		$this->child_theme_source = $this->config['child_theme_source'];
       
       		add_action( 'wp_ajax_' . $this->_prefix . '_install_demo_plugins', array(
       			$this,
      @@ -755,11 +751,7 @@ public function get_steps() {
       					'nonce'       => wp_create_nonce( 'install-supported-extensions' ),
       					'message'     => esc_html__( 'Installing supported extensions', 'creatus' ),
       				),
      -				'install-child-theme'          => array(
      -					'ajax_action' => $this->_prefix . '_install_child_theme',
      -					'nonce'       => wp_create_nonce( 'install-child-theme' ),
      -					'message'     => esc_html__( 'Downloading and installing child theme', 'creatus' ),
      -				),
      +
       			)
       		);
       	}
      @@ -782,10 +774,6 @@ public function add_ajax_requests() {
       			'install_supported_extensions'
       		) );
       
      -		add_action( 'wp_ajax_' . $this->_prefix . '_install_child_theme', array(
      -			$this,
      -			'install_child_theme'
      -		) );
       	}
       
       	public function install_supported_extensions() {
      @@ -916,53 +904,6 @@ public function install_required_plugins() {
       		wp_send_json_success();
       	}
       
      -	public function install_child_theme() {
      -		ob_end_clean();
      -		if ( ! current_user_can( 'install_themes' ) || empty( $this->child_theme_source ) ) {
      -			wp_send_json_error( array( 'message' => esc_html__( 'Current user can\'t install themes or child theme source must be specified','creatus') ) );
      -		}
      -
      -		check_ajax_referer( 'install-child-theme' );
      -		$credentials = get_site_transient( $this->credentials_key );
      -
      -		if ( ! $this->initialize_filesystem( $credentials, wp_normalize_path( get_theme_root() ) ) ) {
      -			wp_send_json_error( array(
      -				'message' => sprintf( esc_html__( 'Failed to install Theme. Folder %s is not writable', 'creatus' ), wp_normalize_path( get_theme_root() ) ),
      -			) );
      -		}
      -
      -		/**
      -		 * @var WP_Filesystem_Base $wp_filesystem
      -		 */
      -		global $wp_filesystem;
      -
      -		$response = array( 'success' => true );
      -
      -		$theme_path = pathinfo( get_template_directory() );
      -		$child_path = $theme_path['dirname'];
      -
      -		$child_name     = $child_path . '/' . $this->get_theme_id() . '-child';
      -		$child_rel_path = str_replace( get_theme_root() . '/', '', $child_name );
      -
      -		if ( ! $wp_filesystem->is_dir( $child_name ) ) {
      -			$response = Thz_Installer_Helper::download_and_install_a_package(
      -				$this->child_theme_source,
      -				$child_name,
      -				array(
      -					'type'   => 'theme',
      -					'action' => 'install',
      -				),
      -				$this->get_theme_id() . '-child'
      -			);
      -		}
      -
      -		switch_theme( $child_rel_path );
      -
      -		$this->insert_step_status( 'install-child-theme', $response['success'] );
      -		wp_send_json_success();
      -	}
      -
      -
       	public function get_setup_messages() {
       		return array(
       			'plugins_and_demo'  => sprintf( esc_html__( 'This option will install and activate all theme plugins and dependencies and %1$s redirect you to theme demo content installer%2$s.', 'creatus' ), '<b>', '</b>' ),
      @@ -1301,9 +1242,7 @@ public function feedback( $string ) {
       
       class Thz_Auto_Install {
       	public function __construct() {
      -		if( check_auto_setup_plugins_status() ) {
      -			new Thz_Admin_Plugins_Install();
      -		} elseif  ( current_user_can( 'install_plugins' ) ) {
      +		if  ( current_user_can( 'install_plugins' ) ) {
       			new Thz_Super_Admin_Auto_Install();
       		} elseif ( current_user_can( 'activate_plugins' ) && current_user_can( 'switch_themes' ) ) {
       			new Thz_Admin_Auto_Install();
      diff --git a/inc/includes/auto-setup/class-thz-plugins-install.php b/inc/includes/auto-setup/class-thz-plugins-install.php
      deleted file mode 100644
      index cd1a87b..0000000
      --- a/inc/includes/auto-setup/class-thz-plugins-install.php
      +++ /dev/null
      @@ -1,653 +0,0 @@
      -<?php if ( ! defined( 'ABSPATH' ) ) {
      -	die( 'Direct access forbidden.' );
      -}
      -
      -class Thz_Admin_Plugins_Install {
      -	
      -	private $page_slug = 'creatus_auto_setup';
      -	private $file_uri;
      -	private $file_path;
      -	private $config_path;
      -	private $view_path;
      -	private $css_uri;
      -	protected $config;
      -	private $plugins;
      -	private $theme_id;
      -	private $option_key;
      -	protected $_prefix = 'thz';
      -
      -	const ERR = 0;
      -	const ERR_REQUIRED = 1;
      -
      -	public function __construct() {
      -		$this->file_uri    = get_template_directory_uri() . '/inc/includes/auto-setup';
      -		$this->file_path   = get_template_directory() . '/inc/includes/auto-setup';
      -		$this->config_path = $this->file_path . '/config';
      -		$this->view_path   = $this->file_path . '/views';
      -		$this->css_uri     = $this->file_uri . '/css';
      -		$this->js_uri      = $this->file_uri . '/js';
      -
      -		$this->config           = require $this->config_path . '/config.php';
      -		$this->demos            = ! empty( $this->config['demos'] ) ? $this->config['demos'] : '';
      -		$this->has_demo_content = ! empty( $this->config['has_demo_content'] );
      -		$this->theme_id         = $this->config['theme_id'];
      -		$this->option_key       = $this->_prefix . '_' . $this->theme_id . '_auto_install_state';
      -		$this->credentials_key  = $this->_prefix . '_' . $this->theme_id . '_auto_install_credentials';
      -
      -		if ( ! function_exists( 'get_plugins' ) ) {
      -			require_once ABSPATH . 'wp-admin/includes/plugin.php';
      -		}
      -
      -		// all installed plugins
      -		$all_plugins       = get_plugins();
      -		$all_plugins_names = array();
      -		foreach ( $all_plugins as $item ) {
      -			$all_plugins_names[ $item['Name'] ] = $item['Name'];
      -		}
      -
      -		$plugin_demos = array();
      -		// parse all required plugins
      -		if ( isset( $this->config['plugins'] ) && ! empty( $this->config['plugins'] ) ) {
      -			foreach ( $this->config['plugins'] as $item ) {
      -				// if is an external plugin
      -				if ( isset( $item['source'] ) && thz_contains( $item['source'],'themezly.io' )) {
      -				//if ( isset( $item['source'] ) && in_array( $item['name'], $all_plugins_names ) ) {
      -					$plugin_demos[ $item['slug'] ] = $item;
      -				}
      -			}
      -		}
      -
      -		// parse all demos plugins
      -		if ( isset( $this->config['demos'] ) && ! empty( $this->config['demos'] ) ) {
      -			foreach ( $this->config['demos'] as $demos_plugin ) {
      -				// parse all plugins for specific demo
      -				foreach ( $demos_plugin as $item ) {
      -					// if is an external plugin
      -					
      -					if ( isset( $item['source'] ) && thz_contains( $item['source'],'themezly.io' )) {
      -					//if ( isset( $item['source'] ) && in_array( $item['name'], $all_plugins_names ) ) {
      -						$plugin_demos[ $item['slug'] ] = $item;
      -					}
      -
      -				}
      -			}
      -		}
      -		
      -		
      -		$this->plugins = $plugin_demos; // plugins for update
      -
      -		$this->redirect_after_activation();
      -
      -		add_action( 'init', array( $this, 'ob_start_action' ), - 1 );
      -
      -		$this->add_actions();
      -		$this->add_ajax_requests();
      -
      -		add_action( 'wp_ajax_' . $this->_prefix . '_install_demo_plugins', array(
      -			$this,
      -			'install_demo_plugins'
      -		) );
      -
      -		// for demo page, install plugins for demos
      -		add_action( 'load-tools_page_fw-backups-demo-content', array( $this, 'load_page_tools_callback' ) );
      -
      -		add_action( 'wp_ajax_' . $this->_prefix . '_activate_demo_plugins', array(
      -			$this,
      -			'activate_demo_plugins'
      -		) );
      -	}
      -
      -	/* demo content install */
      -	public function load_page_tools_callback() {
      -		if ( ! empty( $this->demos ) ) {
      -			wp_enqueue_script(
      -				$this->_prefix . '-demo-content-install',
      -				$this->get_demo_js_uri(),
      -				array( 'jquery', 'underscore', 'fw' )
      -			);
      -
      -			wp_localize_script(
      -				$this->_prefix . '-demo-content-install',
      -				'demo_plugins',
      -				array(
      -					'admin_url'    => admin_url(),
      -					'demo_plugins' => $this->demos,
      -					'steps'        => $this->get_demo_steps(),
      -					'messages'     => array(
      -						'installing'              => __( 'Installing', 'creatus' ),
      -						'start_install_plugins'   => __( 'Installing required plugins ...', 'creatus' ),
      -						'finish_install_plugins'  => __( 'Finished installing required plugins', 'creatus' ),
      -						'start_activate_plugins'  => __( 'Activating required plugins ...', 'creatus' ),
      -						'finish_activate_plugins' => __( 'Finished activating required plugins', 'creatus' ),
      -					)
      -				)
      -			);
      -		}
      -	}
      -
      -	public function get_demo_js_uri() {
      -		return $this->js_uri . '/super_admin_demo_content_install.js';
      -	}
      -
      -	public function get_demo_steps() {
      -		return array(
      -			'activate-demo-plugins' => array(
      -				'ajax_action' => $this->_prefix . '_activate_demo_plugins',
      -				'nonce'       => wp_create_nonce( 'activate-demo-plugins' ),
      -				'message'     => esc_html__( 'Activate required demo plugins', 'creatus' ),
      -			),
      -			'install-demo-plugins'  => array(
      -				'ajax_action' => $this->_prefix . '_install_demo_plugins',
      -				'nonce'       => wp_create_nonce( 'install-demo-plugins' ),
      -				'message'     => esc_html__( 'Install required demo plugins', 'creatus' ),
      -			),
      -		);
      -	}
      -
      -	public function install_demo_plugins() {
      -
      -		if ( ! current_user_can( 'install_plugins' ) ) {
      -			wp_send_json_error( array( 'message' => "Current user can't install plugins" ) );
      -		}
      -
      -		check_ajax_referer( 'install-demo-plugins' );
      -
      -		$credentials = get_site_transient( $this->credentials_key );
      -
      -		if ( ! $this->initialize_filesystem( $credentials, WP_PLUGIN_DIR ) ) {
      -			if (empty($credentials) && get_filesystem_method() !== 'direct') {
      -				/**
      -				 * We don't have credentials and can't ask user for them.
      -				 * So instead of fail, just skip the plugin installation.
      -				 */
      -				wp_send_json_success();
      -			}
      -
      -			wp_send_json_error( array(
      -				'message' => sprintf( esc_html__( 'Failed to install required plugins. Folder %s is not writable', 'creatus' ), WP_PLUGIN_DIR ),
      -			) );
      -		}
      -
      -		if( !isset($_POST['demo_plugins']) ) {
      -			$_POST['demo_plugins'] = array();
      -		}
      -		
      -		$response = Thz_Plugin_Installer_Helper::bulk_install( $_POST['demo_plugins'] );
      -
      -		$message        = array();
      -		$failed_plugins = array();
      -		foreach ( $response as $slug => $data ) {
      -			if ( ! $data['install']['success'] ) {
      -				$message[ $slug ] = $data;
      -				$failed_plugins[] = ucfirst( $slug );
      -			}
      -		}
      -
      -		if ( ! empty( $failed_plugins ) ) {
      -
      -			wp_send_json_error( array(
      -				'message' => sprintf( esc_html__( 'Failed to install required plugins. %s', 'creatus' ), implode( ', ', $failed_plugins ) ),
      -			) );
      -		}
      -		ob_end_clean();
      -		wp_send_json_success();
      -	}
      -
      -	public function activate_demo_plugins() {
      -		/* skip the revslider templates check */
      -		update_option( 'revslider-templates-check',  time() );
      -
      -		check_ajax_referer( 'activate-demo-plugins' );
      -
      -		if( !isset($_POST['demo_plugins']) ) {
      -			$_POST['demo_plugins'] = array();
      -		}
      -
      -		$this->send_response( $this->activate_plugins( $_POST['demo_plugins'] ) );
      -	}
      -
      -	public function activate_plugins( $plugins ) {
      -		if ( ! current_user_can( 'activate_plugins' ) ) {
      -			return new WP_Error( 0, __( 'Current user can\'t activate plugins', 'creatus' ) );
      -		}
      -
      -		$response = Thz_Plugin_Installer_Helper::bulk_activate( $plugins );
      -
      -		$message        = array();
      -		$failed_plugins = array();
      -		$err = self::ERR;
      -		foreach ( $response as $slug => $data ) {
      -			if ( ! $data['activate']['success'] ) {
      -				$message[ $slug ] = $data;
      -				$failed_plugins[] = ucfirst( $slug );
      -			}
      -		}
      -
      -		if ( ! empty( $failed_plugins ) ) {
      -			return new WP_Error( 0, sprintf(
      -					esc_html__( 'Failed to activate required plugins. %s', 'creatus' ),
      -					implode( ', ', $failed_plugins )
      -				)
      -			);
      -		}
      -
      -		return array();
      -	}
      -
      -	public function send_response( $response, $error = false ) {
      -		ob_end_clean();
      -		if ( is_wp_error( $response ) ) {
      -			wp_send_json( array(
      -				'success' => true,
      -				'data' => array(
      -					'message' => $response->get_error_message()
      -				)
      -			) );
      -		}
      -
      -		wp_send_json_success();
      -	}
      -	/* end demo content install */
      -
      -	private function redirect_after_activation() {
      -		if( is_customize_preview() ) {
      -			return;
      -		}
      -
      -		global $pagenow;
      -		if ( is_admin() && ( ( isset( $_GET['activated'] ) && $pagenow == 'themes.php' ) || !get_option($this->option_key) ) ) {
      -			update_option( $this->option_key, $this->get_default_option_value(), false );
      -
      -			header( 'Location: ' . add_query_arg(
      -					array(
      -						'page' => $this->page_slug,
      -					),
      -					admin_url( 'admin.php' )
      -				) );
      -		}
      -	}
      -
      -	public function get_required_plugins() {
      -		return $this->plugins;
      -	}
      -
      -	public function add_ajax_requests() {
      -		add_action( 'wp_ajax_' . $this->_prefix . '_install_required_plugins', array(
      -			$this,
      -			'install_required_plugins'
      -		) );
      -
      -		add_action( 'wp_ajax_' . $this->_prefix . '_finish_install_process', array(
      -			$this,
      -			'finish_install_process'
      -		) );
      -	}
      -
      -	public function item_menu_page() {
      -		add_theme_page( 'Thz Plugins Update', 'Thz Plugins Update', 'manage_options', $this->page_slug, array(
      -			$this,
      -			'auto_setup_page'
      -		) );
      -	}
      -
      -	public function install_required_plugins() {
      -		if ( ! current_user_can( 'install_plugins' ) ) {
      -			wp_send_json_error( array( 'message' => "Current user can't install plugins" ) );
      -		}
      -
      -		check_ajax_referer( 'install-required-plugins' );
      -
      -		$credentials = get_site_transient( $this->credentials_key );
      -
      -		if ( ! $this->initialize_filesystem( $credentials, WP_PLUGIN_DIR ) ) {
      -			wp_send_json_error( array(
      -				'message' => sprintf( esc_html__( 'Failed to install required plugins. Folder %s is not writable', 'creatus' ), WP_PLUGIN_DIR ),
      -			) );
      -		}
      -		
      -		
      -		$required_plugins = $this->get_required_plugins();
      -
      -		if( isset($_POST['skip_plugins']) ){
      -			
      -			$skip_plugins = json_decode( urldecode($_POST['skip_plugins']), true);
      -			
      -			foreach( $required_plugins as $key => $pdata ){
      -				
      -				if( in_array( $pdata['name'], $skip_plugins)  ){
      -					
      -					unset($required_plugins[$key]);
      -				}
      -				
      -			}
      -			
      -		}
      -		
      -		if( empty($required_plugins) ){
      -			
      -			$this->insert_step_status( 'install-required-plugins', true, 'No plugins installed');
      -	
      -			ob_end_clean();
      -	
      -			wp_send_json_success();			
      -			
      -		}
      -
      -		$response = Thz_Plugin_Installer_Helper::bulk_install( $required_plugins , true ); // force install plugins
      -
      -		$message        = array();
      -		$failed_plugins = array();
      -		foreach ( $response as $slug => $data ) {
      -			if ( ! $data['install']['success'] ) {
      -				$message[ $slug ] = $data;
      -				$failed_plugins[] = ucfirst( $slug );
      -			}
      -		}
      -
      -		if ( ! empty( $failed_plugins ) ) {
      -			$this->insert_step_status( 'install-required-plugins', false, $message );
      -
      -			wp_send_json_error( array(
      -				'message' => sprintf( esc_html__( 'Failed to install required plugins. %s', 'creatus' ), implode( ', ', $failed_plugins ) ),
      -			) );
      -		}
      -
      -		$this->insert_step_status( 'install-required-plugins', true, $message );
      -
      -		ob_end_clean();
      -
      -		wp_send_json_success();
      -	}
      -
      -	public function finish_install_process() {
      -		ob_end_clean();
      -
      -		if ( ! current_user_can( 'manage_options' ) ) {
      -			wp_send_json_error( array( 'message' => "Current user can't manage options" ) );
      -		}
      -
      -		check_ajax_referer( 'finish-install-process' );
      -
      -		$this->insert_step_status( 'finish-install-process', true );
      -
      -		// set default steps
      -		$option = $this->get_finished_option_value();
      -		$option['steps']['auto-setup-step-choosed'] = 'plugins_update';
      -		update_option( $this->option_key, $option );
      -		// end set default steps
      -
      -		wp_send_json_success();
      -	}
      -
      -	protected function insert_step_status( $step, $status, $message = null ) {
      -		$option                      = get_option( $this->option_key );
      -		$option['steps'][ $step ]    = (bool) $status;
      -		$option['messages'][ $step ] = $message;
      -
      -		$option['steps']['auto-setup-step-choosed'] = 'plugins_update';
      -
      -		update_option( $this->option_key, $option );
      -	}
      -
      -	public function install_finished() {
      -		$option = get_option( $this->option_key );
      -
      -		$checker = false;
      -
      -		if ( ! empty( $option['steps'] ) ) {
      -			$checker = true;
      -			foreach ( $option['steps'] as $step ) {
      -				if ( $step == false ) {
      -					$checker = false;
      -					break;
      -				}
      -			}
      -		}
      -
      -		return $checker;
      -	}
      -
      -	private function process_is_running() {
      -		$current_state = get_option( $this->option_key, array() );
      -
      -		return ( ! empty( $current_state['install_process']['install_dependencies'] ) || ! empty( $current_state['install_process']['import_demo_content'] ) );
      -	}
      -
      -	private function generate_url( $install_dependencies = 0, $import_demo_content = 0 ) {
      -		return add_query_arg( array(
      -			'page'                 => $this->page_slug,
      -			'install_dependencies' => $install_dependencies,
      -			'import_demo_content'  => $import_demo_content
      -		), admin_url( 'admin.php' )
      -		);
      -	}
      -
      -	private function generate_request_credentials_url( $install_dependecies = 0, $import_demo_content = 0 ) {
      -		return add_query_arg( array(
      -			'page'                => $this->page_slug,
      -			'request_credentials' => true
      -		),
      -			$this->generate_url( $install_dependecies, $import_demo_content )
      -		);
      -	}
      -
      -	public function get_setup_messages() {
      -		return array(
      -			'plugins_only'      => sprintf( esc_html__( 'This option will activate Unyson dependencies. The %1$s demo content will not be installed %2$s.', 'creatus' ), '<b>', '</b>' ),
      -			'plugins_and_demo'  => sprintf( esc_html__( 'This option will activate Unyson dependencies together %1$s with the demo content %2$s for the theme.', 'creatus' ), '<b>', '</b>' ),
      -			'skip_auto_install' => esc_html__( 'Skip the auto setup all together and activate all the Unyson dependencies manually. Note that this page will not be  accessible until you install the theme again.', 'creatus' )
      -		);
      -	}
      -
      -	public function auto_setup_page() {
      -
      -		$auto_setup_url = add_query_arg( array(
      -			'page' => $this->page_slug,
      -		), admin_url( 'admin.php' ) );
      -
      -		$credentials = get_site_transient( $this->credentials_key );
      -
      -		if ( ! empty( $_GET['request_credentials'] ) ) {
      -			request_filesystem_credentials( $auto_setup_url, '', false, false, null );
      -
      -			return;
      -		}
      -
      -		if ( ! $credentials && ! $this->initialize_filesystem( $credentials, WP_PLUGIN_DIR ) ) {
      -			ob_start();
      -			$credentials = request_filesystem_credentials( $auto_setup_url, '', false, false, null );
      -			ob_get_clean();
      -			set_site_transient( $this->credentials_key, $credentials, DAY_IN_SECONDS );
      -		}
      -
      -		$this->auto_setup_page_view();
      -	}
      -
      -	public function get_js_uri() {
      -		return $this->js_uri . '/plugins_install.js';
      -	}
      -
      -	private function admin_enqueue_scripts( $view = 'install' ) {
      -
      -
      -		wp_enqueue_script( 'jquery' );
      -		wp_enqueue_script( 'underscore' );
      -		
      -		if( 'choose' == $view ){
      -			
      -			wp_enqueue_script( $this->_prefix . '-plugins-install-choose', $this->js_uri . '/plugins_install_choose.js', array(
      -				'jquery',
      -				'underscore'
      -			) );			
      -		}
      -		
      -		if( 'install' == $view ){
      -			wp_enqueue_script( $this->_prefix . '-plugins-install', $this->get_js_uri(), array(
      -				'jquery',
      -				'underscore'
      -			) );
      -			
      -			$auto_setup_data = array(
      -				'admin_url'                 => admin_url(),
      -				'demo_content_url'          => add_query_arg( array(
      -					'page'              => 'fw-backups-demo-content',
      -					'from_auto_install' => 1
      -				), admin_url( 'tools.php' ) ),
      -				'steps'                     => $this->get_steps(),
      -				'messages'                  => array(
      -					'on_leave_alert'    => esc_html__( 'Attention, the installation process is not yet finished, if you leave this page, you will lose the information stored on the site!', 'creatus' ),
      -					'server_problems'   => esc_html__( "Sorry, we've encountered some errors, try to access this page later.", "creatus" ),
      -					'process_completed' => esc_html__( 'The installation process was completed successfully.', 'creatus' )
      -				),
      -			);
      -			
      -			wp_localize_script( $this->_prefix . '-plugins-install', 'auto_setup_data', $auto_setup_data );
      -		
      -		}
      -	}
      -
      -	public function initialize_filesystem( $credentials = false, $context ) {
      -		return ( WP_Filesystem( $credentials, $context ) === true );
      -	}
      -
      -	public function auto_setup_page_view() {
      -
      -		if ( $this->process_is_running() ) {
      -			
      -			$this->admin_enqueue_scripts();
      -			echo ($this->render_view( $this->view_path . '/auto_setup.php' ));
      -			
      -		} else {
      -			
      -			//update_option( $this->option_key, array() );
      -			
      -			//echo print_r(get_option( $this->option_key ));
      -			$this->admin_enqueue_scripts('choose');
      -			
      -			
      -			$credentials              = get_site_transient( $this->credentials_key );
      -			$have_credentials         = $this->initialize_filesystem( $credentials, WP_PLUGIN_DIR );
      -			$install_dependencies_url = $have_credentials ? $this->generate_url( true, false ) : $this->generate_request_credentials_url( true, false );
      -			$import_demo_content_url  = $have_credentials ? $this->generate_url( true, true ) : $this->generate_request_credentials_url( true, true );
      -			$this->render_install_setup( array(
      -				'install_dependencies_url' => $install_dependencies_url,
      -				'import_demo_content_url'  => $import_demo_content_url,
      -				'skip_auto_install_url'    => $this->generate_url(),
      -				'update_auto_install_url'  => $this->generate_url(2),
      -				'auto_install_finished'    => $this->install_finished(),
      -				'messages'                 => $this->get_setup_messages(),
      -				'plugins_list'             => wp_list_pluck( $this->plugins, 'name' ),
      -				'plugins_data'             => $this->plugins,
      -				'has_demo_content'         => $this->has_demo_content()
      -			) );
      -		}
      -	}
      -
      -	private function has_demo_content() {
      -		return $this->has_demo_content;
      -	}
      -
      -	private function get_default_option_value() {
      -		return array(
      -			'steps'           => $this->get_steps_keys(),
      -			'install_process' => array(
      -				'install_dependencies' => false,
      -				'import_demo_content'  => false
      -			)
      -		);
      -	}
      -
      -	private function get_finished_option_value() {
      -		return array(
      -			'steps'           => $this->get_steps_keys(true), // force to set steps to true (it's called on plugins_update_finished)
      -			'install_process' => array(
      -				'install_dependencies' => false,
      -				'import_demo_content'  => false
      -			)
      -		);
      -	}
      -
      -	private function get_steps_keys( $fill_value = false ) {
      -		return array_fill_keys( array_keys( $this->get_steps() ), $fill_value );
      -	}
      -
      -	protected function get_steps() {
      -		return array(
      -			'install-required-plugins'     => array(
      -				'ajax_action' => $this->_prefix . '_install_required_plugins',
      -				'nonce'       => wp_create_nonce( 'install-required-plugins' ),
      -				'message'     => esc_html__( 'Installing required plugins', 'creatus' ),
      -			),
      -			'finish-install-process'        => array(
      -				'ajax_action' => $this->_prefix . '_finish_install_process',
      -				'nonce'       => wp_create_nonce( 'finish-install-process' ),
      -				'message'     => esc_html__( 'Finish installing process', 'creatus' )
      -			)
      -		);
      -	}
      -
      -	public function add_actions() {
      -		add_action( 'admin_menu', array( $this, 'item_menu_page' ), 20 );
      -		add_action( 'wp_loaded', array( $this, 'set_option_values' ), 21 );
      -	}
      -
      -	public function ob_start_action() {
      -		$ajax_actions = $this->get_list_of_ajax_actions();
      -
      -		if ( defined( 'DOING_AJAX' ) && DOING_AJAX && isset( $_REQUEST['action'] ) && in_array( $_REQUEST['action'], $ajax_actions ) ) {
      -			ob_start();
      -		}
      -	}
      -
      -	public function get_list_of_ajax_actions() {
      -		return array_values( wp_list_pluck( $this->get_steps(), 'ajax_action' ) );
      -	}
      -
      -	public function set_option_values() {
      -		$option_value = get_option( $this->option_key );
      -
      -		if ( get_option( $this->option_key ) === false ) {
      -			update_option( $this->option_key, $this->get_default_option_value(), false );
      -			$option_value = get_option( $this->option_key );
      -		}
      -
      -		if ( isset( $_GET['install_dependencies'] ) or isset( $_GET['import_demo_content'] ) ) {
      -			$option_value['install_process']['install_dependencies'] = ! empty( $_GET['install_dependencies'] ) ? $_GET['install_dependencies'] : false;
      -			$option_value['install_process']['import_demo_content']  = ( ! empty( $_GET['import_demo_content'] ) );
      -			update_option( $this->option_key, $option_value, false );
      -		}
      -	}
      -
      -	public function render_install_setup( $params ) {
      -		wp_enqueue_style( $this->_prefix.'-auto-setup-css', $this->css_uri . '/styles.css' );
      -
      -		echo ($this->render_view( $this->view_path . '/install_setup.php', $params ));
      -	}
      -
      -	/**
      -	 * Safe render a view and return html
      -	 * In view will be accessible only passed variables
      -	 * Use this function to not include files directly and to not give access to current context variables (like $this)
      -	 *
      -	 * @param string $file_path
      -	 * @param array $view_variables
      -	 * @param bool $return In some cases, for memory saving reasons, you can disable the use of output buffering
      -	 *
      -	 * @return string HTML
      -	 */
      -	private function render_view( $file_path, $view_variables = array(), $return = true ) {
      -		extract( $view_variables, EXTR_REFS );
      -
      -		unset( $view_variables );
      -
      -		if ( $return ) {
      -			ob_start();
      -
      -			require $file_path;
      -
      -			return ob_get_clean();
      -		} else {
      -			require $file_path;
      -		}
      -	}
      -}
      \ No newline at end of file
      diff --git a/inc/includes/auto-setup/config/config.php b/inc/includes/auto-setup/config/config.php
      index 893644d..6fbdca4 100644
      --- a/inc/includes/auto-setup/config/config.php
      +++ b/inc/includes/auto-setup/config/config.php
      @@ -8,9 +8,8 @@
       	'demos'          => _thz_get_demos_plugins_list(),
       	'plugins'        => array(
       		array(
      -			'name'   => 'Thz Core',
      -			'slug'   => 'thz-core',
      -			'source' => esc_url('https://updates.themezly.io/plugins/thz-core.zip')
      +			'name'   => 'Creatus Extended',
      +			'slug'   => 'creatus-extended',
       		),
       		array(
       			'name'   => 'Assign Widgets',
      @@ -18,6 +17,5 @@
       		),
       	),
       	'theme_id'           => 'creatus',
      -	'child_theme_source' => esc_url('https://updates.themezly.io/plugins/creatus-child.zip'),
       	'has_demo_content'   => true
       );
      diff --git a/inc/includes/auto-setup/js/plugins_install.js b/inc/includes/auto-setup/js/plugins_install.js
      deleted file mode 100644
      index 29741a5..0000000
      --- a/inc/includes/auto-setup/js/plugins_install.js
      +++ /dev/null
      @@ -1,100 +0,0 @@
      -/* globals jQuery, _, ajaxurl, auto_setup_data */
      -(function ($) {
      -    var autoSetupProcess;
      -
      -    autoSetupProcess = {
      -        $infoContainer: null,
      -        initialize: function ($infoContainer) {
      -            autoSetupProcess.$infoContainer = $infoContainer;
      -            $(window).on('beforeunload', autoSetupProcess.onLeaveAlert);
      -            autoSetupProcess.install_required_plugins();
      -        },
      -
      -        /*
      -         @finished default is false
      -         */
      -        showInfo: function (info, finished) {
      -
      -            var processing = (_.isUndefined(finished)) ? ' ...' : '';
      -            autoSetupProcess.$infoContainer.append('<p>' + info + processing + '</p>');
      -        },
      -
      -        processFailed: function (jqXHR, textStatus) {
      -            autoSetupProcess.showInfo(auto_setup_data['messages']['server_problems'], true);
      -            $(window).off('beforeunload', autoSetupProcess.onLeaveAlert);
      -        },
      -
      -        checkResponse: function (response, nextStep) {
      -            if (response['success'] === true) {
      -                nextStep.call();
      -            } else {
      -                autoSetupProcess.showInfo(response['data']['message'], true);
      -                autoSetupProcess.showInfo('Please access this page later, it will remain in the menu.', true);
      -                $(window).off('beforeunload', autoSetupProcess.onLeaveAlert);
      -            }
      -        },
      -
      -        install_required_plugins: function () {
      -            autoSetupProcess.showInfo(auto_setup_data['steps']['install-required-plugins']['message']);
      -			
      -            var data = {
      -                action: auto_setup_data['steps']['install-required-plugins']['ajax_action'],
      -                _ajax_nonce: auto_setup_data['steps']['install-required-plugins']['nonce'],
      -				skip_plugins:autoSetupProcess.getUrlVars()["skip_plugins"]
      -            };
      -			
      -            return jQuery.ajax({
      -                url: ajaxurl,
      -                type: 'POST',
      -                data: data,
      -                dataType: 'json'
      -            }).done(function (response) {
      -                autoSetupProcess.checkResponse(response, autoSetupProcess.finish_install_process);
      -            }).fail(autoSetupProcess.processFailed);
      -        },
      -
      -        finish_install_process: function () {
      -            autoSetupProcess.showInfo(auto_setup_data['steps']['finish-install-process']['message']);
      -            var data = {
      -                action: auto_setup_data['steps']['finish-install-process']['ajax_action'],
      -                _ajax_nonce: auto_setup_data['steps']['finish-install-process']['nonce']
      -            };
      -            return $.ajax({
      -                url: ajaxurl,
      -                type: 'POST',
      -                data: data,
      -                dataType: 'json'
      -            }).done(function (response) {
      -                autoSetupProcess.checkResponse(response, autoSetupProcess.finishAutoSetupProcess);
      -            }).fail(autoSetupProcess.processFailed);
      -        },
      -
      -        finishAutoSetupProcess: function () {
      -            $(window).off('beforeunload', autoSetupProcess.onLeaveAlert);
      -            var redirectUrl = auto_setup_data.admin_url;
      -            autoSetupProcess.showInfo(auto_setup_data['messages']['process_completed'], true);
      -            window.location.replace(redirectUrl);
      -        },
      -
      -        onLeaveAlert: function () {
      -            return auto_setup_data['messages']['on_leave_alert'];
      -        },
      -		
      -		getUrlVars: function (){
      -			var vars = [], hash;
      -			var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
      -			for(var i = 0; i < hashes.length; i++)
      -			{
      -				hash = hashes[i].split('=');
      -				vars.push(hash[0]);
      -				vars[hash[0]] = hash[1];
      -			}
      -			return vars;
      -		}
      -    };
      -
      -    $(document).on('ready', function () {
      -        autoSetupProcess.initialize($('.wrap'));
      -    });
      -
      -})(jQuery);
      \ No newline at end of file
      diff --git a/inc/includes/auto-setup/js/plugins_install_choose.js b/inc/includes/auto-setup/js/plugins_install_choose.js
      deleted file mode 100644
      index d66ef95..0000000
      --- a/inc/includes/auto-setup/js/plugins_install_choose.js
      +++ /dev/null
      @@ -1,52 +0,0 @@
      -/* globals jQuery, _, ajaxurl, auto_setup_data */
      -(function ($) {
      -
      -	$(document).on('ready', function () {
      -		
      -		var $current_url = $('.update-plugins-btn').attr('href');
      -		var $count		 = $('.theme-plugins').length;
      -		
      -
      -		 $(".update-all-plugins").on('click', function() {
      -			 $('.theme-plugins').not(this).prop('checked', this.checked).trigger('change');
      -		 });
      -
      -		$('.theme-plugins').on('change',function (){
      -			
      -			var checkboxArray = $(".theme-plugins:not(:checked)").map(function() {
      -				return this.value;
      -			}).get();
      -
      -			$qstring = JSON.stringify( Object.assign({}, checkboxArray));
      -
      -			if( checkboxArray.length > 0){
      -				
      -				$new_url = $current_url + '&skip_plugins=' + $qstring;
      -				
      -				if( $count == checkboxArray.length ){
      -					
      -					$(".update-all-plugins").prop('checked',false);
      -					$('.postbox-holder .actions').hide();
      -					
      -				}else{
      -					
      -					$('.postbox-holder .actions').show();
      -				}
      -				
      -				$('.update-plugins-btn').attr('href', $new_url);
      -			
      -			}else{
      -				
      -				$('.postbox-holder .actions').show();
      -				$('.update-plugins-btn').attr('href',$current_url);
      -			
      -			}
      -
      -			
      -		});	
      -		
      -			
      -	});
      -
      -
      -})(jQuery);
      \ No newline at end of file
      diff --git a/inc/includes/auto-setup/js/super_admin_auto_install.js b/inc/includes/auto-setup/js/super_admin_auto_install.js
      index 86f0df1..599b576 100644
      --- a/inc/includes/auto-setup/js/super_admin_auto_install.js
      +++ b/inc/includes/auto-setup/js/super_admin_auto_install.js
      @@ -92,22 +92,6 @@
       				action: auto_setup_data['steps']['activate-supported-extensions']['ajax_action'],
       				_ajax_nonce: auto_setup_data['steps']['activate-supported-extensions']['nonce']
       			};
      -			return $.ajax({
      -				url: ajaxurl,
      -				type: 'POST',
      -				data: data,
      -				dataType: 'json'
      -			}).done(function (response) {
      -				autoSetupProcess.checkResponse(response, autoSetupProcess.install_child_theme);
      -			}).fail(autoSetupProcess.processFailed);
      -		},
      -		install_child_theme: function () {
      -
      -			autoSetupProcess.showInfo(auto_setup_data['steps']['install-child-theme']['message']);
      -			var data = {
      -				action: auto_setup_data['steps']['install-child-theme']['ajax_action'],
      -				_ajax_nonce: auto_setup_data['steps']['install-child-theme']['nonce']
      -			};
       			return $.ajax({
       				url: ajaxurl,
       				type: 'POST',
      diff --git a/inc/includes/auto-setup/views/install_setup.php b/inc/includes/auto-setup/views/install_setup.php
      index 80cfa12..2d4555c 100644
      --- a/inc/includes/auto-setup/views/install_setup.php
      +++ b/inc/includes/auto-setup/views/install_setup.php
      @@ -1,66 +1,6 @@
       <?php if ( ! defined( 'ABSPATH' ) ) die( 'Direct access forbidden.' ); ?>
       <div class="wrap install-setup">
      -
      -	<?php if( $auto_install_finished ) : ?>
      -		<h1><?php esc_html_e( 'Themezly Plugins Updates', 'creatus' ) ?></h1>
      -		<br/>
      -		<!-- START INSTALL PLUGINS UPDATE -->
      -        <div class="postbox-holder plugins-update-holder">
      -            <div class="postbox auto-setup-box plugins-update">
      -                <div class="header hndle">
      -                    <h3><span><?php esc_html_e( 'Plugins Update', 'creatus' ) ?></span></h3>
      -                </div>
      -                <div class="content">
      -                    <p>
      -                        <?php esc_html_e('This utility can reinstall the latest versions of plugins provided by Themezly.com. Check the plugins you wish to update than click on Update Plugins button.', 'creatus'); ?>
      -                    </p>
      -                    <p><input type="checkbox" class="update-all-plugins"><?php esc_html_e( 'Update All', 'creatus' ) ?></p>
      -                    <ul class="update-plugins-list">
      -                        <?php
      -						
      -						 $tgmpa_plugins = _thz_get_tgmpa_plugins_list();
      -						
      -						if(!empty($plugins_data)){
      -						 foreach ( $plugins_data as $key => $plugin ):
      -							// phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited
      -							$path 			= ABSPATH . 'wp-content/plugins/'.$plugin['slug'].'/'.$plugin['slug'].'.php'; 
      -							$version 		= is_file( $path ) ? get_plugin_data( $path, false, false ) : false;
      -							$version_html 	= '<span class="version-info">'.__( 'Not installed', 'creatus' ).'</span>';
      -							
      -							if ( $version && isset($version['Version']) ){
      -								
      -								$plugin_version = $version['Version'];
      -								$latest_version = $tgmpa_plugins[$plugin['slug']]['version'];
      -								
      -								if ( version_compare($plugin_version, $latest_version, '<') ) {
      -									
      -									$version_html = '<span class="version-info need-update">'.$plugin_version.'<span> ->';
      -									$version_html .= '<span class="version-info latest-version">'.$latest_version.'<span>';
      -									
      -								}else{
      -									
      -									$version_html = '<span class="version-info latest-version">'.$plugin_version.'<span>';
      -									
      -								}
      -								
      -							}
      -							
      -						?>
      -                            <li>
      -                                <input type="checkbox" class="theme-plugins" value="<?php echo $plugin['name'] ?>"> 
      -								<?php printf( esc_html__( '%s Plugin', 'creatus' ), $plugin['name'] ); ?><?php echo $version_html ?><br />
      -                            </li>
      -                        <?php endforeach; }?>
      -                    </ul>
      -                </div>
      -                <div class="actions">
      -                    <a class="button button-primary update-plugins-btn" href="<?php echo esc_url($update_auto_install_url); ?>"><?php esc_html_e( 'Update Plugins', 'creatus' ) ?></a>
      -                </div>
      -            </div>
      -        </div>
      -		<!-- END INSTALL PLUGINS UPDATE -->
      -	<?php else: ?>
      -
      +	<?php if( !$auto_install_finished ) : ?>
       	<h1><?php esc_html_e( 'Auto Setup', 'creatus' ) ?></h1>
       	<p class="sub-header"><?php esc_html_e( 'Choose one of the install methods below.', 'creatus' ) ?></p>
       	<br/>
      @@ -85,10 +25,6 @@
                                   <div class="dashicons dashicons-yes"></div>
                                   <span><?php printf( esc_html__( '%s Plugin', 'creatus' ), $plugin_name ); ?></span></li>
                           <?php endforeach; ?>
      -                    <li>
      -                        <div class="dashicons dashicons-yes"></div>
      -                        <span><?php esc_html_e( 'Download and Activate Child Theme', 'creatus' ) ?></span>
      -                    </li>
                           <li>
                               <div class="dashicons dashicons-yes"></div>
                               <span><?php esc_html_e( 'Redirect to Demo Content Installer', 'creatus' ) ?></span>
      @@ -124,10 +60,6 @@
                                   <div class="dashicons dashicons-yes"></div>
                                   <span><?php printf( esc_html__( '%s Plugin', 'creatus' ), $plugin_name ); ?></span></li>
                           <?php endforeach; ?>
      -                    <li>
      -                        <div class="dashicons dashicons-yes"></div>
      -                        <span><?php esc_html_e( 'Download and Activate Child Theme', 'creatus' ) ?></span>
      -                    </li>
                           <li>
                               <div class="dashicons dashicons-no-alt"></div>
                               <span><?php esc_html_e( 'Redirect to Demo Content Installer', 'creatus' ) ?></span>
      @@ -163,10 +95,6 @@
                                   <div class="dashicons dashicons-no-alt"></div>
                                   <span><?php printf( esc_html__( '%s Plugin', 'creatus' ), $plugin_name ); ?></span></li>
                           <?php endforeach; ?>
      -                    <li>
      -                        <div class="dashicons dashicons-no-alt"></div>
      -                        <span><?php esc_html_e( 'Download and Activate Child Theme', 'creatus' ) ?></span>
      -                    </li>
                           <li>
                               <div class="dashicons dashicons-no-alt"></div>
                               <span><?php esc_html_e( 'Redirect to Demo Content Installer', 'creatus' ) ?></span>
      @@ -181,10 +109,7 @@
               </div>
           </div>
       	<!-- END SKIP AUTO SETUP -->
      -    <?php endif; ?>
      +    
       </div>
      -<?php 
      -if( !$auto_install_finished  ) {
      -	echo $system_info;
      -}
      -?>
      \ No newline at end of file
      +<?php echo $system_info; ?>
      +<?php endif; ?>
      \ No newline at end of file
      diff --git a/inc/includes/auto-setup/views/system_info.php b/inc/includes/auto-setup/views/system_info.php
      index bd6836c..5dceeec 100644
      --- a/inc/includes/auto-setup/views/system_info.php
      +++ b/inc/includes/auto-setup/views/system_info.php
      @@ -289,6 +289,11 @@
       ?>
       <div class="wrap creatus-system-info">
       	<div class="thz-system-info">
      +    	<div class="thz-system-group">
      +        	<h4><?php echo __( 'Please consider using Creatus Child Theme for any custom modifications.', 'creatus' ); ?></h4>
      +            <a class="button button-primary" target="_blank" href="https://github.com/Themezly/Creatus-Child/releases"><?php esc_html_e( 'Download Creatus Child Theme', 'creatus' ) ?></a>
      +        </div>
      +        <br/>
       		<h1><?php esc_html_e( 'System info', 'creatus' ) ?> <span class="thz-admin-system-state<?php echo $hass_issue_class; ?>"></span></h1>
       		<p class="sub-header">
       		<?php echo __( 'Please make sure all items below are marked with a green check <b>before</b> proceeding with the auto setup or saving the theme options.', 'creatus' ) ?>
      diff --git a/inc/includes/builder-templates/class-thz-builder-templates.php b/inc/includes/builder-templates/class-thz-builder-templates.php
      deleted file mode 100644
      index 3623889..0000000
      --- a/inc/includes/builder-templates/class-thz-builder-templates.php
      +++ /dev/null
      @@ -1,631 +0,0 @@
      -<?php if (!defined('FW')) die('Forbidden');
      -
      -class ThzBuilderTemplates {
      -	
      -	
      -	private $api_uri;
      -	private $api_tpl;
      -	private $no_cache;
      -	
      -	/**
      -	 * Get cpac
      -	 */
      -	private $has_cpac = false;
      -
      -	/**
      -	 * ThzBuilderTemplates constructor.
      -	 */
      -	public function __construct() {
      -		
      -		if (!function_exists('fw_get_path_url')) {
      -			return;
      -		}
      -		
      -		$this->no_cache 	= apply_filters( '_thz_filter_library_no_cache', false );
      -		$this->api_uri 		= apply_filters( '_thz_filter_library_api_url', 'https://resources.themezly.io/api/v1/info' );
      -		$this->api_tpl 		= apply_filters( '_thz_filter_library_api_tpl', 'https://resources.themezly.io/api/v1/template/' );
      -		
      -		$this->has_cpac();
      -		
      -		add_action(
      -			'fw_ext_builder:option_type:builder:enqueue',
      -			array($this, '_action_enqueue')
      -		);
      -		add_action(
      -			'wp_ajax_thz-theme-builder-templates-render',
      -			array($this, '_ajax_render')
      -		);
      -		add_action(
      -			'wp_ajax_thz-theme-builder-templates-load',
      -			array($this, '_ajax_load')
      -		);
      -		
      -		add_action(
      -			'wp_ajax_thz-theme-builder-templates-update',
      -			array($this, '_ajax_update')
      -		);
      -	}
      -
      -	/**
      -	 * @return bool
      -	 */
      -	public function current_user_allowed() {
      -		return current_user_can('edit_posts');
      -	}
      -
      -
      -	/**
      -	 * Current dir url
      -	 * @param string
      -	 * @return string
      -	 */
      -	private function get_url($append = '') {
      -		
      -		try {
      -			$url = FW_Cache::get($cache_key = 'thz-theme:pred-tpl:url');
      -		} catch (FW_Cache_Not_Found_Exception $e) {
      -			FW_Cache::set(
      -				$cache_key,
      -				$url = get_template_directory_uri().'/inc/includes/builder-templates/'
      -			);
      -		}
      -		return $url . $append;
      -	}
      -	
      -
      -	/**
      -	 * @param array $data
      -	 * @return void
      -	 * @internal
      -	 */
      -	public function _action_enqueue($data) {
      -		
      -		if ($data['option']['type'] !== 'page-builder') {
      -			return;
      -		}
      -
      -		$prefix = 'thz-theme-';
      -
      -		wp_enqueue_style(
      -			$prefix .'pb-pred-tpl',
      -			$this->get_url( '/static/styles.css' ),
      -			array(),
      -			fw()->theme->manifest->get_version()
      -		);
      -
      -		wp_enqueue_script(
      -			$prefix .'pb-pred-tpl',
      -			$this->get_url( '/static/scripts.js'),
      -			array('jquery', 'fw-events'),
      -			fw()->theme->manifest->get_version(),
      -			true
      -		);
      -
      -		wp_localize_script(
      -			$prefix .'pb-pred-tpl',
      -			'_theme_pb_pred_tpl',
      -			array(
      -				'l10n' => array(
      -					'add_button' => esc_html__('Template Library', 'creatus'),
      -				),
      -			)
      -		);
      -	}
      -
      -	public function _ajax_render() {
      -		$r = array(
      -			'error' => '',
      -			'data' => array(),
      -		);
      -
      -		do {
      -			if (!$this->current_user_allowed()) {
      -				$r['error'] = 'Forbidden';
      -				break;
      -			}
      -
      -			$list = $this->get_list();
      -			
      -			$r['data']['html'] = fw_render_view(
      -				dirname(__FILE__) .'/views/sections.php',
      -				array(
      -					'sections' => $list['sections'],
      -					'sections_categories' => $list['sections_categories'],
      -					'last_update' => get_option('thz:builder:tpl:last:update', 0),
      -					'can_update' => $this->can_update(),
      -					'cpac' => $this->has_cpac
      -				)
      -			);
      -		} while(false);
      -
      -		if ($r['error']) {
      -			wp_send_json_error(
      -				is_wp_error($r['error'])
      -					? $r['error']
      -					: new WP_Error('error', $r['error'])
      -			);
      -		} else {
      -			wp_send_json_success($r['data']);
      -		}
      -	}
      -
      -	public function _ajax_load() {
      -		$r = array(
      -			'error' => '',
      -			'data' => array(),
      -		);
      -
      -		do {
      -			if (!$this->current_user_allowed()) {
      -				$r['error'] = 'Forbidden';
      -				break;
      -			}
      -
      -			if (empty($_POST['id'])) {
      -				$r['error'] = 'Id not specified';
      -				break;
      -			}
      -
      -			$id = $_POST['id'];
      -
      -			$list = $this->get_list();
      -
      -			if (!isset($list['sections'][ $id ])) {
      -				$r['error'] = 'Invalid id';
      -				break;
      -			}
      -			
      -			if( 'remote' == $list['sections'][ $id ]['source'] ){
      -				
      -				$r['data']['json'] = $this->fetch_template( $id ) ;
      -				
      -			}else{
      -				
      -				$json_path = get_stylesheet_directory() .'/inc/includes/builder-templates/'. $id .'/json.php' ;
      -				$r['data']['json'] = fw_render_view( $json_path );
      -			}
      -			
      -			
      -		} while(false);
      -
      -		if ($r['error']) {
      -			wp_send_json_error(
      -				is_wp_error($r['error'])
      -					? $r['error']
      -					: new WP_Error('error', $r['error'])
      -			);
      -		} else {
      -			wp_send_json_success($r['data']);
      -		}
      -	}
      -	
      -	public function _ajax_update() {
      -		$r = array(
      -			'error' => '',
      -			'data' => array(
      -				'updated' => false
      -			),
      -		);
      -
      -		do {
      -			
      -			if (!$this->current_user_allowed()) {
      -				$r['error'] = 'Forbidden';
      -				break;
      -			}
      -			
      -			$u = $this->can_update() ? _thz_force_template_library_update() : false;
      -			$r['data']['updated'] = $u;
      -			
      -		} while(false);
      -
      -		if ($r['error']) {
      -			wp_send_json_error(
      -				is_wp_error($r['error'])
      -					? $r['error']
      -					: new WP_Error('error', $r['error'])
      -			);
      -		} else {
      -			wp_send_json_success($r['data']);
      -		}
      -	}
      -	
      -	
      -	private function can_update(){
      -		
      -		$last_update = get_option('thz:builder:tpl:last:update', 0);
      -		
      -		if( $last_update <= strtotime('-15 minutes') ){
      -			
      -			return true;
      -		}
      -		
      -		return false;
      -	}
      -	
      -	private function process_json( $json ){
      - 
      -		$result = preg_replace_callback('/<p%(.*?)%p>/', function($match) {
      -			
      -			$replaced = $match[0];
      -			
      -			if( isset($match[1]) ){
      -				
      -				$vars 		= explode(',',$match[1]);
      -				$replaced 	= thz_dummy_post_ids( $vars[0],$vars[1] );
      -				
      -			}
      -			
      -			return $replaced; 
      -
      -		}, $json);          
      -		
      -		
      -		return $result;
      -		
      -	}
      -	
      -	
      -	private function fetch_template( $id ){
      -
      -		$transient = 'thz:builder:tpl:'.$id;
      -		
      -		if ( $this->no_cache || false === ( $template_data = get_transient( $transient ) ) ) {
      -			
      -			delete_transient( $transient );
      -			
      -					
      -			$response = wp_remote_get( $this->get_api_uri( 'template', $id ) , array( 'timeout' => 20 ) );
      -			$httpCode = wp_remote_retrieve_response_code( $response );
      -	
      -			if ( $httpCode >= 200 && $httpCode < 300 ) {
      -				
      -				$template_data = wp_remote_retrieve_body( $response );
      -				
      -			} else {
      -				
      -				$template_data = esc_html__( 'Not able to load builder templates', 'creatus' );
      -				
      -			}	
      -			
      -			set_transient( $transient, $template_data, 7 * DAY_IN_SECONDS );
      -			
      -		}
      -		
      -		
      -		$media_importer = new Thz_Media_Importer( $template_data );
      -		$template_data = $media_importer->get_template_json();
      -
      -		return $this->process_json( $template_data );	
      -		
      -	}
      -
      -	private function fetch_list(){
      -		
      -		$transient = 'thz:builder:tpl:info';
      -
      -		if ( $this->no_cache || false === ( $templates_data = get_transient( $transient ) ) ) {
      -			
      -			delete_transient( $transient );
      -			
      -			$response = wp_remote_get( $this->get_api_uri( 'list' ) , array( 'timeout' => 20 ) );
      -			$httpCode = wp_remote_retrieve_response_code( $response );
      -	
      -			if ( $httpCode >= 200 && $httpCode < 300 ) {
      -				
      -				$templates_data = wp_remote_retrieve_body( $response );
      -				
      -			} else {
      -				
      -				$templates_data = esc_html__( 'Not able to load builder templates', 'creatus' );
      -				
      -			}
      -			
      -			update_option ('thz:builder:tpl:last:update', time() );
      -			set_transient( $transient, $templates_data, 7 * DAY_IN_SECONDS );
      -		
      -		}
      -
      -		$data = json_decode($templates_data ,true );
      -
      -		return $data;
      -							
      -	}
      -
      -	/**
      -	 * Get resource URI
      -	 *
      -	 * @param string $type - can have values 'list' or 'template'
      -	 * @param string $prepend
      -	 *
      -	 * @return null|string
      -	 */
      -	private function get_api_uri( $type = 'list', $prepend = '' ){
      -		switch( $type ){
      -			case 'list':
      -				$uri = $this->api_uri . $prepend;
      -			break;
      -			case 'template':
      -				$uri = $this->api_tpl . $prepend;
      -			break;
      -			default:
      -				$uri = null;
      -			break;
      -		}
      -
      -		if( !is_null( $uri ) && $this->has_cpac ){
      -			$uri = add_query_arg( array( 'cpac' => $this->has_cpac ), $uri );
      -		}
      -
      -		return $uri;
      -	}
      -	
      -	
      -	private function has_cpac(){
      -		
      -		$cpac = thz_has_cpac();
      -		
      -		if( $cpac ){
      -			$this->has_cpac = $cpac;
      -		}		
      -	}
      -	
      -	private function get_list() {
      -
      -		$fetched_list = $this->fetch_list();
      -
      -		$r = array(
      -			'sections_categories' => $fetched_list['sections_categories'],
      -			'sections' => $fetched_list['sections'],
      -		);
      -		
      -		$paths = array();
      -		
      -		if( is_child_theme() ){
      -			
      -			$child = glob( get_stylesheet_directory(). '/inc/includes/builder-templates/*',GLOB_ONLYDIR);
      -			if(is_array($child) && !empty($child) ){
      -				$paths = array_merge($paths, $child);
      -			}
      -		}
      -		
      -		if ( !empty($paths) ) {
      -						
      -			foreach ($paths as $path) {
      -				
      -				$id = basename($path);
      -
      -				$cfg = array_merge(
      -					array(
      -						'desc' => '',
      -						'categories' => array(),
      -					),
      -					include ($path .'/config.php')
      -				);
      -			  	
      -				$r['sections'][$id] = array(
      -					'thumbnail' => get_stylesheet_directory_uri() . '/inc/includes/builder-templates/'.$id.'/thumbnail.jpg',
      -					'source' => 'local',
      -					'desc' => $cfg['desc'],
      -					'categories' => $cfg['categories'],
      -				);
      -
      -				$r['sections_categories'] = array_merge($r['sections_categories'], $cfg['categories']);
      -			}
      -		}
      -
      -		return $r;
      -	}
      -}
      -
      -/**
      - * Class Thz_Media_Importer
      - * Import media files into the local Media Gallery
      - */
      -class Thz_Media_Importer{
      -	/**
      -	 * JSON encoded template data
      -	 * @var JSON string
      -	 */
      -	private $template_data;
      -	/**
      -	 * Will store any images found into the content
      -	 * @var array
      -	 */
      -	private $found_images = array();
      -
      -	/**
      -	 * Thz_Media_Importer constructor.
      -	 *
      -	 * @param JSON string $template_data
      -	 */
      -	public function __construct( $template_data ) {
      -		$this->template_data = $template_data;
      -		// begin image detection. Will store all found images in $this->found_images
      -		$this->find_images( json_decode( $template_data, true ) );
      -
      -		if( !$this->found_images ){
      -			return;
      -		}
      -
      -		$this->fetch_remote_images();
      -	}
      -
      -	/**
      -	 * @param string $key - the key that needs to be found
      -	 * @param array $array - array to be searched
      -	 *
      -	 * @return null
      -	 */
      -	private function find_images( $array ){
      -		
      -		if( !is_array($array) ){
      -			return;
      -		}
      -		
      -		foreach ( $array as $kk => $a ) {
      -			if( is_array( $a ) ) {
      -				if( ( 'image' == $kk && array_key_exists( 'url', $a ) ) || array_key_exists( 'attachment_id', $a ) ){
      -					$this->found_images[] = $a;
      -				}
      -
      -				$this->find_images( $a );
      -			}
      -		}
      -	}
      -
      -	/**
      -	 * Fetches all remote images from the template
      -	 */
      -	private function fetch_remote_images(){
      -		foreach( $this->found_images as $key => $image ) {
      -			if( is_array( $image ) && false === strpos( $image['url'], 'resources.themezly.io' ) ){
      -				unset( $this->found_images[ $key ] );
      -				continue;
      -			}
      -
      -			// process images
      -			if ( is_array( $image ) ) {
      -				$image_id = false;
      -				// try to detect image ID
      -				if( isset( $image['attachment_id'] ) ){
      -					$image_id = $image['attachment_id'];
      -				}else if ( isset( $image['id'] ) ){
      -					$image_id = $image['id'];
      -				}
      -				// if no image ID detected, to avoid creating duplicates in media gallery, skip image import
      -				if( !$image_id ){
      -					unset( $this->found_images[ $key ] );
      -					continue;
      -				}
      -
      -				$args = array(
      -					'post_type'  => 'attachment',
      -					'meta_query' => array(
      -						array(
      -							'key'     => 'thz_image_id',
      -							'value'   => $image_id,
      -							'compare' => '='
      -						)
      -					)
      -				);
      -				$img  = get_posts( $args );
      -				if ( $img ) {
      -					$this->found_images[ $key ]['wp_image_id'] = $img[0]->ID;
      -				} else {
      -					$img_id = $this->import_image( $image['url'], $image_id );
      -					if ( $img_id && !is_wp_error( $img_id ) ) {
      -						$this->found_images[ $key ]['wp_image_id'] = $img_id;
      -					}
      -				}
      -			}
      -		}
      -	}
      -
      -	/**
      -	 * Import an image into WP Media Gallery based on its URL
      -	 *
      -	 * @param $image_url
      -	 * @param bool $unique_id
      -	 *
      -	 * @return bool|int|WP_Error
      -	 */
      -	private function import_image( $image_url, $unique_id = false ){
      -		if( 'http' != substr( $image_url, 0, 4 )){
      -			$image_url = 'http:' . $image_url;
      -		}
      -
      -		// get the thumbnail
      -		$response = wp_remote_get(
      -			$image_url,
      -			array(
      -				'sslverify' => false,
      -
      -				/**
      -				 * Request timeout filter
      -				 * @var int
      -				 */
      -				'timeout' => apply_filters( 'thz_image_request_timeout', 5 )
      -			)
      -		);
      -
      -		if( is_wp_error( $response ) || 200 != wp_remote_retrieve_response_code($response) ) {
      -			return false;
      -		}
      -
      -		$image_contents = $response['body'];
      -		$image_type 	= wp_remote_retrieve_header( $response, 'content-type' );
      -		// Translate MIME type into an extension
      -		if ( $image_type == 'image/jpeg' ){
      -			$image_extension = '.jpg';
      -		}elseif ( $image_type == 'image/png' ){
      -			$image_extension = '.png';
      -		}
      -
      -		$file_name = basename( $image_url ) ;
      -
      -		// Save the image bits using the new filename
      -		$upload = wp_upload_bits( $file_name, null, $image_contents );
      -		if ( $upload['error'] ) {
      -			return false;
      -		}
      -
      -		$img_url 	= $upload['url'];
      -		$filename 	= $upload['file'];
      -
      -		$wp_filetype = wp_check_filetype( basename( $filename ), null );
      -		$attachment = array(
      -			'post_mime_type'	=> $wp_filetype['type'],
      -			'post_title'		=> $file_name,
      -			'post_content'		=> '',
      -			'post_status'		=> 'inherit',
      -			'guid'				=> $img_url
      -		);
      -		$attach_id = wp_insert_attachment( $attachment, $filename );
      -		// you must first include the image.php file
      -		// for the function wp_generate_attachment_metadata() to work
      -		require_once( ABSPATH . 'wp-admin/includes/image.php' );
      -		$attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
      -		wp_update_attachment_metadata( $attach_id, $attach_data );
      -
      -		// Add field to mark image as a video thumbnail
      -		update_post_meta( $attach_id, 'thz_image_id', $unique_id );
      -
      -		return $attach_id;
      -	}
      -
      -	/**
      -	 * Get the update template with local paths instead of remote ones
      -	 * @return JSON|mixed
      -	 */
      -	public function get_template_json(){
      -		if( !$this->found_images ){
      -			return $this->template_data;
      -		}
      -
      -		// store strings to search for
      -		$s = array();
      -		// store replacements for the strings
      -		$r = array();
      -
      -		foreach( $this->found_images as $image ){
      -			if( isset( $image['wp_image_id'] ) ){
      -				$img_id = $image['wp_image_id'];
      -				$local_url = wp_get_attachment_image_src( $img_id, 'full' );
      -				if( !$local_url ){
      -					continue;
      -				}
      -				unset( $image['wp_image_id'] );
      -				$s[] = json_encode( $image );
      -				$r[] = json_encode( array(
      -					'attachment_id' => $img_id,
      -					'url' => $local_url[0]
      -				));
      -				$s[] = $image['url'];
      -				$r[] = $local_url[0];
      -			}
      -		}
      -
      -		return str_replace( $s, $r, $this->template_data );
      -	}
      -}
      \ No newline at end of file
      diff --git a/inc/includes/builder-templates/init.php b/inc/includes/builder-templates/init.php
      deleted file mode 100644
      index a1ce598..0000000
      --- a/inc/includes/builder-templates/init.php
      +++ /dev/null
      @@ -1,23 +0,0 @@
      -<?php if (!defined('FW')) die('Forbidden');
      -// Page Builder Templates
      -
      -/** @internal */
      -function _thz_builder_templates_init() {
      -	
      -	remove_action(
      -		'fw_ext_builder:option_type:builder:before_enqueue',
      -		'_thz_builder_templates_init'
      -	);
      -
      -	require_once get_template_directory().'/inc/includes/builder-templates/class-thz-builder-templates.php';
      -	new ThzBuilderTemplates();
      -}
      -
      -if (defined('DOING_AJAX') && DOING_AJAX) {
      -	_thz_builder_templates_init();
      -} else {
      -	add_action(
      -		'fw_ext_builder:option_type:builder:before_enqueue',
      -		'_thz_builder_templates_init'
      -	);
      -}
      \ No newline at end of file
      diff --git a/inc/includes/builder-templates/static/scripts.js b/inc/includes/builder-templates/static/scripts.js
      deleted file mode 100644
      index 88b0e3e..0000000
      --- a/inc/includes/builder-templates/static/scripts.js
      +++ /dev/null
      @@ -1,409 +0,0 @@
      -(function ($, fwe, _, localized) {
      -	$(document.body).on('fw:option-type:builder:init', function(e, data) {
      -		if (data.type !== 'page-builder') {
      -			return;
      -		}
      -
      -		var prefix = 'thz-theme-';
      -		var inst = {
      -			$el: {
      -				builder: $(e.target),
      -				tooltipContent: $('<div class="'+ prefix +'pred-tpl-tooltip-content"></div>'),
      -				tooltipLoading: $(
      -					'<div class="'+ prefix +'pred-tpl-tooltip-loading">'+
      -					/**/'<div class="loading-icon fa-spin thzicon thzicon-spinner10"></div>'+
      -					'</div>'
      -				),
      -				headerTools: data.$headerTools
      -			},
      -			builder: data.builder,
      -			isBusy: false,
      -			tooltipLoading: {
      -				show: function() {
      -					inst.$el.tooltipContent.prepend(inst.$el.tooltipLoading);
      -				},
      -				hide: function() {
      -					inst.$el.tooltipLoading.detach();
      -					inst.$el.tooltipContent.removeClass('show-content');
      -				}
      -			},
      -			tooltipApi: null, // initialized below
      -			refresh: function() {
      -				if (this.isBusy) {
      -					console.log('Working... Try again later');
      -					return;
      -				} else {
      -					this.isBusy = true;
      -					this.tooltipLoading.show();
      -				}
      -
      -				$.ajax({
      -					type: 'post',
      -					dataType: 'json',
      -					url: ajaxurl,
      -					data: {
      -						'action': prefix +'builder-templates-render'
      -					}
      -				})
      -				.done(_.bind(function(json){
      -					this.isBusy = false;
      -					this.tooltipLoading.hide();
      -
      -					if (!json.success) {
      -						console.error('Failed to render builder templates', json);
      -						return;
      -					}
      -
      -					this.$el.tooltipContent
      -						.html(json.data.html)
      -						.trigger('fw:option-type:page-builder:'+ prefix +'pred-tpl:after-html-replace');
      -				}, this))
      -				.fail(_.bind(function(xhr, status, error){
      -					this.isBusy = false;
      -					this.tooltipLoading.hide();
      -
      -					fw.soleModal.show(
      -						prefix +'templates-error',
      -						'<h4>Ajax Error</h4><p class="fw-text-danger">'+ String(error) +'</p>',
      -						{showCloseButton: false}
      -					);
      -				}, this));
      -			},
      -			load: function (id,cats) {
      -				
      -				var self = this;
      -				
      -				if (this.isBusy) {
      -					console.log('Working... Try again later');
      -					return;
      -				} else {
      -					this.isBusy = true;
      -					this.tooltipLoading.show();
      -				}
      -				
      -				var categories = JSON.parse(cats);
      -				
      -				$.ajax({
      -					type: 'post',
      -					dataType: 'json',
      -					url: ajaxurl,
      -					data: {
      -						'action': prefix +'builder-templates-load',
      -						id: id
      -					}
      -				})
      -				.done(_.bind(function(r){
      -					this.isBusy = false;
      -					//this.tooltipLoading.hide();
      -
      -					if (!r.success) {
      -						console.error('Failed to load template', r);
      -						return;
      -					}
      -
      -					if(categories.hasOwnProperty('pages')){
      -						
      -						var builder_json 	= JSON.parse(r.data.json);
      -						var page_json 		= builder_json[0].pagejson;
      -						var page_template 	= page_json.page_template;
      -						
      -						delete builder_json[0].pagejson;
      -						delete page_json.page_template;
      -						
      -						self.ThzFillTemplate( page_json );
      -						
      -						this.builder.rootItems.reset( builder_json );
      -						
      -						$('#page_template').val( page_template ).trigger('change');
      -						$('#fw-option-pcss').trigger('change');
      -						
      -					}else{
      -						
      -						this.builder.rootItems.add(JSON.parse(r.data.json));
      -					}
      -					
      -					this.tooltipApi.hide();
      -					
      -				}, this))
      -				.fail(_.bind(function(xhr, status, error){
      -					this.isBusy = false;
      -					this.tooltipLoading.hide();
      -
      -					fw.soleModal.show(
      -						prefix +'templates-error',
      -						'<h4>Ajax Error</h4><p class="fw-text-danger">'+ String(error) +'</p>',
      -						{showCloseButton: false}
      -					);
      -				}, this));
      -			},
      -			
      -			force_update: function () {
      -				
      -				var self = this;
      -				
      -				$.ajax({
      -					type: 'post',
      -					dataType: 'json',
      -					url: ajaxurl,
      -					data: {
      -						'action': prefix +'builder-templates-update',
      -					}
      -				})
      -				.done(_.bind(function(r){
      -					
      -					this.isBusy = false;
      -					
      -					if (!r.success) {
      -						console.error('Failed to refresh library', r);
      -						return;
      -					}
      -					
      -					self.refresh();
      -
      -				}, this))
      -				.fail(_.bind(function(xhr, status, error){
      -					this.isBusy = false;
      -					this.tooltipLoading.hide();
      -
      -					fw.soleModal.show(
      -						prefix +'templates-error',
      -						'<h4>Ajax Error</h4><p class="fw-text-danger">'+ String(error) +'</p>',
      -						{showCloseButton: false}
      -					);
      -				}, this));
      -			},
      -
      -			ThzFillTemplate: function($data) {
      -	
      -				var self = this;
      -
      -				if($('#fw-options-box-page_options_box').length < 1){
      -					return;
      -				}
      -	
      -				var $options = $data;
      -
      -				$('.thz-page-options-container .items-wrapper,#fw-option-pcss .items-wrapper').find('.delete-item').trigger('click');
      -				
      -				$.each($options, function(id, json) {
      -	
      -					var $split = id.split('-');
      -					var $realinput = $split[2];
      -					var $option = $('div#fw-backend-option-fw-option-' + $realinput);
      -					var $dataforjs = JSON.parse($option.find('.fw-option-type-addable-popup').attr('data-for-js'));
      -					var $params = JSON.parse($dataforjs.join('{{'));
      -					var title = $params.template;
      -	
      -					if ($realinput == 'custom_pagetitle_options') {
      -	
      -						var $seto_opt = JSON.parse(json);
      -						title = 'Page title mode is: <b>' + $seto_opt.page_title_metrics.mode + '</b>';
      -	
      -					}
      -	
      -					if ($realinput == 'hero') {
      -	
      -						var $seto_opt = JSON.parse(json);
      -						title = 'Hero section is: <b>' + $seto_opt.disable + '</b>';
      -	
      -					}
      -	
      -					if ($realinput == 'custom_footer_options') {
      -	
      -						var $seto_opt = JSON.parse(json);
      -						var $footer_txt = 'Footer and widgets sections';
      -						if($seto_opt.footer_mx.m == 'both'){
      -							
      -							$footer_txt ='Only footer';
      -							
      -						}else if($seto_opt.footer_mx.m == 'widgets'){
      -							
      -							$footer_txt ='Only widgets sections';
      -							
      -						}else if($seto_opt.footer_mx.m == 'hidden'){
      -							
      -							$footer_txt ='Hidden';
      -							
      -						}
      -						
      -						title = 'Custom footer options are active and display mode is: <b>' + $footer_txt + '</b>';
      -	
      -					}
      -					
      -					var new_item = self.ThzNewItemTemplate(id, $realinput, title);
      -	
      -					$option.find('.items-wrapper').html(new_item).show({
      -						duration: 0,
      -						done: function() {
      -	
      -							$('#' + id).attr('value', json);
      -							$option.find('.add-new-item').hide();
      -	
      -						}
      -					});
      -	
      -	
      -				});
      -	
      -			},	
      -			
      -			ThzNewItemTemplate: function(id, name, title) {
      -	
      -				var self = this;
      -	
      -				var new_item = '<div class="item">';
      -				new_item += '<div class="input-wrapper">';
      -				new_item += '<input name="fw_options[' + name + '][]" id="' + id + '" class="fw-option fw-option-type-hidden" value="" type="hidden">';
      -				new_item += '</div>';
      -				new_item += '<div class="content">' + title + '</div>';
      -				new_item += '<a href="#" class="dashicons fw-x delete-item"></a>';
      -				new_item += '</div>';
      -	
      -	
      -				return new_item;
      -			},
      -					
      -		};
      -
      -		inst.$el.headerTools
      -			.removeClass('fw-hidden')
      -			.append(
      -				'<div class="'+ prefix +'pred-tpl-add-btn-wrap fw-pull-right">' +
      -				/**/'<a class="tpl-btn" href="#" onclick="return false;"><span title="'+ localized.l10n.add_button +'"></span></a>' +
      -				'</div>'
      -			);
      -		
      -		
      -		
      -		inst.tooltipApi = inst.$el.headerTools
      -			.find('.'+ prefix +'pred-tpl-add-btn-wrap .tpl-btn')
      -			.qtip({
      -				show: 'click',
      -				hide: 'unfocus',
      -				position: {
      -					at: 'center',
      -					my: 'center',
      -					viewport: $(window),
      -					target: $(window) // my target
      -				},
      -				events: {
      -					show: function () {
      -						
      -						inst.refresh();
      -						
      -					},
      -					hide: function(event, api) {
      -						
      -						inst.$el.tooltipContent.html('');
      -					}
      -				},
      -				style: {
      -					classes: 'qtip-fw qtip-fw-builder '+ prefix +'pred-tpl-qtip',
      -				},
      -				content: {
      -					text: inst.$el.tooltipContent
      -				}
      -			})
      -			.qtip('api');
      -
      -
      -
      -						
      -		inst.$el.tooltipContent.on('fw:option-type:page-builder:'+ prefix +'pred-tpl:after-html-replace', function (e) {
      -				
      -				var $this = $(this);
      -				
      -				setTimeout(function(){
      -					$this.addClass('show-content');
      -				},50);
      -				
      -				
      -			$('.'+ prefix +'pred-tpl-cat li a').each(function(index, element) {
      -				
      -					var $cat = $(element).attr('data-val');
      -					
      -					if ($cat.length) {
      -						var $count = $('.thz-theme-pred-tpl-item-img.' + $cat).length;
      -						$(element).find('.'+ prefix +'items-count').text($count);
      -					}
      -					
      -				
      -			});
      -		});	
      -		
      -		
      -		inst.$el.tooltipContent
      -			.on('click', '.'+ prefix +'pred-tpl-cat li a', function (e) {
      -				e.preventDefault();
      -				
      -				$('.'+ prefix +'pred-tpl-cat li a').removeClass('active');
      -				$(this).addClass('active');
      -				
      -				var cat = $(this).attr('data-val'),
      -					$thumbs = inst.$el.tooltipContent.find('.'+ prefix +'pred-tpl-thumb-list .'+ prefix +'pred-tpl-thumb');
      -
      -				if (!cat.length) { // show all
      -					$thumbs.removeClass('fw-hidden');
      -				} else { // show one category
      -					$thumbs.each(function(){
      -						var $thumb = $(this),
      -							categs = JSON.parse($thumb.attr('data-categs'));
      -
      -						$thumb[ (typeof categs[cat] === 'undefined') ? 'addClass' : 'removeClass' ]('fw-hidden');
      -					});
      -				}
      -			})
      -			.on('click', '.'+ prefix +'pred-tpl-thumb-list .'+ prefix +'pred-tpl-thumb .'+ prefix +'pred-tpl-item-img > img', function (e) {
      -				
      -				var $thumb_item = $(this).closest('.'+ prefix +'pred-tpl-thumb'),
      -					$thumb_id = $thumb_item.attr('data-id'),
      -					$thumb_cats = $thumb_item.attr('data-categs');
      -					
      -				inst.load($thumb_id,$thumb_cats);
      -				
      -			})
      -			.on('fw:option-type:page-builder:'+ prefix +'pred-tpl:after-html-replace', function(){
      -				//
      -				var $tsearch = $('#tsearch');
      -				
      -				$tsearch.hideseek({
      -					highlight: true,
      -					nodata: 'No results found'
      -				});
      -				
      -				$tsearch.on("input", function(){
      -					$(this).parent().addClass('searching');
      -				});
      -				
      -				$('.clear-tsearch').on("click", function(e){
      -					e.preventDefault();
      -					 var kp = jQuery.Event("keyup"); 
      -					 kp.which = kp.keyCode = 8;
      -					$tsearch.val('').trigger(kp);
      -					$tsearch.parent().removeClass('searching');
      -				});
      -				
      -				$('.'+ prefix +'pred-tpl-item-img').on({
      -					mouseenter: function() {
      -						$(this).parents('.'+ prefix +'pred-tpl-thumb').addClass('active');
      -					},
      -					mouseleave: function() {
      -						$(this).parents('.'+ prefix +'pred-tpl-thumb').removeClass('active');
      -					}
      -				});
      -				
      -			}).on('click', '.'+ prefix +'pred-tpl-lib-update .force-update', function (e) {
      -				
      -				e.preventDefault();
      -				
      -				inst.force_update();
      -				
      -/*				var $thumb_item = $(this).closest('.'+ prefix +'pred-tpl-thumb'),
      -					$thumb_id = $thumb_item.attr('data-id'),
      -					$thumb_cats = $thumb_item.attr('data-categs');
      -					
      -				inst.load($thumb_id,$thumb_cats);*/
      -				
      -			});
      -	});
      -})(jQuery, fwEvents, _, _theme_pb_pred_tpl);
      \ No newline at end of file
      diff --git a/inc/includes/builder-templates/static/styles.css b/inc/includes/builder-templates/static/styles.css
      deleted file mode 100644
      index 868316e..0000000
      --- a/inc/includes/builder-templates/static/styles.css
      +++ /dev/null
      @@ -1,438 +0,0 @@
      -.qtip.qtip-fw.thz-theme-pred-tpl-qtip {
      -	background: #fbfbfb;
      -	border: none;
      -	box-shadow: 0px 0px 40px 0px rgba(0, 0, 0, 0.25);
      -	padding: 0;
      -}
      -.qtip.qtip-fw.thz-theme-pred-tpl-qtip {
      -	width: 85%;
      -	height: 85%;
      -	min-width:400px;
      -	min-height:400px;
      -}
      -.qtip.qtip-fw.thz-theme-pred-tpl-qtip,
      -.qtip.qtip-fw.thz-theme-pred-tpl-qtip * {
      -	box-sizing: border-box;
      -}
      -.thz-theme-pred-tpl-tooltip-content {
      -	padding: 0;
      -	position: relative;
      -	height: 100%;
      -}
      -.thz-theme-pred-tpl-qtip .qtip-content .thz-theme-pred-tpl-tooltip-loading {
      -	position: absolute;
      -	top: 0;
      -	left: 0;
      -	width: 100%;
      -	height: 100%;
      -	background: #fbfbfb;
      -	z-index: 2;
      -}
      -.thz-theme-pred-tpl-qtip .qtip-content .thz-theme-pred-tpl-tooltip-loading .loading-icon {
      -	display: block;
      -	position: relative;
      -	top: 50%;
      -	margin: -15px auto 0 auto;
      -	font-size: 32px;
      -	text-align: center;
      -}
      -/* end: loading */
      -
      -
      -.thz-theme-pred-tpl-qtip.qtip.qtip-fw .qtip-content {
      -	text-align: left;
      -	font-style: normal;
      -	display: block;
      -	height: 100%;
      -}
      -.thz-theme-pred-tpl-container {
      -	display: block;
      -	position: relative;
      -	opacity: 0;
      -	height: 100%;
      -	-webkit-transition: opacity 0.3s ease-in-out;
      -	transition: opacity 0.3s ease-in-out;
      -}
      -.show-content .thz-theme-pred-tpl-container {
      -	opacity: 1;
      -}
      -.thz-theme-pred-tpl-holder {
      -	display: block;
      -	position: relative;
      -	overflow: hidden;
      -	height: 100%;
      -	overflow-y: auto;
      -}
      -
      -.thz-theme-pred-tpl-menu-title{
      -	text-align:center;
      -	margin: 30px 0 10px 0;
      -	display:block;
      -	overflow:hidden;
      -	padding: 0 30px;
      -}
      -.thz-theme-pred-tpl-cat-avatar img{
      -	border-radius:100%;
      -}
      -.thz-theme-pred-tpl-cat-avatar span.thzicon{
      -	font-size:48px;
      -}
      -.thz-theme-pred-tpl-menu-title span.title{
      -	font-size: 14px;
      -	font-weight:600;
      -	color: #0c0e10;
      -	display:block;
      -	clear:both;
      -	margin: 15px 0 0px 0;
      -	text-transform: uppercase;
      -}
      -.tsearch-container{
      -	display:block;
      -	overflow:hidden;
      -	padding:0;
      -	position:relative;
      -	margin: 15px 0 0 0;
      -}
      -input[type="text"]#tsearch{
      -	margin:0;
      -	border-radius:4px;
      -	border: 1px solid #f2f2f2;
      -	border-radius: 4px;
      -	box-shadow: inset 0px 0px 8px 0px rgba(0, 0, 0, 0.03);
      -	background-color: #ffffff;
      -	font-size: 14px;
      -	width: 100%;
      -	padding: 7px 10px;
      -}
      -input[type="text"]#tsearch:focus{
      -	border-color:#ccc;
      -}
      -#tsearch::-webkit-input-placeholder {
      -  color: #d5d5d5;
      -  font-style:italic;
      -}
      -#tsearch::-moz-placeholder {
      -  color: #d5d5d5;
      -  font-style:italic;
      -}
      -#tsearch:-ms-input-placeholder {
      -  color: #d5d5d5;
      -  font-style:italic;
      -}
      -#tsearch:-moz-placeholder {
      -  color: #d5d5d5;
      -  font-style:italic;
      -}
      -
      -.tsearch-container a.clear-tsearch,
      -.tsearch-container a.clear-tsearch:focus,
      -.tsearch-container a.clear-tsearch:hover{
      -	visibility:hidden;
      -	color:#aaa;
      -	text-decoration:none;
      -	font-size:14px;
      -	position:absolute;
      -	top: 10px;
      -	right: 10px;
      -	margin:0 0 0 5px;
      -	box-shadow:none;
      -}
      -.searching.tsearch-container a.clear-tsearch{
      -	visibility:visible;
      -}
      -.thz-theme-pred-tpl-qtip .qtip-content .thz-theme-pred-tpl-cat {
      -	position: absolute;
      -	top: 0;
      -	left: 0;
      -	bottom: 0;
      -	padding: 20px;
      -	width: 280px;
      -}
      -.thz-theme-pred-tpl-menu-holder {
      -	background: #fff;
      -	position: absolute;
      -	top: 0;
      -	left: 0;
      -	bottom: 0;
      -	right: 0;
      -	overflow-y:auto;
      -	box-shadow: 10px 0 40px rgba(0, 0, 0, 0.04);
      -}
      -.thz-theme-pred-tpl-cat-select {
      -	padding: 30px;
      -	margin: 0;
      -	display: block;
      -}
      -.thz-theme-pred-tpl-cat-select li {
      -	padding:0;
      -	cursor: pointer;
      -	position: relative;
      -	margin: 0;
      -}
      -.thz-theme-pred-tpl-qtip .thz-theme-pred-tpl-cat-select li a {
      -	text-decoration: none;
      -	color: #afafaf;
      -	font-size: 14px;
      -	display: block;
      -	position: relative;
      -	font-weight: 400;
      -	padding: 0 0 22px 0;
      -	-o-transition: color .2s ease-in-out;
      -	-ms-transition: color .2s ease-in-out;
      -	-moz-transition: color .2s ease-in-out;
      -	-webkit-transition: color .2s ease-in-out;
      -	transition: color .2s ease-in-out;
      -}
      -.thz-theme-pred-tpl-qtip .thz-theme-pred-tpl-cat-select li a:hover,
      -.thz-theme-pred-tpl-qtip .thz-theme-pred-tpl-cat-select li a.active {
      -	color: #0c0e10;
      -	box-shadow: none;
      -}
      -.thz-theme-items-count {
      -	float: right;
      -	padding: 2px 8px;
      -	color: #a1a1a1;
      -	position: absolute;
      -	right: 0px;
      -	top: 0;
      -	border-radius: 4px;
      -	background: #f2f2f2;
      -	font-size: 11px;
      -	font-weight: 400;
      -}
      -.thz-theme-pred-tpl-qtip .thz-theme-pred-tpl-cat-select li a:hover span,
      -.thz-theme-pred-tpl-qtip .thz-theme-pred-tpl-cat-select li a.active span {
      -	-o-transition: background .2s ease-in-out;
      -	-ms-transition: background .2s ease-in-out;
      -	-moz-transition: background .2s ease-in-out;
      -	-webkit-transition: background .2s ease-in-out;
      -	transition: background .2s ease-in-out;
      -}
      -.thz-theme-pred-tpl-qtip .qtip-content .thz-theme-pred-tpl-thumb-list {
      -	min-height: 500px;
      -	overflow-y: auto;
      -	width: 100%;
      -	height: 100%;
      -	padding: 0 60px 60px 280px;
      -}
      -.thz-theme-pred-tpl-lib-update{
      -	position:absolute;
      -	top:20px;
      -	right:40px;
      -}
      -.thz-theme-pred-tpl-lib-update .last-update{
      -	font-size:13px;
      -	font-weight:600;
      -	display:inline-block;
      -	margin:0 20px 0 0;
      -}
      -.qtip-fw .thz-theme-pred-tpl-lib-update .force-update,
      -.qtip-fw .thz-theme-pred-tpl-lib-update .force-update:hover,
      -.qtip-fw .thz-theme-pred-tpl-lib-update .force-update:focus{
      -	text-decoration:none;
      -	border:none;
      -	box-shadow:none;
      -}
      -.qtip-fw .thz-theme-pred-tpl-lib-update .force-update:hover{
      -	opacity:0.7;
      -}
      -
      -.thz-theme-pred-tpl-qtip .qtip-content .thz-theme-pred-tpl-thumb-list-inner {
      -	position: relative;
      -	display:flex;
      -	flex-wrap:wrap;
      -	flex-direction:row;
      -	justify-content:flex-start;
      -	align-items: stretch;
      -}
      -.thz-theme-pred-tpl-thumb {
      -	padding: 0;
      -	margin: 0;
      -	box-sizing: border-box;
      -	width: 50%;
      -	float: left;
      -	padding: 0 0 0 60px;
      -	margin-top: 60px;
      -    position: relative;
      -    z-index: 1;
      -}
      -
      -.thz-theme-pred-tpl-thumb-in{
      -	position: relative;
      -	padding: 0px;
      -	margin: 0;
      -	background:#fff;
      -	border-radius:4px;
      -	box-shadow: 0 1px 50px rgba(0, 0, 0, 0.1);
      -	-webkit-transition: all 0.6s cubic-bezier(0.165, 0.84, 0.44, 1);
      -	transition: all 0.6s cubic-bezier(0.165, 0.84, 0.44, 1);
      -}
      -.thz-theme-pred-tpl-thumb-in::before {
      -	content: "";
      -	border-radius: 5px;
      -	position: absolute;
      -	z-index: -1;
      -	top: 0;
      -	left: 0;
      -	width: 100%;
      -	height: 100%;
      -	box-shadow: 0px 4px 20px 2px rgba(0, 0, 0, 0.1);
      -	opacity: 0;
      -	-webkit-transition: all 0.6s cubic-bezier(0.165, 0.84, 0.44, 1);
      -	transition: all 0.6s cubic-bezier(0.165, 0.84, 0.44, 1);
      -	backface-visibility: hidden;
      -}
      -.active:not(.thz-get-cp) .thz-theme-pred-tpl-thumb-in {
      -	-webkit-transform: translateY(-8px) translateZ(0);
      -	transform: translateY(-8px) translateZ(0);
      -}
      -.active .thz-theme-pred-tpl-thumb-in::before {
      -	opacity: 1;
      -}
      -.thz-theme-pred-tpl-item-title {
      -	position: relative;
      -	font-size: 18px;
      -	line-height:1.618;
      -	font-weight: 600;
      -	color: #0c0e10;
      -	text-align: left;
      -	text-transform:capitalize;
      -	padding: 30px 60px 30px 30px;
      -	box-shadow: 0 -20px 40px rgba(0, 0, 0, 0.01);
      -    -o-transition:  color .2s ease-in-out,background .2s ease-in-out,border-color .2s ease-in-out;
      -    -ms-transition: color .2s ease-in-out,background .2s ease-in-out,border-color .2s ease-in-out;
      -    -moz-transition:  color .2s ease-in-out,background .2s ease-in-out,border-color .2s ease-in-out;
      -    -webkit-transition: color .2s ease-in-out,background .2s ease-in-out,border-color .2s ease-in-out;
      -    transition: color .2s ease-in-out,background .2s ease-in-out,border-color .2s ease-in-out;
      -	will-change: transition;
      -}
      -.thz-theme-pred-tpl-item-cats{
      -	font-size:10px;
      -	color:#b7b7b7;
      -	text-transform:uppercase;
      -	letter-spacing:1px;
      -}
      -
      -/* colors */
      -.thz-theme-pred-tpl-cat-avatar span.thzicon,
      -.thz-theme-pred-tpl-thumb.active .thz-theme-pred-tpl-item-title{
      -	color: #039bf4;
      -}
      -.thz-theme-pred-tpl-qtip .thz-theme-pred-tpl-cat-select li a:hover span,
      -.thz-theme-pred-tpl-qtip .thz-theme-pred-tpl-cat-select li a.active span {
      -	color: #fff;
      -	background: #039bf4;
      -}
      -.thz-theme-pred-tpl-qtip .qtip-content .thz-theme-pred-tpl-tooltip-loading .loading-icon {
      -	color: #039bf4;
      -}
      -.thz-theme-pred-tpl-lib-update .last-update{
      -	color:#bebebe;
      -}
      -.qtip-fw .thz-theme-pred-tpl-lib-update .force-update{
      -	color:#039bf4;
      -}
      -
      -.thz-theme-pred-tpl-item-img {
      -	position: relative;
      -	display: block;
      -	border-top-left-radius: inherit;
      -	border-top-right-radius: inherit;
      -	width: 100%;
      -	padding-bottom: 66.66666666666667%;
      -}
      -
      -.thz-theme-pred-tpl-item-img:before {
      -    font-family: 'Thzicons' !important;
      -    content: "\eeda";
      -    color: #aac2d0;
      -    position: absolute;
      -    margin: 0px 0 0 -12px;
      -    display: block;
      -    speak: none;
      -    font-style: normal;
      -    font-weight: normal;
      -    font-variant: normal;
      -    text-transform: none;
      -    line-height: 27px;
      -    top: 50%;
      -    left: 50%;
      -    font-size: 24px;
      -    -webkit-animation: fa-spin 1s infinite linear;
      -    animation: fa-spin 1s infinite linear;
      -}
      -
      -.thz-theme-pred-tpl-item-img:after {
      -	content: "";
      -	display: table;
      -	clear: both;
      -}
      -.thz-theme-pred-tpl-item-img img {
      -	width: 100%;
      -	height: auto;
      -	display: block;
      -	position:absolute;
      -	top:0;
      -	right:0;
      -	bottom:0;
      -	left:0;
      -	cursor: pointer;
      -	border-radius: inherit;
      -}
      -
      -.thz-theme-get-cp{
      -	display:block;
      -	position:absolute;
      -	top:0;
      -	left:0;
      -	right:0;
      -	bottom:0;
      -	z-index:1;
      -}
      -.thz-get-cp a.thz-theme-get-cp-link{
      -	text-decoration:none;
      -	color:#fff;
      -	background: #29d089;
      -	padding: 5px 8px;
      -	display:inline-block;
      -	font-size: 10px;
      -	font-weight:500;
      -	position:absolute;
      -	bottom: 10px;
      -	right: 10px;
      -	text-transform: uppercase;
      -	margin:0;
      -	border-radius:4px;
      -	transition: all 0.4s ease-in-out;
      -}
      -.thz-get-cp a.thz-theme-get-cp-link:hover{
      -	background-color: #23bd7b;
      -}
      -.thz-get-cp.active .thz-theme-get-cp-link{
      -	opacity:1;
      -}
      -
      -@media (min-width: 1820px) {
      -	.thz-theme-pred-tpl-thumb {
      -		width: 33.333333%;
      -	}
      -}
      -@media (max-width: 1200px) {
      -	.thz-theme-pred-tpl-thumb {
      -		width: 100%;
      -	}
      -}
      -@media (max-width: 767px) {
      -	.thz-theme-pred-tpl-qtip .qtip-content .thz-theme-pred-tpl-thumb-list {
      -		padding-left: 0;
      -	}
      -	.thz-theme-pred-tpl-qtip .qtip-content .thz-theme-pred-tpl-cat {
      -		position: relative;
      -		padding: 20px;
      -		margin: 0 auto;
      -		width: 80%;
      -	}
      -	.thz-theme-pred-tpl-menu-holder {
      -		position: relative;
      -	}
      -}
      \ No newline at end of file
      diff --git a/inc/includes/builder-templates/views/index.html b/inc/includes/builder-templates/views/index.html
      deleted file mode 100644
      index e69de29..0000000
      diff --git a/inc/includes/builder-templates/views/sections.php b/inc/includes/builder-templates/views/sections.php
      deleted file mode 100644
      index 71b38ae..0000000
      --- a/inc/includes/builder-templates/views/sections.php
      +++ /dev/null
      @@ -1,87 +0,0 @@
      -<?php if (!defined('FW')) die('Forbidden');
      -/**
      - * @var array $sections
      - * @var array $sections_categories
      - */
      -
      -$prefix = 'thz-theme-';
      -$select_id = $prefix . fw_rand_md5();
      -ksort($sections,SORT_NATURAL);
      -ksort($sections_categories);
      -$current_user = wp_get_current_user();// phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited
      -$avatar = get_avatar($current_user->ID, 60 ); 
      -$avatar	= $avatar ? $avatar : '<span class="thzicon thzicon-creatus"></span>';
      -?>
      -<div class="<?php echo $prefix; ?>pred-tpl-container">
      -    <div class="<?php echo $prefix; ?>pred-tpl-holder">
      -        <?php if ($sections_categories): ?>
      -            <div class="<?php echo $prefix; ?>pred-tpl-cat">
      -                <div class="<?php echo $prefix; ?>pred-tpl-menu-holder">
      -                	<div class="<?php echo $prefix; ?>pred-tpl-menu-title">
      -                		<div class="<?php echo $prefix; ?>pred-tpl-cat-avatar">
      -                        	<?php echo $avatar ?>
      -                        </div>
      -                        <span class="title"><?php esc_html_e('Template Library', 'creatus') ?></span>
      -                        <div class="tsearch-container">
      -                        	<input id="tsearch" name="search" class="tsearch" placeholder="<?php esc_html_e('Quick search', 'creatus') ?>" type="text" data-list=".thz-theme-pred-tpl-thumb-list-inner">
      -                            <a href="#" class="dashicons dashicons-dismiss clear-tsearch"></a>
      -                        </div>
      -                    </div>
      -                    <ul id="<?php echo esc_attr($select_id) ?>" class="<?php echo $prefix; ?>pred-tpl-cat-select">
      -                        <li>
      -                            <a class="active" href="#" data-val="">
      -                                <?php esc_html_e('All Categories', 'creatus') ?> 
      -                                <span class="<?php echo $prefix; ?>items-count"><?php echo count($sections) ?></span>
      -                            </a>
      -                        </li>
      -                        <?php foreach ($sections_categories as $cat_id => $cat_title): // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited ?>
      -                            <li>
      -                                <a href="#" data-val="<?php echo esc_attr($cat_id) ?>">
      -                                    <?php echo esc_html($cat_title) ?> 
      -                                    <span class="<?php echo $prefix; ?>items-count"></span>
      -                                </a>
      -                            </li>
      -                        <?php endforeach; ?>
      -                    </ul>
      -                </div>
      -            </div>
      -        <?php endif; ?>
      -        <?php if ($sections): ?>
      -            <div class="<?php echo $prefix; ?>pred-tpl-thumb-list">
      -            	<div class="<?php echo $prefix; ?>pred-tpl-thumb-list-inner">
      -                <?php foreach ($sections as $section_id => $section): $get_cp = isset($section['type']) && !$cpac ? ' thz-get-cp' :'';?>
      -                    <div class="<?php echo $prefix; ?>pred-tpl-thumb<?php echo $get_cp; ?>" data-categs="<?php echo fw_htmlspecialchars(json_encode(array_fill_keys(array_keys($section['categories']), true))) ?>" data-id="<?php echo esc_attr($section_id) ?>">
      -                    	<div class="<?php echo $prefix; ?>pred-tpl-thumb-in">
      -                            <div class="<?php echo $prefix; ?>pred-tpl-item-img <?php echo implode(' ',array_keys($section['categories'])) ?>">
      -                            <?php if ( isset($section['type']) && !$cpac ): ?>
      -                             <div class="<?php echo $prefix; ?>get-cp">
      -                             </div>
      -                             <?php endif; ?>
      -                            <img src="<?php echo esc_attr( $section['thumbnail'] ) ?>" alt="<?php echo esc_attr($section['desc']) ?>" title="<?php echo esc_attr($section['desc']) ?>" /></div>			
      -                            <div class="<?php echo $prefix; ?>pred-tpl-item-title">
      -                                <?php if ( isset($section['type']) && !$cpac ): ?>
      -                                 <a class="<?php echo $prefix; ?>get-cp-link" href="https://themezly.com/pricing/" target="_blank">
      -                                    <?php esc_html_e('Go Pro', 'creatus') ?>
      -                                 </a>
      -                                <?php endif; ?>
      -                            	<span class="<?php echo $prefix; ?>pred-tpl-item-desc">
      -									<?php echo esc_attr($section['desc']) ?>
      -                                </span>
      -                            	<div class="<?php echo $prefix; ?>pred-tpl-item-cats"><?php echo implode(',',array_keys($section['categories'])) ?></div>
      -                            </div>
      -                        </div>
      -                    </div>
      -                <?php endforeach; ?>
      -                </div>
      -                <?php if( $can_update ) : ?>
      -                <div class="<?php echo $prefix; ?>pred-tpl-lib-update">
      -                    <span class="last-update"><?php echo esc_html__('Last updated', 'creatus').' '. thz_ago( $last_update ) ?></span>
      -                    <a href="#" class="force-update" title="<?php esc_html_e('Force Library Update', 'creatus') ?>">
      -                    	<span class="dashicons dashicons-update"></span>
      -                    </a>
      -                </div>
      -                <?php endif; ?>
      -            </div>
      -        <?php endif; ?>
      -    </div>
      -</div>
      \ No newline at end of file
      diff --git a/inc/includes/class-thz-demos.php b/inc/includes/class-thz-demos.php
      deleted file mode 100644
      index e1bc7dd..0000000
      --- a/inc/includes/class-thz-demos.php
      +++ /dev/null
      @@ -1,135 +0,0 @@
      -<?php
      -/**
      - * @package      Thz Framework
      - * @author       Themezly
      - * @license      http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 only
      - * @websites     http://www.themezly.com | http://www.youjoomla.com | http://www.yjsimplegrid.com
      - */
      - 
      -if ( ! defined( 'ABSPATH' ) ) {
      -	exit; // No direct access
      -}
      -
      -class ThzDemos {
      -
      -    /**
      -     * Global instance object
      -     */
      -    private static $_instance = null;
      -
      -    /**
      -     * API url
      -     */   	
      -	private $api_uri;
      -
      -	/**
      -	 * Allow or bypass request cache
      -	 * @var bool - allow cache (false) or bypass it (true)
      -	 */
      -	private $no_cache;
      -	
      -    /**
      -     * Transient name
      -     */   	
      -	private $transient;
      -	
      -
      -    /**
      -     * Last update option
      -     */   	
      -	private $last_update;
      -
      -	/**
      -	 * ThzBuilderTemplates constructor.
      -	 */
      -	public function __construct() {
      -		
      -		$this->no_cache 	= apply_filters( '_thz_filter_demos_list_no_cache', false );
      -		$this->api_uri 		= apply_filters( '_thz_filter_demos_api_url', 'https://resources.themezly.io/api/v1/demos' );
      -		$this->transient 	= 'thz:demos:list';
      -		$this->last_update 	= 'thz:demos:list:last:update';
      -		
      -		add_action('wp_ajax_thz_refresh_demos_list', array($this, 'demos_list_refresh'));
      -
      -	}
      -	
      -    /**
      -     * Returns the class instance
      -     *
      -     * @return  Thz_Doc instance
      -     *
      -     * @since   1.0.0
      -     */
      -    
      -    public static function getInstance() {
      -        
      -        if ( self::$_instance == null ) {
      -            self::$_instance = new ThzDemos();
      -        }
      -        return self::$_instance;
      -    }
      -	
      -	
      -	public function demos_list(){
      -		
      -		$transient = $this->transient;
      -
      -		if ( $this->no_cache || false === ( $demos_list = get_transient( $transient ) ) ) {
      -			
      -			delete_transient( $transient );
      -			
      -			$response = wp_remote_get( $this->api_uri , array( 'timeout' => 20 ) );
      -			$httpCode = wp_remote_retrieve_response_code( $response );
      -	
      -			if ( $httpCode >= 200 && $httpCode < 300 ) {
      -				
      -				$demos_list = wp_remote_retrieve_body( $response );
      -				
      -			} else {
      -				
      -				$demos_list = esc_html__( 'Not able to load demos', 'creatus' );
      -				
      -			}
      -			
      -			update_option ($this->last_update, time() );
      -			set_transient( $transient, $demos_list, 7 * DAY_IN_SECONDS );
      -		
      -		}
      -
      -		$data = json_decode($demos_list ,true );
      -
      -		return $data;
      -							
      -	}	
      -	
      -	public function demos_list_refresh(){
      -		
      -		$transient = $this->transient;
      -		
      -		if( $this->can_refresh() && delete_transient( $transient )){
      -
      -			wp_send_json_success();
      -			
      -		}else{
      -			
      -			wp_send_json_error();
      -			
      -		}
      -		
      -	}
      -		
      -	public function can_refresh(){
      -		
      -		$last_update = get_option($this->last_update, 0);
      -		
      -		if( $this->no_cache || $last_update <= strtotime('-15 minutes') ){
      -			
      -			return true;
      -		}
      -		
      -		return false;
      -	}
      -
      -}
      -
      -ThzDemos::getInstance();
      \ No newline at end of file
      diff --git a/inc/includes/option-types/thz-typography/class-fw-option-type-thz-typography.php b/inc/includes/option-types/thz-typography/class-fw-option-type-thz-typography.php
      index 708b49b..25aab53 100644
      --- a/inc/includes/option-types/thz-typography/class-fw-option-type-thz-typography.php
      +++ b/inc/includes/option-types/thz-typography/class-fw-option-type-thz-typography.php
      @@ -387,26 +387,31 @@ public function _get_current_font_data( $font, $subset, $return = 'variants'){
       			'subsets' => false
       		);
       		
      -		// typekit
      -		if( $subset == 'default' || $subset == 'all'){
      +		if( thz_creatus_extended() ){
       			
      -			$imported  	= get_option('thz_imported_fonts');
      -			$slug		= thz_typekit_slug($font);
      -			$current_data['variants'] 	= thz_akg('tykfonts/fonts_data/'.$slug.'/variations',$imported,false);
      -			$current_data['subsets'] 	= array($subset);
      -			
      -			return $current_data[$return];
      -		}
      -		
      -		// fontsquirell
      -		if( $subset == 'fsq' ){
      +			// typekit
      +			if( $subset == 'default' || $subset == 'all'){
      +				
      +				$imported  	= get_option('thz_imported_fonts');
      +				$slug		= thz_typekit_slug($font);
      +				$current_data['variants'] 	= thz_akg('tykfonts/fonts_data/'.$slug.'/variations',$imported,false);
      +				$current_data['subsets'] 	= array($subset);
      +				
      +				return $current_data[$return];
      +			}
       			
      -			$imported  	= get_option('thz_imported_fonts');
      -			$variants 	= thz_akg('fsqfonts/'.$font,$imported,false);
      -			$current_data['variants'] 	= $variants ? array_keys($variants) : array();
      -			$current_data['subsets'] 	= array($subset);
       			
      -			return $current_data[$return];
      +			// fontsquirell
      +			if( $subset == 'fsq' ){
      +				
      +				$imported  	= get_option('thz_imported_fonts');
      +				$variants 	= thz_akg('fsqfonts/'.$font,$imported,false);
      +				$current_data['variants'] 	= $variants ? array_keys($variants) : array();
      +				$current_data['subsets'] 	= array($subset);
      +				
      +				return $current_data[$return];
      +			}
      +		
       		}
       
       		// fontfacekit
      diff --git a/inc/includes/utilities/customizer/customizer-defaults.php b/inc/includes/utilities/customizer/customizer-defaults.php
      new file mode 100644
      index 0000000..2f88532
      --- /dev/null
      +++ b/inc/includes/utilities/customizer/customizer-defaults.php
      @@ -0,0 +1,205 @@
      +<?php
      +/**
      + * @package      Thz Framework
      + * @author       Themezly
      + * @license      http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 only
      + * @websites     http://www.themezly.com | http://www.youjoomla.com | http://www.yjsimplegrid.com
      + */
      + 
      +if ( ! defined( 'ABSPATH' ) ) {
      +	exit; // No direct access
      +}
      +/**
      + * https://gist.github.com/NateWr/5fd00beb412f78776e9d
      +*/
      +class Thz_Customizer_Notice_Control extends WP_Customize_Control {
      +	/**
      +	* Control type
      +	*/
      +	public $type = 'thz_customizer_notice';
      +	/**
      +	* HTML content to display
      +	*/
      +	public $content = '';
      +	public function render_content() {
      +	?>
      +    <div class="notice notice-success">
      +		<?php if ( !empty( $this->label ) ) :	?>
      +        <div class="customize-control-title">
      +            <?php echo esc_html( $this->label ); ?>
      +        </div>
      +        <?php endif; ?>
      +        <p>
      +            <?php echo $this->content; ?>
      +        </p>
      +    </div>     
      +		<?php 
      +	}
      +	
      +}
      +
      +/**
      + * Default customizer options if framework is not active
      + */
      +function thz_action_default_customizer_options( $wp_customize ){
      +	
      +	$wp_customize->add_panel( 'creatus_default', array(
      +		'priority' => 30,
      +		'capability' => 'edit_theme_options',
      +		'title' => __('Theme Options', 'creatus'),
      +		'description' => __('Customize the login of your website.', 'creatus'),
      +	));	
      +	
      +	// hero section
      +	$wp_customize->add_section('creatus_default_hero', array(
      +		'priority' => 5,
      +		'title' => __('Hero Section', 'creatus'),
      +		'panel' => 'creatus_default',
      +	));
      +	
      +	// advise that recommended plugins are not installed
      +	$wp_customize->add_control(
      +		new Thz_Customizer_Notice_Control(
      +			$wp_customize,
      +			'hero_notice',
      +			array(
      +				'label'     => __( 'Install Recomended Plugins', 'creatus' ),
      +				'section'   => 'creatus_default_hero',
      +				'settings'   => array(),
      +				'content'   => sprintf(
      +					// Translators: 1 and 2 wrap a link to plugins installation utility.
      +					__( 'This is a default customizer setup. For advanced theme options Install and activate %1$srecommended plugins%2$s.', 'creatus' ),
      +					'<a href="' . esc_url( admin_url( 'themes.php?page=creatus-install-plugins' ) ) . '">',
      +					'</a>'
      +				),
      +			)
      +		)
      +	);
      +	
      +	// before title
      +	$wp_customize->add_setting('creatus_before_hero_title', array(
      +		'default'        => '',
      +        'capability'     => 'edit_theme_options',
      +        'type'           => 'option',
      +		'sanitize_callback' => 'esc_attr'
      +	));
      +	$wp_customize->add_control('creatus_before_hero_title', array(
      +		'label'   => __('Before Title', 'creatus'),
      +		'section' => 'creatus_default_hero',
      +		'type'    => 'text',
      +		'description' => __( 'Add text before hero section title.', 'creatus' )
      +	));
      +	
      +	// title
      +	$wp_customize->add_setting('creatus_hero_title', array(
      +		'default'        => '',
      +        'capability'     => 'edit_theme_options',
      +        'type'           => 'option',
      +		'sanitize_callback' => 'esc_attr'
      +	));
      +	$wp_customize->add_control('creatus_hero_title', array(
      +		'label'   => __('Hero Title', 'creatus'),
      +		'section' => 'creatus_default_hero',
      +		'type'    => 'text',
      +		'description' => __( 'Add hero section title.', 'creatus' )
      +	));	
      +	
      +	// subtitle
      +	$wp_customize->add_setting('creatus_hero_subtitle', array(
      +		'default'        => '',
      +        'capability'     => 'edit_theme_options',
      +        'type'           => 'option',
      +		'sanitize_callback' => 'esc_attr'
      +	));
      +	$wp_customize->add_control('creatus_hero_subtitle', array(
      +		'label'   => __('Sub Title', 'creatus'),
      +		'section' => 'creatus_default_hero',
      +		'type'    => 'text',
      +		'description' => __( 'Add hero section sub title', 'creatus' )
      +	));
      +	
      +	// button text
      +	$wp_customize->add_setting('creatus_hero_button_text', array(
      +		'default'        => '',
      +        'capability'     => 'edit_theme_options',
      +        'type'           => 'option',
      +		'sanitize_callback' => 'esc_attr'
      +	));
      +	$wp_customize->add_control('creatus_hero_button_text', array(
      +		'label'   => __('Button text', 'creatus'),
      +		'section' => 'creatus_default_hero',
      +		'type'    => 'text',
      +		'description' => __( 'Add hero button text', 'creatus' )
      +	));
      +
      +	// button link
      +	$wp_customize->add_setting('creatus_hero_button_link', array(
      +		'default'        => '',
      +        'capability'     => 'edit_theme_options',
      +        'type'           => 'option',
      +		'sanitize_callback' => 'esc_attr'
      +	));
      +	$wp_customize->add_control('creatus_hero_button_link', array(
      +		'label'   => __('Button link', 'creatus'),
      +		'section' => 'creatus_default_hero',
      +		'type'    => 'text',
      +		'description' => __( 'Add hero button link', 'creatus' )
      +	));
      +		
      +	// branding section
      +	$wp_customize->add_section('creatus_default_branding', array(
      +		'priority' => 6,
      +		'title' => __('Branding', 'creatus'),
      +		'panel' => 'creatus_default',
      +	));	
      +
      +	// advise that recommended plugins are not installed
      +	$wp_customize->add_control(
      +		new Thz_Customizer_Notice_Control(
      +			$wp_customize,
      +			'branding_notice',
      +			array(
      +				'label'     => __( 'Install Recomended Plugins', 'creatus' ),
      +				'section'   => 'creatus_default_branding',
      +				'settings'   => array(),
      +				'content'   => sprintf(
      +					// Translators: 1 and 2 wrap a link to plugins installation utility.
      +					__( 'This is a default customizer setup. For advanced theme options Install and activate %1$srecommended plugins%2$s.', 'creatus' ),
      +					'<a href="' . esc_url( admin_url( 'themes.php?page=creatus-install-plugins' ) ) . '">',
      +					'</a>'
      +				),
      +			)
      +		)
      +	);
      +		
      +	// branding text
      +	$wp_customize->add_setting('creatus_branding_text', array(
      +		'default'        => '',
      +        'capability'     => 'edit_theme_options',
      +        'type'           => 'option',
      +		'sanitize_callback' => 'esc_attr'
      +	));
      +	$wp_customize->add_control('creatus_branding_text', array(
      +		'label'   => __('Branding text', 'creatus'),
      +		'section' => 'creatus_default_branding',
      +		'type'    => 'text',
      +		'description' => __( 'Add branding ( copyright ) text', 'creatus' )
      +	));
      +
      +	// branding link
      +	$wp_customize->add_setting('creatus_branding_link', array(
      +		'default'        => '',
      +        'capability'     => 'edit_theme_options',
      +        'type'           => 'option',
      +		'sanitize_callback' => 'esc_attr'
      +	));
      +	$wp_customize->add_control('creatus_branding_link', array(
      +		'label'   => __('Branding link', 'creatus'),
      +		'section' => 'creatus_default_branding',
      +		'type'    => 'text',
      +		'description' => __( 'Add branding link', 'creatus' )
      +	));
      +	
      +}
      +
      +add_action('customize_register', 'thz_action_default_customizer_options');
      \ No newline at end of file
      diff --git a/inc/init.php b/inc/init.php
      index dcf3f0f..d7ef929 100644
      --- a/inc/init.php
      +++ b/inc/init.php
      @@ -80,6 +80,12 @@ private static function include_customizer(){
       			$files    = array(
       				'class-thz-customizer.php'
       			);
      +			
      +			if( !thz_fw_active() && is_customize_preview() ){
      +				
      +				$files[] = 'customizer-defaults.php';
      +			}
      +			
       			foreach ( $files as $file ) {
       				require_once $abs_path . $file;
       			}
      @@ -157,7 +163,6 @@ private static function get_includes_files_list( $dir_rel_path ) {
       			$path . 'class-thz-item-utility.php',
       			$path . 'classes-thz-menu-walkers.php',
       			$path . 'class-thz-doc.php',
      -			$path . 'class-thz-demos.php',
       			$path . 'class-thz-dynamic-css.php',
       			$path . 'class-thz-generate-css.php',
       			$path . 'thz-assign-layout.php',
      @@ -205,8 +210,6 @@ public static function _action_init() {
       	}
       
       	/**
      -	 * @todo - is it a good idea to automatically load widgets in child theme? wouldn't it be better to have an action that allows hooking to it?
      -	 *
       	 * @internal
       	 */
       	public static function _action_widgets_init() {
      diff --git a/inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php b/inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php
      index 9e49599..e6b8e92 100644
      --- a/inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php
      +++ b/inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php
      @@ -527,7 +527,7 @@
       				'desc' => false,
       				'picker' => array(
       					'picked' => array(
      -						'label' => 'Heading font',
      +						'label' =>  __('Heading font', 'creatus'),
       						'type' => 'radio',
       						'value' => 'default',
       						'choices' => array(
      @@ -558,7 +558,7 @@
       				'desc' => false,
       				'picker' => array(
       					'picked' => array(
      -						'label' => 'Sub heading font',
      +						'label' => __('Sub heading font', 'creatus'),
       						'type' => 'radio',
       						'value' => 'default',
       						'choices' => array(
      @@ -589,7 +589,7 @@
       				'desc' => false,
       				'picker' => array(
       					'picked' => array(
      -						'label' => 'Text font',
      +						'label' => __('Text font', 'creatus'),
       						'type' => 'radio',
       						'value' => 'default',
       						'choices' => array(
      diff --git a/inc/thzframework/extensions/shortcodes/shortcodes/notification/options.php b/inc/thzframework/extensions/shortcodes/shortcodes/notification/options.php
      index 6daeaf0..4192c2d 100644
      --- a/inc/thzframework/extensions/shortcodes/shortcodes/notification/options.php
      +++ b/inc/thzframework/extensions/shortcodes/shortcodes/notification/options.php
      @@ -134,7 +134,7 @@
       				'desc' => false,
       				'picker' => array(
       					'picked' => array(
      -						'label' => 'Notification style type',
      +						'label' => __('Notification style type', 'creatus'),
       						'type' => 'switch',
       						'right-choice' => array(
       							'value' => 'predefined',
      diff --git a/inc/thzframework/theme/options/mainmenu/containers_sub_level.php b/inc/thzframework/theme/options/mainmenu/containers_sub_level.php
      index b1e3ae5..4f97f32 100644
      --- a/inc/thzframework/theme/options/mainmenu/containers_sub_level.php
      +++ b/inc/thzframework/theme/options/mainmenu/containers_sub_level.php
      @@ -58,7 +58,7 @@
       	),
       	'tm_subli_border' => array(
       		'type' => 'thz-box-style',
      -		'label' => 'Sub level li border',
      +		'label' => __('Sub level li border', 'creatus'),
       		'attr' => array(
       			'data-tminputid' => 'tm_subli_border',
       			'data-changing' => 'border'
      diff --git a/inc/thzframework/theme/options/mainmenu/hovered_style.php b/inc/thzframework/theme/options/mainmenu/hovered_style.php
      index c8f9dd0..e944ac1 100644
      --- a/inc/thzframework/theme/options/mainmenu/hovered_style.php
      +++ b/inc/thzframework/theme/options/mainmenu/hovered_style.php
      @@ -32,7 +32,7 @@
       	),
       	'tm_link_hover_border' => array(
       		'type' => 'thz-box-style',
      -		'label' => 'Top level hovered link border',
      +		'label' => __('Top level hovered link border', 'creatus'),
       		'attr' => array(
       			'data-tmborders' => 'tm_link_hover_border',
       			'data-changing' => 'border'
      diff --git a/inc/thzframework/theme/options/mainmenu/link_style.php b/inc/thzframework/theme/options/mainmenu/link_style.php
      index 460c012..d4ee275 100644
      --- a/inc/thzframework/theme/options/mainmenu/link_style.php
      +++ b/inc/thzframework/theme/options/mainmenu/link_style.php
      @@ -32,7 +32,7 @@
       	),
       	'tm_tl_border' => array(
       		'type' => 'thz-box-style',
      -		'label' => 'Top level link border',
      +		'label' => __('Top level link border', 'creatus'),
       		'attr' => array(
       			'data-tmborders' => 'tm_tl_border',
       			'data-changing' => 'border'
      diff --git a/inc/thzframework/theme/options/mainmenu/links_layout.php b/inc/thzframework/theme/options/mainmenu/links_layout.php
      index 7fd4029..3445f80 100644
      --- a/inc/thzframework/theme/options/mainmenu/links_layout.php
      +++ b/inc/thzframework/theme/options/mainmenu/links_layout.php
      @@ -28,7 +28,7 @@
       	),
       	'tm_tl_boxstyle' => array(
       		'type' => 'thz-box-style',
      -		'label' => 'Top level link padding',
      +		'label' => __('Top level link padding', 'creatus'),
       		'attr' => array(
       			'data-tminputid' => 'tm_tl_boxstyle',
       			'data-changing' => 'padding'
      @@ -113,7 +113,7 @@
       	),
       	'tm_sl_boxstyle' => array(
       		'type' => 'thz-box-style',
      -		'label' => 'Sub level link padding',
      +		'label' => __('Sub level link padding', 'creatus'),
       		'attr' => array(
       			'data-tminputid' => 'tm_sl_boxstyle',
       			'data-changing' => 'padding'
      diff --git a/inc/thzframework/theme/options/widgetsgenerator.php b/inc/thzframework/theme/options/widgetsgenerator.php
      index 48c7f21..ce31c0d 100644
      --- a/inc/thzframework/theme/options/widgetsgenerator.php
      +++ b/inc/thzframework/theme/options/widgetsgenerator.php
      @@ -10,7 +10,7 @@
       		
       			'no_builder_text' => array(
       				'type' => 'thz-separator',
      -				'label'=>'Grids generator',
      +				'label'=> __('Grids generator', 'creatus'),
       				'value' => false,
       				'html' => esc_html__('<h2>This option requires Unyson Page Builder extension to be active. Please go to Unyson plugin and activate </h2>','creatus'),
       			),
      diff --git a/inc/widgets/index.html b/inc/widgets/index.html
      deleted file mode 100644
      index e69de29..0000000
      diff --git a/inc/widgets/thz-flickr/class-widget-thz-flickr.php b/inc/widgets/thz-flickr/class-widget-thz-flickr.php
      deleted file mode 100644
      index c1544f1..0000000
      --- a/inc/widgets/thz-flickr/class-widget-thz-flickr.php
      +++ /dev/null
      @@ -1,115 +0,0 @@
      -<?php if ( ! defined( 'ABSPATH' ) ) die( 'Direct access forbidden.' );
      -
      -class Widget_Thz_Flickr extends WP_Widget {
      -	
      -	
      -	function __construct() {
      -		$widget_ops = array( 'description' => esc_html__( 'Flickr images widget', 'creatus' ) );
      -		parent::__construct( false, esc_html__( 'Creatus - Flickr images', 'creatus' ), $widget_ops );
      -		
      -        $this->defaults = array(
      -			'title'         => '',
      -			'api'        	=> '',
      -			'userid'        => '',
      -			'photoset'      => '',
      -			'number'        => '',
      -			'keep_data'     => 'i',
      -        );
      -	}
      -
      -
      -	function widget( $args, $instance ) {
      -		
      -		if ( ! isset( $args['widget_id'] ) ) {
      -			$args['widget_id'] = $this->id;
      -		}
      -		
      -		extract( $args );
      -		$params = array();
      -
      -		if( empty($instance) ){
      -			$instance = $this->defaults;
      -		}
      -		
      -		foreach ( $instance as $key => $value ) {
      -			$params[ $key ] = $value;
      -		}
      -
      -		$title = apply_filters( 'widget_title', $params['title'], $instance, $this->id_base );
      -		$title = $params['title'] ? $before_title . $title . $after_title: '';
      -		unset( $params['title'] );
      -
      -		$filepath = thz_theme_file_path ( '/inc/widgets/thz-flickr/views/widget.php' );
      -		
      -		$params['widget_id'] = $args['widget_id'];
      -		
      -		$data = array(
      -			'instance'      => $params,
      -			'title'         => $title,
      -			'before_widget' => str_replace( 'class="widget ', 'class="widget thz-flickr-widget ', $before_widget ),
      -			'after_widget'  => $after_widget,
      -		);
      -		
      -		
      -		echo thz_render_view( $filepath, $data );
      -	}
      -	
      -	
      -	function update( $new_instance, $old_instance ) {
      -		
      -		$userid 	= $new_instance['userid'];
      -		$widget_id 	= $this->id;
      -		$number 	= $new_instance['number'];
      -		$trans_name = 'thz-flickr-images-' . sanitize_title_with_dashes( $userid.$widget_id ) . '-'.$number;
      -		delete_transient($trans_name);
      -		delete_option($trans_name);
      -		
      -		return $new_instance;
      -	}
      -	
      -	
      -	function form( $instance ) {
      -		$instance 	= wp_parse_args( (array) $instance, $this->defaults);
      -		$api 		= $instance['api'];
      -		
      -		if ( empty( $api ) ) {
      -			$api = 'c9d2c2fda03a2ff487cb4769dc0781ea';
      -		}
      -		
      -		$userid_link = 'http://www.webpagefx.com/tools/idgettr/';
      -		$userapi_link = 'http://www.flickr.com/services/apps/create/apply';
      -		$photoset_link = 'https://www.flickr.com/services/api/explore/flickr.photosets.getPhotos';
      -		?>
      -		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Title:', 'creatus' ); ?></label>
      -			<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] ); ?>"/>
      -		</p>
      -		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'api' ) ); ?>"><?php esc_html_e( 'API key ', 'creatus' ); ?> (<a href="<?php echo esc_url($userapi_link); ?>" target="_blank"><?php esc_html_e('Get API key', 'creatus'); ?></a>):</label>
      -			<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'api' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'api' ) ); ?>" type="text" value="<?php echo esc_attr( $api ); ?>"/>
      -            <small><?php printf( __( 'Use this key until you get your own: %s', 'creatus' ), 'c5125a0fd25d986b2ec17e1c2b5d2c7d' ); ?></small>
      -		</p>
      -		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'userid' ) ); ?>"><?php esc_html_e( 'User ID', 'creatus' ); ?> (<a href="<?php echo esc_url($userid_link); ?>" target="_blank"><?php esc_html_e('Get user ID', 'creatus'); ?></a>):</label>
      -			<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'userid' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'userid' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['userid'] ); ?>"/>
      -		</p>
      -		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'photoset' ) ); ?>"><?php esc_html_e( 'Photo set ID', 'creatus' ); ?> (<a href="<?php echo esc_url($photoset_link); ?>" target="_blank"><?php esc_html_e('Get photo set ID', 'creatus'); ?></a>):</label>
      -			<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'photoset' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'photoset' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['photoset'] ); ?>"/>
      -             <small><?php esc_html_e( 'If this is used than only images from this photoset are displayed.', 'creatus' ); ?></small>
      -		</p>
      -		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'number' ) ); ?>"><?php esc_html_e( 'Number of images:', 'creatus' ); ?></label>
      -			<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'number' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'number' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['number'] ); ?>"/>
      -		</p>
      -		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'keep_data' ) ); ?>"><?php esc_html_e( 'Keep data:', 'creatus' ); ?></label>
      -			<select name="<?php echo esc_attr( $this->get_field_name( 'keep_data' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'keep_data' ) ); ?>" class="widefat">
      -				<option value="a" <?php selected( $instance['keep_data'], 'a' ); ?>><?php esc_html_e( 'Acitve', 'creatus' ); ?></option>
      -				<option value="i" <?php selected( $instance['keep_data'], 'i' ); ?>><?php esc_html_e( 'Inactive', 'creatus' ); ?></option>
      -			</select>
      -            <small><?php esc_html_e( 'If this option is active, data is saved as WP option, otherwise it is saved as expiring transient.', 'creatus' ); ?></small>
      -		</p>
      -	<?php
      -	}
      -}
      diff --git a/inc/widgets/thz-flickr/index.html b/inc/widgets/thz-flickr/index.html
      deleted file mode 100644
      index e69de29..0000000
      diff --git a/inc/widgets/thz-flickr/views/index.html b/inc/widgets/thz-flickr/views/index.html
      deleted file mode 100644
      index e69de29..0000000
      diff --git a/inc/widgets/thz-flickr/views/widget.php b/inc/widgets/thz-flickr/views/widget.php
      deleted file mode 100644
      index d0422a4..0000000
      --- a/inc/widgets/thz-flickr/views/widget.php
      +++ /dev/null
      @@ -1,67 +0,0 @@
      -<?php
      -/**
      - * @package      Thz Framework
      - * @author       Themezly
      - * @websites     http://www.themezly.com | http://www.youjoomla.com | http://www.yjsimplegrid.com
      - */
      - 
      -if ( ! defined( 'ABSPATH' ) ) {
      -	exit; // No direct access
      -}
      -/**
      - * @var $instance
      - * @var $before_widget
      - * @var $after_widget
      - * @var $title
      - */
      - 
      -$api 		= $instance['api'];
      -$userid 	= $instance['userid']; 
      -$photoset 	= $instance['photoset'];
      -$number	 	= $instance['number'];
      -$widget_id	= $instance['widget_id']; 
      -$keep_data  = $instance['keep_data'];
      -
      -echo $before_widget;
      -echo $title;
      -
      -$images 		= thz_flickr_images($api,$userid,$photoset,$number,'m',$widget_id,false,$keep_data);
      -$hover_bgtype	= thz_ov_ef('.thz-flickr-images','background/type');
      -$hover_ef 		= thz_ov_ef('.thz-flickr-images','oeffect');
      -$hover_tr 		= thz_ov_ef('.thz-flickr-images','oduration');
      -$img_ef			= thz_ov_ef('.thz-flickr-images','ieffect');
      -$img_tr 		= thz_ov_ef('.thz-flickr-images','iduration');
      -
      -?>
      -<?php if ( is_array( $images ) && ! empty( $images )) {?>
      -<ul class="thz-flickr-images thz-social-images">
      -<?php foreach ($images as $image ) {
      -
      -	$style 				= ' style="background-image:url('.$image['thumb'].');"';
      -	$hover_classes 		= 'thz-hover thz-hover-img-mask thz-hover-bg-'.$hover_bgtype.' '.$hover_ef.' '.$img_ef.' '.$img_tr;
      -	
      -	$thumbnail_print ='<div class="thz-social-img">';
      -	$thumbnail_print .='<div class="'.thz_sanitize_class($hover_classes).'"'.$style.'>';
      -	$thumbnail_print .='<div class="thz-hover-mask '.$hover_tr.'">';
      -	$thumbnail_print .='<div class="thz-hover-mask-table">';
      -	$thumbnail_print .='<a href="'.$image['url'].'" class="thz-hover-link" target="_blank"></a>';
      -	$thumbnail_print .='</div>';
      -	$thumbnail_print .='</div>';
      -	$thumbnail_print .='</div>';	
      -	$thumbnail_print .='</div>';
      -
      -
      -?>
      -	<li>
      -        <?php echo $thumbnail_print ?>
      -    </li>
      -<?php }// end foreach?>
      -</ul>
      -<?php 
      -
      -	}else{
      -		
      - 		echo esc_html_e('Not able to display user images. Check widget settings.', 'creatus');
      -	}
      -	echo $after_widget;
      -?>
      \ No newline at end of file
      diff --git a/inc/widgets/thz-instagram/class-widget-thz-instagram.php b/inc/widgets/thz-instagram/class-widget-thz-instagram.php
      deleted file mode 100644
      index c45232d..0000000
      --- a/inc/widgets/thz-instagram/class-widget-thz-instagram.php
      +++ /dev/null
      @@ -1,93 +0,0 @@
      -<?php if ( ! defined( 'ABSPATH' ) ) die( 'Direct access forbidden.' );
      -
      -class Widget_Thz_Instagram extends WP_Widget {
      -	
      -	
      -	function __construct() {
      -		$widget_ops = array( 'description' => esc_html__( 'Instagram images widget', 'creatus' ) );
      -		parent::__construct( false, esc_html__( 'Creatus - Instagram images', 'creatus' ), $widget_ops );
      -		
      -        $this->defaults = array(
      -			'title'         => '',
      -			'username'      => '',
      -			'number'        => '',
      -			'keep_data'     => 'i',
      -        );
      -	}
      -
      -
      -	function widget( $args, $instance ) {
      -
      -		if ( ! isset( $args['widget_id'] ) ) {
      -			$args['widget_id'] = $this->id;
      -		}
      -
      -		extract( $args );
      -		$params = array();
      -		
      -		if( empty($instance) ){
      -			$instance = $this->defaults;
      -		}
      -
      -		foreach ( $instance as $key => $value ) {
      -			$params[ $key ] = $value;
      -		}
      -
      -		$title = apply_filters( 'widget_title', $params['title'], $instance, $this->id_base );
      -		$title = $params['title'] ? $before_title . $title . $after_title: '';
      -		unset( $params['title'] );
      -
      -		$filepath = thz_theme_file_path ( '/inc/widgets/thz-instagram/views/widget.php' );
      -		
      -		$params['widget_id'] = $args['widget_id'];
      -		
      -		$data = array(
      -			'instance'      => $params,
      -			'title'         => $title,
      -			'before_widget' => str_replace( 'class="widget ', 'class="widget thz-instagram-widget ', $before_widget ),
      -			'after_widget'  => $after_widget,
      -		);
      -
      -		echo thz_render_view( $filepath, $data );
      -	}
      -	
      -	
      -	function update( $new_instance, $old_instance ) {
      -		
      -		$username 	= $new_instance['username'];
      -		$widget_id 	= $this->id;
      -		$number 	= $new_instance['number'];
      -		$trans_name = 'thz-instagram-images-' . sanitize_title_with_dashes( $username.$widget_id ) . '-'.$number;
      -		delete_transient($trans_name);
      -		delete_option($trans_name);
      -		
      -		return $new_instance;
      -	}
      -	
      -	
      -	function form( $instance ) {
      -		$instance = wp_parse_args( (array) $instance, $this->defaults );
      -		?>
      -		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Title:', 'creatus' ); ?></label>
      -			<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] ); ?>"/>
      -		</p>
      -		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'username' ) ); ?>"><?php esc_html_e( 'Username:', 'creatus' ); ?></label>
      -			<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'username' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'username' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['username'] ); ?>"/>
      -		</p>
      -		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'number' ) ); ?>"><?php esc_html_e( 'Number of images:', 'creatus' ); ?></label>
      -			<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'number' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'number' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['number'] ); ?>"/>
      -		</p>
      -		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'keep_data' ) ); ?>"><?php esc_html_e( 'Keep data:', 'creatus' ); ?></label>
      -			<select name="<?php echo esc_attr( $this->get_field_name( 'keep_data' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'keep_data' ) ); ?>" class="widefat">
      -				<option value="a" <?php selected( $instance['keep_data'], 'a' ); ?>><?php esc_html_e( 'Acitve', 'creatus' ); ?></option>
      -				<option value="i" <?php selected( $instance['keep_data'], 'i' ); ?>><?php esc_html_e( 'Inactive', 'creatus' ); ?></option>
      -			</select>
      -            <small><?php esc_html_e( 'If this option is active, data is saved as WP option, otherwise it is saved as expiring transient.', 'creatus' ); ?></small>
      -		</p>
      -	<?php
      -	}
      -}
      diff --git a/inc/widgets/thz-instagram/index.html b/inc/widgets/thz-instagram/index.html
      deleted file mode 100644
      index e69de29..0000000
      diff --git a/inc/widgets/thz-instagram/views/index.html b/inc/widgets/thz-instagram/views/index.html
      deleted file mode 100644
      index e69de29..0000000
      diff --git a/inc/widgets/thz-instagram/views/widget.php b/inc/widgets/thz-instagram/views/widget.php
      deleted file mode 100644
      index 3963f70..0000000
      --- a/inc/widgets/thz-instagram/views/widget.php
      +++ /dev/null
      @@ -1,64 +0,0 @@
      -<?php
      -/**
      - * @package      Thz Framework
      - * @author       Themezly
      - * @websites     http://www.themezly.com | http://www.youjoomla.com | http://www.yjsimplegrid.com
      - */
      - 
      -if ( ! defined( 'ABSPATH' ) ) {
      -	exit; // No direct access
      -}
      -/**
      - * @var $instance
      - * @var $before_widget
      - * @var $after_widget
      - * @var $title
      - */
      - 
      -$username 		= $instance['username'];
      -$number	 		= $instance['number'];
      -$widget_id		= $instance['widget_id'];
      -$keep_data  	= $instance['keep_data'];
      -$images 		= thz_instagram_images($username,$number,$widget_id,false,$keep_data);
      -$hover_bgtype	= thz_ov_ef('.thz-instagram-images','background/type');
      -$hover_ef 		= thz_ov_ef('.thz-instagram-images','oeffect');
      -$hover_tr 		= thz_ov_ef('.thz-instagram-images','oduration');
      -$img_ef			= thz_ov_ef('.thz-instagram-images','ieffect');
      -$img_tr 		= thz_ov_ef('.thz-instagram-images','iduration');
      -echo $before_widget;
      -echo $title;
      -?>
      -<?php if ( is_array( $images ) && !empty( $images ) && ! isset($images->errors ) ) {?>
      -<ul class="thz-instagram-images thz-social-images">
      -<?php foreach ($images as $image ) {;
      -
      -
      -			
      -		$style 				= ' style="background-image:url('.$image['link'].');"';
      -		$hover_classes 		= 'thz-hover thz-hover-img-mask thz-hover-bg-'.$hover_bgtype.' '.$hover_ef.' '.$img_ef.' '.$img_tr;
      -		
      -		$thumbnail_print ='<div class="thz-social-img">';
      -		$thumbnail_print .='<div class="'.thz_sanitize_class($hover_classes).'"'.$style.'>';
      -		$thumbnail_print .='<div class="thz-hover-mask '.$hover_tr.'">';
      -		$thumbnail_print .='<div class="thz-hover-mask-table">';
      -		$thumbnail_print .='<a href="http://instagram.com/p/'.$image['code'].'" class="thz-hover-link" target="_blank"></a>';
      -		$thumbnail_print .='</div>';
      -		$thumbnail_print .='</div>';
      -		$thumbnail_print .='</div>';	
      -		$thumbnail_print .='</div>';
      -
      -
      -?>
      -	<li>
      -        <?php echo $thumbnail_print ?>
      -    </li>
      -<?php }?>
      -</ul>
      -<?php 
      -
      -	}else{
      -		
      - 		echo esc_html_e('Not able to display user images. Check widget settings.', 'creatus');
      -	}
      -	echo $after_widget;
      -?>
      \ No newline at end of file
      diff --git a/inc/widgets/thz-posts/class-widget-thz-posts.php b/inc/widgets/thz-posts/class-widget-thz-posts.php
      deleted file mode 100644
      index 03003c3..0000000
      --- a/inc/widgets/thz-posts/class-widget-thz-posts.php
      +++ /dev/null
      @@ -1,282 +0,0 @@
      -<?php if ( ! defined( 'ABSPATH' ) ) die( 'Direct access forbidden.' );
      -
      -class Widget_Thz_Posts extends WP_Widget {
      -	
      -	protected $defaults;
      -	
      -	public function __construct() {
      -		
      -		$widget_ops = array( 'description' => esc_html__( 'Posts widget', 'creatus' ) );
      -		parent::__construct( false, esc_html__( 'Creatus - Posts', 'creatus' ), $widget_ops );
      -		
      -        $this->defaults = array(
      -			'title'         => 'Posts',
      -			'posts'      	=> array(
      -				'post' 		=> true
      -			),
      -			'cats'      	=> array(),
      -			'metrics'      	=> array(
      -				'thumbnail' => true,
      -				'thumbnail_only' => true, 
      -				'date' 		=> true,
      -			),
      -			'mode'      	=> 'list',
      -			'col'			=> 4,
      -			'gut'			=> 10,
      -			'intro_limit_by' => 'words',
      -			'intro_limit' 	=> 15,
      -			'ratio'			=> 'thz-ratio-1-1',
      -			'thumbnail_size' => 'thumbnail',
      -			'order'      	=> 'DESC',
      -			'orderby'      	=> 'date',
      -			'title_tag'		=> 'span',
      -			'number'        => 5,
      -			'thumbpoz'		=> 'left',
      -			'days'          => 'all_posts',
      -        );		
      -	}
      -
      -
      -	public function widget( $args, $instance ) {
      -
      -		if ( ! isset( $args['widget_id'] ) ) {
      -			$args['widget_id'] = $this->id;
      -		}
      -		
      -		extract( $args );
      -		$params = array();
      -		
      -		if( empty($instance) ){
      -			$instance = $this->defaults;
      -		}
      -
      -		foreach ( $instance as $key => $value ) {
      -			$params[ $key ] = $value;
      -		}
      -		
      -		$title = apply_filters( 'widget_title', $params['title'], $instance, $this->id_base );
      -		$title = $params['title'] ? $before_title . $title . $after_title: '';
      -		unset( $params['title'] );
      -
      -		$filepath = thz_theme_file_path( '/inc/widgets/thz-posts/views/widget.php' );
      -		
      -		$wmode = $instance['mode'] == 'list' ? 'thz-has-list' :'thz-tumbnail-grid'; 
      -		
      -		if($instance['mode'] == 'list' && !isset($instance['metrics']['listclass']) ){
      -			
      -			$wmode ='thz-posts-widget-list';
      -		}
      -		
      -		$data = array(
      -			'instance'      => $params,
      -			'title'         => $title,
      -			'before_widget' => str_replace( 'class="widget ', 'class="widget thz-posts-widget '.$wmode.' ', $before_widget ),
      -			'after_widget'  => $after_widget,
      -		);
      -
      -		echo thz_render_view( $filepath, $data );
      -	}
      -	
      -	
      -	public function update( $new_instance, $old_instance ) {
      -		return $new_instance;
      -	}
      -	
      -	
      -	public function form( $instance ) {
      -		
      -		$instance 			= wp_parse_args( (array) $instance, $this->defaults);
      -		$types_with_label 	= thz_list_post_types(true,array('forum','topic','reply' ));
      -		$all_types 			= thz_list_post_types(false,array('forum','topic','reply' ));
      -		$tax_names 			= thz_get_post_taxonomies($all_types,'objects');
      -		$metrics 			= array(
      -			'thumbnail'=> esc_html__('Show Thumbnail','creatus'),
      -			'thumbnail_only'=> esc_html__('Show only posts with thumbnail','creatus'),
      -			'date'=> esc_html__('Show Post Date','creatus'),
      -			'intro_text'=> esc_html__('Show intro text','creatus'),
      -			'listclass'=> esc_html__('Use .thz-has-list class','creatus'),
      -		);
      -		
      -		$categories = array();
      -		
      -		foreach ($tax_names as $tax){
      -
      -			if (!$tax->hierarchical) {
      -				continue;
      -			}
      -								
      -			$terms = get_terms( array(
      -				'taxonomy'     => $tax->name,
      -			));
      -			
      -			if($terms){
      -				
      -				foreach ($terms as $term){
      -					if (!is_object($term)) {
      -						continue;
      -					}
      -					
      -					if ( 0 == $term->count ) {
      -						continue;
      -					}
      -					$categories[$term->term_id] = $term->name;
      -				}
      -			}
      -			
      -		}	
      -		unset($tax_names,$tax);
      -		
      -		
      -		?>
      -		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Title:', 'creatus' ); ?></label>
      -			<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] ); ?>"/>
      -		</p>
      -		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'number' ) ); ?>"><?php esc_html_e( 'Number of posts:', 'creatus' ); ?></label>
      -			<input size="3" style="width: 45px;" class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'number' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'number' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['number'] ); ?>"/>
      -		</p>
      -        <p>
      -        <label for="<?php echo esc_attr( $this->get_field_id( 'posts' ) ); ?>"><?php esc_html_e( 'Select post types:', 'creatus' ); ?></label><br />
      -        <?php foreach($types_with_label as $id => $name){ ?>
      -   	 		<input id="<?php echo $this->get_field_id('posts') . $id; ?>" name="<?php echo $this->get_field_name('posts'); ?>[<?php echo esc_attr($id) ?>]" type="checkbox" value="true" <?php checked(isset( $instance['posts'][$id] ) ? 1 : 0); ?> />
      -			<label for="<?php echo esc_attr( $this->get_field_id('posts') . $id ); ?>"><?php echo esc_attr( $name ); ?></label>
      -        <?php } ?>
      -        </p>
      -
      -        <p class="thz-pw-cats">
      -        <label for="<?php echo esc_attr( $this->get_field_id( 'cats' ) ); ?>"><?php esc_html_e( 'Specific tax terms:', 'creatus' ); ?></label><br />
      -        <?php foreach($categories as $id => $name){ ?>
      -   	 		<input id="<?php echo $this->get_field_id('cats') . $id; ?>" name="<?php echo $this->get_field_name('cats'); ?>[<?php echo esc_attr($id) ?>]" type="checkbox" value="true" <?php checked(isset( $instance['cats'][$id] ) ? 1 : 0); ?> />
      -			<label for="<?php echo esc_attr( $this->get_field_id('cats') . $id ); ?>"><?php echo esc_attr( $name ); ?></label><br />
      -        <?php } ?>
      -        </p>
      -		<p>
      -        <label for="<?php echo esc_attr( $this->get_field_id( 'order' ) ); ?>"><?php esc_html_e( 'Order:', 'creatus' ); ?></label>
      -        <select name="<?php echo esc_attr( $this->get_field_name( 'order' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'order' ) ); ?>" class="widefat">
      -            <option value="DESC" <?php selected( $instance['order'], 'DESC' ); ?>><?php esc_html_e( 'Descending ( newest first )', 'creatus' ); ?></option>
      -            <option value="ASC" <?php selected( $instance['order'], 'ASC' ); ?>><?php esc_html_e( 'Ascending ( oldest first )', 'creatus' ); ?></option>
      -        </select>
      -		</p>
      -		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'days' ) ); ?>"><?php esc_html_e( 'Select posts published limit:', 'creatus' ); ?></label>
      -			<select name="<?php echo esc_attr( $this->get_field_name( 'days' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'days' ) ); ?>" class="widefat">
      -				<option value="all_posts" <?php selected( $instance['days'], 'all_posts' ); ?>><?php esc_html_e( 'No limit', 'creatus' ); ?></option>
      -				<option value="7" <?php selected( $instance['days'], '7' ); ?>><?php esc_html_e( 'Show 1 Week old posts', 'creatus' ); ?></option>
      -				<option value="30" <?php selected( $instance['days'], '30' ); ?>><?php esc_html_e( 'Show 1 Month old posts', 'creatus' ); ?></option>
      -				<option value="90" <?php selected( $instance['days'], '90' ); ?>><?php esc_html_e( 'Show 3 Months old posts', 'creatus' ); ?></option>
      -				<option value="180" <?php selected( $instance['days'], '180' ); ?>><?php esc_html_e( 'Show 6 Months old posts', 'creatus' ); ?></option>
      -				<option value="360" <?php selected( $instance['days'], '360' ); ?>><?php esc_html_e( 'Show 1 Year old posts', 'creatus' ); ?></option>
      -			</select>
      -		</p>
      -		<p>
      -        <label for="<?php echo esc_attr( $this->get_field_id( 'orderby' ) ); ?>"><?php esc_html_e( 'Order by:', 'creatus' ); ?></label>
      -        <select name="<?php echo esc_attr( $this->get_field_name( 'orderby' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'orderby' ) ); ?>" class="widefat">
      -            <option value="ID" <?php selected( $instance['orderby'], 'ID' ); ?>><?php esc_html_e( 'ID', 'creatus' ); ?></option>
      -            <option value="author" <?php selected( $instance['orderby'], 'author' ); ?>><?php esc_html_e( 'Author', 'creatus' ); ?></option>
      -            <option value="title" <?php selected( $instance['orderby'], 'title' ); ?>><?php esc_html_e( 'Title', 'creatus' ); ?></option>
      -            <option value="name" <?php selected( $instance['orderby'], 'name' ); ?>><?php esc_html_e( 'Name', 'creatus' ); ?></option>
      -            <option value="date" <?php selected( $instance['orderby'], 'date' ); ?>><?php esc_html_e( 'Create date', 'creatus' ); ?></option>
      -            <option value="modified" <?php selected( $instance['orderby'], 'modified' ); ?>><?php esc_html_e( 'Modified date', 'creatus' ); ?></option>
      -            <option value="rand" <?php selected( $instance['orderby'], 'rand' ); ?>><?php esc_html_e( 'Random', 'creatus' ); ?></option>
      -            <option value="comment_count" <?php selected( $instance['orderby'], 'comment_count' ); ?>><?php esc_html_e( 'Number of comments', 'creatus' ); ?></option>
      -			<option value="meta_value" <?php selected( $instance['orderby'], 'meta_value' ); ?>><?php esc_html_e( 'Post views count', 'creatus' ); ?></option>
      -            <option value="meta_value" <?php selected( $instance['orderby'], 'none' ); ?>><?php esc_html_e( 'None', 'creatus' ); ?></option>
      -        </select>
      -		</p>
      -		<p>
      -        <label for="<?php echo esc_attr( $this->get_field_id( 'title_tag' ) ); ?>"><?php esc_html_e( 'Title tag:', 'creatus' ); ?></label>
      -        <select style="width: 45px;" name="<?php echo esc_attr( $this->get_field_name( 'title_tag' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'title_tag' ) ); ?>" class="widefat">
      -        	<option value="span" <?php selected( $instance['title_tag'], 'span' ); ?>><?php esc_html_e( 'span', 'creatus' ); ?></option>
      -            <option value="div" <?php selected( $instance['title_tag'], 'h1' ); ?>><?php esc_html_e( 'div', 'creatus' ); ?></option>
      -            <option value="h1" <?php selected( $instance['title_tag'], 'h1' ); ?>><?php esc_html_e( 'h1', 'creatus' ); ?></option>
      -            <option value="h2" <?php selected( $instance['title_tag'], 'h2' ); ?>><?php esc_html_e( 'h2', 'creatus' ); ?></option>
      -            <option value="h3" <?php selected( $instance['title_tag'], 'h3' ); ?>><?php esc_html_e( 'h3', 'creatus' ); ?></option>
      -            <option value="h4" <?php selected( $instance['title_tag'], 'h4' ); ?>><?php esc_html_e( 'h4', 'creatus' ); ?></option>
      -            <option value="h5" <?php selected( $instance['title_tag'], 'h5' ); ?>><?php esc_html_e( 'h5', 'creatus' ); ?></option>
      -            <option value="h6" <?php selected( $instance['title_tag'], 'h6' ); ?>><?php esc_html_e( 'h6', 'creatus' ); ?></option>
      -        </select>
      -        </p>
      -		<p>
      -        <label for="<?php echo esc_attr( $this->get_field_id( 'mode' ) ); ?>"><?php esc_html_e( 'Display Mode:', 'creatus' ); ?></label>
      -        <select name="<?php echo esc_attr( $this->get_field_name( 'mode' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'mode' ) ); ?>" class="widefat thz-select-switch">
      -            <option data-enable=".thz-pwm-<?php echo $this->id?>" data-disable=".thz-pwc-<?php echo $this->id?>" value="list" <?php selected( $instance['mode'], 'list' ); ?>><?php esc_html_e( 'List', 'creatus' ); ?></option>
      -            <option data-enable=".thz-pwc-<?php echo $this->id?>" data-disable=".thz-pwm-<?php echo $this->id?>" value="thumbnails" <?php selected( $instance['mode'], 'thumbnails' ); ?>><?php esc_html_e( 'Thumbnails grid', 'creatus' ); ?></option>
      -        </select>
      -		</p>
      -        <p class="thz-pwm-<?php echo $this->id?>">
      -        <label for="<?php echo esc_attr( $this->get_field_id( 'metrics' ) ); ?>"><?php esc_html_e( 'Widget metrics:', 'creatus' ); ?></label><br />
      -        <?php foreach($metrics as $id => $name){ ?>
      -   	 		<input id="<?php echo $this->get_field_id('metrics') . $id; ?>" name="<?php echo $this->get_field_name('metrics'); ?>[<?php echo esc_attr($id) ?>]" type="checkbox" value="true" <?php checked(isset( $instance['metrics'][$id] ) ? 1 : 0); ?> />
      -			<label for="<?php echo esc_attr( $this->get_field_id('metrics') . $id ); ?>"><?php echo esc_attr( $name ); ?></label><br />
      -        <?php } ?>
      -        <br />
      -        <label for="<?php echo esc_attr( $this->get_field_id( 'intro_limit_by' ) ); ?>"><?php esc_html_e( 'Intro limit by:', 'creatus' ); ?></label>
      -        <select name="<?php echo esc_attr( $this->get_field_name( 'intro_limit_by' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'intro_limit_by' ) ); ?>" class="widefat">
      -            <option value="chars" <?php selected( $instance['intro_limit_by'], 'chars' ); ?>><?php esc_html_e( 'By characters', 'creatus' ); ?></option>
      -            <option value="words" <?php selected( $instance['intro_limit_by'], 'words' ); ?>><?php esc_html_e( 'By words', 'creatus' ); ?></option>
      -        </select>  <br />  <br />
      -        <label for="<?php echo esc_attr( $this->get_field_id( 'intro_limit' ) ); ?>"><?php esc_html_e( 'Intro limit:', 'creatus' ); ?></label>
      -        <input  size="3" style="width: 45px;" class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'intro_limit' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'intro_limit' ) ); ?>" type="text" value="<?php echo esc_attr( $instance['intro_limit'] ); ?>"/> <br /><br />
      -        <label for="<?php echo esc_attr( $this->get_field_id( 'thumbpoz' ) ); ?>"><?php esc_html_e( 'Thumbnail position:', 'creatus' ); ?></label>
      -        <select name="<?php echo esc_attr( $this->get_field_name( 'thumbpoz' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'thumbpoz' ) ); ?>" class="widefat">
      -            <option value="left" <?php selected( $instance['thumbpoz'], 'left' ); ?>><?php esc_html_e( 'Left', 'creatus' ); ?></option>
      -            <option value="right" <?php selected( $instance['thumbpoz'], 'right' ); ?>><?php esc_html_e( 'Right', 'creatus' ); ?></option>
      -        	<option value="above" <?php selected( $instance['thumbpoz'], 'above' ); ?>><?php esc_html_e( 'Above the title', 'creatus' ); ?></option>
      -            <option value="under" <?php selected( $instance['thumbpoz'], 'under' ); ?>><?php esc_html_e( 'Under the title', 'creatus' ); ?></option>
      -        </select><br />
      -        </p>
      - 		<p>
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'ratio' ) ); ?>"><?php esc_html_e( 'Thumbnail Width:', 'creatus' ); ?></label>
      -            <select name="<?php echo esc_attr( $this->get_field_name( 'ratio' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'ratio' ) ); ?>" class="widefat">
      -              <optgroup label="<?php esc_html_e( 'Square', 'creatus' ); ?>">
      -              <option value="thz-ratio-1-1" <?php selected( $instance['ratio'], 'thz-ratio-1-1' ); ?>><?php esc_html_e( 'Aspect ratio 1:1', 'creatus' ); ?></option>
      -              </optgroup>
      -              <optgroup label="<?php esc_html_e( 'Landscape', 'creatus' ); ?>">
      -              <option value="thz-ratio-2-1" <?php selected( $instance['ratio'], 'thz-ratio-2-1' ); ?>><?php esc_html_e( 'Aspect ratio 2:1', 'creatus' ); ?></option>
      -              <option value="thz-ratio-3-2" <?php selected( $instance['ratio'], 'thz-ratio-3-2' ); ?>><?php esc_html_e( 'Aspect ratio 3:2', 'creatus' ); ?></option>
      -              <option value="thz-ratio-4-3" <?php selected( $instance['ratio'], 'thz-ratio-4-3' ); ?>><?php esc_html_e( 'Aspect ratio 4:3', 'creatus' ); ?></option>
      -              <option value="thz-ratio-16-9" <?php selected( $instance['ratio'], 'thz-ratio-16-9' ); ?>><?php esc_html_e( 'Aspect ratio 16:9', 'creatus' ); ?></option>
      -              <option value="thz-ratio-21-9" <?php selected( $instance['ratio'], 'thz-ratio-21-9' ); ?>><?php esc_html_e( 'Aspect ratio 21:9', 'creatus' ); ?></option>
      -              </optgroup>
      -              <optgroup label="<?php esc_html_e( 'Portrait', 'creatus' ); ?>">
      -              <option value="thz-ratio-1-2" <?php selected( $instance['ratio'], 'thz-ratio-1-2' ); ?>><?php esc_html_e( 'Aspect ratio 1:2', 'creatus' ); ?></option>
      -              <option value="thz-ratio-3-4" <?php selected( $instance['ratio'], 'thz-ratio-3-4' ); ?>><?php esc_html_e( 'Aspect ratio 3:4', 'creatus' ); ?></option>
      -              <option value="thz-ratio-2-3" <?php selected( $instance['ratio'], 'thz-ratio-2-3' ); ?>><?php esc_html_e( 'Aspect ratio 2:3', 'creatus' ); ?></option>
      -              <option value="thz-ratio-9-16" <?php selected( $instance['ratio'], 'thz-ratio-9-16' ); ?>><?php esc_html_e( 'Aspect ratio 9:16', 'creatus' ); ?></option>
      -              </optgroup>
      -            </select>
      -         </p>
      -         <p>
      -            <label for="<?php echo esc_attr( $this->get_field_id( 'thumbnail_size' ) ); ?>"><?php esc_html_e( 'Thumbnail Size:', 'creatus' ); ?></label>
      -              <select name="<?php echo esc_attr( $this->get_field_name( 'thumbnail_size' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'thumbnail_size' ) ); ?>" class="widefat">
      -            <?php foreach(thz_get_image_sizes_list() as $size => $name){ ?>
      -                <option value="<?php echo esc_attr($size)?>" <?php selected( $instance['thumbnail_size'], $size ); ?>><?php echo esc_attr( $name ); ?></option>
      -            <?php } ?>
      -              </select>
      -        </p>        
      -		<p class="thz-pwc-<?php echo $this->id?>">
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'col' ) ); ?>"><?php esc_html_e( 'Number of columns:', 'creatus' ); ?></label>
      -			<select style="width: 45px;" name="<?php echo esc_attr( $this->get_field_name( 'col' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'col' ) ); ?>" class="widefat">
      -				<option value="1" <?php selected( $instance['col'], '1' ); ?>><?php esc_html_e( '1', 'creatus' ); ?></option>
      -				<option value="2" <?php selected( $instance['col'], '2' ); ?>><?php esc_html_e( '2', 'creatus' ); ?></option>
      -				<option value="3" <?php selected( $instance['col'], '3' ); ?>><?php esc_html_e( '3', 'creatus' ); ?></option>
      -				<option value="4" <?php selected( $instance['col'], '4' ); ?>><?php esc_html_e( '4', 'creatus' ); ?></option>
      -				<option value="5" <?php selected( $instance['col'], '5' ); ?>><?php esc_html_e( '5', 'creatus' ); ?></option>
      -                <option value="6" <?php selected( $instance['col'], '6' ); ?>><?php esc_html_e( '6', 'creatus' ); ?></option>
      -			</select>
      -            
      -			<label for="<?php echo esc_attr( $this->get_field_id( 'gut' ) ); ?>"><?php esc_html_e( 'Gutter:', 'creatus' ); ?></label>
      -			<select style="width: 45px;" name="<?php echo esc_attr( $this->get_field_name( 'gut' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'gut' ) ); ?>" class="widefat">
      -				<option value="0" <?php selected( $instance['gut'], '0' ); ?>><?php esc_html_e( '0px', 'creatus' ); ?></option>
      -                <option value="5" <?php selected( $instance['gut'], '5' ); ?>><?php esc_html_e( '5px', 'creatus' ); ?></option>
      -				<option value="10" <?php selected( $instance['gut'], '10' ); ?>><?php esc_html_e( '10px', 'creatus' ); ?></option>
      -				<option value="15" <?php selected( $instance['gut'], '15' ); ?>><?php esc_html_e( '15px', 'creatus' ); ?></option>
      -				<option value="20" <?php selected( $instance['gut'], '20' ); ?>><?php esc_html_e( '20px', 'creatus' ); ?></option>
      -				<option value="25" <?php selected( $instance['gut'], '25' ); ?>><?php esc_html_e( '25px', 'creatus' ); ?></option>
      -                <option value="30" <?php selected( $instance['gut'], '30' ); ?>><?php esc_html_e( '30px', 'creatus' ); ?></option>
      -			</select>
      -		</p>
      -	<?php
      -	}
      -}
      \ No newline at end of file
      diff --git a/inc/widgets/thz-posts/index.html b/inc/widgets/thz-posts/index.html
      deleted file mode 100644
      index e69de29..0000000
      diff --git a/inc/widgets/thz-posts/views/index.html b/inc/widgets/thz-posts/views/index.html
      deleted file mode 100644
      index e69de29..0000000
      diff --git a/inc/widgets/thz-posts/views/widget.php b/inc/widgets/thz-posts/views/widget.php
      deleted file mode 100644
      index e42121c..0000000
      --- a/inc/widgets/thz-posts/views/widget.php
      +++ /dev/null
      @@ -1,149 +0,0 @@
      -<?php
      -/**
      - * @package      Thz Framework
      - * @author       Themezly
      - * @websites     http://www.themezly.com | http://www.youjoomla.com | http://www.yjsimplegrid.com
      - */
      - 
      -if ( ! defined( 'ABSPATH' ) ) {
      -	exit; // No direct access
      -}
      -/**
      - * @var $instance
      - * @var $before_widget
      - * @var $after_widget
      - * @var $title
      - */
      - 
      -$number	 		= (int) $instance['number'];
      -$mode			= $instance['mode']; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited
      -$posts			= isset($instance['posts']) ? array_keys( $instance['posts'] ) : array('post'); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited
      -$cats			= isset($instance['cats']) ? array_keys( $instance['cats'] ) : array();
      -$order			= $instance['order']; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited
      -$orderby		= $instance['orderby']; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited
      -$date			= isset($instance['metrics']['date']) ? true : false;
      -$thumbnail  	= isset($instance['metrics']['thumbnail']) || 'thumbnails' == $mode ? true : false;
      -$thumbnail_only = isset($instance['metrics']['thumbnail_only']) ? true : false;
      -$showtitle  	= isset($instance['metrics']['showtitle']) ? true : false;
      -$intro_text  	= isset($instance['metrics']['intro_text']) ? true : false;
      -$intro_limit_by	= $intro_text ? $instance['intro_limit_by'] : 'words';
      -$intro_limit	= $intro_text ? $instance['intro_limit'] : 20;
      -$title_tag		= $instance['title_tag']; 
      -$thumbpoz		= ' thumbnail-'.$instance['thumbpoz'];
      -$thumbnail_size = $instance['thumbnail_size'];
      -$ratio			= $instance['ratio'];
      -$col			= (int) $instance['col'];
      -$gut			= (int) $instance['gut'];
      -$ul_class		= ' thz-ml-n'.$gut;
      -$top_gut 		= '';
      -$li_class		= ' '.thz_col_width( $col, 4 ).' thz-pl-'.$gut;
      -
      -echo $before_widget;
      -echo $title;
      -
      -$args = array(
      -  'posts_per_page'  => $number,
      -  'post_type'  		=> $posts,
      -  'tax_query'  		=> thz_post_tax_query( $cats,array(),$posts ),
      -  'order'			=> $order,
      -  'orderby'			=> $orderby,
      -  'ignore_sticky_posts' => true,
      -  'date_query'		=> thz_date_query_helper($instance['days'])
      -);
      -
      -
      -if('meta_value' == $orderby){
      -	
      -	$args['meta_key'] = 'thz_post_views';
      -}
      -
      -if('thumbnails' == $mode || $thumbnail_only){
      -	
      -	$args['meta_query'] = array( 
      -        array(
      -            'key' => '_thumbnail_id'
      -        ) 
      -    );
      -}
      -
      -
      -
      -
      -$posts_query 	= new WP_Query( $args );
      -
      -
      -if ($posts_query->have_posts()) :
      -
      -$counter = 0;
      -?>
      -<ul class="thz-posts-widget-list<?php if( 'thumbnails' == $mode ) { echo thz_sanitize_class($ul_class); } ?>">
      -<?php while ( $posts_query->have_posts() ) : $counter++; $posts_query->the_post(); 
      -	
      -	if ('thumbnails' == $mode && $counter > $col){
      -		$top_gut =' thz-pt-'.$gut;
      -	}
      -?>
      -    <li class="thz-posts-widget-item<?php if( 'thumbnails' == $mode ) { echo thz_sanitize_class($li_class.$top_gut); } ?>">
      -    <div class="post-holder<?php if( 'list' == $mode ) { echo thz_sanitize_class($thumbpoz); } ?>">
      -			<?php 
      -                $thumbnail_print 	= null;
      -				if ( $thumbnail ) {
      -                    
      -                    $thumbnail_id 		= get_post_thumbnail_id( get_the_ID() );
      -                    
      -                    if(!empty($thumbnail_id)){
      -
      -                        $img_src 			= get_the_post_thumbnail_url( get_the_ID(), $thumbnail_size );
      -						$hover_bgtype		= thz_ov_ef('.thz-posts-widget-list','background/type');
      -                        $hover_ef 			= thz_ov_ef('.thz-posts-widget-list','oeffect');
      -                        $hover_tr 			= thz_ov_ef('.thz-posts-widget-list','oduration');
      -                        $img_ef				= thz_ov_ef('.thz-posts-widget-list','ieffect');
      -                        $img_tr 			= thz_ov_ef('.thz-posts-widget-list','iduration');			
      -                        
      -                        $style 				= ' style="background-image:url('.esc_url ( $img_src ).');"';
      -                        $hover_classes 		= 'thz-hover thz-hover-img-mask thz-hover-bg-'.$hover_bgtype.' '.$hover_ef.' '.$img_ef.' '.$img_tr;
      -                        
      -                        
      -                        $thumbnail_print .='<div class="post-thumbnail">';
      -                        $thumbnail_print .='<div class="thz-aspect '.$ratio.'">';
      -                        $thumbnail_print .='<div class="thz-ratio-in">';
      -                        $thumbnail_print .='<div class="'.thz_sanitize_class($hover_classes).'"'.$style.'>';
      -                        $thumbnail_print .='<div class="thz-hover-mask '.$hover_tr.'">';
      -                        $thumbnail_print .='<div class="thz-hover-mask-table">';
      -                        $thumbnail_print .='<a href="'.get_the_permalink().'" class="thz-hover-link" title="'.get_the_title().'"></a>';
      -                        $thumbnail_print .='</div>';
      -                        $thumbnail_print .='</div>';
      -                        $thumbnail_print .='</div>';	
      -                        $thumbnail_print .='</div>';
      -                        $thumbnail_print .='</div>';
      -                        $thumbnail_print .='</div>';
      -                        
      -						if($instance['thumbpoz'] == 'left' || $instance['thumbpoz'] == 'above'){
      -                        	echo $thumbnail_print;
      -						}
      -                    }
      -                }
      -             ?>
      -             <?php if('list' == $mode ) : ?>
      -            <div class="post-data">
      -                <<?php echo esc_attr($title_tag)?> class="post-title">
      -                	<a href="<?php the_permalink(); ?>"><?php get_the_title() ? the_title() : the_ID(); ?></a>
      -                </<?php echo esc_attr($title_tag)?>>
      -                <?php if ( $date ) : ?>
      -                <span class="post-date"><?php echo get_the_date(); ?></span>
      -                <?php endif; ?>
      -                <?php if ( $intro_text ) : ?>
      -                <div class="post-intro-text"><?php echo thz_intro_text($intro_limit_by,$intro_limit); ?></div>
      -                <?php endif; ?>
      -            </div>
      -            <?php endif; ?>
      -			<?php 
      -				if($thumbnail_print && ( $instance['thumbpoz'] == 'right' || $instance['thumbpoz'] == 'under')){
      -					echo $thumbnail_print;
      -				}
      -			?>
      -    	</div>
      -    </li>
      -<?php  endwhile; ?>
      -</ul>
      -<?php wp_reset_postdata(); 	endif; echo $after_widget; ?>
      \ No newline at end of file
      diff --git a/inc/widgets/thz-twitter/class-widget-thz-twitter.php b/inc/widgets/thz-twitter/class-widget-thz-twitter.php
      deleted file mode 100644
      index 47d3047..0000000
      --- a/inc/widgets/thz-twitter/class-widget-thz-twitter.php
      +++ /dev/null
      @@ -1,153 +0,0 @@
      -<?php if ( ! defined( 'ABSPATH' ) ) die( 'Direct access forbidden.' );
      -
      -class Widget_Thz_Twitter extends WP_Widget {
      -	
      -	
      -	function __construct() {
      -		$widget_ops = array( 'description' => esc_html__( 'Twitter widget', 'creatus' ) );
      -		parent::__construct( false, esc_html__( 'Creatus - Twitter', 'creatus' ), $widget_ops );
      -		
      -        $this->defaults = array(
      -			'title'         		=> 'Recent Tweets',
      -			'apikeys'    			=> 'theme',
      -			'consumer_key'    		=> '',
      -			'consumer_secret'    	=> '',
      -			'access_token'    		=> '',
      -			'access_token_secret'   => '',
      -			'twitter_id'    		=> '',
      -			'count'        			=> 3,
      -			'tweet_limit'         	=> ''
      -        );
      -	}
      -
      -
      -	function widget( $args, $instance ) {
      -		
      -		if ( ! isset( $args['widget_id'] ) ) {
      -			$args['widget_id'] = $this->id;
      -		}
      -		
      -		extract( $args );
      -		$params = array();
      -
      -		if( empty($instance) ){
      -			$instance = $this->defaults;
      -		}
      -		
      -		foreach ( $instance as $key => $value ) {
      -			$params[ $key ] = $value;
      -		}
      -
      -		$title = apply_filters( 'widget_title', $params['title'], $instance, $this->id_base );
      -		$title = $params['title'] ? $before_title . $title . $after_title: '';
      -		unset( $params['title'] );
      -		
      -		
      -		$haslist = isset($instance['haslist'])  ? 'thz-has-list ' :'';
      -		$tweet_link = isset($instance['tweet_link']) ? 1 : 0; 
      -		
      -		$filepath = thz_theme_file_path( '/inc/widgets/thz-twitter/views/widget.php' );
      -
      -		$data = array(
      -			'instance'      => $params,
      -			'title'         => $title,
      -			'before_widget' => str_replace( 'class="widget ', 'class="widget thz-twitter-widget '.$haslist, $before_widget ),
      -			'after_widget'  => $after_widget,
      -			'transient'		=> 'thz_tweets_'.$widget_id,
      -			'widget_id'  	=> $args['widget_id'],
      -			'tweet_link'  	=> $tweet_link,
      -			'tweet_limit'  	=> $instance['tweet_limit'],
      -		);
      -
      -		echo thz_render_view( $filepath, $data );
      -	}
      -	
      -	
      -	function update( $new_instance, $old_instance ) {
      -		
      -		$transName = 'thz_tweets_'.$this->id;
      -		delete_transient($transName);
      -
      -		return $new_instance;
      -	}
      -	
      -	
      -	function form( $instance ) {
      -
      -		if(empty($instance)) {
      -			$instance['haslist'] = 1;
      -		}
      -				
      -		$instance = wp_parse_args( (array) $instance, $this->defaults );
      -		
      -		$haslist = isset($instance['haslist']) ? 1 : 0;
      -		$tweet_link = isset($instance['tweet_link']) ? 1 : 0;
      -		?>
      -        <p>
      -            <label for="<?php echo esc_attr($this->get_field_id('title')); ?>"><?php echo esc_html__('Title','creatus') ?>:</label>
      -            <input class="widefat" id="<?php echo esc_attr($this->get_field_id('title')); ?>" name="<?php echo esc_attr($this->get_field_name('title')); ?>" value="<?php echo esc_attr($instance['title']); ?>" />
      -        </p>
      -		<p>
      -        <label for="<?php echo esc_attr( $this->get_field_id( 'apikeys' ) ); ?>"><?php esc_html_e( 'Api keys:', 'creatus' ); ?></label>
      -        <select name="<?php echo esc_attr( $this->get_field_name( 'apikeys' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'apikeys' ) ); ?>" class="widefat thz-select-switch">
      -            <option data-enable=".thz-go-twc-<?php echo $this->id?>" data-disable=".thz-twc-<?php echo $this->id?>" value="theme" <?php selected( $instance['apikeys'], 'theme' ); ?>><?php esc_html_e( 'Use theme api keys', 'creatus' ); ?></option>
      -            <option data-enable=".thz-twc-<?php echo $this->id?>" data-disable=".thz-go-twc-<?php echo $this->id?>" value="custom" <?php selected( $instance['apikeys'], 'custom' ); ?>><?php esc_html_e( 'Insert custom api keys', 'creatus' ); ?></option>
      -        </select>
      -		</p>
      -		<p class="thz-go-twc-<?php echo $this->id?>">
      -        	<a href="<?php echo self_admin_url( 'themes.php?page=fw-settings#fw-options-tab-advanced') ?>">
      -        		<?php echo esc_html__('Please go to theme settings and add you Twitter App api keys','creatus'); ?>
      -            </a>
      -        </p>
      -        <div class="thz-twc-<?php echo $this->id?>">
      -			<p><?php echo esc_html__('To obtain Twitter API keys please visit','creatus') ?> <a href="https://dev.twitter.com/apps" target="_blank">https://dev.twitter.com/apps</a> <?php echo esc_html__('and create new application','creatus') ?>.
      -            </p>
      -            <p>
      -                <label for="<?php echo esc_attr($this->get_field_id('consumer_key')); ?>"><?php echo esc_html__('Consumer Key','creatus') ?>:</label>
      -                <input class="widefat" id="<?php echo esc_attr($this->get_field_id('consumer_key')); ?>" name="<?php echo esc_attr($this->get_field_name('consumer_key')); ?>" value="<?php echo esc_attr($instance['consumer_key']); ?>" />
      -            </p>
      -            
      -            <p>
      -                <label for="<?php echo esc_attr($this->get_field_id('consumer_secret')); ?>"><?php echo esc_html__('Consumer Secret','creatus') ?>:</label>
      -                <input class="widefat" id="<?php echo esc_attr($this->get_field_id('consumer_secret')); ?>" name="<?php echo esc_attr($this->get_field_name('consumer_secret')); ?>" value="<?php echo esc_attr($instance['consumer_secret']); ?>" />
      -            </p>
      -    
      -            <p>
      -                <label for="<?php echo esc_attr($this->get_field_id('access_token')); ?>"><?php echo esc_html__('Access Token','creatus') ?>:</label>
      -                <input class="widefat" id="<?php echo esc_attr($this->get_field_id('access_token')); ?>" name="<?php echo esc_attr($this->get_field_name('access_token')); ?>" value="<?php echo esc_attr($instance['access_token']); ?>" />
      -            </p>
      -    
      -            <p>
      -                <label for="<?php echo esc_attr($this->get_field_id('access_token_secret')); ?>"><?php echo esc_html__('Access Token Secret','creatus') ?>:</label>
      -                <input class="widefat" id="<?php echo esc_attr($this->get_field_id('access_token_secret')); ?>" name="<?php echo esc_attr($this->get_field_name('access_token_secret')); ?>" value="<?php echo esc_attr($instance['access_token_secret']); ?>" />
      -            </p>
      -		</div>
      -		<p>
      -			<label for="<?php echo esc_attr($this->get_field_id('twitter_id')); ?>"><?php echo esc_html__('Twitter User','creatus') ?>:</label>
      -			<input class="widefat" id="<?php echo esc_attr($this->get_field_id('twitter_id')); ?>" name="<?php echo esc_attr($this->get_field_name('twitter_id')); ?>" value="<?php echo esc_attr($instance['twitter_id']); ?>" />
      -		</p>
      -
      -			<label for="<?php echo esc_attr($this->get_field_id('count')); ?>"><?php echo esc_html__('Number of Tweets','creatus') ?>:</label>
      -			<input class="widefat" id="<?php echo esc_attr($this->get_field_id('count')); ?>" name="<?php echo esc_attr($this->get_field_name('count')); ?>" value="<?php echo esc_attr($instance['count']); ?>" />
      -
      -
      -        <p>
      -            <label for="<?php echo esc_attr($this->get_field_id('tweet_limit')); ?>"><?php echo esc_html__('Tweet characters limit','creatus') ?>:</label>
      -            <input size="3" style="width: 45px;" class="widefat" id="<?php echo esc_attr($this->get_field_id('tweet_limit')); ?>" name="<?php echo esc_attr($this->get_field_name('tweet_limit')); ?>" value="<?php echo esc_attr($instance['tweet_limit']); ?>" />
      -        </p>
      -
      -
      -        <p>
      -            <input class="checkbox" type="checkbox" <?php checked( $tweet_link, 1 ); ?> id="<?php echo $this->get_field_id( 'tweet_link' ); ?>" name="<?php echo $this->get_field_name( 'tweet_link' ); ?>" /> 
      -            <label for="<?php echo $this->get_field_id( 'tweet_link',1 ); ?>"><?php esc_html_e('Display tweet as link','creatus') ?></label>
      -        </p>
      -
      -        <p>
      -            <input class="checkbox" type="checkbox" <?php checked( $haslist, 1 ); ?> id="<?php echo $this->get_field_id( 'haslist' ); ?>" name="<?php echo $this->get_field_name( 'haslist' ); ?>" /> 
      -            <label for="<?php echo $this->get_field_id( 'haslist',1 ); ?>"><?php esc_html_e('Use .thz-has-list class','creatus') ?></label>
      -        </p>
      -
      -		<p></p>
      -	<?php
      -	}
      -}
      diff --git a/inc/widgets/thz-twitter/index.html b/inc/widgets/thz-twitter/index.html
      deleted file mode 100644
      index e69de29..0000000
      diff --git a/inc/widgets/thz-twitter/views/index.html b/inc/widgets/thz-twitter/views/index.html
      deleted file mode 100644
      index e69de29..0000000
      diff --git a/inc/widgets/thz-twitter/views/widget.php b/inc/widgets/thz-twitter/views/widget.php
      deleted file mode 100644
      index 50c9e7d..0000000
      --- a/inc/widgets/thz-twitter/views/widget.php
      +++ /dev/null
      @@ -1,62 +0,0 @@
      -<?php
      -/**
      - * @package      Thz Framework
      - * @author       Themezly
      - * @websites     http://www.themezly.com | http://www.youjoomla.com | http://www.yjsimplegrid.com
      - */
      - 
      -if ( ! defined( 'ABSPATH' ) ) {
      -	exit; // No direct access
      -}
      -/**
      - * @var $instance
      - * @var $before_widget
      - * @var $after_widget
      - * @var $title
      - */
      -
      -$atts	= array(
      -	'transient' => $transient,
      -	'apikeys' => $instance['apikeys'],
      -	'consumer_key' => $instance['consumer_key'],
      -	'consumer_secret' => $instance['consumer_secret'],
      -	'access_token' => $instance['access_token'],
      -	'access_token_secret' => $instance['access_token_secret'],
      -	'twitter_id' => $instance['twitter_id'],
      -	'count' => $instance['count'],
      -
      -);
      -echo $before_widget;
      -echo $title;
      -
      -$tweets = thz_twitter_feed($atts);
      -?>
      -<?php if($tweets && is_array($tweets)) : ?>
      -<div class="thz-tweets-holder" id="thz_tweets_<?php echo esc_attr($widget_id); ?>">
      -    <ul class="thz-tweets">
      -        <?php foreach($tweets as $tweet): 
      -		
      -		
      -			$tweet_link = 'http://twitter.com/'.esc_attr($tweet->user->screen_name).'/statuses/'.esc_attr($tweet->id_str);
      -			$tweet_text = $tweet_limit > 0 ? substr($tweet->text,0,$tweet_limit)."..." : $tweet->text;
      -			$tweet_title = $tweet_link ? '<a href="'.esc_url($tweet_link).'" target="_blank">'.esc_attr($tweet_text).'</a>' : esc_attr($tweet_text) ;
      -		?>
      -        <li>
      -        	<div class="thz-tweet-container">
      -                <div class="thz-tweet-title">
      -                    <?php echo $tweet_title; ?>
      -                </div>
      -                <span class="thz-tweet-data">
      -                    <a href="<?php echo esc_url($tweet_link); ?>" target="_blank">
      -                        <?php echo thz_twitter_ago( $tweet->created_at ); ?>
      -                    </a>
      -                </span>
      -            </div>
      -        </li>
      -        <?php endforeach; ?>
      -    </ul>
      -</div>
      -<?php else: ?>
      -<?php esc_html_e('No response from Twitter','creatus'); ?>
      -<?php endif; ?>
      -<?php echo $after_widget; ?>
      \ No newline at end of file
      diff --git a/languages/creatus.pot b/languages/creatus.pot
      index bc640f8..57d8f8f 100644
      --- a/languages/creatus.pot
      +++ b/languages/creatus.pot
      @@ -3,23 +3,14 @@ msgid ""
       msgstr ""
       "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
       "Project-Id-Version: Creatus\n"
      -"POT-Creation-Date: 2019-03-08 17:04+0100\n"
      -"PO-Revision-Date: 2017-03-23 13:38+0100\n"
      +"POT-Creation-Date: \n"
      +"PO-Revision-Date: \n"
       "Last-Translator: \n"
       "Language-Team: \n"
       "MIME-Version: 1.0\n"
      -"Content-Type: text/plain; charset=UTF-8\n"
      +"Content-Type: text/plain; charset=iso-8859-1\n"
       "Content-Transfer-Encoding: 8bit\n"
       "X-Generator: Poedit 1.8.13\n"
      -"X-Poedit-Basepath: ..\n"
      -"X-Poedit-WPHeader: style.css\n"
      -"X-Poedit-SourceCharset: UTF-8\n"
      -"X-Poedit-KeywordsList: __;_e;_n:1,2;_x:1,2c;_ex:1,2c;_nx:4c,1,2;esc_attr__;"
      -"esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c;_n_noop:1,2;"
      -"_nx_noop:3c,1,2;__ngettext_noop:1,2\n"
      -"X-Poedit-SearchPath-0: .\n"
      -"X-Poedit-SearchPathExcluded-0: *.js\n"
      -"X-Poedit-SearchPathExcluded-1: languages\n"
       
       #: bbpress/content-statistics.php:26
       msgid "Registered Users"
      @@ -147,92 +138,92 @@ msgstr ""
       msgid "Comments are closed."
       msgstr ""
       
      -#: inc/helpers.php:349
      +#: inc/helpers.php:360
       #, php-format
       msgid "%s has been sucessfuly activated."
       msgstr ""
       
      -#: inc/helpers.php:365
      +#: inc/helpers.php:376
       msgid "Preset file has not been imported."
       msgstr ""
       
      -#: inc/helpers.php:380
      +#: inc/helpers.php:391
       msgid "Something went wrong. Not able to load start preset."
       msgstr ""
       
      -#: inc/helpers.php:982
      +#: inc/helpers.php:993
       msgid "No slides available. Go to Revolution Slider settings and create slides"
       msgstr ""
       
      -#: inc/helpers.php:999
      +#: inc/helpers.php:1010
       msgid "Revolution Slider is not installed"
       msgstr ""
       
      -#: inc/helpers.php:1026
      +#: inc/helpers.php:1037
       msgid "No slides available. Go to Layer Slider settings and create slides"
       msgstr ""
       
      -#: inc/helpers.php:1044
      +#: inc/helpers.php:1055
       msgid "Layer Slider is not installed"
       msgstr ""
       
      -#: inc/helpers.php:1267
      +#: inc/helpers.php:1278
       msgid "Not able to load particles"
       msgstr ""
       
      -#: inc/helpers.php:1638 inc/helpers.php:1778
      +#: inc/helpers.php:1649 inc/helpers.php:1789
       #: woocommerce/myaccount/orders.php:90
       msgid "Previous"
       msgstr ""
       
      -#: inc/helpers.php:1693 inc/helpers.php:1778
      +#: inc/helpers.php:1704 inc/helpers.php:1789
       #: woocommerce/myaccount/orders.php:94
       msgid "Next"
       msgstr ""
       
      -#: inc/helpers.php:2059
      +#: inc/helpers.php:2070
       #, php-format
       msgid "%1$s preferences"
       msgstr ""
       
      -#: inc/helpers.php:2060
      +#: inc/helpers.php:2071
       #, php-format
       msgid "Adjust %1$s preferences"
       msgstr ""
       
      -#: inc/helpers.php:2072
      +#: inc/helpers.php:2083
       msgid "Date link"
       msgstr ""
       
      -#: inc/helpers.php:2074
      +#: inc/helpers.php:2085
       msgid "Link to post"
       msgstr ""
       
      -#: inc/helpers.php:2075
      +#: inc/helpers.php:2086
       msgid "Do not link to post"
       msgstr ""
       
      -#: inc/helpers.php:2080 inc/thzframework/theme/options/heros/title.php:162
      +#: inc/helpers.php:2091 inc/thzframework/theme/options/heros/title.php:162
       #: inc/thzframework/theme/options/posts/project_options.php:220
       msgid "Author link"
       msgstr ""
       
      -#: inc/helpers.php:2082 inc/thzframework/theme/options/heros/title.php:164
      +#: inc/helpers.php:2093 inc/thzframework/theme/options/heros/title.php:164
       #: inc/thzframework/theme/options/posts/project_options.php:222
       msgid "Link to author page"
       msgstr ""
       
      -#: inc/helpers.php:2083 inc/thzframework/theme/options/heros/title.php:165
      +#: inc/helpers.php:2094 inc/thzframework/theme/options/heros/title.php:165
       #: inc/thzframework/theme/options/posts/project_options.php:223
       msgid "Do not link to author page"
       msgstr ""
       
      -#: inc/helpers.php:2087
      +#: inc/helpers.php:2098
       #: inc/thzframework/theme/options/posts/project_options.php:227
       msgid "Author avatar"
       msgstr ""
       
      -#: inc/helpers.php:2095
      +#: inc/helpers.php:2106
       #: inc/includes/option-types/thz-event/class-fw-option-type-thz-event.php:43
       #: inc/includes/option-types/thz-section-builder/items/section/options.php:20
       #: inc/thzframework/extensions/shortcodes/shortcodes/accordion/options.php:145
      @@ -363,7 +354,7 @@ msgstr ""
       msgid "Show"
       msgstr ""
       
      -#: inc/helpers.php:2101
      +#: inc/helpers.php:2112
       #: inc/includes/option-types/thz-event/class-fw-option-type-thz-event.php:47
       #: inc/thzframework/extensions/forms/extensions/contact-forms/shortcodes/contact-form/options.php:93
       #: inc/thzframework/extensions/shortcodes/shortcodes/accordion/options.php:144
      @@ -513,21 +504,21 @@ msgstr ""
       msgid "Hide"
       msgstr ""
       
      -#: inc/helpers.php:2110
      +#: inc/helpers.php:2121
       #: inc/thzframework/theme/options/additional/comments.php:155
       #: inc/thzframework/theme/options/heros/title.php:192
       #: inc/thzframework/theme/options/posts/project_options.php:250
       msgid "Avatar size"
       msgstr ""
       
      -#: inc/helpers.php:2119
      +#: inc/helpers.php:2130
       #: inc/thzframework/theme/options/additional/comments.php:161
       #: inc/thzframework/theme/options/heros/title.php:201
       #: inc/thzframework/theme/options/posts/project_options.php:259
       msgid "Avatar shape"
       msgstr ""
       
      -#: inc/helpers.php:2121 inc/includes/option-types/thz-addable-layer/view.php:38
      +#: inc/helpers.php:2132 inc/includes/option-types/thz-addable-layer/view.php:38
       #: inc/thzframework/extensions/media/extensions/slider/extensions/slick-full/options/options.php:102
       #: inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php:245
       #: inc/thzframework/extensions/shortcodes/shortcodes/icon-box/options.php:400
      @@ -561,11 +552,10 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/single_image.php:57
       #: inc/thzframework/theme/options/woo/single_image.php:338
       #: inc/thzframework/theme/options/woo/subcat_style.php:54
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:232
       msgid "Square"
       msgstr ""
       
      -#: inc/helpers.php:2122
      +#: inc/helpers.php:2133
       #: inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php:246
       #: inc/thzframework/extensions/shortcodes/shortcodes/icon-box/options.php:401
       #: inc/thzframework/extensions/shortcodes/shortcodes/icon/options.php:478
      @@ -589,7 +579,7 @@ msgstr ""
       msgid "Rounded"
       msgstr ""
       
      -#: inc/helpers.php:2123 inc/includes/option-types/thz-background/view.php:428
      +#: inc/helpers.php:2134 inc/includes/option-types/thz-background/view.php:428
       #: inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php:244
       #: inc/thzframework/extensions/shortcodes/shortcodes/icon-box/options.php:399
       #: inc/thzframework/extensions/shortcodes/shortcodes/icon/options.php:476
      @@ -614,16 +604,16 @@ msgstr ""
       msgid "Circle"
       msgstr ""
       
      -#: inc/helpers.php:2131 inc/thzframework/theme/options/heros/title.php:226
      +#: inc/helpers.php:2142 inc/thzframework/theme/options/heros/title.php:226
       #: inc/thzframework/theme/options/posts/project_options.php:271
       msgid "Avatar space"
       msgstr ""
       
      -#: inc/helpers.php:2171
      +#: inc/helpers.php:2182
       msgid "Views"
       msgstr ""
       
      -#: inc/helpers.php:2172 inc/thzframework/theme/options/heros/sub_title.php:129
      +#: inc/helpers.php:2183 inc/thzframework/theme/options/heros/sub_title.php:129
       #: inc/thzframework/theme/options/posts/project_options.php:71
       #: inc/thzframework/theme/options/posts/project_options.php:104
       #: template-parts/events/event-grid.php:129
      @@ -632,125 +622,124 @@ msgstr ""
       msgid "Date"
       msgstr ""
       
      -#: inc/helpers.php:2173 inc/thzframework/theme/options/blog/quote_format.php:51
      +#: inc/helpers.php:2184 inc/thzframework/theme/options/blog/quote_format.php:51
       #: inc/thzframework/theme/options/blog/single.php:47
       #: inc/thzframework/theme/options/heros/sub_title.php:131
       #: inc/thzframework/theme/options/pagetemplates/settings.php:21
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:176
       msgid "Author"
       msgstr ""
       
      -#: inc/helpers.php:2174 inc/includes/option-types/thz-menu-list/view.php:141
      +#: inc/helpers.php:2185 inc/includes/option-types/thz-menu-list/view.php:141
       #: inc/thzframework/theme/options/heros/sub_title.php:130
       #: template-parts/events/event-grid.php:144
       #: template-parts/events/event-sidebar.php:184
       msgid "Categories"
       msgstr ""
       
      -#: inc/helpers.php:2175 inc/thzframework/theme/options/blog/single.php:41
      +#: inc/helpers.php:2186 inc/thzframework/theme/options/blog/single.php:41
       #: inc/thzframework/theme/options/posts/project_options.php:70
       #: inc/thzframework/theme/options/posts/project_options.php:89
       msgid "Tags"
       msgstr ""
       
      -#: inc/helpers.php:2176
      +#: inc/helpers.php:2187
       msgid "Comments count"
       msgstr ""
       
      -#: inc/helpers.php:2177 inc/helpers.php:2334 inc/static.php:73
      +#: inc/helpers.php:2188 inc/helpers.php:2345 inc/static.php:73
       msgid "Likes"
       msgstr ""
       
      -#: inc/helpers.php:2212
      +#: inc/helpers.php:2223
       msgid "views"
       msgstr ""
       
      -#: inc/helpers.php:2269 inc/helpers.php:3421
      +#: inc/helpers.php:2280 inc/helpers.php:3442
       msgid "by"
       msgstr ""
       
      -#: inc/helpers.php:2334 inc/static.php:72
      +#: inc/helpers.php:2345 inc/static.php:72
       msgid "Like"
       msgstr ""
       
      -#: inc/helpers.php:2537 inc/helpers.php:2542
      +#: inc/helpers.php:2548 inc/helpers.php:2553
       msgid "comments"
       msgstr ""
       
      -#: inc/helpers.php:2547
      +#: inc/helpers.php:2558
       msgid "comment"
       msgstr ""
       
      -#: inc/helpers.php:3141
      +#: inc/helpers.php:3152
       msgid "Do not assign position"
       msgstr ""
       
      -#: inc/helpers.php:3142 inc/thzframework/theme/options/heros/heros.php:59
      +#: inc/helpers.php:3153 inc/thzframework/theme/options/heros/heros.php:59
       msgid "Above the header"
       msgstr ""
       
      -#: inc/helpers.php:3143 inc/thzframework/theme/options/heros/heros.php:63
      +#: inc/helpers.php:3154 inc/thzframework/theme/options/heros/heros.php:63
       msgid "Under the header"
       msgstr ""
       
      -#: inc/helpers.php:3144
      +#: inc/helpers.php:3155
       msgid "Under the hero section"
       msgstr ""
       
      -#: inc/helpers.php:3145
      +#: inc/helpers.php:3156
       msgid "Above the footer section"
       msgstr ""
       
      -#: inc/helpers.php:3146
      +#: inc/helpers.php:3157
       msgid "Between the footer section and branding"
       msgstr ""
       
      -#: inc/helpers.php:3147
      +#: inc/helpers.php:3158
       msgid "Under the footer branding"
       msgstr ""
       
      -#: inc/helpers.php:3148
      +#: inc/helpers.php:3159
       msgid "Above the post"
       msgstr ""
       
      -#: inc/helpers.php:3149
      +#: inc/helpers.php:3160
       msgid "Under the post"
       msgstr ""
       
      -#: inc/helpers.php:3150
      +#: inc/helpers.php:3161
       msgid "Above the related posts"
       msgstr ""
       
      -#: inc/helpers.php:3151
      +#: inc/helpers.php:3162
       msgid "Under the related posts"
       msgstr ""
       
      -#: inc/helpers.php:3152
      +#: inc/helpers.php:3163
       msgid "Offcanvas Overlay"
       msgstr ""
       
      -#: inc/helpers.php:3329
      +#: inc/helpers.php:3350
       #: inc/thzframework/theme/options/customizer/options_accordions.php:399
       #: inc/thzframework/theme/options/taxonomies/product_cat.php:46
       #: inc/thzframework/theme/options/woo/settings.php:13
       msgid "Shop"
       msgstr ""
       
      -#: inc/helpers.php:3332
      +#: inc/helpers.php:3353
       msgid "Search Results for:"
       msgstr ""
       
      -#: inc/helpers.php:3335
      +#: inc/helpers.php:3356
       #: inc/thzframework/theme/options/pagetemplates/settings.php:13
       #: template-parts/404-section.php:19
       msgid "404"
       msgstr ""
       
      -#: inc/helpers.php:3407
      +#: inc/helpers.php:3428
       msgid "in"
       msgstr ""
       
      -#: inc/helpers.php:3553
      +#: inc/helpers.php:3574
       #: inc/thzframework/theme/options/advanced/customizer.php:52
       #: inc/thzframework/theme/options/advanced/customizer.php:89
       #: inc/thzframework/theme/options/customizer/options_accordions.php:86
      @@ -758,19 +747,19 @@ msgstr ""
       msgid "Blog"
       msgstr ""
       
      -#: inc/helpers.php:4885
      +#: inc/helpers.php:4915 inc/helpers.php:5958 inc/helpers.php:4885
       msgid "Start typing"
       msgstr ""
       
      -#: inc/helpers.php:5101
      +#: inc/helpers.php:5131 inc/helpers.php:5101
       msgid "Search..."
       msgstr ""
       
      -#: inc/helpers.php:5913
      +#: inc/helpers.php:5954 inc/helpers.php:5913
       msgid "Select metro layout"
       msgstr ""
       
      -#: inc/helpers.php:5916
      +#: inc/helpers.php:5957 inc/helpers.php:5916
       msgid "Select desired metro layout. See help for more info"
       msgstr ""
       
      @@ -782,11 +771,14 @@ msgid ""
       "\"Packery\""
       msgstr ""
       
      -#: inc/helpers.php:6731 inc/includes/woocommerce/hooks.php:226
      +#: inc/helpers.php:6771 inc/includes/woocommerce/hooks.php:226
      +#: inc/helpers.php:6781 inc/helpers.php:6798 inc/helpers.php:6838
      +#: inc/helpers.php:6731
       msgid "Select Options"
       msgstr ""
       
      -#: inc/helpers.php:6736 inc/includes/woocommerce/hooks.php:231
      +#: inc/helpers.php:6776 inc/includes/woocommerce/hooks.php:231
      +#: inc/helpers.php:6736
       msgid "View Options"
       msgstr ""
       
      @@ -797,7 +789,8 @@ msgstr ""
       msgid "More Info"
       msgstr ""
       
      -#: inc/helpers.php:6746 inc/includes/woocommerce/hooks.php:241
      +#: inc/helpers.php:6786 inc/includes/woocommerce/hooks.php:241
      +#: inc/helpers.php:6794 inc/helpers.php:6858 inc/helpers.php:6746
       msgid "Add to Cart"
       msgstr ""
       
      @@ -808,13 +801,13 @@ msgstr ""
       msgid "View cart"
       msgstr ""
       
      -#: inc/helpers.php:6787 inc/includes/woocommerce/hooks.php:282
      -#: woocommerce/single-product/sale-flash.php:37
      +#: inc/helpers.php:6827 inc/includes/woocommerce/hooks.php:282
      +#: inc/helpers.php:6787 woocommerce/single-product/sale-flash.php:37
       msgid "Out of stock!"
       msgstr ""
       
      -#: inc/helpers.php:6807 inc/includes/woocommerce/hooks.php:302
      -#: woocommerce/single-product/sale-flash.php:32
      +#: inc/helpers.php:6847 inc/includes/woocommerce/hooks.php:302
      +#: inc/helpers.php:6807 woocommerce/single-product/sale-flash.php:32
       msgid "Sale!"
       msgstr ""
       
      @@ -834,194 +827,192 @@ msgstr ""
       msgid "Medium Large"
       msgstr ""
       
      -#: inc/hooks.php:736
      +#: inc/hooks.php:622
       #, php-format
       msgid ""
       "Please visit <a href=\"%s\">System info page</a> before saving and make sure "
       "all values are marked with green check."
       msgstr ""
       
      -#: inc/hooks.php:765
      +#: inc/hooks.php:651
       msgid " Magnific popup"
       msgstr ""
       
      -#: inc/hooks.php:766
      +#: inc/hooks.php:652
       msgid ""
       "If link is not an image the popup will be opened as Magnific popup iframe."
       msgstr ""
       
      -#: inc/hooks.php:767
      -#: inc/includes/builder-templates/class-thz-builder-templates.php:109
      -#: inc/includes/builder-templates/views/sections.php:24
      +#: inc/hooks.php:653
       msgid "Template Library"
       msgstr ""
       
      -#: inc/hooks.php:860
      +#: inc/hooks.php:746
       msgid "Passowrd or login guess hints are disabled"
       msgstr ""
       
      -#: inc/hooks.php:923 inc/hooks.php:1163
      +#: inc/hooks.php:809 inc/hooks.php:1049
       #: inc/includes/option-types/thz-assign-to/class-fw-option-type-thz-assign-to.php:292
       #: inc/includes/option-types/thz-content-layout/class-fw-option-type-thz-content-layout.php:100
       msgid "-no title"
       msgstr ""
       
      -#: inc/hooks.php:1454
      +#: inc/hooks.php:1340
       msgid "Table Type"
       msgstr ""
       
      -#: inc/hooks.php:1498
      +#: inc/hooks.php:1384
       msgid "Read more"
       msgstr ""
       
      -#: inc/hooks.php:1893 inc/widgets/thz-twitter/views/widget.php:60
      +#: inc/hooks.php:1779
       msgid "No response from Twitter"
       msgstr ""
       
      -#: inc/hooks.php:2171
      +#: inc/hooks.php:2043
       msgid "Dropcaps"
       msgstr ""
       
      -#: inc/hooks.php:2174
      +#: inc/hooks.php:2046
       msgid "Dropcap"
       msgstr ""
       
      -#: inc/hooks.php:2180
      +#: inc/hooks.php:2052
       msgid "Dropcap box"
       msgstr ""
       
      -#: inc/hooks.php:2186
      +#: inc/hooks.php:2058
       msgid "Dropcap box outline"
       msgstr ""
       
      -#: inc/hooks.php:2192
      +#: inc/hooks.php:2064
       msgid "Dropcap rounded"
       msgstr ""
       
      -#: inc/hooks.php:2198
      +#: inc/hooks.php:2070
       msgid "Dropcap rounded outline"
       msgstr ""
       
      -#: inc/hooks.php:2204
      +#: inc/hooks.php:2076
       msgid "Dropcap circle"
       msgstr ""
       
      -#: inc/hooks.php:2210
      +#: inc/hooks.php:2082
       msgid "Dropcap circle outline"
       msgstr ""
       
      -#: inc/hooks.php:2218
      +#: inc/hooks.php:2090
       msgid "Theme Styles"
       msgstr ""
       
      -#: inc/hooks.php:2221
      +#: inc/hooks.php:2093
       msgid "Highlight"
       msgstr ""
       
      -#: inc/hooks.php:2226
      +#: inc/hooks.php:2098
       msgid "Bold primary color"
       msgstr ""
       
      -#: inc/hooks.php:2231
      +#: inc/hooks.php:2103
       msgid "Primary color"
       msgstr ""
       
      -#: inc/hooks.php:2236
      +#: inc/hooks.php:2108
       msgid "Muted color"
       msgstr ""
       
      -#: inc/hooks.php:2241
      +#: inc/hooks.php:2113
       msgid "Dark color"
       msgstr ""
       
      -#: inc/hooks.php:2246
      +#: inc/hooks.php:2118
       #: inc/thzframework/extensions/shortcodes/shortcodes/special-heading/options.php:144
       msgid "Underline"
       msgstr ""
       
      -#: inc/hooks.php:2251
      +#: inc/hooks.php:2123
       msgid "Underline primary"
       msgstr ""
       
      -#: inc/hooks.php:2259
      +#: inc/hooks.php:2131
       msgid "Font sizes"
       msgstr ""
       
      -#: inc/hooks.php:2262
      +#: inc/hooks.php:2134
       #: inc/thzframework/extensions/shortcodes/shortcodes/media-gallery/options.php:598
       #: inc/thzframework/theme/options/advanced/images.php:45
       msgid "Small"
       msgstr ""
       
      -#: inc/hooks.php:2267
      +#: inc/hooks.php:2139
       msgid "Font medium"
       msgstr ""
       
      -#: inc/hooks.php:2272
      +#: inc/hooks.php:2144
       msgid "Font large"
       msgstr ""
       
      -#: inc/hooks.php:2277
      +#: inc/hooks.php:2149
       msgid "Font Xlarge"
       msgstr ""
       
      -#: inc/hooks.php:2282
      +#: inc/hooks.php:2154
       msgid "Font Jumbo"
       msgstr ""
       
      -#: inc/hooks.php:2287
      +#: inc/hooks.php:2159
       msgid "Font Mega"
       msgstr ""
       
      -#: inc/hooks.php:2295
      +#: inc/hooks.php:2167
       msgid "Content widths"
       msgstr ""
       
      -#: inc/hooks.php:2298
      +#: inc/hooks.php:2170
       msgid "85 percent container"
       msgstr ""
       
      -#: inc/hooks.php:2305
      +#: inc/hooks.php:2177
       msgid "75 percent container"
       msgstr ""
       
      -#: inc/hooks.php:2311
      +#: inc/hooks.php:2183
       msgid "50 percent container"
       msgstr ""
       
      -#: inc/hooks.php:2318
      +#: inc/hooks.php:2190
       msgid "40 percent container"
       msgstr ""
       
      -#: inc/hooks.php:2325
      +#: inc/hooks.php:2197
       msgid "Stretch full width"
       msgstr ""
       
      -#: inc/hooks.php:2332
      +#: inc/hooks.php:2204
       msgid "Stretch site width"
       msgstr ""
       
      -#: inc/hooks.php:2339
      +#: inc/hooks.php:2211
       msgid "2 text columns"
       msgstr ""
       
      -#: inc/hooks.php:2346
      +#: inc/hooks.php:2218
       msgid "3 text columns"
       msgstr ""
       
      -#: inc/hooks.php:2353
      +#: inc/hooks.php:2225
       msgid "4 text columns"
       msgstr ""
       
      -#: inc/hooks.php:2360
      +#: inc/hooks.php:2232
       msgid "5 text columns"
       msgstr ""
       
      -#: inc/hooks.php:2367
      +#: inc/hooks.php:2239
       msgid "6 text columns"
       msgstr ""
       
      -#: inc/hooks.php:2376
      +#: inc/hooks.php:2248
       #: inc/includes/option-types/thz-panel-builder/items/section/options.php:160
       #: inc/includes/option-types/thz-section-builder/items/section/options.php:115
       #: inc/thzframework/extensions/shortcodes/shortcodes/section/options.php:135
      @@ -1033,86 +1024,86 @@ msgstr ""
       msgid "Containers"
       msgstr ""
       
      -#: inc/hooks.php:2379
      +#: inc/hooks.php:2251
       msgid "Div"
       msgstr ""
       
      -#: inc/hooks.php:2385
      +#: inc/hooks.php:2257
       #: inc/includes/option-types/thz-panel-builder/items/section/class-fw-option-type-thz-panel-builder-item-section.php:24
       #: inc/includes/option-types/thz-section-builder/items/section/class-fw-option-type-thz-section-builder-item-section.php:24
       #: inc/thzframework/extensions/shortcodes/shortcodes/section/config.php:18
       msgid "Section"
       msgstr ""
       
      -#: inc/hooks.php:2394
      +#: inc/hooks.php:2266
       msgid "Blockquotes"
       msgstr ""
       
      -#: inc/hooks.php:2397
      +#: inc/hooks.php:2269
       msgid "Blockquote"
       msgstr ""
       
      -#: inc/hooks.php:2402
      +#: inc/hooks.php:2274
       msgid "Pullquote"
       msgstr ""
       
      -#: inc/hooks.php:2408
      +#: inc/hooks.php:2280
       msgid "Blockquote right"
       msgstr ""
       
      -#: inc/hooks.php:2413
      +#: inc/hooks.php:2285
       msgid "Blockquote centered"
       msgstr ""
       
      -#: inc/hooks.php:2418
      +#: inc/hooks.php:2290
       msgid "Blockquote quoted"
       msgstr ""
       
      -#: inc/hooks.php:2424
      +#: inc/hooks.php:2296
       msgid "Blockquote brackets"
       msgstr ""
       
      -#: inc/hooks.php:2586
      +#: inc/hooks.php:2458
       msgid "Password:"
       msgstr ""
       
      -#: inc/hooks.php:2587
      +#: inc/hooks.php:2459
       msgid "Enter post password"
       msgstr ""
       
      -#: inc/hooks.php:2592
      +#: inc/hooks.php:2464
       msgctxt "post password form"
       msgid "Enter"
       msgstr ""
       
      -#: inc/hooks.php:2687
      +#: inc/hooks.php:2559
       msgid "Logged in ( overrides all roles above ) "
       msgstr ""
       
      -#: inc/hooks.php:2691
      +#: inc/hooks.php:2563
       msgid "Logged out ( site visitors only )"
       msgstr ""
       
      -#: inc/hooks.php:2752 inc/thzframework/theme/options/posts/forum.php:12
      +#: inc/hooks.php:2624 inc/thzframework/theme/options/posts/forum.php:12
       msgid "Add CSS for this page"
       msgstr ""
       
      -#: inc/hooks.php:2753 inc/thzframework/theme/options/posts/forum.php:13
      +#: inc/hooks.php:2625 inc/thzframework/theme/options/posts/forum.php:13
       msgid "Page CSS is active"
       msgstr ""
       
      -#: inc/hooks.php:2754 inc/hooks.php:2765 inc/hooks.php:2775
      +#: inc/hooks.php:2626 inc/hooks.php:2637 inc/hooks.php:2647
       #: inc/thzframework/theme/options/posts/forum.php:14
       #: inc/thzframework/theme/options/posts/forum.php:25
       #: inc/thzframework/theme/options/posts/forum.php:35
       msgid "Page CSS"
       msgstr ""
       
      -#: inc/hooks.php:2760 inc/thzframework/theme/options/posts/forum.php:20
      +#: inc/hooks.php:2632 inc/thzframework/theme/options/posts/forum.php:20
       msgid "Click to add page CSS"
       msgstr ""
       
      -#: inc/hooks.php:2766 inc/thzframework/theme/options/posts/forum.php:26
      +#: inc/hooks.php:2638 inc/thzframework/theme/options/posts/forum.php:26
       #: inc/thzframework/theme/options/posts/fw-event.php:39
       #: inc/thzframework/theme/options/posts/fw-portfolio.php:39
       #: inc/thzframework/theme/options/posts/post.php:42
      @@ -1126,7 +1117,7 @@ msgid ""
       "#thz-wrapper before selector to avoid the use of !important rule."
       msgstr ""
       
      -#: inc/hooks.php:2782 inc/hooks.php:2831
      +#: inc/hooks.php:2654 inc/hooks.php:2703
       #: inc/thzframework/theme/options/posts/forum.php:40
       #: inc/thzframework/theme/options/posts/fw-event.php:57
       #: inc/thzframework/theme/options/posts/fw-portfolio.php:56
      @@ -1138,7 +1129,7 @@ msgstr ""
       msgid "Creatus options"
       msgstr ""
       
      -#: inc/hooks.php:2786 inc/thzframework/theme/options/posts/forum.php:45
      +#: inc/hooks.php:2658 inc/thzframework/theme/options/posts/forum.php:45
       #: inc/thzframework/theme/options/posts/fw-event.php:70
       #: inc/thzframework/theme/options/posts/fw-portfolio.php:80
       #: inc/thzframework/theme/options/posts/page.php:27
      @@ -1148,111 +1139,107 @@ msgstr ""
       msgid "Page options"
       msgstr ""
       
      -#: inc/hooks.php:2851 inc/hooks.php:2854
      +#: inc/hooks.php:2723 inc/hooks.php:2726
       #: inc/thzframework/theme/options/taxonomies/product_cat.php:32
       msgid "Custom posts options"
       msgstr ""
       
      -#: inc/hooks.php:2852
      +#: inc/hooks.php:2724
       msgid ""
       "Add custom posts options for this category or leave as is for theme defaults."
       msgstr ""
       
      -#: inc/hooks.php:2853
      +#: inc/hooks.php:2725
       msgid "Custom posts options are set"
       msgstr ""
       
      -#: inc/hooks.php:2857
      +#: inc/hooks.php:2729
       #: inc/thzframework/theme/options/taxonomies/product_cat.php:41
       msgid "Add custom posts options"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:169
      +#: inc/includes/auto-setup/class-thz-auto-install.php:167
       #, php-format
       msgid "Failed to activate supported extensions. %s "
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:229
      +#: inc/includes/auto-setup/class-thz-auto-install.php:227
       #, php-format
       msgid ""
       "This option will activate theme dependencies. You will %1$s not be "
       "redirected to demo content installer %2$s."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:230
      +#: inc/includes/auto-setup/class-thz-auto-install.php:228
       #, php-format
       msgid ""
       "This option will activate theme dependencies and %1$s redirect you to demo "
       "content installer %2$s."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:231
      +#: inc/includes/auto-setup/class-thz-auto-install.php:229
       msgid ""
       "Skip the auto setup all together and activate all the theme dependencies "
       "manually. Note that this page will not be  accessible until you deactivate/"
       "activate the theme again."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:282
      +#: inc/includes/auto-setup/class-thz-auto-install.php:280
       msgid ""
       "Attention, the installation process is not finished, if you leave this page "
       "the information stored will be lost!"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:283
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:499
      +#: inc/includes/auto-setup/class-thz-auto-install.php:281
       msgid "Sorry, we've encountered some errors, try to access this page later."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:284
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:500
      +#: inc/includes/auto-setup/class-thz-auto-install.php:282
       msgid "The installation process was completed successfully."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:353
      +#: inc/includes/auto-setup/class-thz-auto-install.php:351
       msgid "Activating supported extensions"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:358
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:584
      +#: inc/includes/auto-setup/class-thz-auto-install.php:356
       msgid "Finish installing process"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:492
      +#: inc/includes/auto-setup/class-thz-auto-install.php:490
       msgid "Installing, please wait"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:493
      +#: inc/includes/auto-setup/class-thz-auto-install.php:491
       msgid "Installing required plugins, please wait ..."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:494
      +#: inc/includes/auto-setup/class-thz-auto-install.php:492
       msgid "Finished installing required plugins, please wait"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:495
      +#: inc/includes/auto-setup/class-thz-auto-install.php:493
       msgid "Activating required plugins, please wait..."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:496
      +#: inc/includes/auto-setup/class-thz-auto-install.php:494
       msgid "Finished Activating required plugins, please wait"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:512
      -#: inc/includes/auto-setup/class-thz-auto-install.php:677
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:137
      +#: inc/includes/auto-setup/class-thz-auto-install.php:510
      +#: inc/includes/auto-setup/class-thz-auto-install.php:673
       msgid "Activate required demo plugins"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:534
      +#: inc/includes/auto-setup/class-thz-auto-install.php:532
       msgid "Activating Unyson"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:539
      +#: inc/includes/auto-setup/class-thz-auto-install.php:537
       msgid "Activate required plugins"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:547
      +#: inc/includes/auto-setup/class-thz-auto-install.php:545
       #, php-format
       msgid ""
       "This option will activate %1$s already installed plugins and dependencies "
      @@ -1260,189 +1247,120 @@ msgid ""
       "content installer %4$s."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:548
      +#: inc/includes/auto-setup/class-thz-auto-install.php:546
       #, php-format
       msgid ""
       "This option will activate theme dependencies %1$s and redirect you to theme "
       "demo content installer %2$s."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:549
      +#: inc/includes/auto-setup/class-thz-auto-install.php:547
       msgid ""
       "Skip the auto setup all together and activate all the plugins manually. Note "
       "that this page will not be accessible until you deactivate/activate the "
       "theme again."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:610
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:211
      +#: inc/includes/auto-setup/class-thz-auto-install.php:608
       msgid "Current user can't activate plugins"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:627
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:228
      +#: inc/includes/auto-setup/class-thz-auto-install.php:625
       #, php-format
       msgid "Failed to activate required plugins. %s"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:682
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:142
      +#: inc/includes/auto-setup/class-thz-auto-install.php:678
       msgid "Install required demo plugins"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:707
      -#: inc/includes/auto-setup/class-thz-auto-install.php:889
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:167
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:304
      +#: inc/includes/auto-setup/class-thz-auto-install.php:703
      +#: inc/includes/auto-setup/class-thz-auto-install.php:877
       #, php-format
       msgid "Failed to install required plugins. Folder %s is not writable"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:728
      -#: inc/includes/auto-setup/class-thz-auto-install.php:908
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:189
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:351
      +#: inc/includes/auto-setup/class-thz-auto-install.php:724
      +#: inc/includes/auto-setup/class-thz-auto-install.php:896
       #, php-format
       msgid "Failed to install required plugins. %s"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:746
      +#: inc/includes/auto-setup/class-thz-auto-install.php:742
       msgid "Downloading and installing Unyson"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:751
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:579
      +#: inc/includes/auto-setup/class-thz-auto-install.php:747
       msgid "Installing required plugins"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:756
      +#: inc/includes/auto-setup/class-thz-auto-install.php:752
       msgid "Installing supported extensions"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:761
      -msgid "Downloading and installing child theme"
      -msgstr ""
      -
      -#: inc/includes/auto-setup/class-thz-auto-install.php:796
      -#: inc/includes/auto-setup/class-thz-auto-install.php:854
      -#: inc/includes/auto-setup/class-thz-auto-install.php:880
      +#: inc/includes/auto-setup/class-thz-auto-install.php:784
      +#: inc/includes/auto-setup/class-thz-auto-install.php:842
      +#: inc/includes/auto-setup/class-thz-auto-install.php:868
       msgid "Current user can't install plugins"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:805
      +#: inc/includes/auto-setup/class-thz-auto-install.php:793
       #, php-format
       msgid "Failed to install supported extensions. Folder %s is not writable"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:838
      +#: inc/includes/auto-setup/class-thz-auto-install.php:826
       #, php-format
       msgid "Failed to install supported extensions. %s "
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:862
      +#: inc/includes/auto-setup/class-thz-auto-install.php:850
       #, php-format
       msgid "Failed to install Unyson. Folder %s is not writable"
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:922
      -msgid ""
      -"Current user can't install themes or child theme source must be specified"
      -msgstr ""
      -
      -#: inc/includes/auto-setup/class-thz-auto-install.php:930
      -#, php-format
      -msgid "Failed to install Theme. Folder %s is not writable"
      -msgstr ""
      -
      -#: inc/includes/auto-setup/class-thz-auto-install.php:968
      +#: inc/includes/auto-setup/class-thz-auto-install.php:909
       #, php-format
       msgid ""
       "This option will install and activate all theme plugins and dependencies and "
       "%1$s redirect you to theme demo content installer%2$s."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:969
      +#: inc/includes/auto-setup/class-thz-auto-install.php:910
       #, php-format
       msgid ""
       "This option will install and activate all theme plugins and dependencies. "
       "You will %1$s not be redirected to theme demo content installer%2$s."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:970
      +#: inc/includes/auto-setup/class-thz-auto-install.php:911
       msgid ""
       "Skip the auto setup all together and install all the plugins manually. Note "
       "that this page will not be accessible until you deactivate/activate the "
       "theme again."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:1084
      +#: inc/includes/auto-setup/class-thz-auto-install.php:1025
       msgid "Plugin is already installed."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:1118
      +#: inc/includes/auto-setup/class-thz-auto-install.php:1059
       #, php-format
       msgid "It was not possible to activate %s. Because it isn't installed."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:1149
      +#: inc/includes/auto-setup/class-thz-auto-install.php:1090
       msgid "Current user can't activate plugins."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-auto-install.php:1196
      -#: inc/includes/auto-setup/class-thz-auto-install.php:1200
      +#: inc/includes/auto-setup/class-thz-auto-install.php:1137
      +#: inc/includes/auto-setup/class-thz-auto-install.php:1141
       msgid ""
       "An unexpected error occurred. Something may be wrong with WordPress.org or "
       "this server&#8217;s configuration. If you continue to have problems, please "
       "try the <a href=\"http://wordpress.org/support/\">support forums</a>."
       msgstr ""
       
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:117
      -msgid "Installing"
      -msgstr ""
      -
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:118
      -msgid "Installing required plugins ..."
      -msgstr ""
      -
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:119
      -msgid "Finished installing required plugins"
      -msgstr ""
      -
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:120
      -msgid "Activating required plugins ..."
      -msgstr ""
      -
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:121
      -msgid "Finished activating required plugins"
      -msgstr ""
      -
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:436
      -#, php-format
      -msgid ""
      -"This option will activate Unyson dependencies. The %1$s demo content will "
      -"not be installed %2$s."
      -msgstr ""
      -
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:437
      -#, php-format
      -msgid ""
      -"This option will activate Unyson dependencies together %1$s with the demo "
      -"content %2$s for the theme."
      -msgstr ""
      -
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:438
      -msgid ""
      -"Skip the auto setup all together and activate all the Unyson dependencies "
      -"manually. Note that this page will not be  accessible until you install the "
      -"theme again."
      -msgstr ""
      -
      -#: inc/includes/auto-setup/class-thz-plugins-install.php:498
      -msgid ""
      -"Attention, the installation process is not yet finished, if you leave this "
      -"page, you will lose the information stored on the site!"
      -msgstr ""
      -
       #: inc/includes/auto-setup/views/auto_setup.php:5
       #: inc/includes/class-tgm-plugin-activation.php:3573
       msgid ""
      @@ -1450,85 +1368,51 @@ msgid ""
       "hosts, so please be patient."
       msgstr ""
       
      -#: inc/includes/auto-setup/views/install_setup.php:5
      -msgid "Themezly Plugins Updates"
      -msgstr ""
      -
      -#: inc/includes/auto-setup/views/install_setup.php:11
      -msgid "Plugins Update"
      -msgstr ""
      -
      -#: inc/includes/auto-setup/views/install_setup.php:15
      -msgid ""
      -"This utility can reinstall the latest versions of plugins provided by "
      -"Themezly.com. Check the plugins you wish to update than click on Update "
      -"Plugins button."
      -msgstr ""
      -
      -#: inc/includes/auto-setup/views/install_setup.php:17
      -msgid "Update All"
      -msgstr ""
      -
      -#: inc/includes/auto-setup/views/install_setup.php:28
      -msgid "Not installed"
      -msgstr ""
      -
      -#: inc/includes/auto-setup/views/install_setup.php:51
      -#: inc/includes/auto-setup/views/install_setup.php:86
      -#: inc/includes/auto-setup/views/install_setup.php:125
      -#: inc/includes/auto-setup/views/install_setup.php:164
      -#, php-format
      -msgid "%s Plugin"
      -msgstr ""
      -
      -#: inc/includes/auto-setup/views/install_setup.php:57
      -msgid "Update Plugins"
      -msgstr ""
      -
      -#: inc/includes/auto-setup/views/install_setup.php:64
      +#: inc/includes/auto-setup/views/install_setup.php:4
       msgid "Auto Setup"
       msgstr ""
       
      -#: inc/includes/auto-setup/views/install_setup.php:65
      +#: inc/includes/auto-setup/views/install_setup.php:5
       msgid "Choose one of the install methods below."
       msgstr ""
       
      -#: inc/includes/auto-setup/views/install_setup.php:72
      +#: inc/includes/auto-setup/views/install_setup.php:12
       msgid "Plugins & Demo Content"
       msgstr ""
       
      -#: inc/includes/auto-setup/views/install_setup.php:82
      -#: inc/includes/auto-setup/views/install_setup.php:121
      -#: inc/includes/auto-setup/views/install_setup.php:160
      +#: inc/includes/auto-setup/views/install_setup.php:22
      +#: inc/includes/auto-setup/views/install_setup.php:57
      +#: inc/includes/auto-setup/views/install_setup.php:92
       msgid "Unyson Framework"
       msgstr ""
       
      -#: inc/includes/auto-setup/views/install_setup.php:90
      -#: inc/includes/auto-setup/views/install_setup.php:129
      -#: inc/includes/auto-setup/views/install_setup.php:168
      -msgid "Download and Activate Child Theme"
      +#: inc/includes/auto-setup/views/install_setup.php:26
      +#: inc/includes/auto-setup/views/install_setup.php:61
      +#: inc/includes/auto-setup/views/install_setup.php:96
      +#, php-format
      +msgid "%s Plugin"
       msgstr ""
       
      -#: inc/includes/auto-setup/views/install_setup.php:94
      -#: inc/includes/auto-setup/views/install_setup.php:133
      -#: inc/includes/auto-setup/views/install_setup.php:172
      +#: inc/includes/auto-setup/views/install_setup.php:30
      +#: inc/includes/auto-setup/views/install_setup.php:65
      +#: inc/includes/auto-setup/views/install_setup.php:100
       msgid "Redirect to Demo Content Installer"
       msgstr ""
       
      -#: inc/includes/auto-setup/views/install_setup.php:100
      +#: inc/includes/auto-setup/views/install_setup.php:36
       msgid "Install Plugins & Demo Content"
       msgstr ""
       
      -#: inc/includes/auto-setup/views/install_setup.php:111
      +#: inc/includes/auto-setup/views/install_setup.php:47
       msgid "Plugins Only"
       msgstr ""
       
      -#: inc/includes/auto-setup/views/install_setup.php:139
      +#: inc/includes/auto-setup/views/install_setup.php:71
       msgid "Install Plugins Only"
       msgstr ""
       
      -#: inc/includes/auto-setup/views/install_setup.php:150
      -#: inc/includes/auto-setup/views/install_setup.php:178
      +#: inc/includes/auto-setup/views/install_setup.php:82
      +#: inc/includes/auto-setup/views/install_setup.php:106
       msgid "Skip Auto Setup"
       msgstr ""
       
      @@ -1895,50 +1779,32 @@ msgstr ""
       msgid "fsockopen/cURL"
       msgstr ""
       
      -#: inc/includes/auto-setup/views/system_info.php:292
      -msgid "System info"
      +#: inc/includes/auto-setup/views/system_info.php:293
      +msgid "Please consider using Creatus Child Theme for any custom modifications."
       msgstr ""
       
       #: inc/includes/auto-setup/views/system_info.php:294
      +msgid "Download Creatus Child Theme"
      +msgstr ""
      +
      +#: inc/includes/auto-setup/views/system_info.php:297
      +msgid "System info"
      +msgstr ""
      +
      +#: inc/includes/auto-setup/views/system_info.php:299
       msgid ""
       "Please make sure all items below are marked with a green check <b>before</b> "
       "proceeding with the auto setup or saving the theme options."
       msgstr ""
       
      -#: inc/includes/auto-setup/views/system_info.php:315
      +#: inc/includes/auto-setup/views/system_info.php:320
       msgid "Meets minimum requirements"
       msgstr ""
       
      -#: inc/includes/auto-setup/views/system_info.php:315
      +#: inc/includes/auto-setup/views/system_info.php:320
       msgid "We have some improvements to suggest"
       msgstr ""
       
      -#: inc/includes/builder-templates/class-thz-builder-templates.php:287
      -#: inc/includes/builder-templates/class-thz-builder-templates.php:320
      -msgid "Not able to load builder templates"
      -msgstr ""
      -
      -#: inc/includes/builder-templates/views/sections.php:26
      -msgid "Quick search"
      -msgstr ""
      -
      -#: inc/includes/builder-templates/views/sections.php:33
      -msgid "All Categories"
      -msgstr ""
      -
      -#: inc/includes/builder-templates/views/sections.php:64
      -#: inc/thzframework/extensions/backups/extensions/backups-demo/views/page.php:105
      -msgid "Go Pro"
      -msgstr ""
      -
      -#: inc/includes/builder-templates/views/sections.php:78
      -msgid "Last updated"
      -msgstr ""
      -
      -#: inc/includes/builder-templates/views/sections.php:79
      -msgid "Force Library Update"
      -msgstr ""
      -
       #: inc/includes/class-tgm-plugin-activation.php:332
       msgid "Install Required Plugins"
       msgstr ""
      @@ -2412,10 +2278,6 @@ msgstr ""
       msgid "Hide Details"
       msgstr ""
       
      -#: inc/includes/class-thz-demos.php:90
      -msgid "Not able to load demos"
      -msgstr ""
      -
       #: inc/includes/class-thz-dynamic-css.php:326
       msgid ""
       "Not able to create folders. Check wp-content/uploads folder permissions."
      @@ -2514,7 +2376,6 @@ msgstr ""
       #: inc/thzframework/theme/options/slider_settings.php:470
       #: inc/thzframework/theme/options/sliders_ext_navigations.php:246
       #: inc/utility.php:1628 inc/utility.php:1836 inc/utility.php:1920
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:223
       msgid "Left"
       msgstr ""
       
      @@ -2580,7 +2441,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/products_style.php:120
       #: inc/thzframework/theme/options/woo/single_image.php:60
       #: inc/thzframework/theme/options/woo/subcat_style.php:57
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:233
       msgid "Aspect ratio 1:1"
       msgstr ""
       
      @@ -2598,7 +2458,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/products_style.php:125
       #: inc/thzframework/theme/options/woo/single_image.php:65
       #: inc/thzframework/theme/options/woo/subcat_style.php:62
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:235
       msgid "Landscape"
       msgstr ""
       
      @@ -2616,7 +2475,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/products_style.php:128
       #: inc/thzframework/theme/options/woo/single_image.php:68
       #: inc/thzframework/theme/options/woo/subcat_style.php:65
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:236
       msgid "Aspect ratio 2:1"
       msgstr ""
       
      @@ -2634,7 +2492,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/products_style.php:129
       #: inc/thzframework/theme/options/woo/single_image.php:69
       #: inc/thzframework/theme/options/woo/subcat_style.php:66
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:237
       msgid "Aspect ratio 3:2"
       msgstr ""
       
      @@ -2652,7 +2509,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/products_style.php:130
       #: inc/thzframework/theme/options/woo/single_image.php:70
       #: inc/thzframework/theme/options/woo/subcat_style.php:67
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:238
       msgid "Aspect ratio 4:3"
       msgstr ""
       
      @@ -2670,7 +2526,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/products_style.php:131
       #: inc/thzframework/theme/options/woo/single_image.php:71
       #: inc/thzframework/theme/options/woo/subcat_style.php:68
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:239
       msgid "Aspect ratio 16:9"
       msgstr ""
       
      @@ -2688,7 +2543,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/products_style.php:132
       #: inc/thzframework/theme/options/woo/single_image.php:72
       #: inc/thzframework/theme/options/woo/subcat_style.php:69
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:240
       msgid "Aspect ratio 21:9"
       msgstr ""
       
      @@ -2706,7 +2560,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/products_style.php:137
       #: inc/thzframework/theme/options/woo/single_image.php:77
       #: inc/thzframework/theme/options/woo/subcat_style.php:74
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:242
       msgid "Portrait"
       msgstr ""
       
      @@ -2724,7 +2577,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/products_style.php:140
       #: inc/thzframework/theme/options/woo/single_image.php:80
       #: inc/thzframework/theme/options/woo/subcat_style.php:77
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:243
       msgid "Aspect ratio 1:2"
       msgstr ""
       
      @@ -2742,7 +2594,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/products_style.php:141
       #: inc/thzframework/theme/options/woo/single_image.php:81
       #: inc/thzframework/theme/options/woo/subcat_style.php:78
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:244
       msgid "Aspect ratio 3:4"
       msgstr ""
       
      @@ -2760,7 +2611,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/products_style.php:142
       #: inc/thzframework/theme/options/woo/single_image.php:82
       #: inc/thzframework/theme/options/woo/subcat_style.php:79
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:245
       msgid "Aspect ratio 2:3"
       msgstr ""
       
      @@ -2778,7 +2628,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/products_style.php:143
       #: inc/thzframework/theme/options/woo/single_image.php:83
       #: inc/thzframework/theme/options/woo/subcat_style.php:80
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:246
       msgid "Aspect ratio 9:16"
       msgstr ""
       
      @@ -2962,8 +2811,6 @@ msgstr ""
       #: inc/thzframework/theme/options/sliders_ext_navigations.php:105
       #: inc/thzframework/theme/options/woo/product_tabs.php:270 inc/utility.php:1820
       #: inc/utility.php:1859 inc/utility.php:1904 inc/utility.php:1943
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:109
      -#: inc/widgets/thz-instagram/class-widget-thz-instagram.php:87
       msgid "Inactive"
       msgstr ""
       
      @@ -3592,7 +3439,7 @@ msgstr ""
       #: inc/thzframework/extensions/shortcodes/shortcodes/team-members/member_settings.php:31
       #: inc/thzframework/theme/options/mainmenu/general.php:38
       #: inc/thzframework/theme/options/portfolio/general.php:88 inc/utility.php:1119
      -#: inc/utility.php:1152 inc/widgets/thz-posts/class-widget-thz-posts.php:184
      +#: inc/utility.php:1152
       msgid "None"
       msgstr ""
       
      @@ -3915,7 +3762,6 @@ msgstr ""
       #: inc/thzframework/theme/options/slider_settings.php:452
       #: inc/thzframework/theme/options/sliders_ext_navigations.php:228
       #: inc/utility.php:1629 inc/utility.php:1837 inc/utility.php:1921
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:224
       msgid "Right"
       msgstr ""
       
      @@ -5815,8 +5661,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/products_style.php:220
       #: inc/thzframework/theme/options/woo/single_elements.php:16
       #: inc/thzframework/theme/options/woo/subcat_style.php:112
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:177
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:87
       msgid "Title"
       msgstr ""
       
      @@ -6888,6 +6732,94 @@ msgstr ""
       msgid "This will take a moment. Loading customizer options please wait..."
       msgstr ""
       
      +#: inc/includes/utilities/customizer/customizer-defaults.php:49
      +msgid "Theme Options"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:50
      +msgid "Customize the login of your website."
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:56
      +msgid "Hero Section"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:66
      +#: inc/includes/utilities/customizer/customizer-defaults.php:162
      +msgid "Install Recomended Plugins"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:71
      +#: inc/includes/utilities/customizer/customizer-defaults.php:167
      +#, php-format
      +msgid ""
      +"This is a default customizer setup. For advanced theme options Install and "
      +"activate %1$srecommended plugins%2$s."
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:87
      +msgid "Before Title"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:90
      +msgid "Add text before hero section title."
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:101
      +msgid "Hero Title"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:104
      +msgid "Add hero section title."
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:115
      +msgid "Sub Title"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:118
      +msgid "Add hero section sub title"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:129
      +msgid "Button text"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:132
      +msgid "Add hero button text"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:143
      +msgid "Button link"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:146
      +msgid "Add hero button link"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:152
      +#: inc/thzframework/theme/options/footer_settings.php:201
      +#: inc/thzframework/theme/options/footer_settings.php:211
      +#: inc/thzframework/theme/options/footer_settings.php:221
      +msgid "Branding"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:183
      +msgid "Branding text"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:186
      +msgid "Add branding ( copyright ) text"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:197
      +msgid "Branding link"
      +msgstr ""
      +
      +#: inc/includes/utilities/customizer/customizer-defaults.php:200
      +msgid "Add branding link"
      +msgstr ""
      +
       #: inc/includes/utilities/item/main-page-utility.class.php:51
       msgid ""
       "Class should be instantiated before \"wp\" action is triggered because it "
      @@ -6986,6 +6918,10 @@ msgstr ""
       msgid "Live Preview"
       msgstr ""
       
      +#: inc/thzframework/extensions/backups/extensions/backups-demo/views/page.php:105
      +msgid "Go Pro"
      +msgstr ""
      +
       #: inc/thzframework/extensions/forms/extensions/contact-forms/shortcodes/contact-form/config.php:8
       msgid "Contact form"
       msgstr ""
      @@ -7385,7 +7321,6 @@ msgstr ""
       #: inc/thzframework/theme/options/heros/title.php:112
       #: inc/thzframework/theme/options/heros/title.php:216
       #: inc/thzframework/theme/options/pagetitle/sub_title.php:41
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:226
       msgid "Under the title"
       msgstr ""
       
      @@ -7397,7 +7332,6 @@ msgstr ""
       #: inc/thzframework/theme/options/heros/title.php:105
       #: inc/thzframework/theme/options/heros/title.php:215
       #: inc/thzframework/theme/options/pagetitle/sub_title.php:45
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:225
       msgid "Above the title"
       msgstr ""
       
      @@ -9047,6 +8981,10 @@ msgstr ""
       msgid "Set icon color."
       msgstr ""
       
      +#: inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php:530
      +msgid "Heading font"
      +msgstr ""
      +
       #: inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php:534
       #: inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php:565
       #: inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php:596
      @@ -9067,6 +9005,10 @@ msgstr ""
       msgid "Heading font family and metrics"
       msgstr ""
       
      +#: inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php:561
      +msgid "Sub heading font"
      +msgstr ""
      +
       #: inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php:568
       msgid "Set custom font settings for sub heading"
       msgstr ""
      @@ -9075,6 +9017,12 @@ msgstr ""
       msgid "Sub heading font family and metrics"
       msgstr ""
       
      +#: inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php:592
      +#: inc/thzframework/extensions/shortcodes/shortcodes/text-block/options.php:59
      +#: inc/thzframework/theme/options/custom_typo.php:19
      +msgid "Text font"
      +msgstr ""
      +
       #: inc/thzframework/extensions/shortcodes/shortcodes/call-to-action/options.php:599
       msgid "Set custom font settings for cta text"
       msgstr ""
      @@ -10056,7 +10004,6 @@ msgid "Nudge icon. All values must be entered for style to be applied."
       msgstr ""
       
       #: inc/thzframework/extensions/shortcodes/shortcodes/list/config.php:15
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:203
       msgid "List"
       msgstr ""
       
      @@ -10576,7 +10523,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/single_image.php:179
       #: inc/thzframework/theme/options/woo/single_related.php:28
       #: inc/thzframework/theme/options/woo/single_upsell.php:28
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:261
       msgid "1"
       msgstr ""
       
      @@ -10614,7 +10560,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/single_image.php:180
       #: inc/thzframework/theme/options/woo/single_related.php:29
       #: inc/thzframework/theme/options/woo/single_upsell.php:29
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:262
       msgid "2"
       msgstr ""
       
      @@ -10651,7 +10596,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/single_image.php:181
       #: inc/thzframework/theme/options/woo/single_related.php:30
       #: inc/thzframework/theme/options/woo/single_upsell.php:30
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:263
       msgid "3"
       msgstr ""
       
      @@ -10687,7 +10631,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/single_image.php:182
       #: inc/thzframework/theme/options/woo/single_related.php:31
       #: inc/thzframework/theme/options/woo/single_upsell.php:31
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:264
       msgid "4"
       msgstr ""
       
      @@ -10723,7 +10666,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/single_image.php:183
       #: inc/thzframework/theme/options/woo/single_related.php:32
       #: inc/thzframework/theme/options/woo/single_upsell.php:32
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:265
       msgid "5"
       msgstr ""
       
      @@ -10759,7 +10701,6 @@ msgstr ""
       #: inc/thzframework/theme/options/woo/single_image.php:184
       #: inc/thzframework/theme/options/woo/single_related.php:33
       #: inc/thzframework/theme/options/woo/single_upsell.php:33
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:266
       msgid "6"
       msgstr ""
       
      @@ -11334,7 +11275,6 @@ msgstr ""
       
       #: inc/thzframework/extensions/shortcodes/shortcodes/media-gallery/options.php:567
       #: inc/thzframework/extensions/shortcodes/shortcodes/media-gallery/options.php:626
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:93
       msgid "User ID"
       msgstr ""
       
      @@ -11344,7 +11284,6 @@ msgid "Get %1s"
       msgstr ""
       
       #: inc/thzframework/extensions/shortcodes/shortcodes/media-gallery/options.php:574
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:97
       msgid "Photo set ID"
       msgstr ""
       
      @@ -12161,6 +12100,10 @@ msgstr ""
       msgid "This is dummy notification text. Please replace it."
       msgstr ""
       
      +#: inc/thzframework/extensions/shortcodes/shortcodes/notification/options.php:137
      +msgid "Notification style type"
      +msgstr ""
      +
       #: inc/thzframework/extensions/shortcodes/shortcodes/notification/options.php:141
       msgid "Predefined"
       msgstr ""
      @@ -13143,7 +13086,6 @@ msgstr ""
       #: inc/thzframework/theme/options/posts/project_options.php:114
       #: inc/thzframework/theme/options/posts/project_options.php:134
       #: inc/thzframework/theme/options/posts/project_options.php:153
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:178
       #: template-parts/events/event-grid.php:171
       #: template-parts/events/event-sidebar.php:211
       #: woocommerce/single-product-reviews.php:75
      @@ -13753,11 +13695,6 @@ msgstr ""
       msgid "Headings font"
       msgstr ""
       
      -#: inc/thzframework/extensions/shortcodes/shortcodes/text-block/options.php:59
      -#: inc/thzframework/theme/options/custom_typo.php:19
      -msgid "Text font"
      -msgstr ""
      -
       #: inc/thzframework/extensions/shortcodes/shortcodes/text-block/options.php:69
       msgid "Links font"
       msgstr ""
      @@ -14379,7 +14316,6 @@ msgid "and create new project."
       msgstr ""
       
       #: inc/thzframework/theme/options/advanced/apis.php:11
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:103
       msgid "To obtain Twitter API keys please visit"
       msgstr ""
       
      @@ -15601,7 +15537,6 @@ msgstr ""
       #: inc/thzframework/theme/options/events/related_intro.php:11
       #: inc/thzframework/theme/options/portfolio/projects_style.php:758
       #: inc/thzframework/theme/options/portfolio/related_intro.php:12
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:96
       msgid "Show intro text"
       msgstr ""
       
      @@ -15629,21 +15564,18 @@ msgstr ""
       #: inc/thzframework/theme/options/blog/posts_style.php:743
       #: inc/thzframework/theme/options/events/events_style.php:197
       #: inc/thzframework/theme/options/portfolio/projects_style.php:785
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:217
       msgid "By words"
       msgstr ""
       
       #: inc/thzframework/theme/options/blog/posts_style.php:744
       #: inc/thzframework/theme/options/events/events_style.php:198
       #: inc/thzframework/theme/options/portfolio/projects_style.php:786
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:216
       msgid "By characters"
       msgstr ""
       
       #: inc/thzframework/theme/options/blog/posts_style.php:745
       #: inc/thzframework/theme/options/events/events_style.php:199
       #: inc/thzframework/theme/options/portfolio/projects_style.php:787
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:164
       msgid "No limit"
       msgstr ""
       
      @@ -18093,12 +18025,6 @@ msgstr ""
       msgid "Social links"
       msgstr ""
       
      -#: inc/thzframework/theme/options/footer_settings.php:201
      -#: inc/thzframework/theme/options/footer_settings.php:211
      -#: inc/thzframework/theme/options/footer_settings.php:221
      -msgid "Branding"
      -msgstr ""
      -
       #: inc/thzframework/theme/options/footer_settings.php:207
       msgid "Middle content"
       msgstr ""
      @@ -18761,6 +18687,10 @@ msgstr ""
       msgid "Set sub level ul border radius."
       msgstr ""
       
      +#: inc/thzframework/theme/options/mainmenu/containers_sub_level.php:61
      +msgid "Sub level li border"
      +msgstr ""
      +
       #: inc/thzframework/theme/options/mainmenu/containers_sub_level.php:88
       msgid "First sub level top offset"
       msgstr ""
      @@ -19020,6 +18950,10 @@ msgstr ""
       msgid "Set top level hovered item colors"
       msgstr ""
       
      +#: inc/thzframework/theme/options/mainmenu/hovered_style.php:35
      +msgid "Top level hovered link border"
      +msgstr ""
      +
       #: inc/thzframework/theme/options/mainmenu/hovered_style.php:54
       msgid "Sub level hovered link colors"
       msgstr ""
      @@ -19036,6 +18970,10 @@ msgstr ""
       msgid "Set top level link colors"
       msgstr ""
       
      +#: inc/thzframework/theme/options/mainmenu/link_style.php:35
      +msgid "Top level link border"
      +msgstr ""
      +
       #: inc/thzframework/theme/options/mainmenu/link_style.php:54
       msgid "Sub level link colors"
       msgstr ""
      @@ -19057,6 +18995,10 @@ msgid ""
       "Set top level link height. The menu height will be adjusted to this option."
       msgstr ""
       
      +#: inc/thzframework/theme/options/mainmenu/links_layout.php:31
      +msgid "Top level link padding"
      +msgstr ""
      +
       #: inc/thzframework/theme/options/mainmenu/links_layout.php:62
       msgid "Top level links spacing"
       msgstr ""
      @@ -19099,6 +19041,10 @@ msgstr ""
       msgid "Set sub level link height."
       msgstr ""
       
      +#: inc/thzframework/theme/options/mainmenu/links_layout.php:116
      +msgid "Sub level link padding"
      +msgstr ""
      +
       #: inc/thzframework/theme/options/mainmenu/links_layout.php:148
       msgid "Sub level link border radius"
       msgstr ""
      @@ -19668,12 +19614,10 @@ msgid "Select projects order"
       msgstr ""
       
       #: inc/thzframework/theme/options/portfolio/general.php:75
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:157
       msgid "Descending ( newest first )"
       msgstr ""
       
       #: inc/thzframework/theme/options/portfolio/general.php:76
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:158
       msgid "Ascending ( oldest first )"
       msgstr ""
       
      @@ -19682,17 +19626,14 @@ msgid "Order by"
       msgstr ""
       
       #: inc/thzframework/theme/options/portfolio/general.php:85
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:179
       msgid "Create date"
       msgstr ""
       
       #: inc/thzframework/theme/options/portfolio/general.php:86
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:180
       msgid "Modified date"
       msgstr ""
       
       #: inc/thzframework/theme/options/portfolio/general.php:87
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:181
       msgid "Random"
       msgstr ""
       
      @@ -21696,6 +21637,10 @@ msgstr ""
       msgid "Adjust tag items font metrics."
       msgstr ""
       
      +#: inc/thzframework/theme/options/widgetsgenerator.php:13
      +msgid "Grids generator"
      +msgstr ""
      +
       #: inc/thzframework/theme/options/widgetsgenerator.php:15
       msgid ""
       "<h2>This option requires Unyson Page Builder extension to be active. Please "
      @@ -22826,329 +22771,6 @@ msgstr ""
       msgid "This effect does NOT work if media height is auto."
       msgstr ""
       
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:7
      -msgid "Flickr images widget"
      -msgstr ""
      -
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:8
      -msgid "Creatus - Flickr images"
      -msgstr ""
      -
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:84
      -#: inc/widgets/thz-instagram/class-widget-thz-instagram.php:72
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:132
      -msgid "Title:"
      -msgstr ""
      -
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:88
      -msgid "API key "
      -msgstr ""
      -
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:88
      -msgid "Get API key"
      -msgstr ""
      -
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:90
      -#, php-format
      -msgid "Use this key until you get your own: %s"
      -msgstr ""
      -
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:93
      -msgid "Get user ID"
      -msgstr ""
      -
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:97
      -msgid "Get photo set ID"
      -msgstr ""
      -
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:99
      -msgid "If this is used than only images from this photoset are displayed."
      -msgstr ""
      -
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:102
      -#: inc/widgets/thz-instagram/class-widget-thz-instagram.php:80
      -msgid "Number of images:"
      -msgstr ""
      -
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:106
      -#: inc/widgets/thz-instagram/class-widget-thz-instagram.php:84
      -msgid "Keep data:"
      -msgstr ""
      -
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:108
      -#: inc/widgets/thz-instagram/class-widget-thz-instagram.php:86
      -msgid "Acitve"
      -msgstr ""
      -
      -#: inc/widgets/thz-flickr/class-widget-thz-flickr.php:111
      -#: inc/widgets/thz-instagram/class-widget-thz-instagram.php:89
      -msgid ""
      -"If this option is active, data is saved as WP option, otherwise it is saved "
      -"as expiring transient."
      -msgstr ""
      -
      -#: inc/widgets/thz-flickr/views/widget.php:64
      -#: inc/widgets/thz-instagram/views/widget.php:61
      -msgid "Not able to display user images. Check widget settings."
      -msgstr ""
      -
      -#: inc/widgets/thz-instagram/class-widget-thz-instagram.php:7
      -msgid "Instagram images widget"
      -msgstr ""
      -
      -#: inc/widgets/thz-instagram/class-widget-thz-instagram.php:8
      -msgid "Creatus - Instagram images"
      -msgstr ""
      -
      -#: inc/widgets/thz-instagram/class-widget-thz-instagram.php:76
      -msgid "Username:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:9
      -msgid "Posts widget"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:10
      -msgid "Creatus - Posts"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:93
      -msgid "Show Thumbnail"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:94
      -msgid "Show only posts with thumbnail"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:95
      -msgid "Show Post Date"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:97
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:147
      -msgid "Use .thz-has-list class"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:136
      -msgid "Number of posts:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:140
      -msgid "Select post types:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:148
      -msgid "Specific tax terms:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:155
      -msgid "Order:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:162
      -msgid "Select posts published limit:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:165
      -msgid "Show 1 Week old posts"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:166
      -msgid "Show 1 Month old posts"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:167
      -msgid "Show 3 Months old posts"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:168
      -msgid "Show 6 Months old posts"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:169
      -msgid "Show 1 Year old posts"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:173
      -msgid "Order by:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:175
      -msgid "ID"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:182
      -msgid "Number of comments"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:183
      -msgid "Post views count"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:188
      -msgid "Title tag:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:190
      -msgid "span"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:191
      -msgid "div"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:192
      -msgid "h1"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:193
      -msgid "h2"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:194
      -msgid "h3"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:195
      -msgid "h4"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:196
      -msgid "h5"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:197
      -msgid "h6"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:201
      -msgid "Display Mode:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:204
      -msgid "Thumbnails grid"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:208
      -msgid "Widget metrics:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:214
      -msgid "Intro limit by:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:219
      -msgid "Intro limit:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:221
      -msgid "Thumbnail position:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:230
      -msgid "Thumbnail Width:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:251
      -msgid "Thumbnail Size:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:259
      -msgid "Number of columns:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:269
      -msgid "Gutter:"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:271
      -msgid "0px"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:272
      -msgid "5px"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:273
      -msgid "10px"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:274
      -msgid "15px"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:275
      -msgid "20px"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:276
      -msgid "25px"
      -msgstr ""
      -
      -#: inc/widgets/thz-posts/class-widget-thz-posts.php:277
      -msgid "30px"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:7
      -msgid "Twitter widget"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:8
      -msgid "Creatus - Twitter"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:91
      -msgid "Api keys:"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:93
      -msgid "Use theme api keys"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:94
      -msgid "Insert custom api keys"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:99
      -msgid "Please go to theme settings and add you Twitter App api keys"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:103
      -msgid "and create new application"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:106
      -msgid "Consumer Key"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:111
      -msgid "Consumer Secret"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:116
      -msgid "Access Token"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:121
      -msgid "Access Token Secret"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:126
      -msgid "Twitter User"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:130
      -msgid "Number of Tweets"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:135
      -msgid "Tweet characters limit"
      -msgstr ""
      -
      -#: inc/widgets/thz-twitter/class-widget-thz-twitter.php:142
      -msgid "Display tweet as link"
      -msgstr ""
      -
       #: searchform.php:17 template-parts/search/search-layout.php:32
       msgid "Search site"
       msgstr ""
      diff --git a/readme.txt b/readme.txt
      index ff0daf4..61d0b1b 100644
      --- a/readme.txt
      +++ b/readme.txt
      @@ -1,16 +1,16 @@
       === Creatus ===
       Contributors: Themezly
      -Tags: one-column, two-columns, left-sidebar, right-sidebar, custom-background, custom-header, custom-menu, editor-style, featured-image-header, featured-images, post-formats, theme-options, translation-ready
      +Tags: one-column, two-columns, left-sidebar, right-sidebar, custom-background, custom-header, custom-menu, editor-style, featured-image-header, featured-images, post-formats, theme-options, translation-ready, rtl-language-support
       Requires at least: 4.0
      -Tested up to: 5.0.3
      -Stable tag: 1.5.0
      +Tested up to: 5.1.1
      +Stable tag: 1.5.6
       License: GPLv2 or later
       License URI: http://www.gnu.org/licenses/gpl-2.0.html
       
       
       == Description ==
       
      -Ultimate WordPress theme with comprehensive set of tools that will help you create any WordPress based website concept.
      +Ultimate Multipurpose WordPress theme with comprehensive set of tools that will help you create any WordPress based website concept. Whatever the type of website you are looking to create, Creatus has it covered. With a wide assortment of ready-to-go full site demos, page templates or page blocks, from eCommerce and Portfolio to Blog and Agency, any concept is possible. Simply select and install the demo of your choice in just one-click, and then customize as appropriate.
       
       == Installation ==
       
      @@ -27,7 +27,7 @@ More details here: http://www.gnu.org/licenses/gpl-2.0.html
       == Resources ==
       
       jQuery Easing, Copyright 2008 George McGinley Smith
      -Licenses: BSD
      +Licenses: Open source under the 3-Clause BSD License
       Source: http://gsgd.co.uk/sandbox/jquery/easing/
       
       Isotope, Copyright 2015 Metafizzy
      @@ -162,3 +162,12 @@ Source: https://necolas.github.io/normalize.css/
       Font Awesome icons, Copyright Dave Gandy
       License: SIL Open Font License, version 1.1.
       Source: http://fontawesome.io/
      +
      +Images
      +License: Creative Commons CC0 
      +Source: https://stocksnap.io
      +https://stocksnap.io/photo/J2KJ6CNZTC
      +https://stocksnap.io/photo/0PTTRQX5L1
      +https://stocksnap.io/photo/NOFSYE1P0V
      +https://stocksnap.io/photo/BBA96CDDCD
      +https://stocksnap.io/photo/O9V8SGL6FD
      \ No newline at end of file
      diff --git a/screenshot.jpg b/screenshot.jpg
      index 21e4a20..7cce52e 100644
      Binary files a/screenshot.jpg and b/screenshot.jpg differ
      diff --git a/style.css b/style.css
      index d4b099b..d890970 100644
      --- a/style.css
      +++ b/style.css
      @@ -4,7 +4,7 @@ Theme URI: https://creatus.io
       Description: Ultimate WordPress theme with comprehensive set of tools that will help you create any WordPress based website concept.
       Author: Themezly
       Author URI: https://themezly.com
      -Version: 1.5.4
      +Version: 1.5.6
       License: GNU General Public License v2 or later
       License URI: http://www.gnu.org/licenses/gpl-2.0.html
       Text Domain: creatus
      diff --git a/template-parts/customizer-hero-section.php b/template-parts/customizer-hero-section.php
      new file mode 100644
      index 0000000..f3afec0
      --- /dev/null
      +++ b/template-parts/customizer-hero-section.php
      @@ -0,0 +1,67 @@
      +<?php
      +/**
      + * @package      Thz Framework
      + * @author       Themezly
      + * @websites     http://www.themezly.com | http://www.youjoomla.com | http://www.yjsimplegrid.com
      + */
      + 
      +if ( ! defined( 'ABSPATH' ) ) {
      +	exit; // No direct access
      +}
      +/**
      + * This is a default customizer hero section
      + */
      + 
      +$before 		= get_option('creatus_before_hero_title',false);
      +$title 			= get_option('creatus_hero_title',false); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.OverrideProhibited
      +$sub 			= get_option('creatus_hero_subtitle',false);
      +$button_text 	= get_option('creatus_hero_button_text',false);
      +$button_link 	= get_option('creatus_hero_button_link',false);
      +
      +if( !$before && !$title && !$sub && !$button_text && !$button_link ) {
      +	return;
      +}
      +
      +$allow = array(
      +    'a' => array(
      +        'href' => array(),
      +        'title' => array()
      +    ),
      +    'br' => array(),
      +    'em' => array(),
      +    'strong' => array(),
      +);
      +
      +?>
      +<div id="thz-customizer-hero">
      +  <div class="thz-container content-contained thz-site-width">
      +    <div class="thz-row">
      +      <div class="thz-column thz-col-1">
      +        <?php if( $before ) { ?>
      +        <span class="thz-heading-before">
      +          <?php echo wp_kses( $before, $allow ); ?>
      +        </span>
      +        <?php } ?>
      +        <?php if( $title ) { ?>
      +        <h2 class="thz-heading-title"><?php echo wp_kses( $title, $allow ); ?></h2>
      +        <?php } ?>
      +        <?php if( $sub ) { ?>
      +        <p class="thz-heading-sub">
      +          <?php echo wp_kses( $sub, $allow ); ?>
      +        </p>
      +        <?php } ?>
      +        <?php if( $button_text || $button_link ) { ?>
      +        <div class="thz-btn-center-wrap">
      +          <div class="thz-btn-container thz-btn-move-up thz-btn-sh-ishidden thz-mt-30 thz-btn-flat">
      +            <a class="thz-button thz-btn-green thz-btn-trans thz-btn-medium thz-radius-50 thz-align-center thz-boxshadow-down-02" href="<?php echo esc_html( $button_link ); ?>">
      +              <span class="thz-btn-text thz-fs-14 thz-fw-600 thz-lsp1">
      +               <?php echo esc_html( $button_text ); ?>
      +              </span>
      +            </a>
      +          </div>
      +        </div>
      +        <?php } ?>
      +      </div>
      +    </div>
      +  </div>
      +</div>
      \ No newline at end of file