1class ScriptContentDetail extends Script { 2 constructor(params) { 3 super(params) 4 this.$dom = document.querySelector(`#${this.attrId}`) 5 this.videoUrl = this.$dom.querySelector('[video-src]')?.getAttribute('video-src') || '' 6 this.config = JSON.parse(this.utilts.htmlDecode(params.config)) 7 this.isMp4 = /\.(mp4|m3u8)(\?|$)/i.test(this.videoUrl) 8 this.isIframe = /^\s*<iframe[^>]*>[\s\S]*?<\/iframe>\s*$/.test(this.videoUrl) 9 10 let methodMap = { 11 default: this.config.method, 12 md: this.config.method_md, 13 xl: this.config.method_xl 14 } 15 this.method = methodMap[this.utilts.getScreen()] 16 this.relate_product = JSON.parse(this.utilts.htmlDecode(params.relate_product)) 17 this.modal = null 18 this.inquiryDrawer = null 19 // æ¯å¦å±å¼å¯¼è´äº§å 20 this.isExpand = true 21 this.initStatus = 0 22 this.xgPlayer = null 23 } 24 async init() { 25 if (this.initStatus === 0) { 26 this.initStatus++ 27 this.initStickyEvent() 28 // ç»å®è§é¢ç¸å ³äºä»¶ 29 this.initNodeEvent() 30 // å ¶ä»ç¸å ³äºä»¶ 31 this.initSwiper() 32 this.initModal() 33 this.initDrawer() 34 this.initMoreTextEvent() 35 } 36 } 37 initStickyEvent() { 38 const videoInner = this.$dom.querySelector('.video-inner') 39 if (this.utilts.getScreen() === 'default' && !this.utilts.checkDesign() && !videoInner.destroyFn) { 40 let offsetTop = 0 41 let headerBlock = document.querySelector(`[package-block-type="header"]`) 42 if (['2', '3'].includes(headerBlock?.getAttribute('position'))) { 43 offsetTop = headerBlock.offsetHeight 44 } 45 this.utilts.stickyByViewport(videoInner, offsetTop, 999, { width: '100vw', clearLeft: true }) 46 } 47 } 48 /** ç»å®ææ¾äºä»¶ */ 49 initNodeEvent() {
50 let config = JSON.parse(JSON.stringify(this.config)) 51 let $el = this.$dom.querySelector('[video-src]') 52 if (!$el) return 53 let url = this.videoUrl 54 const videothumbDom = $el.querySelector('.base-video__thumb img') 55 const videothumb = videothumbDom.getAttribute('src') || videothumbDom.getAttribute('lazy-src') 56 const isIframe = this.isIframe 57 const showMask = config.show_mask * 1 58 const opacity = showMask?`filter:brightness(${config.opacity});`:'' 59 const showControls = config.controls && config.controls.toString() === '1' || false 60 if (url) { 61 // éæ 62 const replayWrap = 63 `<div class="base-video__wrap--replay"> 64 <div class="replay-icon"> 65 <svg height="100%" version="1.1" viewBox="0 0 36 36" width="100%"> 66 <path class="ytp-svg-fill" d="M 18,11 V 7 l -5,5 5,5 v -4 c 3.3,0 6,2.7 6,6 0,3.3 -2.7,6 -6,6 -3.3,0 -6,-2.7 -6,-6 h -2 c 0,4.4 3.6,8 8,8 4.4,0 8,-3.6 8,-8 0,-4.4 -3.6,-8 -8,-8 z" id="ytp-id-125"></path> 67 </svg> 68 </div> 69 </div>` 70 71 const videoList = [ 72 `<div class="base-video__wrap"> 73 ${showControls && this.method=== '2' ? '<div class="base-video__wrap--close">Ã</div>': ''} 74 ${showControls && this.method=== '2' ? replayWrap : replayWrap} 75 <video 76 style="height:auto;display:block;margin:0 auto;max-width:100%;${opacity}" 77 autoplay 78 controlsList="nodownload" 79 webkit-playsinline="true" 80 playsinline="true" 81 x5-video-player-type="h5-page" 82 preload="metadata" 83 src="${url}" 84 ${config.loop && config.loop.toString() === '1' ? ' loop' : ''} 85 ${config.muted && config.muted.toString() === '1' ? ' muted' : ''} 86 ${showControls ? ' controls' : '' } 87 poster="${videothumb}" 88 ></video> 89 </div>`, 90 '<iframe '+ opacity +' width="100%" frameborder="0" allow="autoplay" allowfullscreen="true" webkitallowfullscreen="true" mozallowfullscreen="true" src="' + url + '"></iframe>' 91 ] 92 let videoHtml; 93 let iframeUrl = [] 94 if (isIframe) { 95 iframeUrl = globalThis.Server.iframeAutoplay(url).split('<iframe') 96 videoHtml = `<iframe style="filter:brightness(${showMask?config.opacity:'1'})"`+iframeUrl[1] 97 } else if (this.isMp4) { 98 this.xgPlayer = new VideoPlayer($el.querySelector('.video-container'), url, { 99 ...config, 100 playerConfig: { 101 poster: videothumb, 102 } 103 }) 104 const relateProductEle = this.$dom.querySelector('.relate-product-inner') 105 this.xgPlayer.onControls('show', () => { 106 if (this.utilts.getScreen() === 'xl') { 107 relateProductEle.classList.add('show-video-controls') 108 } 109 }) 110 this.xgPlayer.onControls('hide', () => { 111 if (this.utilts.getScreen() === 'xl') { 112 relateProductEle.classList.remove('show-video-controls') 113 } 114 }) 115 return 116 } else { 117 videoHtml = globalThis.Server.iframeAutoplay(videoList[1]) 118 } 119 // å½åææ¾ 120 const playVideo = $el.playVideo = () => { 121 const videothumb = $el.querySelector('.base-video__thumb img') 122 const videotDom = $el.querySelector('.base-video__preview video') 123 const videoPoster = videothumb && (videothumb.currentSrc || videothumb.getAttribute('src') || videothumb.getAttribute('lazy-src')) 124 const $preview = $el.querySelector('.base-video__preview') 125 const $videos = $preview.querySelectorAll('video, iframe') 126 $preview.classList.add('play') 127 // $el.getAttribute('videoscale') && $el.classList.add('base-video--scale') 128 $el.classList.add('play') 129 if ($preview && !$videos.length) { 130 const template = document.createElement('template') 131 template.innerHTML = videoHtml 132 const videos = Array.from(template.content.children) 133 videos.forEach(video => { 134 $preview.insertAdjacentElement('beforeend', video) 135 }) 136 } 137 if (this.$carouselEl.swiper) { 138 this.$carouselEl.swiper.autoplay.stop() 139 } 140 if (videothumb && videotDom) videotDom.poster = videothumb.getAttribute('src') || videothumb.getAttribute('lazy-src') 141 $el.querySelector('.base-video__preview').classList.add('play') 142 // $el.getAttribute('videoscale') && $el.classList.add('base-video--scale') 143 $el.classList.add('play') 144 const closeBtn = $el.querySelector('.base-video__preview').querySelector('.base-video__wrap--close') 145 const replayBtn = $el.querySelector('.base-video__preview').querySelector('.replay-icon') 146 if (showControls && closeBtn) { 147 const closeVideo = (event) => { 148 event.stopPropagation() 149 event.preventDefault() 150 const videoWrapDom = $el.querySelector('.base-video__preview').querySelector('.base-video__wrap') 151 if (videoWrapDom) { 152 videoWrapDom?.remove() 153 $el.querySelector('.base-video__preview')?.classList.remove('play') 154 $el.classList.remove('play') 155 } 156 } 157 closeBtn.addEventListener('click', closeVideo, { once: true }) 158 } 159 // if (showControls && replayBtn && this.config.auto_reset !== '1') { 160 if (showControls && replayBtn ) { 161 const videoDom = $el.querySelector('.base-video__wrap video') 162 const replayWrapDom = $el.querySelector('.base-video__preview').querySelector('.base-video__wrap--replay') 163 const showReplayBtn = (event) => { 164 event.stopPropagation() 165 event.preventDefault() 166 if(replayWrapDom) { 167 replayWrapDom.style.display = 'flex' 168 videoDom.controls = false 169 } 170 } 171 videoDom?.addEventListener('ended', showReplayBtn) 172 const replay = (event) => { 173 event.stopPropagation() 174 event.preventDefault() 175 videoDom.currentTime = 0 176 videoDom.play() 177 replayWrapDom.style.display = 'none' 178 videoDom.controls = true 179 } 180 replayBtn?.addEventListener('click', replay) 181 } 182 let myVideo = $el.querySelectorAll('video') 183 myVideo.forEach(elVideo => { 184 if (videoPoster) { 185 elVideo.poster = videoPoster 186 } 187 }) 188 } 189 const clickPlayVideo = (e) => { 190 e.stopPropagation() 191 e.stopImmediatePropagation() 192 if (!$el.querySelector('.base-video__preview').classList.contains('play')) { 193 // æè§é¢ 194 // e.preventDefault() 195 playVideo() 196 } 197 198 // if (/\.mp4(\?|$)/.test(url) && window.app.utilts.checkScreenMobile()) { 199 // // ææºç«¯ 200 // $el.querySelector('video').requestFullscreen() 201 // } 202 return false 203 }
204 if (config.autoplay.toString() === '1' && this.isMp4 && $el.querySelector('.base-video__preview').classList.value.indexOf('play') === -1) { 205 // èªå¨ææ¾ 206 playVideo() 207 if (this.config.auto_reset > 0) { 208 $el.addEventListener('click', clickPlayVideo, {useCapture: false}) 209 } 210 } else { 211 // æå¨ææ¾ 212 if (isIframe || !this.isMp4) { 213 videoHtml = this.config.default_src ? videoHtml : globalThis.Server.iframeAutoplayClear(videoHtml, config.muted && config.muted.toString() === '1') 214 } 215 $el.addEventListener('click', clickPlayVideo, {useCapture: false}) 216 } 217 } 218 } 219 /**æ£æ¥è§é¢é¾æ¥æ¯å¦ææ */ 220 _checkVideoUrl(url, callback, errBack) { 221 let fragment = document.createDocumentFragment() 222 let video = document.createElement('video') 223 video.src = url 224 fragment.append(video) 225 video.onloadedmetadata = () => { 226 if (callback) callback() 227 } 228 video.onerror = () => { 229 if (errBack) errBack() 230 } 231 } 232 initSwiper() { 233 const loadSwiper = () => { 234 let relateProSwiper = null 235 if (this.config.show_product && this.relate_product.length) { 236 relateProSwiper = new Swiper(`#${this.attrId} .relate-product-container`, { 237 centeredSlides: true, 238 autoplay: { 239 delay: 5000, 240 disableOnInteraction: false, 241 pauseOnMouseEnter: true 242 }, 243 pagination: { 244 el: ".swiper-pagination", 245 clickable: true 246 } 247 }); 248 relateProSwiper.el.onmouseover = function(){ 249 relateProSwiper.autoplay.stop(); 250 } 251 relateProSwiper.el.onmouseout = function(){ 252 relateProSwiper.autoplay.start(); 253 } 254 if (this.utilts.getScreen() === 'default') { 255 this.$dom.querySelector('.content-body').style.paddingTop = '0px' 256 this.$dom.querySelector('.relate-product-container').style.paddingTop = '15px' 257 this.$dom.querySelector('.relate-product-container').style.paddingBottom = '15px' 258 } 259 } 260 const allSlide = this.$dom.querySelectorAll('.relate-product-container .swiper-slide') 261 if (allSlide.length) { 262 allSlide.forEach((val, index) => { 263 val.addEventListener('click', (e) => { 264 // console.log(e); 265 if (relateProSwiper && (e.target.classList.contains('inquire-img') || e.target.classList.contains('inquire-iconfont'))) { 266 relateProSwiper.slideTo(0, 0, false) 267 } else { 268 if (index === 0 && this.config.show_inquire) { 269 if (this.utilts.getScreen() === 'default') { 270 // this.inquiryDrawer.open() 271 this.showInquire() 272 } else { 273 this.modal.open() 274 } 275 } else { 276 const link = val.getAttribute('data-link') 277 window.open(globalThis.Server.getRinseHref(link, window.app.info.site)) 278 } 279 } 280 }) 281 }) 282 } 283 const moreProSlide = this.$dom.querySelectorAll('.more-product-list .swiper-slide') 284 if (moreProSlide.length) { 285 moreProSlide.forEach((val, index) => { 286 val.addEventListener('click', (e) => { 287 // console.log(e); 288 if (index === 0 && this.config.show_inquire) { 289 this.modal.open() 290 } else { 291 const link = val.getAttribute('data-link') 292 window.open(globalThis.Server.getRinseHref(link, window.app.info.site)) 293 } 294 }) 295 }) 296 } 297 } 298 loadSwiper() 299 if (this.utilts.getScreen() === 'xl' && this.xgPlayer) { 300 const relateProductEle = this.$dom.querySelector('.relate-product-inner') 301 relateProductEle.addEventListener('mouseenter', () => { 302 this.xgPlayer.checkHideControls(true) 303 }) 304 } 305 const relateProductInner = this.$dom.querySelector('.relate-product-inner .content-body') 306 const relateProductContainer = this.$dom.querySelector('.relate-product-container') 307 const closeIcon = this.$dom.querySelector('.close-icon') 308 const expandIcon = this.$dom.querySelector('.relate-product-icon') 309 const moreIcon = this.$dom.querySelector('.more-icon') 310 const moreProduct = this.$dom.querySelector('.more-relate-product') 311 const moreProductClose = this.$dom.querySelector('.more-product-header__close') 312 if (this.utilts.getScreen() !== 'default') closeIcon?.classList.remove('d-none') 313 closeIcon?.addEventListener('click', () => { 314 this.isExpand = false 315 closeIcon.classList.add('d-none') 316 relateProductContainer.classList.add('d-none') 317 expandIcon.classList.remove('d-none') 318 relateProductInner.classList.add('set-width') 319 if (moreIcon) moreIcon.classList.add('d-none') 320 if (moreProduct) moreProduct.classList.add('d-none') 321 }) 322 relateProductInner?.addEventListener('click', (e) => { 323 if (!e.target.classList.contains('icon-action-close-2') && !this.isExpand) { 324 this.isExpand = true 325 closeIcon?.classList.remove('d-none') 326 relateProductContainer.classList.remove('d-none') 327 expandIcon.classList.add('d-none') 328 relateProductInner.classList.remove('set-width') 329 if (moreIcon) moreIcon.classList.remove('d-none') 330 } 331 }) 332 if (this.utilts.getScreen() === 'default') return 333 if (moreIcon) { 334 moreIcon.addEventListener('click', () => { 335 moreProduct.classList.remove('d-none') 336 }) 337 } 338 if (moreProductClose) { 339 moreProductClose.addEventListener('click', () => { 340 moreProduct.classList.add('d-none') 341 }) 342 } 343 } 344 initModal() { 345 if (this.utilts.getScreen() === 'default') return 346 this.modal = new Modal() 347 const $modal = this.$dom.querySelector('.inquiry-modal-inner') 348 if (!$modal) return 349 this.modal.init({ 350 body: $modal, 351 title_style: 1, 352 title: this.utilts.$t('Send Inquiry'), 353 size: 'lg', 354 className: 'inquiry-modal content-detail-inquiry', 355 onSubmit: () => { 356 $modal.querySelector(`.btn`).click() 357 } 358 }) 359 } 360 initDrawer() { 361 if (this.utilts.getScreen() === 'default') { 362 const moreIcon = this.$dom.querySelector('.more-icon') 363 moreIcon?.addEventListener('click', () => { 364 // const videoInner = this.$dom.querySelector('.video-inner') 365 // const videoRect = videoInner.getBoundingClientRect() 366 let drawer = new Drawer() 367 drawer.setOptions({ 368 title: this.$dom.querySelector('.more-relate-product .more-product-header__inner').innerHTML, 369 className: 'modal-more-product__info unit-content-detail', 370 content: this.$dom.querySelector('.more-relate-product .more-product-list__inner').innerHTML, 371 hiddentMask: true 372 // bottomVal: videoRect.bottom 373 }) 374 drawer.open() 375 const moreProSlide = document.querySelectorAll('.modal-more-product__info .swiper-slide') 376 if (moreProSlide.length) { 377 moreProSlide.forEach((val, index) => { 378 val.addEventListener('click', () => { 379 if (index === 0) { 380 this.showInquire() 381 } else { 382 const link = val.getAttribute('data-link') 383 window.open(globalThis.Server.getRinseHref(link, window.app.info.site)) 384 } 385 }) 386 }) 387 } 388 }) 389 } 390 } 391 showInquire() { 392 const inquireEle = this.$dom.querySelector('.unit-detail-button-inquiry') 393 const modalMorePro = document.querySelector('.modal-more-product__info') 394 const copyrightEle = document.querySelector('[package-block-type="copyright"]') 395 inquireEle.style.left = '0px' 396 inquireEle.classList.add('inquiry-drawer-container', 'active') 397 inquireEle.children[0].classList.remove('d-none') 398 if (this.utilts.getScreen() === 'default') { 399 // const videoInner = this.$dom.querySelector('.video-inner') 400 // const videoRect = videoInner.getBoundingClientRect()
401 // inquireEle.style.height = `calc(100vh - ${videoRect.bottom}px - var(--SAIB))` 402 } 403 // this.$dom.querySelector('.inquiry-mask').classList.add('active') 404 document.body.style.overflow = 'hidden' 405 copyrightEle.style.opacity = 0 406 copyrightEle.style['pointer-events'] = 'none' 407 const parents = this.utilts.getParentsByAttr(this.$dom, 'package-item', 'block') 408 parents[0].style.position = 'relative' 409 const cellDom = this.utilts.getParentsByAttr(this.$dom, 'package-item', 'cell') 410 cellDom[0].style.zIndex = 99 411 document.querySelector('[package-group="block"]').style.zIndex = 111 412 if (modalMorePro?.classList.contains('active')) { 413 document.querySelector('#app').style.position = 'relative' 414 document.querySelector('#app').style.zIndex = 1000 415 } 416 const closeInquire = inquireEle.querySelector('.drawer-close-btn') 417 closeInquire.addEventListener('click', () => { 418 inquireEle.classList.remove('active') 419 // this.$dom.querySelector('.inquiry-mask').classList.remove('active') 420 inquireEle.children[0].classList.add('d-none') 421 if (!document.querySelector('.modal-more-product__info.active')) document.body.style.overflow = '' 422 copyrightEle.style.removeProperty('opacity') 423 copyrightEle.style.removeProperty('pointer-events') 424 parents[0].style.removeProperty('position') 425 cellDom[0].style.removeProperty('zIndex') 426 document.querySelector('[package-group="block"]').style.removeProperty('zIndex') 427 if (modalMorePro?.classList.contains('active')) { 428 document.querySelector('#app').style.removeProperty('position') 429 document.querySelector('#app').style.removeProperty('zIndex') 430 } 431 }) 432 } 433 initMoreTextEvent() { 434 setTimeout(() => { 435 const content = this.$dom.querySelector('.unit-content-detail__summary .text-inner'); 436 const moreBtn = this.$dom.querySelector('.unit-content-detail__summary .more-text-btn') 437 if (!content) return 438 console.log('content.scrollHeight', content.scrollHeight, 'clientHeight', content.clientHeight); 439 if (content.scrollHeight > content.clientHeight) { 440 const tempSpan = document.createElement('span'); 441 tempSpan.textContent = content.textContent; 442 tempSpan.style.visibility = 'hidden'; 443 tempSpan.style.whiteSpace = 'nowrap'; 444 const range = document.createRange(); 445 range.selectNodeContents(content); 446 const rects = range.getClientRects(); 447 const secondLineEnd = rects[1]; // 第äºè¡çç©å½¢ä¿¡æ¯ 448 moreBtn.classList.remove('d-none') 449 } 450 moreBtn.addEventListener('click', () => { 451 if (content.classList.contains('rich-text')) { 452 content.classList.remove('rich-text') 453 moreBtn.innerText = this.utilts.$t('Put Away') 454 } else { 455 content.classList.add('rich-text') 456 moreBtn.innerText = this.utilts.$t('More') 457 } 458 // if (content.classList.contains('d-none')) { 459 // content.classList.remove('d-none') 460 // moreBtn.innerText = 'Put Away' 461 // moreBtn.style.marginTop = '8px' 462 // } else { 463 // content.classList.add('d-none') 464 // moreBtn.innerText = 'Check Description' 465 // moreBtn.style.marginTop = '0px' 466 // } 467 }) 468 }, 100) 469 } 470}
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.