PageSourceSearch

https://liceulhaltrich.ro/src/images-grid.js

js liceulhaltrich.ro collected 2026-10-03 18:12:45 UTC 18,083 bytes, 652 lines download raw bytes

1
2;(function($) {
3
4    /**
5     * Plugin
6     */
7
8    $.fn.imagesGrid = function(options) {
9
10        var args = arguments;
11
12        return this.each(function() {
13
14            // If options is plain object - destroy previous instance and create new
15            if ($.isPlainObject(options)) {
16                
17                if (this._imgGrid instanceof ImagesGrid) {
18                    this._imgGrid.destroy();
19                    delete this._imgGrid;
20                }
21
22                var opts = $.extend({}, $.fn.imagesGrid.defaults, options);
23                opts.element = $(this);
24                this._imgGrid = new ImagesGrid(opts);
25
26                return;
27            }
28
29            // If options is string - execute method
30            if (typeof options === 'string' && this._imgGrid instanceof ImagesGrid) {
31                switch (options) {
32                    case 'modal.open':
33                        this._imgGrid.modal.open(args[1]);
34                        break;
35                    case 'modal.close':
36                        this._imgGrid.modal.close();
37                        break;
38                    case 'destroy':
39                        this._imgGrid.destroy();
40                        delete this._imgGrid;
41                        break;
42                }
43            }
44
45        });
46
47    };
48
49    /**
50     * Plugin default options
51     */
52
53    $.fn.imagesGrid.defaults = {
54        images: [],
55        cells: 5,
56        align: false,
57        nextOnClick: true,
58        showViewAll: 'more',
59        viewAllStartIndex: 'auto',
60        loading: 'loading...',
61        getViewAllText: function(imagesCount) {
62            return '+' + imagesCount + '';
63        },
64        onGridRendered: $.noop,
65        onGridItemRendered: $.noop,
66        onGridLoaded: $.noop,
67        onGridImageLoaded: $.noop,
68        onModalOpen: $.noop,
69        onModalClose: $.noop,
70        onModalImageClick: $.noop,
71        onModalImageUpdate: $.noop
72    };
73
74    /**
75     * ImagesGrid
76     *   opts                    - Grid options 
77     *   opts.element            - Element where to render images grid
78     *   opts.images             - Array of images. Array item can be string or object { src, alt, title, caption, thumbnail }
79     *   opts.align              - Align images with different height
80     *   opts.cells              - Maximum number of cells (from 1 to 6)
81     *   opts.showViewAll        - Show view all text:
82     *                                'more'   - show if number of images greater than number of cells
83     *                                'always' - always show
84     *                                false    - never show
85     *   opts.viewAllStartIndex  - Start image index when view all link clicked
86     *   opts.getViewAllText     - Callback function returns text for "view all images" link
87     *   opts.onGridRendered     - Callback function fired when grid items added to the DOM
88     *   opts.onGridItemRendered - Callback function fired when grid item added to the DOM
89     *   opts.onGridLoaded       - Callback function fired when grid images loaded
90     *   opts.onGridImageLoaded  - Callback function fired when grid image loaded
91     */
92
93    function ImagesGrid(opts) {
94
95        this.opts = opts || {};
96
97        this.$window = $(window);
98        this.$element = this.opts.element;
99        this.$gridItems = [];
100
101        this.modal = null;
102        this.imageLoadCount = 0;
103
104        var cells = this.opts.cells;
105        this.opts.cells = (cells < 1)? 1: (cells > 6)? 6: cells;
106
107        this.onWindowResize = this.onWindowResize.bind(this);
108        this.onImageClick = this.onImageClick.bind(this);
109
110        this.init();
111    }
112
113    ImagesGrid.prototype.init = function()  {
114
115        this.setGridClass();
116        this.renderGridItems();
117        this.createModal();
118
119        this.$window.on('resize', this.onWindowResize);
120    }
121
122    ImagesGrid.prototype.createModal = function() {
123
124        var opts = this.opts;
125
126        this.modal = new ImagesGridModal({
127            loading: opts.loading,
128            images: opts.images,
129            nextOnClick: opts.nextOnClick,
130            onModalOpen: opts.onModalOpen,
131            onModalClose: opts.onModalClose,
132            onModalImageClick: opts.onModalImageClick,
133            onModalImageUpdate: opts.onModalImageUpdate
134        });
135    }
136
137    ImagesGrid.prototype.setGridClass = function() {
138
139        var opts = this.opts,
140            imgsLen = opts.images.length,
141            cellsCount = (imgsLen < opts.cells)? imgsLen: opts.cells;
142
143        this.$element.addClass('imgs-grid imgs-grid-' + cellsCount);
144    }
145
146    ImagesGrid.prototype.renderGridItems = function() {
147
148        var opts = this.opts,
149            imgs = opts.images,
150            imgsLen = imgs.length;
151
152        if (!imgs) {
153            return;
154        }
155
156        this.$element.empty();
157        this.$gridItems = [];
158
159        for (var i = 0; i < imgsLen; ++i) {
160            if (i === opts.cells) {
161                break;
162            }
163            this.renderGridItem(imgs[i], i);
164        }
165
166        if (opts.showViewAll === 'always' || 
167            (opts.showViewAll === 'more' && imgsLen > opts.cells)
168        ) {
169            this.renderViewAll();
170        }
171
172        opts.onGridRendered(this.$element);
173    }
174
175    ImagesGrid.prototype.renderGridItem = function(image, index) {
176
177        var src = image,
178            alt = '',
179            title = '',
180            opts = this.opts,
181            _this = this;
182
183        if ($.isPlainObject(image)) {
184            src = image.thumbnail || image.src;
185            alt = image.alt || '';
186            title = image.title || '';
187        }
188
189        var item = $('<div>', {
190            class: 'imgs-grid-image',
191            click: this.onImageClick,
192            data: { index: index }
193        });
194
195        item.append(
196            $('<div>', {
197                class: 'image-wrap'
198            }).append(
199                $('<img>', {
200                    src: src,
201                    alt: alt,
202                    title: title,
203                    on: {
204                        load: function(event) {
205                            _this.onImageLoaded(event, $(this), image);
206                        }
207                    }
208                })
209            )
210        );
211
212        this.$gridItems.push(item);
213        this.$element.append(item);
214
215        opts.onGridItemRendered(item, image);
216    }
217
218    ImagesGrid.prototype.renderViewAll = function() {
219
220        var opts = this.opts;
221
222        this.$element.find('.imgs-grid-image:last .image-wrap').append(
223            $('<div>', {
224                class: 'view-all'
225            }).append(
226                $('<span>', {
227                    class: 'view-all-cover',
228                }),
229                $('<span>', {
230                    class: 'view-all-text',
231                    text: opts.getViewAllText(opts.images.length)
232                })
233            )
234        );
235    }
236
237    ImagesGrid.prototype.onWindowResize = function(event) {
238        if (this.opts.align) {
239            this.align();
240        }
241    }
242
243    ImagesGrid.prototype.onImageClick = function(event) {
244
245        var opts = this.opts,
246            img = $(event.currentTarget),
247            imageIndex;
248
249        if (img.find('.view-all').length > 0 &&
250            typeof opts.viewAllStartIndex === 'number' ) {
251            imageIndex = opts.viewAllStartIndex;
252        } else {
253            imageIndex = img.data('index');
254        }
255
256        this.modal.open(imageIndex);
257    }
258
259    ImagesGrid.prototype.onImageLoaded = function(event, imageEl, image) {
260
261        var opts = this.opts;
262
263        ++this.imageLoadCount;
264
265        opts.onGridImageLoaded(event, imageEl, image);
266
267        if (this.imageLoadCount === this.$gridItems.length) {
268            this.imageLoadCount = 0;
269            this.onAllImagesLoaded()
270        }
271    }
272
273    ImagesGrid.prototype.onAllImagesLoaded = function() {
274
275        var opts = this.opts;
276
277        if (opts.align) {
278            this.align();
279        }
280
281        opts.onGridLoaded(this.$element);
282    }
283
284    ImagesGrid.prototype.align = function() {
285
286        var itemsLen = this.$gridItems.length;
287
288        switch (itemsLen) {
289            case 2:
290            case 3:
291                this.alignItems(this.$gridItems);
292                break;
293            case 4:
294                this.alignItems(this.$gridItems.slice(0, 2));
295                this.alignItems(this.$gridItems.slice(2));
296                break;
297            case 5:
298            case 6:
299                this.alignItems(this.$gridItems.slice(0, 3));
300                this.alignItems(this.$gridItems.slice(3));
301                break;
302        }
303    }
304
305    ImagesGrid.prototype.alignItems = function(items) {
306
307        var itemsHeight = items.map(function(item) {
308            return item.find('img').height();
309        });
310
311        var normalizedHeight = Math.min.apply(null, itemsHeight);
312
313        $(items).each(function() {
314
315            var item = $(this),
316                imgWrap = item.find('.image-wrap'),
317                img = item.find('img'),
318                imgHeight = img.height();
319
320            imgWrap.height(normalizedHeight);
321
322            if (imgHeight > normalizedHeight) {
323                var top = Math.floor((imgHeight - normalizedHeight) / 2);
324                img.css({ top: -top });
325            }
326        });
327    }
328
329    ImagesGrid.prototype.destroy = function() {
330
331        this.$window.off('resize',this.onWindowResize);
332
333        this.$element.empty()
334            .removeClass('imgs-grid imgs-grid-' + this.$gridItems.length);
335
336        this.modal.destroy();
337    }
338
339    /**
340     * ImagesGridModal 
341     *  opts                    - Modal options
342     *  opts.images             - Array of images
343     *  opts.nextOnClick        - Show next image when click on modal image
344     *  opts.loading            - Image loading text
345     *  opts.onModalOpen        - Callback function called when modal opened
346     *  opts.onModalClose       - Callback function called when modal closed
347     *  opts.onModalImageClick  - Callback function called on modal image click
348     */
349
350    function ImagesGridModal(opts) {
351
352        this.opts = opts || {};
353
354        this.imageIndex = null;
355
356        this.$document = $(document);
357        this.$modal = null;
358        this.$indicator = null;
359
360        this.close = this.close.bind(this);
361        this.prev = this.prev.bind(this);
362        this.next = this.next.bind(this);
363        this.onIndicatorClick = this.onIndicatorClick.bind(this);
364        this.onImageLoaded = this.onImageLoaded.bind(this);
365        this.onKeyUp = this.onKeyUp.bind(this);
366
367        this.$document.on('keyup', this.onKeyUp);
368    }
369
370    ImagesGridModal.prototype.open = function(imageIndex) {
371
372        if (this.isOpened()) {
373            return;
374        }
375
376        this.imageIndex = parseInt(imageIndex) || 0;
377        this.render();
378    }
379
380    ImagesGridModal.prototype.close = function(event) {
381
382        if (!this.$modal) {
383            return;
384        }
385
386        var opts = this.opts;
387
388        this.$modal.animate({
389            opacity: 0
390        }, {
391            duration: 100,
392            complete: function() {
393                this.$modal.remove();
394                this.$modal = null;
395                this.$indicator = null;
396                this.imageIndex = null;
397                opts.onModalClose();
398            }.bind(this)
399        });
400    }
401
402    ImagesGridModal.prototype.isOpened = function() {
403        return (this.$modal && this.$modal.is(':visible'));
404    }
405
406    ImagesGridModal.prototype.render = function() {
407
408        var opts = this.opts;
409
410        this.renderModal();
411        this.renderCaption();
412        this.renderCloseButton();
413        this.renderInnerContainer();
414        this.renderIndicatorContainer();
415
416        this.$modal.animate({
417            opacity: 1
418        }, {
419            duration: 100,
420            complete: function() {
421                opts.onModalOpen(this.$modal, opts.images[this.imageIndex]);
422            }.bind(this)
423        });
424    }
425
426    ImagesGridModal.prototype.renderModal = function() {
427        this.$modal = $('<div>', {
428            class: 'imgs-grid-modal'
429        }).appendTo('body');
430    }
431
432    ImagesGridModal.prototype.renderCaption = function() {
433        this.$caption = $('<div>', {
434            class: 'modal-caption',
435            text: this.getImageCaption(this.imageIndex)
436        }).appendTo(this.$modal);
437    }
438
439    ImagesGridModal.prototype.renderCloseButton = function() {
440        this.$modal.append($('<div>', {
441            class: 'modal-close',
442            click: this.close
443        }));
444    }
445
446    ImagesGridModal.prototype.renderInnerContainer = function() {
447
448        var opts = this.opts,
449            image = this.getImage(this.imageIndex);
450
451        this.$modal.append(
452            $('<div>', {
453                class: 'modal-inner'
454            }).append(
455                $('<div>', {
456                    class: 'modal-image'
457                }).append(
458                    $('<img>', {
459                        src: image.src,
460                        alt: image.alt,
461                        title: image.title,
462                        on: {
463                            load: this.onImageLoaded,
464                            click: function(event) {
465                                this.onImageClick(event, $(this), image);
466                            }.bind(this)
467                        }
468                    }),
469                    $('<div>', {
470                        class: 'modal-loader',
471                        html: opts.loading
472                    })
473                ),
474                $('<div>', {
475                    class: 'modal-control left',
476                    click: this.prev
477                }).append(
478                    $('<div>', {
479                        class: 'arrow left'
480                    })
481                ),
482                $('<div>', {
483                    class: 'modal-control right',
484                    click: this.next
485                }).append(
486                    $('<div>', {
487                        class: 'arrow right'
488                    })
489                )
490            )
491        );
492
493        if (opts.images.length <= 1) {
494            this.$modal.find('.modal-control').hide();
495        }
496    }
497
498    ImagesGridModal.prototype.renderIndicatorContainer = function() {
499
500        var opts = this.opts,
501            imgsLen = opts.images.length;
502
503        if (imgsLen == 1) {
504            return;
505        }
506
507        this.$indicator = $('<div>', {
508            class: 'modal-indicator'
509        });
510
511        var list = $('<ul>'), i;
512        for (i = 0; i < imgsLen; ++i) {
513            list.append($('<li>', {
514                class: this.imageIndex == i? 'selected': '',
515                click: this.onIndicatorClick,
516                data: { index: i }
517            }));
518        }
519
520        this.$indicator.append(list);
521        this.$modal.append(this.$indicator);
522    }
523
524    ImagesGridModal.prototype.prev = function() {
525
526        var imgsLen = this.opts.images.length;
527
528        if (this.imageIndex > 0) {
529            --this.imageIndex;
530        } else {
531            this.imageIndex = imgsLen - 1;
532        }
533
534        this.updateImage();
535    }
536
537    ImagesGridModal.prototype.next = function() {
538
539        var imgsLen = this.opts.images.length;
540
541        if (this.imageIndex < imgsLen - 1) {
542            ++this.imageIndex;
543        } else {
544            this.imageIndex = 0;
545        }
546
547        this.updateImage();
548    }
549
550    ImagesGridModal.prototype.updateImage = function() {
551
552        var opts = this.opts,
553            image = this.getImage(this.imageIndex),
554            imageEl = this.$modal.find('.modal-image img');
555
556        imageEl.attr({
557            src: image.src,
558            alt: image.alt,
559            title: image.title
560        });
561
562        this.$modal.find('.modal-caption').text(
563            this.getImageCaption(this.imageIndex) );
564
565        if (this.$indicator) {
566            var indicatorList = this.$indicator.find('ul');
567            indicatorList.children().removeClass('selected');
568            indicatorList.children().eq(this.imageIndex).addClass('selected');
569        }
570
571        this.showLoader();
572
573        opts.onModalImageUpdate(imageEl, image);
574    }
575
576    ImagesGridModal.prototype.onImageClick = function(event, imageEl, image) {
577
578        var opts = this.opts;
579
580        if (opts.nextOnClick) {
581            this.next();
582        }
583
584        opts.onModalImageClick(event, imageEl, image);
585    }
586
587    ImagesGridModal.prototype.onImageLoaded = function() {
588        this.hideLoader();
589    }
590
591    ImagesGridModal.prototype.onIndicatorClick = function(event) {
592        var index = $(event.target).data('index');
593        this.imageIndex = index;
594        this.updateImage();
595    }
596
597    ImagesGridModal.prototype.onKeyUp = function(event) {
598
599        if (!this.$modal) {
600            return;
601        }
602
603        switch (event.keyCode) {
604            case 27: // Esc
605                this.close();
606                break;
607            case 37: // Left arrow
608                this.prev();
609                break;
610            case 39: // Right arrow
611                this.next();
612                break;
613        }
614    }
615
616    ImagesGridModal.prototype.getImage = function(index) {
617
618        var opts = this.opts,
619            image = opts.images[index];
620
621        if ($.isPlainObject(image)) {
622            return image;
623        } else {
624            return { src: image, alt: '', title: '' }
625        }
626    }
627
628    ImagesGridModal.prototype.getImageCaption = function(imgIndex) {
629        var img = this.getImage(imgIndex);
630        return img.caption || '';
631    }
632
633    ImagesGridModal.prototype.showLoader = function() {
634        if (this.$modal) {
635            this.$modal.find('.modal-image img').hide();
636            this.$modal.find('.modal-loader').show();
637        }
638    }
639
640    ImagesGridModal.prototype.hideLoader = function() {
641        if (this.$modal) {
642            this.$modal.find('.modal-image img').show();
643            this.$modal.find('.modal-loader').hide();
644        }
645    }
646
647    ImagesGridModal.prototype.destroy = function() {
648        this.$document.off('keyup', this.onKeyUp);
649        this.close();
650    }
651
652})(jQuery);

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.