1class EventEmitter { 2 constructor() { 3 this.listeners = {}; 4 } 5 6 /** 7 * СлÑÑаÑÑ ÑобÑÑие 8 * @param {String} eventName Ðазвание ÑобÑÑÐ¸Ñ 9 * @param {Function} fn Callback 10 */ 11 on(eventName, fn = null) { 12 if (!fn) { 13 throw new Error('EventEmitter: callback is not provided') 14 } 15 16 this.listeners[eventName] = this.listeners[eventName] || []; 17 this.listeners[eventName].push({ 18 fn 19 }); 20 } 21 22 /** 23 * СлÑÑаÑÑ ÑобÑÑие один Ñаз 24 * @param {String} eventName Ðазвание ÑобÑÑÐ¸Ñ 25 * @param {Function} fn Callback 26 */ 27 once(eventName, fn = null) { 28 if (!fn) { 29 throw new Error('EventEmitter: callback is not provided') 30 } 31 32 this.listeners[eventName] = this.listeners[eventName] || []; 33 this.listeners[eventName].push({ 34 fn, 35 once: true 36 }); 37 } 38 39 /** 40 * ÐÑзваÑÑ ÑобÑÑие. ÐоÑле вÑзова бÑдÑÑ Ð·Ð°Ð¿ÑÑÐµÐ½Ñ Ð²Ñе обÑабоÑÑики ÑÑого ÑобÑÑÐ¸Ñ Ñ Ð¿ÐµÑеданнÑми паÑамеÑÑами 41 * @param {String} eventName Ðазвание ÑобÑÑÐ¸Ñ 42 * @param {...any} data ÐÑбÑе паÑамеÑÑÑ 43 */ 44 emit(eventName, ...data) { 45 if (this.listeners[eventName]) { 46 this.listeners[eventName].forEach(listener => { 47 listener.fn(...data); 48 49 if (listener.once) { 50 this.off(eventName, listener.fn); 51 } 52 }); 53 } 54 } 55 56 /** 57 * УбÑаÑÑ Ð²Ñе обÑабоÑÑики Ñ ÑобÑÑÐ¸Ñ 58 * @param {String} eventName Ðазвание ÑобÑÑÐ¸Ñ 59 * @param {Function} fn Callback 60 */ 61 off(eventName, fn = null) { 62 if (fn) { 63 this.listeners[eventName] = this.listeners[eventName] 64 .filter(listener => listener.fn !== fn); 65 } else { 66 this.listeners[eventName] = []; 67 } 68 } 69} 70 71const elementParamKey = Symbol(); 72const initKey = Symbol(); 73 74/** 75 * Get component instance from dom-element 76 * @param {Element} element 77 * @returns {Component} 78 */ 79function getComponent(element) { 80 return element[elementParamKey]; 81} 82 83window.getComponent = getComponent 84 85class Component extends EventEmitter { 86 static defaultParams = { 87 componentAttribute: 'data-component', 88 autobindExclude: [ 89 'constructor' 90 ] 91 } 92 93 /** 94 * ÐÐ»Ñ ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñа иÑполÑзÑеÑÑÑ ÑÑÐ¾Ñ Ð¼ÐµÑод 95 * @param {Element} el ÐоÑневой dom-ÑÐ»ÐµÐ¼ÐµÐ½Ñ 96 * @param {Object} params ÐаÑамеÑÑÑ 97 * @returns {Component} 98 */ 99 static create(el, params) { 100 const component = new this(el, params); 101 component[initKey](); 102 103 if (component.init) { 104 component.init(el, params); 105 } 106 107 return component; 108 } 109 110 /** 111 * СÑÑлка на getComponent 112 */ 113 static getComponent(element) { 114 return getComponent(element); 115 } 116 117 /** 118 * @param {Element} el 119 * @param {Object} params 120 */ 121 constructor(el, params) { 122 super(); 123 124 this.root = el; 125 this.rootEl = this.root; 126 this.userParams = params; 127 128 this.params = this._initParams(this.userParams); 129 this.namespace = this.root.getAttribute(this.params.componentAttribute); 130 this.root[elementParamKey] = this; 131 this._bindMethods(); 132 } 133 134 /** 135 * Соединение вÑÐµÑ Ð¿Ð°ÑамеÑÑов 136 * @param {Object} params 137 * @returns 138 */ 139 _initParams(params) { 140 return { 141 ...Component.defaultParams, 142 ...this.defaultParams, 143 ...this._getParamsFromElemenet(this.root), 144 ...params 145 } 146 } 147 148 /** 149 * ÐоÑÑаÑÑ Ð¿Ð°ÑамеÑÑÑ Ð¸Ð· json в ÑазмеÑке 150 * @param {Element} element 151 * @returns {Object} 152 */ 153 _getParamsFromElemenet(element) { 154 try { 155 return JSON.parse(element.getAttribute('data-component-params')); 156 } catch (e) { 157 throw new Error('Invalid component params json') 158 } 159 } 160 161 /** 162 * ÐвÑомаÑиÑеÑÐºÐ°Ñ Ð¿ÑивÑзка конÑекÑÑа к меÑодам компоненÑа 163 * ÐеÑод не пÑивÑзÑваеÑÑÑ, еÑли он Ñказан в маÑÑиве autobindExclude в паÑамеÑÑÐ°Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñа 164 */ 165 _bindMethods() { 166 Object.getOwnPropertyNames(Object.getPrototypeOf(this)).forEac
166h((property) => { 167 if ( 168 typeof this[property] == 'function' 169 && property !== 'constructor' 170 && !this.params.autobindExclude.includes(property) 171 ) { 172 this[property] = this[property].bind(this); 173 } 174 }); 175 } 176 177 /** 178 * ÐоиÑк ÑлеменÑа в конÑекÑÑе компоненÑа или в заданном конÑекÑÑе 179 * @param {String} name Ðазвание ÑлеменÑа 180 * @param {Element} context 181 * @returns {Element} 182 */ 183 $(name, context) { 184 context = context || this.root; 185 return context.querySelector(this.getSelector(name, true)); 186 } 187 188 /** 189 * ÐоиÑк ÑлеменÑов в конÑекÑÑе компоненÑа или в заданном конÑекÑÑе 190 * @param {String} name Ðазвание ÑлеменÑа 191 * @param {Element} context 192 * @returns {Array} 193 */ 194 $$(name, context) { 195 context = context || this.root; 196 197 return [...context.querySelectorAll(this.getSelector(name, true))]; 198 } 199 200 /** 201 * ÐолÑÑиÑÑ ÑелекÑÐ¾Ñ Ñ ÑÑеÑом конÑекÑÑа компоненÑа 202 * @param {String} name Ðазвание ÑлеменÑа 203 * @param {Boolean} brackets ÐовзÑаÑаÑÑ Ð»Ð¸ ÑелекÑÐ¾Ñ Ñ ÐºÐ²Ð°Ð´ÑаÑнÑми Ñкобками 204 * @returns {String} 205 */ 206 getSelector(name, brackets = false) { 207 return name 208 ? `${brackets ? '[' : ''}data-${this.namespace}-${name}${brackets ? ']' : ''}` 209 : `${brackets ? '[' : ''}data-${this.namespace}${brackets ? ']' : ''}`; 210 } 211} 212 213class Lightbox extends Component { 214 constructor(el, params) { 215 super(el, params); 216 this.init(); 217 } 218 init() { 219 this.itemEls = this.$$('item'); 220 this.openBtns = this.$$('open'); 221 222 this.itemEls.forEach(el => { 223 el.addEventListener('click', (e) => this._onClick(e, 'item')); 224 }); 225 226 this.openBtns.forEach(el => { 227 el.addEventListener('click', (e) => this._onClick(e, 'open')); 228 }); 229 } 230 231 async _onClick(e, selectorType) { 232 e.preventDefault(); 233 234 const target = e.target; 235 236 if (!this.lightbox) { 237 this._initLightbox(); 238 } 239 240 const slideIndex = target.getAttribute(this.getSelector(selectorType)); 241 this.lightbox.open(parseInt(slideIndex)); 242 } 243 244 _initLightbox() { 245 this.lightbox = new FsLightbox(); 246 this.lightbox.props.sources = this._getSources(); 247 248 this.lightbox.props.onOpen = () => { 249 this.isOpened = true; 250 this._initOnSlideChange(); 251 } 252 this.lightbox.props.onClose = () => { 253 this.isOpened = false; 254 } 255 document.addEventListener('keydown', (e) => { 256 e = e || window.event; 257 if (e.keyCode == '37' || e.keyCode == '39') { 258 this._onSlideChange(); 259 } 260 }); 261 } 262 263 _initOnSlideChange() { 264 if (!this.observer) { 265 this.observer = new MutationObserver((mutationList) => { 266 for (const mutation of mutationList) { 267 if (mutation.type === "attributes") { 268 if ( 269 this.lightbox.elements.container.getAttribute('class') === 'fslightbox-container fslightbox-full-dimension fslightbox-fade-in-strong' 270 && this.isOpened 271 ) { 272 this._onSlideChange(); 273 } 274 } 275 } 276 }); 277 278 this.observer.observe(this.lightbox.elements.container, { attributes: true }); 279 280 ['.fslightbox-slide-btn-container-previous', '.fslightbox-slide-btn-container-next'].forEach(cls => { 281 this.lightbox.elements.container.querySelector(cls).addEventListener('click', () => { 282 this._onSlideChange(); 283 }); 284 }); 285 } 286 } 287 288 _onSlideChange() { 289 [...this.lightbox.elements.container.querySelectorAll('video, iframe')].forEac
289h(el => { 290 if (el.tagName.toLowerCase() === 'video') { 291 el.pause(); 292 } else if (el.tagName.toLowerCase() === 'iframe') { 293 // паÑза видео Ð´Ð»Ñ youtube 294 el.contentWindow.postMessage('{"event":"command","func":"stopVideo","args":""}', '*'); 295 296 // паÑза видео Ð´Ð»Ñ rutube 297 el.contentWindow.postMessage(JSON.stringify({ 298 type: 'player:pause', 299 data: {} 300 }), '*'); 301 302 // паÑза видео Ð´Ð»Ñ vimeo 303 el.contentWindow.postMessage('{"method":"pause"}', '*'); 304 305 // паÑза видео Ð´Ð»Ñ vk 306 el.setAttribute('src', el.getAttribute('src')); 307 } 308 }); 309 } 310 311 _getSources() { 312 return this.itemEls.map(el => { 313 let src = el.getAttribute(this.getSelector('src')); 314 315 if(src[0] === '#') { 316 src = document.querySelector(src); 317 } 318 319 return src; 320 }); 321 } 322}
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.