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