Men's American Racing-themed Casual Printed Short-Sleeved T-shirt

$17.99
Size: 
Quantity
Description
Product ID SP260416HGSC
Season All Season
Occasion Sports, daily life, leisure (free time)
Washing Mode Machine Wash
Material Cotton Blend
Fit Regular
Collar/Neckline Round Collar
Yards (cm) S M L XL 2XL 3XL 4XL 5XL
UK 8/10 12/14 16 18 20 twenty two twenty four 26
US 4/6 8/10 12 14 16 18 20 twenty two
EU 36/38 40/42 44 46 48 50 52 54
Bust 94 99 104 109 114 119 124 129
Waistline 80 85 90 95 100 105 110 115
Hips 97 102 107 112 117 122 127 132
Shoulder Width 43.5 45 46.5 48 49.5 51 52.5 54
weight (kg) 55-60 60-65 65-70 70-75 75-80 80-85 85-90 90-95


Shipping & Returns

Shipping & Processing

Free shipping on orders over $99

Standard Delivery: All orders process and ship within 5 business days after being placed

More Info: Shipping Policy

RETURNS

We want you to be 100% satisfied with your purchase.

Return Window: Return requests can be submitted within 30 days of delivery.

Condition: Products must be unused, undamaged, and in their original packaging.

Exclusions: Clearance items, final sale items, and discounted items are not eligible for returns or exchanges.

More Info: Returns & Refunds

Reviews
const TAG = 'spz-custom-revue-util'; const DEFAULT_DELAY_TIME = 100; class SpzCustomRevueUtil extends SPZ.BaseElement { constructor(element) { super(element); this.templates_ = SPZServices.templatesForDoc(); } buildCallback = () => { this.action_ = SPZServices.actionServiceForDoc(this.element); this.templates_ = SPZServices.templatesForDoc(this.element); this.xhr_ = SPZServices.xhrFor(this.win); } static deferredMount() { return false; } mountCallback() { } debounceRender(el, thisEl, containerStr) { return this.smoothRender_(el, thisEl, containerStr).then(() => this.attemptToFit_(thisEl)); } smoothRender_(newEl, thisEl, containerStr) { const that = this; that.appendAsUnvisibleContainer_(newEl, thisEl); const components = newEl.querySelectorAll('[layout]'); return Promise.race([ Promise.all( Array.prototype.map.call(components, (e) => SPZ.whenDefined(e).then(() => e.whenBuilt()) ) ), SPZServices.timerFor(that.win).promise(DEFAULT_DELAY_TIME), ]).then(() => { return containerStr !== 'form_' ? thisEl.mutateElement(() => that.quickReplace(thisEl, newEl)) : thisEl.mutateElement(() => that.quickReplaceForm(thisEl, newEl)); }); } quickReplace(thisEl, newEl) { thisEl.container_ && this.toggleVisible_(thisEl.container_); this.toggleVisible_(newEl, true); thisEl.container_ && SPZCore.Dom.removeElement(thisEl.container_); thisEl.container_ = newEl; }; quickReplaceForm(thisEl, newEl) { thisEl.form_ && this.toggleVisible_(thisEl.form_); this.toggleVisible_(newEl, true); const children = thisEl.form_.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); this.toggleVisible_(thisEl.form_, true); thisEl.form_.appendChild(newEl); }; appendAsUnvisibleContainer_(el, thisEl) { this.toggleVisible_(el); thisEl.element.appendChild(el); } attemptToFit_(thisEl) { const fitFunc = () => { thisEl.mutateElement(this.setElementHeight_.bind(thisEl)); }; const container = thisEl.container_ || thisEl.form_; if (container) { const children = container.querySelectorAll('*:not(template)'); const spzChildren = Array.prototype.filter .call(children, SPZUtils.isSpzElement) .filter((e) => !(e.isMount && e.isMount())); spzChildren .map((e) => SPZ.whenDefined(e).then(() => e.whenMounted())) .forEach((p) => p.then(() => fitFunc())); } return fitFunc(); } setElementHeight_() { const targetHeight = (this.container_ || this.form_)?./*OK*/ scrollHeight; const height = this.element./*OK*/ offsetHeight; if (height !== targetHeight) { SPZCore.Dom.setStyles(this.element, { height: `${targetHeight}px`, }); } } toggleVisible_(el, visible = false) { if (!visible) { el.classList.add('i-spzhtml-layout-fill'); SPZCore.Dom.setStyles(el, { 'z-index': -100000, 'opacity': 0, }); } else { el.classList.remove('i-spzhtml-layout-fill'); SPZCore.Dom.setStyles(el, { 'z-index': 'auto', 'opacity': 1, }); } } setMinWidth_() { const targetWidth = this.container_?./*OK*/ scrollWidth; const width = this.element./*OK*/ offsetWidth; if (width !== targetWidth) { SPZCore.Dom.setStyles(this.element, { 'min-width': `${targetWidth}px`, }); } } triggerEvent_ = (name, data) => { const event = SPZUtils.Event.create(this.win, `${TAG}.${name}`, data || {}); this.action_.trigger(this.element, name, event); } isLayoutSupported(layout) { return layout == SPZCore.Layout.CONTAINER; } } SPZ.defineElement(TAG, SpzCustomRevueUtil); const TAG = 'spz-custom-revue-star'; class SPZCustomRevueStar extends SPZ.BaseElement { constructor(element) { super(element); } static deferredMount() { return false; } buildCallback = () => { this.action_ = SPZServices.actionServiceForDoc(this.element); this.templates_ = SPZServices.templatesForDoc(this.element); this.xhr_ = SPZServices.xhrFor(this.win); this.starNum = this.element.getAttribute('starNum'); this.starTotal = this.element.getAttribute('starTotal'); this.showStarText = this.element.getAttribute('showStarText'); this.starColor = this.element.getAttribute('color'); this.interact = this.element.getAttribute('interact'); this.starSize = this.element.getAttribute('starSize') || 14; } mountCallback = () => { this.doRender_({ starTotal: this.starTotal, totalArray: Array.from({ length: Number(this.starTotal) }, (v, k) => k + 1), starNum: this.starNum, showStarText: this.showStarText, starColor: this.starColor, starSize: this.starSize }).then(() => { if (this.interact) { this.addEventListeners_(); } }); } addEventListeners_ = () => { const stars = document.querySelectorAll('.revue-star__star'); stars.forEach(star => { star.addEventListener('click', event => { const starEl = star.closest('.revue-star__star'); const starIndex = Number(starEl.dataset.index); let isHalf = event.offsetX < star.offsetWidth / 2; // rtl if (document.documentElement.getAttribute('dir') === 'rtl') { isHalf = event.offsetX > star.offsetWidth / 2; } const starValue = isHalf ? starIndex - 0.5 : starIndex; this.starClickHandler_({ value: starValue }); }); }); } renderStar = () => { const isRtl = document.documentElement.getAttribute('dir') === 'rtl'; const stars = this.element.querySelectorAll('.revue-star__star'); stars.forEach((star, i) => { const starIndex = i + 1; const starEl = star.querySelector('svg:nth-child(2)'); const isHalf = this.starNum % 1 > 0 && Math.ceil(this.starNum) === starIndex; const isSolid = starIndex <= Math.ceil(this.starNum); starEl.style.display = isSolid ? 'block' : 'none'; if (isHalf) { if (isRtl) { // RTL布局下,如果是半星,显示星星的右半边 starEl.style.clipPath = `polygon(50% 0, 100% 0, 100% 100%, 50% 100%)`; } else { // LTR布局下,如果是半星,显示星星的左半边 starEl.style.clipPath = `polygon(0 0, 50% 0, 50% 100%, 0 100%)`; } } else { starEl.style.clipPath = `polygon(0 0, 100% 0, 100% 100%, 0 100%)` } }); const showCountEle = this.element.querySelector('#revue-star-show-count'); showCountEle && SPZ.whenApiDefined(showCountEle).then((api) => { api.render({ starNum: this.starNum, starTotal: this.starTotal }); }); } doRender_ = (data) => { return this.templates_ .findAndRenderTemplate(this.element, { starSize: this.starSize, ...data }, null) .then((el) => { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); this.element.appendChild(el); }) .then(() => { this.starNum = data.starNum; this.renderStar(); }); } starClickHandler_ = (event) => { this.starNum = event.value; this.renderStar(); this.triggerEvent_('change', { value: event.value }); } triggerEvent_(name, data) { const event = SPZUtils.Event.create(this.win, `${ TAG }.${ name }`, data || {}); this.action_.trigger(this.element, name, event); } isLayoutSupported(layout) { return layout == SPZCore.Layout.CONTAINER; } } SPZ.defineElement(TAG, SPZCustomRevueStar) const TAG = 'spz-custom-revue-like'; class SPZCustomRevueLike extends SPZ.BaseElement { constructor(element) { super(element); } static deferredMount() { return false; } buildCallback = () => { this.action_ = SPZServices.actionServiceForDoc(this.element); this.templates_ = SPZServices.templatesForDoc(this.element); this.xhr_ = SPZServices.xhrFor(this.win); this.grayColor = this.element.getAttribute('gray_color') || "#BDBDBD"; this.likedColor = this.element.getAttribute('like_color') || "#FFCB44"; this.color = this.grayColor; this.count = this.element.getAttribute('count'); this.revueId = this.element.getAttribute('revue-id'); this.location = this.element.getAttribute('location'); } mountCallback = () => { const likes = sessionStorage.getItem('likes') ? JSON.parse(sessionStorage.getItem('likes')) : []; const like = likes.find(item => item.id === this.revueId); if (like) { this.color = like.like_status === 1 ? this.likedColor : this.grayColor; } // 如果location是modal,则找到相同revue-id的list的元素,拿到其count,存在list count变了,但是modal的count没变的情况 if (this.location === 'modal') { const listElement = document.querySelector(`spz-custom-revue-like[revue-id="${this.revueId}"] .revue-like-count`); if (listElement) { this.count = listElement.getAttribute('data-real-count'); } } this.doRender_({ color: this.color, count: this.count }).then(() => { this.addEventListeners_(); if(this.location === 'list') { // modal数量变更,list同步变更 document.addEventListener('like-clicked', (e) => { if (e.detail.location !== this.location && e.detail.id === this.revueId) { this.color = e.detail.like_status === 1 ? this.likedColor : this.grayColor; this.count = e.detail.count; this.element.querySelector('.revue-like__icon').querySelector('svg').setAttribute('fill', this.color); this.element.querySelector('.revue-like__icon').querySelector('svg').querySelector('path').setAttribute('fill', this.color); this.element.querySelector('.revue-like-count').innerText = this.count > 99 ? '99+' : this.count < 1 ? '' : this.count; this.element.querySelector('.revue-like-count').setAttribute('data-real-count', this.count); if(this.count > 0){ this.element.querySelector('.revue-like-count').classList.remove('hidden'); }else{ this.element.querySelector('.revue-like-count').classList.add('hidden'); } } }); } }); } addEventListeners_ = () => { const icon = this.element.querySelector('.revue-like__icon'); icon.addEventListener('click', (e) => { e.stopPropagation(); const likeStatus = this.color === this.likedColor ? 0 : 1; this.color = this.color === this.likedColor ? this.grayColor : this.likedColor; this.count = likeStatus === 1 ? parseInt(this.count) + 1 : parseInt(this.count) - 1; icon.querySelector('svg').setAttribute('fill', this.color); icon.querySelector('svg').querySelector('path').setAttribute('fill', this.color); this.element.querySelector('.revue-like-count').innerText = this.count > 99 ? '99+' : this.count < 1 ? '' : this.count; this.element.querySelector('.revue-like-count').setAttribute('data-real-count', this.count); if(this.count > 0){ this.element.querySelector('.revue-like-count').classList.remove('hidden'); }else{ this.element.querySelector('.revue-like-count').classList.add('hidden'); } this.postLike(likeStatus); if (this.location === 'modal') { const clickedEvent = new CustomEvent('like-clicked', { detail: { id: this.revueId, like_status: likeStatus, count: this.count, location: this.location } }); document.dispatchEvent(clickedEvent); } }); } setLikeToStorage = (likeToStore) => { if (typeof (Storage) !== 'function') return; const likesInStore = sessionStorage.getItem('likes') ? JSON.parse(sessionStorage.getItem('likes')) : []; const reviewIndex = likesInStore.findIndex(item => item.id === likeToStore.id); if (reviewIndex !== -1) { likesInStore[reviewIndex].like_status = likeToStore.like_status; likesInStore[reviewIndex].count = likeToStore.count; } else { likesInStore.push(likeToStore); } sessionStorage.setItem('likes', JSON.stringify(likesInStore)); } doRender_ = (data) => { return this.templates_ .findAndRenderTemplate(this.element, data, null) .then((el) => { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); this.element.appendChild(el); }); } postLike = (likeStatus) => { fetch('/api/comment/like', { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ id: this.revueId, status: likeStatus }) }).then((res) => { if (res.status === 200) { this.setLikeToStorage({ id: this.revueId, like_status: likeStatus, count: this.count }); } }); } triggerEvent_(name, data) { const event = SPZUtils.Event.create(this.win, `${ TAG }.${ name }`, data || {}); this.action_.trigger(this.element, name, event); } isLayoutSupported(layout) { return layout == SPZCore.Layout.CONTAINER; } } SPZ.defineElement(TAG, SPZCustomRevueLike) const TAG = 'spz-custom-review-media'; class SPZCustomReviewMedia extends SPZ.BaseElement { constructor(element) { super(element); } static deferredMount() { return false; } buildCallback = () => { this.action_ = SPZServices.actionServiceForDoc(this.element); this.templates_ = SPZServices.templatesForDoc(this.element); this.xhr_ = SPZServices.xhrFor(this.win); // data-images 格式为 xxxx.png?width=1&height=1,xxxx.png?width=1&height=1 const images = this.element.getAttribute('data-images').split(',') || []; const parsedImages = images.map(image => { return this.mediaParse_(image); }); this.images = parsedImages; this.isPC = window.innerWidth > 960; } mountCallback = () => { this.doRender_({ images: this.images, isPC: this.isPC }).then(() => { }); } doRender_ = (data) => { return this.templates_ .findAndRenderTemplate(this.element, data, null) .then((el) => { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); this.element.appendChild(el); }); } mediaParse_ = function (url) { var result = {}; try { url.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (str, key, value) { try { result[key] = decodeURIComponent(value); } catch (e) { result[key] = value; } }); result.preview_image = url.split('?')[0]; } catch (e) {}; return result; } triggerEvent_(name, data) { const event = SPZUtils.Event.create(this.win, `${ TAG }.${ name }`, data || {}); this.action_.trigger(this.element, name, event); } isLayoutSupported(layout) { return layout == SPZCore.Layout.CONTAINER; } } SPZ.defineElement(TAG, SPZCustomReviewMedia) const TAG = 'spz-custom-revue-carousel'; class SpzCustomRevueCarourel extends SPZ.BaseElement { constructor(element) { super(element); this.debouncedCartChangeHandler = null; } static deferredMount() { return false; } buildCallback = () => { this.action_ = SPZServices.actionServiceForDoc(this.element); this.setupAction_(); this.reviewsList = [] this.isPC = window.innerWidth > (window.breakpoint || 960); this.blockIndex = this.element.getAttribute('data-block-index'); this.blockSectionId = this.element.getAttribute('data-section-id'); this.commentConfig = window.globaCarouselSettings[this.blockIndex] const { star_least, only_complex, only_show_selected } = this.commentConfig; this.params = { star_least: Number(star_least) || 1, only_media: !!only_complex, show_reply: true, limit: 20, offset: 0, filter_type: 'product', show_product: true, only_featured: !!only_show_selected, } this.debouncedCartChangeHandler = this.debounce_(this.renderReviewsByCartProducts_.bind(this), 500); } mountCallback = () => { const { isNeedFill, min } = this.getIfFillReviews_(); if (this.blockSectionId == 'cart_drawer') { this.product_ids = this.commentConfig.cart_products_id; } else { this.product_ids = window.SHOPLAZZA.meta.page.resource_id; }; this.params = { ...this.params, product_ids: this.product_ids || '', ...isNeedFill ? { fill_strategy: 'store', fill_min_threshold: min } : {} }; this.fetchConfigReviewsCarousel_(); if (this.blockSectionId == 'cart_drawer') { document.removeEventListener('dj.cartChange', this.debouncedCartChangeHandler); document.addEventListener('dj.cartChange', this.debouncedCartChangeHandler); } } unmountCallback() { document.removeEventListener('dj.cartChange', this.debouncedCartChangeHandler); } setupAction_ = () => { this.registerAction('renderProductCommentModal', async(invocation) => { const { current } = invocation.args; const currentReview = this.reviewsList.find(_data => _data.id == current); const imgArr = currentReview.img.map(image => { const width = this.getUrlKey_('width', image); const height = this.getUrlKey_('height', image); return { width, height, rate: (height/width).toFixed(2)*100, url: image }; }); const modalEle = document.querySelector(`#revueDetailModal-${this.blockSectionId}`); if (modalEle) { SPZ.whenApiDefined(modalEle).then((api) => { api.renderModalFn({ data: { ...currentReview, img: imgArr }, ...this.blockSectionId == 'cart_drawer' ? { mimic_mobile_style: true } : {}, closeCB: () => { const carouselEl = document.querySelector(`#reviews-carousel-${this.blockSectionId}-${this.blockIndex}`); if(carouselEl){ carouselEl.removeAttribute('pause'); } }, commentConfig: this.commentConfig, // 评论配置 layout: '', // 布局 level_type: this.commentConfig.star_least, // 最低星级 show_number: 1 // 显示数量 }); }) const carouselEl = document.querySelector(`#reviews-carousel-${this.blockSectionId}-${this.blockIndex}`); if(carouselEl){ carouselEl.setAttribute('pause', ''); } } }); } getUrlKey_ = (name, url) => { return ( decodeURIComponent( (new RegExp("[?|&]" + name + "=" + "([^&;]+?)(&|#|;|$)").exec( url ) || [, ""])[1].replace(/\+/g, "%20") ) || null ); } getIfFillReviews_ = () => { const { comment_handle_type, review_type, min_comments_count } = this.commentConfig; const min = Number(min_comments_count); const isExistFillType = comment_handle_type !== 'no_carousel_card'; return { isNeedFill: isExistFillType, min: review_type == 'less than' ? min : 1 }; } debounce_ = (func, delay) => { let timeoutId; return (...args) => { // 使用箭头函数保留实例上下文 clearTimeout(timeoutId); timeoutId = setTimeout(() => { func(...args); }, delay); }; } fetchCommentConfig_ = async () => { const response = await fetch('/api/comment-config'); return response.json(); } fetchCommentList_ = async(data) => { const response = await fetch('/api/v1/comments', { method: 'POST', body: JSON.stringify(data) }); return response.json(); } fetchCartList_ = async() => { const response = await fetch(`/api/cart`); return response.json(); } renderReviewsByCartProducts_ = async () => { try { const data = await this.fetchCartList_(); this.product_ids = data?.cart?.line_items.map(item => item.product_id).join(','); if (this.product_ids) { this.params = { ...this.params, product_ids: this.product_ids, }; const commentsRes = await this.fetchCommentList_(this.params); const { isNeedFill, min } = this.getIfFillReviews_(); const isBlank = !isNeedFill && Number(commentsRes.data.count) < min; this.renderReviewsList_({ list: isBlank ? { list: [] } : commentsRes.data, config: this.commentConfig }); } } catch (err) { this.renderEmptyReviewCarousel_(); } } fetchConfigReviewsCarousel_ = ()=> { Promise.all([this.fetchCommentConfig_(), this.fetchCommentList_(this.params)]) .then(([configRes, commentsRes]) => { const rawColor = this.commentConfig.carousel_accent_color const star_color = !rawColor ? configRes.data.star_color : rawColor; this.commentConfig = { ...this.commentConfig, ...configRes.data, star_color, }; const { isNeedFill, min } = this.getIfFillReviews_(); const isBlank = !isNeedFill && Number(commentsRes.data.count) < min; this.renderReviewsList_({ list: isBlank ? { list: [] } : commentsRes.data, config: this.commentConfig }); }) .catch(error => { this.renderEmptyReviewCarousel_(); }); } renderEmptyReviewCarousel_ = () => { const emptyEle = document.querySelector(`#revue_empty-${this.blockSectionId}-${this.blockIndex}`); const isInB = window.top != window.self; if (emptyEle && isInB) { emptyEle.classList.remove('hidden'); } const carouselEle = document.querySelector(`#revue-carousel-box-${this.blockSectionId}-${this.blockIndex}`); if (carouselEle) { carouselEle.classList.add('hidden'); } } renderReviewsList_ = (data) => { const listEle = document.querySelector(`#revue-carousel-box-${this.blockSectionId}-${this.blockIndex}`); const emptyEle = document.querySelector(`#revue_empty-${this.blockSectionId}-${this.blockIndex}`); if (listEle) { if (data.list.list.length == 0) { this.renderEmptyReviewCarousel_(); } else { listEle.classList.remove('hidden'); if (emptyEle) { emptyEle.classList.add('hidden'); } SPZ.whenApiDefined(listEle).then((api) => { api.render({ ...data, list: data.list.list, star_color: this.commentConfig.star_color, isPC: this.isPC, }, true); }) .catch((error) => { console.log(error); }); }; } this.reviewsList = data.list.list } triggerEvent_(name, data) { const event = SPZUtils.Event.create(this.win, `${ TAG }.${ name }`, data || {}); this.action_.trigger(this.element, name, event); } isLayoutSupported(layout) { return layout == SPZCore.Layout.CONTAINER; } } SPZ.defineElement(TAG, SpzCustomRevueCarourel) const TAG = 'spz-custom-revue-modal'; class SPZCustomRevueModal extends SPZ.BaseElement { constructor(element) { super(element); this.renderedId = ''; this.closeCB = null; this.sectionId = this.element.getAttribute('section-id'); } static deferredMount() { return false; } buildCallback = () => { this.setupAction_(); } mountCallback = () => { } setupAction_ = () => { this.registerAction('renderModal', this.renderModalFn) this.registerAction('closeFn',() => { this?.closeCB?.() }) } mediaParse_ = function (url) { var result = {}; try { url.replace(/[?&]+([^=&]+)=([^&]*)/gi, function (str, key, value) { try { result[key] = decodeURIComponent(value); } catch (e) { result[key] = value; } }); result.src = url.split('?')[0]; } catch (e) {}; return result; } impFunc = function (selector, cb) { // 添加自动曝光 const el = document.querySelector(selector); const onImpress = () => { cb(); }; // 元素未曝光时添加曝光事件监听,已曝光则可以立刻触发处理器 if (el && !el.getAttribute('imprsd')) { el.addEventListener('impress', onImpress); } else if (el) { onImpress(); } }; addModalImpression = function (selector, params) { this.impFunc(selector, () => { window.sa && window.sa.track('plugin_reviews_modal_pv', { ...params, plugin_timestamp: new Date().valueOf().toString(), }); }); }; renderModalFn(receivedData){ if(!receivedData) return; const { data:current, commentConfig, layout, level_type, show_number, closeCB, mimic_mobile_style, props } = receivedData; try{ if(closeCB){ this.closeCB = () => { closeCB() }; } }catch(e){ console.log(e); }; const commentModalEl = document.querySelector(`#revue-product-comment-modal-${this.sectionId}`); const modalRenderEl = document.querySelector(`#revue_flow_modal_render-${this.sectionId}`); if (!!mimic_mobile_style) { if (commentModalEl) { commentModalEl.classList.add('mobile-wrap'); } if (modalRenderEl) { modalRenderEl.classList.add('w-h-full-h5'); } }; const parsedImages = current?.img?.map(image => { return this.mediaParse_(`${image.url}?width=${image.width}&height=${image.height}`); }); const modalEle = document.querySelector(`#revue_flow_modal_render-${this.sectionId}`); if (modalEle) { SPZ.whenApiDefined(modalEle).then((api) => { api.render({ ...current, img: parsedImages, config: commentConfig, shop_name: window.SHOPLAZZA.shop.shop_name, mimic_mobile_style }, true).then(() => { this.addModalImpression('.revue_modal_container', { id: current.id, username: current.username, content: current.content, star: current.star, is_verified: current.is_verified, is_featured: current.is_featured, anonymous: current.anonymous, iso_code_3: current.iso_code_3, like_count: current.like, layout_type: layout, level_type: level_type, show_number: show_number, }); }).then(()=>{ this.renderedId = current.id }); }); } } isLayoutSupported(layout) { return layout == SPZCore.Layout.CONTAINER; } } SPZ.defineElement('spz-custom-revue-modal', SPZCustomRevueModal) const TAG = 'spz-custom-revue-selector'; class SpzCustomRevueSelector extends SPZ.BaseElement { constructor(element) { super(element); } buildCallback = () => { this.action_ = SPZServices.actionServiceForDoc(this.element); this.templates_ = SPZServices.templatesForDoc(this.element); this.total = this.element.getAttribute('total'); this.blockIndex = this.element.getAttribute('blockIndex'); this.setupAction_(); } setupAction_ = () => { this.registerAction('toggleChangeSelector', async (invocation) => { const { option } = invocation.args; const total = Number(this.total); this.updateDots_(option, total); }); } updateDots_ = (currentIndex, totalDots) => { const dots = this.element.querySelectorAll('.dot'); if (totalDots < 2 || dots?.length < 1) return; const maxVisibleDots = 5; // 重置所有点 dots?.forEach(dot => { dot.classList.remove('active', 'scaled'); }); // 设置当前激活点 if (dots[currentIndex]) { dots[currentIndex].classList.add('active'); } // 计算显示的点和缩放效果 let startIndex = 0; let endIndex = totalDots - 1; let visibleRange = [0, totalDots - 1]; let translateX = 0; if (totalDots > maxVisibleDots) { // 计算可见范围 if (currentIndex < maxVisibleDots - 1) { // 前 maxVisibleDots-1 个点 startIndex = 0; endIndex = maxVisibleDots - 1; translateX = 0; } else if (currentIndex >= totalDots - (maxVisibleDots - 1)) { // 最后 maxVisibleDots-1 个点 startIndex = totalDots - maxVisibleDots; endIndex = totalDots - 1; translateX = -(totalDots - maxVisibleDots) * 8; } else { // 中间点 startIndex = currentIndex - Math.floor(maxVisibleDots / 2); endIndex = currentIndex + Math.floor(maxVisibleDots / 2); // 调整边界情况 if (startIndex < 0) { endIndex -= startIndex; startIndex = 0; } if (endIndex >= totalDots) { startIndex -= (endIndex - totalDots + 1); endIndex = totalDots - 1; } translateX = -startIndex * 8; } // 设置可见范围 visibleRange = [startIndex, endIndex]; // 设置点的缩放效果 // 最左边的点(除了第一个) if (startIndex > 0) { dots[startIndex].classList.add('scaled'); } // 最右边的点(除了最后一个) if (endIndex < totalDots - 1) { dots[endIndex].classList.add('scaled'); } // 特殊处理第一个和最后一个点 if (currentIndex === 0) { dots[0].classList.remove('scaled'); } if (currentIndex === totalDots - 1) { dots[totalDots - 1].classList.remove('scaled'); } } // 设置dotsWrap的位置 const dotsWrap = this.element.querySelector('#dotsWrap'); if (dotsWrap) { dotsWrap.style.transform = `translateX(${translateX}px)`; } } mountCallback() { this.doRender_({ total: this.total, blockIndex: this.blockIndex }); } doRender_ = (data) => { return this.templates_ .findAndRenderTemplate(this.element, data, null) .then((el) => { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); this.element.appendChild(el); }) } triggerEvent_ = (name, data) => { const event = SPZUtils.Event.create(this.win, `${TAG}.${name}`, data || {}); this.action_.trigger(this.element, name, event); } isLayoutSupported(layout) { return layout == SPZCore.Layout.CONTAINER; } } SPZ.defineElement(TAG, SpzCustomRevueSelector);