1"use strict"; 2 3/* 4 Interactivity for L layout elements 5*/ 6 7window.Lview = { 8 gallery: { 9 // !!! NOTE !!! if there's a weird random image size error in galleries, it may be because the width is set to something like XX.00000000001, which CSS rejects because it's too long. If that happens, more meticulous parsing of the number is required. 10 popup_currentGallery: 0, 11 popup_currentImage: 0, 12 popup_initialized: false, 13 get_popup_window: function () { 14 let popup = D.ID("gallerypopup"); 15 if (popup) return popup; 16 17 function close (event) { 18 let popup = this; 19 popup.classList.remove("visible"); 20 setTimeout(function(){if (!popup.classList.contains("visible")) REMOVE(popup);},500); 21 } 22 function prev (event) { 23 event.stopPropagation(); 24 Lview.gallery.popup_flip(-1); 25 } 26 function next (event) { 27 event.stopPropagation(); 28 Lview.gallery.popup_flip(1); 29 } 30 function info (event) { 31 event.preventDefault(); 32 event.stopPropagation(); 33 let popup = D.ID("popup"); 34 let infocontainer = popup.CLASS("infocontainer"); 35 if (infocontainer.className.indexOf("opened") >= 0) { 36 infocontainer.classList.remove("opened"); 37 } 38 else { 39 infocontainer.classList.add("opened"); 40 41 infocontainer.innerHTML = STRING(Lview.gallery.popup_currentImage.dataset.caption); 42 } 43 return false; 44 } 45 46 popup = CREATE("div", {id:"popup", className:"popup", event:["click", close]}, [ 47 CREATE("div", {className:"imagecontainer"}), 48 CREATE("div", {className:"prev", event:["click", prev], innerHTML:'<img src="'+wpinfo.url_template+'/res/icon_left.svg">'}), 49 CREATE("div", {className:"info", event:["click", info], innerHTML:'<img src="'+wpinfo.url_template+'/res/icon_info.png">'}), 50 CREATE("div", {className:"next", event:["click", next], innerHTML:'<img src="'+wpinfo.url_template+'/res/icon_right.svg">'}), 51 CREATE("div", {className:"infocontainer", event:["click", info]}), 52 ]); 53 D.body.appendChild(popup); 54 return popup; 55 }, 56 popup_flip: function (pos) { 57 // find next image 58 let img = Lview.gallery.popup_currentImage; 59 if (pos > 0) { 60 img = img.nextSibling; 61 if (!img) { 62 img = Lview.gallery.popup_currentImage.parentNode.CLASS("L-galleryimage"); 63 } 64 } 65 else if (pos < 0) { 66 img = img.previousSibling; 67 if (!img) { 68 img = Lview.gallery.popup_currentImage.parentNode.CLASSES("L-galleryimage").LAST(); 69 } 70 } 71 Lview.gallery.popup_currentImage = img; 72 73 // transition images 74 let popup = D.ID("popup"); 75 let imagecontainer = popup.CLASS("imagecontainer"); 76 let old = imagecontainer.CLASS("current"); 77 old.classList.remove("current"); 78 let newimg = imagecontainer.appendChild(CREATE("img", {src:img.href, className:"current"})); 79 if (pos > 0) { 80 newimg.classList.add("inright"); 81 if (old) old.classList.add("outleft"); 82 } 83 else { 84 newimg.classList.add("inleft"); 85 if (old) old.classList.add("outright"); 86 } 87 setTimeout(function(){REMOVE(old);}, 1000); 88 89 // caption 90 let infocontainer = popup.CLASS("infocontainer"); 91 if (img.dataset.caption) { 92 infocontainer.innerHTML = img.dataset.caption; 93 popup.classList.remove("nocaption"); 94 } 95 else { 96 infocontainer.innerHTML = ""; 97 popup.classList.add("nocaption"); 98 } 99 }, 100 popup_initItem: function (item) { 101 function imageClicked(event) { 102 event.preventDefault(); 103 event.stopPropagation(); 104 105 Lview.gallery.popup_currentGallery = this.PWC("L-type-gallery"); 106 Lview.gallery.popup_currentImage = this; 107 108 let popup = Lview.gallery.get_popup_window(); 109 110 let imagecontainer = popup.CLASS("imagecontainer"); 111 imagecontainer.innerHTML = ""; 112 if (this.dataset.iframe) { 113 imagecontainer.appendChild(CREATE("iframe", {src:this.href, className:"current"})); 114 } 115 else { 116 imagecontainer.appendChild(CREATE("img", {src:this.href, className:"current"})); 117 } 118 119 if (Lview.gallery.popup_currentGallery && Lview.gallery.popup_currentGallery.CLASSES("L-galleryimage").length > 1) { 120 popup.classList.add("canflip"); 121 } 122 else { 123 popup.classList.remove("canflip"); 124 } 125 // info 126 if (this.dataset.caption) { 127 popup.classList.remove("nocaption"); 128 } 129 else { 130 popup.classList.add("nocaption"); 131 } 132 133 // open popup display 134 requestAnimationFrame(function(){ 135 requestAnimationFrame(function(){ 136 requestAnimationFrame(function(){ 137 popup.classList.add("visible"); 138 }); 139 }); 140 }); 141 return false;
142 } 143 item.addEventListener("click", imageClicked); 144 }, 145 popup_init: function (gallery) { 146 // handle galleries 147 let items = gallery.CLASSES("L-galleryimage"); 148 for (let item of items) { 149 Lview.gallery.popup_initItem(item); 150 } 151 }, 152 153 carousel_containers: [], 154 carousel_lastTime: 0, 155 carousel_looping: false, 156 carousel_loop: function() { 157 // loop through swapboxes, and switch the image if needed 158 let now = Date.now(); 159 // var delta = now - scrolldisp.lasttime; 160 let delta = Math.min(1000, now - Lview.gallery.carousel_lastTime); 161 Lview.gallery.carousel_lastTime = now; 162 for (let me of Lview.gallery.carousel_containers) { 163 let cInner = me.element.CLASS("L-carouselinner"); 164 let cContents = me.element.CLASS("L-carouselcontents"); 165 166 if (me.hovering) { 167 me.spdmod = Math.max(0, me.spdmod-0.05); 168 } 169 else{ 170 me.spdmod = Math.min(1, me.spdmod+0.033); 171 } 172 // move things 173 me.posoffset -= me.speed*delta/1000*me.spdmod, 174 175 cInner.style.left = Math.floor(me.posoffset) + "px"; 176 177 // figure out if elements need to be deleted from front 178 let innerNodes = cInner.CLASSES("L-galleryimage"); 179 let contentNodes = cContents.CLASSES("L-galleryimage"); 180 if (innerNodes[0].getBoundingClientRect().right < me.element.getBoundingClientRect().left) { 181 me.posoffset = me.posoffset + innerNodes[0].offsetWidth; 182 cInner.style.left = Math.floor(me.posoffset) + "px"; 183 184 cInner.appendChild(innerNodes[0]); 185 } 186 187 // fill displaycontainer if empty space has become visible 188 let failsafe = 32; 189 innerNodes = cInner.CLASSES("L-galleryimage"); 190 while ( 191 innerNodes.length === 0 || 192 innerNodes[innerNodes.length-1].getBoundingClientRect().right < me.element.getBoundingClientRect().right 193 ) { 194 // add nodes 195 for (let n=0; n<contentNodes.length; n++) { 196 let theelement = contentNodes[n].cloneNode(true); 197 cInner.appendChild(theelement); 198 Lview.gallery.popup_initItem(theelement); 199 } 200 201 failsafe --; 202 if (failsafe < 0) break; 203 innerNodes = cInner.CLASSES("L-galleryimage"); 204 } 205 } 206 requestAnimationFrame(Lview.gallery.carousel_loop); 207 }, 208 carousel_init: function (container) { 209 Lview.gallery.carousel_lastTime = Date.now(); 210 211 let cc = container.CLASSES("L-galleryimage"); 212 if (cc.length) { 213 let cContents = CREATE("div", {className:"L-carouselcontents"}); 214 let cInner = CREATE("div", {className:"L-carouselinner"}); 215 for (let c of cc) { 216 cContents.appendChild(c); 217 } 218 container.appendChild(cInner); 219 container.appendChild(cContents); 220 let me = { 221 element: container, 222 speed: (!isNaN(Number(container.dataset.carouselspeed))) ? Number(container.dataset.carouselspeed) : 0, // scrolling speed 223 posoffset: 0, // automatic 224 hovering: false, // automatic 225 spdmod: 1 // automatic 226 }; 227 Lview.gallery.carousel_containers.push(me); 228 229 // setup events and id 230 container.dataset.id = Lview.gallery.carousel_containers.length-1; 231 container.addEventListener("mouseover", function() { 232 let myid = Number(this.dataset.id); 233 Lview.gallery.carousel_containers[myid].hovering = true; 234 }); 235 container.addEventListener("mouseout", function() { 236 let myid = Number(this.dataset.id); 237 Lview.gallery.carousel_containers[myid].hovering = false; 238 }); 239 240 // fill displaycontainer, add every node, then add every node again if there's space left, repeat until full 241 let failsafe = 32; 242 let innerNodes = cInner.CLASSES("L-galleryimage"); 243 let contentNodes = cContents.CLASSES("L-galleryimage"); 244 while ( 245 innerNodes.length === 0 || 246 innerNodes[innerNodes.length-1].getBoundingClientRect().right < container.getBoundingClientRect().right 247 ) { 248 // add nodes 249 for (let cn of contentNodes) { 250 let theelement = cn.cloneNode(true); 251 cInner.appendChild(theelement); 252 Lview.gallery.popup_initItem(theelement); 253 } 254 255 failsafe --; 256 if (failsafe < 0) break; 257 innerNodes = cInner.CLASSES("L-galleryimage"); 258 } 259 } 260 261 // start loop 262 if (!Lview.gallery.carousel_looping) { 263 Lview.gallery.carousel_looping = true; 264 requestAnimationFrame(Lview.gallery.carousel_loop); 265 } 266 }, 267 268 fit_refreshSquares: function (gallery) { 269 let images = gallery.CLASSES("L-galleryimage"); 270 if (!images.length) return; 271 272 let idealHeight = Number(gallery.dataset.height) || 200; 273 let padding = parseFloat(window.getComputedStyle(images[0], null).paddingLeft); 274 let containerWidth = gallery.offsetWidth; 275 //containerWidth -= parseFloat(window.getComputedStyle(gallery, null).paddingLeft) * 2; 276 277 let sideBySideAmount = Math.max(1, Math.round(containerWidth / (idealHeight+padding*2))); 278 let size = 1/sideBySideAmount*100; 279 280 for (let img of images) { 281 img.style.width = size+"%"; 282 } 283 }, 284 fit_refresh: function (gallery) { 285 let images = gallery.CLASSES("L-galleryimage"); 286 if (!images.length) return; 287 288 let idealHeight = Number(gallery.dataset.height) || 200; 289 let padding = parseFloat(window.getComputedStyle(images[0], null).paddingLeft)*2; 290 let containerWidth = gallery.offsetWidth; 291 //containerWidth -= parseFloat(window.getComputedStyle(gallery, null).paddingLeft) * 2; 292 293 for (let i=0; i<images.length; ) { 294 let rowWidth = 0; 295 let ri = i; 296 297 // find which images belong to row 298 for (ri; ri<images.length; ri++) { 299 let img = images[ri]; 300 let ratio = Number(img.dataset.r); 301 302 let targetOuterWidth = idealHeight*ratio + padding; 303 304 if (rowWidth + targetOuterWidth > containerWidth) { // this image crosses the container width 305 // if image width is more than ideal height (can and maybe should use some other value as the limit), skip this image 306 if ( rowWidth > 0 && containerWidth - rowWidth < idealHeight+padding ) { 307 // skip this image (use for the next row) 308 ri --; 309 } 310 else { 311 // use this image in this row 312 rowWidth += targetOuterWidth+padding; 313 } 314 break; 315 } 316 rowWidth += targetOuterWidth+padding; 317 if (ri === images.length-1) break; 318 } 319 let rowImageCount = ri-i+1; 320 let spaceLeft = containerWidth - rowWidth; 321 let spaceForImages = containerWidth - rowImageCount*padding; 322 323 // special case for last row, which is too short to be stretched. 324 if (ri == images.length-1 && Math.abs(spaceLeft) > idealHeight*1.5) { 325 for (let iii=i; iii<ri+1; iii++) { 326 let img = images[iii]; 327 let inner = img.TAG("img"); 328 let ratio = Number(img.dataset.r); 329 330 let finalWidth = idealHeight*ratio; 331 332 let w = Math.floor((finalWidth/spaceForImages*100) * 1000)/1000; 333 img.style.width = "calc("+ w + "% + "+padding+"px)"; 334 335 // set height (same for all items in this row) 336 inner.style.height = idealHeight+"px"; 337 } 338 } 339 else { 340 // find average ratio 341 let ratioAvg = 0; 342 for (let iii=i; iii<ri+1; iii++) { 343 let img = images[iii]; 344 let ratio = Number(img.dataset.r); 345 ratioAvg += ratio; 346 } 347 ratioAvg /= rowImageCount; 348 349 // solve final size 350 let sharedHeight = 0; 351 let usedWidth = 0; 352 for (let iii=i; iii<ri+1; iii++) { 353 let img = images[iii]; 354 let inner = img.TAG("img"); 355 let ratio = Number(img.dataset.r); 356 357 let finalWidth = spaceForImages/rowImageCount*(ratio/ratioAvg); 358 359 let dw = 0;
360 if (iii < ri) { 361 dw = Math.round(finalWidth + padding); 362 } 363 else { 364 // do special trick to figure out size of last item, makes it less likely to be 1px too big or something and then wrap 365 dw = containerWidth-Math.ceil(usedWidth); 366 } 367 usedWidth += dw; 368 let w = Math.floor((dw/containerWidth*100) * 1000)/1000; 369 img.style.width = w + "%"; 370 371 // set height (same for all items in this row) 372 if (!sharedHeight) sharedHeight = Math.round(finalWidth/ratio); 373 inner.style.height = sharedHeight+"px"; 374 } 375 } 376 i += rowImageCount; 377 } 378 }, 379 fit_init: function (gallery) { 380 if (gallery.classList.contains("L-gshape-square")) { 381 let images = gallery.CLASSES("L-galleryimage"); 382 for (let img of images) { 383 let inner = img.CLASS("arbox"); 384 inner.style.width = "100%"; 385 inner.style.height = ""; 386 } 387 } 388 else if (gallery.classList.contains("L-gshape-default")) { 389 let images = gallery.CLASSES("L-galleryimage"); 390 for (let img of images) { 391 let inner = img.TAG("img"); 392 let w = NUMBER(img.dataset.w); 393 let h = NUMBER(img.dataset.h); 394 if (!w || !h) { 395 w = 10; 396 h = 10; 397 } 398 img.dataset.r = w/h; 399 } 400 401 Lview.gallery.fit_refresh(gallery); 402 } 403 }, 404 fit_carousel_init: function (gallery) { 405 let idealHeight = Number(gallery.dataset.height) || 200; 406 if (gallery.classList.contains("L-gshape-square")) { 407 let images = gallery.CLASSES("L-galleryimage"); 408 for (let img of images) { 409 let inner = img.CLASS("arbox"); 410 inner.style.width = "100%"; 411 inner.style.height = ""; 412 } 413 } 414 else if (gallery.classList.contains("L-gshape-default")) { 415 let images = gallery.CLASSES("L-galleryimage"); 416 for (let img of images) { 417 let inner = img.TAG("img"); 418 let w = NUMBER(img.dataset.w); 419 let h = NUMBER(img.dataset.h); 420 if (!w || !h) { 421 w = 10; 422 h = 10; 423 } 424 img.dataset.r = w/h; 425 inner.style.height = Math.round(idealHeight) + "px"; 426 inner.style.width = Math.round(idealHeight * (w/h)) + "px"; 427 } 428 } 429 }, 430 431 init: function (container) { 432 let galleries = container.CLASSES("L-type-gallery"); 433 for (let gallery of galleries) { 434 if (gallery.classList.contains("L-gsize-fit") && !gallery.classList.contains("L-gallerycarousel")) { 435 Lview.gallery.fit_init(gallery); 436 } 437 else if (gallery.classList.contains("L-gsize-fit") && gallery.classList.contains("L-gallerycarousel")) { 438 Lview.gallery.fit_carousel_init(gallery); 439 } 440 if (gallery.classList.contains("L-gallerypopup")) { 441 Lview.gallery.popup_init(gallery); 442 } 443 if (gallery.classList.contains("L-gallerycarousel")) { 444 Lview.gallery.carousel_init(gallery); 445 } 446 } 447 448 function fitAll() { 449 let galleries = D.CLASSES("L-gsize-fit"); 450 for (let gallery of galleries) { 451 if (!gallery.classList.contains("L-gallerycarousel")) { 452 if (gallery.classList.contains("L-gshape-square")) { 453 Lview.gallery.fit_refreshSquares(gallery); 454 } 455 else { 456 Lview.gallery.fit_refresh(gallery); 457 } 458 } 459 } 460 } 461 requestAnimationFrame(fitAll); 462 window.addEventListener("resize", function(){ 463 requestAnimationFrame(fitAll); 464 }); 465 466 // handle popup for stray images 467 let pics = container.CLASSES("indipop"); 468 for (let pic of pics) { 469 Lview.gallery.popup_initItem(pic); 470 } 471 } 472 }, 473 picswitcher: { 474 currentgallery: 0, 475 currentimage: 0, 476 idcounter: 0, 477 switchers: [], 478 looping: false, 479 switchTo: function(container, node) { 480 // set fadeouts 481 let items = container.element.CLASSES("L-switcherimage"); 482 let nodeindex = 0; 483 for (let i=0; i<items.length; i++) { 484 let item = items[i]; 485 // previously faded in (i.e. currently visible) gets faded out 486 if (item.classList.contains("L-picswitcherfadein") || item.classList.contains("L-picswitcherfadeinitial")) { 487 item.classList.add("L-picswitcherfadeout"); 488 item.classList.remove("L-picswitcherfadenone"); 489 item.classList.remove("L-picswitcherfadein"); 490 item.classList.remove("L-picswitcherfadeinitial"); 491 } 492 else { 493 item.classList.add("L-picswitcherfadenone"); 494 item.classList.remove("L-picswitcherfadein"); 495 item.classList.remove("L-picswitcherfadeout"); 496 } 497 if (item === node) nodeindex = i; // for button 498 } 499 // target image gets faded in 500 node.classList.remove("L-picswitcherfadenone"); 501 node.classList.remove("L-picswitcherfadeout"); 502 node.classList.add("L-picswitcherfadein"); 503 504 // mod buttons 505 items = container.element.CLASSES("button"); 506 for (let i=0; i<items.length; i++) { 507 items[i].classList.remove("active"); 508 } 509 items[nodeindex].classList.add("active"); 510 511 if (node.dataset.isvideo) {
512 node.dataset.finished = 0; 513 let v = node.TAG("video"); 514 v.play(); 515 } 516 if (container.current.dataset.isvideo) { 517 let v = container.current.TAG("video"); 518 v.pause(); 519 } 520 521 container.current = node; 522 container.swaptime = Date.now(); 523 }, 524 swapLoop: function(container) { 525 // loop through swapboxes, and switch the image if needed 526 for (let c=0; c<Lview.picswitcher.switchers.length; c++) { 527 let switcher = Lview.picswitcher.switchers[c]; 528 if (D.hidden) { 529 switcher.swaptime = Date.now() - switcher.swapdelay/2; 530 } 531 else if (switcher.current.dataset.isvideo) { 532 if (switcher.current.dataset.finished == 1) { 533 switcher.current.dataset.finished = 0; 534 let v = switcher.current.TAG("video"); 535 v.pause(); 536 537 let next = switcher.current.nextSibling; 538 while (next && (!next.tagName || !next.classList.contains("L-switcherimage"))) { 539 next = next.nextSibling; 540 } 541 if (!next) { 542 next = switcher.current.parentNode.CLASS("L-switcherimage"); 543 } 544 Lview.picswitcher.switchTo(switcher, next); 545 } 546 } 547 else if (switcher.autoswap && switcher.swaptime+switcher.swapdelay < Date.now()) { 548 let next = switcher.current.nextSibling; 549 while (next && (!next.tagName || !next.classList.contains("L-switcherimage"))) { 550 next = next.nextSibling; 551 } 552 if (!next) { 553 next = switcher.current.parentNode.CLASS("L-switcherimage"); 554 } 555 556 Lview.picswitcher.switchTo(switcher, next); 557 } 558 }; 559 requestAnimationFrame(Lview.picswitcher.swapLoop); 560 }, 561 initSwitcher: function(gallery) { 562 let items = gallery.CLASSES("L-switcherimage"); 563 let buttoncontainer = gallery.CLASS("L-picswitcherbuttons"); 564 if (!buttoncontainer) gallery.appendChild(CREATE("div", {className:"L-picswitcherbuttons"})); 565 for (let i=0; i<items.length; i++) { 566 // handle video 567 let v = items[i].TAG("video"); 568 if (v) { 569 // v.loop = 0; 570 items[i].dataset.isvideo = 1; 571 v.addEventListener('ended',function(){ 572 this.parentNode.dataset.finished = 1; 573 this.play(); 574 }); 575 if (i == 0) { 576 v.addEventListener('loadeddata', function(){ 577 this.play(); 578 }); 579 } 580 } 581 // crate button for me 582 let button = buttoncontainer.appendChild( 583 CREATE("div", {className:"button", style:{width:(1/items.length*100)+"%"}, dataset:{id:i, switcher:Lview.picswitcher.switchers.length}, event:["click", function() { 584 let item = this.PWC("L-picswitcher").CLASSES("L-switcherimage")[Number(this.dataset.id)]; 585 let container = Lview.picswitcher.switchers[Number(this.dataset.switcher)]; 586 Lview.picswitcher.switchTo(container, item); 587 }]}) 588 ); 589 // set classes 590 let item = items[i]; 591 if (i === 0) { 592 button.classList.add("active"); 593 } 594 } 595 let swapdelay = Number(gallery.dataset.swapdelay) || 5000; 596 let autoswap = Number(gallery.dataset.autoswap); 597 if (isNaN(autoswap)) autoswap = false; 598 let foo = { 599 element: gallery, 600 swaptime: Date.now(), 601 swapdelay: swapdelay, 602 autoswap: autoswap, 603 current: items[0] 604 }; 605 Lview.picswitcher.switchers.push(foo); 606 if (items.length <= 1) { 607 // disable swapper since there's only 1 element 608 foo.autoswap = false; 609 buttoncontainer.style.display = "none"; 610 } 611 612 // start loop 613 if (!Lview.picswitcher.looping) { 614 Lview.picswitcher.looping = true; 615 requestAnimationFrame(Lview.picswitcher.swapLoop); 616 } 617 }, 618 init: function(container) { 619 let galleries = container.CLASSES("L-picswitcher"); 620 for (let g=0; g<galleries.length; g++) { 621 Lview.picswitcher.initSwitcher(galleries[g]); 622 } 623 } 624 }, 625 dropboxes: { 626 initDropbox: function(dropbox) { 627 dropbox.classList.add("closed"); 628 dropbox.CLASS("L-dropboxcontent").style.height = "0"; 629 dropbox.CLASS("L-dropboxtitle").addEventListener("click", function() { 630 let dropbox = this.PWC("L-dropbox"); 631 if (dropbox.classList.contains("closed")) { 632 // open 633 dropbox.classList.remove("closed"); 634 635 let content = dropbox.CLASS("L-dropboxcontent"); 636 content.style = "height:auto;transition:none;"; 637 let h = content.offsetHeight; 638 content.style = "height:0;transition:none;"; 639 // I hate the web so fucking much 640 requestAnimationFrame(function() { 641 requestAnimationFrame(function() { 642 requestAnimationFrame(function() { 643 content.style = "height:0;"; 644 requestAnimationFrame(function() { 645 requestAnimationFrame(function() { 646 requestAnimationFrame(function() { 647 content.style = "height:"+h+"px;"; 648 }); 649 }); 650 }); 651 }); 652 }); 653 }); 654 setTimeout(function(){ 655 if (!dropbox.classList.contains("closed")) { 656 content.style.height = ""; 657 } 658 }, 1000); 659 } 660 else{ 661 // close
662 let content = dropbox.CLASS("L-dropboxcontent"); 663 content.style.height = content.offsetHeight + "px"; 664 // I hate the web so fucking much 665 requestAnimationFrame(function() { 666 requestAnimationFrame(function() { 667 requestAnimationFrame(function() { 668 dropbox.classList.add("closed"); 669 content.style.height = "0"; 670 }); 671 }); 672 }); 673 } 674 }); 675 }, 676 init: function(container) { 677 let droppers = container.CLASSES("L-dropbox"); 678 for (let dropper of droppers) { 679 Lview.dropboxes.initDropbox(dropper); 680 } 681 } 682 }, 683 init: function (container) { 684 Lview.gallery.init(container); 685 Lview.dropboxes.init(container); 686 Lview.picswitcher.init(container); 687 }, 688};
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.