PageSourceSearch

https://www.mindmapart.com/wp-content/themes/expression/js/grid-gallery.js?ver=1.4.7

js mindmapart.com collected 2026-09-24 10:44:26 UTC 56,869 bytes, 1,258 lines download raw bytes

1// Simple JavaScript Templating
2// John Resig - http://ejohn.org/ - MIT Licensed
3(function(){
4  var cache = {};
5 
6  this.jrtmpl = function tmpl(str, data){
7	// Figure out if we're getting a template, or if we need to
8	// load the template - and be sure to cache the result.
9	var fn = !/\W/.test(str) ?
10	  cache[str] = cache[str] ||
11		tmpl(document.getElementById(str).innerHTML) :
12	 
13	  // Generate a reusable function that will serve as a template
14	  // generator (and which will be cached).
15	  new Function("obj",
16		"var p=[],print=function(){p.push.apply(p,arguments);};" +
17	   
18		// Introduce the data as local variables using with(){}
19		"with(obj){p.push('" +
20	   
21		// Convert the template into pure JavaScript
22		str
23		  .replace(/[\r\t\n]/g, " ")
24		  .split("<%").join("\t")
25		  .replace(/((^|%>)[^\t]*)'/g, "$1\r")
26		  .replace(/\t=(.*?)%>/g, "',$1,'")
27		  .split("\t").join("');")
28		  .split("%>").join("p.push('")
29		  .split("\r").join("\\'")
30	  + "');}return p.join('');");
31   
32	// Provide some basic currying to the user
33	return data ? fn( data ) : fn;
34  };
35})();
36
37/**
38 * jQuery Plugin to obtain touch gestures from iPhone, iPod Touch and iPad, should also work with Android mobile phones (not tested yet!)
39 * Common usage: wipe images (left and right to show the previous or next image)
40 * 
41 * @author Andreas Waltl, netCU Internetagentur (http://www.netcu.de)
42 * @version 1.1.1 (9th December 2010) - fix bug (older IE's had problems)
43 * @version 1.1 (1st September 2010) - support wipe up and wipe down
44 * @version 1.0 (15th July 2010)
45 */
46(function($){$.fn.touchwipe=function(settings){var config={min_move_x:20,min_move_y:20,wipeLeft:function(){},wipeRight:function(){},wipeUp:function(){},wipeDown:function(){},preventDefaultEvents:true};if(settings)$.extend(config,settings);this.each(function(){var startX;var startY;var isMoving=false;function cancelTouch(){this.removeEventListener('touchmove',onTouchMove);startX=null;isMoving=false}function onTouchMove(e){if(config.preventDefaultEvents){e.preventDefault()}if(isMoving){var x=e.touches[0].pageX;var y=e.touches[0].pageY;var dx=startX-x;var dy=startY-y;if(Math.abs(dx)>=config.min_move_x){cancelTouch();if(dx>0){config.wipeLeft()}else{config.wipeRight()}}else if(Math.abs(dy)>=config.min_move_y){cancelTouch();if(dy>0){config.wipeDown()}else{config.wipeUp()}}}}function onTouchStart(e){if(e.touches.length==1){startX=e.touches[0].pageX;startY=e.touches[0].pageY;isMoving=true;this.addEventListener('touchmove',onTouchMove,false)}}if('ontouchstart'in document.documentElement){this.addEventListener('touchstart',onTouchStart,false)}});return this}})(jQuery);
47
48
49/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
50* Licensed under the MIT License (LICENSE.txt).
51*
52* Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
53* Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
54* Thanks to: Seamus Leahy for adding deltaX and deltaY
55*
56* Version: 3.0.6
57*
58* Requires: 1.2.2+
59*/
60
61(function(d){var b=["DOMMouseScroll","mousewheel"];if(d.event.fixHooks){for(var a=b.length;a;){d.event.fixHooks[b[--a]]=d.event.mouseHooks}}d.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var e=b.length;e;){this.addEventListener(b[--e],c,false)}}else{this.onmousewheel=c}},teardown:function(){if(this.removeEventListener){for(var e=b.length;e;){this.removeEventListener(b[--e],c,false)}}else{this.onmousewheel=null}}};d.fn.extend({mousewheel:function(e){return e?this.bind("mousewheel",e):this.trigger("mousewheel")},unmousewheel:function(e){return this.unbind("mousewheel",e)}});function c(j){var h=j||window.event,g=[].slice.call(arguments,1),k=0,i=true,f=0,e=0;j=d.event.fix(h);j.type="mousewheel";if(h.wheelDelta){k=h.wheelDelta/120}if(h.detail){k=-h.detail/3}e=k;if(h.axis!==undefined&&h.axis===h.HORIZONTAL_AXIS){e=0;f=-1*k}if(h.wheelDeltaY!==undefined){e=h.wheelDeltaY/120}if(h.wheelDeltaX!==undefined){f=-1*h.wheelDeltaX/120}g.unshift(j,k,f,e);return(d.event.dispatch||d.event.handle).apply(this,g)}})(jQuery);
62
63
64
65/**
66 * @author trixta
67 * @version 1.2
68 */
69(function(c){var b={pos:[-260,-260]},d=3,h=document,g=h.documentElement,e=h.body,a,i;function f(){if(this===b.elem){b.pos=[-260,-260];b.elem=false;d=3}}c.event.special.mwheelIntent={setup:function(){var j=c(this).bind("mousewheel",c.event.special.mwheelIntent.handler);if(this!==h&&this!==g&&this!==e){j.bind("mouseleave",f)}j=null;return true},teardown:function(){c(this).unbind("mousewheel",c.event.special.mwheelIntent.handler).unbind("mouseleave",f);return true},handler:function(j,k){var l=[j.clientX,j.clientY];if(this===b.elem||Math.abs(b.pos[0]-l[0])>d||Math.abs(b.pos[1]-l[1])>d){b.elem=this;b.pos=l;d=250;clearTimeout(i);i=setTimeout(function(){d=10},200);clearTimeout(a);a=setTimeout(function(){d=3},1500);j=c.extend({},j,{type:"mwheelIntent"});return c.event.dispatch.apply(this,arguments)}}};c.fn.extend({mwheelIntent:function(j){return j?this.bind("mwheelIntent",j):this.trigger("mwheelIntent")},unmwheelIntent:function(j){return this.unbind("mwheelIntent",j)}});c(function(){e=h.body;c(h).bind("mwheelIntent.mwheelIntentDefault",c.noop)})})(jQuery);
70
71/**
72 * jQuery Masonry v2.1.05
73 * A dynamic layout plugin for jQuery
74 * The flip-side of CSS Floats
75 * http://masonry.desandro.com
76 *
77 * Licensed under the MIT license.
78 * Copyright 2012 David DeSandro
79 */
80(function(a,b,c){"use strict";var d=b.event,e;d.special.smartresize={setup:function(){b(this).bind("resize",d.special.smartresize.handler)},teardown:function(){b(this).unbind("resize",d.special.smartresize.handler)},handler:function(a,c){var d=this,f=arguments;a.type="smartresize",e&&clearTimeout(e),e=setTimeout(function(){b.event.dispatch.apply(d,f)},c==="execAsap"?0:100)}},b.fn.smartresize=function(a){return a?this.bind("smartresize",a):this.trigger("smartresize",["execAsap"])},b.Mason=function(a,c){this.element=b(c),this._create(a),this._init()},b.Mason.settings={isResizable:!0,isAnimated:!1,animationOptions:{queue:!1,duration:500},gutterWidth:0,isRTL:!1,isFitWidth:!1,containerStyle:{position:"relative"}},b.Mason.prototype={_filterFindBricks:function(a){var b=this.options.itemSelector;return b?a.filter(b).add(a.find(b)):a},_getBricks:function(a){var b=this._filterFindBricks(a).css({position:"absolute"}).addClass("masonry-brick");return b},_create:function(c){this.options=b.extend(!0,{},b.Mason.settings,c),this.styleQueue=[];var d=this.element[0].style;this.originalStyle={height:d.height||""};var e=this.options.containerStyle;for(var f in e)this.originalStyle[f]=d[f]||"";this.element.css(e),this.horizontalDirection=this.options.isRTL?"right":"left",this.offset={x:parseInt(this.element.css("padding-"+this.horizontalDirection),10),y:parseInt(this.element.css("padding-top"),10)},this.isFluid=this.options.columnWidth&&typeof this.options.columnWidth=="function";var g=this;setTimeout(function(){g.element.addClass("masonry")},0),this.options.isResizable&&b(a).bind("smartresize.masonry",function(){g.resize()}),this.reloadItems()},_init:function(a){this._getColumns(),this._reLayout(a)},option:function(a,c){b.isPlainObject(a)&&(this.options=b.extend(!0,this.options,a))},layout:function(a,b){for(var c=0,d=a.length;c<d;c++)this._placeBrick(a[c]);var e={};e.height=Math.max.apply(Math,this.colYs);if(this.options.isFitWidth){var f=0;c=this.cols;while(--c){if(this.colYs[c]!==0)break;f++}e.width=(this.cols-f)*this.columnWidth-this.options.gutterWidth}this.styleQueue.push({$el:this.element,style:e});var g=this.isLaidOut?this.options.isAnimated?"animate":"css":"css",h=this.options.animationOptions,i;for(c=0,d=this.styleQueue.length;c<d;c++)i=this.styleQueue[c],i.$el[g](i.style,h);this.styleQueue=[],b&&b.call(a),this.isLaidOut=!0},_getColumns:function(){var a=this.options.isFitWidth?this.element.parent():this.element,b=a.width();this.columnWidth=this.isFluid?this.options.columnWidth(b):this.options.columnWidth||this.$bricks.outerWidth(!0)||b,this.columnWidth+=this.options.gutterWidth,this.cols=Math.floor((b+this.options.gutterWidth)/this.columnWidth),this.cols=Math.max(this.cols,1)},_placeBrick:function(a){var c=b(a),d,e,f,g,h;d=Math.ceil(c.outerWidth(!0)/this.columnWidth),d=Math.min(d,this.cols);if(d===1)f=this.colYs;else{e=this.cols+1-d,f=[];for(h=0;h<e;h++)g=this.colYs.slice(h,h+d),f[h]=Math.max.apply(Math,g)}var i=Math.min.apply(Math,f),j=0;for(var k=0,l=f.length;k<l;k++)if(f[k]===i){j=k;break}var m={top:i+this.offset.y};m[this.horizontalDirection]=this.columnWidth*j+this.offset.x,this.styleQueue.push({$el:c,style:m});var n=i+c.outerHeight(!0),o=this.cols+1-l;for(k=0;k<o;k++)this.colYs[j+k]=n},resize:function(){var a=this.cols;this._getColumns(),(this.isFluid||this.cols!==a)&&this._reLayout()},_reLayout:function(a){var b=this.cols;this.colYs=[];while(b--)this.colYs.push(0);this.layout(this.$bricks,a)},reloadItems:function(){this.$bricks=this._getBricks(this.element.children())},reload:function(a){this.reloadItems(),this._init(a)},appended:function(a,b,c){if(b){this._filterFindBricks(a).css({top:this.element.height()});var d=this;setTimeout(function(){d._appended(a,c)},1)}else this._appended(a,c)},_appended:function(a,b){var c=this._getBricks(a);this.$bricks=this.$bricks.add(c),this.layout(c,b)},remove:function(a){this.$bricks=this.$bricks.not(a),a.remove()},destroy:function(){this.$bricks.removeClass("masonry-brick").each(function(){this.style.position="",this.style.top="",this.style.left=""});var c=this.element[0].style;for(var d in this.originalStyle)c[d]=this.originalStyle[d];this.element.unbind(".masonry").removeClass("masonry").removeData("masonry"),b(a).unbind(".masonry")}},b.fn.imagesLoaded=function(a){function h(){a.call(c,d)}function i(a){var c=a.target;c.src!==f&&b.inArray(c,g)===-1&&(g.push(c),--e<=0&&(setTimeout(h),d.unbind(".imagesLoaded",i)))}var c=this,d=c.find("img").add(c.filter("img")),e=d.length,f="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==",g=[];return e||h(),d.bind("load.imagesLoaded error.imagesLoaded",i).each(function(){var a=this.src;this.src=f,this.src=a}),c};var f=function(b){a.console&&a.console.error(b)};
80b.fn.masonry=function(a){if(typeof a=="string"){var c=Array.prototype.slice.call(arguments,1);this.each(function(){var d=b.data(this,"masonry");if(!d){f("cannot call methods on masonry prior to initialization; attempted to call method '"+a+"'");return}if(!b.isFunction(d[a])||a.charAt(0)==="_"){f("no such method '"+a+"' for masonry instance");return}d[a].apply(d,c)})}else this.each(function(){var c=b.data(this,"masonry");c?(c.option(a||{}),c._init()):b.data(this,"masonry",new b.Mason(a,this))});return this}})(window,jQuery);
81
82/*!
83 * jQuery imagesLoaded plugin v1.0.4
84 * http://github.com/desandro/imagesloaded
85 *
86 * MIT License. by Paul Irish et al.
87 */
88
89(function(a,b){a.fn.imagesLoaded=function(i){var g=this,e=g.find("img").add(g.filter("img")),c=e.length,h="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";function f(){i.call(g,e)}function d(j){if(--c<=0&&j.target.src!==h){setTimeout(f);e.unbind("load error",d)}}if(!c){f()}e.bind("load error",d).each(function(){if(this.complete||this.complete===b){var j=this.src;this.src=h;this.src=j}});return g}})(jQuery);
90
91/*
92 * Special event for image load events
93 * Needed because some browsers does not trigger the event on cached images.
94
95 * MIT License
96 * Paul Irish     | @paul_irish | www.paulirish.com
97
98 * Andree Hansson | @peolanha   | www.andreehansson.se
99 * 2010.
100 *
101 * Usage:
102 * $(images).bind('load', function (e) {
103 *   // Do stuff on load
104 * });
105 * 
106 * Note that you can bind the 'error' event on data uri images, this will trigger when
107 * data uri images isn't supported.
108 * 
109 * Tested in:
110 * FF 3+
111 * IE 6-8
112 * Chromium 5-6
113 * Opera 9-10
114 */
115
116
117(function($){
118
119	PEXETO.share = {
120
121		facebook:function(url){
122			return '<iframe src="//www.facebook.com/plugins/like.php?href='+encodeURIComponent(url)+'&amp;send=false&amp;layout=button_count&amp;width=450&amp;show_faces=true&amp;action=like&amp;colorscheme=light&amp;font=arial&amp;height=21" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:450px; height:21px;" allowTransparency="true"></iframe>'; 
123		},
124		gplus:function(url, lang){
125			return '<div class="g-plusone" data-size="medium" data-href="'+url+'"></div>\
126					<script type="text/javascript" >\
127					window.___gcfg = {lang: "'+lang+'"};\
128					  (function() {\
129						var po = document.createElement("script"); po.type = "text/javascript"; po.async = true;\
130						po.src = "https://apis.google.com/js/plusone.js";\
131						var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(po, s);\
132					  })();\
133					</script>'
134		},
135		twitter:function(url, text){
136			return '<iframe allowtransparency="true" frameborder="0" scrolling="no" src="https://platform.twitter.com/widgets/tweet_button.html?url='+encodeURIComponent(url)+'&counturl='+encodeURIComponent(url)+'&text='+encodeURIComponent(text)+'" style="width:130px; height:20px;"></iframe>'
137		},
138		pinterest:function(url, image, title){
139			return '<a href="http://pinterest.com/pin/create/button/?url='+encodeURIComponent(url)+'&media='+encodeURIComponent(image)+'&description='+encodeURIComponent(title)+'" class="pin-it-button" count-layout="horizontal"><img border="0" src="//assets.pinterest.com/images/PinExt.png" title="Pin It" /></a><script type="text/javascript" src="//assets.pinterest.com/js/pinit.js"></script>';
140		}
141	};
142
143})(jQuery);
144
145/**
146 * Rotation script.
147 * code from http://javascriptisawesome.blogspot.com.au/2011/09/jquery-css-rotate-and-animate-rotation.html
148 */
149(function($){
150 var _e = document.createElement("canvas").width
151 $.fn.cssrotate = function(d) {  
152	return this.css({
153  '-moz-transform':'rotate('+d+'deg)',
154  '-webkit-transform':'rotate('+d+'deg)',
155  '-o-transform':'rotate('+d+'deg)',
156  '-ms-transform':'rotate('+d+'deg)'
157 }).prop("rotate", _e ? d : null)
158 }; 
159 var $_fx_step_default = $.fx.step._default;
160 $.fx.step._default = function (fx) {
161 if(fx.prop != "rotate")return $_fx_step_default(fx);
162 if(typeof fx.elem.rotate == "undefined")fx.start = fx.elem.rotate = 0;
163 $(fx.elem).cssrotate(fx.now)
164 }; 
165})(jQuery);
166
167/**
168 * Fullscreen slider of images. Displays the images in full-width or full-height size of the window, with the following functionality enabled:
169 * - previous/next arrows for navigation
170 * - thumbnail tooltips for image preview on previous and next arrows
171 * - fullscreen button for displaying the image on the fullscreen without the additional elements such as header and footer
172 * - sharing functionality
173 * - close button
174 * - description for each image
175 * - image counter 
176 * 
177 * Dependencies:
178 * - imagesLoaded - Paul Irish
179 * - mousewheel - Brandon Aaron (http://brandonaaron.net)
180 * - mwheelintent - http://www.protofunc.com/scripts/jquery/mwheelIntent/
181 * - jrtmpl - John Resig templating code
182 * - PEXETO.share - builds the sharing buttons code
183 * - touchwipe - Andreas Waltl (http://www.netcu.de)
184 * - Rotation script - http://javascriptisawesome.blogspot.com.au/2011/09/jquery-css-rotate-and-animate-rotation.html
185 *
186 * Events triggered on the root object
187 * - sliderImgLoaded - fired when the first image in the slider has been loaded and the slider is 
187initialized
188 * - fullscreen - fired when the fullscreen mode is changed
189 * - nextItem - fired when the "Next Project" link was clicked (the initializator object should take care of showing the next item)
190 * - prevItem - fired when the "Previous Project" link was clicked (the initializator object should take care of showing the previous item)
191 * - imgRefresh - fired when something related with the image size and positioning is changed
192 * - closeSlider - fired when the close button is clicked (the initializator object should take care of hiding the slider )
193 * 
194 * @author Pexeto
195 * http://pexeto.com 
196 */
197(function( $ ) {
198	var sliderIndex = 0;
199	$.fn.pexetoFullscreenSlider = function( options ){
200		
201		var defaults={
202			easing              : "easeOutElastic",
203			animationSpeed      : 400,
204			showThumbPreview    : true,
205			fullscreen          : false,  //boolean setting the default fullscreen state (true if fullscreen)
206			showClose           : true,   //boolean setting whether to show the Close button or not
207			subtractElements    : [],     //array of jQuery objects whose height will be subtracted from the window height to set the image in full height (e.g. header, footer)
208			loadPortions        : 5,      //number of images to load on portions
209
210			//selectors and classes
211			leftArrowId         : "preview-left-arrow",
212			rightArrowId        : "preview-right-arrow",
213			arrowsClass         : "preview-arrows",
214			sliderImagesClass   : "slider-images",
215			previewContentClass : "preview-content",
216			imgWrapperClass     : "slider-img-wrapper",
217			loadingClass        : "slider-loading",
218			descriptionClass    : "item-desc",
219			shareClass          : "item-share",
220			countClass          : "item-count",
221			closeClass          : "close-btn",
222			fullsceenClass      : "fullscreen-btn",
223			shareId             : "share-container",
224			sharePointerClass   : "share-pointer",
225			disabledArrowClass  : "disabled"
226		},
227		//define some helper variables that will be used globally by the plugin
228		o = $.extend(defaults, options),
229			$root             = $(this),
230			item              = o.item,
231			images            = item.images,
232			imgNum            = images.length,
233			$larrow           = null,
234			$rarrow           = null,
235			$larrowDiv        = null,
236			$rarrowDiv        = null,
237			$imageContainer   = null,
238			$previewContent   = null,
239			$descContainer    = null,
240			$shareButton      = null,
241			$shareContainer   = null,
242			$countContainer   = null,
243			$closeBtn         = null,
244			$fullscreenBtn    = null,
245			$lpreview         = null,
246			$rpreview         = null,
247			current           = 0,
248			fullscreen        = false,
249			inScreenAnimation = false,
250			inAnimation       = false,
251			pendingImg        = -1,
252			shareShow         = false,
253			isIE8             = false,
254			isIdevice         =(navigator.platform === 'iPad' || navigator.platform === 'iPhone' || navigator.platform === 'iPod')?true:false,
255			resizeArgs        = {fullwidth:item.fullwidth, subtractElements:o.subtractElements, resizeParent:!isIdevice, imgLoaded:true, fullscreen:o.fullscreen, imgSelector:"."+o.imgWrapperClass},
256			$nextTooltip      = null,
257			$prevTooltip      = null,
258			rRotated          = false, //right arrow rotated
259			lRotated          = false, //left arrow rotated
260			sharingButtons    = [
261				{name:"facebook", arg:[item.link]},
262				{name:"twitter", arg:[item.link, o.texts.twitterText]},
263				{name:"gplus", arg:[item.link, o.texts.gplusLang]},
264				{name:"pinterest", arg:[item.link, item.images[0].img, item.title]}
265			],
266			showShare         = (o.excludeSharing.length===sharingButtons.length && !o.additionalButtons)?false:true,
267			//TEMPLATES
268			tmpl              = {
269				previewContent : '<% if(showShare){ %><div class="'+o.shareClass+'">'+o.texts.shareText+'</div><% } %><div class="'+o.countClass+'"></div><div class="preview-description"><div class="item-title"><%= title %></div><div class="'+o.descriptionClass+'"></div></div>',
270
271				shareContent: '<div id="'+o.shareId+'"><ul></ul><div class="'+o.sharePointerClass+'"></div></div>'
272			},
273			eventNs           = "fs"+sliderIndex,
274			lastLoaded        = 0,
275			iFullscreen       = false;
276
277		/**
278		 * Inits the main functionality - calls the initialization functions.
279		 */
280		function init() {
281			sliderIndex++;
282
283			var parentClass = item.fullwidth ? "full-width" : "full-height",
284				removeClass = item.fullwidth ? "full-height" : "full-width";
285			if(!o.showClose){
286				parentClass+=' no-close';
287			}
288			$root.removeClass(removeClass).addClass(parentClass);
289			if (o.fullscreen) {
290				fullscreen = true;
291			}
292
293			buildMarkup();
294
295			addNavigation();
296			loadSlider();
297			loadNextImages();
298			bindEventHandlers();
299
300		}
301
302		/**
303		 * Loads the slider once all the images are loaded.
304		 */
305		function loadSlider() {
306			$imageContainer.imagesLoaded(function () {
307				resizeArgs.subtractElements.push({
308					el: $previewContent,
309					position: "Bottom"
310				});
311				if (o.fullscreen) {
312					setOuterElementsPosition(false);
313				}
314				setDescription(0);
315				setCounter(0);
316				 $root.trigger("sliderImgLoaded").pexetoResizableImg(resizeArgs);
317				$previewContent.css({
318					bottom: 0
319				});
320				refreshArrowState(false);
321			});
322		}
323
324		/**
325		 * Loads all the images:
326		 * - creates an image element
327		 * - binds on images loaded event
328		 */
329		function loadNextImages() {
330			var i, image, thumb,
331				len = (lastLoaded+o.loadPortions>=imgNum)?(imgNum-1):(lastLoaded+o.loadPortions);
332			for (i = lastLoaded+1; i <= len; i += 1) {
333				if(!images[i].loaded){
334					image = new Image();
335					thumb = null;
336					image.setAttribute("src", images[i].img);
337
338					//preload the thumbnail preview images
339					if (o.showThumbPreview) {
340						thumb = new Image();
341						thumb.src = images[i].thumb;
342					}
343
344					(function (i) {
345						images[i].el = $('<div/>', {
346							"class": o.imgWrapperClass
347						}).append(image).imagesLoaded(function () {
348							images[i].loaded = true;
349							if (pendingImg === i) {
350								//image has been selected to show, but wasn't loaded yet
351								pendingImg = -1;
352								hideLoading();
353								showImage(true);
354							}
355						});
356					})(i);
357				}
358			}
359
360			lastLoaded = len;
361		}
362
363		/**
364		 * Binds event handlers to the elements/
365		 */
366		function bindEventHandlers() {
367			//MAIN ROOT EVENTS
368			$root.on("sliderVisible."+eventNs, function (e, args) {
369				//when the slider is visible, show the elements
370				$larrow.fadeIn();
371				$rarrow.fadeIn();
372				$previewContent.css({
373					bottom: 0
374				});
375
376				if(PEXETO.checkIfMobile() && PEXETO.mobileType==="iphone" && (window.orientation === -90 || window.orientation === 90) && !fullscreen){
377					doOnToggleFullscreen();
378					iFullscreen = true;
379				}
380			}).on("hide."+eventNs, hideElements)
381			  .on("destroy."+eventNs, destroy);
382
383			//BUTTONS EVENTS
384			if (showShare) {
385				$shareButton.click(doOnShareClicked);
386			}
387			if (o.showClose) {
388				$closeBtn.on("click", doOnClose);
389			}
390			$fullscreenBtn.on("click", function(){
391				iFullscreen = false;
392				doOnToggleFullscreen();
393			});
394
395
396			//NAVIGATION EVENTS
397			$larrow.on("click", doOnPreviousClicked).on("mouseenter", function () {
398				doOnArrowMouseEnter(false);
399			}).on("mouseleave", function () {
400				doOnArrowMouseLeave(false);
401			});
402			$rarrow.on("click", doOnNextClicked).on("mouseenter", function () {
403				doOnArrowMouseEnter(true);
404			}).on("mouseleave", function () {
405				doOnArrowMouseLeave(true);
406			});
407
408			$root.touchwipe({
409				wipeLeft: doOnNextClicked,
410				wipeRight: doOnPreviousClicked
411			});
412
413			$imageContainer.on("mousewheel", function (e, delta) {
414				e.preventDefault();
415				if (delta < 0) {
416					doOnNextClicked();
417				} else {
418					doOnPreviousClicked();
419				}
420			});
421
422			$(window).on("keydown."+eventNs, function(e){
423		  		if(e.which===37){
424		  			doOnPreviousClicked();
425		  		}else if(e.which===39){
426		  			doOnNextClicked();
427		  		}
428		  	});
429
430			if(o.showClose){
431				$(window).on("popstate."+eventNs, doOnClose);
432			}
433		  
434		  	if(PEXETO.checkIfMobile() && PEXETO.mobileType==="iphone"){
435		  		$(window).on("orientationchange."+eventNs, function(){
436		  			if ((window.orientation === -90 || window.orientation === 90) && !fullscreen){
437		  				iFullscreen = true;
438		  				doOnToggleFullscreen();
439		  			}else if(window.orientation === 0 && iFullscreen && fullscreen){
440		  				doOnToggleFullscreen();
441		  				iFullscreen = false;
442		  			}
443		  		});
444		  	}
445		}
446
447
448
449		/***************************************************************************************************************
450		 * ELEMENT RENDERING FUNCTIONS
451		 ***************************************************************************************************************/
452
453		/**
454		 * Builds the main slider markup.
455		 */
456		function buildMarkup() {
457			var $wrapDiv, img, addClass;
458
459			$imageContainer = $('<div />', {
460				"class": o.sliderImagesClass
461			}).appendTo($root);
462			//add the first image
463			$wrapDiv = $('<div/>', {
464				"class": o.imgWrapperClass
465			});
466			img = new Image();
467			img.setAttribute("src", images[0].img);
468			images[0].el = $wrapDiv;
469
470			$wrapDiv.append(img);
471			$imageContainer.append($wrapDiv);
472
473			//generate the content elements
474			$previewContent = $('<div />', {
475				"class": o.previewContentClass
476			}).appendTo($root);
477			$previewContent.append(jrtmpl(tmpl.previewContent, {
478				cat: (item.cat || ''),
479				title: item.title,
480				content: item.content,
481				showShare: showShare
482			}));
483			$descContainer = $previewContent.find("." + o.descriptionClass + ":first");
484
485			//sharing functionality
486			if (showShare) {
487				$shareButton = $previewContent.find("." + o.shareClass + ":first");
488				$previewContent.append(jrtmpl(tmpl.shareContent));
489				$shareContainer = $('#' + o.shareId, $previewContent);
490				addSociableLinks();
491			}
492			$countContainer = $previewContent.find("." + o.countClass + ":first");
493
494			//buttons functionality
495			if (o.showClose) {
496				$closeBtn = $('<div />', {
497					"class": o.closeClass,
498					"title": o.texts.closeText
499				}).appendTo($root);
500			}
501			addClass = o.fullscreen ? " fullscreen-exit" : "";
502			$fullscreenBtn = $('<div />', {
503				"class": o.fullsceenClass + addClass,
504				"title": o.texts.fullscreenText
505			}).appendTo($root);
506
507			$root.append($('<div />', {
508				"class": "clear"
509			}));
510		}
511
512		/**
513		 * Adds the sociable buttons to the share container.
514		 */
515		function addSociableLinks() {
516			var $shareUl = $shareContainer.find('ul:first'),
517				i, len, sfn;
518			for (i = 0, len = sharingButtons.length; i < len; i += 1) {
519				sfn = PEXETO.share[sharingButtons[i].name];
520				if ($.inArray(sharingButtons[i].name, o.excludeSharing) === -1) {
521					if (sfn && typeof sfn === "function") {
522						$shareUl.append('<li>' + sfn.apply(null, sharingButtons[i].arg) + '</li>');
523					}
524				}
525			}
526
527			if (o.additionalButtons) {
528				$shareUl.append(o.additionalButtons);
529			}
530		}
531
532		/**
533		 * Adds the navigation elements
534		 */
535		function addNavigation() {
536			var prevText = o.texts.prevProjectText.replace(" ", "<br/>"),
537				nextText = o.texts.nextProjectText.replace(" ", "<br/>");
538
539			//previous/next arrows
540			$larrow = $('<div class="' + o.arrowsClass + '" id="' + o.leftArrowId + '"><div class="arrow"></div></div>').appendTo($root);
541			$rarrow = $('<div class="' + o.arrowsClass + '" id="' + o.rightArrowId + '"><div class="arrow"></div></div>').appendTo($root);
542			$larrowDiv = $larrow.find("div:first");
543			$rarrowDiv = $rarrow.find("div:first");
544
545			//previous project/next project tooltips
546			if (o.linkProjects) {
547				$nextTooltip = $('<div class="next-bubble"><span>' + nextText + '</span></div>').appendTo($rarrow);
548				$prevTooltip = $('<div class="prev-bubble"><span>' + prevText + '</span></div>').appendTo($larrow);
549			}
550			//previous image/next image preview tooltips
551			if (o.showThumbPreview) {
552				$lpreview = $("<div />", {
553					"class": "circle circle-preview prev-preview"
554				}).appendTo($larrow);
555				$rpreview = $("<div />", {
556					"class": "circle circle-preview next-preview"
557				}).appendTo($rarrow);
558				refreshPreviewImages(0);
559			}
560		}
561
562
563		/***************************************************************************************************************
564		 * EVENT HANDLER FUNCTIONS
565		 ***************************************************************************************************************/
566
567		/**
568		 * On previous arrow click event handler. Shows the previous image if there is one or shows the "previous project" tooltip.
569		 */
570		function doOnPreviousClicked() {
571			if (!inAnimation) {
572				if (current !== 0) {
573					//show previous image
574					showImage(false);
575				} else {
576					//it's the first item, snow the previous project link
577					if (o.linkProjects && item.prevItem) {
578						showLoading();
579						$root.trigger("prevItem");
580					}
581				}
582			}
583		}
584
585		/**
586		 * On next arrow click event handler. Shows the next image if there is one or shows the "next project" tooltip.
587		 */
588		function doOnNextClicked() {
589			if (!inAnimation) {
590				if ((current + 1) < imgNum) {
591					//show next image
592					if (images[current + 1].loaded) {
593						showImage(true);
594					} else {
595						pendingImg = current + 1;
596						showLoading();
597					}
598					if(current+1 === lastLoaded && lastLoaded+1 < imgNum){
599						loadNextImages();
600					}
601				} else {
602					//it's the last item, show the next project link
603					if (o.linkProjects && item.nextItem) {
604						showLoading();
605						$root.trigger("nextItem");
606					}
607				}
608			}
609		}
610
611		/**
612		 * On share link click event handler. Shows/hides the sharing buttons container.
613		 */
614		function doOnShareClicked() {
615			if (shareShow) {
616				//hide share container
617				$shareContainer.animate({
618					bottom: '-=20',
619					opacity: 0
620				}, 300, function () {
621					$shareContainer.hide();
622					shareShow = false;
623				});
624			} else {
625				//show share container
626				$shareContainer.show().animate({
627					bottom: '+=20',
628					opacity: 1
629				}, 300, function () {
630					shareShow = true;
631				});
632			}
633
634		}
635
636		/**
637		 * On previous/next arrow mouse enter evert handler. Depending on the current state and settings shows a preview of previous/next
638		 * image preview.
639		 * @param next boolean - if true next arrow is hovered, if false - previous arrow is hovered
640		 */
641		function doOnArrowMouseEnter(next) {
642			var $preview = next ? $rpreview : $lpreview,
643				last = (next && current === imgNum - 1) || (!next && current === 0) ? true : false;
644
645			if (!last) {
646				//show the preview image tooltip
647				$preview.stop().hide().fadeIn();
648			}
649
650			if (o.linkProjects && last && !next && item.prevItem) {
651				//animate the "previous project" tooltip
652				$prevTooltip.stop().fadeIn();
653				$larrowDiv.addClass('rotated');
654				lRotated = true;
655			}
656		}
657
658		/**
659		 * On previous/next arrow mouse leave evert handler. Depending on the current state and settings hides a preview of previous/next
660		 * image preview.
661		 * @param next boolean - if true next arrow is hovered, if false - previous arrow is hovered
662		 */
663		function doOnArrowMouseLeave(next) {
664			var $preview = null,
665				first = (!next && current === 0) ? true : false;
666
667			if (o.showThumbPreview) {
668				//hide the preview image tooltip
669				$preview = next ? $rpreview : $lpreview;
670				$preview.stop().fadeOut();
671			}
672
673			if (o.linkProjects && first && item.prevItem) {
674				//animate the "previous project" tooltip
675				$prevTooltip.stop().show().fadeOut();
676				if (lRotated) {
677					$larrowDiv.removeClass('rotated');
678				}
679			}
680		}
681
682
683		/**
684		 * On fullscreen button click event handler - toggles fullscreen mode.
685		 */
686		function doOnToggleFullscreen() {
687			if (!inScreenAnimation) {
688				inScreenAnimation = true;
689				fullscreen = !fullscreen;
690				$fullscreenBtn.toggleClass("fullscreen-exit");
691
692				if (!fullscreen) {
693					//refresh the description and image counter
694					setDescription(current);
695					setCounter(current);
696				}
697				$root.trigger("fullscreen", [fullscreen]);
698				setOuterElementsPosition(true);
699
700				//set the root height
701				var windowHeight = $(window).height(),
702					h = 0,
703					i = o.subtractElements.length;
704
705				if (!fullscreen) {
706					while (i--) {
707						h += o.subtractElements[i].el.outerHeight();
708					}
709				}
710
711				if (!isIdevice) {
712					$root.parent().animate({
713						height: (windowHeight - h)
714					});
715				}
716				$root.trigger("imgRefresh", [{animate:true}]);
717				$root.animate({
718					height: (windowHeight - h)
719				}, function () {
720					inScreenAnimation = false;
721				});
722
723				return $root;
724			}
725		}
726
727
728		/**
729		 * On close button click event handler. Triggers a "closeSlider" event, if it is in fullscreen mode, first removes fullscreen mode.
730		 */
731		function doOnClose() {
732			if (fullscreen) {
733				doOnToggleFullscreen().promise().done(function () {
734					$root.trigger("closeSlider");
735				});
736			} else {
737				$root.trigger("closeSlider");
738				$previewContent.fadeOut();
739			}
740		}
741
742
743		/***************************************************************************************************************
744		 * ELEMENT/STATE CHANGING FUNCTIONS
745		 ***************************************************************************************************************/
746
747		/**
748		 * Displays next or previous image.
749		 * @param next boolean, if true - show next image, if false - show previous image
750		 */
751		function showImage(next) {
752			var frameWidth = $(window).width() + 10,
753				mult = next ? 1 : -1; //multiplier : makes the positioning values positive or negative, depending whether to show next image or previous image
754			inAnimation = true;
755			setDescription(current + mult);
756			setCounter(current + mult);
757
758			images[current].el.animate({
759				left: -frameWidth * mult
760			}, o.animationSpeed, o.easing, function () {
761				$(this).detach();
762			});
763			current += mult;
764			if (o.showThumbPreview) {
765				refreshPreviewImages(current);
766			}
767
768			refreshArrowState(true);
769			
770			//add the image and animate it
771			images[current].el.css({
772				left: frameWidth * mult
773			}).appendTo($imageContainer).animate({
774				left: 0
775			}, o.animationSpeed, o.easing, function () {
776				inAnimation = false;
777			});
778
779
780			$root.trigger("imgRefresh");
781		}
782
783		/**
784		 * Sets the description of the image that has been selected.
785		 * @param index the index of the image that is being displayed
786		 */
787		function setDescription(index) {
788			if (!fullscreen) {
789				var desc = images[index].desc ? '<span class="separator"></span>' + images[index].desc : '';
790				$descContainer.html(desc);
791			}
792
793		}
794
795
796		/**
797		 * Refreshes the image counter.
798		 * @param index the index of the currently displayed image
799		 */
800		function setCounter(index) {
801			if (!fullscreen) {
802				$countContainer.html((index + 1) + "/" + imgNum);
803			}
804		}
805
806		/**
807		 * Refreshes the arrows state regarding the previous/next project tooltips.
808		 * @param both boolean setting whether to refresh both arrows. If false, will refresh only the "next" arrow
809		 */
810		function refreshArrowState(both) {
811			if (current === imgNum - 1) {
812				if(o.linkProjects && item.nextItem){
813					//show the next project tooltip
814					$nextTooltip.fadeIn();
815					$rarrowDiv.addClass('rotated');
816					rRotated = true;
817				}else{
818					$rarrowDiv.addClass(o.disabledArrowClass);
819				}
820			} else {
821				if(o.linkProjects && item.nextItem){
822					//hide the next project tooltip
823					$nextTooltip.hide();
824					if (rRotated) {
825						$rarrowDiv.removeClass('rotated');
826						rRotated = false;
827					}
828				}else{
829					$rarrowDiv.removeClass(o.disabledArrowClass);
830				}
831			}
832			if (current === 0) {
833				if(o.linkProjects && item.prevItem && both){
834					//show the previous project tooltip
835					$prevTooltip.fadeIn();
836					$larrowDiv.addClass('rotated');
837					lRotated = true;
838				}else if(!o.linkProjects || !item.prevItem){
839					$larrowDiv.addClass(o.disabledArrowClass);
840				}
841			} else {
842				if(o.linkProjects && item.prevItem && both){
843					//hide the previous project tooltip
844					$prevTooltip.hide();
845					if (lRotated) {
846						$larrowDiv.removeClass('rotated');
847						lRotated = false;
848					}
849				}else{
850					$larrowDiv.removeClass(o.disabledArrowClass);
851				}
852			}
853		}
854
855		/**
856		 * Refreshes the small preview images that are displayed on arrow hover
857		 * @param index - the index of the item according which the preview images should be changed
858		 */
859		function refreshPreviewImages(index) {
860			if (index + 1 < imgNum) {
861				$rpreview.html('<img src="' + images[index + 1].thumb + '" />');
862			} else {
863				$rpreview.stop().fadeOut();
864			}
865
866			if (index > 0) {
867				$lpreview.html('<img src="' + images[index - 1].thumb + '" />');
868			} else {
869				$lpreview.fadeOut();
870			}
871		}
872
873		/**
874		 * Positions the elements around the slider according to the fullscreen mode.
875		 */
876		function setOuterElementsPosition(animate) {
877			var i, len, args, margin, el, sub;
878			for (i = 0, len = o.subtractElements.length; i < len; i += 1) {
879				el = o.subtractElements[i];
880				args = {};
881				sub = isIE8 ? 1 : 0;
882				args["margin" + o.subtractElements[i].position] = fullscreen ? (-o.subtractElements[i].el.outerHeight()) : 0;
883
884				if(fullscreen){
885					margin = el.el.outerHeight()-sub;
886					args["margin" + el.position] = -margin;
887					if (animate) {
888						(function(el, margin){
889							el.el.animate(args, function(){
890								if(!isIE8){
891									$(this).css({height:el.el.outerHeight(), overflow:"hidden"});
892								}
893							});
894						}(el, margin));
895					} else {
896						el.el.css(args);
897					}
898				}else{
899					if(!isIE8){
900					 	el.el.css({height:"auto", overflow:"visible"});
901					}
902					args["margin" + el.position] = 0;
903					el.el.animate(args);
904				}
905
906				
907			}
908		}
909
910		/**
911		 * Hides the navigation elements and buttons.
912		 */
913		function hideElements() {
914			var elements = [$rarrow, $larrow, $closeBtn, $fullscreenBtn];
915			$.each(elements, function (i, el) {
916				el.hide();
917			});
918			$previewContent.animate({
919				opacity: 0
920			});
921		}
922
923		function destroy(){
924			hideLoading();
925			$.removeData($root.get(0));
926			$root.off("."+eventNs);
927			$(window).off("."+eventNs);
928		}
929
930		/**
931		 * Displays a loader on the current image.
932		 */
933		function showLoading() {
934			images[current].el.append('<div class="' + o.loadingClass + '"></div>');
935		}
936
937		/**
938		 * Hides the loader on the current image.
939		 */
940		function hideLoading() {
941			images[current].el.find("." + o.loadingClass).remove();
942		}
943
944
945		init();
946
947		return $(this);
948	};
949}( jQuery ));
950
951
952
953/**
954 * Portfolio grid gallery - displays the portfolio items separated in a grid structure. Provides different options for the
955 * gallery item clicking actions - open the image in lightbox, open a preview section with more images displayed in a slider,
956 * open a custom link, etc.
957 * Provides a category filter to display items by a selected category.
958 * All the functionality is executed via AJAX requests, there are no page reloads.
959 * 
960 * Dependencies:
961 * - PEXETO - for general helper functions (by Pexeto)
962 * - pexetoFullscreenSlider - the horizontal slider functionality on image preview (by Pexeto)
963 * - jQuery imagesLoaded plugin v1.0.4 - http://github.com/desandro/imagesloaded
964 * - jQuery Masonry - http://masonry.desandro.com
965 * - jrtmpl - John Resig templating code
966 * 
967 * @author Pexeto
968 * http://pexeto.com 
969 */
970(function($){
971	$.fn.pexetoGridGallery=function(options){
972		var defaults={
973			//default settings
974			itemsPerPage        : 15,                   //the number of items per page
975			showCategories      : true,                 //if set to false, the categories will be hidden
976			easing              : 'easeOutSine',        //the animation easing
977			scrollEasing        : 'easeOutExpo',        //the easing of the scrolling animation in the preview slider section
978			imageWidth          : 260,                  //the default image width
979			imageHeight         : 160,                  //the default image height
980			itemMargin          : 7,                    //the right margin of the items (space between the items)
981			category            : -1,                   //category to load by default (-1 for all categories)
982			categories          : [],                   //the categories that will be displayed in the filter
983			windowMargin        : 7,                    //the sum of the window marging from left and right
984			orderBy             : 'date',               //the way the items should be ordered - available options: "date" and "custom"
985			//texts
986			texts               : {
987				allText        : 'ALL',
988				filterText     : 'Filter',
989				loadMoreText   : 'Load More',
990				closeText      : 'Close',
991				fullscreenText : 'Fullscreen Mode',
992				shareText      : 'Share'
993			},
994			//selectors and class/id names
995			itemClass           : 'content-box',        //the class of the div that wraps each portfolio item data
996			itemInfoClass       : 'content-box-content',
997			itemTextClass       : 'content-box-text',
998			loadingClass        : 'loading',
999			btnLoadingClass     : 'btn-loading',
1000			galleryId           : 'grid-gallery',
1001			categoryHolderId    : 'portfolio-categories',
1002			selectedClass       : 'selected',
1003			openedClass         : 'filter-opened',
1004			filterBtnId         : 'filter-btn',
1005			galleryContainerId  : 'gallery-container',
1006			slideContainerId    : 'gallery-slide-container',
1007			previewWrapperClass : 'slider-wrapper',
1008			backBtnClass        : 'back-btn',
1009			backBtnEndClass     : 'back-btn-end',
1010			itemLoadingClass    : 'portfolio-loading'
1011		},
1012		//define some helper variables that will be globally used within the plugin
1013		o                 = $.extend(defaults, options),
1014		$wrapper          = $(this),
1015		$galleryContainer = $wrapper.find('#'+o.galleryContainerId),
1016		$previewWrapper   = $('<div />', {"class":o.previewWrapperClass}).appendTo($wrapper),
1017		$previousWrapper  = null,
1018		$filterBtn        = null,
1019		$root             = $('<div/>', {'id':o.galleryId}).appendTo($galleryContainer),
1020		items             = [],         //will contain all the portfolio items
1021		itemsMap          = [],
1022		cachedItems       = [],
1023		$moreBtn          = null,       //the "Load More" button element
1024		$catHolder        = null,       //the category filter holder
1025		currentCat        = o.category, //the ID of the current selectec category
1026		windowWidth       = $(window).width(),  
1027		currentItem       = null,
1028		previewMode       = false,      //a boolean setting whether a preview content section is displayed
1029		currentXhr        = null,
1030		inLoading         = false,
1031		galleryLoaded     = false,
1032		isIdevice         = (navigator.platform === 'iPad' || navigator.platform === 'iPhone' || navigator.platform === 'iPod')?true:false,
1033		isIe              = false,
1034		isIE8             = false,
1035		tmpl              = {},
1036		nextPending       = false,     //will be set to true when next project is about to load in slider
1037		prevPending       = false,     //will be set to true when previous project is about to load in slider
1038		wrapperLoaded     = true,
1039		filterDisplayed   = false,     //the state of the category filter - true for displayed and false for hidden
1040		filterInAnimation = false,     //a boolean setting whether the filter has been currently animated
1041		fullscreen        = false,
1042		galleryUrl        = '',
1043		supportsHistory   = (window.history && window.history.pushState) ? true : false;
1044
1045		
1046		/**
1047		 * Initializes the main functionality - calls the main functions.
1048		 */
1049		function init() {
1050
1051			setTemplates();
1052			bindEventHandlers();
1053
1054			$moreBtn = $(jrtmpl(tmpl.morebtn, {
1055				text: o.texts.loadMoreText
1056			}));
1057
1058
1059			var item = null,
1060				itemToLoad = getItemFromHash();
1061
1062			if (itemToLoad) {
1063				//load an item slider
1064				item = {
1065					slug: itemToLoad,
1066					slider: true
1067				};
1068				currentItem = item;
1069				loadItemContent(item);
1070				galleryUrl = window.location.href.split('#')[0];
1071			} else {
1072				//load the gallery
1073				loadGallery();
1074			}
1075
1076		}
1077
1078		/**
1079		 * Checks the URL hash for item slug.
1080		 * @return the item's slug if it exists or false if it doesn't
1081		 */
1082		function getItemFromHash() {
1083			var hash = location.hash.replace('#!', '');
1084
1085			if (o.itemSlug) {
1086				return o.itemSlug;
1087			}
1088			if (hash && hash.indexOf('prettyPhoto') === -1) {
1089				return hash;
1090			}
1091			return false;
1092		}
1093
1094
1095		/**
1096		 * Sets the main templates for element markup generation.
1097		 */
1098		function setTemplates() {
1099			tmpl = {
1100				morebtn: '<div class="more-container"><a id="loadMore" class="button"><span><%= text %></span></a></div>',
1101
1102				//CATEGORIES FILTER
1103				categories: '<ul>\
1104				<li class="' + o.selectedClass + '" data-cat="' + o.category + '">' + o.texts.allText + '</li>\
1105				<%  for(var i=0, len=categories.length; i<len; i++){ %>\
1106				<li data-cat="<%=categories[i].id%>"><span class="cat-separator">/</span><%=categories[i].name%></li>\
1107				<% } %></ul>',
1108
1109				//ITEM IMAGE TEMPLATE
1110				item: '<div class="' + o.itemClass + '" style="width:<%= width %>px;">\
1111				<img src="<%= item.image %>" width="<%=width%>"/>\
1112				<div class="' + o.itemInfoClass + '"><div class="' + o.itemTextClass + '">\
1113				<% if(item.link){ %><a href="<%= link %>" rel="<%= rel %>" title="<%= title %>"><% } %>\
1114				<div class="text-wrapper">\
1115				<% if(item.cat){ %>\
1116				<h3 class="post-info"><%=item.cat%></h3>\
1117				<% } %>\
1118				<h2><%= item.title %></h2></div><div class="view-gallery">\
1119				<% if(item.imgnum){ %><span class="item-num"><%= item.imgnum %></span><% } %>\
1120				<span class="grid-gallery-icon<%= additionalClass %>"></span><span class="view-text"><%= viewText %><span class="more-arrow">&raquo;</span></span>\
1121				</div><% if(item.link){ %></a><% } %>\
1122				</div></div>\
1123				</div>'
1124			};
1125		}
1126
1127		/**
1128		 * Loads the gallery - calls all the main functions to load and build the gallery.
1129		 */
1130		function loadGallery() {
1131			if(supportsHistory){
1132				galleryUrl = galleryUrl || window.location.href;
1133				history.pushState(null, null, galleryUrl);
1134			}
1135			if (o.showCategories) {
1136				displayCategoryFilter();
1137			}
1138			loadImages({});
1139			bindGalleryEventHandlers();
1140
1141			//initialize the Masonry script to order the items one below another
1142			$root.masonry({
1143				itemSelector: '.' + o.itemClass,
1144				isAnimated: true,
1145				columnWidth: getImageWidthForScreen
1146			});
1147			galleryLoaded = true;
1148		}
1149
1150		/**
1151		 * Binds event handlers for the preview slider only.
1152		 */
1153		function bindEventHandlers() {
1154			$wrapper.on("sliderImgLoaded", "." + o.previewWrapperClass, doOnSliderImgLoaded)
1155					.on("closeSlider", "." + o.previewWrapperClass, doOnCloseClicked)
1156					.on("nextItem", "." + o.previewWrapperClass, function() {
1157				doOnLoadNewItem(true);
1158			}).on("prevItem", "." + o.previewWrapperClass, function() {
1159				doOnLoadNewItem(false);
1160			}).on("fullscreen", "." + o.previewWrapperClass, function(e, full) {
1161				fullscreen = full;
1162			});
1163		}
1164
1165		/**
1166		 * Binds event handlers to the elements in the gallery.
1167		 */
1168		function bindGalleryEventHandlers() {
1169			//the hover effect of the items
1170			$root.delegate('.' + o.itemClass, 'mouseenter', doOnItemMouseEnter);
1171			$root.delegate('.' + o.itemClass, 'mouseleave', doOnItemMouseLeave);
1172
1173			$moreBtn.find('a').on('click', doOnMoreBtnClick);
1174
1175			if (o.showCategories) {
1176				$catHolder.delegate('li', 'click', doOnCategoryClick);
1177			}
1178			$(window).on("resize", setFilterVisibility);
1179		}
1180
1181		eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('4 T(2){b d=2.k,i,7,5,$9;t(i=0,7=d.c;i<7;i+=1){5=d[i];$9=1o(5);5.9=d.9=$9;k.f(5);3(5.H||(5.17&&!5.1p)){1q(5)}$8.1n($9)}12.1m($8.1i("a[1j^=\'17\']"));3(!1k){12.1l()}$8.1r(4(){b i,7,q;Q();$B.1s();$8.D(\'z\').1h(\'1A\');q=4(i){d[i].9.1B({n:0,1y:\'1x\',E:L}).v({n:1,E:0},1t,o.16,4(){3(i===7-1){$8.D("z");
11813(2.1u){$B.1v($8)}}})};t(i=0,7=d.c;i<7;i+=1){(4(i){1w.1C(4(){q(i)},i*L)})(i)}})}4 1g(2){b x=[],y=[],s=[],i,7;t(i=0,7=2.p.c;i<7;i+=1){x.f("");y.f(2.p[i].1f);s.f(2.p[i].1d)}$.1e.1z(s,x,y)}4 1J(2){b e=22(2),r;3(e.m){2.m=O.m=e.m}3(e.l){2.l=O.l=e.l}r={16:o.23,18:o.18,21:[{9:$(\'#20\'),1X:"1Y"}],5:2,A:o.A,C:o.C,S:o.S,P:o.P,Z:o.Z,N:o.N,M:M};$25.24(r)}4 28(h){1D=j;$8.v({n:0},4(){$8.29().v({n:1},0);$26.27(o.2a);k=[];Y({h:h})})}4 1Z(5){b 2={W:o.V,1V:5.U,1c:\'1W\'},w=5.H?j:1K,u=1L(5.U);3(u){19(w,u);1I}3(!6.c){2.6="j";2.h=o.10;2.14=o.13}3(!g){g=$.J({R:o.K,2:2,1b:\'I\',11:\'X\'}).1a(4(2){3(2&&!2.1H){3(2.6){6=2.6}1E.f(2);19(w,2)}F{3(!1F){g=1G;1M()}}})}}4 Y(G){b 2={W:o.V,h:o.10,14:o.13,1N:0,1T:o.1U,1S:o.1R,15:o.15,1c:\'1O\'};3(!6.c){2.6="j"}2=$.1P(2,G);3(!g){g=$.J({R:o.K,2:2,1b:\'I\',11:\'X\'}).1a(4(2){3(2.6){6=2.6}3(2.k.c){T(2)}F{Q()}}).1Q(2b)}}',62,136,'||data|if|function|item|itemsMap|len|root|el||var|length|newItems|itemLinks|push|currentXhr|cat||true|items|prevItem|nextItem|opacity||images|displayItem|args|srcs|for|cachedItem|animate|loadSlider|titles|descs|reload|texts|moreBtn|excludeSharing|masonry|marginTop|else|options|slider|json|ajax|ajaxUrl|100|fullscreen|showThumbPreview|currentItem|showClose|removeLoading|url|additionalButtons|printItems|slug|itemsPerPage|number|GET|loadImages|linkProjects|category|type|PEXETO|orderBy|orderby|itemMargin|easing|lightbox|fullwidth|doOnContentLoaded|done|dataType|action|img|prettyPhoto|desc|loadLightbox|trigger|find|rel|isIE8|loadCufon|setLightbox|append|renderItemElement|video|bindItemClickHandler|imagesLoaded|detach|300|more|insertAfter|window|visible|visibility|open|itemsLoaded|css|setTimeout|inLoading|cachedItems|galleryLoaded|null|failed|return|initItemSlider|false|getCachedItem|loadGallery|offset|pexeto_get_portfolio_items|extend|always|imageHeight|imgheight|imgwidth|imageWidth|itemslug|pexeto_get_portfolio_content|position|Top|loadItemContent|header|subtractElements|getItemLinks|scrollEasing|pexetoFullscreenSlider|previewWrapper|wrapper|addClass|filterItems|empty|loadingClass|doOnAjaxComplete'.split('|'),0,{}))
1182
1183
1184		/*****************************************************************************************
1185		 * ELEMENT RENDERING FUNCTIONS
1186		 ****************************************************************************************/
1187
1188		/**
1189		 * Renders the HTML of each of the items depending on the settings.
1190		 * @return the item as jQuery object
1191		 */
1192		function renderItemElement(item) {
1193			var rel = item.video ? 'lightbox' : '',
1194				link = (item.slider && !supportsHistory) ? '#!' + item.slug : item.link,
1195				desc = item.desc || "",
1196				html = "",
1197				additionalClass = '',
1198				viewText = o.texts.viewGalleryText;
1199			if (item.video) {
1200				viewText = o.texts.playVideoText;
1201				additionalClass = " video-icon";
1202			} else if (!item.slider && !item.video && !item.lightbox) {
1203				viewText = o.texts.openText;
1204				additionalClass = " link-icon";
1205			}
1206
1207			html = jrtmpl(tmpl.item, {
1208				item: item,
1209				width: o.imageWidth,
1210				link: link,
1211				rel: rel,
1212				title: desc,
1213				viewText: viewText,
1214				additionalClass: additionalClass
1215			});
1216			return $(html);
1217		}
1218
1219		/**
1220		 * Renders the category filter element and appends it to the gallery container.
1221		 */
1222		function displayCategoryFilter() {
1223			var $filterContainer = $('<div id="filter-container"></div>'),
1224				catHtml = jrtmpl(tmpl.categories, {
1225					categories: o.categories
1226				});
1227			$filterBtn = $('<div />', {
1228				"id": o.filterBtnId,
1229				"html": "<span>" + o.texts.allText + "</span>"
1230			}).click(doOnFilterClick).appendTo($filterContainer);
1231			$catHolder = $('<div />', {
1232				"id": o.categoryHolderId,
1233				"html": catHtml
1234			}).appendTo($filterContainer);
1235
1236			$galleryContainer.prepend($filterContainer);
1237		}
1238		function abortPendingRequests() {
1239			if (currentXhr) {
1240				//there is a request pending, abort it and execute this one
1241				currentXhr.abort();
1242				if (currentItem) {
1243					removeItemLoading(currentItem.el);
1244				}
1245			}
1246		}
1247
1248		/*****************************************************************************************
1249		 * EVENT BINDING AND HANDLER FUNCTIONS
1250		 ****************************************************************************************/
1251
1252		eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('3 2A(25,k){4(25){4(k.G){6.G=k.G}4(k.H){6.H=k.H}4(k.13){6.13=k.13}2l(k);1o=g}v{2j(k);1y(6.d)}22()}3 2o(){u m;1V=$(12).7(),O=2p,L=10;4(!2q){1T.2r()}4(1a){m=$n.z();14(6);$l.b("1b",[{1Z:g}]).f({m:0},O,o.J);$n.b("V").r({7:\'11%\',1e:L}).f({m:(-m-L)},O,o.J,3(){$n.b("1n").1w();U=g});1a=D}v 4(1t){14(6,{2n:g});m=$n.z();$n.b("V");$l.r({m:(-m-L),1e:L}).f({m:0},O,o.J,3(){$n.b("1n").1w();U=g}).b("1b",[{1Z:g}]);1t=D}v{28();4(6.d){1y(6.d)}$(\'#1F\').V();18();$Y.f({1C:-1V-2k},1B,o.J,3(){$(B).f({z:\'V\'});$l.b("1b",[{}]);16()})}}3 2m(){1R($(B).a(\'.\'+o.1E),1)}3 2i(){4(!$(B).a(\'.\'+o.1p).C&&!1T.2s()){26($(B).a(\'.\'+o.1E),0)}}3 2t(){u M=$(B),q=1I(M.k(\'q\')),1k=o.2z.2B;1g();4(N!==q){N=q;2y(q);M.1q(o.1f).2x(\'.\'+o.1f).1x(o.1f);$1r.2u();4(q!==-1){1k=1s.a(o.2v,3(c){K 1I(c.2w)===q}).2C}$T.a("2f:2a").2b(1k);4($T.r("2c")!=="2e"){$T.b("1L")}}}3 2d(24){4(!S&&U){u 8="";U=D;S=g;$n=$l;$l=$(\'<1j />\',{"1J":o.2h});4(24){$l.2g($n);1a=g;8=6.G}v{$l.2K($n);1t=g;8=6.H}6={8:8,1Q:g};1M(6)}}3 33(){u M=$(B),1m=1i?0:10;4(!1h){1h=g;$T.34().f({m:1m,1e:1m});M.32(o.31);$1d.2Y(2Z,\'36\',3(){1h=D;1i=!1i})}}3 35(){1g();$1r.1q(o.1S);3b({3a:s.C,q:N})}3 37(5){5.d.1L(3(e){e.39();4(5.1Q){14(5)}1g();4(!1o&&!S){5.d.38(\'<1j 1J="\'+o.1p+\'"></1j>\');6=5;1M(5)}})}3 3c(){4(1Y){12.1U.21(P,P,30)}v{1D.29=\'\'}4(6&&6.d){6.d.a(\'1z\').b("1G")}18();1o=D;$I.r({z:"1c"});$(\'#1F\').2D();$Y.1N().f({1C:0,9:1},1B,o.J,3(){16();$l.b("1n").2J("2X","").2L()});4(2I){$2H.2E(\'2F\')}v{27();2G()}}3 22(){S=D;2M=P}3 18(){u W=$(12).7();$I.7(2*W);$l.r({7:W});$Y.7(W)}3 16(){$I.r({7:\'11%\'});$l.r({7:\'11%\'});$Y.r({7:\'11%\'})}3 2N(X){u t=0,R=0,1l=0,A,i,j,F,Q,w,h;t=19.17(X/o.Z);R=X-t*(o.Z-o.y);4(R>0){A=0;4(!(t===1&&o.Z/2>R)){t+=1}A=19.17(X/t)-o.y;1l=o.Z/A;1A(i=0,j=s.C;i<j;i+=1){F=s[i].F;Q=s[i].Q;w=A;h=0;4(F>1&&t>1){w=(A+o.y)*F-o.y}s[i].d.7(w).a("1z").7(w);s[i].d.7(w).a(".1W-1X").7(w);4(o.23!=="1c"){h=t===1?"1c":(19.17(o.23/1l)+o.y)*Q-o.y;s[i].d.z(h).a("1z").z(h);s[i].d.7(w).a(".1W-1X").z(h)}}}K A+o.y}3 2T(8){u 1u=P,i,j;1A(i=0,j=1v.C;i<j;i+=1){4(1v[i].8===8){1u=1v[i];20}}K 1u}3 2U(5){u p=[],x=-1,i,j=0,15={};4(N!==-1){p=1s.2V(1H,3(1K){K 1s.2S(1K.q,N)!==-1})}p=p.C?p:1H;j=p.C;1A(i=0;i<j;i+=1){4(p[i].8===5.8){x=i;20}}4(x!==-1){4(x+1<j){15.G=p[x+1].8}4(x!==0){15.H=p[x-1].8}}K 15}3 14(5,2R){4(1Y){1U.21({2O:5.8},5.2P,5.13)}v{1D.29=\'!\'+5.8}}3 2W(){4($(12).7()>2Q&&$1d){$1d.1N()}}3 1y($5){$5.a(\'.\'+o.1p).1w();$5.b("1G")}3 28(){$I.1x(o.1P);$1r.1x(o.1S)}3 27(){$I.1q(o.1P)}3 1R($E,9){9=9||1;$E.1O().f({9:1},3(){$E.f({9:9},0)})}3 26($E,9){$E.1O().f({9:9},3(){$E.f({9:9},0)})}',62,199,'|||function|if|item|currentItem|width|slug|opacity|find|trigger||el||animate|true|||len|data|previewWrapper|marginTop|previousWrapper||filtItems|cat|css|items|numColumns|var|else||itemIndex|itemMargin|height|newImgW|this|length|false|elem|col|nextItem|prevItem|wrapper|easing|return|marg|that|currentCat|sp|null|row|spaceLeft|inLoading|filterBtn|wrapperLoaded|hide|winWidth|containerWidth|galleryContainer|imageWidth||100|window|link|setUrl|res|resetWrappersSize|floor|setWrappersSize|Math|nextPending|sliderVisible|auto|catHolder|marginBottom|selectedClass|abortPendingRequests|filterInAnimation|filterDisplayed|div|catName|ratio|margin|destroy|previewMode|itemLoadingClass|addClass|moreBtn|_|prevPending|cachedItem|cachedItems|remove|removeClass|removeItemLoading|img|for|800|marginLeft|location|itemTextClass|footer|mou
1252seleave|itemsMap|Number|class|it|click|loadItemContent|show|stop|loadingClass|slider|elemFadeIn|btnLoadingClass|PEXETO|history|windowWidth|no|color|supportsHistory|staticDesc|break|replaceState|doOnAjaxComplete|imageHeight|next|loadSlider|elemFadeOut|addLoading|removeLoading|hash|first|html|display|doOnLoadNewItem|none|span|insertAfter|previewWrapperClass|doOnItemMouseLeave|loadLightbox|50|initItemSlider|doOnItemMouseEnter|replace|doOnSliderImgLoaded|600|isIE8|loadCufon|checkIfMobile|doOnCategoryClick|detach|categories|id|siblings|filterItems|texts|doOnContentLoaded|allText|name|fadeIn|masonry|reload|loadGallery|root|galleryLoaded|attr|insertBefore|empty|currentXhr|getImageWidthForScreen|state|title|490|options|indexOf|getCachedItem|getItemLinks|filter|setFilterVisibility|style|slideToggle|200|galleryUrl|openedClass|toggleClass|doOnFilterClick|parent|doOnMoreBtnClick|linear|bindItemClickHandler|append|preventDefault|offset|loadImages|doOnCloseClicked'.split('|'),0,{}))
1253
1254
1255		init();
1256	
1257	};
1258}(jQuery));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.