1(function(){ 2 3 class Gallery { 4 constructor($el) { 5 this.$el = $el; 6 this.minHeight = 250 7 this.maxHeight = 800 8 this.gap = 50; //AKA the padding/margin in between elements 9 this.container = this.$el.getBoundingClientRect(); // The list 10 this.rows = [] 11 this.precision = 2; //Precision with which we will increase the image sizes. You can tweak this for performance. 12 this.itemsLoaded = 0 13 14 //We need to calculate after all the images have been loaded. 15 //We could calculate every time a new image has been loaded but this would mean we calculate N times on page load (N = amount of images). 16 const images = [...$el.querySelectorAll('.gallery__image')]; 17 this.update() 18 images.forEach( item => { 19 item.addEventListener('load', () => { 20 this.update() 21 }) 22 }) 23 } 24 25 update(){ 26 this.getBox() 27 this.calculate() 28 } 29 30 getBox(){ 31 this.container = this.$el.getBoundingClientRect(); 32 } 33 34 calculate(){ 35 this.rows = [] 36 const items = [...this.$el.querySelectorAll('.gallery__item')]; 37 /* 38 To calculate row: 39 40 2. size image with min scalar 41 3. push images into row right up until row width will exceed container width 42 4. increase scalar until images fit container width 43 */ 44 45 let currentRow = [] 46 let currentRowWidth = 0 47 items.forEach((item) => { 48 49 //scale img with min height 50 this.scaleImage(item, this.minHeight) 51 52 //Check if item fits into row 53 if(currentRowWidth + this.getItemWidth(item) + this.gap < this.container.width){ 54 //Push item into row 55 currentRow.push(item); 56 //Add item width + gap to row width 57 currentRowWidth = this.calculateRowWidth(currentRow) 58 59 } else{ 60 //Increase scalars 61 this.findAndApplyScalar(currentRow); 62 this.rows.push(currentRow); 63 currentRow = [] 64 //Push item into row 65 currentRow.push(item); 66 //Add image width + gap to row width 67 currentRowWidth = this.calculateRowWidth(currentRow) 68 } 69 }) 70 this.findAndApplyScalar(currentRow); 71 this.rows.push(currentRow) 72 this.rows.forEach(this.addOffSet) 73 } 74 getItemWidth(item){ 75 if(item.classList.contains('gallery__text')){ 76 //Since the text container doesnt have a .width we need to use .offsetWidth 77 return item.offsetWidth 78 } 79 return item.width 80 } 81 scaleImage(img, scalar){ 82 if(img.classList.contains('gallery__text')) return 83 //Scale image using scalar 84 85 img.style.width = 'auto' 86 img.style.height = `${scalar}px`; 87 } 88 calculateRowWidth(row){ 89 let width = 0; 90 row.forEach(image => { 91 width = width + this.getItemWidth(image) + this.gap; 92 }) 93 return width; 94 } 95 addOffSet(row){ 96 /* 97 Add offset to images 98 -- 99 First image (i % 3 == 0) - no offset 100 Second image (i % 3 == 1) - offset to top 101 Third image (i % 3 == 2) - offset to bottom 102 -- 103 */ 104 row.forEach( (item, i) => { 105 if(item.classList.contains('gallery__text')) return; 106 let offset = i % 3; 107 if(offset){ 108 const classToAdd = `gallery__image--offset-${offset===1?'top':'bottom'}`; 109 item.classList.add(classToAdd); 110 } 111 }) 112 } 113 findAndApplyScalar(row){
114 const scalar = this.findScalar(row, this.minHeight, this.precision); 115 row.forEach(image => { 116 this.scaleImage(image, scalar) 117 }) 118 119 120 } 121 findScalar(row, scalar, precision){ 122 /* 123 Find the most suitable scalar recursively 124 125 -- scale images with scalar 126 127 128 - break on row width exceeding container width with new scalar 129 - return previous scalar 130 131 - break on newScalar exceeding max height 132 - return previous scalar 133 134 Recursive with row, newScalar (aka just used scalar), precision, 135 136 */ 137 const newScalar = scalar + precision 138 row.forEach( image => { 139 this.scaleImage(image, newScalar) 140 }) 141 142 let currentRowWidth = this.calculateRowWidth(row) 143 if ( currentRowWidth >= this.container.width){ 144 return scalar; 145 } 146 if ( newScalar > this.maxHeight ){ 147 return scalar 148 } 149 150 return this.findScalar(row, newScalar, precision) 151 } 152 } 153 154 155 156 const lists = [...document.querySelectorAll('.gallery__list')] 157 const galleries = [] 158 lists.forEach(list => { 159 galleries.push(new Gallery(list)) 160 }) 161 162 window.addEventListener('resize', () => { 163 galleries.forEach(gallery => { 164 gallery.update(); 165 }) 166 }) 167 168 document.addEventListener("visibilitychange", () => { 169 if (document.visibilityState === "hidden") return null; 170 galleries.forEach(gallery => { 171 gallery.update(); 172 }) 173 }) 174})();
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.