1// Copyright (c) 2021-2025 GrayBits LLC 2 3import * as Builder from 'gray_matter/utility/builder' 4 5export default class{ 6 constructor(element, options = {}){ 7 this.element = element; 8 this.slide_class = options.slide_class || 'slide' 9 this.selector_wrapper_class = options.selector_wrapper_class || 'slide_selector_wrapper' 10 this.selector_class = options.selector_class || 'slide_selector' 11 this.slideSet = options.slide_set; 12 this.preSlideSet = options.pre_slide_set; 13 element.gm = this; 14 this.cycle = element.dataset.cycle; 15 this._previous_index = 0; 16 this.updateSlideElements(); 17 18 if (this.slide_selectors.length > 0 && this.n > 1){ 19 [].forEach.call(this.slides, 20 (slide, i) => { 21 [].forEach.call(this.slide_selectors, 22 (container) => { 23 container.appendChild(this.createSelectorButton(slide, i)); 24 }); 25 }); 26 } 27 this.updateSlides(0); 28 element.offsetHeight; 29 } 30 31 static init(element, options = {}) { 32 [].forEach.call((element ? element : document).querySelectorAll( 33 options.slideshow_class ? '.' + options.slideshow_class : '.slideshow'), 34 (slideshow) => { 35 if (!slideshow.gm){ 36 new this(slideshow, options); 37 } 38 } 39 ); 40 } 41 42 updateSlideElements(){ 43 this._slides = this.element.getElementsByClassName(this.slide_class); 44 this._slide_selectors = this.element.getElementsByClassName(this.selector_wrapper_class); 45 this._n = this._slides.length; 46 this.element.querySelectorAll('.current').forEach((s) => s.classList.remove('current')); 47 } 48 49 updateSlides(i){ 50 this.updateSlideElements(); 51 if (i == undefined){ 52 this.current = this._n - 1; 53 } else { 54 this.current = i; 55 } 56 57 this.empty = this.slides.length == 0; 58 } 59 60 get slides(){ 61 return this._slides; 62 } 63 64 get slide_selectors(){ 65 return this._slide_selectors; 66 } 67 68 createSelectorButton(slide, i){ 69 let html = ''; 70 if (slide.dataset.selectorLabel){ 71 html = slide.dataset.selectorLabel; 72 } else if (this.element.dataset.indexLabel){ 73 html = `Show slide ${i + 1}`; 74 } 75 76 return Builder.createElement('button', { 77 class: [this.selector_class], listeners: { click: () => { this.current = i } }, 78 html: html 79 }); 80 } 81 82 get current(){ 83 return this._current; 84 } 85 86 get n(){ 87 return this._n; 88 } 89 90 get previous_index(){ 91 return this._previous_index; 92 } 93 94 set current(i){ 95 i = i * 1; 96 if (!this.slides[i]) return; 97 98 if (this.preSlideSet){ 99 this.preSlideSet(); 100 }; 101 102 if (this.current_slide) this.current_slide.classList.remove('current'); 103 if (this.slide_selectors.length > 0 && this.n > 1){ 104 [].forEach.call(this.slide_selectors, 105 (container) => { 106 if (container.childElementCount == 0) return; 107 108 if (this.current != undefined){ 109 container.children[this.current].classList.remove('current'); 110 } 111 container.children[i].classList.add('current'); 112 }); 113 } 114 this._previous_index = this.current; 115 this._current = i; 116 this.slides[i].classList.add('current'); 117 118 if (this.slideSet){ 119 this.slideSet(); 120 }; 121 this.element.dispatchEvent(new CustomEvent('gm:slideset',{detail: {current: i, previous: this._previous_index}})); 122 } 123 124 get current_slide(){ 125 return this.slides[this.current]; 126 } 127 128 nextSlide(force){ 129 let new_slide; 130 if (this.cycle){ 131 new_slide = (this.current + 1) % this.n; 132 } else { 133 new_slide = Math.min(this.current + 1, this.n - 1); 134 } 135 this.current = new_slide; 136 } 137 138 previousSlide(force){ 139 let new_slide; 140 if (this.cycle){ 141 new_slide = (this.current + this.n - 1) % this.n; 142 } else { 143 new_slide = Math.max(this.current - 1, 0); 144 } 145 this.current = new_slide; 146 } 147};
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.