Subversion-Projekte lars-tiefland.ci

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
776 lars 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
                    } 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 > 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
1357
jQuery.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) => 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(/#cbpf=(.*?)([#\?&]|$)/gi, '');
1949
                    location.href = url + '#cbpf=' + 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
                } 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
 
2485
if (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 = /#cbpf=(.*?)([#\?&]|$)/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 = item.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);