/*! * Cube Portfolio - Responsive jQuery Grid Plugin * * version: 3.7.0 (6 June, 2016) * require: jQuery v1.7+ * * Copyright 2013-2016, Mihai Buricea (http://scriptpie.com/cubeportfolio/live-preview/) * Licensed under CodeCanyon License (http://codecanyon.net/licenses) * */ !function(a,b,c,d){"use strict";function e(b,c,d){/*jshint validthis: true */ var f,g=this,h="cbp";if(a.data(b,"cubeportfolio"))throw new Error("cubeportfolio is already initialized. Destroy it before initialize again!"); // js element g.obj=b, // jquery element g.$obj=a(b), // attached this instance to obj a.data(g.obj,"cubeportfolio",g), // extend options g.options=a.extend({},a.fn.cubeportfolio.options,c,g.$obj.data("cbp-options")), // store the state of the animation used for filters g.isAnimating=!0, // default filter for plugin g.defaultFilter=g.options.defaultFilter, // registered events (observator & publisher pattern) g.registeredEvents=[], // queue for this plugin g.queue=[], // has wrapper g.addedWrapp=!1, // register callback function a.isFunction(d)&&g.registerEvent("initFinish",d,!0),f=g.$obj.children(),g.options.caption&&("expand"===g.options.caption||e["private"].modernBrowser||(g.options.caption="minimal"),h+=" cbp-caption-active cbp-caption-"+g.options.caption),g.$obj.addClass(h),(0===f.length||f.first().hasClass("cbp-item"))&&(g.wrapInner(g.obj,"cbp-wrapper"),g.addedWrapp=!0),g.$ul=g.$obj.children().addClass("cbp-wrapper"),g.wrapInner(g.obj,"cbp-wrapper-outer"),g.wrapper=g.$obj.children(".cbp-wrapper-outer"),g.blocks=g.$ul.children(".cbp-item"),g.blocksOn=g.blocks,g.wrapInner(g.blocks,"cbp-item-wrapper"),g.plugins=a.map(e.plugins,function(a){return a(g)}),g.triggerEvent("afterPlugins"),g.loadImages(g.$obj,g.display)}a.extend(e.prototype,{storeData:function(b,c){var d=this;c=c||0,b.each(function(b,e){var f=a(e),g=f.width(),h=f.height();f.data("cbp",{index:c+b,wrapper:f.children(".cbp-item-wrapper"),widthInitial:g,heightInitial:h,width:g,height:h,widthAndGap:g+d.options.gapVertical,heightAndGap:h+d.options.gapHorizontal,left:null,leftNew:null,top:null,topNew:null,pack:!1})})}, // http://bit.ly/pure-js-wrap wrapInner:function(a,b){var e,f,g;if(b=b||"",!(a.length&&a.length<1))for(a.length===d&&(a=[a]),f=a.length-1;f>=0;f--){for(e=a[f],g=c.createElement("div"),g.setAttribute("class",b);e.childNodes.length;)g.appendChild(e.childNodes[0]);e.appendChild(g)}},removeAttrImage:function(a){a.removeAttribute("width"),a.removeAttribute("height"),a.removeAttribute("style")},/** * Wait to load all images */ loadImages:function(b,c){var d=this; // wait a frame (Safari bug) requestAnimationFrame(function(){var e=b.find("img").map(function(b,c){ // don't wait for images that have a width & height defined if(c.hasAttribute("width")&&c.hasAttribute("height")){if(c.style.width=c.getAttribute("width")+"px",c.style.height=c.getAttribute("height")+"px",c.hasAttribute("data-cbp-src"))return null;if(null===d.checkSrc(c))d.removeAttrImage(c);else{var e=a("");e.on("load.cbp error.cbp",function(){a(this).off("load.cbp error.cbp"),d.removeAttrImage(c)}),c.srcset?(e.attr("sizes",c.sizes||"100vw"),e.attr("srcset",c.srcset)):e.attr("src",c.src)}return null}return d.checkSrc(c)}),f=e.length;return 0===f?void c.call(d):void a.each(e,function(b,e){var g=a("");g.on("load.cbp error.cbp",function(){a(this).off("load.cbp error.cbp"),f--,0===f&&c.call(d)}), // ie8 compatibility e.srcset?(g.attr("sizes",e.sizes),g.attr("srcset",e.srcset)):g.attr("src",e.src)})})},checkSrc:function(b){var c=b.srcset,e=b.src;if(""===e)return null;var f=a("");c?(f.attr("sizes",b.sizes||"100vw"),f.attr("srcset",c)):f.attr("src",e);var g=f[0];return g.complete&&g.naturalWidth!==d&&0!==g.naturalWidth?null:g},/** * Show the plugin */ display:function(){var a=this; // store main container width a.width=a.$obj.outerWidth(), // store to data values of t.blocks a.storeData(a.blocks),a.triggerEvent("initStartRead"),a.triggerEvent("initStartWrite"), // make layout a.layoutAndAdjustment(),a.triggerEvent("initEndRead"),a.triggerEvent("initEndWrite"), // plugin is ready to show and interact a.$obj.addClass("cbp-ready"),a.runQueue("delayFrame",a.delayFrame)},delayFrame:function(){var a=this;requestAnimationFrame(function(){a.resizeEvent(),a.triggerEvent("initFinish"), // animating is now false a.isAnimating=!1, // trigger public event initComplete a.$obj.trigger("initComplete.cbp")})},/** * Add resize event when browser width changes */ resizeEvent:function(){var a,b=this;e["private"].resize.initEvent({instance:b,fn:function(){var b=this; // used by wp fullWidth force option b.triggerEvent("beforeResizeGrid"),a=b.$obj.outerWidth(),b.width!==a&&("alignCenter"===b.options.gridAdjustment&&(b.wrapper[0].style.maxWidth=""),b.width=a,b.layoutAndAdjustment(),b.triggerEvent("resizeGrid")),b.triggerEvent("resizeWindow")}})},gridAdjust:function(){var b=this; // if responsive "responsive"===b.options.gridAdjustment?b.responsiveLayout():( // reset the style attribute for all blocks so I can read a new width & height // for the current grid width. This is usefull for the styles defined in css // to create a custom responsive system. // Note: reset height if it was set for addHeightToBlocks b.blocks.removeAttr("style"),b.blocks.each(function(c,d){var e=a(d).data("cbp"),f=d.getBoundingClientRect(),g=b.columnWidthTruncate(f.right-f.left),h=Math.round(f.bottom-f.top);e.height=h,e.heightAndGap=h+b.options.gapHorizontal,e.width=g,e.widthAndGap=g+b.options.gapVertical}),b.widthAvailable=b.width+b.options.gapVertical), // used by slider layoutMode b.triggerEvent("gridAdjust")},layoutAndAdjustment:function(){var a=this;a.gridAdjust(),a.layout()},/** * Build the layout */ layout:function(){var a=this;a.computeBlocks(a.filterConcat(a.defaultFilter)),"slider"===a.options.layoutMode?(a.sliderLayoutReset(),a.sliderLayout()):(a.mosaicLayoutReset(),a.mosaicLayout()), // positionate the blocks a.positionateItems(), // resize main container height a.resizeMainContainer()},computeFilter:function(a){var b=this;b.computeBlocks(a),b.mosaicLayoutReset(),b.mosaicLayout(), // filter call layout b.filterLayout()},/** * Default filter layout if nothing overrides */ filterLayout:function(){var b=this;b.blocksOff.addClass("cbp-item-off"),b.blocksOn.removeClass("cbp-item-off").each(function(b,c){var d=a(c).data("cbp");d.left=d.leftNew,d.top=d.topNew,c.style.left=d.left+"px",c.style.top=d.top+"px"}), // resize main container height b.resizeMainContainer(),b.filterFinish()},/** * Trigger when a filter is finished */ filterFinish:function(){var a=this; // if blocks are sorted (the index ascending is broken) revert // this state so the index is ascending again a.blocksAreSorted&&a.sortBlocks(a.blocks,"index"),a.isAnimating=!1,a.$obj.trigger("filterComplete.cbp"),a.triggerEvent("filterFinish")},computeBlocks:function(a){var b=this; // blocks that are visible before applying the filter b.blocksOnInitial=b.blocksOn, // blocks visible after applying the filter b.blocksOn=b.blocks.filter(a), // blocks off after applying the filter b.blocksOff=b.blocks.not(a),b.triggerEvent("computeBlocksFinish",a)},/** * Make this plugin responsive */ responsiveLayout:function(){var b=this; // calculate numbers of cols b.cols=b[a.isArray(b.options.mediaQueries)?"getColumnsBreakpoints":"getColumnsAuto"](),b.columnWidth=b.columnWidthTruncate((b.width+b.options.gapVertical)/b.cols),b.widthAvailable=b.columnWidth*b.cols,"mosaic"===b.options.layoutMode&&b.getMosaicWidthReference(),b.blocks.each(function(c,d){var// grid & slider layoutMode must be 1 e,f=a(d).data("cbp"),g=1;"mosaic"===b.options.layoutMode&&(g=b.getColsMosaic(f.widthInitial)),e=b.columnWidth*g-b.options.gapVertical,d.style.width=e+"px",f.width=e,f.widthAndGap=e+b.options.gapVertical,d.style.height=""});var c=[];b.blocks.each(function(b,d){var e=a(d),f=e.data("cbp").width;a.each(e.find("img").filter("[width][height]"),function(a,b){var d=parseInt(b.getAttribute("width"),10),e=parseInt(b.getAttribute("height"),10),g=parseFloat((d/e).toFixed(10));c.push({el:b,width:f,height:Math.round(f/g)})})}),a.each(c,function(a,b){b.el.width=b.width,b.el.height=b.height,b.el.style.width=b.width+"px",b.el.style.height=b.height+"px"}),b.blocks.each(function(c,d){var e=a(d).data("cbp"),f=d.getBoundingClientRect(),g=Math.round(f.bottom-f.top);e.height=g,e.heightAndGap=g+b.options.gapHorizontal})},getMosaicWidthReference:function(){var b=this,c=[];b.blocks.each(function(b,d){var e=a(d).data("cbp");c.push(e.widthInitial)}),c.sort(function(a,b){return a-b}),c[0]?b.mosaicWidthReference=c[0]:b.mosaicWidthReference=b.columnWidth},getColsMosaic:function(a){var b=this;if(a===b.width)return b.cols;var c=a/b.mosaicWidthReference;return c=c%1>=.79?Math.ceil(c):Math.floor(c),Math.min(Math.max(c,1),b.cols)},/** * Get numbers of columns when t.options.mediaQueries is not an array */ getColumnsAuto:function(){var a=this;if(0===a.blocks.length)return 1;var b=a.blocks.first().data("cbp").widthInitial+a.options.gapVertical;return Math.max(Math.round(a.width/b),1)},/** * Get numbers of columns if t.options.mediaQueries is an array */ getColumnsBreakpoints:function(){var b,c=this,e=c.width;return a.each(c.options.mediaQueries,function(a,c){return e>=c.width?(b=c.cols,!1):void 0}),b===d&&(b=c.options.mediaQueries[c.options.mediaQueries.length-1].cols),b},/** * Defines how the columns dimension & position (width, left) will be truncated * * If you use `Math.*` there could be some issues with the items on the right side * that can have some pixels hidden(1 or 2, depends on the number of columns) * but this is a known limitation. * * If you don't use the built-in captions effects (overlay at hover over an item) returning * the possibly floated values may be a solution for the pixels hidden on the right side. * * The column width must be an integer because browsers have some visual issues * with transform properties for caption effects. * * The initial behaviour was return Math.floor * */ columnWidthTruncate:function(a){return Math.floor(a)},positionateItems:function(){var b,c=this;c.blocksOn.removeClass("cbp-item-off").each(function(c,d){b=a(d).data("cbp"),b.left=b.leftNew,b.top=b.topNew,d.style.left=b.left+"px",d.style.top=b.top+"px"}),c.blocksOff.addClass("cbp-item-off"), // if blocks are sorted (the index ascending is broken) revert // this state so the index is ascending again c.blocksAreSorted&&c.sortBlocks(c.blocks,"index")},/** * Resize main container vertically */ resizeMainContainer:function(){var b,c=this,f=Math.max(c.freeSpaces.slice(-1)[0].topStart-c.options.gapHorizontal,0); // set container height for `overflow: hidden` to be applied // set max-width to center the grid if I need to // set container height for `overflow: hidden` to be applied // if resizeMainContainer is called for the first time skip this event trigger return"alignCenter"===c.options.gridAdjustment&&(b=0,c.blocksOn.each(function(c,d){var e=a(d).data("cbp"),f=e.left+e.width;f>b&&(b=f)}),c.wrapper[0].style.maxWidth=b+"px"),f===c.height?void c.triggerEvent("resizeMainContainer"):(c.obj.style.height=f+"px",c.height!==d&&(e["private"].modernBrowser?c.$obj.one(e["private"].transitionend,function(){c.$obj.trigger("pluginResize.cbp")}):c.$obj.trigger("pluginResize.cbp")),c.height=f,void c.triggerEvent("resizeMainContainer"))},filterConcat:function(a){return a.replace(/\|/gi,"")},pushQueue:function(a,b){var c=this;c.queue[a]=c.queue[a]||[],c.queue[a].push(b)},runQueue:function(b,c){var d=this,e=d.queue[b]||[];a.when.apply(a,e).then(a.proxy(c,d))},clearQueue:function(a){var b=this;b.queue[a]=[]},/** * Register event */ registerEvent:function(a,b,c){var d=this;d.registeredEvents[a]||(d.registeredEvents[a]=[]),d.registeredEvents[a].push({func:b,oneTime:c||!1})},/** * Trigger event */ triggerEvent:function(a,b){var c,d,e=this;if(e.registeredEvents[a])for(c=0,d=e.registeredEvents[a].length;d>c;c++)e.registeredEvents[a][c].func.call(e,b),e.registeredEvents[a][c].oneTime&&(e.registeredEvents[a].splice(c,1), // function splice change the t.registeredEvents[name] array // if event is one time you must set the i to the same value // next time and set the length lower c--,d--)},addItems:function(b,c,d){var f=this; // wrap .cbp-item-wrap div inside .cbp-item f.wrapInner(b,"cbp-item-wrapper"),f.$ul[d](b.addClass("cbp-item-loading").css({top:"100%",left:0})),e["private"].modernBrowser?b.last().one(e["private"].animationend,function(){f.addItemsFinish(b,c)}):f.addItemsFinish(b,c),f.loadImages(b,function(){if(f.$obj.addClass("cbp-updateItems"),"append"===d) // push to data values of items f.storeData(b,f.blocks.length),a.merge(f.blocks,b);else{ // push to data values of items f.storeData(b);var c=b.length;f.blocks.each(function(b,d){a(d).data("cbp").index=c+b}), // push the new items to t.blocks f.blocks=a.merge(b,f.blocks)}f.triggerEvent("addItemsToDOM",b),f.layoutAndAdjustment(), // if show count was actived, call show count function again f.elems&&e["public"].showCounter.call(f.obj,f.elems)})},addItemsFinish:function(b,c){var d=this;d.isAnimating=!1,d.$obj.removeClass("cbp-updateItems"),b.removeClass("cbp-item-loading"),a.isFunction(c)&&c.call(d,b)},removeItems:function(b,c){var d=this;d.$obj.addClass("cbp-updateItems"),e["private"].modernBrowser?b.last().one(e["private"].animationend,function(){d.removeItemsFinish(b,c)}):d.removeItemsFinish(b,c),b.each(function(b,c){d.blocks.each(function(b,f){if(c===f){var g=a(f); // remove element from blocks d.blocks.splice(b,1),e["private"].modernBrowser?(g.one(e["private"].animationend,function(){g.remove()}),g.addClass("cbp-removeItem")):g.remove()}})}),d.blocks.each(function(b,c){a(c).data("cbp").index=b}),d.layoutAndAdjustment(), // if show count was actived, call show count function again d.elems&&e["public"].showCounter.call(d.obj,d.elems)},removeItemsFinish:function(b,c){var d=this;d.isAnimating=!1,d.$obj.removeClass("cbp-updateItems"),a.isFunction(c)&&c.call(d,b)}}),/** * jQuery plugin initializer */ a.fn.cubeportfolio=function(a,b,c){return this.each(function(){if("object"==typeof a||!a)return e["public"].init.call(this,a,b);if(e["public"][a])return e["public"][a].call(this,b,c);throw new Error("Method "+a+" does not exist on jquery.cubeportfolio.js")})},e.plugins={},a.fn.cubeportfolio.constructor=e}(jQuery,window,document),function(a,b,c,d){"use strict";var e=a.fn.cubeportfolio.constructor;a.extend(e.prototype,{mosaicLayoutReset:function(){var b=this; // flag to be set after the blocks sorting is done b.blocksAreSorted=!1, // when I start layout all blocks must not be positionated b.blocksOn.each(function(b,c){a(c).data("cbp").pack=!1})},mosaicLayout:function(){var a,b=this,c=b.blocksOn.length,d={};for( // array of objects where I keep the spaces available in the grid b.freeSpaces=[{leftStart:0,leftEnd:b.widthAvailable,topStart:0,topEnd:Math.pow(2,18)}],a=0;c>a;a++){ // if space or block are null then start sorting if(d=b.getSpaceIndexAndBlock(),null===d) // sort blocks // after the sort is finished start the layout again return b.sortBlocksToPreventGaps(),void b.mosaicLayout();b.generateF1F2(d.spaceIndex,d.dataBlock),b.generateG1G2G3G4(d.dataBlock),b.cleanFreeSpaces(),b.addHeightToBlocks()} // sort the blocks from top to bottom to add properly displayAnimation and animationType b.blocksAreSorted&&b.sortBlocks(b.blocksOn,"topNew")},/** * Chose from freeSpaces the best space available * Find block by verifying if it can fit in bestSpace(top-left space available) * If block doesn't fit in the first space available & t.options.sortToPreventGaps * is set to true then sort the blocks and start the layout once again * Decide the free rectangle Fi from F to pack the rectangle R into. */ getSpaceIndexAndBlock:function(){var b=this,c=null;return a.each(b.freeSpaces,function(d,e){var f=e.leftEnd-e.leftStart,g=e.topEnd-e.topStart; // if first space don't have a block and sortToPreventGaps is true => return from loop // if first space don't have a block and sortToPreventGaps is true => return from loop // if space & block is founded => return from loop return b.blocksOn.each(function(b,h){var i=a(h).data("cbp");if(i.pack!==!0) // now the rectagle can be positioned return i.widthAndGap<=f&&i.heightAndGap<=g?(i.pack=!0,c={spaceIndex:d,dataBlock:i},i.leftNew=e.leftStart,i.topNew=e.topStart,!1):void 0}),!b.blocksAreSorted&&b.options.sortToPreventGaps&&d>0?(c=null,!1):null!==c?!1:void 0}),c},/** * Use the MAXRECTS split scheme to subdivide Fi(space) into F1 and F2 and * then remove that space from spaces * Insert F1 & F2 in F in place of Fi */ generateF1F2:function(a,b){var c=this,d=c.freeSpaces[a],e={leftStart:d.leftStart+b.widthAndGap,leftEnd:d.leftEnd,topStart:d.topStart,topEnd:d.topEnd},f={leftStart:d.leftStart,leftEnd:d.leftEnd,topStart:d.topStart+b.heightAndGap,topEnd:d.topEnd}; // remove Fi from F c.freeSpaces.splice(a,1),e.leftEnd>e.leftStart&&e.topEnd>e.topStart&&(c.freeSpaces.splice(a,0,e),a++),f.leftEnd>f.leftStart&&f.topEnd>f.topStart&&c.freeSpaces.splice(a,0,f)},/** * Generate G1, G2, G3, G4 from intersaction of t.freeSpaces with block */ generateG1G2G3G4:function(b){var c=this,d=[];a.each(c.freeSpaces,function(a,e){var f=c.intersectSpaces(e,b); // if block & space are the same push space in spaces and return // if block & space are the same push space in spaces and return return null===f?void d.push(e):(c.generateG1(e,f,d),c.generateG2(e,f,d),c.generateG3(e,f,d),void c.generateG4(e,f,d))}),c.freeSpaces=d},/** * Return the intersected rectagle of Fi and block * If the two spaces don't intersect or are the same return null */ intersectSpaces:function(a,b){var c={leftStart:b.leftNew,leftEnd:b.leftNew+b.widthAndGap,topStart:b.topNew,topEnd:b.topNew+b.heightAndGap};if(a.leftStart===c.leftStart&&a.leftEnd===c.leftEnd&&a.topStart===c.topStart&&a.topEnd===c.topEnd)return null;var d=Math.max(a.leftStart,c.leftStart),e=Math.min(a.leftEnd,c.leftEnd),f=Math.max(a.topStart,c.topStart),g=Math.min(a.topEnd,c.topEnd);return d>=e||f>=g?null:{leftStart:d,leftEnd:e,topStart:f,topEnd:g}},/** * The top subdivide space */ generateG1:function(a,b,c){a.topStart!==b.topStart&&c.push({leftStart:a.leftStart,leftEnd:a.leftEnd,topStart:a.topStart,topEnd:b.topStart})},/** * The right subdivide space */ generateG2:function(a,b,c){a.leftEnd!==b.leftEnd&&c.push({leftStart:b.leftEnd,leftEnd:a.leftEnd,topStart:a.topStart,topEnd:a.topEnd})},/** * The bottom subdivide space */ generateG3:function(a,b,c){a.topEnd!==b.topEnd&&c.push({leftStart:a.leftStart,leftEnd:a.leftEnd,topStart:b.topEnd,topEnd:a.topEnd})},/** * The left subdivide space */ generateG4:function(a,b,c){a.leftStart!==b.leftStart&&c.push({leftStart:a.leftStart,leftEnd:b.leftStart,topStart:a.topStart,topEnd:a.topEnd})},/** * For every Fi check if is another Fj so Fj contains Fi * @todo - refactor */ cleanFreeSpaces:function(){var a=this; // sort space from top to bottom and left to right a.freeSpaces.sort(function(a,b){return a.topStart>b.topStart?1:a.topStartb.leftStart?1:a.leftStarta;a++)c=e.freeSpaces[a],d=e.freeSpaces[a+1],d.topStart-c.topStart<=1&&(d.topStart=c.topStart)},/** * Remove spaces that are not maximal * If Fi contains Fj then remove Fj from F */ removeNonMaximalFreeSpaces:function(){var b=this;b.uniqueFreeSpaces(),b.freeSpaces=a.map(b.freeSpaces,function(c,d){return a.each(b.freeSpaces,function(a,b){return d!==a&&b.leftStart<=c.leftStart&&b.leftEnd>=c.leftEnd&&b.topStart<=c.topStart&&b.topEnd>=c.topEnd?(c=null,!1):void 0}),c})},/** * Remove duplicates spaces from freeSpaces */ uniqueFreeSpaces:function(){var b=this,c=[];a.each(b.freeSpaces,function(b,d){a.each(c,function(a,b){return b.leftStart===d.leftStart&&b.leftEnd===d.leftEnd&&b.topStart===d.topStart&&b.topEnd===d.topEnd?(d=null,!1):void 0}),null!==d&&c.push(d)}),b.freeSpaces=c},/** * If freeSpaces arrray has only one space and that space overlap the * height of the bottom blocks with 1px cut those blocks */ addHeightToBlocks:function(){var b=this;a.each(b.freeSpaces,function(c,d){b.blocksOn.each(function(c,e){var f=a(e).data("cbp");if(f.pack===!0&&b.intersectSpaces(d,f)){var g=d.topStart-f.topNew-f.heightAndGap;-1===g&&(e.style.height=f.height-1+"px")}})})},/** * Sort by the longer width first, followed by a comparison of the shorter height */ sortBlocksToPreventGaps:function(){var b=this;b.blocksAreSorted=!0, // sort based on timestamp attribute b.blocksOn.sort(function(b,c){var d=a(b).data("cbp"),e=a(c).data("cbp"); // order desc by width // order desc by width // order desc by height // order asc by index return d.widthAndGape.widthAndGap?-1:d.heightAndGape.heightAndGap?-1:d.index>e.index?1:d.indexf[c]?1:e[c]f.leftNew?1:e.leftNew