PageSourceSearch

https://diaszporaprojekt.org/assets/global/plugins/cubeportfolio/js/jquery.cubeportfolio.js

js diaszporaprojekt.org collected 2026-10-02 20:34:09 UTC 184,765 bytes, 5,660 lines download raw bytes

1/*!
2 * Cube Portfolio - Responsive jQuery Grid Plugin
3 *
4 * version: 3.5.2 (11 February, 2016)
5 * require: jQuery v1.7+
6 *
7 * Copyright 2013-2016, Mihai Buricea (http://scriptpie.com/cubeportfolio/live-preview/)
8 * Licensed under CodeCanyon License (http://codecanyon.net/licenses)
9 *
10 */
11
12(function($, window, document, undefined) {
13    'use strict';
14
15    function CubePortfolio(obj, options, callback) {
16        /*jshint validthis: true */
17        var t = this,
18            initialCls = 'cbp',
19            children;
20
21        if ($.data(obj, 'cubeportfolio')) {
22            throw new Error('cubeportfolio is already initialized. Destroy it before initialize again!');
23        }
24
25        // attached this instance to obj
26        $.data(obj, 'cubeportfolio', t);
27
28        // extend options
29        t.options = $.extend({}, $.fn.cubeportfolio.options, options);
30
31        // store the state of the animation used for filters
32        t.isAnimating = true;
33
34        // default filter for plugin
35        t.defaultFilter = t.options.defaultFilter;
36
37        // registered events (observator & publisher pattern)
38        t.registeredEvents = [];
39
40        // queue for this plugin
41        t.queue = [];
42
43        // has wrapper
44        t.addedWrapp = false;
45
46        // register callback function
47        if ($.isFunction(callback)) {
48            t.registerEvent('initFinish', callback, true);
49        }
50
51        // js element
52        t.obj = obj;
53
54        // jquery element
55        t.$obj = $(obj);
56
57        // when there are no .cbp-item
58        children = t.$obj.children();
59
60        // if caption is active
61        if (t.options.caption) {
62            if (t.options.caption !== 'expand' && !CubePortfolio.private.modernBrowser) {
63                t.options.caption = 'minimal';
64            }
65
66            // .cbp-caption-active is used only for css
67            // so it will not generate a big css from sass if a caption is set
68            initialCls += ' cbp-caption-active cbp-caption-' + t.options.caption;
69        }
70
71        t.$obj.addClass(initialCls);
72
73        if (children.length === 0 || children.first().hasClass('cbp-item')) {
74            t.wrapInner(t.obj, 'cbp-wrapper');
75            t.addedWrapp = true;
76        }
77
78        // jquery wrapper element
79        t.$ul = t.$obj.children().addClass('cbp-wrapper');
80
81        // wrap the $ul in a outside wrapper
82        t.wrapInner(t.obj, 'cbp-wrapper-outer');
83
84        t.wrapper = t.$obj.children('.cbp-wrapper-outer');
85
86        t.blocks = t.$ul.children('.cbp-item');
87        t.blocksOn = t.blocks;
88
89        // wrap .cbp-item-wrap div inside .cbp-item
90        t.wrapInner(t.blocks, 'cbp-item-wrapper');
91
92        // register and initialize plugins
93        t.plugins = $.map(CubePortfolio.plugins, function(pluginName) {
94            return pluginName(t);
95        });
96
97        // used by the filters plugin. @todo - remove from here and create proper API with position for plugins
98        t.triggerEvent('afterPlugins');
99
100        // wait to load all images and then go further
101        t.loadImages(t.$obj, t.display);
102    }
103
104
105    $.extend(CubePortfolio.prototype, {
106        storeData: function(blocks, indexStart) {
107            var t = this;
108
109            indexStart = indexStart || 0; // used by loadMore
110
111            blocks.each(function(index, el) {
112                var item = $(el),
113                    width = item.width(),
114                    height = item.height();
115
116                item.data('cbp', {
117                    index: indexStart + index, // used when I sort the items and I need them to revert that sorting
118                    wrapper: item.children('.cbp-item-wrapper'),
119
120                    widthInitial: width,
121                    heightInitial: height,
122
123                    width: width, // used by drag & drop wp @todo - maybe I will use widthAndGap
124                    height: height,
125
126                    widthAndGap: width + t.options.gapVertical,
127                    heightAndGap: height + t.options.gapHorizontal,
128
129                    left: null,
130                    leftNew: null,
131                    top: null,
132                    topNew: null,
133
134                    pack: false,
135                });
136            });
137        },
138
139
140        // http://bit.ly/pure-js-wrap
141        wrapInner: function(items, classAttr) {
142            var t = this,
143                item, i, div;
144
145            classAttr = classAttr || '';
146
147            if (items.length && items.length < 1) {
148                return; // there are no .cbp-item
149            } else if (items.length === undefined) {
150                items = [items];
151            }
152
153            for (i = items.length - 1; i >= 0; i--) {
154                item = items[i];
155
156                div = document.createElement('div');
157
158                div.setAttribute('class', classAttr);
159
160                while (item.childNodes.length) {
161                    div.appendChild(item.childNodes[0]);
162                }
163
164                item.appendChild(div);
165            }
166        },
167
168        removeAttrImage: function(img) {
169            img.removeAttribute('width');
170            img.removeAttribute('height');
171            img.removeAttribute('style');
172        },
173
174
175        /**
176         * Wait to load all images
177         */
178        loadImages: function(elems, callback) {
179            var t = this;
180
181            // wait a frame (Safari bug)
182            requestAnimationFrame(function() {
183                var src = elems.find('img').map(function(index, el) {
184                    // don't wait for images that have a width & height defined
185                    if (el.hasAttribute('width') && el.hasAttribute('height')) {
186                        el.style.width = el.getAttribute('width') + 'px';
187                        el.style.height = el.getAttribute('height') + 'px';
188
189                        if (el.hasAttribute('data-cbp-src')) {
190                            return null;
191                        }
192
193                        if (t.checkSrc(el.src) === null) {
194                            t.removeAttrImage(el);
195                        } else {
196                            $('<img>').on('load.cbp error.cbp', function() {
197                                t.removeAttrImage(el);
198                            }).attr('src', el.src); // for ie8
199                        }
200
201                        return null;
202                    } else {
203                        return t.checkSrc(el.src);
204                    }
205                });
206
207                var srcLength = src.length;
208
209                if (srcLength === 0) {
210                    callback.call(t);
211                    return;
212                }
213
214                $.each(src, function(i, el) {
215                    $('<img>').on('load.cbp error.cbp', function() {
216                        srcLength--;
217
218                        if (srcLength === 0) {
219                            callback.call(t);
220                        }
221                    }).attr('src', el); // for ie8
222                });
223            });
224        },
225
226
227        checkSrc: function(src) {
228            if (src === '') {
229                return null;
230            }
231
232            var img = new Image();
233            img.src = src;
234
235            if (img.complete && img.naturalWidth !== undefined && img.naturalWidth !== 0) {
236                return null;
237            }
238
239            return src;
240        },
241
242
243        /**
244         * Show the plugin
245         */
246        display: function() {
247            var t = this;
248
249            // store main container width
250            t.width = t.$obj.outerWidth();
251
252            // store to data values of t.blocks
253            t.storeData(t.blocks);
254
255            t.triggerEvent('initStartRead');
256            t.triggerEvent('initStartWrite');
257
258            // make layout
259            t.layoutAndAdjustment();
260
261            t.triggerEvent('initEndRead');
262            t.triggerEvent('initEndWrite');
263
264            // plugin is ready to show and interact
265            t.$obj.addClass('cbp-ready');
266
267            t.runQueue('delayFrame', t.delayFrame);
268        },
269
270
271        delayFrame: function() {
272            var t = this;
273
274            requestAnimationFrame(function() {
275                t.resizeEvent();
276
277                t.triggerEvent('initFinish');
278
279                // animating is now false
280                t.isAnimating = false;
281
282                // trigger public event initComplete
283                t.$obj.trigger('initComplete.cbp');
284            });
285        },
286
287
288        /**
289         * Add resize event when browser width changes
290         */
291        resizeEvent: function() {
292            var t = this,
293                gridWidth;
294
295            CubePortfolio.private.initResizeEvent({
296                instance: t,
297                fn: function() {
298                    var tt = this;
299
300                    // used by wp fullWidth force option
301                    tt.triggerEvent('beforeResizeGrid');
302
303                    gridWidth = tt.$obj.outerWidth();
304
305                    if (tt.width !== gridWidth) {
306
307                        if (tt.options.gridAdjustment === 'alignCenter') {
308                            tt.wrapper[0].style.maxWidth = '';
309                        }
310
311                        // update the current grid width
312                        tt.width = gridWidth;
313
314                        // reposition the blocks with gridAdjustment set to true
315                        tt.layoutAndAdjustment();
316
317                        tt.triggerEvent('resizeGrid');
318                    }
319
320                    tt.triggerEvent('resizeWindow');
321                }
322            });
323        },
324
325
326        gridAdjust: function() {
327            var t = this;
328
329            // if responsive
330            if (t.options.gridAdjustment === 'responsive') {
331                t.responsiveLayout();
332            } else {
333                // reset the style attribute for all blocks so I can read a new width & height
334                // for the current grid width. This is usefull for the styles defined in css
335                // to create a custom responsive system.
336                // Note: reset height if it was set for addHeightToBlocks
337                t.blocks.removeAttr('style');
338
339                t.blocks.each(function(index, el) {
340                    var data = $(el).data('cbp'),
341                        bound = el.getBoundingClientRect(),
342                        width = t.columnWidthTruncate(bound.right - bound.left),
343                        height = Math.round(bound.bottom - bound.top);
344
345                    data.height = height;
346                    data.heightAndGap = height + t.options.gapHorizontal;
347
348                    data.width = width;
349                    data.widthAndGap = width + t.options.gapVertical;
350                });
351
352                t.widthAvailable = t.width + t.options.gapVertical;
353            }
354
355            // used by slider layoutMode
356            t.triggerEvent('gridAdjust');
357        },
358
359
360        layoutAndAdjustment: function() {
361            var t = this;
362
363            t.gridAdjust();
364
365            t.layout();
366        },
367
368
369        /**
370         * Build the layout
371         */
372        layout: function() {
373            var t = this;
374
375            t.computeBlocks(t.filterConcat(t.defaultFilter));
376
377            if (t.options.layoutMode === 'slider') {
378                t.sliderLayoutReset();
379                t.sliderLayout();
380            } else {
381                t.mosaicLayoutReset();
382                t.mosaicLayout();
383            }
384
385
386            // positionate the blocks
387            t.positionateItems();
388
389            // resize main container height
390            t.resizeMainContainer();
391        },
392
393
394        computeFilter: function(expression) {
395            var t = this;
396
397            t.computeBlocks(expression);
398
399            t.mosaicLayoutReset();
400            t.mosaicLayout();
401
402            // filter call layout
403            t.filterLayout();
404        },
405
406
407        /**
408         *  Default filter layout if nothing overrides
409         */
410        filterLayout: function() {
411            var t = this;
412
413            t.blocksOff.addClass('cbp-item-off');
414
415            t.blocksOn.removeClass('cbp-item-off')
416                .each(function(index, el) {
417                    var data = $(el).data('cbp');
418
419                    data.left = data.leftNew;
420                    data.top = data.topNew;
421
422                    el.style.left = data.left + 'px';
423                    el.style.top = data.top + 'px';
424                });
425
426            // resize main container height
427            t.resizeMainContainer();
428
429            t.filterFinish();
430        },
431
432
433        /**
434         *  Trigger when a filter is finished
435         */
436        filterFinish: function() {
437            var t = this;
438
439            // if blocks are sorted (the index ascending is broken) revert
440            // this state so the index is ascending again
441            if (t.blocksAreSorted) {
442                t.sortBlocks(t.blocks, 'index');
443            }
444
445            t.isAnimating = false;
446
447            t.$obj.trigger('filterComplete.cbp');
448            t.triggerEvent('filterFinish');
449        },
450
451
452        computeBlocks: function(expression) {
453            var t = this;
454
455            // blocks that are visible before applying the filter
456            t.blocksOnInitial = t.blocksOn;
457
458            // blocks visible after applying the filter
459            t.blocksOn = t.blocks.filter(expression);
460
461            // blocks off after applying the filter
462            t.blocksOff = t.blocks.not(expression);
463
464            t.triggerEvent('computeBlocksFinish', expression);
465        },
466
467
468        /**
469         * Make this plugin responsive
470         */
471        responsiveLayout: function() {
472            var t = this;
473
474            // calculate numbers of cols
475            t.cols = t[($.isArray(t.options.mediaQueries) ? 'getColumnsBreakpoints' : 'getColumnsAuto')]();
476
477            t.columnWidth = t.columnWidthTruncate((t.width + t.options.gapVertical) / t.cols);
478
479            t.widthAvailable = t.columnWidth * t.cols;
480
481            if (t.options.layoutMode === 'mosaic') {
482                t.getMosaicWidthReference();
483            }
484
485            t.blocks.each(function(index, el) {
486                var data = $(el).data('cbp'),
487                    cols = 1, // grid & slider layoutMode must be 1
488                    width;
489
490                if (t.options.layoutMode === 'mosaic') {
491                    cols = t.getColsMosaic(data.widthInitial);
492                }
493
494                width = t.columnWidth * cols - t.options.gapVertical;
495
496                el.style.width = width + 'px';
497                data.width = width;
498                data.widthAndGap = width + t.options.gapVertical;
499
500                // reset height if it was set for addHeightToBlocks
501                el.style.height = '';
502            });
503
504            var imgs = [];
505
506            t.blocks.each(function(index, el) {
507                var block = $(el),
508                    width = block.data('cbp').width;
509
510                $.each(block.find('img').filter('[width][height]'), function(index, el) {
511                    var procent = width / parseInt(el.getAttribute('width'), 10);
512
513                    imgs.push({
514                        el: el,
515                        width: width,
516                        height: Math.floor(parseInt(el.getAttribute('height'), 10) * procent),
517                    });
518                });
519            });
520
521            $.each(imgs, function(index, item) {
522                 item.el.width = item.width;
523                 item.el.height = item.height;
524                 item.el.style.width = item.width + 'px';
525                 item.el.style.height = item.height + 'px';
526            });
527
528            t.blocks.each(function(index, el) {
529                var data = $(el).data('cbp'),
530                    bound = el.getBoundingClientRect(),
531                    height = Math.round(bound.bottom - bound.top);
532
533                data.height = height;
534                data.heightAndGap = height + t.options.gapHorizontal;
535            });
536        },
537
538
539        getMosaicWidthReference: function() {
540            var t = this,
541                arrWidth = [];
542
543            t.blocks.each(function(index, el) {
544                var data = $(el).data('cbp');
545                arrWidth.push(data.widthInitial);
546            });
547
548            arrWidth.sort(function(a, b) {
549                return a - b;
550            });
551
552            if (arrWidth[0]) {
553                t.mosaicWidthReference = arrWidth[0];
554            } else {
555                t.mosaicWidthReference = t.columnWidth;
556            }
557        },
558
559
560        getColsMosaic: function(widthInitial) {
561            var t = this;
562
563            if (widthInitial === t.width) {
564                return t.cols;
565            }
566
567            var ratio = widthInitial / t.mosaicWidthReference;
568
569            if (ratio % 1 >= 0.79) {
570                ratio = Math.ceil(ratio);
571            } else {
572                ratio = Math.floor(ratio);
573            }
574
575            return Math.min(Math.max(ratio, 1), t.cols);
576        },
577
578
579        /**
580         * Get numbers of columns when t.options.mediaQueries is not an array
581         */
582        getColumnsAuto: function() {
583            var t = this;
584
585            if (t.blocks.length === 0) {
586                return 1;
587            }
588
589            var columnWidth = t.blocks.first().data('cbp').widthInitial + t.options.gapVertical;
590
591            return Math.max(Math.round(t.width / columnWidth), 1);
592        },
593
594
595        /**
596         * Get numbers of columns if t.options.mediaQueries is an array
597         */
598        getColumnsBreakpoints: function() {
599            var t = this,
600                gridWidth = t.width,
601                columns;
602
603            $.each(t.options.mediaQueries, function(index, val) {
604                if (gridWidth >= val.width) {
605                    columns = val.cols;
606                    return false;
607                }
608            });
609
610            if (columns === undefined) {
611                columns = t.options.mediaQueries[t.options.mediaQueries.length - 1].cols;
612            }
613
614            return columns;
615        },
616
617
618        /**
619         *  Defines how the columns dimension & position (width, left) will be truncated
620         *
621         *  If you use `Math.*` there could be some issues with the items on the right side
622         *  that can have some pixels hidden(1 or 2, depends on the number of columns)
623         *  but this is a known limitation.
624         *
625         *  If you don't use the built-in captions effects (overlay at hover over an item) returning
626         *  the possibly floated values may be a solution for the pixels hidden on the right side.
627         *
628         *  The column width must be an integer because browsers have some visual issues
629         *  with transform properties for caption effects.
630         *
631         *  The initial behaviour was return Math.floor
632         *
633         */
634        columnWidthTruncate: function(value) {
635            return Math.floor(value);
636        },
637
638
639        positionateItems: function() {
640            var t = this,
641                data;
642
643            t.blocksOn.removeClass('cbp-item-off')
644                .each(function(index, el) {
645                    data = $(el).data('cbp');
646
647                    data.left = data.leftNew;
648                    data.top = data.topNew;
649
650                    el.style.left = data.left + 'px';
651                    el.style.top = data.top + 'px';
652                });
653
654            t.blocksOff.addClass('cbp-item-off');
655
656            // if blocks are sorted (the index ascending is broken) revert
657            // this state so the index is ascending again
658            if (t.blocksAreSorted) {
659                t.sortBlocks(t.blocks, 'index');
660            }
661        },
662
663
664        /**
665         * Resize main container vertically
666         */
667        resizeMainContainer: function() {
668            var t = this,
669                height = Math.max(t.freeSpaces.slice(-1)[0].topStart - t.options.gapHorizontal, 0),
670                maxWidth;
671
672            // set max-width to center the grid if I need to
673            if (t.options.gridAdjustment === 'alignCenter') {
674                maxWidth = 0;
675
676                t.blocksOn.each(function(index, el) {
677                    var data = $(el).data('cbp'),
678                        rightEdge = data.left + data.width;
679
680                    if (rightEdge > maxWidth) {
681                        maxWidth = rightEdge;
682                    }
683                });
684
685                t.wrapper[0].style.maxWidth = maxWidth + 'px';
686            }
687
688            // set container height for `overflow: hidden` to be applied
689            if (height === t.height) {
690                t.triggerEvent('resizeMainContainer');
691                return;
692            }
693
694            t.obj.style.height = height + 'px';
695
696            // if resizeMainContainer is called for the first time skip this event trigger
697            if (t.height !== undefined) {
698                if (CubePortfolio.private.modernBrowser) {
699                    t.$obj.one(CubePortfolio.private.transitionend, function() {
700                        t.$obj.trigger('pluginResize.cbp');
701                    });
702                } else {
703                    t.$obj.trigger('pluginResize.cbp');
704                }
705            }
706
707            t.height = height;
708
709            t.triggerEvent('resizeMainContainer');
710        },
711
712
713        filterConcat: function(filter) {
714            return filter.replace(/\|/gi, '');
715        },
716
717
718        pushQueue: function(name, deferred) {
719            var t = this;
720
721            t.queue[name] = t.queue[name] || [];
722            t.queue[name].push(deferred);
723        },
724
725
726        runQueue: function(name, fn) {
727            var t = this,
728                queue = t.queue[name] || [];
729
730            $.when.apply($, queue).then($.proxy(fn, t));
731        },
732
733
734        clearQueue: function(name) {
735            var t = this;
736
737            t.queue[name] = [];
738        },
739
740
741        /**
742         *  Register event
743         */
744        registerEvent: function(name, callbackFunction, oneTime) {
745            var t = this;
746
747            if (!t.registeredEvents[name]) {
748                t.registeredEvents[name] = [];
749            }
750
751            t.registeredEvents[name].push({
752                func: callbackFunction,
753                oneTime: oneTime || false
754            });
755        },
756
757
758        /**
759         *  Trigger event
760         */
761        triggerEvent: function(name, param) {
762            var t = this,
763                i, len;
764
765            if (t.registeredEvents[name]) {
766                for (i = 0, len = t.registeredEvents[name].length; i < len; i++) {
767                    t.registeredEvents[name][i].func.call(t, param);
768
769                    if (t.registeredEvents[name][i].oneTime) {
770                        t.registeredEvents[name].splice(i, 1);
771                        // function splice change the t.registeredEvents[name] array
772                        // if event is one time you must set the i to the same value
773                        // next time and set the length lower
774                        i--;
775                        len--;
776                    }
777                }
778            }
779        },
780
781
782        addItems: function(items, callback) {
783            var t = this;
784
785            // wrap .cbp-item-wrap div inside .cbp-item
786            t.wrapInner(items, 'cbp-item-wrapper');
787
788            items.addClass('cbp-item-loading').css({
789                top: '100%',
790                left: 0
791            }).appendTo(t.$ul);
792
793            if (CubePortfolio.private.modernBrowser) {
794                items.last().one(CubePortfolio.private.animationend, function() {
795                    t.addItemsFinish(items, callback);
796                });
797            } else {
798                t.addItemsFinish(items, callback); // @todo - on ie8 & ie9 callback trigger to early
799            }
800
801            t.loadImages(items, function() {
802                t.$obj.addClass('cbp-addItems');
803
804                // push to data values of items
805                t.storeData(items, t.blocks.length);
806
807                // push the new items to t.blocks
808                $.merge(t.blocks, items);
809
810                t.triggerEvent('addItemsToDOM', items);
811
812                t.layoutAndAdjustment();
813
814                // if show count was actived, call show count function again
815                if (t.elems) {
816                    CubePortfolio.public.showCounter.call(t.obj, t.elems);
817                }
818
819                t.triggerEvent('appendItemsFinish');
820            });
821        },
822
823
824        addItemsFinish: function(items, callback) {
825            var t = this;
826
827            t.isAnimating = false;
828
829            t.$obj.removeClass('cbp-addItems');
830            items.removeClass('cbp-item-loading');
831
832            if ($.isFunction(callback)) {
833                callback.call(t, items);
834            }
835        }
836    });
837
838
839    /**
840     * jQuery plugin initializer
841     */
842    $.fn.cubeportfolio = function(method, options, callback) {
843        return this.each(function() {
844            if (typeof method === 'object' || !method) {
845                return CubePortfolio.public.init.call(this, method, options);
846            } else if (CubePortfolio.public[method]) {
847                return CubePortfolio.public[method].call(this, options, callback);
848            }
849
850            throw new Error('Method ' + method + ' does not exist on jquery.cubeportfolio.js');
851        });
852    };
853
854    CubePortfolio.plugins = {};
855    $.fn.cubeportfolio.constructor = CubePortfolio;
856})(jQuery, window, document);
857
858(function($, window, document, undefined) {
859    'use strict';
860
861    var CubePortfolio = $.fn.cubeportfolio.constructor;
862
863    $.extend(CubePortfolio.prototype, {
864        mosaicLayoutReset: function() {
865            var t = this;
866
867            // flag to be set after the blocks sorting is done
868            t.blocksAreSorted = false;
869
870            // when I start layout all blocks must not be positionated
871            t.blocksOn.each(function(index, el) {
872                $(el).data('cbp').pack = false;
873            });
874        },
875
876
877        mosaicLayout: function() {
878            var t = this,
879                blocksLen = t.blocksOn.length,
880                i, spaceIndexAndBlock = {},
881                leftEnd;
882
883            // array of objects where I keep the spaces available in the grid
884            t.freeSpaces = [{
885                leftStart: 0,
886                leftEnd: t.widthAvailable,
887                topStart: 0,
888                topEnd: Math.pow(2, 18) // @todo - optimize
889            }];
890
891            for (i = 0; i < blocksLen; i++) {
892                spaceIndexAndBlock = t.getSpaceIndexAndBlock();
893
894                // if space or block are null then the sorting must be done
895                if (spaceIndexAndBlock === null) {
896                    // sort blocks
897                    t.sortBlocksToPreventGaps();
898
899                    // after the sort is done start the layout again
900                    t.mosaicLayout();
901
902                    return;
903                }
904
905                t.generateF1F2(spaceIndexAndBlock.spaceIndex, spaceIndexAndBlock.dataBlock);
906
907                t.generateG1G2G3G4(spaceIndexAndBlock.dataBlock);
908
909                t.cleanFreeSpaces();
910
911                t.addHeightToBlocks();
912            }
913
914            // sort the blocks from top to bottom to add properly displayAnimation and animationType
915            if (t.blocksAreSorted) {
916                t.sortBlocks(t.blocksOn, 'topNew');
917            }
918        },
919
920
921        /**
922         * Chose from freeSpaces the best space available
923         * Find block by verifying if it can fit in bestSpace(top-left space available)
924         * If block don't fit in the first space available & t.options.sortToPreventGaps
925         * is set to true then sort the blocks and start the layout once again
926         * Decide the free rectangle Fi from F to pack the rectangle R into.
927         */
928        getSpaceIndexAndBlock: function() {
929            var t = this,
930                spaceIndexAndBlock = null;
931
932            $.each(t.freeSpaces, function(index1, space) {
933                var widthSpace = space.leftEnd - space.leftStart,
934                    heightSpace = space.topEnd - space.topStart;
935
936                t.blocksOn.each(function(index2, block) {
937                    var data = $(block).data('cbp');
938
939                    if (data.pack === true) {
940                        return;
941                    }
942
943                    if (data.widthAndGap <= widthSpace && data.heightAndGap <= heightSpace) {
944                        // now the rectagle can be positioned
945                        data.pack = true;
946
947                        spaceIndexAndBlock = {
948                            spaceIndex: index1,
949                            dataBlock: data
950                        };
951
952                        data.leftNew = space.leftStart;
953                        data.topNew = space.topStart;
954
955                        // if the block is founded => return from this loop
956                        return false;
957                    }
958                });
959
960                // if first space don't have a block and sortToPreventGaps is true => return from loop
961                if (!t.blocksAreSorted && t.options.sortToPreventGaps && index1 > 0) {
962                    spaceIndexAndBlock = null;
963
964                    return false;
965                }
966
967                // if space & block is founded => return from loop
968                if (spaceIndexAndBlock !== null) {
969                    return false;
970                }
971            });
972
973            return spaceIndexAndBlock;
974        },
975
976
977        /**
978         * Use the MAXRECTS split scheme to subdivide Fi(space) into F1 and F2 and
979         * then remove that space from spaces
980         * Insert F1 & F2 in F in place of Fi
981         */
982        generateF1F2: function(spaceIndex, block) {
983            var t = this,
984                space = t.freeSpaces[spaceIndex];
985
986            var F1 = {
987                leftStart: space.leftStart + block.widthAndGap,
988                leftEnd: space.leftEnd,
989                topStart: space.topStart,
990                topEnd: space.topEnd
991            };
992
993            var F2 = {
994                leftStart: space.leftStart,
995                leftEnd: space.leftEnd,
996                topStart: space.topStart + block.heightAndGap,
997                topEnd: space.topEnd
998            };
999
1000            // remove Fi from F
1001            t.freeSpaces.splice(spaceIndex, 1);
1002
1003            if (F1.leftEnd > F1.leftStart && F1.topEnd > F1.topStart) {
1004                t.freeSpaces.splice(spaceIndex, 0, F1);
1005                spaceIndex++;
1006            }
1007
1008            if (F2.leftEnd > F2.leftStart && F2.topEnd > F2.topStart) {
1009                t.freeSpaces.splice(spaceIndex, 0, F2);
1010            }
1011        },
1012
1013
1014        /**
1015         * Generate G1, G2, G3, G4 from intersaction of t.freeSpaces with block
1016         */
1017        generateG1G2G3G4: function(block) {
1018            var t = this;
1019
1020            var spaces = [];
1021
1022            $.each(t.freeSpaces, function(index, space) {
1023                var intersectSpace = t.intersectSpaces(space, block);
1024
1025                // if block & space are the same push space in spaces and return
1026                if (intersectSpace === null) {
1027                    spaces.push(space);
1028                    return;
1029                }
1030
1031                t.generateG1(space, intersectSpace, spaces);
1032                t.generateG2(space, intersectSpace, spaces);
1033                t.generateG3(space, intersectSpace, spaces);
1034                t.generateG4(space, intersectSpace, spaces);
1035            });
1036
1037            t.freeSpaces = spaces;
1038        },
1039
1040
1041        /**
1042         * Return the intersected rectagle of Fi and block
1043         * If the two spaces don't intersect or are the same return null
1044         */
1045        intersectSpaces: function(space1, block) {
1046            var t = this,
1047                space2 = {
1048                    leftStart: block.leftNew,
1049                    leftEnd: block.leftNew + block.widthAndGap,
1050                    topStart: block.topNew,
1051                    topEnd: block.topNew + block.heightAndGap,
1052                };
1053
1054            if (space1.leftStart === space2.leftStart &&
1055                space1.leftEnd === space2.leftEnd &&
1056                space1.topStart === space2.topStart &&
1057                space1.topEnd === space2.topEnd) {
1058                return null;
1059            }
1060
1061            var leftStart = Math.max(space1.leftStart, space2.leftStart),
1062                leftEnd = Math.min(space1.leftEnd, space2.leftEnd),
1063                topStart = Math.max(space1.topStart, space2.topStart),
1064                topEnd = Math.min(space1.topEnd, space2.topEnd);
1065
1066            if (leftEnd <= leftStart || topEnd <= topStart) {
1067                return null;
1068            }
1069
1070            return {
1071                leftStart: leftStart,
1072                leftEnd: leftEnd,
1073                topStart: topStart,
1074                topEnd: topEnd
1075            };
1076        },
1077
1078
1079        /**
1080         * The top subdivide space
1081         */
1082        generateG1: function(space, intersectSpace, spaces) {
1083            if (space.topStart === intersectSpace.topStart) {
1084                return;
1085            }
1086
1087            spaces.push({
1088                leftStart: space.leftStart,
1089                leftEnd: space.leftEnd,
1090                topStart: space.topStart,
1091                topEnd: intersectSpace.topStart
1092            });
1093        },
1094
1095
1096        /**
1097         * The right subdivide space
1098         */
1099        generateG2: function(space, intersectSpace, spaces) {
1100            if (space.leftEnd === intersectSpace.leftEnd) {
1101                return;
1102            }
1103
1104            spaces.push({
1105                leftStart: intersectSpace.leftEnd,
1106                leftEnd: space.leftEnd,
1107                topStart: space.topStart,
1108                topEnd: space.topEnd
1109            });
1110        },
1111
1112
1113        /**
1114         * The bottom subdivide space
1115         */
1116        generateG3: function(space, intersectSpace, spaces) {
1117            if (space.topEnd === intersectSpace.topEnd) {
1118                return;
1119            }
1120
1121            spaces.push({
1122                leftStart: space.leftStart,
1123                leftEnd: space.leftEnd,
1124                topStart: intersectSpace.topEnd,
1125                topEnd: space.topEnd
1126            });
1127        },
1128
1129
1130        /**
1131         * The left subdivide space
1132         */
1133        generateG4: function(space, intersectSpace, spaces) {
1134            if (space.leftStart === intersectSpace.leftStart) {
1135                return;
1136            }
1137
1138            spaces.push({
1139                leftStart: space.leftStart,
1140                leftEnd: intersectSpace.leftStart,
1141                topStart: space.topStart,
1142                topEnd: space.topEnd
1143            });
1144        },
1145
1146
1147        /**
1148         * For every Fi check if is another Fj so Fj contains Fi
1149         * @todo - refactor
1150         */
1151        cleanFreeSpaces: function() {
1152            var t = this;
1153
1154            // sort space from top to bottom and left to right
1155            t.freeSpaces.sort(function(space1, space2) {
1156                if (space1.topStart > space2.topStart) {
1157                    return 1;
1158                } else if (space1.topStart < space2.topStart) {
1159                    return -1;
1160                } else {
1161                    if (space1.leftStart > space2.leftStart) {
1162                        return 1;
1163                    }
1163 else if (space1.leftStart < space2.leftStart) {
1164                        return -1;
1165                    } else {
1166                        return 0;
1167                    }
1168                }
1169            });
1170
1171            t.correctSubPixelValues();
1172
1173            t.removeNonMaximalFreeSpaces();
1174        },
1175
1176
1177        /**
1178         * If topStart values for spaces are <= 1px then align those spaces
1179         */
1180        correctSubPixelValues: function() {
1181            var t = this,
1182                i, len, diff, space1, space2;
1183
1184            for (i = 0, len = t.freeSpaces.length - 1; i < len; i++) {
1185                space1 = t.freeSpaces[i];
1186                space2 = t.freeSpaces[i + 1];
1187
1188                if ((space2.topStart - space1.topStart) <= 1) {
1189                    space2.topStart = space1.topStart;
1190                }
1191            }
1192        },
1193
1194
1195        /**
1196         * Remove spaces that are not maximal
1197         * If Fi contains Fj then remove Fj from F
1198         */
1199        removeNonMaximalFreeSpaces: function() {
1200            var t = this;
1201
1202            t.uniqueFreeSpaces();
1203
1204            t.freeSpaces = $.map(t.freeSpaces, function(space1, index1) {
1205                $.each(t.freeSpaces, function(index2, space2) {
1206                    // don't compare the same free spaces
1207                    if (index1 === index2) {
1208                        return;
1209                    }
1210
1211                    if (space2.leftStart <= space1.leftStart &&
1212                        space2.leftEnd >= space1.leftEnd &&
1213                        space2.topStart <= space1.topStart &&
1214                        space2.topEnd >= space1.topEnd) {
1215
1216                        space1 = null;
1217                        return false;
1218                    }
1219                });
1220
1221                return space1;
1222            });
1223        },
1224
1225
1226        /**
1227         * Remove duplicates spaces from freeSpaces
1228         */
1229        uniqueFreeSpaces: function() {
1230            var t = this,
1231                result = [];
1232
1233            $.each(t.freeSpaces, function(index1, space1) {
1234                $.each(result, function(index2, space2) {
1235                    if (space2.leftStart === space1.leftStart &&
1236                        space2.leftEnd === space1.leftEnd &&
1237                        space2.topStart === space1.topStart &&
1238                        space2.topEnd === space1.topEnd) {
1239
1240                        space1 = null;
1241                        return false;
1242                    }
1243                });
1244
1245                if (space1 !== null) {
1246                    result.push(space1);
1247                }
1248            });
1249
1250            t.freeSpaces = result;
1251        },
1252
1253
1254        /**
1255         * If freeSpaces have only one space and that space overlap the
1256         * height of the bottom blocks with 1px cut those blocks
1257         */
1258        addHeightToBlocks: function() {
1259            var t = this;
1260
1261            if (t.freeSpaces.length > 1) {
1262                return;
1263            }
1264
1265            var topStart = t.freeSpaces[0].topStart;
1266
1267            t.blocksOn.each(function(index, block) {
1268                var data = $(block).data('cbp');
1269
1270                if (data.pack !== true) {
1271                    return;
1272                }
1273
1274                var diff = topStart - data.topNew - data.heightAndGap;
1275
1276                if (diff < 0) {
1277                    block.style.height = (data.height + diff) + 'px';
1278                }
1279            });
1280        },
1281
1282
1283        /**
1284         * Sort by the longer width first, followed by a comparison of the shorter height
1285         */
1286        sortBlocksToPreventGaps: function() {
1287            var t = this;
1288
1289            t.blocksAreSorted = true;
1290
1291            // sort based on timestamp attribute
1292            t.blocksOn.sort(function(block1, block2) {
1293                var data1 = $(block1).data('cbp'),
1294                    data2 = $(block2).data('cbp');
1295
1296                // order desc by width
1297                if (data1.widthAndGap < data2.widthAndGap) {
1298                    return 1;
1299                } else if (data1.widthAndGap >
1299 data2.widthAndGap) {
1300                    return -1;
1301                } else {
1302                    // order desc by height
1303                    if (data1.heightAndGap < data2.heightAndGap) {
1304                        return 1;
1305                    } else if (data1.heightAndGap > data2.heightAndGap) {
1306                        return -1;
1307                    } else {
1308                        // order asc by index
1309                        if (data1.index > data2.index) {
1310                            return 1;
1311                        } else if (data1.index < data2.index) {
1312                            return -1;
1313                        }
1314                    }
1315                }
1316            });
1317
1318            // when I start the layout again all blocks must not be positionated
1319            // reset height if it was set for addHeightToBlocks
1320            t.blocksOn.each(function(index, el) {
1321                $(el).data('cbp').pack = false;
1322                el.style.height = '';
1323            });
1324        },
1325
1326
1327        /**
1328         * Generic sort block function from lower to highest values
1329         */
1330        sortBlocks: function(blocks, compare) {
1331            var t = this;
1332
1333            blocks.sort(function(block1, block2) {
1334                var data1 = $(block1).data('cbp'),
1335                    data2 = $(block2).data('cbp');
1336
1337                // if the items are equally order them from left to right
1338                if (data1[compare] > data2[compare]) {
1339                    return 1;
1340                } else if (data1[compare] < data2[compare]) {
1341                    return -1;
1342                } else {
1343                    if (data1.leftNew > data2.leftNew) {
1344                        return 1;
1345                    } else if (data1.leftNew < data2.leftNew) {
1346                        return -1;
1347                    } else {
1348                        return 0;
1349                    }
1350                }
1351            });
1352        }
1353    });
1354})(jQuery, window, document);
1355
1356// Plugin default options
1357jQuery.fn.cubeportfolio.options = {
1358    /**
1359     *  Define the wrapper for filters
1360     *  Values: strings that represent the elements in the document (DOM selector).
1361     */
1362    filters: '',
1363
1364    /**
1365     *  Define the wrapper for loadMore
1366     *  Values: strings that represent the elements in the document (DOM selector).
1367     */
1368    loadMore: '',
1369
1370    /**
1371     *  How the loadMore functionality should behave. Load on click on the button or
1372     *  automatically when you scroll the page
1373     *  Values: - click
1374     *          - auto
1375     */
1376    loadMoreAction: 'click',
1377
1378    /**
1379     *  Define the search input element
1380     *  Values: strings that represent the element in the document (DOM selector).
1381     */
1382    search: '',
1383
1384    /**
1385     *  Layout Mode for this instance
1386     *  Values: 'grid', 'mosaic' or 'slider'
1387     */
1388    layoutMode: 'grid',
1389
1390    /**
1391     *  Sort the items (bigger to smallest) if there are gaps in grid
1392     *  Option available only for `layoutMode: 'mosaic'`
1393     *  Values: true or false
1394     */
1395    sortToPreventGaps: false,
1396
1397    /**
1398     *  Mouse and touch drag support
1399     *  Option available only for `layoutMode: 'slider'`
1400     *  Values: true or false
1401     */
1402    drag: true,
1403
1404    /**
1405     *  Autoplay the slider
1406     *  Option available only for `layoutMode: 'slider'`
1407     *  Values: true or false
1408     */
1409    auto: false,
1410
1411    /**
1412     *  Autoplay interval timeout. Time is set in milisecconds
1413     *  1000 milliseconds equals 1 second.
1414     *  Option available only for `layoutMode: 'slider'`
1415     *  Values: only integers (ex: 1000, 2000, 5000)
1416     */
1417    autoTimeout: 5000,
1418
1419    /**
1420     *  Stops autoplay when user hover the slider
1421     *  Option available only for `layoutMode: 'slider'`
1422     *  Values: true or false
1423     */
1424    autoPauseOnHover: true,
1425
1426    /**
1427     *  Show `next` and `prev` buttons for slider
1428     *  Option available only for `layoutMode: 'slider'`
1429     *  Values: true or false
1430     */
1431    showNavigation: true,
1432
1433    /**
1434     *  Show pagination for slider
1435     *  Option available only for `layoutMode: 'slider'`
1436     *  Values: true or false
1437     */
1438    showPagination: true,
1439
1440    /**
1441     *  Enable slide to first item (last item)
1442     *  Option available only for `layoutMode: 'slider'`
1443     *  Values: true or false
1444     */
1445    rewindNav: true,
1446
1447    /**
1448     *  Scroll by page and not by item. This option affect next/prev buttons and drag support
1449     *  Option available only for `layoutMode: 'slider'`
1450     *  Values: true or false
1451     */
1452    scrollByPage: false,
1453
1454    /**
1455     *  Default filter for plugin
1456     *  Option available only for `layoutMode: 'grid'`
1457     *  Values: strings that represent the filter name(ex: *, .logo, .web-design, .design)
1458     */
1459    defaultFilter: '*',
1460
1461    /**
1462     *  Enable / disable the deeplinking feature when you click on filters
1463     *  Option available only for `layoutMode: 'grid'`
1464     *  Values: true or false
1465     */
1466    filterDeeplinking: false,
1467
1468    /**
1469     *  Defines which animation to use for items that will be shown or hidden after a filter has been activated.
1470     *  Option available only for `layoutMode: 'grid'`
1471     *  The plugin use the best browser features available (css3 transitions and transform, GPU acceleration).
1472     *  Values: - fadeOut
1473     *          - quicksand
1474     *          - bounceLeft
1475     *          - bounceTop
1476     *          - bounceBottom
1477     *          - moveLeft
1478     *          - slideLeft
1479     *          - fadeOutTop
1480     *          - sequentially
1481     *          - skew
1482     *          - slideDelay
1483     *          - rotateSides
1484     *          - flipOutDelay
1485     *          - flipOut
1486     *          - unfold
1487     *          - foldLeft
1488     *          - scaleDown
1489     *          - scaleSides
1490     *          - frontRow
1491     *          - flipBottom
1492     *          - rotateRoom
1493     */
1494    animationType: 'fadeOut',
1495
1496    /**
1497     *  Adjust the layout grid
1498     *  Values: - default (no adjustment applied)
1499     *          - alignCenter (align the grid on center of the page)
1500     *          - responsive (use a fluid algorithm to resize the grid)
1501     */
1502    gridAdjustment: 'responsive',
1503
1504    /**
1505     * Define `media queries` for columns layout.
1506     * Format: [{width: a, cols: d}, {width: b, cols: e}, {width: c, cols: f}],
1507     * where a, b, c are the grid width and d, e, f are the columns displayed.
1508     * e.g. [{width: 1100, cols: 4}, {width: 800, cols: 3}, {width: 480, cols: 2}] means
1509     * if (gridWidth >= 1100) => show 4 columns,
1510     * if (gridWidth >= 800 && gridWidth < 1100) =>
1510 show 3 columns,
1511     * if (gridWidth >= 480 && gridWidth < 800) => show 2 columns,
1512     * if (gridWidth < 480) => show 2 columns
1513     * Keep in mind that a > b > c
1514     * This option is available only when `gridAdjustment: 'responsive'`
1515     * Values:  - array of objects of format: [{width: a, cols: d}, {width: b, cols: e}]
1516     *          - you can define as many objects as you want
1517     *          - if this option is `false` Cube Portfolio will adjust the items
1518     *            width automatically (default option for backward compatibility)
1519     */
1520    mediaQueries: false,
1521
1522    /**
1523     *  Horizontal gap between items
1524     *  Values: only integers (ex: 1, 5, 10)
1525     */
1526    gapHorizontal: 10,
1527
1528    /**
1529     *  Vertical gap between items
1530     *  Values: only integers (ex: 1, 5, 10)
1531     */
1532    gapVertical: 10,
1533
1534    /**
1535     *  Caption - the overlay that is shown when you put the mouse over an item
1536     *  NOTE: If you don't want to have captions set this option to an empty string ( caption: '')
1537     *  Values: - pushTop
1538     *          - pushDown
1539     *          - revealBottom
1540     *          - revealTop
1541     *          - revealLeft
1542     *          - moveRight
1543     *          - overlayBottom
1544     *          - overlayBottomPush
1545     *          - overlayBottomReveal
1546     *          - overlayBottomAlong
1547     *          - overlayRightAlong
1548     *          - minimal
1549     *          - fadeIn
1550     *          - zoom
1551     *          - opacity
1552     *          - ''
1553     */
1554    caption: 'pushTop',
1555
1556    /**
1557     *  The plugin will display his content based on the following values.
1558     *  Values: - default (the content will be displayed without any animation)
1559     *          - fadeIn (the plugin will fully preload the images before displaying the items with a fadeIn effect)
1560     *          - fadeInToTop (the plugin will fully preload the images before displaying the items with a fadeIn effect from bottom to top)
1561     *          - sequentially (the plugin will fully preload the images before displaying the items with a sequentially effect)
1562     *          - bottomToTop (the plugin will fully preload the images before displaying the items with an animation from bottom to top)
1563     */
1564    displayType: 'fadeIn',
1565
1566    /**
1567     *  Defines the speed of displaying the items (when `displayType == default` this option will have no effect)
1568     *  Values: only integers, values in ms (ex: 200, 300, 500)
1569     */
1570    displayTypeSpeed: 400,
1571
1572    /**
1573     *  This is used to define any clickable elements you wish to use to trigger lightbox popup on click.
1574     *  Values: strings that represent the elements in the document (DOM selector)
1575     */
1576    lightboxDelegate: '.cbp-lightbox',
1577
1578    /**
1579     *  Enable / disable gallery mode
1580     *  Values: true or false
1581     */
1582    lightboxGallery: true,
1583
1584    /**
1585     *  Attribute of the delegate item that contains caption for lightbox
1586     *  Values: html atributte
1587     */
1588    lightboxTitleSrc: 'data-title',
1589
1590    /**
1591     *  Markup of the lightbox counter
1592     *  Values: html markup
1593     */
1594    lightboxCounter: '<div class="cbp-popup-lightbox-counter">{{current}} of {{total}}</div>',
1595
1596    /**
1597     *  This is used to define any clickable elements you wish to use to trigger singlePage popup on click.
1598     *  Values: strings that represent the elements in the document (DOM selector)
1599     */
1600    singlePageDelegate: '.cbp-singlePage',
1601
1602    /**
1603     *  Enable / disable the deeplinking feature for singlePage popup
1604     *  Values: true or false
1605     */
1606    singlePageDeeplinking: true,
1607
1608    /**
1609     *  Enable / disable the sticky navigation for singlePage popup
1610     *  Values: true or false
1611     */
1612    singlePageStickyNavigation: true,
1613
1614    /**
1615     *  Markup of the singlePage counter
1616     *  Values: html markup
1617     */
1618    singlePageCounter: '<div class="cbp-popup-singlePage-counter">{{current}} of {{total}}</div>',
1619
1620    /**
1621     *  Defines which animation to use when singlePage appear
1622     *  Values: - left
1623     *          - fade
1624     *          - right
1625     */
1626    singlePageAnimation: 'left',
1627
1628    /**
1629     *  Use this callback to update singlePage content.
1630     *  The callback will trigger after the singlePage popup will open.
1631     *  @param url = the href attribute of the item clicked
1632     *  @param element = the item clicked
1633     *  Values: function
1634     */
1635    singlePageCallback: function(url, element) {
1636        // to update singlePage content use the following method: this.updateSinglePage(yourContent)
1637    },
1638
1639    /**
1640     *  This is used to define any clickable elements you wish to use to trigger singlePage Inline on click.
1641     *  Values: strings that represent the elements in the document (DOM selector)
1642     */
1643    singlePageInlineDelegate: '.cbp-singlePageInline',
1644
1645    /**
1646     *  Enable / disable the deeplinking feature for singlePageInline
1647     *  Values: true or false
1648     */
1649    singlePageInlineDeeplinking: false,
1650
1651    /**
1652     *  This is used to define the position of singlePage Inline block
1653     *  Values: - above ( above current element )
1654     *          - below ( below current elemnet)
1655     *          - top ( positon top )
1656     *          - bottom ( positon bottom )
1657     */
1658    singlePageInlinePosition: 'top',
1659
1660    /**
1661     *  Push the open panel in focus and at close go back to the former stage
1662     *  Values: true or false
1663     */
1664    singlePageInlineInFocus: true,
1665
1666    /**
1667     *  Use this callback to update singlePage Inline content.
1668     *  The callback will trigger after the singlePage Inline will open.
1669     *  @param url = the href attribute of the item clicked
1670     *  @param element = the item clicked
1671     *  Values: function
1672     */
1673    singlePageInlineCallback: function(url, element) {
1674        // to update singlePage Inline content use the following method: this.updateSinglePageInline(yourContent)
1675    },
1676
1677    /**
1678     *  Used by the plugins registered to set local options for the current instance
1679     *  Values: object
1680     */
1681    plugins: {},
1682};
1683
1684(function($, window, document, undefined) {
1685    'use strict';
1686
1687    var CubePortfolio = $.fn.cubeportfolio.constructor;
1688
1689    CubePortfolio.private = {
1690        // array or objects: {instance: instance, fn: fn}
1691        resizeEventArray: [],
1692
1693        initResizeEvent: function(obj) {
1694            var t = CubePortfolio.private;
1695
1696            if (t.resizeEventArray.length === 0) {
1697                t.resizeEvent();
1698            }
1699
1700            t.resizeEventArray.push(obj);
1701        },
1702
1703        destroyResizeEvent: function(instance) {
1704            var t = CubePortfolio.private;
1705
1706            var newResizeEvent = $.map(t.resizeEventArray, function(val, index) {
1707                if (val.instance !== instance) {
1708                    return val;
1709                }
1710            });
1711
1712            t.resizeEventArray = newResizeEvent;
1713
1714            if (t.resizeEventArray.length === 0) {
1715                // remove off resize event
1716                $(window).off('resize.cbp');
1717            }
1718        },
1719
1720        resizeEvent: function() {
1721            var t = CubePortfolio.private,
1722                timeout;
1723
1724            // resize
1725            $(window).on('resize.cbp', function() {
1726                clearTimeout(timeout);
1727
1728                timeout = setTimeout(function() {
1729                    if (window.innerHeight == screen.height) {
1730                        // this is fulll screen mode. don't need to trigger a resize
1731                        return;
1732                    }
1733
1734                    $.each(t.resizeEventArray, function(index, val) {
1735                        val.fn.call(val.instance);
1736                    });
1737                }, 50);
1738            });
1739        },
1740
1741        /**
1742         * Check if cubeportfolio instance exists on current element
1743         */
1744        checkInstance: function(method) {
1745            var t = $.data(this, 'cubeportfolio');
1746
1747            if (!t) {
1748                throw new Error('cubeportfolio is not initialized. Initialize it before calling ' + method + ' method!');
1749            }
1750
1751            t.triggerEvent('publicMethod');
1752
1753            return t;
1754        },
1755
1756        /**
1757         * Get info about client browser
1758         */
1759        browserInfo: function() {
1760            var t = CubePortfolio.private,
1761                appVersion = navigator.appVersion,
1762                transition, animation, perspective;
1763
1764            if (appVersion.indexOf('MSIE 8.') !== -1) { // ie8
1765                t.browser = 'ie8';
1766            } else if (appVersion.indexOf('MSIE 9.') !== -1) { // ie9
1767                t.browser = 'ie9';
1768            } else if (appVersion.indexOf('MSIE 10.') !== -1) { // ie10
1769                t.browser = 'ie10';
1770            } else if (window.ActiveXObject || 'ActiveXObject' in window) { // ie11
1771                t.browser = 'ie11';
1772            } else if ((/android/gi).test(appVersion)) { // android
1773                t.browser = 'android';
1774            } else if ((/iphone|ipad|ipod/gi).test(appVersion)) { // ios
1775                t.browser = 'ios';
1776            } else if ((/chrome/gi).test(appVersion)) {
1777                t.browser = 'chrome';
1778            } else {
1779                t.browser = '';
1780            }
1781
1782            // check if perspective is available
1783            perspective = t.styleSupport('perspective');
1784
1785            // if perspective is not available => no modern browser
1786            if (typeof perspective === undefined) {
1787                return;
1788            }
1789
1790            transition = t.styleSupport('transition');
1791
1792            t.transitionend = {
1793                WebkitTransition: 'webkitTransitionEnd',
1794                transition: 'transitionend'
1795            }[transition];
1796
1797            animation = t.styleSupport('animation');
1798
1799            t.animationend = {
1800                WebkitAnimation: 'webkitAnimationEnd',
1801                animation: 'animationend'
1802            }[animation];
1803
1804            t.animationDuration = {
1805                WebkitAnimation: 'webkitAnimationDuration',
1806                animation: 'animationDuration'
1807            }[animation];
1808
1809            t.animationDelay = {
1810                WebkitAnimation: 'webkitAnimationDelay',
1811                animation: 'animationDelay'
1812            }[animation];
1813
1814            t.transform = t.styleSupport('transform');
1815
1816            if (transition && animation && t.transform) {
1817                t.modernBrowser = true;
1818            }
1819
1820        },
1821
1822
1823        /**
1824         * Feature testing for css3
1825         */
1826        styleSupport: function(prop) {
1827            var supportedProp,
1828                // capitalize first character of the prop to test vendor prefix
1829                webkitProp = 'Webkit' + prop.charAt(0).toUpperCase() + prop.slice(1),
1830                div = document.createElement('div');
1831
1832            // browser supports standard CSS property name
1833            if (prop in div.style) {
1834                supportedProp = prop;
1835            } else if (webkitProp in div.style) {
1836                supportedProp = webkitProp;
1837            }
1838
1839            // avoid memory leak in IE
1840            div = null;
1841
1842            return supportedProp;
1843        },
1844
1845    };
1846
1847    CubePortfolio.private.browserInfo();
1848
1849})(jQuery, window, document);
1850
1851(function($, window, document, undefined) {
1852    'use strict';
1853
1854    var CubePortfolio = $.fn.cubeportfolio.constructor;
1855
1856    CubePortfolio.public = {
1857
1858        /*
1859         * Init the plugin
1860         */
1861        init: function(options, callback) {
1862            new CubePortfolio(this, options, callback);
1863        },
1864
1865        /*
1866         * Destroy the plugin
1867         */
1868        destroy: function(callback) {
1869            var t = CubePortfolio.private.checkInstance.call(this, 'destroy');
1870
1871            t.triggerEvent('beforeDestroy');
1872
1873            // remove data
1874            $.removeData(this, 'cubeportfolio');
1875
1876            // remove data from blocks
1877            t.blocks.removeData('cbp');
1878
1879            // remove loading class and .cbp on container
1880            t.$obj.removeClass('cbp-ready').removeAttr('style');
1881
1882            // remove class from ul
1883            t.$ul.removeClass('cbp-wrapper');
1884
1885            // remove resize event
1886            CubePortfolio.private.destroyResizeEvent(t);
1887
1888            t.$obj.off('.cbp');
1889
1890            // reset blocks
1891            t.blocks.removeClass('cbp-item-off').removeAttr('style');
1892
1893            t.blocks.find('.cbp-item-wrapper').children().unwrap();
1894
1895            if (t.options.caption) {
1896                t.$obj.removeClass('cbp-caption-active cbp-caption-' + t.options.caption);
1897            }
1898
1899            t.destroySlider();
1900
1901            // remove .cbp-wrapper-outer
1902            t.$ul.unwrap();
1903
1904            // remove .cbp-wrapper
1905            if (t.addedWrapp) {
1906                t.blocks.unwrap();
1907            }
1908
1909            $.each(t.plugins, function(i, item) {
1910                if (typeof item.destroy === 'function') {
1911                    item.destroy();
1912                }
1913            });
1914
1915            if ($.isFunction(callback)) {
1916                callback.call(t);
1917            }
1918
1919            t.triggerEvent('afterDestroy');
1920        },
1921
1922        /*
1923         * Filter the plugin by filterName
1924         */
1925        filter: function(param, callback) {
1926            var t = CubePortfolio.private.checkInstance.call(this, 'filter'),
1927                expression;
1928
1929            if (t.isAnimating) {
1930                return;
1931            }
1932
1933            t.isAnimating = true;
1934
1935            // register callback function
1936            if ($.isFunction(callback)) {
1937                t.registerEvent('filterFinish', callback, true);
1938            }
1939
1940            if ($.isFunction(param)) {
1941                expression = param.call(t, t.blocks);
1942
1943                if(expression === undefined) {
1944                    throw new Error('When you call cubeportfolio API `filter` method with a param of type function you must return the blocks that will be visible.');
1945                }
1946            } else {
1947                if (t.options.filterDeeplinking) {
1948                    var url = location.href.replace(/#e=(.*?)([#\?&]|$)/gi, '');
1949                    location.href = url + '#e=' + encodeURIComponent(param);
1950
1951                    if (t.singlePage && t.singlePage.url) {
1952                        t.singlePage.url = location.href;
1953                    }
1954                }
1955
1956                t.defaultFilter = param;
1957                expression = t.filterConcat(t.defaultFilter);
1958            }
1959
1960            if (t.singlePageInline && t.singlePageInline.isOpen) {
1961                t.singlePageInline.close('promise', {
1962                    callback: function() {
1963                        t.computeFilter(expression);
1964                    }
1965                });
1966            } else {
1967                t.computeFilter(expression);
1968            }
1969        },
1970
1971        /*
1972         * Show counter for filters
1973         */
1974        showCounter: function(elems, callback) {
1975            var t = CubePortfolio.private.checkInstance.call(this, 'showCounter');
1976
1977            // register callback function
1978            if ($.isFunction(callback)) {
1979                t.registerEvent('showCounterFinish', callback, true);
1980            }
1981
1982            t.elems = elems;
1983
1984            elems.each(function() {
1985                var el = $(this);
1986
1987                var count = t.blocks.filter(el.data('filter')).length;
1988                el.find('.cbp-filter-counter').text(count);
1989            });
1990
1991            t.triggerEvent('showCounterFinish', elems);
1992        },
1993
1994        /*
1995         * ApendItems elements
1996         */
1997        appendItems: function(els, callback) {
1998            var t = CubePortfolio.private.checkInstance.call(this, 'appendItems'),
1999                items = $(els).filter('.cbp-item');
2000
2001            if (t.isAnimating || items.length < 1) {
2002                if ($.isFunction(callback)) {
2003                    callback.call(t, items);
2004                }
2005
2006                return;
2007            }
2008
2009            t.isAnimating = true;
2010
2011            if (t.singlePageInline && t.singlePageInline.isOpen) {
2012                t.singlePageInline.close('promise', {
2013                    callback: function() {
2014                        t.addItems(items, callback);
2015                    }
2016                });
2017            } else {
2018                t.addItems(items, callback);
2019            }
2020        },
2021
2022    };
2023
2024})(jQuery, window, document);
2025
2026(function($, window, document, undefined) {
2027    'use strict';
2028
2029    var CubePortfolio = $.fn.cubeportfolio.constructor;
2030
2031    // @todo - gandit cum ar trebui sa fac aici ca nu prea ar merge un plugin
2032    // pt slider ca as extinde pe CubePortfolio.prototype la fiecare initializare
2033    $.extend(CubePortfolio.prototype, {
2034        updateSliderPagination: function() {
2035            var t = this,
2036                pages,
2037                i;
2038
2039            if (t.options.showPagination) {
2040                // get number of pages
2041                pages = Math.ceil(t.blocksOn.length / t.cols);
2042                t.navPagination.empty();
2043
2044                for (i = pages - 1; i >= 0; i--) {
2045                    $('<div/>', {
2046                        'class': 'cbp-nav-pagination-item',
2047                        'data-slider-action': 'jumpTo'
2048                    }).appendTo(t.navPagination);
2049                }
2050
2051                t.navPaginationItems = t.navPagination.children();
2052            }
2053
2054            // enable disable the nav
2055            t.enableDisableNavSlider();
2056        },
2057
2058        destroySlider: function() {
2059            var t = this;
2060
2061            if (t.options.layoutMode !== 'slider') {
2062                return;
2063            }
2064
2065            t.$obj.removeClass('cbp-mode-slider');
2066
2067            t.$ul.removeAttr('style');
2068
2069            t.$ul.off('.cbp');
2070
2071            $(document).off('.cbp'); // @todo - don't interfer with the lightbox
2072
2073            if (t.options.auto) {
2074                t.stopSliderAuto();
2075            }
2076        },
2077
2078        nextSlider: function(el) {
2079            var t = this;
2080
2081            if (t.isEndSlider()) {
2082                if (t.isRewindNav()) {
2083                    t.sliderActive = 0;
2084                } else {
2085                    return;
2086                }
2087            } else {
2088                if (t.options.scrollByPage) {
2089                    t.sliderActive = Math.min(t.sliderActive + t.cols, t.blocksOn.length - t.cols);
2090                } else {
2091                    t.sliderActive += 1;
2092                }
2093            }
2094
2095            t.goToSlider();
2096        },
2097
2098        prevSlider: function(el) {
2099            var t = this;
2100
2101            if (t.isStartSlider()) {
2102                if (t.isRewindNav()) {
2103                    t.sliderActive = t.blocksOn.length - t.cols;
2104                } else {
2105                    return;
2106                }
2107            } else {
2108                if (t.options.scrollByPage) {
2109                    t.sliderActive = Math.max(0, t.sliderActive - t.cols);
2110                } else {
2111                    t.sliderActive -= 1;
2112                }
2113            }
2114
2115            t.goToSlider();
2116        },
2117
2118        jumpToSlider: function(el) {
2119            var t = this,
2120                index = Math.min(el.index() * t.cols, t.blocksOn.length - t.cols);
2121
2122            if (index === t.sliderActive) {
2123                return;
2124            }
2125
2126            t.sliderActive = index;
2127
2128            t.goToSlider();
2129        },
2130
2131        jumpDragToSlider: function(pos) {
2132            var t = this,
2133                jumpWidth,
2134                offset,
2135                condition,
2136                index,
2137                dragLeft = (pos > 0) ? true : false;
2138
2139            if (t.options.scrollByPage) {
2140                jumpWidth = t.cols * t.columnWidth;
2141                offset = t.cols;
2142            } else {
2143                jumpWidth = t.columnWidth;
2144                offset = 1;
2145            }
2146
2147            pos = Math.abs(pos);
2148            index = Math.floor(pos / jumpWidth) * offset;
2149
2150            if (pos % jumpWidth > 20) {
2151                index += offset;
2152            }
2153
2154            if (dragLeft) { // drag to left
2155                t.sliderActive = Math.min(t.sliderActive + index, t.blocksOn.length - t.cols);
2156            } else { // drag to right
2157                t.sliderActive = Math.max(0, t.sliderActive - index);
2158            }
2159
2160            t.goToSlider();
2161        },
2162
2163        isStartSlider: function() {
2164            return this.sliderActive === 0;
2165        },
2166
2167        isEndSlider: function() {
2168            var t = this;
2169            return (t.sliderActive + t.cols) > t.blocksOn.length - 1;
2170        },
2171
2172        goToSlider: function() {
2173            var t = this;
2174
2175            // enable disable the nav
2176            t.enableDisableNavSlider();
2177
2178            t.updateSliderPosition();
2179        },
2180
2181        startSliderAuto: function() {
2182            var t = this;
2183
2184            if (t.isDrag) {
2185                t.stopSliderAuto();
2186                return;
2187            }
2188
2189            t.timeout = setTimeout(function() {
2190                // go to next slide
2191                t.nextSlider();
2192
2193                // start auto
2194                t.startSliderAuto();
2195
2196            }, t.options.autoTimeout);
2197        },
2198
2199        stopSliderAuto: function() {
2200            clearTimeout(this.timeout);
2201        },
2202
2203        enableDisableNavSlider: function() {
2204            var t = this,
2205                page,
2206                method;
2207
2208            if (!t.isRewindNav()) {
2209                method = (t.isStartSlider()) ? 'addClass' : 'removeClass';
2210                t.navPrev[method]('cbp-nav-stop');
2211
2212                method = (t.isEndSlider()) ? 'addClass' : 'removeClass';
2213                t.navNext[method]('cbp-nav-stop');
2214            }
2215
2216            if (t.options.showPagination) {
2217                if (t.options.scrollByPage) {
2218                    page = Math.ceil(t.sliderActive / t.cols);
2219                } else {
2220                    if (t.isEndSlider()) {
2221                        page = t.navPaginationItems.length - 1;
2222                    } else {
2223                        page = Math.floor(t.sliderActive / t.cols);
2224                    }
2225                }
2226
2227                // add class active on pagination's items
2228                t.navPaginationItems.removeClass('cbp-nav-pagination-active')
2229                    .eq(page)
2230                    .addClass('cbp-nav-pagination-active');
2231            }
2232
2233            if (t.customPagination) {
2234                if (t.options.scrollByPage) {
2235                    page = Math.ceil(t.sliderActive / t.cols);
2236                } else {
2237                    if (t.isEndSlider()) {
2238                        page = t.customPaginationItems.length - 1;
2239                    } else {
2240                        page = Math.floor(t.sliderActive / t.cols);
2241                    }
2242                }
2243
2244                // add class active on pagination's items
2245                t.customPaginationItems.removeClass(t.customPaginationClass)
2246                    .eq(page)
2247                    .addClass(t.customPaginationClass);
2248            }
2249        },
2250
2251        /**
2252         * If slider loop is enabled don't add classes to `next` and `prev` buttons
2253         */
2254        isRewindNav: function() {
2255            var t = this;
2256
2257            if (!t.options.showNavigation) {
2258                return true;
2259            }
2260
2261            if (t.blocksOn.length <= t.cols) {
2262                return false;
2263            }
2264
2265            if (t.options.rewindNav) {
2266                return true;
2267            }
2268
2269            return false;
2270        },
2271
2272        sliderItemsLength: function() {
2273            return this.blocksOn.length <= this.cols;
2274        },
2275
2276        /**
2277         * Arrange the items in a slider layout
2278         */
2279        sliderLayout: function() {
2280            var t = this;
2281
2282            t.blocksOn.each(function(index, el) {
2283                var data = $(el).data('cbp');
2284
2285                // update the values with the new ones
2286                data.leftNew = t.columnWidth * index;
2287                data.topNew = 0;
2288
2289                t.sliderFreeSpaces.push({
2290                    topStart: data.heightAndGap
2291                });
2292            });
2293
2294            t.getFreeSpacesForSlider();
2295
2296            t.$ul.width(t.columnWidth * t.blocksOn.length - t.options.gapVertical);
2297        },
2298
2299        getFreeSpacesForSlider: function() {
2300            var t = this;
2301
2302            t.freeSpaces = t.sliderFreeSpaces.slice(t.sliderActive, t.sliderActive + t.cols);
2303
2304            t.freeSpaces.sort(function(space1, space2) {
2305                if (space1.topStart > space2.topStart) {
2306                    return 1;
2307                }
2307 else if (space1.topStart < space2.topStart) {
2308                    return -1;
2309                }
2310            });
2311        },
2312
2313        updateSliderPosition: function() {
2314            var t = this,
2315                value = -t.sliderActive * t.columnWidth;
2316
2317            if (CubePortfolio.private.modernBrowser) {
2318                t.$ul[0].style[CubePortfolio.private.transform] = 'translate3d(' + value + 'px, 0px, 0)';
2319            } else {
2320                t.$ul[0].style.left = value + 'px';
2321            }
2322
2323            t.getFreeSpacesForSlider();
2324
2325            t.resizeMainContainer();
2326        },
2327
2328        dragSlider: function() {
2329            var t = this,
2330                $document = $(document),
2331                posInitial,
2332                pos,
2333                target,
2334                ulPosition,
2335                ulMaxWidth,
2336                isAnimating = false,
2337                events = {},
2338                isTouch = false,
2339                touchStartEvent,
2340                isHover = false;
2341
2342            t.isDrag = false;
2343
2344            if (('ontouchstart' in window) ||
2345                (navigator.maxTouchPoints > 0) ||
2346                (navigator.msMaxTouchPoints > 0)) {
2347
2348                events = {
2349                    start: 'touchstart.cbp',
2350                    move: 'touchmove.cbp',
2351                    end: 'touchend.cbp'
2352                };
2353
2354                isTouch = true;
2355            } else {
2356                events = {
2357                    start: 'mousedown.cbp',
2358                    move: 'mousemove.cbp',
2359                    end: 'mouseup.cbp'
2360                };
2361            }
2362
2363            function dragStart(e) {
2364                if (t.sliderItemsLength()) {
2365                    return;
2366                }
2367
2368                if (!isTouch) {
2369                    e.preventDefault();
2370                } else {
2371                    touchStartEvent = e;
2372                }
2373
2374                if (t.options.auto) {
2375                    t.stopSliderAuto();
2376                }
2377
2378                if (isAnimating) {
2379                    $(target).one('click.cbp', function() {
2380                        return false;
2381                    });
2382                    return;
2383                }
2384
2385                target = $(e.target);
2386                posInitial = pointerEventToXY(e).x;
2387                pos = 0;
2388                ulPosition = -t.sliderActive * t.columnWidth;
2389                ulMaxWidth = t.columnWidth * (t.blocksOn.length - t.cols);
2390
2391                $document.on(events.move, dragMove);
2392                $document.on(events.end, dragEnd);
2393
2394                t.$obj.addClass('cbp-mode-slider-dragStart');
2395            }
2396
2397            function dragEnd(e) {
2398                t.$obj.removeClass('cbp-mode-slider-dragStart');
2399
2400                // put the state to animate
2401                isAnimating = true;
2402
2403                if (pos !== 0) {
2404                    target.one('click.cbp', function(e) {
2405                        return false;
2406                    });
2407
2408                    // wait a frame to be sure the .cbp-mode-slider-dragStart is removed from the dom
2409                    requestAnimationFrame(function() {
2410                        t.jumpDragToSlider(pos);
2411                        t.$ul.one(CubePortfolio.private.transitionend, afterDragEnd);
2412                    });
2413                } else {
2414                    afterDragEnd.call(t);
2415                }
2416
2417                $document.off(events.move);
2418                $document.off(events.end);
2419            }
2420
2421            function dragMove(e) {
2422                pos = posInitial - pointerEventToXY(e).x;
2423
2424                if (pos > 8 || pos < -8) {
2425                    e.preventDefault();
2426                }
2427
2428                t.isDrag = true;
2429
2430                var value = ulPosition - pos;
2431
2432                if (pos < 0 && pos < ulPosition) { // to right
2433                    value = (ulPosition - pos) / 5;
2434                } else if (pos > 0 && (ulPosition - pos) < -ulMaxWidth) { // to left
2435                    value = -ulMaxWidth + (ulMaxWidth + ulPosition - pos) / 5;
2436                }
2437
2438                if (CubePortfolio.private.modernBrowser) {
2439                    t.$ul[0].style[CubePortfolio.private.transform] = 'translate3d(' + value + 'px, 0px, 0)';
2440                } else {
2441                    t.$ul[0].style.left = value + 'px';
2442                }
2443            }
2444
2445            function afterDragEnd() {
2446                isAnimating = false;
2447                t.isDrag = false;
2448
2449                if (t.options.auto) {
2450                    if (t.mouseIsEntered) {
2451                        return;
2452                    }
2453
2454                    t.startSliderAuto();
2455                }
2456            }
2457
2458            function pointerEventToXY(e) {
2459                if (e.originalEvent !== undefined && e.originalEvent.touches !== undefined) {
2460                    e = e.originalEvent.touches[0];
2461                }
2462
2463                return {
2464                    x: e.pageX,
2465                    y: e.pageY
2466                };
2467            }
2468
2469            t.$ul.on(events.start, dragStart);
2470        },
2471
2472        /**
2473         * Reset the slider layout
2474         */
2475        sliderLayoutReset: function() {
2476            var t = this;
2477
2478            t.freeSpaces = [];
2479
2480            t.sliderFreeSpaces = [];
2481        },
2482    });
2483})(jQuery, window, document);
2484
2485if (typeof Object.create !== 'function') {
2486    Object.create = function(obj) {
2487        function F() {}
2488        F.prototype = obj;
2489        return new F();
2490    };
2491}
2492
2493// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
2494// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
2495
2496// requestAnimationFrame polyfill by Erik M�ller. fixes from Paul Irish and Tino Zijdel
2497
2498// MIT license
2499
2500(function() {
2501    var lastTime = 0;
2502    var vendors = ['moz', 'webkit'];
2503
2504    for (var x = 0; x < vendors.length && !window.requestAnimationFrame; x++) {
2505        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
2506        window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame'];
2507    }
2508
2509    if (!window.requestAnimationFrame) {
2510        window.requestAnimationFrame = function(callback, element) {
2511            var currTime = new Date().getTime();
2512            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
2513            var id = window.setTimeout(function() {
2514                    callback(currTime + timeToCall);
2515                },
2516                timeToCall);
2517            lastTime = currTime + timeToCall;
2518            return id;
2519        };
2520    }
2521
2522    if (!window.cancelAnimationFrame) {
2523        window.cancelAnimationFrame = function(id) {
2524            clearTimeout(id);
2525        };
2526    }
2527}());
2528
2529(function($, window, document, undefined) {
2530    'use strict';
2531
2532    var CubePortfolio = $.fn.cubeportfolio.constructor;
2533
2534    function Plugin(parent) {
2535        var t = this;
2536
2537        t.parent = parent;
2538
2539        parent.filterLayout = t.filterLayout;
2540
2541        parent.registerEvent('computeBlocksFinish', function(expression) {
2542            parent.blocksOn2On = parent.blocksOnInitial.filter(expression);
2543            parent.blocksOn2Off = parent.blocksOnInitial.not(expression);
2544        });
2545    }
2546
2547    // here this value point to parent grid
2548    Plugin.prototype.filterLayout = function() {
2549        var t = this;
2550
2551        t.$obj.addClass('cbp-animation-' + t.options.animationType);
2552
2553        // [1] - blocks that are only moving with translate
2554        t.blocksOn2On.addClass('cbp-item-on2on')
2555            .each(function(index, el) {
2556                var data = $(el).data('cbp');
2557                el.style[CubePortfolio.private.transform] = 'translate3d(' + (data.leftNew - data.left) + 'px, ' + (data.topNew - data.top) + 'px, 0)';
2558            });
2559
2560        // [2] - blocks than intialy are on but after applying the filter are off
2561        t.blocksOn2Off.addClass('cbp-item-on2off');
2562
2563        // [3] - blocks that are off and it will be on
2564        t.blocksOff2On = t.blocksOn
2565            .filter('.cbp-item-off')
2566            .removeClass('cbp-item-off')
2567            .addClass('cbp-item-off2on')
2568            .each(function(index, el) {
2569                var data = $(el).data('cbp');
2570
2571                el.style.left = data.leftNew + 'px';
2572                el.style.top = data.topNew + 'px';
2573            });
2574
2575        if (t.blocksOn2Off.length) {
2576            t.blocksOn2Off.last().data('cbp').wrapper.one(CubePortfolio.private.animationend, animationend);
2577        } else if (t.blocksOff2On.length) {
2578            t.blocksOff2On.last().data('cbp').wrapper.one(CubePortfolio.private.animationend, animationend);
2579        } else {
2580            animationend();
2581        }
2582
2583        // resize main container height
2584        t.resizeMainContainer();
2585
2586        function animationend() {
2587            t.blocks.removeClass('cbp-item-on2off cbp-item-off2on cbp-item-on2on')
2588                .each(function(index, el) {
2589                    var data = $(el).data('cbp');
2590
2591                    data.left = data.leftNew;
2592                    data.top = data.topNew;
2593
2594                    el.style.left = data.left + 'px';
2595                    el.style.top = data.top + 'px';
2596
2597                    el.style[CubePortfolio.private.transform] = '';
2598                });
2599
2600            t.blocksOff.addClass('cbp-item-off');
2601
2602            t.$obj.removeClass('cbp-animation-' + t.options.animationType);
2603
2604            t.filterFinish();
2605        }
2606    };
2607
2608    Plugin.prototype.destroy = function() {
2609        var parent = this.parent;
2610        parent.$obj.removeClass('cbp-animation-' + parent.options.animationType);
2611    };
2612
2613    CubePortfolio.plugins.animationClassic = function(parent) {
2614        if (!CubePortfolio.private.modernBrowser || $.inArray(parent.options.animationType, ['boxShadow', 'fadeOut', 'flipBottom', 'flipOut', 'quicksand', 'scaleSides', 'skew']) < 0) {
2615            return null;
2616        }
2617
2618        return new Plugin(parent);
2619    };
2620})(jQuery, window, document);
2621
2622(function($, window, document, undefined) {
2623    'use strict';
2624
2625    var CubePortfolio = $.fn.cubeportfolio.constructor;
2626
2627    function Plugin(parent) {
2628        var t = this;
2629
2630        t.parent = parent;
2631
2632        parent.filterLayout = t.filterLayout;
2633    }
2634
2635    // here this value point to parent grid
2636    Plugin.prototype.filterLayout = function() {
2637        var t = this,
2638            ulClone = t.$ul[0].cloneNode(true);
2639
2640        ulClone.setAttribute('class', 'cbp-wrapper-helper');
2641        t.wrapper[0].insertBefore(ulClone, t.$ul[0]);
2642
2643        requestAnimationFrame(function() {
2644            t.$obj.addClass('cbp-animation-' + t.options.animationType);
2645
2646            t.blocksOff.addClass('cbp-item-off');
2647
2648            t.blocksOn.removeClass('cbp-item-off')
2649                .each(function(index, el) {
2650                    var data = $(el).data('cbp');
2651
2652                    data.left = data.leftNew;
2653                    data.top = data.topNew;
2654
2655                    el.style.left = data.left + 'px';
2656                    el.style.top = data.top + 'px';
2657
2658                    if (t.options.animationType === 'sequentially') {
2659                        data.wrapper[0].style[CubePortfolio.private.animationDelay] = (index * 60) + 'ms';
2660                    }
2661                });
2662
2663            if (t.blocksOn.length) {
2664                t.blocksOn.last().data('cbp').wrapper.one(CubePortfolio.private.animationend, animationend);
2665            } else if (t.blocksOnInitial.length) {
2666                t.blocksOnInitial.last().data('cbp').wrapper.one(CubePortfolio.private.animationend, animationend);
2667            } else {
2668                animationend();
2669            }
2670
2671            // resize main container height
2672            t.resizeMainContainer();
2673        });
2674
2675        function animationend() {
2676            t.wrapper[0].removeChild(ulClone);
2677
2678            if (t.options.animationType === 'sequentially') {
2679                t.blocksOn.each(function(index, el) {
2680                    $(el).data('cbp').wrapper[0].style[CubePortfolio.private.animationDelay] = '';
2681                });
2682            }
2683
2684            t.$obj.removeClass('cbp-animation-' + t.options.animationType);
2685
2686            t.filterFinish();
2687        }
2688    };
2689
2690    Plugin.prototype.destroy = function() {
2691        var parent = this.parent;
2692        parent.$obj.removeClass('cbp-animation-' + parent.options.animationType);
2693    };
2694
2695    CubePortfolio.plugins.animationClone = function(parent) {
2696        if (!CubePortfolio.private.modernBrowser || $.inArray(parent.options.animationType, ['fadeOutTop', 'slideLeft', 'sequentially']) < 0) {
2697            return null;
2698        }
2699
2700        return new Plugin(parent);
2701    };
2702})(jQuery, window, document);
2703
2704(function($, window, document, undefined) {
2705    'use strict';
2706
2707    var CubePortfolio = $.fn.cubeportfolio.constructor;
2708
2709    function Plugin(parent) {
2710        var t = this;
2711
2712        t.parent = parent;
2713
2714        parent.filterLayout = t.filterLayout;
2715    }
2716
2717    // here this value point to parent grid
2718    Plugin.prototype.filterLayout = function() {
2719        var t = this,
2720            ulClone = t.$ul.clone(true, true);
2721
2722        ulClone[0].setAttribute('class', 'cbp-wrapper-helper');
2723        t.wrapper[0].insertBefore(ulClone[0], t.$ul[0]);
2724
2725        // hack for safari osx because it doesn't want to work if I set animationDelay
2726        // on cbp-item-wrapper before I clone the t.$ul
2727        var items = ulClone.find('.cbp-item').not('.cbp-item-off');
2728        t.sortBlocks(items, 'top');
2729        items.children('.cbp-item-wrapper').each(function(index, el) {
2730            el.style[CubePortfolio.private.animationDelay] = (index * 50) + 'ms';
2731        });
2732
2733        requestAnimationFrame(function() {
2734            t.$obj.addClass('cbp-animation-' + t.options.animationType);
2735
2736            t.blocksOff.addClass('cbp-item-off');
2737
2738            t.blocksOn.removeClass('cbp-item-off')
2739                .each(function(index, el) {
2740                    var data = $(el).data('cbp');
2741
2742                    data.left = data.leftNew;
2743                    data.top = data.topNew;
2744
2745                    el.style.left = data.left + 'px';
2746                    el.style.top = data.top + 'px';
2747
2748                    data.wrapper[0].style[CubePortfolio.private.animationDelay] = (index * 50) + 'ms';
2749                });
2750
2751            var onLength = t.blocksOn.length,
2752                offLength = items.length;
2753
2754            if (onLength === 0 && offLength === 0) {
2755                animationend();
2756            } else if (onLength < offLength) {
2757                items.last().children('.cbp-item-wrapper').one(CubePortfolio.private.animationend, animationend);
2758            } else {
2759                t.blocksOn.last().data('cbp').wrapper.one(CubePortfolio.private.animationend, animationend);
2760            }
2761
2762            // resize main container height
2763            t.resizeMainContainer();
2764        });
2765
2766        function animationend() {
2767            t.wrapper[0].removeChild(ulClone[0]);
2768
2769            t.$obj.removeClass('cbp-animation-' + t.options.animationType);
2770
2771            t.blocks.each(function(index, el) {
2772                $(el).data('cbp').wrapper[0].style[CubePortfolio.private.animationDelay] = '';
2773            });
2774
2775            t.filterFinish();
2776        }
2777    };
2778
2779    Plugin.prototype.destroy = function() {
2780        var parent = this.parent;
2781        parent.$obj.removeClass('cbp-animation-' + parent.options.animationType);
2782    };
2783
2784    CubePortfolio.plugins.animationCloneDelay = function(parent) {
2785        if (!CubePortfolio.private.modernBrowser || $.inArray(parent.options.animationType, ['3dflip', 'flipOutDelay', 'foldLeft', 'frontRow', 'rotateRoom', 'rotateSides', 'scaleDown', 'slideDelay', 'unfold']) < 0) {
2786            return null;
2787        }
2788
2789        return new Plugin(parent);
2790    };
2791})(jQuery, window, document);
2792
2793(function($, window, document, undefined) {
2794    'use strict';
2795
2796    var CubePortfolio = $.fn.cubeportfolio.constructor;
2797
2798    function Plugin(parent) {
2799        var t = this;
2800
2801        t.parent = parent;
2802
2803        parent.filterLayout = t.filterLayout;
2804    }
2805
2806    // here this value point to parent grid
2807    Plugin.prototype.filterLayout = function() {
2808        var t = this,
2809            ulClone = t.$ul[0].cloneNode(true);
2810
2811        ulClone.setAttribute('class', 'cbp-wrapper-helper');
2812        t.wrapper[0].insertBefore(ulClone, t.$ul[0]);
2813
2814        requestAnimationFrame(function() {
2815            t.$obj.addClass('cbp-animation-' + t.options.animationType);
2816
2817            t.blocksOff.addClass('cbp-item-off');
2818
2819            t.blocksOn.removeClass('cbp-item-off')
2820                .each(function(index, el) {
2821                    var data = $(el).data('cbp');
2822
2823                    data.left = data.leftNew;
2824                    data.top = data.topNew;
2825
2826                    el.style.left = data.left + 'px';
2827                    el.style.top = data.top + 'px';
2828                });
2829
2830            if (t.blocksOn.length) {
2831                t.$ul.one(CubePortfolio.private.animationend, animationend);
2832            } else if (t.blocksOnInitial.length) {
2833                $(ulClone).one(CubePortfolio.private.animationend, animationend);
2834            } else {
2835                animationend();
2836            }
2837
2838            // resize main container height
2839            t.resizeMainContainer();
2840        });
2841
2842        function animationend() {
2843            t.wrapper[0].removeChild(ulClone);
2844
2845            t.$obj.removeClass('cbp-animation-' + t.options.animationType);
2846
2847            t.filterFinish();
2848        }
2849    };
2850
2851    Plugin.prototype.destroy = function() {
2852        var parent = this.parent;
2853        parent.$obj.removeClass('cbp-animation-' + parent.options.animationType);
2854    };
2855
2856    CubePortfolio.plugins.animationWrapper = function(parent) {
2857        if (!CubePortfolio.private.modernBrowser || $.inArray(parent.options.animationType, ['bounceBottom', 'bounceLeft', 'bounceTop', 'moveLeft']) < 0) {
2858            return null;
2859        }
2860
2861        return new Plugin(parent);
2862    };
2863})(jQuery, window, document);
2864
2865(function($, window, document, undefined) {
2866    'use strict';
2867
2868    var CubePortfolio = $.fn.cubeportfolio.constructor;
2869
2870    function Plugin(parent) {
2871        var t = this;
2872
2873        t.parent = parent;
2874
2875        parent.registerEvent('initFinish', function() {
2876            parent.$obj.on('click.cbp', '.cbp-caption-defaultWrap', function(e) {
2877                e.preventDefault();
2878
2879                if (parent.isAnimating) {
2880                    return;
2881                }
2882
2883                parent.isAnimating = true;
2884
2885                var defaultWrap = $(this),
2886                    activeWrap = defaultWrap.next(),
2887                    caption = defaultWrap.parent(),
2888                    endStyle = {
2889                        position: 'relative',
2890                        height: activeWrap.outerHeight(true)
2891                    },
2892                    startStyle = {
2893                        position: 'relative',
2894                        height: 0
2895                    };
2896
2897                parent.$obj.addClass('cbp-caption-expand-active');
2898
2899                // swap endStyle & startStyle
2900                if (caption.hasClass('cbp-caption-expand-open')) {
2901                    var temp = startStyle;
2902                    startStyle = endStyle;
2903                    endStyle = temp;
2904                    caption.removeClass('cbp-caption-expand-open');
2905                }
2906
2907                activeWrap.css(endStyle);
2908
2909                parent.$obj.one('pluginResize.cbp', function() {
2910                    parent.isAnimating = false;
2911                    parent.$obj.removeClass('cbp-caption-expand-active');
2912
2913                    if (endStyle.height === 0) {
2914                        caption.removeClass('cbp-caption-expand-open');
2915                        activeWrap.attr('style', '');
2916                    }
2917                });
2918
2919                // reposition the blocks
2920                parent.layoutAndAdjustment();
2921
2922                // set activeWrap to 0 so I can start animation in the next frame
2923                activeWrap.css(startStyle);
2924
2925                // delay animation
2926                requestAnimationFrame(function() {
2927                    caption.addClass('cbp-caption-expand-open');
2928
2929                    activeWrap.css(endStyle);
2930
2931                    // used by slider layoutMode
2932                    parent.triggerEvent('gridAdjust');
2933
2934                    parent.triggerEvent('resizeGrid');
2935                });
2936            });
2937        }, true);
2938    }
2939
2940    Plugin.prototype.destroy = function() {
2941        this.parent.$obj.find('.cbp-caption-defaultWrap').off('click.cbp').parent().removeClass('cbp-caption-expand-active');
2942    };
2943
2944    CubePortfolio.plugins.captionExpand = function(parent) {
2945
2946        if (parent.options.caption !== 'expand') {
2947            return null;
2948        }
2949
2950        return new Plugin(parent);
2951    };
2952
2953})(jQuery, window, document);
2954
2955(function($, window, document, undefined) {
2956    'use strict';
2957
2958    var CubePortfolio = $.fn.cubeportfolio.constructor;
2959
2960    function Plugin(parent) {
2961        var deferred = $.Deferred();
2962
2963        parent.pushQueue('delayFrame', deferred);
2964
2965        parent.registerEvent('initEndWrite', function() {
2966            parent.blocksOn.each(function(index, el) {
2967                el.style[CubePortfolio.private.animationDelay] = (index * parent.options.displayTypeSpeed) + 'ms';
2968            });
2969
2970            parent.$obj.addClass('cbp-displayType-bottomToTop');
2971
2972            // get last element
2973            parent.blocksOn.last().one(CubePortfolio.private.animationend, function() {
2974                parent.$obj.removeClass('cbp-displayType-bottomToTop');
2975
2976                parent.blocksOn.each(function(index, el) {
2977                    el.style[CubePortfolio.private.animationDelay] = '';
2978                });
2979
2980                // resolve event after the animation is finished
2981                deferred.resolve();
2982            });
2983        }, true);
2984    }
2985
2986    CubePortfolio.plugins.displayBottomToTop = function(parent) {
2987        if (!CubePortfolio.private.modernBrowser || parent.options.displayType !== 'bottomToTop' || parent.blocksOn.length === 0) {
2988            return null;
2989        }
2990
2991        return new Plugin(parent);
2992    };
2993})(jQuery, window, document);
2994
2995(function($, window, document, undefined) {
2996    'use strict';
2997
2998    var CubePortfolio = $.fn.cubeportfolio.constructor;
2999
3000    function Plugin(parent) {
3001        var deferred = $.Deferred();
3002
3003        parent.pushQueue('delayFrame', deferred);
3004
3005        parent.registerEvent('initEndWrite', function() {
3006            parent.obj.style[CubePortfolio.private.animationDuration] = parent.options.displayTypeSpeed + 'ms';
3007
3008            parent.$obj.addClass('cbp-displayType-fadeIn');
3009
3010            parent.$obj.one(CubePortfolio.private.animationend, function() {
3011                parent.$obj.removeClass('cbp-displayType-fadeIn');
3012
3013                parent.obj.style[CubePortfolio.private.animationDuration] = '';
3014
3015                // resolve event after the animation is finished
3016                deferred.resolve();
3017            });
3018        }, true);
3019    }
3020
3021    CubePortfolio.plugins.displayFadeIn = function(parent) {
3022        if (!CubePortfolio.private.modernBrowser || (parent.options.displayType !== 'lazyLoading' && parent.options.displayType !== 'fadeIn') || parent.blocksOn.length === 0) {
3023            return null;
3024        }
3025
3026        return new Plugin(parent);
3027    };
3028})(jQuery, window, document);
3029
3030(function($, window, document, undefined) {
3031    'use strict';
3032
3033    var CubePortfolio = $.fn.cubeportfolio.constructor;
3034
3035    function Plugin(parent) {
3036        var deferred = $.Deferred();
3037
3038        parent.pushQueue('delayFrame', deferred);
3039
3040        parent.registerEvent('initEndWrite', function() {
3041            parent.obj.style[CubePortfolio.private.animationDuration] = parent.options.displayTypeSpeed + 'ms';
3042
3043            parent.$obj.addClass('cbp-displayType-fadeInToTop');
3044
3045            parent.$obj.one(CubePortfolio.private.animationend, function() {
3046                parent.$obj.removeClass('cbp-displayType-fadeInToTop');
3047
3048                parent.obj.style[CubePortfolio.private.animationDuration] = '';
3049
3050                // resolve event after the animation is finished
3051                deferred.resolve();
3052            });
3053        }, true);
3054    }
3055
3056    CubePortfolio.plugins.displayFadeInToTop = function(parent) {
3057        if (!CubePortfolio.private.modernBrowser || parent.options.displayType !== 'fadeInToTop' || parent.blocksOn.length === 0) {
3058            return null;
3059        }
3060
3061        return new Plugin(parent);
3062    };
3063})(jQuery, window, document);
3064
3065(function($, window, document, undefined) {
3066    'use strict';
3067
3068    var CubePortfolio = $.fn.cubeportfolio.constructor;
3069
3070    function Plugin(parent) {
3071        var deferred = $.Deferred();
3072
3073        parent.pushQueue('delayFrame', deferred);
3074
3075        parent.registerEvent('initEndWrite', function() {
3076            parent.blocksOn.each(function(index, el) {
3077                el.style[CubePortfolio.private.animationDelay] = (index * parent.options.displayTypeSpeed) + 'ms';
3078            });
3079
3080            parent.$obj.addClass('cbp-displayType-sequentially');
3081
3082            // get last element
3083            parent.blocksOn.last().one(CubePortfolio.private.animationend, function() {
3084                parent.$obj.removeClass('cbp-displayType-sequentially');
3085
3086                parent.blocksOn.each(function(index, el) {
3087                    el.style[CubePortfolio.private.animationDelay] = '';
3088                });
3089
3090                // resolve event after the animation is finished
3091                deferred.resolve();
3092            });
3093        }, true);
3094    }
3095
3096    CubePortfolio.plugins.displaySequentially = function(parent) {
3097        if (!CubePortfolio.private.modernBrowser || parent.options.displayType !== 'sequentially' || parent.blocksOn.length === 0) {
3098            return null;
3099        }
3100
3101        return new Plugin(parent);
3102    };
3103})(jQuery, window, document);
3104
3105(function($, window, document, undefined) {
3106    'use strict';
3107
3108    var CubePortfolio = $.fn.cubeportfolio.constructor;
3109
3110    function Plugin(parent) {
3111        var t = this;
3112
3113        t.parent = parent;
3114
3115        t.filters = $(parent.options.filters);
3116        t.filterData = [];
3117
3118        parent.registerEvent('afterPlugins', function(elems) {
3119            // set default filter if it's present in url
3120            t.filterFromUrl();
3121            t.registerFilter();
3122        });
3123
3124    }
3125
3126    Plugin.prototype.registerFilter = function() {
3127        var t = this,
3128            parent = t.parent,
3129            filtersCallback,
3130            arr = parent.defaultFilter.split('|');
3131
3132        t.wrap = t.filters.find('.cbp-l-filters-dropdownWrap')
3133            .on({
3134                'mouseover.cbp': function() {
3135                    $(this).addClass('cbp-l-filters-dropdownWrap-open');
3136                },
3137                'mouseleave.cbp': function() {
3138                    $(this).removeClass('cbp-l-filters-dropdownWrap-open');
3139                }
3140            });
3141
3142        t.filters.each(function(index, el) {
3143            var filter = $(el),
3144                filterName = '*',
3145                items = filter.find('.cbp-filter-item'),
3146                dropdown = {};
3147
3148            if (filter.hasClass('cbp-l-filters-dropdown')) {
3149                dropdown.wrap = filter.find('.cbp-l-filters-dropdownWrap');
3150                dropdown.header = filter.find('.cbp-l-filters-dropdownHeader');
3151                dropdown.headerText = dropdown.header.text();
3152            }
3153
3154            // activate counter for filters
3155            parent.$obj.cubeportfolio('showCounter', items);
3156
3157            $.each(arr, function(index, val) {
3158                if (items.filter('[data-filter="' + val + '"]').length) {
3159                    filterName = val;
3160                    arr.splice(index, 1);
3161                    return false;
3162                }
3163            });
3164
3165            $.data(el, 'filterName', filterName);
3166            t.filterData.push(el);
3167
3168            t.filtersCallback(dropdown, items.filter('[data-filter="' + filterName + '"]'));
3169
3170            items.on('click.cbp', function() {
3171                var item = $(this);
3172
3173                if (item.hasClass('cbp-filter-item-active') || parent.isAnimating) {
3174                    return;
3175                }
3176
3177                t.filtersCallback(dropdown, item);
3178
3179                $.data(el, 'filterName', item.data('filter'));
3180
3181                var name = $.map(t.filterData, function(el, index) {
3182                    var f = $.data(el, 'filterName');
3183                    return (f !== "" && f !== '*') ? f : null;
3184                });
3185
3186                if (name.length < 1) {
3187                    name = ['*'];
3188                }
3189
3190                var filterJoin = name.join('|');
3191
3192                if (parent.defaultFilter !== filterJoin) {
3193                    // filter the items
3194                    parent.$obj.cubeportfolio('filter', filterJoin);
3195                }
3196            });
3197        });
3198    };
3199
3200    Plugin.prototype.filtersCallback = function(dropdown, item) {
3201        if (!$.isEmptyObject(dropdown)) {
3202            dropdown.wrap.trigger('mouseleave.cbp');
3203
3204            if (dropdown.headerText) {
3205                dropdown.headerText = '';
3206            } else {
3207                dropdown.header.html(item.html());
3208            }
3209        }
3210
3211        item.addClass('cbp-filter-item-active').siblings().removeClass('cbp-filter-item-active');
3212    };
3213
3214    /**
3215     * Check if filters are present in url
3216     */
3217    Plugin.prototype.filterFromUrl = function() {
3218        var match = /#e=(.*?)([#\?&]|$)/gi.exec(location.href);
3219
3220        if (match !== null) {
3221            this.parent.defaultFilter = decodeURIComponent(match[1]);
3222        }
3223    };
3224
3225    Plugin.prototype.destroy = function() {
3226        var t = this;
3227
3228        t.filters.find('.cbp-filter-item').off('.cbp');
3229        t.wrap.off('.cbp');
3230    };
3231
3232    CubePortfolio.plugins.filters = function(parent) {
3233        if (parent.options.filters === '') {
3234            return null;
3235        }
3236
3237        return new Plugin(parent);
3238    };
3239})(jQuery, window, document);
3240
3241(function($, window, document, undefined) {
3242    'use strict';
3243
3244    var options = {};
3245
3246    var CubePortfolio = $.fn.cubeportfolio.constructor;
3247
3248    function Plugin(parent) {
3249        var t = this;
3250
3251        t.parent = parent;
3252
3253        t.options = $.extend({}, options, t.parent.options.plugins.inlineSlider);
3254
3255        t.runInit();
3256
3257        parent.registerEvent('addItemsToDOM', function() {
3258            t.runInit();
3259        });
3260
3261    }
3262
3263    function InitSlider(slider) {
3264        var t = this;
3265
3266        if (slider.hasClass('cbp-slider-inline-ready')) {
3267            return;
3268        }
3269
3270        slider.addClass('cbp-slider-inline-ready');
3271
3272        t.items = slider.find('.cbp-slider-wrapper').children('.cbp-slider-item');
3273
3274        t.active = t.items.filter('.cbp-slider-item--active').index();
3275        t.total = t.items.length - 1;
3276
3277        t.updateLeft();
3278
3279        slider.find('.cbp-slider-next').on('click.cbp', function(e) {
3280            e.preventDefault();
3281
3282            if (t.active < t.total) {
3283                t.active++;
3284                t.updateLeft();
3285            } else if (t.active === t.total) {
3286                t.active = 0;
3287                t.updateLeft();
3288            }
3289        });
3290
3291        slider.find('.cbp-slider-prev').on('click.cbp', function(e) {
3292            e.preventDefault();
3293
3294            if (t.active > 0) {
3295                t.active--;
3296                t.updateLeft();
3297            } else if (t.active === 0) {
3298                t.active = t.total;
3299                t.updateLeft();
3300            }
3301        });
3302    };
3303
3304    InitSlider.prototype.updateLeft = function() {
3305        var t = this;
3306
3307        t.items.removeClass('cbp-slider-item--active');
3308        t.items.eq(t.active).addClass('cbp-slider-item--active');
3309
3310        t.items.each(function(index, el) {
3311            el.style.left = (index - t.active) + '00%';
3312        });
3313    };
3314
3315    Plugin.prototype.runInit = function() {
3316        var t = this;
3317
3318        t.parent.$obj.find('.cbp-slider-inline').not('.cbp-slider-inline-ready').each(function(index, el) {
3319            var slider = $(el);
3320            var activeImage = slider.find('.cbp-slider-item--active').find('img')[0];
3321
3322            if (activeImage.hasAttribute('data-cbp-src')) {
3323                t.parent.$obj.on('lazyLoad.cbp', function(e, image) {
3324                    if (image.src === activeImage.src) {
3325                        new InitSlider(slider);
3326                    }
3327                });
3328            } else {
3329                new InitSlider(slider);
3330            }
3331        });
3332    };
3333
3334    Plugin.prototype.destroy = function() {
3335        var t = this;
3336
3337        t.parent.$obj.find('.cbp-slider-next').off('click.cbp');
3338        t.parent.$obj.find('.cbp-slider-prev').off('click.cbp');
3339
3340        t.parent.$obj.off('lazyLoad.cbp');
3341
3342        t.parent.$obj.find('.cbp-slider-inline').each(function(index, el) {
3343            var slider = $(el);
3344
3345            slider.removeClass('cbp-slider-inline-ready');
3346
3347            var items = slider.find('.cbp-slider-item');
3348            items.removeClass('cbp-slider-item--active');
3349
3350            items.removeAttr('style');
3351
3352            items.eq(0).addClass('cbp-slider-item--active');
3353        });
3354    };
3355
3356    CubePortfolio.plugins.inlineSlider = function(parent) {
3357        return new Plugin(parent);
3358    };
3359})(jQuery, window, document);
3360
3361(function($, window, document, undefined) {
3362    'use strict';
3363
3364    var options = {
3365        loadingClass: 'cbp-lazyload',
3366        threshold: 0, // loads images 150px before they're visible
3367    };
3368
3369    var CubePortfolio = $.fn.cubeportfolio.constructor;
3370
3371    function Plugin(parent) {
3372        var t = this;
3373
3374        t.window = $(window);
3375
3376        t.parent = parent;
3377
3378        t.options = $.extend({}, options, t.parent.options.plugins.lazyLoad);
3379
3380        parent.registerEvent('initEndWrite', function() {
3381            var timeout;
3382
3383            t.triggerImg();
3384
3385            parent.registerEvent('resizeMainContainer', function() {
3386                t.triggerImg();
3387            });
3388
3389            // scroll event. @todo - this must be done like the global resize event
3390            t.window.on('scroll.cbp', function() {
3391                clearTimeout(timeout);
3392
3393                timeout = setTimeout(function() {
3394                    t.triggerImg();
3395                }, 300);
3396            });
3397        }, true);
3398    }
3399
3400    Plugin.prototype.triggerImg = function() {
3401        var t = this;
3402
3403        var imgs = t.parent.$obj.find('img').filter('[data-cbp-src]');
3404
3405        if (imgs.length === 0) {
3406            return;
3407        }
3408
3409        t.screenHeight = t.window.height();
3410
3411        imgs.each(function(index, el) {
3412            var parentNode = $(el.parentNode);
3413
3414            if (!t.isElementInScreen(el)) {
3415                parentNode.addClass(t.options.loadingClass);
3416                return;
3417            }
3418
3419            var dataSrc = el.getAttribute('data-cbp-src');
3420
3421            if (t.parent.checkSrc(dataSrc) === null) {
3422                t.removeLazy(el, dataSrc);
3423                parentNode.removeClass(t.options.loadingClass);
3424            } else {
3425                parentNode.addClass(t.options.loadingClass);
3426                $('<img>').on('load.cbp error.cbp', function() {
3427                    t.removeLazy(el, dataSrc, parentNode);
3428                }).attr('src', dataSrc); // for ie8
3429            }
3430        });
3431    };
3432
3433    Plugin.prototype.removeLazy = function(el, dataSrc, parentNode) {
3434        var t = this;
3435
3436        el.src = dataSrc;
3437        el.removeAttribute('data-cbp-src');
3438        t.parent.removeAttrImage(el);
3439
3440        // trigger public event
3441        t.parent.$obj.trigger('lazyLoad.cbp', el);
3442
3443        if (parentNode) {
3444            if (CubePortfolio.private.modernBrowser) {
3445                $(el).one(CubePortfolio.private.transitionend, function() {
3446                    parentNode.removeClass(t.options.loadingClass);
3447                });
3448            } else {
3449                parentNode.removeClass(t.options.loadingClass);
3450            }
3451        }
3452    };
3453
3454    Plugin.prototype.isElementInScreen = function(el) {
3455        var t = this;
3456
3457        var bound = el.getBoundingClientRect();
3458        var bottom = bound.bottom + t.options.threshold;
3459        var screenHeight = t.screenHeight + bottom - (bound.top - t.options.threshold);
3460
3461        return bottom >= 0 && bottom <= screenHeight;
3462    };
3463
3464    Plugin.prototype.destroy = function() {
3465        var t = this;
3466
3467        t.window.off('scroll.cbp');
3468    };
3469
3470    CubePortfolio.plugins.lazyLoad = function(parent) {
3471        return new Plugin(parent);
3472    };
3473})(jQuery, window, document);
3474
3475(function($, window, document, undefined) {
3476    'use strict';
3477
3478    var CubePortfolio = $.fn.cubeportfolio.constructor;
3479
3480    function Plugin(parent) {
3481        var t = this;
3482
3483        t.parent = parent;
3484
3485        t.loadMore = $(parent.options.loadMore).find('.cbp-l-loadMore-link');
3486
3487        // load click or auto action
3488        if (t.loadMore.length) {
3489            t[parent.options.loadMoreAction]();
3490        }
3491
3492    }
3493
3494    Plugin.prototype.click = function() {
3495        var t = this,
3496            numberOfClicks = 0;
3497
3498        t.loadMore.on('click.cbp', function(e) {
3499            var button = $(this);
3500
3501            e.preventDefault();
3502
3503            if (t.parent.isAnimating || button.hasClass('cbp-l-loadMore-stop')) {
3504                return;
3505            }
3506
3507            // set loading status
3508            button.addClass('cbp-l-loadMore-loading');
3509
3510            numberOfClicks++;
3511
3512            // perform ajax request
3513            $.ajax({
3514                url: t.loadMore.attr('href') + '?block=' + numberOfClicks,
3515                type: 'GET',
3516                dataType: 'HTML'
3517            }).done(function(result) {
3518                var items = result.replace(/(\r\n|\n|\r)/gm,"");
3519
3520                var startBlock = items.indexOf('cbp-loadMore-block' + numberOfClicks);
3521
3522                // stop the loadMore because the block doesn't exist
3523                if (startBlock === -1) {
3524                    button.addClass('cbp-l-loadMore-stop');
3525                    return;
3526                }
3527
3528                // set start from where I will substring
3529                var start = items.indexOf('>', startBlock) + 1;
3530
3531                var endBlock = items.indexOf('cbp-loadMore-block' + (numberOfClicks + 1));
3532                var end;
3533
3534                // if endBlock doesn't exist
3535                if (endBlock === -1) {
3536                    end = items.lastIndexOf('</');
3537                } else {
3538                    end = items.lastIndexOf('</', endBlock);
3539                }
3540
3541                t.parent.$obj.cubeportfolio('appendItems', items.substring(start, end), function() {
3542                    // remove class from button
3543                    button.removeClass('cbp-l-loadMore-loading');
3544
3545                    // check if we have more works
3546                    if (endBlock === -1) {
3547                        button.addClass('cbp-l-loadMore-stop');
3548                    }
3549                });
3550
3551            }).fail(function() {
3552                // error
3553            });
3554
3555        });
3556    };
3557
3558
3559    Plugin.prototype.auto = function() {
3560        var t = this;
3561
3562        t.parent.$obj.on('initComplete.cbp', function() {
3563            Object.create({
3564                init: function() {
3565                    var self = this;
3566
3567                    // the job inactive
3568                    self.isActive = false;
3569
3570                    self.numberOfClicks = 0;
3571
3572                    // set loading status
3573                    t.loadMore.addClass('cbp-l-loadMore-loading');
3574
3575                    // cache window selector
3576                    self.window = $(window);
3577
3578                    // add events for scroll
3579                    self.addEvents();
3580
3581                    // trigger method on init
3582                    self.getNewItems();
3583                },
3584
3585                addEvents: function() {
3586                    var self = this,
3587                        timeout;
3588
3589                    t.loadMore.on('click.cbp', function(e) {
3590                        e.preventDefault();
3591                    });
3592
3593                    self.window.on('scroll.loadMoreObject', function() {
3594
3595                        clearTimeout(timeout);
3596
3597                        timeout = setTimeout(function() {
3598                            if (!t.parent.isAnimating) {
3599                                // get new items on scroll
3600                                self.getNewItems();
3601                            }
3602                        }, 80);
3603
3604                    });
3605
3606                    // when the filter is completed
3607                    t.parent.$obj.on('filterComplete.cbp', function() {
3608                        self.getNewItems();
3609                    });
3610                },
3611
3612                getNewItems: function() {
3613                    var self = this,
3614                        topLoadMore, topWindow;
3615
3616                    if (self.isActive || t.loadMore.hasClass('cbp-l-loadMore-stop')) {
3617                        return;
3618                    }
3619
3620                    // add a treshold
3621                    topLoadMore = t.loadMore.offset().top - 200;
3622                    topWindow = self.window.scrollTop() + self.window.height();
3623
3624                    if (topLoadMore > topWindow) {
3625                        return;
3626                    }
3627
3628                    // this job is now busy
3629                    self.isActive = true;
3630
3631                    // increment number of clicks
3632                    self.numberOfClicks++;
3633
3634                    // perform ajax request
3635                    $.ajax({
3636                            url: t.loadMore.attr('href') + '?block=' + self.numberOfClicks,
3637                            type: 'GET',
3638                            dataType: 'HTML',
3639                            cache: true
3640                        })
3641                        .done(function(result) {
3642                            var items = result.replace(/(\r\n|\n|\r)/gm,"");
3643
3644                            var startBlock = items.indexOf('cbp-loadMore-block' + self.numberOfClicks);
3645
3646                            // stop the loadMore because the block doesn't exist
3647                            if (startBlock === -1) {
3648                                t.loadMore.addClass('cbp-l-loadMore-stop');
3649                                return;
3650                            }
3651
3652                            // set start from where I will substring
3653                            var start = items.indexOf('>', startBlock) + 1;
3654
3655                            var endBlock = items.indexOf('cbp-loadMore-block' + (self.numberOfClicks + 1));
3656                            var end;
3657
3658                            // if endBlock doesn't exist
3659                            if (endBlock === -1) {
3660                                end = items.lastIndexOf('</');
3661                            } else {
3662                                end = items.lastIndexOf('</', endBlock);
3663                            }
3664
3665                            t.parent.$obj.cubeportfolio('appendItems', items.substring(start, end), function() {
3666                                if (endBlock === -1) {
3667                                    t.loadMore.addClass('cbp-l-loadMore-stop');
3668
3669                                    // remove events
3670                                    self.window.off('scroll.loadMoreObject');
3671                                    t.parent.$obj.off('filterComplete.cbp');
3672                                } else {
3673                                    // make the job inactive
3674                                    self.isActive = false;
3675
3676                                    self.window.trigger('scroll.loadMoreObject');
3677                                }
3678                            });
3679                        })
3680                        .fail(function() {
3681                            // make the job inactive
3682                            self.isActive = false;
3683                        });
3684                }
3685            }).init();
3686        });
3687
3688    };
3689
3690
3691    Plugin.prototype.destroy = function() {
3692        var t = this;
3693
3694        t.loadMore.off('.cbp');
3695
3696        $(window).off('scroll.loadMoreObject');
3697    };
3698
3699    CubePortfolio.plugins.loadMore = function(parent) {
3700        if (parent.options.loadMore === '') {
3701            return null;
3702        }
3703
3704        return new Plugin(parent);
3705    };
3706
3707})(jQuery, window, document);
3708
3709(function($, window, document, undefined) {
3710    'use strict';
3711
3712    var CubePortfolio = $.fn.cubeportfolio.constructor;
3713
3714    var popup = {
3715
3716        /**
3717         * init function for popup
3718         * @param cubeportfolio = cubeportfolio instance
3719         * @param type =  'lightbox' or 'singlePage'
3720         */
3721        init: function(cubeportfolio, type) {
3722            var t = this,
3723                currentBlock;
3724
3725            // remember cubeportfolio instance
3726            t.cubeportfolio = cubeportfolio;
3727
3728            // remember if this instance is for lightbox or for singlePage
3729            t.type = type;
3730
3731            // remember if the popup is open or not
3732            t.isOpen = false;
3733
3734            t.options = t.cubeportfolio.options;
3735
3736            if (type === 'lightbox') {
3737                t.cubeportfolio.registerEvent('resizeWindow', function() {
3738                    t.resizeImage();
3739                });
3740            }
3741
3742            if (type === 'singlePageInline') {
3743                t.height = 0;
3744
3745                // create markup, css and add events for SinglePageInline
3746                t.createMarkupSinglePageInline();
3747
3748                t.cubeportfolio.registerEvent('resizeGrid', function() {
3749                    if (t.isOpen) {
3750                        // @todo must add support for this features in the future
3751                        t.close(); // workaround
3752                    }
3753                });
3754
3755                if (t.options.singlePageInlineDeeplinking) {
3756                    t.url = location.href;
3757
3758                    if (t.url.slice(-1) === '#') {
3759                        t.url = t.url.slice(0, -1);
3760                    }
3761
3762                    var links = t.url.split('#cbpi=');
3763                    var url = links.shift(); // remove first item
3764
3765                    $.each(links, function(index, link) {
3766                        t.cubeportfolio.blocksOn.each(function(index1, el) {
3767                            var singlePageInline = $(el).find(t.options.singlePageInlineDelegate + '[href="' + link + '"]');
3768
3769                            if (singlePageInline.length) {
3770                                currentBlock = singlePageInline;
3771                                return false;
3772                            }
3773                        });
3774
3775                        if (currentBlock) {
3776                            return false;
3777                        }
3778                    });
3779
3780                    if (currentBlock) {
3781                        t.cubeportfolio.registerEvent('initFinish', function() {
3782                            t.openSinglePageInline(t.cubeportfolio.blocksOn, currentBlock[0]);
3783                        }, true);
3784                    }
3785                }
3786
3787                return;
3788            }
3789
3790            // create markup, css and add events for lightbox and singlePage
3791            t.createMarkup();
3792
3793            if (type === 'singlePage') {
3794                t.cubeportfolio.registerEvent('resizeWindow', function() {
3795                    if (t.options.singlePageStickyNavigation) {
3796
3797                        var width = t.wrap[0].clientWidth;
3798
3799                        if (width > 0) {
3800                            t.navigationWrap.width(width);
3801
3802                            // set navigation width='window width' to center the divs
3803                            t.navigation.width(width);
3804                        }
3805
3806                    }
3807                });
3808
3809                if (t.options.singlePageDeeplinking) {
3810                    t.url = location.href;
3811
3812                    if (t.url.slice(-1) === '#') {
3813                        t.url = t.url.slice(0, -1);
3814                    }
3815
3816                    var links = t.url.split('#cbp=');
3817                    var url = links.shift(); // remove first item
3818
3819                    $.each(links, function(index, link) {
3820                        t.cubeportfolio.blocksOn.each(function(index1, el) {
3821                            var singlePage = $(el).find(t.options.singlePageDelegate + '[href="' + link + '"]');
3822
3823                            if (singlePage.length) {
3824                                currentBlock = singlePage;
3825                                return false;
3826                            }
3827                        });
3828
3829                        if (currentBlock) {
3830                            return false;
3831                        }
3832                    });
3833
3834                    if (currentBlock) {
3835                        t.url = url;
3836
3837                        var self = currentBlock,
3838                            gallery = self.attr('data-cbp-singlePage'),
3839                            blocks = [];
3840
3841                        if (gallery) {
3842                            blocks = self.closest($('.cbp-item')).find('[data-cbp-singlePage="' + gallery + '"]');
3843                        } else {
3844                            t.cubeportfolio.blocksOn.each(function(index, el) {
3845                                var item = $(el);
3846
3847                                if (item.not('.cbp-item-off')) {
3848                                    item.find(t.options.singlePageDelegate).each(function(index2, el2) {
3849                                        if (!$(el2).attr('data-cbp-singlePage')) {
3850                                            blocks.push(el2);
3851                                        }
3852                                    });
3853                                }
3854                            });
3855                        }
3856
3857                        t.openSinglePage(blocks, currentBlock[0]);
3858                    } else if (links.length) { // @todo - hack to load items from loadMore
3859                        var fakeLink = document.createElement('a');
3860                        fakeLink.setAttribute('href', links[0]);
3861                        t.openSinglePage([fakeLink], fakeLink);
3862                    }
3863                }
3864            }
3865        },
3866
3867        /**
3868         * Create markup, css and add events
3869         */
3870        createMarkup: function() {
3871            var t = this,
3872                animationCls = '';
3873
3874            if (t.type === 'singlePage') {
3875                if (t.options.singlePageAnimation !== 'left') {
3876                    animationCls = ' cbp-popup-singlePage-' + t.options.singlePageAnimation;
3877                }
3878            }
3879
3880            // wrap element
3881            t.wrap = $('<div/>', {
3882                'class': 'cbp-popup-wrap cbp-popup-' + t.type + animationCls,
3883                'data-action': (t.type === 'lightbox') ? 'close' : ''
3884            }).on('click.cbp', function(e) {
3885                if (t.stopEvents) {
3886                    return;
3887                }
3888
3889                var action = $(e.target).attr('data-action');
3890
3891                if (t[action]) {
3892                    t[action]();
3893                    e.preventDefault();
3894                }
3895            });
3896
3897            // content element
3898            t.content = $('<div/>', {
3899                'class': 'cbp-popup-content'
3900            }).appendTo(t.wrap);
3901
3902            // append loading div
3903            $('<div/>', {
3904                'class': 'cbp-popup-loadingBox'
3905            }).appendTo(t.wrap);
3906
3907            // add background only for ie8
3908            if (CubePortfolio.private.browser === 'ie8') {
3909                t.bg = $('<div/>', {
3910                    'class': 'cbp-popup-ie8bg',
3911                    'data-action': (t.type === 'lightbox') ? 'close' : ''
3912                }).appendTo(t.wrap);
3913            }
3914
3915            // create navigation wrap
3916            t.navigationWrap = $('<div/>', {
3917                'class': 'cbp-popup-navigation-wrap'
3918            }).appendTo(t.wrap);
3919
3920            // create navigation block
3921            t.navigation = $('<div/>', {
3922                'class': 'cbp-popup-navigation'
3923            }).appendTo(t.navigationWrap);
3924
3925            // close
3926            t.closeButton = $('<div/>', {
3927                'class': 'cbp-popup-close',
3928                'title': 'Close (Esc arrow key)',
3929                'data-action': 'close'
3930            }).appendTo(t.navigation);
3931
3932            // next
3933            t.nextButton = $('<div/>', {
3934                'class': 'cbp-popup-next',
3935                'title': 'Next (Right arrow key)',
3936                'data-action': 'next'
3937            }).appendTo(t.navigation);
3938
3939
3940            // prev
3941            t.prevButton = $('<div/>', {
3942                'class': 'cbp-popup-prev',
3943                'title': 'Previous (Left arrow key)',
3944                'data-action': 'prev'
3945            }).appendTo(t.navigation);
3946
3947
3948            if (t.type === 'singlePage') {
3949                if (t.options.singlePageCounter) {
3950                    // counter for singlePage
3951                    t.counter = $(t.options.singlePageCounter).appendTo(t.navigation);
3952                    t.counter.text('');
3953                }
3954
3955                t.content.on('click.cbp', t.options.singlePageDelegate, function(e) {
3956                    e.preventDefault();
3957
3958                    var i,
3959                        len = t.dataArray.length,
3960                        href = this.getAttribute('href');
3961
3962                    for (i = 0; i < len; i++) {
3963                        if (t.dataArray[i].url === href) {
3964                            break;
3965                        }
3966                    }
3967
3968                    t.singlePageJumpTo(i - t.current);
3969                });
3970
3971                // if there are some events than overrides the default scroll behaviour don't go to them
3972                t.wrap.on('mousewheel.cbp' + ' DOMMouseScroll.cbp', function(e) {
3973                    e.stopImmediatePropagation();
3974                });
3975            }
3976
3977            $(document).on('keydown.cbp', function(e) {
3978                // if is not open => return
3979                if (!t.isOpen) {
3980                    return;
3981                }
3982
3983                // if all events are stopped => return
3984                if (t.stopEvents) {
3985                    return;
3986                }
3987
3988                if (e.keyCode === 37) { // prev key
3989                    t.prev();
3990                } else if (e.keyCode === 39) { // next key
3991                    t.next();
3992                } else if (e.keyCode === 27) { //esc key
3993                    t.close();
3994                }
3995            });
3996        },
3997
3998        createMarkupSinglePageInline: function() {
3999            var t = this;
4000
4001            // wrap element
4002            t.wrap = $('<div/>', {
4003                'class': 'cbp-popup-singlePageInline'
4004            }).on('click.cbp', function(e) {
4005                if (t.stopEvents) {
4006                    return;
4007                }
4008
4009                var action = $(e.target).attr('data-action');
4010
4011                if (action && t[action]) {
4012                    t[action]();
4013                    e.preventDefault();
4014                }
4015            });
4016
4017            // content element
4018            t.content = $('<div/>', {
4019                'class': 'cbp-popup-content'
4020            }).appendTo(t.wrap);
4021
4022            // append loading div
4023            // $('<div/>', {
4024            //     'class': 'cbp-popup-loadingBox'
4025            // }).appendTo(t.wrap);
4026
4027            // create navigation block
4028            t.navigation = $('<div/>', {
4029                'class': 'cbp-popup-navigation'
4030            }).appendTo(t.wrap);
4031
4032            // close
4033            t.closeButton = $('<div/>', {
4034                'class': 'cbp-popup-close',
4035                'title': 'Close (Esc arrow key)',
4036                'data-action': 'close'
4037            }).appendTo(t.navigation);
4038
4039        },
4040
4041        destroy: function() {
4042            var t = this,
4043                body = $('body');
4044
4045            // remove off key down
4046            $(document).off('keydown.cbp');
4047
4048            // external lightbox and singlePageInline
4049            body.off('click.cbp', t.options.lightboxDelegate);
4050            body.off('click.cbp', t.options.singlePageDelegate);
4051
4052            t.content.off('click.cbp', t.options.singlePageDelegate);
4053
4054            t.cubeportfolio.$obj.off('click.cbp', t.options.singlePageInlineDelegate);
4055            t.cubeportfolio.$obj.off('click.cbp', t.options.lightboxDelegate);
4056            t.cubeportfolio.$obj.off('click.cbp', t.options.singlePageDelegate);
4057
4058            t.cubeportfolio.$obj.removeClass('cbp-popup-isOpening');
4059
4060            t.cubeportfolio.$obj.find('.cbp-item').removeClass('cbp-singlePageInline-active');
4061
4062            t.wrap.remove();
4063        },
4064
4065        openLightbox: function(blocks, currentBlock) {
4066            var t = this,
4067                i = 0,
4068                currentBlockHref, tempHref = [],
4069                element;
4070
4071            if (t.isOpen) {
4072                return;
4073            }
4074
4075            // remember that the lightbox is open now
4076            t.isOpen = true;
4077
4078            // remember to stop all events after the lightbox has been shown
4079            t.stopEvents = false;
4080
4081            // array with elements
4082            t.dataArray = [];
4083
4084            // reset current
4085            t.current = null;
4086
4087            currentBlockHref = currentBlock.getAttribute('href');
4088            if (currentBlockHref === null) {
4089                throw new Error('HEI! Your clicked element doesn\'t have a href attribute.');
4090            }
4091
4092            $.each(blocks, function(index, item) {
4093                var href = item.getAttribute('href'),
4094                    src = href, // default if element is image
4095                    type = 'isImage', // default if element is image
4096                    videoLink;
4097
4098                if ($.inArray(href, tempHref) === -1) {
4099                    if (currentBlockHref === href) {
4100                        t.current = i;
4101                    } else if (!t.options.lightboxGallery) {
4102                        return;
4103                    }
4104
4105                    if (/youtube/i.test(href)) {
4106                        videoLink = href.substring(href.lastIndexOf('v=') + 2);
4107
4108                        if (!(/autoplay=/i.test(videoLink))) {
4109                            videoLink += '&autoplay=1';
4110                        }
4111
4112                        videoLink = videoLink.replace(/\?|&/, '?');
4113
4114                        // create new href
4115                        src = '//www.youtube.com/embed/' + videoLink;
4116
4117                        type = 'isYoutube';
4118                    } else if (/vimeo\.com/i.test(href)) {
4119                        videoLink = href.substring(href.lastIndexOf('/') + 1);
4120
4121                        if (!(/autoplay=/i.test(videoLink))) {
4122                            videoLink += '&autoplay=1';
4123                        }
4124
4125                        videoLink = videoLink.replace(/\?|&/, '?');
4126
4127                        // create new href
4128                        src = '//player.vimeo.com/video/' + videoLink;
4129
4130                        type = 'isVimeo';
4131                    } else if (/www\.ted\.com/i.test(href)) {
4132                        // create new href
4133                        src = 'http://embed.ted.com/talks/' + href.substring(href.lastIndexOf('/') + 1) + '.html';
4134
4135                        type = 'isTed';
4136                    } else if (/soundcloud\.com/i.test(href)) {
4137                        // create new href
4138                        src = href;
4139
4140                        type = 'isSoundCloud';
4141                    } else if (/(\.mp4)|(\.ogg)|(\.ogv)|(\.webm)/i.test(href)) {
4142                        if (href.indexOf('|') !== -1) {
4143                            // create new href
4144                            src = href.split('|');
4145                        } else {
4146                            // create new href
4147                            src = href.split('%7C');
4148                        }
4149
4150                        type = 'isSelfHostedVideo';
4151                    } else if (/\.mp3$/i.test(href)) {
4152                        src = href;
4153                        type = 'isSelfHostedAudio';
4154                    }
4155
4156                    t.dataArray.push({
4157                        src: src,
4158                        title: item.getAttribute(t.options.lightboxTitleSrc),
4159                        type: type
4160                    });
4161
4162                    i++;
4163                }
4164
4165                tempHref.push(href);
4166            });
4167
4168            // total numbers of elements
4169            t.counterTotal = t.dataArray.length;
4170
4171            if (t.counterTotal === 1) {
4172                t.nextButton.hide();
4173                t.prevButton.hide();
4174                t.dataActionImg = '';
4175            } else {
4176                t.nextButton.show();
4177                t.prevButton.show();
4178                t.dataActionImg = 'data-action="next"';
4179            }
4180
4181            // append to body
4182            t.wrap.appendTo(document.body);
4183
4184            t.scrollTop = $(window).scrollTop();
4185
4186            t.originalStyle = $('html').attr('style');
4187
4188            $('html').css({
4189                overflow: 'hidden',
4190                marginRight: window.innerWidth - $(document).width()
4191            });
4192
4193            t.wrap.addClass('cbp-popup-transitionend');
4194
4195            // show the wrapper (lightbox box)
4196            t.wrap.show();
4197
4198            // get the current element
4199            element = t.dataArray[t.current];
4200
4201            // call function if current element is image or video (iframe)
4202            t[element.type](element);
4203        },
4204
4205        openSinglePage: function(blocks, currentBlock) {
4206            var t = this,
4207                i = 0,
4208                currentBlockHref, tempHref = [];
4209
4210            if (t.isOpen) {
4211                return;
4212            }
4213
4214            // check singlePageInline and close it
4215            if (t.cubeportfolio.singlePageInline && t.cubeportfolio.singlePageInline.isOpen) {
4216                t.cubeportfolio.singlePageInline.close();
4217            }
4218
4219            // remember that the lightbox is open now
4220            t.isOpen = true;
4221
4222            // remember to stop all events after the popup has been showing
4223            t.stopEvents = false;
4224
4225            // array with elements
4226            t.dataArray = [];
4227
4228            // reset current
4229            t.current = null;
4230
4231            currentBlockHref = currentBlock.getAttribute('href');
4232            if (currentBlockHref === null) {
4233                throw new Error('HEI! Your clicked element doesn\'t have a href attribute.');
4234            }
4235
4236            $.each(blocks, function(index, item) {
4237                var href = item.getAttribute('href');
4238
4239                if ($.inArray(href, tempHref) === -1) {
4240                    if (currentBlockHref === href) {
4241                        t.current = i;
4242                    }
4243
4244                    t.dataArray.push({
4245                        url: href,
4246                        element: item
4247                    });
4248
4249                    i++;
4250                }
4251
4252                tempHref.push(href);
4253            });
4254
4255            // total numbers of elements
4256            t.counterTotal = t.dataArray.length;
4257
4258            if (t.counterTotal === 1) {
4259                t.nextButton.hide();
4260                t.prevButton.hide();
4261            } else {
4262                t.nextButton.show();
4263                t.prevButton.show();
4264            }
4265
4266            // append to body
4267            t.wrap.appendTo(document.body);
4268
4269            t.scrollTop = $(window).scrollTop();
4270
4271            // go to top of the page (reset scroll)
4272            t.wrap.scrollTop(0);
4273
4274            // show the wrapper
4275            t.wrap.show();
4276
4277            // finish the open animation
4278            t.finishOpen = 2;
4279
4280            // if transitionend is not fulfilled
4281            t.navigationMobile = $();
4282            t.wrap.one(CubePortfolio.private.transitionend, function() {
4283                $('html').css({
4284                    overflow: 'hidden',
4285                    marginRight: window.innerWidth - $(document).width()
4286                });
4287
4288                t.wrap.addClass('cbp-popup-transitionend');
4289
4290                // make the navigation sticky
4291                if (t.options.singlePageStickyNavigation) {
4292
4293                    t.wrap.addClass('cbp-popup-singlePage-sticky');
4294
4295                    t.navigationWrap.width(t.wrap[0].clientWidth);
4296
4297                    if (CubePortfolio.private.browser === 'android' || CubePortfolio.private.browser === 'ios') {
4298                        // wrap element
4299                        t.navigationMobile = $('<div/>', {
4300                            'class': 'cbp-popup-singlePage cbp-popup-singlePage-sticky',
4301                            'id': t.wrap.attr('id')
4302                        }).on('click.cbp', function(e) {
4303                            if (t.stopEvents) {
4304                                return;
4305                            }
4306
4307                            var action = $(e.target).attr('data-action');
4308
4309                            if (t[action]) {
4310                                t[action]();
4311                                e.preventDefault();
4312                            }
4313                        });
4314
4315                        t.navigationMobile.appendTo(document.body).append(t.navigationWrap);
4316                    }
4317                }
4318
4319                t.finishOpen--;
4320
4321                if (t.finishOpen <= 0) {
4322                    t.updateSinglePageIsOpen.call(t);
4323                }
4324            });
4325
4326            if (CubePortfolio.private.browser === 'ie8' || CubePortfolio.private.browser === 'ie9') {
4327                // make the navigation sticky
4328                if (t.options.singlePageStickyNavigation) {
4329                    t.navigationWrap.width(t.wrap[0].clientWidth);
4330
4331                    setTimeout(function() {
4332                        t.wrap.addClass('cbp-popup-singlePage-sticky');
4333                    }, 1000);
4334                }
4335
4336                t.finishOpen--;
4337            }
4338
4339            t.wrap.addClass('cbp-popup-loading');
4340
4341            // force reflow and then add class
4342            t.wrap.offset();
4343            t.wrap.addClass('cbp-popup-singlePage-open');
4344
4345            // change link
4346            if (t.options.singlePageDeeplinking) {
4347                // ignore old #cbp from href
4348                t.url = t.url.split('#cbp=')[0];
4349                location.href = t.url + '#cbp=' + t.dataArray[t.current].url;
4350            }
4351
4352            // run callback function
4353            if ($.isFunction(t.options.singlePageCallback)) {
4354                t.options.singlePageCallback.call(t, t.dataArray[t.current].url, t.dataArray[t.current].element);
4355            }
4356        },
4357
4358        openSinglePageInline: function(blocks, currentBlock, fromOpen) {
4359            var t = this,
4360                start = 0,
4361                currentBlockHref,
4362                tempCurrent,
4363                cbpitem,
4364                parentElement;
4365
4366            fromOpen = fromOpen || false;
4367
4368            t.fromOpen = fromOpen;
4369
4370            t.storeBlocks = blocks;
4371            t.storeCurrentBlock = currentBlock;
4372
4373            // check singlePageInline and close it
4374            if (t.isOpen) {
4375                tempCurrent = $(currentBlock).closest('.cbp-item').index();
4376
4377                if ((t.dataArray[t.current].url !== currentBlock.getAttribute('href')) || (t.current !== tempCurrent)) {
4378                    t.cubeportfolio.singlePageInline.close('open', {
4379                        blocks: blocks,
4380                        currentBlock: currentBlock,
4381                        fromOpen: true
4382                    });
4383                } else {
4384                    t.close();
4385                }
4386
4387                return;
4388            }
4389
4390            // remember that the lightbox is open now
4391            t.isOpen = true;
4392
4393            // remember to stop all events after the popup has been showing
4394            t.stopEvents = false;
4395
4396            // array with elements
4397            t.dataArray = [];
4398
4399            // reset current
4400            t.current = null;
4401
4402            currentBlockHref = currentBlock.getAttribute('href');
4403            if (currentBlockHref === null) {
4404                throw new Error('HEI! Your clicked element doesn\'t have a href attribute.');
4405            }
4406
4407            cbpitem = $(currentBlock).closest('.cbp-item')[0];
4408
4409            blocks.each(function(index, el) {
4410                if (cbpitem === el) {
4411                    t.current = index;
4412                }
4413            });
4414
4415            t.dataArray[t.current] = {
4416                url: currentBlockHref,
4417                element: currentBlock
4418            };
4419
4420            parentElement = $(t.dataArray[t.current].element).parents('.cbp-item').addClass('cbp-singlePageInline-active');
4421
4422            // total numbers of elements
4423            t.counterTotal = blocks.length;
4424
4425            t.wrap.insertBefore(t.cubeportfolio.wrapper);
4426
4427            if (t.options.singlePageInlinePosition === 'top') {
4428                t.blocksToMove = blocks;
4429                t.top = 0;
4430            } else if (t.options.singlePageInlinePosition === 'bottom') {
4431                t.blocksToMove = $();
4432                t.top = t.cubeportfolio.height;
4433            } else if (t.options.singlePageInlinePosition === 'above') {
4434                t.top = $(blocks[t.current]).data('cbp').top;
4435                t.blocksToMove = $();
4436
4437                blocks.each(function(index, el) {
4438                    var data = $(el).data('cbp');
4439
4440                    if ((data.top + data.height) >= t.top) {
4441                        t.blocksToMove = t.blocksToMove.add(el);
4442                    }
4443                });
4444
4445                t.top = Math.max(t.top - t.options.gapHorizontal, 0);
4446            } else { // below
4447                var dataBlock = $(blocks[t.current]).data('cbp');
4448
4449                t.top = dataBlock.top + dataBlock.height;
4450                t.blocksToMove = $();
4451
4452                blocks.each(function(index, el) {
4453                    var data = $(el).data('cbp');
4454
4455                    if ((data.top + data.height) > t.top) {
4456                        t.blocksToMove = t.blocksToMove.add(el);
4457                    }
4458                });
4459            }
4460
4461            t.wrap[0].style.height = t.wrap.outerHeight(true) + 'px';
4462
4463            // debouncer for inline content
4464            t.deferredInline = $.Deferred();
4465
4466            if (t.options.singlePageInlineInFocus) {
4467                t.scrollTop = $(window).scrollTop();
4468
4469                var goToScroll = t.cubeportfolio.$obj.offset().top + t.top - 100;
4470
4471                if (t.scrollTop !== goToScroll) {
4472                    $('html,body').animate({
4473                            scrollTop: goToScroll
4474                        }, 350)
4475                        .promise()
4476                        .then(function() {
4477                            t.resizeSinglePageInline();
4478                            t.deferredInline.resolve();
4479                        });
4480                } else {
4481                    t.resizeSinglePageInline();
4482                    t.deferredInline.resolve();
4483                }
4484            } else {
4485                t.resizeSinglePageInline();
4486                t.deferredInline.resolve();
4487            }
4488
4489            t.cubeportfolio.$obj.addClass('cbp-popup-singlePageInline-open');
4490
4491            t.wrap.css({
4492                top: t.top
4493            });
4494
4495            // change link
4496            if (t.options.singlePageInlineDeeplinking) {
4497                // ignore old #cbpi from href
4498                t.url = t.url.split('#cbpi=')[0];
4499                location.href = t.url + '#cbpi=' + t.dataArray[t.current].url;
4500            }
4501
4502            // register callback function
4503            if ($.isFunction(t.options.singlePageInlineCallback)) {
4504                t.options.singlePageInlineCallback.call(t, t.dataArray[t.current].url, t.dataArray[t.current].element);
4505            }
4506        },
4507
4508        resizeSinglePageInline: function() {
4509            var t = this;
4510
4511            t.height = ((t.top === 0) || (t.top === t.cubeportfolio.height)) ? t.wrap.outerHeight(true) : t.wrap.outerHeight(true) - t.options.gapHorizontal;
4512
4513            t.storeBlocks.each(function(index, el) {
4514                if (CubePortfolio.private.modernBrowser) {
4515                    el.style[CubePortfolio.private.transform] = '';
4516                } else {
4517                    el.style.marginTop = '';
4518                }
4519            });
4520
4521            t.blocksToMove.each(function(index, el) {
4522                if (CubePortfolio.private.modernBrowser) {
4523                    el.style[CubePortfolio.private.transform] = 'translate3d(0px, ' + t.height + 'px, 0)';
4524                } else {
4525                    el.style.marginTop = t.height + 'px';
4526                }
4527            });
4528
4529            t.cubeportfolio.obj.style.height = t.cubeportfolio.height + t.height + 'px';
4530        },
4531
4532        revertResizeSinglePageInline: function() {
4533            var t = this;
4534
4535            // reset deferred object
4536            t.deferredInline = $.Deferred();
4537
4538            t.storeBlocks.each(function(index, el) {
4539                if (CubePortfolio.private.modernBrowser) {
4540                    el.style[CubePortfolio.private.transform] = '';
4541                } else {
4542                    el.style.marginTop = '';
4543                }
4544            });
4545
4546            t.cubeportfolio.obj.style.height = t.cubeportfolio.height + 'px';
4547        },
4548
4549        appendScriptsToWrap: function(scripts) {
4550            var t = this,
4551                index = 0,
4552                loadScripts = function(item) {
4553                    var script = document.createElement('script'),
4554                        src = item.src;
4555
4556                    script.type = 'text/javascript';
4557
4558                    if (script.readyState) { // ie
4559                        script.onreadystatechange = function() {
4560                            if (script.readyState == 'loaded' || script.readyState == 'complete') {
4561                                script.onreadystatechange = null;
4562                                index++;
4563                                if (scripts[index]) {
4564                                    loadScripts(scripts[index]);
4565                                }
4566                            }
4567                        };
4568                    } else {
4569                        script.onload = function() {
4570                            index++;
4571                            if (scripts[index]) {
4572                                loadScripts(scripts[index]);
4573                            }
4574                        };
4575                    }
4576
4577                    if (src) {
4578                        script.src = src;
4579                    } else {
4580                        script.text = item.text;
4581                    }
4582
4583                    t.content[0].appendChild(script);
4584
4585                };
4586
4587            loadScripts(scripts[0]);
4588        },
4589
4590        updateSinglePage: function(html, scripts, isWrap) {
4591            var t = this,
4592                counterMarkup,
4593                animationFinish;
4594
4595            t.content.addClass('cbp-popup-content').removeClass('cbp-popup-content-basic');
4596
4597            if (isWrap === false) {
4598                t.content.removeClass('cbp-popup-content').addClass('cbp-popup-content-basic');
4599            }
4600
4601            // update counter navigation
4602            if (t.counter) {
4603                counterMarkup = $(t.getCounterMarkup(t.options.singlePageCounter, t.current + 1, t.counterTotal));
4604                t.counter.text(counterMarkup.text());
4605            }
4606
4607            t.fromAJAX = {
4608                html: html,
4609                scripts: scripts
4610            };
4611
4612            t.finishOpen--;
4613
4614            if (t.finishOpen <= 0) {
4615                t.updateSinglePageIsOpen.call(t);
4616            }
4617        },
4618
4619        updateSinglePageIsOpen: function() {
4620            var t = this,
4621                selectorSlider;
4622
4623            t.wrap.addClass('cbp-popup-ready');
4624            t.wrap.removeClass('cbp-popup-loading');
4625
4626            t.content.html(t.fromAJAX.html);
4627
4628            if (t.fromAJAX.scripts) {
4629                t.appendScriptsToWrap(t.fromAJAX.scripts);
4630            }
4631
4632            t.fromAJAX = {};
4633
4634
4635            // trigger public event
4636            t.cubeportfolio.$obj.trigger('updateSinglePageStart.cbp');
4637
4638            // instantiate slider if exists
4639            selectorSlider = t.content.find('.cbp-slider');
4640            if (selectorSlider) {
4641                selectorSlider.find('.cbp-slider-item').addClass('cbp-item');
4642                t.slider = selectorSlider.cubeportfolio({
4643                    layoutMode: 'slider',
4644                    mediaQueries: [{
4645                        width: 1,
4646                        cols: 1
4647                    }],
4648                    gapHorizontal: 0,
4649                    gapVertical: 0,
4650                    caption: '',
4651                    coverRatio: '', // wp version only
4652                });
4653            } else {
4654                t.slider = null;
4655            }
4656
4657            // check for social share icons
4658            t.checkForSocialLinks(t.content);
4659
4660            // scroll bug on android and ios
4661            if (CubePortfolio.private.browser === 'android' || CubePortfolio.private.browser === 'ios') {
4662                $('html').css({
4663                    position: 'fixed'
4664                });
4665            }
4666
4667            // trigger public event
4668            t.cubeportfolio.$obj.trigger('updateSinglePageComplete.cbp');
4669        },
4670
4671        checkForSocialLinks: function(content) {
4672            var t = this;
4673
4674            t.createFacebookShare(content.find('.cbp-social-fb'));
4675            t.createTwitterShare(content.find('.cbp-social-twitter'));
4676            t.createGooglePlusShare(content.find('.cbp-social-googleplus'));
4677            t.createPinterestShare(content.find('.cbp-social-pinterest'));
4678        },
4679
4680        createFacebookShare: function(item) {
4681            if (item.length && !item.attr('onclick')) {
4682                item.attr('onclick', "window.open('http://www.facebook.com/sharer.php?u=" + encodeURIComponent(window.location.href) + "', '_blank', 'top=100,left=100,toolbar=0,status=0,width=620,height=400'); return false;");
4683            }
4684        },
4685
4686        createTwitterShare: function(item) {
4687            if (item.length && !item.attr('onclick')) {
4688                item.attr('onclick', "window.open('https://twitter.com/intent/tweet?source=" + encodeURIComponent(window.location.href) + "&text=" + encodeURIComponent(document.title) + "', '_blank', 'top=100,left=100,toolbar=0,status=0,width=620,height=300'); return false;");
4689            }
4690        },
4691
4692        createGooglePlusShare: function(item) {
4693            if (item.length && !item.attr('onclick')) {
4694                item.attr('onclick', "window.open('https://plus.google.com/share?url=" + encodeURIComponent(window.location.href) + "', '_blank', 'top=100,left=100,toolbar=0,status=0,width=620,height=450'); return false;");
4695            }
4696        },
4697
4698        createPinterestShare: function(item) {
4699            if (item.length && !item.attr('onclick')) {
4700                var media = '';
4701                var firstImg = this.content.find('img')[0];
4702
4703                if(firstImg) {
4704                    media = firstImg.src;
4705                }
4706
4707                item.attr('onclick', "window.open('http://pinterest.com/pin/create/button/?url=" + encodeURIComponent(window.location.href) + "&media=" + media + "', '_blank', 'top=100,left=100,toolbar=0,status=0,width=620,height=400'); return false;");
4708            }
4709        },
4710
4711        updateSinglePageInline: function(html, scripts) {
4712            var t = this;
4713
4714            t.content.html(html);
4715
4716            if (scripts) {
4717                t.appendScriptsToWrap(scripts);
4718            }
4719            // trigger public event
4720            t.cubeportfolio.$obj.trigger('updateSinglePageInlineStart.cbp');
4721
4722            t.singlePageInlineIsOpen.call(t);
4723        },
4724
4725        singlePageInlineIsOpen: function() {
4726            var t = this;
4727
4728            function finishLoading() {
4729                t.wrap.addClass('cbp-popup-singlePageInline-ready');
4730                t.wrap[0].style.height = '';
4731
4732                t.resizeSinglePageInline();
4733
4734                // trigger public event
4735                t.cubeportfolio.$obj.trigger('updateSinglePageInlineComplete.cbp');
4736            }
4737
4738            // wait to load all images
4739            t.cubeportfolio.loadImages(t.wrap, function() {
4740                // instantiate slider if exists
4741                var selectorSlider = t.content.find('.cbp-slider');
4742
4743                if (selectorSlider.length) {
4744                    selectorSlider.find('.cbp-slider-item').addClass('cbp-item');
4745
4746                    selectorSlider.one('initComplete.cbp', function() {
4747                        t.deferredInline.done(finishLoading);
4748                    });
4749
4750                    selectorSlider.on('pluginResize.cbp', function() {
4751                        t.deferredInline.done(finishLoading);
4752                    });
4753
4754                    t.slider = selectorSlider.cubeportfolio({
4755                        layoutMode: 'slider',
4756                        displayType: 'default',
4757                        mediaQueries: [{
4758                            width: 1,
4759                            cols: 1
4760                        }],
4761                        gapHorizontal: 0,
4762                        gapVertical: 0,
4763                        caption: '',
4764                        coverRatio: '', // wp version only
4765                    });
4766                } else {
4767                    t.slider = null;
4768                    t.deferredInline.done(finishLoading);
4769                }
4770
4771                // check for social share icons
4772                t.checkForSocialLinks(t.content);
4773            });
4774        },
4775
4776        isImage: function(el) {
4777            var t = this,
4778                img = new Image();
4779
4780            t.tooggleLoading(true);
4781
4782            t.cubeportfolio.loadImages($('<div><img src="' + el.src + '"></div>'), function() {
4783                t.updateImagesMarkup(el.src, el.title, t.getCounterMarkup(t.options.lightboxCounter, t.current + 1, t.counterTotal));
4784
4785                t.tooggleLoading(false);
4786            });
4787        },
4788
4789        isVimeo: function(el) {
4790            var t = this;
4791            t.updateVideoMarkup(el.src, el.title, t.getCounterMarkup(t.options.lightboxCounter, t.current + 1, t.counterTotal));
4792        },
4793
4794        isYoutube: function(el) {
4795            var t = this;
4796            t.updateVideoMarkup(el.src, el.title, t.getCounterMarkup(t.options.lightboxCounter, t.current + 1, t.counterTotal));
4797
4798        },
4799
4800        isTed: function(el) {
4801            var t = this;
4802            t.updateVideoMarkup(el.src, el.title, t.getCounterMarkup(t.options.lightboxCounter, t.current + 1, t.counterTotal));
4803        },
4804
4805        isSoundCloud: function(el) {
4806            var t = this;
4807            t.updateVideoMarkup(el.src, el.title, t.getCounterMarkup(t.options.lightboxCounter, t.current + 1, t.counterTotal));
4808        },
4809
4810        isSelfHostedVideo: function(el) {
4811            var t = this;
4812            t.updateSelfHostedVideo(el.src, el.title, t.getCounterMarkup(t.options.lightboxCounter, t.current + 1, t.counterTotal));
4813        },
4814
4815        isSelfHostedAudio: function(el) {
4816            var t = this;
4817            t.updateSelfHostedAudio(el.src, el.title, t.getCounterMarkup(t.options.lightboxCounter, t.current + 1, t.counterTotal));
4818        },
4819
4820        getCounterMarkup: function(markup, current, total) {
4821            if (!markup.length) {
4822                return '';
4823            }
4824
4825            var mapObj = {
4826                current: current,
4827                total: total
4828            };
4829
4830            return markup.replace(/\{\{current}}|\{\{total}}/gi, function(matched) {
4831                return mapObj[matched.slice(2, -2)];
4832            });
4833        },
4834
4835        updateSelfHostedVideo: function(src, title, counter) {
4836            var t = this,
4837                i;
4838
4839            t.wrap.addClass('cbp-popup-lightbox-isIframe');
4840
4841            var markup = '<div class="cbp-popup-lightbox-iframe">' +
4842                '<video controls="controls" height="auto" style="width: 100%">';
4843
4844            for (i = 0; i < src.length; i++) {
4845                if (/(\.mp4)/i.test(src[i])) {
4846                    markup += '<source src="' + src[i] + '" type="video/mp4">';
4847                } else if (/(\.ogg)|(\.ogv)/i.test(src[i])) {
4848                    markup += '<source src="' + src[i] + '" type="video/ogg">';
4849                } else if (/(\.webm)/i.test(src[i])) {
4850                    markup += '<source src="' + src[i] + '" type="video/webm">';
4851                }
4852            }
4853
4854            markup += 'Your browser does not support the video tag.' +
4855                '</video>' +
4856                '<div class="cbp-popup-lightbox-bottom">' +
4857                ((title) ? '<div class="cbp-popup-lightbox-title">' + title + '</div>' : '') +
4858                counter +
4859                '</div>' +
4860                '</div>';
4861
4862            t.content.html(markup);
4863            t.wrap.addClass('cbp-popup-ready');
4864            t.preloadNearbyImages();
4865        },
4866
4867        updateSelfHostedAudio: function(src, title, counter) {
4868            var t = this,
4869                i;
4870
4871            t.wrap.addClass('cbp-popup-lightbox-isIframe');
4872
4873            var markup = '<div class="cbp-popup-lightbox-iframe">' +
4874                '<div class="cbp-misc-video"><audio controls="controls" height="auto" style="width: 75%">' +
4875                '<source src="' + src + '" type="audio/mpeg">' +
4876                'Your browser does not support the audio tag.' +
4877                '</audio></div>' +
4878                '<div class="cbp-popup-lightbox-bottom">' +
4879                ((title) ? '<div class="cbp-popup-lightbox-title">' + title + '</div>' : '') +
4880                counter +
4881                '</div>' +
4882                '</div>';
4883
4884            t.content.html(markup);
4885            t.wrap.addClass('cbp-popup-ready');
4886            t.preloadNearbyImages();
4887        },
4888
4889        updateVideoMarkup: function(src, title, counter) {
4890            var t = this;
4891            t.wrap.addClass('cbp-popup-lightbox-isIframe');
4892
4893            var markup = '<div class="cbp-popup-lightbox-iframe">' +
4894                '<iframe src="' + src + '" frameborder="0" allowfullscreen scrolling="no"></iframe>' +
4895                '<div class="cbp-popup-lightbox-bottom">' +
4896                ((title) ? '<div class="cbp-popup-lightbox-title">' + title + '</div>' : '') +
4897                counter +
4898                '</div>' +
4899                '</div>';
4900
4901            t.content.html(markup);
4902            t.wrap.addClass('cbp-popup-ready');
4903            t.preloadNearbyImages();
4904        },
4905
4906        updateImagesMarkup: function(src, title, counter) {
4907            var t = this;
4908
4909            t.wrap.removeClass('cbp-popup-lightbox-isIframe');
4910
4911            var markup = '<div class="cbp-popup-lightbox-figure">' +
4912                '<img src="' + src + '" class="cbp-popup-lightbox-img" ' + t.dataActionImg + ' />' +
4913                '<div class="cbp-popup-lightbox-bottom">' +
4914                ((title) ? '<div class="cbp-popup-lightbox-title">' + title + '</div>' : '') +
4915                counter +
4916                '</div>' +
4917                '</div>';
4918
4919            t.content.html(markup);
4920            t.wrap.addClass('cbp-popup-ready');
4921            t.resizeImage();
4922            t.preloadNearbyImages();
4923        },
4924
4925        next: function() {
4926            var t = this;
4927            t[t.type + 'JumpTo'](1);
4928        },
4929
4930        prev: function() {
4931            var t = this;
4932            t[t.type + 'JumpTo'](-1);
4933        },
4934
4935        lightboxJumpTo: function(index) {
4936            var t = this,
4937                el;
4938
4939            t.current = t.getIndex(t.current + index);
4940
4941            // get the current element
4942            el = t.dataArray[t.current];
4943
4944            // call function if current element is image or video (iframe)
4945            t[el.type](el);
4946        },
4947
4948
4949        singlePageJumpTo: function(index) {
4950            var t = this;
4951
4952            t.current = t.getIndex(t.current + index);
4953
4954            // register singlePageCallback function
4955            if ($.isFunction(t.options.singlePageCallback)) {
4956                t.resetWrap();
4957
4958                // go to top of the page (reset scroll)
4959                t.wrap.scrollTop(0);
4960
4961                t.wrap.addClass('cbp-popup-loading');
4962                t.options.singlePageCallback.call(t, t.dataArray[t.current].url, t.dataArray[t.current].element);
4963
4964                if (t.options.singlePageDeeplinking) {
4965                    location.href = t.url + '#cbp=' + t.dataArray[t.current].url;
4966                }
4967            }
4968        },
4969
4970        resetWrap: function() {
4971            var t = this;
4972
4973            if (t.type === 'singlePage' && t.options.singlePageDeeplinking) {
4974                location.href = t.url + '#';
4975            }
4976
4977            if (t.type === 'singlePageInline' && t.options.singlePageInlineDeeplinking) {
4978                location.href = t.url + '#';
4979            }
4980        },
4981
4982        getIndex: function(index) {
4983            var t = this;
4984
4985            // go to interval [0, (+ or -)this.counterTotal.length - 1]
4986            index = index % t.counterTotal;
4987
4988            // if index is less then 0 then go to interval (0, this.counterTotal - 1]
4989            if (index < 0) {
4990                index = t.counterTotal + index;
4991            }
4992
4993            return index;
4994        },
4995
4996        close: function(method, data) {
4997            var t = this;
4998
4999            function finishClose() {
5000                // reset content
5001                t.content.html('');
5002
5003                // hide the wrap
5004                t.wrap.detach();
5005
5006                t.cubeportfolio.$obj.removeClass('cbp-popup-singlePageInline-open cbp-popup-singlePageInline-close');
5007
5008                if (method === 'promise') {
5009                    if ($.isFunction(data.callback)) {
5010                        data.callback.call(t.cubeportfolio);
5011                    }
5012                }
5013
5014                t.resetWrap();
5015            }
5016
5017            function checkFocusInline() {
5018                if (t.options.singlePageInlineInFocus && method !== 'promise') {
5019                    $('html,body').animate({
5020                            scrollTop: t.scrollTop
5021                        }, 350)
5022                        .promise()
5023                        .then(function() {
5024                            finishClose();
5025                        });
5026                } else {
5027                    finishClose();
5028                }
5029            }
5030
5031            // now the popup is closed
5032            t.isOpen = false;
5033
5034            if (t.type === 'singlePageInline') {
5035                if (method === 'open') {
5036                    t.wrap.removeClass('cbp-popup-singlePageInline-ready');
5037                    $(t.dataArray[t.current].element).closest('.cbp-item').removeClass('cbp-singlePageInline-active');
5038                    t.openSinglePageInline(data.blocks, data.currentBlock, data.fromOpen);
5039                } else {
5040                    t.height = 0;
5041
5042                    t.revertResizeSinglePageInline();
5043                    t.wrap.removeClass('cbp-popup-singlePageInline-ready');
5044                    t.cubeportfolio.$obj.addClass('cbp-popup-singlePageInline-close');
5045                    t.cubeportfolio.$obj.find('.cbp-item').removeClass('cbp-singlePageInline-active');
5046
5047                    if (CubePortfolio.private.modernBrowser) {
5048                        t.wrap.one(CubePortfolio.private.transitionend, function() {
5049                            checkFocusInline();
5050                        });
5051                    } else {
5052                        checkFocusInline();
5053                    }
5054                }
5055
5056            } else if (t.type === 'singlePage') {
5057                t.resetWrap();
5058
5059                t.wrap.removeClass('cbp-popup-ready cbp-popup-transitionend');
5060
5061                // scroll bug on android and ios
5062                if (CubePortfolio.private.browser === 'android' || CubePortfolio.private.browser === 'ios') {
5063                    $('html').css({
5064                        position: ''
5065                    });
5066
5067                    t.navigationWrap.appendTo(t.wrap);
5068                    t.navigationMobile.remove();
5069                }
5070
5071                $(window).scrollTop(t.scrollTop);
5072
5073                // weird bug on mozilla. fixed with setTimeout
5074                setTimeout(function() {
5075                    t.stopScroll = true;
5076
5077                    t.navigationWrap.css({
5078                        top: t.wrap.scrollTop()
5079                    });
5080
5081                    t.wrap.removeClass('cbp-popup-singlePage-open cbp-popup-singlePage-sticky');
5082
5083                    if (CubePortfolio.private.browser === 'ie8' || CubePortfolio.private.browser === 'ie9') {
5084                        // reset content
5085                        t.content.html('');
5086
5087                        // hide the wrap
5088                        t.wrap.detach();
5089
5090                        $('html').css({
5091                            overflow: '',
5092                            marginRight: '',
5093                            position: ''
5094                        });
5095
5096                        t.navigationWrap.removeAttr('style');
5097                    }
5098                }, 0);
5099
5100                $('html').css({
5101                    overflow: '',
5102                    marginRight: '',
5103                    position: ''
5104                });
5105
5106                t.wrap.one(CubePortfolio.private.transitionend, function() {
5107                    // reset content
5108                    t.content.html('');
5109
5110                    // hide the wrap
5111                    t.wrap.detach();
5112
5113
5114                    t.navigationWrap.removeAttr('style');
5115                });
5116            } else {
5117                if (t.originalStyle) {
5118                    $('html').attr('style', t.originalStyle);
5119                } else {
5120                    $('html').css({
5121                        overflow: '',
5122                        marginRight: ''
5123                    });
5124                }
5125
5126                $(window).scrollTop(t.scrollTop);
5127
5128                // reset content
5129                t.content.html('');
5130
5131                // hide the wrap
5132                t.wrap.detach();
5133            }
5134        },
5135
5136        tooggleLoading: function(state) {
5137            var t = this;
5138
5139            t.stopEvents = state;
5140            t.wrap[(state) ? 'addClass' : 'removeClass']('cbp-popup-loading');
5141        },
5142
5143        resizeImage: function() {
5144            // if lightbox is not open go out
5145            if (!this.isOpen) {
5146                return;
5147            }
5148
5149            var height = $(window).height(),
5150                img = this.content.find('img'),
5151                padding = parseInt(img.css('margin-top'), 10) + parseInt(img.css('margin-bottom'), 10);
5152
5153            img.css('max-height', (height - padding) + 'px');
5154        },
5155
5156        preloadNearbyImages: function() {
5157            var arr = [],
5158                img, t = this,
5159                src;
5160
5161            arr.push(t.getIndex(t.current + 1));
5162            arr.push(t.getIndex(t.current + 2));
5163            arr.push(t.getIndex(t.current + 3));
5164            arr.push(t.getIndex(t.current - 1));
5165            arr.push(t.getIndex(t.current - 2));
5166            arr.push(t.getIndex(t.current - 3));
5167
5168            for (var i = arr.length - 1; i >= 0; i--) {
5169                if (t.dataArray[arr[i]].type === 'isImage') {
5170                    t.cubeportfolio.checkSrc(t.dataArray[arr[i]].src);
5171                }
5172            }
5173        }
5174    };
5175
5176    function Plugin(parent) {
5177        var t = this;
5178
5179        t.parent = parent;
5180
5181        // if lightboxShowCounter is false, put lightboxCounter to ''
5182        if (parent.options.lightboxShowCounter === false) {
5183            parent.options.lightboxCounter = '';
5184        }
5185
5186        // if singlePageShowCounter is false, put singlePageCounter to ''
5187        if (parent.options.singlePageShowCounter === false) {
5188            parent.options.singlePageCounter = '';
5189        }
5190
5191        // @todo - schedule this in  future
5192        parent.registerEvent('initStartRead', function() {
5193            t.run();
5194        }, true);
5195    }
5196
5197    var lightboxInit = false,
5198        singlePageInit = false;
5199
5200    Plugin.prototype.run = function() {
5201        var t = this,
5202            p = t.parent,
5203            body = $(document.body);
5204
5205        // default value for lightbox
5206        p.lightbox = null;
5207
5208        // LIGHTBOX
5209        if (p.options.lightboxDelegate && !lightboxInit) {
5210            // init only one time @todo
5211            lightboxInit = true;
5212
5213            p.lightbox = Object.create(popup);
5214            p.lightbox.init(p, 'lightbox');
5215
5216            body.on('click.cbp', p.options.lightboxDelegate, function(e) {
5217                e.preventDefault();
5218
5219                var self = $(this),
5220                    gallery = self.attr('data-cbp-lightbox'),
5221                    scope = t.detectScope(self),
5222                    cbp = scope.data('cubeportfolio'),
5223                    blocks = [];
5224
5225                // is inside a cbp
5226                if (cbp) {
5227                    cbp.blocksOn.each(function(index, el) {
5228                        var item = $(el);
5229
5230                        if (item.not('.cbp-item-off')) {
5231                            item.find(p.options.lightboxDelegate).each(function(index2, el2) {
5232                                if (gallery) {
5233                                    if ($(el2).attr('data-cbp-lightbox') === gallery) {
5234                                        blocks.push(el2);
5235                                    }
5236                                } else {
5237                                    blocks.push(el2);
5238                                }
5239                            });
5240                        }
5241                    });
5242                } else {
5243                    if (gallery) {
5244                        blocks = scope.find(p.options.lightboxDelegate + '[data-cbp-lightbox=' + gallery + ']');
5245                    } else {
5246                        blocks = scope.find(p.options.lightboxDelegate);
5247                    }
5248                }
5249
5250                p.lightbox.openLightbox(blocks, self[0]);
5251            });
5252        }
5253
5254        // default value for singlePage
5255        p.singlePage = null;
5256
5257        // SINGLEPAGE
5258        if (p.options.singlePageDelegate && !singlePageInit) {
5259            // init only one time @todo
5260            singlePageInit = true;
5261
5262            p.singlePage = Object.create(popup);
5263            p.singlePage.init(p, 'singlePage');
5264
5265            body.on('click.cbp', p.options.singlePageDelegate, function(e) {
5266                e.preventDefault();
5267
5268                var self = $(this),
5269                    gallery = self.attr('data-cbp-singlePage'),
5270                    scope = t.detectScope(self),
5271                    cbp = scope.data('cubeportfolio'),
5272                    blocks = [];
5273
5274                // is inside a cbp
5275                if (cbp) {
5276                    cbp.blocksOn.each(function(index, el) {
5277                        var item = $(el);
5278
5279                        if (item.not('.cbp-item-off')) {
5280                            item.find(p.options.singlePageDelegate).each(function(index2, el2) {
5281                                if (gallery) {
5282                                    if ($(el2).attr('data-cbp-singlePage') === gallery) {
5283                                        blocks.push(el2);
5284                                    }
5285                                } else {
5286                                    blocks.push(el2);
5287                                }
5288                            });
5289                        }
5290                    });
5291                } else {
5292                    if (gallery) {
5293                        blocks = scope.find(p.options.singlePageDelegate + '[data-cbp-singlePage=' + gallery + ']');
5294                    } else {
5295                        blocks = scope.find(p.options.singlePageDelegate);
5296                    }
5297                }
5298
5299                p.singlePage.openSinglePage(blocks, self[0]);
5300            });
5301        }
5302
5303        // default value for singlePageInline
5304        p.singlePageInline = null;
5305
5306        // SINGLEPAGEINLINE
5307        if (p.options.singlePageInlineDelegate) {
5308            p.singlePageInline = Object.create(popup);
5309
5310            p.singlePageInline.init(p, 'singlePageInline');
5311
5312            p.$obj.on('click.cbp', p.options.singlePageInlineDelegate, function(e) {
5313                e.preventDefault();
5314
5315                var oldDate = $.data(this, 'cbp-locked'),
5316                    newDate = $.data(this, 'cbp-locked', +new Date());
5317
5318                if(!oldDate || ((newDate - oldDate) > 300)) {
5319                    p.singlePageInline.openSinglePageInline(p.blocksOn, this);
5320                }
5321            });
5322        }
5323    };
5324
5325    Plugin.prototype.detectScope = function(item) {
5326        var singlePageInline,
5327            singlePage,
5328            cbp;
5329
5330        singlePageInline = item.closest('.cbp-popup-singlePageInline');
5331        if (singlePageInline.length) {
5332            cbp = item.closest('.cbp', singlePageInline[0]);
5333            return (cbp.length) ? cbp : singlePageInline;
5334        }
5335
5336        singlePage = item.closest('.cbp-popup-singlePage');
5337        if (singlePage.length) {
5338            cbp = item.closest('.cbp', singlePage[0]);
5339            return (cbp.length) ? cbp : singlePage;
5340        }
5341
5342        cbp = ite
5342m.closest('.cbp');
5343        return (cbp.length) ? cbp : $(document.body);
5344
5345    };
5346
5347    Plugin.prototype.destroy = function() {
5348        var p = this.parent;
5349
5350        $(document.body).off('click.cbp');
5351
5352        // @todo - remove these from here
5353        lightboxInit = false;
5354        singlePageInit = false;
5355
5356        // destroy lightbox if enabled
5357        if (p.lightbox) {
5358            p.lightbox.destroy();
5359        }
5360
5361        // destroy singlePage if enabled
5362        if (p.singlePage) {
5363            p.singlePage.destroy();
5364        }
5365
5366        // destroy singlePage inline if enabled
5367        if (p.singlePageInline) {
5368            p.singlePageInline.destroy();
5369        }
5370    };
5371
5372    CubePortfolio.plugins.popUp = function(parent) {
5373        return new Plugin(parent);
5374    };
5375})(jQuery, window, document);
5376
5377(function($, window, document, undefined) {
5378    'use strict';
5379
5380    var CubePortfolio = $.fn.cubeportfolio.constructor;
5381
5382    function Plugin(parent) {
5383        var t = this;
5384
5385        t.parent = parent;
5386
5387        t.searchInput = $(parent.options.search);
5388
5389        t.searchInput.each(function(index, el) {
5390            var selector = el.getAttribute('data-search');
5391
5392            if (!selector) {
5393                selector = '*';
5394            }
5395
5396            $.data(el, 'searchData', {
5397                value: el.value,
5398                el: selector
5399            });
5400        });
5401
5402        var timeout = null;
5403
5404        t.searchInput.on('keyup.cbp paste.cbp', function(e) {
5405            e.preventDefault();
5406
5407            var el = $(this);
5408
5409            clearTimeout(timeout);
5410            timeout = setTimeout(function() {
5411                t.runEvent.call(t, el);
5412            }, 300);
5413        });
5414
5415        t.searchNothing = t.searchInput.siblings('.cbp-search-nothing').detach();
5416        t.searchNothingHeight = null;
5417        t.searchNothingHTML = t.searchNothing.html();
5418
5419        t.searchInput.siblings('.cbp-search-icon').on('click.cbp', function(e) {
5420            e.preventDefault();
5421
5422            t.runEvent.call(t, $(this).prev().val(''));
5423        });
5424    }
5425
5426    Plugin.prototype.runEvent = function(el) {
5427        var t = this,
5428            value = el.val(),
5429            searchData = el.data('searchData'),
5430            reg = new RegExp(value, 'i');
5431
5432        if (searchData.value === value || t.parent.isAnimating) {
5433            return;
5434        }
5435
5436        searchData.value = value;
5437
5438        if (value.length > 0) {
5439            el.attr('value', value);
5440        } else {
5441            el.removeAttr('value');
5442        }
5443
5444        t.parent.$obj.cubeportfolio('filter', function(blocks) {
5445            var blocksNew = blocks.filter(function(index, block) {
5446                var text = $(block).find(searchData.el).text();
5447
5448                if (text.search(reg) > -1) {
5449                    return true;
5450                }
5451            });
5452
5453            if (blocksNew.length === 0 && t.searchNothing.length) {
5454                var innerText = t.searchNothingHTML.replace('{{query}}', value);
5455                t.searchNothing.html(innerText);
5456
5457                t.searchNothing.appendTo(t.parent.$obj);
5458
5459                if (t.searchNothingHeight === null) {
5460                    t.searchNothingHeight = t.searchNothing.outerHeight(true);
5461                }
5462
5463                t.parent.registerEvent('resizeMainContainer', function() {
5464                    t.parent.height = t.parent.height + t.searchNothingHeight;
5465                    t.parent.obj.style.height = t.parent.height + 'px';
5466                }, true);
5467            } else {
5468                t.searchNothing.detach();
5469            }
5470
5471            return blocksNew;
5472        }, function() {
5473            el.trigger('keyup.cbp');
5474        });
5475    };
5476
5477    Plugin.prototype.destroy = function() {
5478        var t = this;
5479
5480        t.searchInput.off('.cbp');
5481        t.searchInput.next('.cbp-search-icon').off('.cbp');
5482
5483        t.searchInput.each(function(index, el) {
5484            $.removeData(el);
5485        });
5486    };
5487
5488    CubePortfolio.plugins.search = function(parent) {
5489        if (parent.options.search === '') {
5490            return null;
5491        }
5492
5493        return new Plugin(parent);
5494    };
5495})(jQuery, window, document);
5496
5497(function($, window, document, undefined) {
5498    'use strict';
5499
5500    var options = {
5501        /**
5502         *  Pagination custom selector
5503         *  Values: strings that represent the elements in the document (DOM selector).
5504         */
5505        pagination: '',
5506        paginationClass: 'cbp-pagination-active',
5507    };
5508
5509    var CubePortfolio = $.fn.cubeportfolio.constructor;
5510
5511    function Plugin(parent) {
5512        var t = this;
5513
5514        t.parent = parent;
5515
5516        t.options = $.extend({}, options, t.parent.options.plugins.slider);
5517
5518        var customPagination = $(t.options.pagination);
5519
5520        if (customPagination.length > 0) {
5521            t.parent.customPagination = customPagination;
5522            t.parent.customPaginationItems = customPagination.children();
5523            t.parent.customPaginationClass = t.options.paginationClass;
5524
5525            t.parent.customPaginationItems.on('click.cbp', function(e) {
5526                e.preventDefault();
5527                e.stopImmediatePropagation();
5528                e.stopPropagation();
5529
5530                if (t.parent.sliderStopEvents) {
5531                    return;
5532                }
5533
5534                t.parent.jumpToSlider($(this));
5535            });
5536        }
5537
5538        t.parent.registerEvent('gridAdjust', function() {
5539            t.sliderMarkup.call(t.parent);
5540
5541            t.parent.registerEvent('gridAdjust', function() {
5542                t.updateSlider.call(t.parent);
5543            });
5544        }, true);
5545    }
5546
5547    /**
5548     * Create mark-up for slider layout
5549     */
5550    Plugin.prototype.sliderMarkup = function() {
5551        var t = this;
5552
5553        t.sliderStopEvents = false;
5554
5555        t.sliderActive = 0;
5556
5557        t.$obj.one('initComplete.cbp', function() {
5558            t.$obj.addClass('cbp-mode-slider');
5559        });
5560
5561        t.nav = $('<div/>', {
5562            'class': 'cbp-nav'
5563        });
5564
5565        t.nav.on('click.cbp', '[data-slider-action]', function(e) {
5566            e.preventDefault();
5567            e.stopImmediatePropagation();
5568            e.stopPropagation();
5569
5570            if (t.sliderStopEvents) {
5571                return;
5572            }
5573
5574            var el = $(this),
5575                action = el.attr('data-slider-action');
5576
5577            if (t[action + 'Slider']) {
5578                t[action + 'Slider'](el);
5579            }
5580        });
5581
5582        if (t.options.showNavigation) {
5583            t.controls = $('<div/>', {
5584                'class': 'cbp-nav-controls'
5585            });
5586
5587            t.navPrev = $('<div/>', {
5588                'class': 'cbp-nav-prev',
5589                'data-slider-action': 'prev'
5590            }).appendTo(t.controls);
5591
5592            t.navNext = $('<div/>', {
5593                'class': 'cbp-nav-next',
5594                'data-slider-action': 'next'
5595            }).appendTo(t.controls);
5596
5597            t.controls.appendTo(t.nav);
5598        }
5599
5600        if (t.options.showPagination) {
5601            t.navPagination = $('<div/>', {
5602                'class': 'cbp-nav-pagination'
5603            }).appendTo(t.nav);
5604        }
5605
5606        if (t.controls || t.navPagination) {
5607            t.nav.appendTo(t.$obj);
5608        }
5609
5610        t.updateSliderPagination();
5611
5612        if (t.options.auto) {
5613            if (t.options.autoPauseOnHover) {
5614                t.mouseIsEntered = false;
5615                t.$obj.on('mouseenter.cbp', function(e) {
5616                    t.mouseIsEntered = true;
5617                    t.stopSliderAuto();
5618                }).on('mouseleave.cbp', function(e) {
5619                    t.mouseIsEntered = false;
5620                    t.startSliderAuto();
5621                });
5622            }
5623
5624            t.startSliderAuto();
5625        }
5626
5627        if (t.options.drag && CubePortfolio.private.modernBrowser) {
5628            t.dragSlider();
5629        }
5630    };
5631
5632    Plugin.prototype.updateSlider = function() {
5633        var t = this;
5634
5635        t.updateSliderPosition();
5636
5637        t.updateSliderPagination();
5638    };
5639
5640    Plugin.prototype.destroy = function() {
5641        var t = this;
5642
5643        if (t.parent.customPaginationItems) {
5644            t.parent.customPaginationItems.off('.cbp');
5645        }
5646
5647        if (t.parent.controls || t.parent.navPagination) {
5648            t.parent.nav.off('.cbp');
5649            t.parent.nav.remove();
5650        }
5651    };
5652
5653    CubePortfolio.plugins.slider = function(parent) {
5654        if (parent.options.layoutMode !== 'slider') {
5655            return null;
5656        }
5657
5658        return new Plugin(parent);
5659    };
5660})(jQuery, window, document);

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.