PageSourceSearch

https://www.hanbi-hotelsupplies.com/dist/js/cloud-editor-events.js

js hanbi-hotelsupplies.com collected 2026-10-08 16:17:31 UTC 38,534 bytes, 990 lines download raw bytes

1/** 防抖 */
2function debounce(fn, delay = 300) {
3  let timer;
4  return function (...args) {
5    // 清除上一次的定时器
6    if (timer) {
7      clearTimeout(timer);
8    }
9    // 设置新的定时器
10    timer = setTimeout(() => {
11      // @ts-ignore
12      fn.apply(this, args);  // 使用 apply 保证 this 和参数的传递
13    }, delay);
14  };
15}
16function initBetween(target, config) {
17  const getNodeStyle = (node) => {
18    if (node.currentStyle) return node.currentStyle
19    else return document.defaultView?.getComputedStyle(node, null)
20  }
21  const $itemFirst = target.querySelector(`.ce-list_item`)
22  if (!$itemFirst) return
23  const style = getNodeStyle($itemFirst)
24  const item_pr = parseFloat(style.paddingRight) || 0
25  const item_pl = parseFloat(style.paddingLeft) || 0
26  const item_mr = parseFloat(style.marginRight) || 0
27  const item_ml = parseFloat(style.marginLeft) || 0
28  const $style = document.createElement('style')
29  const id = target.getAttribute('id')
30  $style.classList.add('special-style')
31  let html = `#${id} .ce-list_item{margin-left:0!important;padding:0!important}`
32  html += `#${id} .ce-col-w-${config.colsPhone}, #${id} .ce-col-w-md-${config.colsPad}, #${id} .ce-col-w-xl-${config.colsPc} {max-width: unset; flex: none}`
33  $style.innerHTML = html
34  target.appendChild($style)
35  const result = item_pr + item_pl + item_mr + item_ml
36  return result || 19.72 // 清理数据
37}
38// 初始化swiper
39function ceInitSwiper() {
40  if (!Swiper) return
41  const $dom = document.querySelectorAll('div[type="swiper"]:not([swiper-init]), div[list-swiper-config]:not([swiper-init])')
42  $dom.forEach($html => {
43    const specialSytle = $html.querySelector(`.special-style`)
44    if (specialSytle) {
45      specialSytle.parentNode.removeChild(specialSytle)
46    }
47    $html.setAttribute('swiper-init', 'true') // 设置已经初始化的标识
48    let swiperInstance;
49    let $config = $html.getAttribute('list-swiper-config')
50    let config = {}
51    if ($config) {
52      // 新版
53      config = $config ? JSON.parse($config) : {}
54      config.observer = true
55      config.observeParents = true
56      let swiperHtml = ''
57
58      if (config.effect === 'fade') {
59        config.fadeEffect = {
60          crossFade: true
61        }
62      } else if (config.effect === 'cube') {
63        config.cubeEffect = {
64          slideShadows: true,
65          shadow: false,
66          shadowOffset: 0,
67          shadowScale: 0
68        }
69      }
70
71      if (config.pagination) {
72        config.pagination = { el: '.swiper-pagination', type: config.pagination }
73        swiperHtml += '<div class="swiper-pagination"></div>'
74      }
75
76      // 滚动条
77      // const $scrollbar = this.target.querySelectorAll(pagination_el)
78      // if (config.scrollbar && $scrollbar && $scrollbar.length > 0) {
79      //   config.scrollbar = {
80      //     el: scrollbar_el,
81      //     draggable: true
82      //   }
83      // }
84
85      // navigation
86      const hasNavigationOutside = [config.navigation_position_pc, config.navigation_position_pad, config.navigation_position_phone].includes('outside')
87      if (config.navigation) {
88        config.navigation = {
89          nextEl: '.swiper-button-next',
90          prevEl: '.swiper-button-prev'
91        }
92        $html.setAttribute('navigation-position-pc', config.navigation_position_pc)
93        $html.setAttribute('navigation-position-pad', config.navigation_position_pad)
94        $html.setAttribute('navigation-position-phone', config.navigation_position_phone)
95        swiperHtml += '<div class="swiper-button-prev"></div><div class="swiper-button-next"></div>'
96        if (hasNavigationOutside) {
97          $html.innerHTML += `<div class="swiper-button-prev swiper-button-prev--outside"></div><div class="swiper-button-next swiper-button-next--outside">`
98          $html.querySelector('.swiper-button-prev--outside')?.addEventListener('click',() => {
99            swiperInstance?.slidePrev()
100          })
101          $html.querySelector('.swiper-button-next--outside')?.addEventListener('click',() =>{
102            swiperInstance?.slideNext()
103          })
104        }
105      }
106
107      // 响应式
108      if (config.slidesPerView !== 'auto') {
109        config.breakpoints = {
110          0: { slidesPerView: config.colsPhone || 1 },
111          768: { slidesPerView: config.colsPad || 1 },
112          1200: { slidesPerView: config.colsPc || 1 }
113        }
114      }
115
116      const container = $html.querySelector('.ce-list_container')
117      if (container) {
118        container.innerHTML += swiperHtml
119        container.classList.add('swiper-container')
120      }
121      config.spaceBetween = initBetween($html, config)
122      swiperInstance = new Swiper('#' + $html.getAttribute('id') + ' .swiper-container', config)
123      if (config.effect === 'cube' && container) {
124        if (config.loop) {
125          const $first = container.querySelector('.swiper-wrapper > div:first-child')
126          if ($first) $first.style.opacity = '0'
127        }
128        container.style.overflow = "hidden"
129      }
130      // 箭头相对图片居中-----------------------------------------------
131      function getDistanceToParent(img, parent) {
132        // 获取img边界框
133        const imgRect = img?.getBoundingClientRect();
134        if (!parent || !imgRect) {
135          return {
136            offsetX: 0,
137            offsetY: 0
138          };
139        }
140        // 获取父元素的边界框
141        const parentRect = parent.getBoundingClientRect();
142
143        // 计算img相对于父元素的距离
144        const offsetX = imgRect.left - parentRect.left;
145        const offsetY = imgRect.top - parentRect.top;
146        return {
147            offsetX: offsetX,
148            offsetY: offsetY
149        };
150      }
151      let initNavigation = false
152      const setNavigation = (dom, prevSelector='.swiper-button-prev', nextSelector='.swiper-button-next') => {
153        if (!dom) return
154        try {
155          let maxHeight = 0
156          let maxItem;
157          const list = dom.querySelectorAll('.ce-image_item img')
158          list.forEach(item => {
159            const {height} = item.getBoundingClientRect()
160            if (height > maxHeight) {
161              maxHeight = height;
162              maxItem = item;
163            }
164          })
165          const {offsetY} = getDistanceToParent(maxItem, dom)
166          let $prev = dom.querySelector(prevSelector)
167          let $next = dom.querySelector(nextSelector)
168          if (!$prev || !$next) return
169          $prev.style.top = `${offsetY + (maxHeight / 2)}px`
170          $next.style.top = `${offsetY + (maxHeight / 2)}px`
171          if (!initNavigation) {
172            $prev.classList.add('initialized')
173            $next.classList.add('initialized')
174          }
175          if (prevSelector !== '.swiper-button-prev' || nextSelector !== '.swiper-button-next') {
176            if (swiperInstance.slides.length <= swiperInstance.params.slidesPerView) {
177              $prev.classList.add('swiper-button-disabled')
178              $next.classList.add('swiper-button-disabled')
179            } else {
180              $prev.classList.remove('swiper-button-disabled')
181              $next.classList.remove('swiper-button-disabled')
182            }
183          }
184        } catch (e) {
185          console.error(e);
186        }
187      }
188      if (config.navigation) {
189        let imgDom = $html.querySelector('.swiper-slide .ce-image_item img')
190
191        if(imgDom) {
192          const observer = new ResizeObserver(() => {
193            setNavigation(container)
194            if (hasNavigationOutside) {
195              setNavigation($html, '.swiper-button-prev--outside', '.swiper-button-next--outside')
196            }
197          });
198          observer.observe(container);
199        }
200      }
201      // 箭头位置边界处理-------------------------------------------------
202      if (config.navigation && hasNavigationOutside) {
203        let $prev = $html.querySelector('.swiper-button-prev--outside')
204        let $next = $html.querySelector('.swiper-button-next--outside')
205        let navigationAreaWidth = Math.abs(parseFloat(getComputedStyle($prev).left)) // 记录箭头在外所需要的宽度
206        const checkNavigation = (dom) => {
207          const viewportWidth = window.innerWidth;
208          const rect = dom.getBoundingClientRect();
209          // 判断元素是否溢出屏幕左右边界
210          const isOverflowingLeft = rect.left < 0;
211          const isOverflowingRight = rect.right > viewportWidth;
212
213          return isOverflowingLeft || isOverflowingRight;
214        }
215        const handleNavigation = () => { // 检测箭头是否溢出屏幕
216          try {
217            if (checkNavigation($prev) || checkNavigation($next)) {
218              $prev.style.left = '10px';
219              $next.style.right = '10px';
220            } else if ($html.getBoundingClientRect().left >= navigationAreaWidth){
221              $prev.style.left = '';
222              $next.style.right = '';
223            }
224          } catch (error) {
225            console.error(error);
226          }
227        }
228        const observer = new ResizeObserver(debounce(handleNavigation));
229        observer.observe(container);
230        window.addEventListener('resize', debounce(handleNavigation))
231      }
232      // -------------------------------------------------------------
233    } else {
234      // 旧版
235      $config = $html.getAttribute('swiper-config') || ''
236      config = $config ? JSON.parse($config) : {}
237      const $list = $html.getAttribute('swiper-list') || ''
238      const list = $list ? JSON.parse($list) : []
239      if (!$list || !$config) return
240
241      // 重新生成swiper相关dom
242      const $swiperOld = $html.querySelector('.ce-swiper-container')
243      if ($swiperOld) $html.removeChild($swiperOld)
244      const $swiper = document.createElement('div')
245      $swiper.classList.add('ce-swiper-container', 'swiper-container')
246      const $wrapper = document.createElement('div')
247      $wrapper.classList.add('ce-swiper-wrapper', 'swiper-wrapper')
248      let slideStr = ''
249      list.forEach(item => {
250        const aHref = item.href ? `href="${item.href}"` : ''
251        slideStr = slideStr.concat(
252          `<div class="ce-swiper-slide swiper-slide" textShow='${item.textShow}'>
253            <a ${aHref} target="${item.target}" style="justify-content:${item.textAlign}">
254              <img src="${item.src}">
255              <div class="ce-text-panel" ${item.textEffect} style="width:${item.textWidth}%;top:${item.textTop}%;">${item.text}</div>
256              ${item.textShadow ? '<div class="ce-text-panel-shadow" style="width:' + item.textWidth + '%;background:' + item.textShadowColor + ';"></div>' : ''}
257              ${item.textShow === 'button' ? '<div class="ce-text-panel-bar" style="width:' + item.textWidth + '%;"><div class="ce-row-bar-wrap" style="--bar-color:' + item.textButtonColor + '"><div class="ce-row-bar"></div></div></div>' : ''}
258              </a>
259          </div>`
260        )
261      })
262      $wrapper.innerHTML = slideStr
263      const $fragment = document.createDocumentFragment()
264      $fragment.appendChild($wrapper)
265      // 分页器
266      if (config.pagination) {
267        const $pagination = document.createElement('div')
268        $pagination.classList.add('ce-swiper-pagination', 'swiper-pagination')
269        $fragment.appendChild($pagination)
270        config.pagination = { el: '.ce-swiper-pagination', type: config.paginationType }
271      }
272      // 左右控制
273      if (config.navigation) {
274        const $next = document.createElement('div')
275        $next.classList.add('ce-swiper-button-next', 'swiper-button-next')
276        const $prev = document.createElement('div')
277        $prev.classList.add('ce-swiper-button-prev', 'swiper-button-prev')
278        $fragment.appendChild($next)
279        $fragment.appendChild($prev)
280        config.navigation = { nextEl: '.ce-swiper-button-next', prevEl: '.ce-swiper-button-prev' }
281      }
282      if (config.autoplay) {
283        config.autoplay = { delay: config.delay, disableOnInteraction: false }
284      }
285      $swiper.appendChild($fragment)
286      $html.appendChild($swiper)
287
288      // 按钮事件
289      const doms = $swiper.querySelectorAll('.ce-text-panel-bar .ce-row-bar-wrap')
290      doms.forEach(item => {
291        const $pNode = item.parentNode.parentNode.parentNode
292        item.onmouseover = () => {
293          $pNode.classList.add('active')
294        }
295        item.onmouseout = () => {
296          $pNode.classList.remove('active')
297        }
298      })
299      config.spaceBetween = initBetween($html, config)
300
301      let timer = 0
302      const initSwiperFun = e => {
303        // 垂直处理
304        const verticalHandler = (flag = false, n = 100) => {
305          // 设置垂直高度
306          if (config.direction === 'vertical') {
307            const $img = $swiper.querySelector(`.ce-swiper-slide img`)
308            if ($img && $img.clientHeight) $swiper.style.height = `${$img.clientHeight}px`
309            if (flag) setTimeout(() => s.update(), n)
310          }
311        }
312
313        const s = new Swiper(`#${e} .ce-swiper-container`, {
314          direction: 'horizontal',
315          ...config,
316          observer: true, // 修改swiper自己或子元素时,自动初始化swiper
317          observeParents: true, // 修改swiper的父元素时,自动初始化swiper
318          on: {
319            resize: () => {
320              if (timer) clearTimeout(timer)
321              timer = setTimeout(() => {
322                verticalHandler(true, 0)
323                timer = 0
324              }, 100)
325            },
326            imagesReady: () => {
327              verticalHandler(true)
328            },
329            observerUpdate: () => {
330              if (config.direction === 'horizontal') {
331                // 处理高度偏矮时分页位置
332                const $pagination = $swiper.querySelector(`.ce-swiper-pagination`)
333                if ($pagination && $swiper.clientHeight < 100) $pagination['style']['bottom'] = '2px'
334              } else {
335                verticalHandler()
336              }
337            }
338          }
339        })
340      }
341      initSwiperFun($html.getAttribute('id'))
342    }
343  })
344}
345
346// 初始化选项卡事件
347function ceInitTabs() {
348  setTimeout(() => {
349    const $tabs = document.querySelectorAll('div[cloud-editor="unit"][type="tabs"][init="false"]')
350    if ($tabs.length > 0) {
351      $tabs.forEach(($html, index) => {
352        $tabs[index].setAttribute('init', 'true')
353        const $btnBox = $html.querySelector(':scope > .ce-tabs-btn-row')
354        const $btns = $btnBox.querySelectorAll(':scope > .ce-tabs-btn')
355        const $panelBox = $html.querySelector(':scope > .ce-tabs-panel-row')
356        const $panels = $panelBox.querySelectorAll(':scope > .ce-tabs-panel')
357        $btnBox.onclick = e => {
358          const $target = e.target
359          if ($target.className === 'ce-tabs-btn') {
360            const idx = $target.getAttribute('idx')
361            const activeStyle = $btns[0].getAttribute('active-data')
362            const initStyle = $target.getAttribute('style')?.replace(activeStyle, '')
363            const currentIndex = Array.from($btns).findIndex(val => val.getAttribute('idx') == idx)
364            $btns.forEach(btn => {
365              // 恢复之前的样式配置
366              const btnStyle = btn.getAttribute('style')?.replace(activeStyle, '')
367              btn.removeAttribute('current')
368              btn.setAttribute('style', btnStyle)
369            })
370            console.log('currentIndex', currentIndex);
371            $btns[currentIndex].setAttribute('current', 'true')
372            $btns[currentIndex].setAttribute('style', initStyle + (activeStyle ? activeStyle : ''))
373            $panels.forEach(pan => pan.removeAttribute('current'))
374            $panels[currentIndex].setAttribute('current', 'true')
375          }
376        }
377      })
378    }
379  }, 100)
380}
381
382// 初始化 tabs-pro
383function ceInitTabsPro() {
384  const $tabs_pro = document.querySelectorAll('div[cloud-editor="unit"][type="tabs-pro"][init="false"]')
385  if ($tabs_pro.length > 0) {
386    $tabs_pro.forEach((item, index) => {
387      $tabs_pro[index].setAttribute('init', 'true')
388      const attrId = item.id
389      const $swiperButtonPrev = item.querySelector('.swiper-button-prev')
390      const $swiperButtonNext = item.querySelector('.swiper-button-next')
391      const $tabsHeader = item.querySelector(`.ce-tabs-pro__header`)
392      const $tabsNavWrap = item.querySelector(`.ce-tabs-pro__nav-wrap`)
393      const $panelWrap = item.querySelector('.ce-tabs-pro__panel-wrap')
394      const $tabItems = item.querySelectorAll('.ce-tabs-pro__nav-item')
395      const $tabPanels = $panelWrap.querySelectorAll('.ce-tabs-pro__panel')
396      let tabItemsClass = $tabItems[0]?.getAttribute('class')
397      const columnsInfo = {
398        phone: parseInt(tabItemsClass?.match(/ce-col-w-\d+/)?.[0]?.match(/\d+/)?.[0]) || 3,
399        pad: parseInt(tabItemsClass?.match(/ce-col-w-md-\d+/)?.[0]?.match(/\d+/)?.[0]) || 6,
400        pc: parseInt(tabItemsClass?.match(/ce-col-w-xl-\d+/)?.[0]?.match(/\d+/)?.[0]) || 6
401      }
402      let activeIndex = 0
403      
404      let currentScreen = ''
405      let tabsSwiper
406      initScreen()
407      window.addEventListener('resize', () => {
408        if (currentScreen === getScreen()) return
409        initScreen()
410      })
411      
412      function getScreen() {
413        if (window.innerWidth >= 1200) {
414          return 'pc'
415        } else if (768 <= window.innerWidth && window.innerWidth < 1200) {
416          return 'pad'
417        } else {
418          return 'phone'
419        }
420      }
421      function initScreen() {
422        currentScreen = getScreen()
423        initTab()
424      }
425      function initTab() {
426        tabsSwiper?.destroy(true, true)
427
428        const swiperConfig = {
429          slidesPerView: columnsInfo[currentScreen],
430          spaceBetween: 0,
431          initialSlide: activeIndex,
432          freeMode: true,
433          navigation: {
434            prevEl: '.swiper-button-prev',
435            nextEl: '.swiper-button-next',
436          }
437        }
438        if (['phone', 'pad'].includes(currentScreen)) {
439          $swiperButtonPrev.classList.remove('d-none')
440          $swiperButtonNext.classList.remove('d-none')
441          $tabsHeader.classList.add('swiper-container')
442          $tabsNavWrap.classList.add('swiper-wrapper')
443          $tabItems.forEach(($item) => {
444            $item.classList.add('swiper-slide')
445          })
446          
447          tabsSwiper = new Swiper(`#${attrId} > .ce-tabs-pro >.ce-tabs-pro__header`, swiperConfig)
448        } else {
449          $swiperButtonPrev.classList.add('d-none')
450          $swiperButtonNext.classList.add('d-none')
451          $tabsHeader.classList.remove('swiper-container')
452          $tabsNavWrap.classList.remove('swiper-wrapper')
453          $tabItems.forEach(($item) => {
454            $item.classList.remove('swiper-slide')
455          })
456        }
457        initEvent()
458      }
459      function initEvent() {
460        $tabItems.forEach((item, index) => {
461          item.addEventListener('click', (e) => tabClick(e, index))
462        })
463      }
464      function tabChange(e, index) {
465        activeIndex = index
466        $tabItems.forEach(it => it.classList.remove('active'))
467        $tabItems[index].classList.add('active')
468      }
469      function tabClick(e, index) {
470        tabChange(e, index)
471        if (['phone', 'pad'].includes(currentScreen)) {
472          tabsSwiper.slideTo(index)
473        }
474        $tabPanels.forEach((tabItem, tabIndex) => {
475          if (tabIndex === activeIndex) {
476            tabItem.style.display = ''
477          } else {
478            tabItem.style.display = 'none'
479          }
480        })
481      }
482    })
483  }
484}
485
486// 处理图片点击后全屏预览功能,这里注意云站那边有懒加载只有lazy-src还有层级要移动到body直接子元素
487function ceImgMagnification() {
488  setTimeout(() => {
489    const $dom = document.querySelectorAll('div[cloud-editor="unit"][magnification="img"]:not([magnification-init])')
490    if ($dom.length > 0) {
491      $dom.forEach(($html, index) => {
492        $dom[index].setAttribute('magnification-init', 'true')
493        // 开始获取图片列表数据(根据组件类型判断,如图片组件、列表组件、轮播组件的dom结构上面获取),创建全屏预览层
494        const unitType = $html.getAttribute('type')
495        // 给自身创建一个预览dom
496        let preview = $html.querySelector('.magnification-preview')
497        if (!preview) {
498          preview = document.createElement('div')
499          preview.classList.add('magnification-preview')
500          $html.appendChild(preview)
501        }
502        if (!(preview instanceof HTMLElement)) return
503        const eventFun = (ets, imgs) => {
504          imgs = (Array.from(new Set(imgs))).filter(i => !!i);
505          if (!imgs.length) return
506          preview.innerHTML = ''
507          const fragment = document.createDocumentFragment()
508          const closeBtn = document.createElement('img')
509          const numDiv = document.createElement('div')
510          closeBtn.src = '//img.yfisher.com/1655774389493.png'
511          closeBtn.setAttribute('fetchpriority', 'low')
512          closeBtn.setAttribute('decoding', 'async')
513          closeBtn.setAttribute('loading', 'lazy')
514          numDiv.innerText = `1/${imgs.length}`
515          closeBtn.classList.add('mgnpw-close_btn')
516          numDiv.classList.add('mgnpw-num_panel')
517          imgs.forEach((img, idx) => {
518            const d = document.createElement('img')
519            d.src = img
520            d.setAttribute('fetchpriority', 'low')
521            d.setAttribute('decoding', 'async')
522            d.setAttribute('loading', 'lazy')
523            d.classList.add('editor-preview-imgs')
524            d.setAttribute('style', `display:${idx === 0 ? 'block' : 'none'};`)
525            fragment.appendChild(d)
526          })
527          closeBtn.onclick = () => preview.style.display = 'none'
528
529          let leftArrow = null
530          let rightArrow = null
531          if (imgs.length > 1) {
532            leftArrow = document.createElement('img')
533            rightArrow = document.createElement('img')
534            leftArrow.src = '//img.yfisher.com/1655774390439.png'
535            rightArrow.src = '//img.yfisher.com/1655774390157.png'
536            leftArrow.classList.add('mgnpw-left_btn')
537            rightArrow.classList.add('mgnpw-right_btn')
538            fragment.appendChild(leftArrow)
539            fragment.appendChild(rightArrow)
540          }
541
542          fragment.appendChild(closeBtn)
543          fragment.appendChild(numDiv)
544          preview?.appendChild(fragment)
545          const pimgs = preview.querySelectorAll('.editor-preview-imgs')
546          let currentIndex = 0
547          ets.forEach(et => {
548            et.onclick = e => {
549              if ($html.getAttribute('magnification') !== 'img') return
550              const s = e.target.getAttribute('lazy-src') || e.target.src || ''
551              currentIndex = imgs.findIndex(m => m.includes(s.split('?')[0]))
552              if (currentIndex === -1) return
553              preview.style.display = 'block';
554              pimgs.forEach((p, idx) => (p.style.display = idx === currentIndex ? 'block' : 'none'));
555              numDiv.innerText = `${currentIndex + 1}/${imgs.length}`;
556              e.stopPropagation()
557              e.preventDefault()
558              return false
559            }
560          })
561          if (imgs.length > 1) {
562            leftArrow.onclick = () => {
563              if (currentIndex >= 0) {
564                currentIndex -= 1
565                if (currentIndex < 0) currentIndex = imgs.length - 1
566                pimgs.forEach((p, idx) => p.style.display = idx === currentIndex ? 'block' : 'none')
567                numDiv.innerText = `${currentIndex + 1}/${imgs.length}`;
568              }
569            }
570
571            rightArrow.onclick = () => {
572              if (currentIndex <= imgs.length - 1) {
573                currentIndex += 1
574                if (currentIndex > imgs.length - 1) currentIndex = 0
575                pimgs.forEach((p, idx) => p.style.display = idx === currentIndex ? 'block' : 'none')
576                numDiv.innerText = `${currentIndex + 1}/${imgs.length}`;
577              }
578            }
579          }
580          // 丢到body对象里,层级才会高
581          document.body.appendChild(preview)
582        }
583        const imgList = []
584        switch (unitType) {
585          case 'image':
586            const img = $html.querySelector('img')
587            const imgArr = []
588            if (img) {
589              imgList.push(img.getAttribute('lazy-src') || img.src)
590              imgArr.push(img)
591
592              let img2
593              if ($html.getAttribute('double-img')) {
594                img2 = $html.querySelector('.ce-img-double_other')
595              }
596              if ($html.querySelector('.ce-img-double_other')) {
597                img2 = $html.querySelector('.ce-img-double_other')
598              }
599              if (img2) {
600                imgList.push(img2.getAttribute('lazy-src') || img.src)
601                imgArr.push(img2)
602              }
603              eventFun(imgArr, imgList)
604            }
605            break
606          case 'list':
607            const imgs = $html.querySelectorAll('img')
608            if (imgs.length) {
609              imgs.forEach(e => imgList.push(e.getAttribute('lazy-src') || e.src))
610              eventFun(imgs, imgList)
611            }
612            break
613          case 'swiper':
614            // 轮播的图片链接去重,打开某张看点击的哪张,从预览列表匹配链接找索引
615            const imgs2 = $html.querySelectorAll('.ce-swiper-slide img')
616            if (imgs2.length) {
617              imgs2.forEach(e => imgList.push(e.getAttribute('lazy-src') || e.src))
618              eventFun(imgs2, imgList)
619            }
620            break
621        }
622      })
623    }
624  }, 500)
625}
626
627// 图片组件鼠标经过或者点击后换图,这里不用判断是否初始化事件,统一初始化一次
628function ceImageSwitch() {
629  const $dom = document.querySelectorAll('div[cloud-editor="unit"][type="image"][double-img="true"], div[cloud-editor="unit"][type="image"][switch-method]')
630  $dom.forEach($html => {
631    const switchMethod = parseInt($html.getAttribute('switch-method') || 0)
632    const originImg = $html.querySelector('.ce-img-double_box .ce-img-double_origin')
633    const otherImg = $html.querySelector('.ce-img-double_box .ce-img-double_other')
634    let controlImg
635    if (switchMethod && switchMethod === 1) {
636      controlImg = $html.querySelector('.ce-img-double_box')
637    } else {
638      controlImg = $html.querySelector('.ce-img-double_icon')
639    }
640
641    if (controlImg) {
642      if (document.body.clientWidth > 768) {
643        controlImg.onmouseenter = () => {
644          originImg.classList.remove('ceFadeIn')
645          originImg.classList.add('ceFadeOut')
646          otherImg.classList.remove('ceFadeOut')
647          otherImg.classList.add('ceFadeIn')
648        }
649
650        controlImg.onmouseleave = () => {
651          originImg.classList.remove('ceFadeOut')
652          originImg.classList.add('ceFadeIn')
653          otherImg.classList.remove('ceFadeIn')
654          otherImg.classList.add('ceFadeOut')
655        }
656      } else {
657        controlImg.onclick = e => {
658          if (originImg.classList.contains('ceFadeOut')) {
659            originImg.classList.remove('ceFadeOut')
660            originImg.classList.add('ceFadeIn')
661            otherImg.classList.remove('ceFadeIn')
662            otherImg.classList.add('ceFadeOut')
663          } else {
664            originImg.classList.remove('ceFadeIn')
665            originImg.classList.add('ceFadeOut')
666            otherImg.classList.remove('ceFadeOut')
667            otherImg.classList.add('ceFadeIn')
668          }
669          e.stopPropagation()
670          e.preventDefault()
671          return false
672        }
673      }
674    }
675
676  })
677}
678
679function ceFold() {
680  const $dom = document.querySelectorAll('div[cloud-editor="unit"][type="faq"]:not([faq-init])')
681  if ($dom.length > 0) {
682    const foldAction = function ($item, fold) {
683      if (fold) {
684        $item.classList.remove('faq_open')
685      } else {
686        $item.classList.add('faq_open')
687      }
688      $item.querySelector('.ce-faq_icon').classList.add(fold ? 'icon-action-plus' : 'icon-action-minus')
689      $item.querySelector('.ce-faq_icon').classList.remove(fold ? 'icon-action-minus' : 'icon-action-plus')
690    }
691
692    $dom.forEach($html => {
693      const $faq = $html.querySelectorAll('[ce-data-type="item"]')
694      const foldMethod = $html.getAttribute('fold-method') || ''
695      $faq.forEach(($item, index) => {
696        if (foldMethod === '') {
697          foldAction($item, false)
698        }
699
700        $item.addEventListener('click', function () {
701          foldAction($item, $item.classList.contains('faq_open'))
702        })
703      })
704    })
705  }
706}
707
708function ceCollapse() {
709  const $dom = document.querySelectorAll('div[cloud-editor="unit"][type="collapse"]:not([collapse-init])')
710  if ($dom.length > 0) {
711    $dom.forEach($html => {
712      $html.setAttribute('collapse-init', 'true') // 设置已经初始化的标识
713
714      const $action = $html.querySelectorAll('[ce-data-type="title"]')
715      $action.forEach(($title) => {
716        if (!$title.getAttribute('click-init')) {
717          $title.addEventListener('click', function () {
718            const $item = $title.parentNode
719            const $content = $item.querySelector('.ce-collapse_content')
720            const fold = $item.classList.contains('collapse_open')
721            if ($content) {
722              if (fold) {
723                $item.classList.remove('collapse_open')
724                $content.style.maxHeight = '0'
725              } else {
726                $item.classList.add('collapse_open')
727                $content.style.maxHeight = '9999px'
728              }
729            }
730          })
731          $title.setAttribute('click-init', 'true')
732        }
733      })
734    })
735  }
736}
737
738function ceVideo() {
739  let $dom = document.querySelectorAll('[is-video]')
740  const $videoDom = document.querySelectorAll('div[cloud-editor="unit"][type="video"]:not([is-video])')
741  $dom = Array.from($dom).concat(Array.from($videoDom))
742  if ($dom.length > 0) {
743    $dom.forEach($html => {
744      $html.setAttribute('video-init', 'true') // 设置已经初始化的标识
745
746      const $playDom = $html.querySelector('.ce-video_play')
747      const $replayDom = $html.querySelector('.ce-video-replay .replay-icon')
748      const $posterDom = $html.querySelector('.ce-video_poster')
749      const $videoDom = $html.querySelector('.ce-video')
750      const $videoCloseDom = $html.querySelector('.ce-video-close')
751      const showControls = !!$videoDom?.getAttribute('controls')
752      const videoLoop = $videoDom?.getAttribute('loop') !== null
753
754      if ($videoDom && $videoDom.getAttribute('autoplay') === 'autoplay') {
755        if ($posterDom) $posterDom.classList.add('hide')
756      }
757      console.log('$playDom',$playDom)
758      console.log('视频播放3',$playDom)
759      let $currentDom
760      if ($playDom) {
761        $playDom.addEventListener('click', () => {
762          console.log('视频播放4',$playDom)
763          // let $currentDom
764          console.log('method123', $videoDom.getAttribute('method'))
765          if ($videoDom.getAttribute('method') === '1') {
766            let newVideoDemo = $videoDom.cloneNode(true)
767            newVideoDemo.style.display = 'block'
768            let newVideoDemo2 = $html.querySelector('.ce-video-replay').cloneNode(true)
769            let videoPopupNode = document.getElementById('video-detail-popup')
770            if (!videoPopupNode) {
771              videoPopupNode = document.createElement('div')
772              videoPopupNode.setAttribute('id', 'video-detail-popup')
773              videoPopupNode.className = 'unit-video-popup__window-wrap'
774              document.body.appendChild(videoPopupNode)
775            }
776
777            videoPopupNode.innerHTML = `
778            <div class="unit-video-popup__window">
779              <div class="unit-video-popup__close">×</div>
780              <div class="unit-video-popup__content">` + newVideoDemo.outerHTML + newVideoDemo2?.outerHTML || '' + `</div>
781            </div>`
782
783            videoPopupNode.getElementsByClassName('unit-video-popup__close')[0].addEventListener('click', function () {
784              videoPopupNode?.classList.remove('show')
785              videoPopupNode?.getElementsByTagName('video')[0].pause()
786              $playDom.classList.remove('d-none')
787            })
788
789            $currentDom = videoPopupNode
790
791            // if (window.app.utilts.checkScreenMobile()) {
792            //   // 手机端
793            //   videoPopupNode.getElementsByTagName("video")[0].requestFullscreen()
794            // }
795            videoPopupNode.classList.add('show')
796          } else {
797            $playDom.classList.add('d-none')
798            $videoDom.style.display = 'block'
799            if ($videoCloseDom) {
800              $videoCloseDom.style.display = 'block'
801            }
802            $currentDom = $html
803            if ($posterDom) $posterDom.classList.add('hide')
804          }
805
806          $currentDom.getElementsByTagName('video')[0].style.pointerEvents = 'auto'
807          $currentDom.getElementsByTagName('video')[0].play()
808          if ($videoCloseDom) {
809            $videoCloseDom.addEventListener('click', () => {
810              $videoCloseDom.style.display = 'none'
811              $videoDom.style.display = 'none'
812              $currentDom.getElementsByTagName('video')[0].pause()
813              $playDom.classList.remove('d-none')
814              if ($posterDom) {
815                $posterDom.classList.remove('hide')
816                const position = window.getComputedStyle($posterDom).position;
817                if (position === 'absolute') {
818                  $videoDom.style.display = 'block'
819                }
820              }
821            }, { once: true })
822          }
823          if ($replayDom) {
824            const video = $currentDom?.getElementsByTagName('video')[0]
825            console.log('video', video)
826            if (video && showControls) {
827              video.addEventListener('ended', () => {
828                if (!videoLoop) {
829                  $currentDom.querySelector('.ce-video-replay').style.display = 'flex'
830                  video.controls = false
831                }
832              })
833            }
834            $currentDom.querySelector('.ce-video-replay .replay-icon')?.addEventListener('click', () => {
835              video.currentTime = 0
836              video.controls = true
837              video?.play();
838              $currentDom.querySelector('.ce-video-replay').style.display = 'none'
839            })
840          }
841        })
842      }
843
844      if ($videoCloseDom) {
845        $videoCloseDom.addEventListener('click', () => {
846          $videoCloseDom.style.display = 'none'
847          $videoDom.style.display = 'none'
848          $videoDom.pause()
849          $playDom.classList.remove('d-none')
850          if ($posterDom) $posterDom.classList.remove('hide')
851        }, { once: true })
852      }
853      if ($replayDom) {
854        const video = $videoDom;
855        if (video && showControls) {
856          video.addEventListener('ended', () => {
857            if (!videoLoop) {
858              $replayDom.style.display = 'flex'
859              video.controls = false
860            }
861          })
862        }
863        $replayDom.addEventListener('click', () => {
864          video.currentTime = 0
865          video.controls = true
866          video.play()
867          $replayDom.style.display = 'none'
868        })
869      }
870    })
871  }
872}
873
874function ceVideoGif() {
875  const $gifDoms = document.querySelectorAll('[video-gif] .ce-list-hover__image')
876  if ($gifDoms.length > 0) {
877    Array.from($gifDoms).forEach(val => {
878      val.addEventListener('click', () => {
879        val.classList.add('d-none')
880        val.parentNode.querySelector('.ce-video_play').click()
881      })
882    });
883  }
884}
885
886function ceDownloadContent() {
887  const checkInquired = function () {
888    const contentId = window.renderInfo && window.renderInfo.page && window.renderInfo.page.content_id || 0
889    let inquired = localStorage.getItem('product_inquired_list')
890    let product_inquired_list = []
891    try {
892      product_inquired_list = JSON.parse(inquired)
893    } catch (e) {
894
895    }
896    if (!Array.isArray(product_inquired_list)) {
897      product_inquired_list = []
898    }
899    return contentId && product_inquired_list.includes(contentId)
900  }
901  document.querySelectorAll('.ce-download_item [ce-data-is_limit="inquiry"][ce-data-type="link"]').forEach(function (item) {
902    if (checkInquired()) {
903      item.removeAttribute('onclick')
904      item.onclick = null
905    }
906    if (item.getAttribute('ce-data-is_limit')) {
907      item.addEventListener('click', function () {
908        if (checkInquired()) {
909          item.removeAttribute('onclick')
910          return true
911        } else {
912          // 触发cloud-web打开询盘事件
913          window.dispatchEvent(new CustomEvent('evt_open_product_inquiry'))
914        }
915        return false;
916      })
917    }
918  })
919
920
921  const checkLogin = function () {
922    const app = window.app
923    const appInfo = app && app.info
924    const loginUser = appInfo && appInfo.user
925    return !!(loginUser && loginUser.is_login)
926  }
927
928  document.querySelectorAll('.ce-download_item [ce-data-is_limit="login"][ce-data-type="link"]').forEach(function (item) {
929    if (checkLogin()) {
930      // 检查登录
931      item.removeAttribute('onclick')
932      item.onclick = null
933    }
934    if (item.getAttribute('ce-data-is_limit')) {
935      item.addEventListener('click', function () {
936        if (checkLogin()) {
937          item.removeAttribute('onclick')
938          return true
939        } else {
940          // 触发cloud-web需要登录事件
941          window.dispatchEvent(new CustomEvent('evt_required_login'))
942        }
943        return false;
944      })
945    }
946  })
947
948}
949
950function ceLink() {
951  document.querySelectorAll('[type="cebutton"] [ce-data-type="link"][target="product_inquiry"]').forEach(function (item) {
952    item.addEventListener('click', function (e) {
953      e.preventDefault()
954      e.stopPropagation()
955      window.dispatchEvent(new CustomEvent('evt_open_product_inquiry'))
956    })
957  })
958}
959
960function ceEditorEventHandler() {
961  // 如果获取不到图片的高度,就换成load事件
962  // window.addEventListener('DOMContentLoaded', () => {
963  // 轮播事件
964  ceInitSwiper()
965  // 选项卡事件
966  ceInitTabs()
967  // tabs-pro 事件
968  ceInitTabsPro()
969  // })
970  // 用监听方法,window.onload的不能重复执行容易与其他js冲突
971  // window.addEventListener('load', () => {
972  // 图片点击放大事件
973  ceImgMagnification()
974  //鼠标经过换图事件
975  ceImageSwitch()
976  // 问答展开事件
977  ceFold()
978  // 折叠事件
979  ceCollapse()
980  // 视频事件
981  ceVideo()
982  ceVideoGif()
983
984  /* 文件下载链接 */
985  ceDownloadContent()
986  // })
987  ceLink()
988}
989
990ceEditorEventHandler()

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.