1 2/* 3 Copyright 2018 - 2026 Marcel Pol (email: [email protected]) 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18*/ 19 20 21/* 22 * option: type: default: description: 23 * zoomValue number in percentage 100 It defines the initial zoom value of an image. 24 * maxZoom number in percentage 500 It defines maximum percentage you can zoom an image. 25 * snapView boolean true Configuration to show/hide snap view. 26 * refreshOnResize boolean true Defines wether to refresh the viewer on resize of window. 27 * zoomOnMouseWheel boolean true Defines weather to allow zoom with mouse scroll or not. 28 * 29 */ 30 31 32/* 33 * Start the ImageViewer. 34 * 35 * @since 1.0.0 36 */ 37document.addEventListener('DOMContentLoaded', function () { 38 39 /* 40 * Set data-high-res-src attribute for image, if there is a link with a href to an image. 41 * <a href="hi-res-image1.png"><img id="image" src="image1.png" data-high-res-src="hi-res-image1.png"></a> 42 */ 43 document.querySelectorAll( 'a' ).forEach( a_element => { 44 45 var href = a_element.getAttribute( 'href' ); 46 if ( ! href ) { 47 href = toString( '' ); 48 } 49 50 if ( href.length > 0 ) { 51 // Use test_href and remove ?get parameters from test_href so we can check for image url. 52 var test_href = href; 53 var test_href_match = test_href.match(/\?(.*)?$/i); 54 if ( test_href_match != null ) { 55 test_href = test_href.replace(test_href_match[0], ''); 56 } 57 58 // Check if it links to an image. 59 if ( test_href.match(/.(jpg|jpeg|png|gif|webp|heif|heifs|heic|heics|avci|avcs|hif|avif|JPG|JPEG|PNG|GIF|WEBP|HEIF|HEIFS|HEIC|HEICS|AVCI|AVCS|HIF|AVIF)$/i)) { 60 61 const img = a_element.querySelector( 'img' ); 62 if ( typeof img !== 'undefined' ) { 63 // Do not overwrite data that is already there. 64 var high_res_src = img.getAttribute( 'data-high-res-src' ); 65 if ( ! high_res_src ) { 66 img.setAttribute( 'data-high-res-src', href ); 67 } 68 69 // Catch keycodes. 70 document.body.addEventListener( 'keyup', function(e) { 71 if ( e.keyCode == 13 ) { // Enter key to open viewer. 72 iv_show_image_from_enter( img ); 73 } 74 if ( e.keyCode == 27 ) { // Esc key to close viewer. 75 iv_hide_viewer(); 76 } 77 }); 78 79 // Make sure we don't follow the href on a click event. 80 a_element.addEventListener( 'click', function (e) { 81 event.preventDefault(); 82 }); 83 } 84 85 } 86 } 87 88 }); 89 90 91 /* 92 * Catch keycodes. 93 */ 94 document.body.addEventListener( 'keyup', function(e) { 95 if ( e.key === 'Escape' ) { 96 iv_hide_viewer(); 97 } else if ( e.keyCode == 39 ) { // Arrow key. 98 if ( iv_is_viewer_active() == false ) { 99 return; 100 } 101 iv_show_image_prev(); 102 } else if ( e.keyCode == 37 ) { // Arrow key. 103 if ( iv_is_viewer_active() == false ) { 104 return; 105 } 106 iv_show_image_next(); 107 } 108 }); 109 110 111 /* 112 * Collect array of images and feed it to the monster. 113 * <img id="image" src="image1.png" data-high-res-src="hi-res-image1.png"> 114 * images is an array. 115 * each item is an object: { small: high_res_src, big: high_res_src, alt: alt } 116 * each image gets a click event to show the image on click. 117 */ 118 var images = []; 119 120 document.querySelectorAll( 'img' ).forEach( img => { 121 122 var src = img.getAttribute( 'src' ); 123 if ( ! src ) { 124 src = ''; 125 } 126 var high_res_src = img.getAttribute( 'data-high-res-src' ); 127 if ( ! high_res_src ) { 128 high_res_src = ''; 129 } 130 var alt = img.getAttribute( 'alt' ); 131 if ( ! alt ) { 132 alt = ''; 133 } 134 135 if ( src.length > 0 && high_res_src.length > 0 ) { 136 // Set src to main image, not thumbnails. Some thumbnails have a hard crop and aspect ratio goes wrong. 137 images.push({ small: high_res_src, big: high_res_src, alt: alt }); 138 var this_image = images.length; 139 140 img.addEventListener( 'click', function (e) { 141 iv_show_image( this_image ); 142 }); 143 } 144 145 }); 146 147 148 var options = {}; 149 if ( typeof imageviewer_custom_options === 'object' ) { 150 options = imageviewer_custom_options; 151 } 152 var viewer = new ImageViewer.FullScreenViewer( options ); 153 154 var current_image = 1; 155 var total = images.length; 156 157 158 // Add navigation and description. 159 const iv_container = document.querySelector( '.iv-container' ); 160 if ( iv_container ) { 161 iv_container.insertAdjacentHTML( 'beforeend', '<div class="iv-prev"></div><div class="iv-next"></div>' ); 162 } 163 const iv_image_wrap = document.querySelector( '.iv-image-wrap' ); 164 if ( iv_image_wrap ) { 165 iv_image_wrap.insertAdjacentHTML( 'beforeend', '<div class="iv-description"><span class="iv-total"></span> <span class="iv-img-alt"></span></div>' ); 166 } 167 const iv_total = document.querySelector( '.iv-total' ); 168 if ( iv_total ) { 169 iv_total.innerHTML = total; 170 } 171 172 173 /* 174 * Click events for navigation buttons. 175 */ 176 const iv_next = document.querySelector( '.iv-next' ); 177 if ( iv_next ) { 178 iv_next.addEventListener( 'click', function (e) { 179 iv_show_image_prev(); 180 }); 181 } 182 const iv_prev = document.querySelector( '.iv-prev' ); 183 if ( iv_prev ) { 184 iv_prev.addEventListener( 'click', function (e) { 185 iv_show_image_next(); 186 }); 187 } 188 189 function iv_show_image_prev() { 190 if ( iv_is_viewer_active() == false ) { 191 return; 192 } 193 current_image++; 194 if (current_image > total) { 195 current_image = 1; 196 } 197 iv_show_image( current_image ); 198 } 199 200 function iv_show_image_next() { 201 if ( iv_is_viewer_active() == false ) { 202 return; 203 } 204 current_image--; 205 if (current_image == 0) { 206 current_image = total; 207 } 208 iv_show_image( current_image ); 209 } 210 211 /* 212 * Show the image in the viewer. Used by the click and keyboard events. 213 * @param int this_image integer where it is located in the images array (-1). 214 */ 215 function iv_show_image( this_image ) { 216 current_image = this_image; 217 var image_object = images[current_image - 1]; // array starts at 0, current_image starts at 1. 218 viewer.show( image_object.small, image_object.big ); 219 220 iv_total.innerHTML = current_image + '/' + total + ' '; 221 const iv_img_alt = document.querySelector( '.iv-img-alt' ); 222 iv_img_alt.innerHTML = ' ' + image_object.alt; 223 } 224 225 function iv_show_image_from_enter( img_obj ) { 226 var high_res_src = img_obj.getAttribute( 'data-high-res-src' ); 227 for ( i=0; i < images.length; i++ ) { 228 var img_big = images[i].big; 229 if ( high_res_src == img_big ) { 230 iv_show_image( i + 1 ); 231 return; 232 } 233 } 234 } 235 236 function iv_hide_viewer() { 237 if ( iv_is_viewer_active() == false ) { 238 return; 239 } 240 viewer.hide(); 241 } 242 243 function iv_is_viewer_active() { 244 const viewer = document.querySelector( 'div.iv-fullscreen' ); 245 var display = viewer.style.display; 246 if ( typeof display == 'undefined' || display == 'none' || display == '' ) { 247 return false;
248 } else { 249 return true; 250 } 251 } 252 253 function iv_get_zoom() { 254 var zoom = parseInt( viewer._state.zoomValue ); 255 return zoom; 256 } 257 258 /* 259 * Touch events for navigation swipes. 260 */ 261 var startx = null; 262 var distx = null; 263 264 onTouchStart = function(el) { 265 var touchobj = el.originalEvent.changedTouches[0]; // reference first touch point (ie: first finger) 266 startx = parseInt(touchobj.clientX); // get x position of touch point relative to left edge of browser 267 268 if ( el.originalEvent.touches.length > 1 ) { 269 // We have multitouch, probably for zoom. Reset everything and do nothing. 270 startx = null; 271 distx = null; 272 return; 273 } 274 275 //el.originalEvent.preventDefault(); // No need to prevent clicks. 276 }; 277 if ( iv_container ) { 278 iv_container.addEventListener( 'touchstart', onTouchStart ); 279 } 280 281 onTouchEnd = function(el) { 282 if ( startx == null ) { 283 return; 284 } 285 286 var zoom = iv_get_zoom(); 287 if ( zoom > 100 ) { 288 return; 289 } 290 291 var width = parseInt( document.querySelector( '.iv-container' ).offsetWidth ); 292 var touchobj = el.originalEvent.changedTouches[0]; // reference first touch point (ie: first finger) 293 distx = parseInt(touchobj.clientX) - startx; 294 295 if ( distx > 0 ) { 296 var perc = parseInt( ( distx / width ) * 80); 297 if ( ( perc > 5 ) || ( distx > 100 ) ) { 298 iv_show_image_next(); 299 } 300 } 301 if ( distx < 0 ) { 302 distx = Math.abs(distx); 303 var perc = parseInt( ( distx / width ) * 80); 304 if ( ( perc > 5 ) || ( distx > 100 ) ) { 305 iv_show_image_prev(); 306 } 307 } 308 309 startx = null; 310 distx = null; 311 //el.originalEvent.preventDefault(); // No need to prevent clicks. 312 }; 313 if ( iv_container ) { 314 iv_container.addEventListener( 'touchend', onTouchEnd ); 315 } 316 317});
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.