1class ScriptTabs extends Script { 2 constructor(params) { 3 super(params) 4 this.$dom = document.querySelector(`#${this.attrId}`) 5 this.$swiperButtonPrev = this.$dom.querySelector('.swiper-button-prev') 6 this.$swiperButtonNext = this.$dom.querySelector('.swiper-button-next') 7 this.$tabsHeader = this.$dom.querySelector(`.unit-tabs__header`) 8 this.$tabsNavWrap = this.$dom.querySelector(`.unit-tabs__nav-wrap`) 9 this.$panelWrap = this.$dom.querySelector('.unit-tabs__panel-wrap') 10 this.$tabItems = this.$dom.querySelectorAll('.unit-tabs__nav-item') 11 this.$tabPanels = this.$panelWrap.querySelectorAll('.unit-tabs__panel') 12 13 this.config = JSON.parse(this.utilts.htmlDecode(params.config)) 14 this.tab_list = JSON.parse(this.utilts.htmlDecode(params.tab_list).replace(/\n<\s*br\s*\/*\s*>/ig, '<br/>').replace(/\n<\s*p\s*>/ig, '<p>').replace(/<\s*p\s*>\n/ig, '<p>').replace(/\n<\s*\/p\s*>/ig, '</p>')) 15 this.columnsInfo = JSON.parse(this.utilts.htmlDecode(params.columnsInfo)) 16 // mock ---------------- 17 // params.colInfo = undefined 18 // ---------------------- 19 if (params.colInfo) { 20 this.colInfo = JSON.parse(this.utilts.htmlDecode(params.colInfo)) 21 } else { 22 let columnsObj = { 23 1: '12', 24 2: '6', 25 3: '4', 26 4: '3', 27 5: '2_4', 28 6: '2', 29 7: '12_7', 30 8: '12_8', 31 9: '12_9', 32 10: '12_10', 33 11: '12_11', 34 12: '1' 35 } 36 this.colInfo = { 37 cols_col: columnsObj[this.columnsInfo.default], 38 cols_md: columnsObj[this.columnsInfo.md], 39 cols_xl: columnsObj[this.columnsInfo.xl], 40 } 41 } 42 43 this.activeIndex = 0 44 if (this.utilts.checkDesign()) { // è£ ä¿®æ¶ï¼éæ°æ¸²æä¿æ activeIndexï¼é¿å ç¼è¾å ¶ä»tabçå å®¹æ»æ¯è·³å第ä¸ä¸ªtab 45 if (!window.tabsState) window.tabsState = {}; 46 if (!window.tabsState[this.attrId]) window.tabsState[this.attrId] = { activeIndex: 0 } 47 if (window.tabsState[this.attrId].activeIndex < this.tab_list.length) { 48 this.activeIndex = window.tabsState[this.attrId].activeIndex 49 } 50 } 51 52 // å·¥å · 53 this.utilts = window.app.utilts 54 } 55 56 async init() { 57 // siwper 58 if (!window.Swiper) await new Load('/assets/plugins/swiper.min.js') 59 this.utilts.interObserver(this.$dom, () => { // é¿å æ¬ç»ä»¶å¨display:noneçç¶æåå§åï¼å¯¼è´swiperæ ·å¼é®é¢ï¼ä¾å¦å¨column-tabs䏿·»å tabsï¼ 60 this.initScreen() 61 window.addEventListener('resize', () => { 62 if (this.currentScreen === this.utilts.getScreen()) return 63 this.initScreen() 64 }) 65 this.checkBlank() 66 }, false) 67 } 68 initScreen() { 69 this.currentScreen = this.utilts.getScreen() 70 this.initTab() 71 // this.initContentSwiper() 72 this.initContentSwiperHack() 73 } 74 initTab() { 75 this.$tabsSwiper?.destroy(true, true) 76 if (this.utilts.checkDesign()) { 77 this.$tabItems.forEach((it, i) => { // html ä¸é»è®¤ç¬¬ä¸ä¸ªæ¯ activeï¼éè¦åæ¥ä¸ä¸ window.tabsState[this.attrId].activeIndex 78 if (i === this.activeIndex) { 79 it.classList.add('active') 80 } else { 81 it.classList.remove('active') 82 } 83 }) 84 } 85 86 const swiperConfig = { 87 slidesPerView: this.columnsInfo[this.currentScreen], 88 spaceBetween: 0, 89 initialSlide: this.activeIndex, 90 // slideToClickedSlide: true, 91 // centeredSlides: true, 92 freeMode: true, 93 navigation: { 94 prevEl: '.swiper-button-prev', 95 nextEl: '.swiper-button-next', 96 }, 97 on: { 98 // slideChange: (swiper) => { 99 // this.tabClick(swiper, swiper.activeIndex) 100 // }, 101 } 102 } 103 104 this.$dom.querySelector(`#initBetween_${this.attrId}`)?.remove() 105 106 if (['default', 'md'].includes(this.currentScreen)) { 107 this.$swiperButtonPrev.classList.remove('d-none') 108 this.$swiperButtonNext.classList.remove('d-none') 109 this.$tabsHeader.classList.add('swiper-container') 110 this.$tabsNavWrap.classList.add('swiper-wrapper') 111 this.$dom.querySelectorAll(`.unit-tabs__nav-item`).forEach(($item) => { 112 $item.classList.add('swiper-slide') 113 }) 114 // setTimeout(() => { 115 swiperConfig.spaceBetween = this.initBetween() 116 this.$tabsSwiper = new Swiper(`#${this.attrId} .unit-tabs__header`, swiperConfig) 117 // },); 118 } else { 119 this.$swiperButtonPrev.classList.add('d-none') 120 this.$swiperButtonNext.classList.add('d-none') 121 this.$tabsHeader.classList.remove('swiper-container') 122 this.$tabsNavWrap.classList.remove('swiper-wrapper') 123 this.$dom.querySelectorAll(`.unit-tabs__nav-item`).forEach(($item) => { 124 $item.classList.remove('swiper-slide') 125 }) 126 } 127 this.initEvent() 128 } 129 initBetween() { // 廿é´è·ï¼è¯»åé´è·çå¼ä¼ ç»swiperå¤ç 130 const itemClass = 'unit-tabs__nav-item' 131 const $itemFirst = this.$dom.querySelector(`.${itemClass}`) 132 if (!$itemFirst) return 133 const style = this.utilts.getNodeStyle($itemFirst) 134 const item_pr = parseFloat(style.paddingRight) || 0 135 const item_pl = parseFloat(style.paddingLeft) || 0 136 const item_mr = parseFloat(style.marginRight) || 0 137 const item_ml = parseFloat(style.marginLeft) || 0 138 139 140 const $style = document.createElement('style') 141 $style.setAttribute('id', `initBetween_${this.attrId}`) 142 143 let html = `#${this.attrId} .unit-tabs__nav-wrap {margin:0!important;} 144 #${this.attrId} .${itemClass}{margin-left:0!important;padding:0!important} 145 #${this.attrId} .col-${this.colInfo.cols_col.toString().replace('.', '_')}, #${this.attrId} .col-md-${this.colInfo.cols_md.toString().replace('.', '_')}, #${this.attrId} .col-xl-${this.colInfo.cols_xl.toString().replace('.', '_')} {max-width: unset; flex: none}` 146 $style.innerHTML = html 147 this.$dom.appendChild($style) 148 return item_pr + item_pl + item_mr + item_ml 149 } 150 initContentSwiper() { 151 if (this.$contentSwiper) return 152 const swiperConfigBase = { 153 effect: 'fade', 154 initialSlide: this.activeIndex, 155 noSwiping: true, 156 noSwipingClass: 'swiper-slide', 157 speed: 0, 158 } 159 const swiperConfig = { 160 ...swiperConfigBase 161 } 162 163 const swiperConfigMobile = { 164 ...swiperConfigBase, 165 // controller: { 166 // control: this.$tabsSwiper, // æ§å¶ this.$tabsSwiper 167 // }, 168 // on: { 169 // slideChange: (swiper) => { 170 // this.tabChange(swiper, swiper.activeIndex) 171 // } 172 // } 173 } 174 setTimeout(()=>{ 175 this.$contentSwiper = new Swiper(`#${this.attrId} .unit-tabs__content`, ['default', 'md'].includes(this.currentScreen) ? swiperConfigMobile : swiperConfig) 176 // if (['default', 'md'].includes(this.currentScreen)) { this.$tabsSwiper.controller.control = this.$contentSwiper } 177 }) 178 } 179 initContentSwiperHack() { 180 const slideTo = () => {
181 this.$tabPanels.forEach((tabItem, tabIndex) => { 182 if (tabIndex === this.activeIndex) { 183 tabItem.style.display = '' 184 } else { 185 tabItem.style.display = 'none' 186 } 187 }) 188 } 189 slideTo() 190 if (this.$contentSwiper) return 191 this.$contentSwiper = { 192 slideTo 193 } 194 } 195 initEvent() { 196 this.$tabItems.forEach((item, index) => { 197 item.addEventListener('click', (e) => this.tabClick(e, index)) 198 }) 199 } 200 tabChange(e, index) { 201 if (this.utilts.checkDesign()) { 202 window.tabsState[this.attrId].activeIndex = index 203 } 204 this.activeIndex = index 205 this.$tabItems.forEach(it => it.classList.remove('active')) 206 this.$tabItems[index].classList.add('active') 207 208 this.checkBlank() 209 } 210 tabClick(e, index) { 211 this.tabChange(e, index) 212 if (['default', 'md'].includes(this.currentScreen)) { 213 this.$tabsSwiper.slideTo(index) 214 } 215 this.$contentSwiper.slideTo(index) 216 this.$panelWrap.querySelectorAll('[data-observer]').forEach(($item) => { 217 if ('_observer' in $item && $item._observer instanceof Function) { 218 // åæ¢æ¶æ§è¡å¾çå è½½æ£æ¥ 219 $item._observer() 220 } else { 221 $item.removeAttribute('[data-observer]') 222 } 223 }) 224 } 225 checkBlank() { 226 if (!this.tab_list[this.activeIndex].tab_panel.length) { 227 this.$dom.classList.add('blank-package') 228 } else { 229 this.$dom.classList.remove('blank-package') 230 } 231 } 232}
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.