PageSourceSearch

https://www.meetion.id/assets/js/unit/list-sort.js

js meetion.id collected 2026-10-04 20:37:20 UTC 22,835 bytes, 516 lines download raw bytes

1class ScriptListSort extends Script {
2  constructor(params) {
3    super(params)
4    this.$dom = document.querySelector(`#${this.attrId}`)
5    this.attrIdBym = `${this.attrId}_by-m`;
6    this.$link = this.$dom.querySelectorAll('.unit-list-sort__menu-icon')
7    this.$title = this.$dom.querySelectorAll('.unit-list-sort__title')
8    this.type = params.type
9    this.isCustomer = params.column !== ''
10    this.$mobOverlay = null
11		this.foldMethod = params.foldMethod
12    console.log('this.foldMethod', this.foldMethod);
13		this.mySwiper = null; // 保存 Swiper 实例的引用
14    this.$subNavBox = this.$dom.querySelector('.unit-list-sort__subcontent')
15    this.$navBox = this.$dom.querySelector('.unit-list-sort')
16		this.config = params.config ? JSON.parse(this.utilts.htmlDecode(params.config)) : {column_type: 1, column_style: 1}
17    this.$flatSubmenu = this.$dom.querySelector('.unit-list-sort__subcontent-flat')
18    this.$submenuCover = this.$dom.querySelector('.navigation-submenu__cover')
19  }
20  async init() {
21    this._initEvent()
22    this._initMSortEvent()
23  }
24  /** 初始化事件绑定 */
25  _initEvent() {
26    if (Number(this.type) === 3) {
27      this.$dom.querySelector('.unit-list-sort').style.setProperty('--width', this.$dom.querySelector('.unit-list-sort').offsetWidth + 'px');
28		  let attrId = this.attrId
29      if (this.config.column_type === 1) {
30        this.mySwiper = new Swiper(`#${attrId} .swiper-container`, {
31          speed: 1000,
32          slidesPerView: 'auto',
33          navigation: {
34            nextEl: `#${attrId} .next`,
35            prevEl: `#${attrId} .prev`,
36          },
37          on: {
38            sliderMove: () => {
39              if (this.config.column_style === 1) {
40                this.$subNavBox.classList.remove('show')
41              }
42            }
43          }
44        })
45        if (this.$dom.querySelector(`[aria-disabled="false"]`)) {
46          this.$dom.querySelector('.unit-list-sort__menu').style.justifyContent = 'unset'
47        } else {
48          this.$dom.querySelector('.unit-list-sort__menu').justifyContent = ''
49        }
50      }
51      const sortItems = this.$dom.querySelectorAll('.swiper-slide')
52      for (let $el of sortItems) {
53        $el.addEventListener('mouseenter', () => {
54          if (this.config.column_style === 2) {
55            const menuId = $el.getAttribute('id')
56            const currentWrapper = this.$flatSubmenu.querySelector(`.list-sort-flat_wrapper.container-${menuId}`)
57            if (!currentWrapper) return
58            if (this.$submenuCover) {
59              const $content = $el.children[1]
60              if (!$content) {
61                this.$flatSubmenu.style.height = '0px'
62                this.$submenuCover.classList.remove('navigation-submenu__cover-show')
63              } else {
64                // const currentEleStyle = window.getComputedStyle(this.$navBox)
65                // const borderBottomVal = currentEleStyle.borderBottomStyle !== 'none' && currentEleStyle.borderBottomWidth || '0px'
66                this.$submenuCover.classList.add('navigation-submenu__cover-show')
67                const elRect = $el.getBoundingClientRect()
68                this.$submenuCover.style.top = elRect.bottom + 'px'
69                this.$flatSubmenu.style.position = 'fixed'
70                this.$flatSubmenu.style.top = elRect.bottom + 'px'
71                const maxHeightVal = window.innerHeight - elRect.bottom
72                if (currentWrapper.offsetHeight <= maxHeightVal) {
73                  this.$flatSubmenu.style.height = currentWrapper.offsetHeight + 'px'
74                  this.$flatSubmenu.style['overflow-y'] = 'hidden'
75                } else {
76                  this.$flatSubmenu.style.height = maxHeightVal + 'px'
77                  this.$flatSubmenu.style['overflow-y'] = 'auto'
78                }
79              }
80            }
81            const allWrapper = this.$flatSubmenu.querySelectorAll('.list-sort-flat_wrapper')
82            allWrapper.forEach(val => {
83              val.classList.remove('submenu-wrapper-show')
84            })
85            this.$flatSubmenu.classList.add('navigation-submenu-open')
86            currentWrapper.classList.add('submenu-wrapper-show')
87            currentWrapper.style.width = this.$navBox.offsetWidth + 'px'
88            currentWrapper.style.left = this.$navBox.getBoundingClientRect().left + 'px'
89          } else {
90            this.$subNavBox.classList.remove('show')
91            const $content = $el.children[1]
92            this.$subNavBox.innerHTML = $content ? $content.innerHTML : ''
93            if ($content) {
94              this.$subNavBox.classList.add('show')
95              this.setSecondPosition(this.$subNavBox, $el)
96              let domRect = this.$dom.getBoundingClientRect()
97              let elRect = $el.getBoundingClientRect()
98              this.$subNavBox.style.top = (elRect.top - domRect.top + elRect.height) + 'px'
99            }
100          }
101          replaceZindex('set')
102        })
103      }
104      const hideSubmenu = () => {
105        if (this.$submenuCover) {
106          this.$submenuCover.classList.remove('navigation-submenu__cover-show')
107          this.$submenuCover.style.removeProperty('top')
108          this.$submenuCover.style.removeProperty('position')
109        }
110        this.$flatSubmenu.classList.remove('navigation-submenu-open')
111        this.$flatSubmenu.style.height = '0px'
112        const allWrapper = this.$flatSubmenu.querySelectorAll('.list-sort-flat_wrapper')
113        allWrapper.forEach(val => {
114          val.classList.remove('submenu-wrapper-show')
115        })
116        replaceZindex()
117      }
118      const replaceZindex = (attr) => {
119        if (attr) this.$dom.style.zIndex = 99
120        else this.$dom.style.removeProperty('z-index')
121        const currentCell = this.utilts.getParents(this.$navBox, { attrName: 'package-item', attrValue: 'cell' })[0]
122        if (currentCell) {
123          if (attr) currentCell.style.zIndex = 99
124          else currentCell.style.removeProperty('z-index')
125          if (attr) currentCell.style.position = 'relative'
126          else currentCell.style.removeProperty('position')
127        }
128        const currentGrid = this.utilts.getParents(this.$navBox, { attrName: 'package-item', attrValue: 'grid' })[0]
129        if (currentGrid) {
130          if (attr) currentGrid.style.zIndex = 99
131          else currentGrid.style.removeProperty('z-index')
132          if (attr) currentGrid.style.position = 'relative'
133          else currentGrid.style.removeProperty('position')
134        }
135        const currentModule = this.utilts.getParents(this.$navBox, { attrName: 'package-item', attrValue: 'module' })[0]
136        if (currentModule) {
137          if (attr) currentModule.style.zIndex = 99
138          else currentModule.style.removeProperty('z-index')
139          if (attr) currentModule.style.position = 'relative'
140          else currentModule.style.removeProperty('position')
141        }
142        const currentBlock = this.utilts.getParents(this.$navBox, { attrName: 'package-item', attrValue: 'block' })[0]
143        if (currentBlock) {
144          if (attr) currentBlock.style.zIndex = 99
145          else currentBlock.style.removeProperty('z-index')
146          if (attr) currentBlock.style.position = 'relative'
147          else currentBlock.style.removeProperty('position')
148        }
149      }
150      this.$dom.addEventListener('mouseleave', () => {
151        if (this.config.column_style === 2) {
152          hideSubmenu()
153        } else {
154          this.$subNavBox.classList.remove('show')
155          this.$subNavBox.style.left = '0px'
156          replaceZindex()
157        }
158      })
159      if (this.config.column_style === 2) {
160        window.addEventListener('scroll', () => {
161          if (this.$flatSubmenu.classList.contains('navigation-submenu-open')) {
162            hideSubmenu()
163          }
164        })
165      } else {
166        if (this.$dom.querySelector('.prev')) {
167          this.$dom.querySelector('.prev').addEventListener('click', () => {
168            this.$subNavBox.classList.remove('show')
169            replaceZindex()
170          })
171        }
172        if (this.$dom.querySelector('.next')) {
173          this.$dom.querySelector('.next').addEventListener('click', () => {
174            this.$subNavBox.classList.remove('show')
175            replaceZindex()
176          })
177        }
178      }
179    }
180    if (Number(this.type) === 2) {
181      const parentCell = this.$dom.parentNode
182      // if (parentCell) parentCell.style.zIndex = 8
183      // 产品列表存在属性 unit-attr-text-search__items 引起层级问题
184      if (parentCell) {
185        parentCell.style.zIndex = 8
186        const cellAllstyle = window.getComputedStyle(parentCell)
187        if (cellAllstyle.position === 'static') {
188          parentCell.style.position = 'relative'
189          if (this.utilts.checkDesign()) {
190            parentCell.parentNode.style.zIndex = 8
191          }
192        }
193      }
194
195      const $grateson = this.$dom.querySelectorAll('.unit-list-sort__grateson')
196      if ($grateson && Object.keys($grateson).length > 0) {
197        const domstyle = window.getComputedStyle(this.$dom, null)
198        for (const $i of $grateson) {
199          $i.style.backgroundColor = domstyle['backgroundColor'];
200          // if (domstyle['border'] !== '0px') {
201          //   $i.style.right = 'calc(-100% - ' + domstyle['borderBlockWidth'] + ')'
202          // }
203        }
204      }
205      let sortMenuItemEles = this.$dom.querySelectorAll('.unit-list-sort__son>.unit-list-sort__menu-item')
206      // Array.from(sortMenuItemEles).forEach((_val, index) => {
207      //   if (index == 0 && _val.className.includes('active')) {
208      //     _val.children[1]?.children[0].classList.add('active')
209      //   }
210      // })
211      let hasActive = Array.from(sortMenuItemEles).some(el => {
212        return el.classList.contains('active')
213      })
214      if (!hasActive && sortMenuItemEles.length) {
215        sortMenuItemEles[0]?.classList.add('active')
216      }
217    }
218    if (this.foldMethod !== '') {
219      let sortMenuItemEles = this.$dom.querySelector('.unit-list-sort__menu').children
220      Array.from(sortMenuItemEles).forEach((_val, index) => {
221        _val.classList.remove('active')
222        if (this.foldMethod == 1 && index === 0) {
223          _val.classList.add('active')
224        }
225        if (this.foldMethod == 2) {
226          _val.classList.add('active')
227        }
228      })
229      // 全部展开时,递归展开所有有子菜单的节点
230      if (this.foldMethod == 2) {
231        // 找到所有有子菜单的菜单项(有 .unit-list-sort__menu-content 子元素)
232        const allMenuItemsWithChildren = this.$dom.querySelectorAll('.unit-list-sort__menu-item')
233        allMenuItemsWithChildren.forEach(menuItem => {
234          const hasChildren = Array.from(menuItem.children).some(child =>
235            child.classList.contains('unit-list-sort__menu-content')
236          )
237          if (hasChildren) {
238            menuItem.classList.add('active')
239            // console.log('menuItem', menuItem)
240
241            const $Grateson = Array.from(menuItem.children).find(child =>
242              child.classList.contains('unit-list-sort__grateson')
243            )
244            if ($Grateson) {
245              // console.log('$Grateson',$Grateson)
246              $Grateson.classList.add('expend-all')
247            }
248          }
249
250        })
251      }
252    }
253
254    if (!this.utilts.checkDesign()) {
255      if (Object.keys(this.$title).length > 0) {
256        for (const $li of this.$title) {
257          $li.addEventListener('click', (e) => {
258            location.href = $li.parentNode.parentNode.href;
259          })
260        }
261      }
262    }
263    if (Number(this.type) !== 3) {
264      for (const $li of this.$link) {
265        $li.addEventListener('click', (e) => {
266          if (e.target.className) {
267            e.preventDefault()
268            const parentNodes = $li.parentNode.parentNode.parentNode
269            const brother = this.utilts.getSiblings(parentNodes)
270            parentNodes.classList.toggle('active')
271            if (Number(this.type) === 1 && (this.foldMethod != 2 || (this.foldMethod == 2 && parentNodes.parentNode?.classList.contains('unit-list-sort__menu-content')))) {
272              for (let $el of brother) $el.classList.remove('active')
273            }
274            if (Number(this.type) === 2) {
275              for (let $el of brother) $el.classList.remove('active')
276              const $activeList = $li.parentNode.parentNode.parentNode.querySelectorAll('.active')
277              $activeList.forEach(item => item.classList.remove('active'))
278              // this.$unitList = this.$dom.querySelectorAll('.unit-list-sort__menu-item')
279              // for (let $el of this.$unitList) $el.classList.remove('current');
280              // parentNodes.classList.add('current')
281            }
282          }
283        })
284      }
285    }
286  }
287  setSecondPosition($target, $parent) {
288    const pLeft = this.utilts.getOffset($parent).left
289    const boxLeft = this.utilts.getOffset(this.$navBox).left
290    if (pLeft < 0) {
291      $target.style.left = 0 + 'px'
292    } else if (pLeft + 250 > window.innerWidth) {
293      $target.style.left = (pLeft + $parent.offsetWidth - boxLeft - $target.offsetWidth) + 'px'
294    } else {
295      $target.style.left = (pLeft - boxLeft) + 'px'
296    }
297    if (Number(this.type) === 3) {
298      $target.style.left = `calc(${$target.style.left} + ${window.getComputedStyle(this.$dom)['paddingLeft']})`
299    }
300    $target.style.width = 'auto'
301  }
302  setLevelNavTree(item, level = 0) {
303    if (!item) return []
304    const sonNav = []
305    const sonMenuEles = item.children
306    level = ++level
307    Array.from(sonMenuEles).forEach(_val => {
308      const menuLinkEle = _val.children[0]
309      const menuItemContent = _val.children[1]
310      const menuText = menuLinkEle.querySelector('.unit-list-sort__title').innerText
311      sonNav.push({
312        title: menuText,
313        href: menuLinkEle.href,
314        level,
315        is_active: _val.classList.contains("active") || _val.classList.contains("fill-active"),
316        is_current: menuLinkEle.children[0].classList.contains("unit-list-sort__link-current"),
317        children: menuItemContent ? this.setLevelNavTree(menuItemContent, level) : []
318      })
319    })
320    return sonNav
321  }
322  setMenuOverlay() {
323    if (!document.querySelector('.mobile_menu_overlay')) {
324      const $overlay = document.createElement('div')
325      $overlay.classList.add('mobile_menu_overlay')
326      document.body.append($overlay)
327    }
328    document.querySelector('.mobile_menu_overlay').style.position = 'fixed'
329    this.$mobOverlay = document.querySelector('.mobile_menu_overlay')
330  }
331  setTreeHtml(data) {
332    let levelObj = {
333      1: 'first',
334      2: 'second',
335      3: 'third',
336      4: 'fourth'
337    }
338    let str = ``
339    str += `
340      ${data.map(item => {
341      return `
342          <div class="${levelObj[this.isCustomer ? item.level : item.level - 1]}-item sort-menu-content_item ${item.is_active ? 'active' : ''}">
343            <a href="${item.href}" class="unit-sort-menu_link ${item.is_current ? 'current-link' : ''}">
344              <div class="sort-menu-name_box"><span class="unit-sort-menu_name follow-font-family" text-style="3">${item.title}</span></div>
345              ${item.children.length ? `<span class="unit-sort-menu_drop iconfont icon-action-left-lighter"></span>` : ''}
346            </a>
347            ${item.children.length ? `
348              <div class="sort-menu-${levelObj[this.isCustomer ? item.level + 1 : item.level]}_item-content sort-menu-content ${item.is_active ? 'show' : ''}">
349                ${this.setTreeHtml(item.children)}
350              </div>
351            ` : ''}
352          </div>`
353    }).join('')
354      }
355    `
356    return str
357  }
358  setSonContent(contentArr, isShowFirst) {
359    let str = ``
360    if (contentArr && contentArr.length) {
361      str += `
362        <div class="sort-menu-${isShowFirst ? 'first' : 'second'}_item-content sort-menu-content ${!isShowFirst ? 'hidden-first-content' : ''}">
363          ${this.setTreeHtml(isShowFirst ? contentArr : contentArr[0].children, isShowFirst ? true : false)}
364        </div>
365      `
366    }
367    return str
368  }
369  _initMSortEvent() {
370    let allSortMenuEle = this.$dom.querySelector('[package-unit-type="list_sort"]:not([hide-phone]) .unit-list-sort__menu')
371    if (!allSortMenuEle) return
372    const cSortMenuByM = document.querySelector(`#${this.attrIdBym}`);
373    if (!cSortMenuByM) {
374      return;
375    }
376    if (this.utilts.checkDesign()) {
377      const $header = document.querySelector('[package-item="block"][package-type="header"]');
378      const cSortMenuByM = this.$dom.querySelector(`#${this.attrIdBym}`);
379      if (!cSortMenuByM) return
380      // 更新dom
381      $header?.querySelector(`#${this.attrIdBym}`)?.remove();
382      cSortMenuByM.classList.add('only-pc-design')
383      $header?.appendChild(cSortMenuByM)
384      return
385    }
386    if (cSortMenuByM.hasAttribute('data-rendered')) {
387      return;
388    } else {
389      cSortMenuByM.setAttribute('data-rendered', '');
390    }
391    let menuArr = []
392    try {
393      const script = cSortMenuByM.querySelector(`script[data-id="${this.attrIdBym}"]`);
394      const menuData = script?.innerText;
395      if (menuData) {
396        menuArr = JSON.parse(menuData)
397      }
398    } catch (e) {
399      console.error(e)
400    }
401    // menuArr = this.setLevelNavTree(allSortMenuEle);
402    // 不展示一级
403    // if (!this.isCustomer) menuArr = menuArr.reduce((prev, next) => prev.concat(next.children), [])
404    // console.log(' menuArr', menuArr);
405    if (!menuArr.length) return;
406    // alert(JSON.stringify(menuArr))
407    // if (document.querySelector('.unit-sort-menu_by-m')) return
408    // if (!document.querySelector('.unit-sort-menu_by-m')) {
409    //   cSortMenuByM = document.createElement('div')
410    //   cSortMenuByM.classList.add('unit-sort-menu_by-m')
411    // }
412    let sonContentStr = ``
413    // let menuStr =
414    //   `<div class="unit-sort-menu_body">
415    //     <div>
416    //       <div class="unit-sort-menu_list">
417    //         ${menuArr.map((_val, index) => {
418    //     return `
419    //       <div class="unit-sort-menu_item">
420    //         <a href="${_val.href}" data-index="${index}">
421    //           <span>${_val.title}</span>
422    //           ${_val.children.length ? `<span class="iconfont-box iconfont icon-action-bottom-lighter"></span>` : ''}
423    //         </a>
424    //       </div>
425    //   `
426    //   }).join('')}
427    //       </div>
428    //       <div class="menu-show-icon">
429    //         <span class="iconfont-box iconfont icon-base-list"></span>
430    //       </div>
431    //     </div>
432    //     <div class="unit-sort-menu_content-box sort-menu-content_item active">
433    //       ${sonContentStr}
434    //     </div>
435    //   </div>
436    //   <div class="unit-sort-menu_line"></div>
437    // `;
438    // cSortMenuByM.innerHTML = menuStr;
439    // document.querySelector('[package-type="header"]')?.appendChild(cSortMenuByM)
440    cSortMenuByM.addEventListener('click', (e) => {
441      const fMenuSortBody = this.utilts.getParentsByAttr(e.target, 'class', 'unit-sort-menu_body')[0]
442      const fMenuSortContent = fMenuSortBody.querySelector('.unit-sort-menu_content-box')
443      if (e.target.className.includes('iconfont-box') || e.target.className.includes('menu-show-icon')) {
444        e.preventDefault()
445        let isFlag = true
446        if (e.target.className.includes('menu-show-icon') || e.target.className.includes('icon-base-list')) {
447          Array.from(fMenuSortBody.querySelectorAll('.unit-sort-menu_list .unit-sort-menu_item')).forEac
447h(_val => _val.classList.remove('active'))
448          if (e.target.className.includes('menu-show-icon')) {
449            if (e.target.className.includes('active')) {
450              fMenuSortContent.classList.remove('show')
451              fMenuSortContent.children[0].classList.remove('show')
452              if (this.$mobOverlay) this.$mobOverlay.style.display = 'none'
453              e.target.classList.remove('active')
454              isFlag = false
455            } else {
456              e.target.classList.add('active')
457            }
458          }
459          if (e.target.className.includes('icon-base-list')) {
460            if (e.target.parentNode.className.includes('active')) {
461              fMenuSortContent.classList.remove('show')
462              fMenuSortContent.children[0].classList.remove('show')
463              if (this.$mobOverlay) this.$mobOverlay.style.display = 'none'
464              e.target.parentNode.classList.remove('active')
465              isFlag = false
466            } else {
467              e.target.parentNode.classList.add('active')
468            }
469          }
470          if (isFlag) sonContentStr = this.setSonContent(menuArr, true)
471        }
472        if (e.target.className.includes('icon-action-bottom-lighter')) {
473          fMenuSortBody.querySelector('.menu-show-icon').classList.remove('active')
474          let unitSortMenuItem = e.target.parentNode.parentNode
475          Array.from(unitSortMenuItem.parentNode.children).filter(child => child !== unitSortMenuItem).forEach(sibling => {
476            sibling.classList.remove('active')
477          })
478          if (unitSortMenuItem.className.includes('active')) {
479            unitSortMenuItem.classList.remove('active')
480            if (cSortMenuByM.querySelector('.hidden-first-content') && cSortMenuByM.querySelector('.hidden-first-content').className.includes('show')) {
481              fMenuSortContent.classList.remove('show')
482              fMenuSortContent.children[0].classList.remove('show')
483              if (this.$mobOverlay) this.$mobOverlay.style.display = 'none'
484              isFlag = false
485            }
486          } else {
487            unitSortMenuItem.classList.add('active')
488            isFlag = true
489          }
490          if (isFlag) sonContentStr = this.setSonContent([menuArr[e.target.parentNode.getAttribute('data-index')]])
491        }
492        if (!isFlag) return
493        cSortMenuByM.querySelector('.unit-sort-menu_content-box').innerHTML = sonContentStr
494        this.setMenuOverlay()
495        if (this.$mobOverlay) this.$mobOverlay.style.display = 'block'
496        fMenuSortContent.classList.add('show')
497        fMenuSortContent.children[0].classList.add('show')
498      }
499      if (e.target.className.includes('icon-action-left-lighter')) {
500        e.preventDefault()
501        let sortMenuContentItem = e.target.parentNode.parentNode
502        Array.from(sortMenuContentItem.parentNode.children).filter(child => child !== sortMenuContentItem).forEach(sibling => {
503          sibling.classList.remove('active')
504          Array.from(sibling.querySelectorAll('.sort-menu-content')).forEach(_val => _val.classList.remove('show'))
505        })
506        if (sortMenuContentItem.children[1].className.includes('show')) {
507          sortMenuContentItem.classList.remove('active')
508          sortMenuContentItem.children[1].classList.remove('show')
509        } else {
510          sortMenuContentItem.classList.add('active')
511          sortMenuContentItem.children[1].classList.add('show')
512        }
513      }
514    })
515  }
516}

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.