1class RoomviewModal { 2 3 modal = null; 4 active = false; 5 outside = null; 6 background = null; 7 hideTimer = null; 8 desktopViewport = null; 9 constructor(id) { 10 11 const self = this; 12 self.modal = document.querySelector(`#roomview-modal-${id}`); 13 // Escape stacking contexts created by Roomview's transformed containers. 14 document.body.appendChild(self.modal); 15 self.outside = self.modal.querySelector('.roomview-outside'); 16 self.modal.show = self.show.bind(this) 17 self.background = self.modal.querySelector('.roomview-background'); 18 self.active = self.modal.style.display !== 'none'; 19 self.desktopViewport = window.matchMedia('(min-width: 768px)'); 20 self.updateContent = self.updateContent.bind(self); 21 self.desktopViewport.addEventListener('change', self.updateContent); 22 self.updateContent(); 23 24 self.modal.addEventListener("touchstart", self.innerScroll, {passive: false}); 25 self.modal.addEventListener("touchmove", self.innerScroll, {passive: false}); 26 self.modal.addEventListener("touchend", self.innerScroll, {passive: false}); 27 self.modal.addEventListener("wheel", self.innerScroll, {passive: false}); 28 29 self.background.addEventListener("touchstart", self.dropAction, {passive: false}); 30 self.background.addEventListener("touchmove", self.dropAction, {passive: false}); 31 self.background.addEventListener("touchend", self.dropAction, {passive: false}); 32 self.background.addEventListener("wheel", self.dropAction, {passive: false}); 33 34 document.body.addEventListener("keyup", self.listen.bind(this)); 35 36 self.modal.addEventListener("click", self.click.bind(this)); 37 self.modal.addEventListener('click', function (e) { 38 if (e.target.classList.contains('roomview-modal-closer')) { 39 self.hide(); 40 } 41 }) 42 43 } 44 45 show() { 46 const self = this; 47 self.updateContent(); 48 clearTimeout(self.hideTimer); 49 self.modal.classList.add("roomview-modal-hide"); 50 self.modal.style.display = 'block'; 51 setTimeout(() => self.modal.classList.remove("roomview-modal-hide"), 10) 52 self.active = true; 53 } 54 55 updateContent() { 56 const desktop = this.modal.querySelector('[data-roomview-text-id="11724"]'); 57 const mobile = this.modal.querySelector('[data-roomview-text-id="12877"]'); 58 const showDesktop = this.desktopViewport.matches; 59 60 // Also override conflicting theme rules and outdated responsive CSS. 61 for (const [element, visible] of [[desktop, showDesktop], [mobile, !showDesktop]]) { 62 if (element) { 63 element.hidden = !visible; 64 element.style.setProperty('display', visible ? 'block' : 'none', 'important'); 65 } 66 } 67 } 68 69 dropAction (e) { 70 e.preventDefault(); 71 e.stopPropagation(); 72 } 73 74 innerScroll (e) { 75 const target = e.currentTarget.querySelector('.roomview-modal-body'); 76 const scrollTop = target.scrollTop; 77 const scrollHeight = target.scrollHeight; 78 const targetHeight = target.clientHeight; 79 const atTop = scrollTop === 0 && e.deltaY < 0; 80 const atBottom = scrollTop + targetHeight + 2 >= scrollHeight && e.deltaY > 0; 81 const outside = e.target.classList.contains('roomview-outside'); 82 if (atTop || atBottom || outside) { 83 e.preventDefault(); 84 } 85 e.stopPropagation(); 86 } 87 88 hide () { 89 const self = this; 90 clearTimeout(self.hideTimer); 91 self.modal.classList.add("roomview-modal-hide"); 92 self.hideTimer = setTimeout(() => self.modal.style.display = 'none', 450) 93 self.active = false; 94 } 95 96 listen(e) { 97 98 if(e.key === 'Escape') { 99 if(this.active) { 100 this.hide(); 101 } 102 } 103 } 104 105 click(e) { 106 const self = this; 107 if(e.target === self.outside) { 108 self.hide(); 109 } 110 } 111 112} 113 114 115 116
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.