Free Shipping For Order Over $120
Home
🔥AB DRILL HIGH QUALITY🔥
🔥Promotional Kit
🔥New Arrival🔥
X.99 Zone
All For $2.99
All For $3.99
All For $4.99
All For $6.99
Diamond Painting Drill Type
Full Round Drill DP
Full Square Diamond Painting
Full Rhinestone DP
Special Shaped Diamond Painting
Mystery DP
Diamond Painting Series
African
Abstract Art
Car
Cat
Children's Series
Christmas
Chucks & Pearls
5D flower
Dog
Dream Catcher Crafts
Eyeglasses
Fashion Girl
Flag
Halloween
Lion
Pink Flower
Saying
Tiger
Tracey Richter
Tree
Photo Custom
Big Size
🖍Accessories🖌
DIY Crafts
Diamond Painting Coaster
Diamond Painting Ornament
Diy Pendant
DIY Keychain
Diamond cup stickers
Diamond Wooden Trays With Handle
DIY Mirror
Bookmark
Diy Bag
Diy Earrings
Bling Bling
Diamond painting crafts
DIY Baseball Cap
DIY Christmas Gift Bag
Diy Comb
DIY Diamond Painting Tag
Diy Fingertip Gyroscope
DIY Glasses
Diy Kitchen Apron
Diy Mask Storage Box
Diy Led Light
DIY Pen Holder
DIY Three-Dimensional Painting
Jewelry Box
Free Kits
Buy 2 Get 1 Free
Dream painting
Login
Register
Login
Register
Learn More
new arrivals
Quick View
Luxury AB Velvet Diamond Painting Kit - Ocean Goddess
mysite
$27.99
Quick View
Luxury AB Velvet Diamond Painting Kit - Glass Bird
mysite
$27.99
Quick View
Luxury AB Velvet Diamond Painting Kit - Indians
mysite
$27.99
Quick View
Luxury AB Velvet Diamond Painting Kit - Woman
mysite
$27.99
Quick View
15%
OFF
Luxury AB Velvet Diamond Painting Kit - Playing cards
mysite
$21.99
$25.99
Quick View
23%
OFF
Luxury AB Velvet Diamond Painting Kit - elves and owls
mysite
$19.99
$25.99
Quick View
Luxury AB Velvet Diamond Painting Kit - Landscape
mysite
$26.99
Quick View
Luxury AB Velvet Diamond Painting Kit - Butterfly wings
mysite
$26.99
Quick View
Luxury AB Velvet Diamond Painting Kit - Purple flowers
mysite
$27.99
Quick View
23%
OFF
Luxury AB Velvet Diamond Painting Kit - A glowing landscape
mysite
$19.99
$25.99
Quick View
Luxury AB Velvet Diamond Painting Kit - Angels of the Sea
mysite
$27.99
Quick View
Luxury AB Velvet Diamond Painting Kit - Colorful landscape
mysite
$26.99
Quick View
15%
OFF
Luxury AB Velvet Diamond Painting Kit - Purple House
mysite
$21.99
$25.99
Quick View
15%
OFF
Luxury AB Velvet Diamond Painting Kit - Cat
mysite
$21.99
$25.99
Quick View
15%
OFF
Luxury AB Velvet Diamond Painting Kit - Purple Cat
mysite
$21.99
$25.99
View all
🔥AB Aurora Custom Diamond Painting
Diamond Paint Hobby
$19.95
Shop Now
67%
OFF
Custom Diamond Painting - Personalized Diamond Art
mysite
$5.99
$17.99
Shop Now
DIY keychain
Quick View
38%
OFF
9 pcs DIY Diamond Painting Keychain | Christmas (single sided)
mysite
$9.99
$15.99
Quick View
20%
OFF
22pcs DIY Diamond Painting Keychain | Christmas (Single Side)
diamondpeintre
$15.99
$19.99
Quick View
38%
OFF
9 pcs DIY Diamond Painting Keychain | animal (single sided)
mysite
$9.99
$15.99
Quick View
30%
OFF
16pcs DIY Diamond Painting Keychain | Christmas (Single Side)
diamondpeintre
$13.99
$19.99
Quick View
60%
OFF
6pcs DIY Diamond Painting Keychain | snowman (Single Side)
diamondpeintre
$7.99
$19.99
Quick View
20%
OFF
20pcs DIY Diamond Painting Keychain | snowman (Single Side)
QLUO
$15.99
$19.99
Quick View
60%
OFF
6pcs DIY Diamond Painting Keychain | Santa Claus (Single Side)Christmas
diamondpeintre
$7.99
$19.99
Quick View
30%
OFF
16pcs DIY Diamond Painting Keychain | snowman (Single Side)
diamondpeintre
$13.99
$19.99
Quick View
60%
OFF
6pcs DIY Diamond Painting Keychain | snowman (Single Side)
diamondpeintre
$7.99
$19.99
Quick View
40%
OFF
12pcs DIY Diamond Painting Keychain | snowman (Single Side)
mysite
$11.99
$19.99
View all
🔥diamond Ornaments🔥
Quick View
Free shipping - DIY Pendant Decoration | - 8pcs Mystery Series
mysite
$21.99
Quick View
DIY Pendant Decoration | - 4pcs Mystery Series
mysite
$3.99
Quick View
74%
OFF
DIY Diamond Painting Pendant | Cartoon
diamondpeintre
$6.99
$26.89
Quick View
74%
OFF
DIY Diamond Painting Pendant | Cartoon
diamondpeintre
$6.99
$26.89
Quick View
74%
OFF
DIY Diamond Painting Pendant | Cartoon
diamondpeintre
$6.99
$26.89
Quick View
74%
OFF
DIY Diamond Painting Pendant | Cartoon
diamondpeintre
$6.99
$26.89
Quick View
74%
OFF
DIY Diamond Painting Pendant | Cartoon
diamondpeintre
$6.99
$26.89
Quick View
74%
OFF
DIY Diamond Painting Pendant | Cartoon
diamondpeintre
$6.99
$26.89
Quick View
74%
OFF
DIY Diamond Painting Pendant | Cartoon
diamondpeintre
$6.99
$26.89
Quick View
74%
OFF
DIY Diamond Painting Pendant | Cartoon
diamondpeintre
$6.99
$26.89
View all
🔥High End AB DP🔥
Quick View
15%
OFF
AB Diamond Painting | Life Tree
mysite
$21.99
$25.99
Quick View
31%
OFF
AB Diamond Painting | hot air balloon
mysite
$17.99
$25.99
Quick View
15%
OFF
Luxury AB Velvet Resin Diamond Painting Kit - Mr. Punk
mysite
$21.99
$25.99
Quick View
23%
OFF
AB Diamond Painting | OWL
mysite
$19.99
$25.99
Quick View
15%
OFF
AB Diamond Painting | Owl
mysite
$21.99
$25.99
Quick View
31%
OFF
AB Diamond Painting | Garden Girl
mysite
$17.99
$25.99
Quick View
15%
OFF
AB Diamond Painting | Flower Eye
mysite
$21.99
$25.99
Quick View
75%
OFF
Diamond Painting - Dream Castle
Diamond Paint Hobby
$19.95
$79.95
Quick View
15%
OFF
AB Diamond Painting | girl
mysite
$21.99
$25.99
Quick View
19%
OFF
AB Diamond Painting | Colorful dragon
mysite
$20.99
$25.99
Quick View
15%
OFF
Luxury AB Velvet Diamond Painting Kit | Fey version of the mad hatter
mysite
$21.99
$25.99
Quick View
31%
OFF
AB Diamond Painting | Dreaming of her
mysite
$17.99
$25.99
Quick View
15%
OFF
AB Diamond Painting | Mask
mysite
$21.99
$25.99
Quick View
15%
OFF
AB Diamond Painting | Angel Wings
mysite
$16.99
$19.99
Quick View
Luxury AB Velvet Diamond Painting Kit - Santa ClausChristmas
mysite
$22.99
Quick View
15%
OFF
AB Diamond Painting | The witch
mysite
$21.99
$25.99
Quick View
15%
OFF
AB Diamond Painting | Colorful Butterfly In The Forest
mysite
$21.99
$25.99
Quick View
19%
OFF
AB Diamond Painting | Sunflower Storm
mysite
$20.99
$25.99
Quick View
27%
OFF
AB Diamond Painting | Girl And Dragon
mysite
$18.99
$25.99
Quick View
15%
OFF
Luxury AB Velvet Diamond Painting Kit | Elf
mysite
$21.99
$25.99
Quick View
10%
OFF
AB Diamond Painting | Rose
mysite
$18.99
$20.99
Quick View
15%
OFF
AB Diamond Painting | Hot Air Balloon
mysite
$21.99
$25.99
Quick View
15%
OFF
AB Diamond Painting | Glass Flower
mysite
$16.99
$19.99
Quick View
15%
OFF
AB Diamond Painting | Seahorse
mysite
$21.99
$25.99
View all
cartoon
Quick View
10%
OFF
Luxury AB Velvet Diamond Painting Kit - Cartoon
mysite
$17.99
$19.99
Quick View
10%
OFF
Luxury AB Velvet Diamond Painting Kit - Cartoon
mysite
$17.99
$19.99
Quick View
10%
OFF
Luxury AB Velvet Diamond Painting Kit - Cartoon Halloween
mysite
$17.99
$19.99
Quick View
10%
OFF
Luxury AB Velvet Diamond Painting Kit - Cartoon
mysite
$17.99
$19.99
Quick View
10%
OFF
Luxury AB Velvet Diamond Painting Kit - Cartoon
mysite
$17.99
$19.99
Quick View
10%
OFF
Luxury AB Velvet Diamond Painting Kit - Cartoon
mysite
$17.99
$19.99
Quick View
10%
OFF
Luxury AB Velvet Diamond Painting Kit - Cartoon
mysite
$17.99
$19.99
Quick View
10%
OFF
Luxury AB Velvet Diamond Painting Kit -Cartoon
mysite
$17.99
$19.99
Quick View
Alphabet Series Diamond Painting(Canvas) - Cartoon
mysite
$1.99
Quick View
Alphabet Series Diamond Painting(Canvas) - Cartoon
mysite
$0.99
View all
Canvas painting(not diy)
Quick View
70%
OFF
Canvas painting 4 piece set -Cartoon(50x50cm )
QLUO
$8.99
$29.99
Quick View
70%
OFF
Canvas painting 4 piece set -Cartoon(50x50cm )
QLUO
$8.99
$29.99
Quick View
70%
OFF
Canvas painting 4 piece set -Cartoon(50x50cm )
QLUO
$8.99
$29.99
Quick View
70%
OFF
Canvas painting 4 piece set -Cartoon(50x50cm )
QLUO
$8.99
$29.99
Quick View
70%
OFF
Canvas painting 4 piece set -Cartoon(50x50cm )
QLUO
$8.99
$29.99
Quick View
70%
OFF
Canvas painting 4 piece set -Cartoon(50x50cm )
QLUO
$8.99
$29.99
Quick View
67%
OFF
Canvas painting 6 piece set -Cartoon(40x60cm)
QLUO
$9.99
$29.99
Quick View
70%
OFF
Canvas painting 3 piece set -Cartoon(40x60cm)
QLUO
$8.99
$29.99
Quick View
70%
OFF
Canvas painting 6 piece set -Cartoon(30x40cm )
QLUO
$8.99
$29.99
Quick View
70%
OFF
Canvas painting 6 piece set -Cartoon(30x40cm )
QLUO
$8.99
$29.99
View all
Iron on Transfers Patches Sticker
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
40%
OFF
Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$2.99
$4.99
Quick View
40%
OFF
Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$2.99
$4.99
View all
Car coaster
Quick View
60%
OFF
2pc Car Cup Holder Coaster | Cartoon(No diamonds)
diamondpeintre
$7.99
$19.99
Quick View
60%
OFF
2pc Car Cup Holder Coaster | Cartoon(No diamonds)
diamondpeintre
$7.99
$19.99
Quick View
60%
OFF
2pc Car Cup Holder Coaster | Cartoon(No diamonds)
diamondpeintre
$7.99
$19.99
Quick View
60%
OFF
2pc Car Cup Holder Coaster | Cartoon(No diamonds)
diamondpeintre
$7.99
$19.99
Quick View
60%
OFF
2pc Car Cup Holder Coaster | Cartoon(No diamonds)
diamondpeintre
$7.99
$19.99
Quick View
60%
OFF
2pc Car Cup Holder Coaster | Cartoon(No diamonds)
diamondpeintre
$7.99
$19.99
Quick View
60%
OFF
2pc Car Cup Holder Coaster | Cartoon(No diamonds)
diamondpeintre
$7.99
$19.99
Quick View
60%
OFF
2pc Car Cup Holder Coaster | Cartoon(No diamonds)
diamondpeintre
$7.99
$19.99
Quick View
60%
OFF
2pc Car Cup Holder Coaster | Cartoon(No diamonds)
diamondpeintre
$7.99
$19.99
Quick View
60%
OFF
2pc Car Cup Holder Coaster | Cartoon(No diamonds)
diamondpeintre
$7.99
$19.99
View all
Special Shaped diamond painting
Quick View
Partial Special Shaped Diamond Painting - Cartoon
diamondpeintre
$6.99
Quick View
Partial Special Shaped Diamond Painting - Cartoon
diamondpeintre
$6.99
Quick View
Partial Special Shaped Diamond Painting - Cartoon
diamondpeintre
$6.99
Quick View
Partial Special Shaped Diamond Painting - Cartoon
diamondpeintre
$6.99
Quick View
Partial Special Shaped Diamond Painting - Cartoon
diamondpeintre
$6.99
Quick View
Partial Special Shaped Diamond Painting - Cartoon
diamondpeintre
$6.99
Quick View
Partial Special Shaped Diamond Painting - Cartoon
diamondpeintre
$6.99
Quick View
Partial Special Shaped Diamond Painting - Cartoon
diamondpeintre
$6.99
Quick View
Partial Special Shaped Diamond Painting - Cartoon
diamondpeintre
$6.99
Quick View
Partial Special Shaped Diamond Painting - Cartoon
diamondpeintre
$6.99
View all
Diamond Photo Frame
Quick View
43%
OFF
Diamond Painting Special Shape Floral Photo Frame -20*20
diamondpeintre
$16.99
$29.99
Quick View
43%
OFF
Diamond Painting Special Shape Floral Photo Frame -20*20
diamondpeintre
$16.99
$29.99
Quick View
43%
OFF
Diamond Painting Special Shape Floral Photo Frame -20*15
diamondpeintre
$16.99
$29.99
Quick View
43%
OFF
Diamond Painting Special Shape Floral Photo Frame -20*15
diamondpeintre
$16.99
$29.99
Quick View
43%
OFF
Diamond Painting Special Shape Floral Photo Frame -20*15
diamondpeintre
$16.99
$29.99
Quick View
43%
OFF
Diamond Painting Special Shape Floral Photo Frame -20*15
diamondpeintre
$16.99
$29.99
Quick View
43%
OFF
Diamond Painting Special Shape Floral Photo Frame -20*15
diamondpeintre
$16.99
$29.99
Quick View
43%
OFF
Diamond Painting Special Shape Floral Photo Frame -20*15
diamondpeintre
$16.99
$29.99
View all
Mini Square Diamond Painting
Quick View
25%
OFF
16pcs Mini Square Diamond Painting - Christmas
diamondpeintre
$29.99
$39.99
Quick View
40%
OFF
12pcs Mini Square Diamond Painting -Flower
diamondpeintre
$23.99
$39.99
Quick View
40%
OFF
12pcs Mini Square Diamond Painting -Plant
diamondpeintre
$23.99
$39.99
Quick View
40%
OFF
11pcs Mini Square Diamond Painting -Plant
diamondpeintre
$23.99
$39.99
Quick View
60%
OFF
6pcs Mini Square Diamond Painting -Mandala
diamondpeintre
$15.99
$39.99
Quick View
53%
OFF
9pcs Mini Square Diamond Painting -Bee
diamondpeintre
$18.99
$39.99
Quick View
40%
OFF
12pcs Mini Square Diamond Painting -Planet
diamondpeintre
$23.99
$39.99
Quick View
40%
OFF
12pcs Mini Square Diamond Painting -Clock
diamondpeintre
$23.99
$39.99
View all
Afternoon Tea Display
Quick View
25%
OFF
DIY Diamond Art Painting Three Layer Afternoon Tea Display | Mandala
diamondpeintre
$29.99
$39.99
Quick View
25%
OFF
DIY Diamond Art Painting Three Layer Afternoon Tea Display | Mandala
diamondpeintre
$29.99
$39.99
Quick View
25%
OFF
DIY Diamond Art Painting Three Layer Afternoon Tea Display | Mandala
diamondpeintre
$29.99
$39.99
Quick View
25%
OFF
DIY Diamond Art Painting Three Layer Afternoon Tea Display | Mandala
diamondpeintre
$29.99
$39.99
Quick View
25%
OFF
DIY Diamond Art Painting Three Layer Afternoon Tea Display | Mandala
diamondpeintre
$29.99
$39.99
Quick View
25%
OFF
DIY Diamond Art Painting Three Layer Afternoon Tea Display | Mandala
diamondpeintre
$29.99
$39.99
Quick View
25%
OFF
DIY Diamond Art Painting Three Layer Afternoon Tea Display | Mandala
diamondpeintre
$29.99
$39.99
Quick View
25%
OFF
DIY Diamond Art Painting Three Layer Afternoon Tea Display | Mandala
diamondpeintre
$29.99
$39.99
View all
🔥Diamond Painting Wooden Trays With Handle
Quick View
Diamond Painting Wooden Trays With Handle - Butterfly
diamondpeintre
$29.99
Quick View
Diamond Painting Wooden Trays With Handle - Christmas
diamondpeintre
$29.99
Quick View
Diamond Painting Wooden Trays With Handle - Fruit
diamondpeintre
$29.99
Quick View
Diamond Painting Wooden Trays With Handle - Mandala
diamondpeintre
$29.99
Quick View
Diamond Painting Wooden Trays With Handle - Mandala
diamondpeintre
$29.99
Quick View
Diamond Painting Wooden Trays With Handle - Sunflower
diamondpeintre
$29.99
Quick View
8%
OFF
DIY Diamond Painting Decor Wooden Food Tray - Highland Cattle
diamondpeintre
$36.99
$39.99
Quick View
8%
OFF
DIY Diamond Painting Decor Wooden Food Tray - Flower
diamondpeintre
$36.99
$39.99
View all
stickers
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
57%
OFF
12pcs Diamond Painting Stickers - Cartoon
mysite
$2.99
$6.99
Quick View
57%
OFF
8pcs Diamond Painting Stickers - Cartoon
mysite
$2.99
$6.99
Quick View
57%
OFF
500pcs non-drilled stickers
mysite
$2.99
$6.99
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
Quick View
50%
OFF
4Pcs Iron on Transfers Patches Sticker - Cartoon
diamondpeintre
$7.99
$15.99
View all
Tool
Quick View
70%
OFF
Refillable Wax Pen - Diamond Painting Pen | Stainless steel tool
diamondpeintre
$0.90
$3.00
Quick View
54%
OFF
1pc DIY Diamond Painting Point Drill Pen | Standable Punt Pen-tool
mysite
$3.99
$8.69
Quick View
65%
OFF
230cm/Self-adhesive Flexible Foam Molding Trim | 3D Sticky Decorative Wall Lines Wallpaper Border Frame-tool
QLUO
$5.99
$16.99
Quick View
54%
OFF
1pc DIY Diamond Painting Point Drill Pen | Standable Punt Pen-tool
mysite
$3.99
$8.69
Quick View
63%
OFF
Diamond Drawing Tools | Ring and 100pc Storage Bag
diamondpeintre
$1.99
$5.33
Quick View
82%
OFF
A5 (Transparent shell)Ring binder for collecting and sorting DMC stones - DIY Diamond Painting | accesories | Tool
mysite
$1.99
$10.99
Quick View
67%
OFF
Diamond Painting Tools Bead Storage jar Bottles Accessories
QLUO
$9.99
$29.99
Quick View
87%
OFF
1pc DIY Diamond Painting Point Drill Pen | Syringe-tool
diamondpeintre
$2.99
$23.32
View all
Dream painting
Quick View
Pink House | Full Round/Square Diamond Painting Kits | 50x70cm | 60x80cm|80X100CM
diamondpeintre
$13.99
Quick View
Pink House | Full Round/Square Diamond Painting Kits | 50x70cm | 60x80cm|80X100CM
diamondpeintre
$13.99
Quick View
House | Full Round/Square Diamond Painting Kits | 50x70cm | 60x80cm|80X100CM
diamondpeintre
$13.99
Quick View
Pink House | Full Round/Square Diamond Painting Kits | 50x70cm | 60x80cm|80X100CM
diamondpeintre
$13.99
View all
let section_id = '1683281270956'; window.reviewSettings = {}; window.reviewSettings[section_id] = { "sub_title": "Subscribe to get special offers, free giveaways, and once-in-a-lifetime deals.", "star_least": "5", "only_featured": false, "with_photo": true, "review_insufficient": "no_reviews", "minimum_comment_num": 5, "fill_strategy": "hide", "layout": "grid", "image_size": "natural", "wall_mobile_num": 2, "wall_pc_num": 4, "limit": 8, "show_product": true, "hide_review_section": true, "title": "Customer Reviews", "accent_color": null, "color_title": "#000000", "text_color": "#000000", "card_wrap_color": null, "background_color": "#ffffff" };
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-render'; class SPZCustomRevueRender 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); } mountCallback = () => {} render = (data) => { return this.templates_ .findAndRenderTemplate(this.element, data, null) .then((el) => { if (this.element.children.length > 0) { this.element.children[0].style.display = 'none'; } this.element.appendChild(el); // const utilsEl = document.getElementById('spz_custom_revue_util'); // utilsEl && SPZ.whenApiDefined(utilsEl).then((api) => { // api.debounceRender(el, this); // }); }); } 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, SPZCustomRevueRender)
${function(){ return `
${data.starNum}
/
${data.starTotal}
`; }()}
${function(){ return `
${data.showStarText === 'true' ? `
${data.starNum}
/
${data.starTotal}
` : ''}
`; }()}
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)
${function() { return `
${data.count > 99 ? '99+' : data.count < 1 ? '' : data.count}
`; }()}
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)
${function() { return `
${function() { if(data.imgCover) { if(media.videosrc) { let src = ''; if (media.videosrc) { src = media.videosrc + '.' + media.ext; } const videoDom = `
`; if(!isPC){ return `
${videoDom}
` } return `
${videoDom}
` } else if(media.mp4 || media.hls) { const videoDom = `
`; if(!isPC){ return `
${videoDom}
` } return `
${videoDom}
` } else { if(!isPC){ return `
` }else{ return `
` } } } else { if (media.videosrc) { let src = ''; if (media.videosrc) { src = media.videosrc + '.' + media.ext; } return `
` } else if(media.mp4 || media.hls) { return `
` } else { return `
` } } }()}
`; }()}
const TAG = 'spz-custom-revue-media'; class SPZCustomRevueMedia 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.imgCover = this.element.getAttribute('img-cover') ?? false; this.pc_layout = this.element.getAttribute('pc-layout') ?? ''; // 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, imgCover: this.imgCover, pc_layout: this.pc_layout }).then(() => { this.addEventListeners_(); }); } addEventListeners_ = () => { const images = this.element.querySelectorAll('.revue-image-item'); images.forEach((image, index) => { image.addEventListener('click', () => { const carousel = document.querySelector('#revue-image-carousel-render'); carousel && SPZ.whenApiDefined(carousel).then((api) => { const width = this.isPC ? 460 : window.innerWidth * 0.9; const height = this.isPC ? 630 : 500; api.render({ images: this.images, index: index, width: width, height: height }); }); }); }); } 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, SPZCustomRevueMedia)
${function() { return `
Newest
` }()}
${function() { return `
Newest
Most liked
Highest ratings
Lowest ratings
` }()}
${function() { return `
Newest
Most liked
Highest ratings
Lowest ratings
` }()}
const TAG = 'spz-custom-revue-sort'; class SPZCustomRevueSort extends SPZ.BaseElement { constructor(element) { super(element); } static deferredMount() { return false; } 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; } buildCallback = () => { this.action_ = SPZServices.actionServiceForDoc(this.element); this.templates_ = SPZServices.templatesForDoc(this.element); this.xhr_ = SPZServices.xhrFor(this.win); this.isPC = window.innerWidth > 960; this.width = this.isPC ? `${this.element.getAttribute('width') || 150}px` : '100%'; this.randomStr = Math.random().toString(36).substr(2); this.sectionId = this.element.getAttribute('section-id') || '1683281270956'; this.prefix = this.element.getAttribute('prefix'); } mountCallback = () => { const data = { width: this.width, randomStr: this.randomStr }; this.doRender_(data).then(() => { let revueSortListRender = this.isPC ? this.element.querySelector(`#${this.prefix}-revue-sort-list-render-${this.sectionId}`) : this.element.querySelector(`#${this.prefix}-revue-sort-dropdown-render-${this.sectionId}`); revueSortListRender && SPZ.whenApiDefined(revueSortListRender).then((api) => { api.render(data).then(() => { if (this.isPC) { this.addEventListenersForPC_(); } else { this.addEventListenersForMobile_(); } }); }); }); } 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); }); } addEventListenersForPC_ = () => { const revueSelectList = this.element.querySelector('.revue_select_list'); const revueSelectItem = this.element.querySelectorAll('.revue_select_item'); const revueSelectSortIcon = this.element.querySelector(`#${this.prefix}-revue_select_sort_icon-${this.sectionId}`); revueSelectItem.forEach(item => { item.addEventListener('click', () => { const sort = item.getAttribute('data-sort'); const direction = item.getAttribute('data-direction'); this.triggerEvent_('sort', { sort, direction }); this.element.querySelector('.revue_select_label').innerText = item.innerText; revueSelectList.classList.remove('revue_select_list_active'); const revueChecked = this.element.querySelector(`#${this.prefix}-revue_checked`); revueChecked && SPZCore.Dom.removeElement(revueChecked); const revueCheckedClone = revueChecked.cloneNode(true); item.appendChild(revueCheckedClone); const pcDropdownEle = document.querySelector(`#${this.prefix}-revue-sort-pc-dropdown-${this.sectionId}`); if (!revueSelectSortIcon.classList.contains('up_icon')) { return; } revueSelectSortIcon.classList.remove('up_icon'); SPZ.whenApiDefined(pcDropdownEle).then((api) => { api.close(); }); }); }); window.addEventListener('scroll', (e) => { if (!revueSelectSortIcon || !revueSelectSortIcon.classList.contains('up_icon')) { return; } revueSelectSortIcon.classList.remove('up_icon'); SPZ.whenApiDefined(pcDropdownEle).then((api) => { api.close(); }); }); } addEventListenersForMobile_ = () => { const revueSortDropdownRender = document.querySelector(`#${this.prefix}-revue-sort-dropdown-render-${this.sectionId}`); revueSortDropdownRender && SPZ.whenApiDefined(revueSortDropdownRender).then(async (api) => { await api.render(); const revueSortDropdownItem = document.querySelectorAll(`#${this.prefix}-revue-sort-dropdown-${this.sectionId} .revue_sort_dropdown_item`); revueSortDropdownItem.forEach(item => { item.addEventListener('click', () => { const sort = item.getAttribute('data-sort'); const direction = item.getAttribute('data-direction'); revueSortDropdownItem.forEach((_item)=>{_item.classList.remove('selected')}) item.classList.add('selected'); // 抛出事件 this.triggerEvent_('sort', { sort, direction }); // 移除revue_checked元素,复制一个新的到当前选中的元素 const revueChecked = document.querySelector(`#${this.prefix}-revue-sort-dropdown-${this.sectionId} #${this.prefix}-revue_checked`); revueChecked && SPZCore.Dom.removeElement(revueChecked); const revueCheckedClone = revueChecked.cloneNode(true); item.appendChild(revueCheckedClone); const mDropdownEle = document.querySelector(`#${this.prefix}-revue-sort-dropdown-${this.sectionId}`); SPZ.whenApiDefined(mDropdownEle).then((api) => { api.close(); }); }); }); }) } } SPZ.defineElement(TAG, SPZCustomRevueSort)
const TAG = 'spz-custom-revue-flow'; class SpzCustomRevueFlow extends SPZ.BaseElement { constructor(element) { super(element); this.sectionId = this.element.getAttribute('section-id'); this.show_product = ''; this.with_photo = ''; this.limit = ''; this.star_least = ''; this.layout = '' this.wall_pc_num = '' this.wall_mobile_num = '' this.accent_color = '' this.isProductPage = '15' == 1; this.isCollectionPage = '15' == 2; this.isCartPage = '15' == 13; this.lastWidth = window.innerWidth; } static deferredMount() { return false; } buildCallback = () => { this.action_ = SPZServices.actionServiceForDoc(this.element); this.xhr_ = SPZServices.xhrFor(this.win); this.setupAction_(); const url = new URL(window.location.href); const preview_theme_id = url.searchParams.get('preview_theme_id'); if (preview_theme_id) { this.preview_theme_id = preview_theme_id; } this.commentConfig = {}; this.sort = 'created_at'; this.direction = 'desc'; this.isPC = window.innerWidth > (window.breakpoint || 960); this.appendList = []; this.commentListRes = []; this.cardConfig = window.reviewSettings[this.sectionId]; } render_ = (data={}) => { const {star_least, with_photo, show_product, limit, layout, wall_pc_num, wall_mobile_num, accent_color, fill_strategy, review_insufficient, minimum_comment_num, only_featured, hide_review_section} = this.cardConfig; Object.assign(this, {star_least, with_photo, show_product, limit, layout, wall_pc_num, wall_mobile_num, accent_color, fill_strategy, review_insufficient, minimum_comment_num, only_featured, hide_review_section}); if(this.layout === 'wall'){ this.with_photo = 1; }; this.params = { offset: this.appendList.length || 0, sort_by: this.sort, sort_direction: this.direction, show_reply: 1 || this.commentConfig.show_reply ? 1 : 0, with_photo: this.with_photo, ...data } if(this.fill_strategy == 'store'){ if(this.review_insufficient == 'less_than'){ this.params.fill_min_threshold = minimum_comment_num; }else{ this.params.fill_min_threshold = 1; } this.params.fill_strategy = this.fill_strategy; } const summaryObj = { star_least:this.star_least, product_ids: this.isProductPage ? '' : this.isCartPage ? '' : '', collection_id: this.isCollectionPage ? '' : '', filter_type: (this.isProductPage || this.isCartPage) ? 'product' : this.isCollectionPage ? 'collection' : 'store', fill_strategy: this.params?.fill_strategy || '', only_media: !!this.params.with_photo, only_featured:this.only_featured } if(this.params.fill_min_threshold){ summaryObj.fill_min_threshold = this.params.fill_min_threshold; } Promise.all([ this.fetchSummary_(summaryObj), this.fetchCommentConfig_(), this.fetchCommentList_(this.params) ]).then(response => { const [starCountRes,commentConfigRes, commentListRes] = response; this.commentConfig = commentConfigRes.data; this.commentConfig.show_product = this.show_product; this.commentListRes = commentListRes; this.starCountRes = starCountRes; /* 评论不足逻辑 */ const listLen = Number(commentListRes?.data?.count) || 0; const isListEmpty = listLen === 0; const isLessThanMinimum = this.review_insufficient === 'less_than' && listLen < this.minimum_comment_num; const shouldHide = isListEmpty || isLessThanMinimum; /* 隐藏评论区域 */ if ((this.fill_strategy === 'hide' && shouldHide) || (this.hide_review_section && isListEmpty)) { this.renderHideSkeleton_(); this.renderHideComment_(); return; } /* 显示空状态 */ if (this.fill_strategy === 'empty' && shouldHide) { this.renderHideSkeleton_(); if (this.isProductPage) { this.renderEmptyComment_(); } else { this.renderHideComment_(); } return; } if (this.preview_theme_id) { this.fetchThemeConfig_(this.preview_theme_id).then(themeConfig => { if (themeConfig?.star_color) { this.commentConfig.star_color = themeConfig.star_color; } if(this.accent_color && this.accent_color != 'null'){ this.commentConfig.star_color = this.accent_color; } }); } /* render */ const colums = this.calculateColums_(); this.renderFlowMain_({ config: this.commentConfig, comment: commentListRes.data, column_count: colums }).then(() => { this.renderHeader_({ starData: this.starCountRes.data, listData: this.commentListRes.data, star_color: this.commentConfig.star_color, comment_avg_star: this.commentListRes.data.avg_star, comment_count: this.commentListRes.data?.count, isPC: this.isPC, }); this.renderStarCounts_(this.starCountRes.data); this.addImpression(`[data-section-id="${this.sectionId}"] .revue_container`); this.renderCommentList_({ list: commentListRes.data, config: this.commentConfig, shop_name: window.SHOPLAZZA.shop.shop_name },true); }); window.removeEventListener('resize', this.rerenderFn); window.addEventListener('resize', this.rerenderFn); }) .catch(error => { this.renderHideSkeleton_(); this.renderHideComment_(); console.error('error', error); }); } mountCallback = () => { this.render_() } /* fetch api/comment-config */ fetchCommentConfig_ = async () => { const response = await fetch('/api/comment-config'); return response.json(); } fetchSummary_ = async (data) => { const response = await fetch('/api/v1/comments/summary',{ method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); return response.json(); } fetchCommentList_ = async(data) => { const response = await fetch(`/api/v1/comments`,{ method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ ...data, offset: data.offset, show_product:!!this.show_product, star_least:this.star_least, limit:this.limit, sort_by:data.sort_by || 'created_at', sort_direction: data.sort_direction || 'desc', filter_type:(this.isProductPage || this.isCartPage) ? 'product' : this.isCollectionPage ? 'collection' : 'store', show_reply: !!data.show_reply, only_media: !!data.with_photo, product_ids: this.isProductPage ? '' : this.isCartPage ? '' : '', collection_id: this.isCollectionPage ? '' : '', only_featured: this.only_featured, }) }); if(response.status != 200){ return Promise.reject(false); } return response.json(); } fetchThemeConfig_ = async(themeId) => { const response = await fetch(`/api/comment/theme-config?theme_id=${themeId}`); return response.json(); } renderHideSkeleton_ = () => { const skeleton = document.getElementById(`revue_flow_skeleton-${this.sectionId}`); if(skeleton){ skeleton.style.display = 'none'; }; } renderHideComment_ = () => { const holderEl = document.getElementById(`revue_no_data_placeholder_${this.sectionId}`); if (window.top !== window.self) { SPZ.whenApiDefined(holderEl).then((api) => { api.render({}, true); }); }else{ holderEl.style.display = 'none'; } } renderEmptyComment_ = () => { const emptyEle = document.querySelector(`#revue-empty-1683281270956`); if(emptyEle) { emptyEle.classList.remove('hidden'); } } renderFlowMain_ = async (data) => { const mainEle = document.querySelector(`#revue_flow_render-${this.sectionId}`); if (mainEle) { const api = await SPZ.whenApiDefined(mainEle); return api.render({ ...data },true); } } calculateColums_ = () => { let colums = 1; this.isPC = window.innerWidth > (window.breakpoint || 960); if (this.layout === 'grid') { colums = this.isPC ? 4 : 2; } else { colums = this.isPC ? 2 : 1; } if(this.layout == 'wall'){ colums = this.isPC ? (this.wall_pc_num || 4) : (this.wall_mobile_num || 2); } return colums } rerenderFn = (list) => { try{ if(!this?.commentListRes?.data) return; const currentWidth = window.innerWidth; if (currentWidth == this.lastWidth ) { return } else { this.lastWidth = currentWidth; } const throttleHandle = SPZCore.Types.throttle(window,()=>{ let colums = this.calculateColums_(); this.renderFlowMain_({ config: this.commentConfig, comment: this.commentListRes.data, column_count: colums }).then(() => { this.renderHeader_({ starData: this.starCountRes.data, listData: this.commentListRes.data, star_color: this.commentConfig.star_color, comment_avg_star: this.commentListRes.data.avg_star, comment_count: this.commentListRes.data?.count, isPC: this.isPC, }); this.renderStarCounts_(this.starCountRes.data); this.renderCommentList_({ list: this.commentListRes.data, config: this.commentConfig, shop_name: window.SHOPLAZZA.shop.shop_name }, true); }); },200) throttleHandle() }catch(e){ console.log(e); } } renderCommentList_ = (data,redo=false) => { if(this.accent_color && this.accent_color != 'null'){ this.commentConfig.star_color = this.accent_color; } const listEle = document.querySelector(`#revue_flow_list-${this.sectionId}`); if (listEle) { const current_list = data.list.list.map((item, index) => { return { ...item, config: this.commentConfig, index: data.sorted ? index : this.appendList.length + index, shop_name: window.SHOPLAZZA.shop.shop_name } }); if (data.sorted) { this.appendList = current_list; SPZ.whenApiDefined(listEle).then((api) => { api.listRender({ count: data.list.count, list: current_list },true); }); } else { let obj = {}; this.appendList = this.appendList.concat(current_list).reduce((cur,next) => { obj[next.id] ? "" : obj[next.id] = true && cur.push(next); return cur; },[]); SPZ.whenApiDefined(listEle).then((api) => { api.listRender({ count: data.list.count, list: current_list },redo); }); } }; this.renderLoadMoreBtn(data.list); } 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(); } }; addImpression = function (selector) { this.impFunc(selector, () => { window.sa && window.sa.track('plugin_reviews_masonry_pv', { layout_type: this.layout, level_type: this.star_least, show_number: this.limit, plugin_timestamp: new Date().valueOf().toString(), reviews_num: this.appendList.length }); }); }; addModalImpression = function (selector, params) { this.impFunc(selector, () => { window.sa && window.sa.track('plugin_reviews_modal_pv', { ...params, plugin_timestamp: new Date().valueOf().toString(), }); }); }; setupAction_ = () => { this.registerAction('refresh', async(invocation) => { this.render_({ ...this.params, offset: 0, sort_by: 'created_at', sort_direction: 'desc', show_reply: true, with_photo: false, }) }); this.registerAction('renderTypeChangeList', async(invocation) => { const {type,direction } = invocation.args.data; this.with_photo = type === 'with_photo'; this.direction = direction; this.params = { ...this.params, offset: 0, sort_by: this.sort, sort_direction: this.direction, show_reply: 1, with_photo: this.with_photo }; this.fetchCommentList_(this.params).then(response => { this.renderCommentList_({ sorted: true, list: response.data, config: this.commentConfig, shop_name: window.SHOPLAZZA.shop.shop_name }, true); }); }) this.registerAction('renderSortedList', async(invocation) => { const {sort, direction} = invocation.args.data; this.sort = sort; this.direction = direction; const panelId = this.panelId; this.params = { ...this.params, offset: 0, sort_by: this.sort, sort_direction: this.direction, show_reply: 1 , with_photo: this.with_photo } this.fetchCommentList_(this.params).then(response => { this.renderCommentList_({ sorted: true, list: response.data, config: this.commentConfig, shop_name: window.SHOPLAZZA.shop.shop_name }, true); }); }); this.registerAction('renderProductCommentModal', async(invocation) => { const id = invocation.args.id; const current = this.appendList?.find(_data => _data.id == id); const modalEle = document.querySelector(`#revueDetailModal-${this.sectionId}`); const imgArr = current.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 }; }); if (modalEle) { SPZ.whenApiDefined(modalEle).then((api) => { api.renderModalFn({ data: { ...current, img: imgArr }, commentConfig: this.commentConfig, layout: this.layout, level_type: this.star_least, show_number: this.limit }); }); } }); this.registerAction('loadMore', async(invocation) => { this.params = { ...this.params, offset: this.appendList.length, sort_by: this.sort, sort_direction: this.direction, show_reply: 1 || this.commentConfig.show_reply ? 1 : 0, with_photo: this.with_photo } this.fetchCommentList_(this.params).then(response => { this.renderCommentList_({ list: response.data, config: this.commentConfig, shop_name: window.SHOPLAZZA.shop.shop_name }); }); }); } getUrlKey = (name, url) => { return ( decodeURIComponent( (new RegExp("[?|&]" + name + "=" + "([^&;]+?)(&|#|;|$)").exec( url ) || [, ""])[1].replace(/\+/g, "%20") ) || null ); } renderHeader_ = (data) => { if(this.accent_color && this.accent_color != 'null'){ data.star_color = this.commentConfig.star_color = this.accent_color; } const headerEle = document.querySelector(`#review-revue-header-${this.sectionId}`); if (headerEle) { SPZ.whenApiDefined(headerEle).then(async (api) => { api.render(data); }); } } renderStarCounts_ = (data) => { const summaryEle = document.querySelector(`#revue-summary-${this.sectionId}`); if (summaryEle) { SPZ.whenApiDefined(summaryEle).then((api) => { api.render({ ...data, star_color: this.commentConfig.star_color }); }); } } renderLoadMoreBtn = (data) => { const loadEle = document.querySelector(`#revue_flow_load_more_render-${this.sectionId}`); if (loadEle) { SPZ.whenApiDefined(loadEle).then((api) => { api.render({ comment: data }, true); }); } } triggerEvent_(name, data) { const event = SPZUtils.Event.create(this.win, `${ TAG }.${ name }`, data || {}); this.action_.trigger(this.element, name, event); } unmountCallback(){ } isLayoutSupported(layout) { return layout == SPZCore.Layout.CONTAINER; } } SPZ.defineElement(TAG, SpzCustomRevueFlow)
${function() { const randomStr = Math.random().toString(36).substring(7); const formatDate = value => { let date = new Date(value * 1000); const day = date.toLocaleString('en-US', { day: '2-digit' }); const month = date.toLocaleString('en-US', { month: 'short' }); const year = date.toLocaleString('en-US', { year: 'numeric' }); return month + ' ' + day + ', ' + year; }; const item = data; const config = data.config; const mimic_mobile_style = data?.mimic_mobile_style; return `
${data.img.map(media => { return `
`; }).join('')}
${data.img.map((media, i) => { return `
` }).join('')}
${data.img.map((media, i) => { return `
` }).join('')}
${item.username}
.${item.iso_code_3}
${formatDate(item.created_at)}
Verified
${item.content}
${data.shop_name} reply:
${item.reply && item.reply.length && item.reply[0].content}
${item.product?.title}
`; }()}
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)
${function() { return `
${function(){ if (media.videosrc) { const src = media.videosrc + '.' + media.ext; return `
` } else if(media.mp4 || media.hls) { return `
` } else { return `` } }()}
`; }()}
const TAG = 'spz-custom-revue-video'; class SPZCustomRevueVideo 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; } loadVideo = () => { this.doRender_({ images: this.images, isPC: this.isPC }).then(()=>{ this.triggerEvent_('connected', {}); }) } mountCallback = () => { this.loadVideo(); this.registerAction('loadVideo', async(invocation) => { this.loadVideo(); }) } 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, SPZCustomRevueVideo)
${function(){ const isPC = data.isPC; const pc_layout = 'single_column'; const m_loading_type = 'modal'; const showCount = data.showCount ?? (!isPC || pc_layout !== 'single_column'); const showSummary = data.showSummary ?? (!isPC || pc_layout !== 'single_column'); const showWriteReview = data.showWriteReview ?? (isPC && pc_layout !== 'single_column'); const viewall = data.viewall ?? (!isPC && m_loading_type === 'modal'); const showType = data.showType ?? ((!isPC || pc_layout !== 'single_column') && !viewall); const showSort = data.showSort ?? ((!isPC || pc_layout !== 'single_column') && !viewall); if(!data.suffix){ data.suffix = '1683281270956' } return `
Customer Reviews
(${data.comment_count > 500 ? '500+' : (data.comment_count || 0)})
Write a Review
View all
` }()}
const TAG = 'spz-custom-revue-header'; class SPZCustomRevueHeader extends SPZ.BaseElement { constructor(element) { super(element); this.showCount = this.element.getAttribute('show-count'); } static deferredMount() { return false; } isLayoutSupported(layout) { return layout == SPZCore.Layout.CONTAINER; } buildCallback() { this.action_ = SPZServices.actionServiceForDoc(this.element); this.templates_ = SPZServices.templatesForDoc(this.element); this.xhr_ = SPZServices.xhrFor(this.win); this.showCount = this.element.getAttribute('show-count'); this.showSummary = this.element.getAttribute('show-summary'); this.showWriteReview = this.element.getAttribute('show-write-review'); this.showType = this.element.getAttribute('show-type') ; this.showSort = this.element.getAttribute('show-sort') ; this.sectionId = this.element.getAttribute('section-id'); this.viewall = this.element.getAttribute('viewall') ?? false; this.prefix = this.element.getAttribute('prefix'); } mountCallback() { } triggerEvent_(name, data) { const event = SPZUtils.Event.create(this.win, `${ TAG }.${ name }`, data || {}); this.action_.trigger(this.element, name, event); } render(data) { const ndata = { ...data, showCount: this.showCount, showSummary: this.showSummary, showWriteReview: this.showWriteReview, showType: this.showType, showSort: this.showSort, } if(this.viewall == 'review'){ ndata.viewall = false } return this.templates_ .findAndRenderTemplate(this.element, ndata, null, true) .then(({el}) => { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); this.element.appendChild(el); }).then(() => { if(data && Object.keys(data).length > 0) { this.updateRender(data); this.setupSummaryContainerEffects_(data); } }); } updateRender(data) { this.renderStarCounts_(data); this.renderTypeSelect(data); this.renderSortSelect(data); } renderStarCounts_(data) { const renderData = { ...data.starData, star_color: data.star_color, isPC: data.isPC, } const summaryEle = data.isPC ? this.element.querySelector(`#${this.prefix}-revue-summary-${this.sectionId}_header_pc`) : this.element.querySelector(`#${this.prefix}-revue-summary-${this.sectionId}_header`); if(summaryEle) { SPZ.whenApiDefined(summaryEle).then((api) => { api.render(renderData); }); } } renderTypeSelect(data) { const typeSelect = this.element.querySelector(`#${this.prefix}-revue-header-type-${this.sectionId}`); if(typeSelect) { SPZ.whenApiDefined(typeSelect).then((api) => { api.render(data); api.registerAction('headerType_', (invocation) => { this.triggerEvent_('headerType', invocation.args.data); }); }); } } renderSortSelect(data) { const suffix = data.suffix || this.sectionId; const sortSelect = this.element.querySelector(`#${this.prefix}-revue-header-sort-${suffix}`); if(sortSelect) { SPZ.whenApiDefined(sortSelect).then((api) => { api.registerAction('headerSort_', (invocation) => { this.triggerEvent_('headerSort', invocation.args.data); }); }); } } setupSummaryContainerEffects_(data) { if(data.isPC) { this.setupSummaryContainerHover_(); } else { this.setupSummaryContainerTap_(); } } setupSummaryContainerHover_() { const summaryContainer = this.element.querySelector(`#revue-header-summary-container-${this.sectionId}`); const summaryEle = this.element.querySelector(`#${this.prefix}-revue-summary-${this.sectionId}_header_pc`); if (!summaryContainer || !summaryEle) return; let isHovering = false; // 鼠标移入容器时显示summary SPZUtils.Event.listen(summaryContainer, 'mouseenter', () => { isHovering = true; summaryEle.removeAttribute('hidden'); const selectIcon = summaryContainer.querySelector(`#revue-header-summary-icon-${this.sectionId}`); if(selectIcon) { selectIcon.classList.add('up-icon'); } }); // 鼠标移入summary时也保持显示 SPZUtils.Event.listen(summaryEle, 'mouseenter', () => { isHovering = true; }); // 鼠标移出容器时,检查是否还在summary上 SPZUtils.Event.listen(summaryContainer, 'mouseleave', () => { isHovering = false; setTimeout(() => { if (!isHovering) { summaryEle.setAttribute('hidden', 'true'); const selectIcon = summaryContainer.querySelector(`#revue-header-summary-icon-${this.sectionId}`); if(selectIcon) { selectIcon.classList.remove('up-icon'); } } }, 50); }); // 鼠标移出summary时,检查是否还在容器上 SPZUtils.Event.listen(summaryEle, 'mouseleave', () => { isHovering = false; setTimeout(() => { if (!isHovering) { summaryEle.setAttribute('hidden', 'true'); const selectIcon = summaryEle.querySelector(`#revue-header-summary-icon-${this.sectionId}`); if(selectIcon) { selectIcon.classList.remove('up-icon'); } } }, 50); }); } setupSummaryContainerTap_() { const selectIcon = this.element.querySelector(`#revue-header-summary-icon-${this.sectionId}`); const summaryEle = this.element.querySelector(`#${this.prefix}-revue-summary-${this.sectionId}_header`); if(!summaryEle) return; let isTapped = false; // 是否显示summary SPZ.whenApiDefined(summaryEle).then((api) => { api.registerAction('display', () => { if(isTapped) { isTapped = false; summaryEle.removeAttribute('hidden'); selectIcon.classList.add('up-icon'); } else { isTapped = true; summaryEle.setAttribute('hidden', 'true'); selectIcon.classList.remove('up-icon'); } }); }); } } SPZ.defineElement(TAG, SPZCustomRevueHeader);
${function(){ const starOrder = ['one_star', 'two_star', 'three_star', 'four_star', 'five_star']; function sortStarRatings(ratings) { const sortedRatingsArr = []; starOrder.map((star,index) => { sortedRatingsArr.push(index+1); return star; }); return sortedRatingsArr; }; const star_levels = sortStarRatings(data.star_detail).reverse(); return `
${data.comment_avg_star}
Total reviews: ${data.comment_count > 999 ? '999+' : data.comment_count}
${level}
`; }()}
${function() { return `
All
` }()}
${function() { const list = data.listData; return `
All(${list.count})
With Photos(${list.image_count})
` }()}
${function() { const list = data.listData; return `
All(${list.count})
With Photos(${list.image_count})
` }()}
const TAG = 'spz-custom-revue-type'; class SPZCustomRevueType extends SPZ.BaseElement { constructor(element) { super(element); } static deferredMount() { return false; } 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; } buildCallback = () => { this.action_ = SPZServices.actionServiceForDoc(this.element); this.templates_ = SPZServices.templatesForDoc(this.element); this.xhr_ = SPZServices.xhrFor(this.win); this.isPC = window.innerWidth > 960; this.width = this.isPC ? `${this.element.getAttribute('width') || 150}px` : '100%'; this.randomStr = Math.random().toString(36).substr(2); this.sectionId = this.element.getAttribute('section-id') || '1683281270956'; this.prefix = this.element.getAttribute('prefix'); } mountCallback = () => { } render = (data) => { const renderData = { ...data, width: this.width, randomStr: this.randomStr }; return this.templates_ .findAndRenderTemplate(this.element, renderData, null) .then((el) => { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); this.element.appendChild(el); }).then(() => { let revueTypeListRender = this.isPC ? this.element.querySelector(`#${this.prefix}-revue-type-list-render-${this.sectionId}`) : this.element.querySelector(`#${this.prefix}-revue-type-dropdown-render-${this.sectionId}`); revueTypeListRender && SPZ.whenApiDefined(revueTypeListRender).then((api) => { api.render(renderData).then(() => { if (this.isPC) { this.addEventListenersForPC_(); } else { this.addEventListenersForMobile_(); } }); }); }); } addEventListenersForPC_ = () => { const revueSelectList = this.element.querySelector('.revue_select_list'); const revueSelectItem = this.element.querySelectorAll('.revue_select_item'); const revueSelectTypeIcon = this.element.querySelector(`#${this.prefix}-revue_select_type_icon-${this.sectionId}`); revueSelectItem.forEach(item => { item.addEventListener('click', () => { const type = item.getAttribute('data-type'); const direction = item.getAttribute('data-direction'); this.triggerEvent_('type', { type, direction }); this.element.querySelector('.revue_select_label').innerText = item.innerText; revueSelectList.classList.remove('revue_select_list_active'); const revueChecked = this.element.querySelector(`#${this.prefix}-revue_checked`); revueChecked && SPZCore.Dom.removeElement(revueChecked); const revueCheckedClone = revueChecked.cloneNode(true); item.appendChild(revueCheckedClone); if (!revueSelectTypeIcon.classList.contains('up_icon')) { return; } const pcDropdownEle = this.element.querySelector(`#${this.prefix}-revue-type-pc-dropdown-${this.sectionId}`); revueSelectTypeIcon.classList.remove('up_icon'); SPZ.whenApiDefined(pcDropdownEle).then((api) => { api.close(); }); }); }); window.addEventListener('scroll', (e) => { if (!revueSelectTypeIcon.classList.contains('up_icon')) { return; } revueSelectTypeIcon.classList.remove('up_icon'); SPZ.whenApiDefined(pcDropdownEle).then((api) => { api.close(); }); }); } addEventListenersForMobile_ = () => { const revueTypeDropdownItem = this.element.querySelectorAll(`#${this.prefix}-revue-type-dropdown-${this.sectionId} .revue_type_dropdown_item`); revueTypeDropdownItem.forEach(item => { item.addEventListener('click', () => { const type = item.getAttribute('data-type'); const direction = item.getAttribute('data-direction'); revueTypeDropdownItem.forEach((_item)=>{_item.classList.remove('selected')}) item.classList.add('selected'); // 抛出事件 this.triggerEvent_('type', { type, direction }); // 移除revue_checked元素,复制一个新的到当前选中的元素 const revueChecked = this.element.querySelector(`#${this.prefix}-revue-type-dropdown-${this.sectionId} #${this.prefix}-revue_checked`); revueChecked && SPZCore.Dom.removeElement(revueChecked); const revueCheckedClone = revueChecked.cloneNode(true); item.appendChild(revueCheckedClone); const mDropdownEle = this.element.querySelector(`#${this.prefix}-revue-type-dropdown-${this.sectionId}`); SPZ.whenApiDefined(mDropdownEle).then((api) => { api.close(); }); }); }); } } SPZ.defineElement(TAG, SPZCustomRevueType)
${function() { const isPercentage = data.show_percentage === 'true' && data.total <= data.show_percentage_num; return `
${!isPercentage ? `${data.count}` : `${data.count / data.total * 100}%`}
` }()}
const TAG = 'spz-custom-revue-progress'; class SPZCustomRevueProgress 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.isPC = window.innerWidth > (window.breakpoint || 960); this.height = '6px'; this.color = this.element.getAttribute('color') || '#000000'; this.show_percentage = 'false'; this.show_percentage_num = 100; this.count = this.element.getAttribute('count'); this.total = this.element.getAttribute('total'); } mountCallback = () => { this.doRender_({ count: Number(this.count), total: Number(this.total), height: this.height, color: this.color, show_percentage: this.show_percentage, show_percentage_num: this.show_percentage_num }).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); }); } 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, SPZCustomRevueProgress)
${function() { const item = data.originData; const config = data.config; item.imgArr = item.img.map(image => { const width = getUrlKey('width', image); const height = getUrlKey('height', image); return { width, height, rate: (height/width).toFixed(2)*100, url: image }; }); const randomStr = Math.random().toString(36).substring(7); const formatDate = value => { let date = new Date(value * 1000); const day = date.toLocaleString('en-US', { day: '2-digit' }); const month = date.toLocaleString('en-US', { month: 'short' }); const year = date.toLocaleString('en-US', { year: 'numeric' }); return month + ' ' + day + ', ' + year; }; function getUrlKey(name, url) { return ( decodeURIComponent( (new RegExp("[?|&]" + name + "=" + "([^&;]+?)(&|#|;|$)").exec( url ) || [, ""])[1].replace(/\+/g, "%20") ) || null ); } let videoMp4 = ''; let videoHls = ''; if(item.imgArr.length > 0 && item.imgArr[0].url?.includes('media_type=video')){ videoMp4 = getUrlKey('mp4',item.imgArr[0].url); videoHls = getUrlKey('hls',item.imgArr[0].url); } function mediaParse_(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; } const parsedImages = item?.img.map(image => { return mediaParse_(image); }); return `
${item.username}
${item.iso_code_3}
${item.content}
${data.shop_name} reply:
${item.reply && item.reply.length && item.reply[0].content}
${formatDate(item.created_at)}
${item.product.title}
`; }()}
${function() { const item = data.originData; const config = data.config; item.imgArr = item.img.map(image => { const width = getUrlKey('width', image); const height = getUrlKey('height', image); return { width, height, rate: (height/width).toFixed(2)*100, url: image }; }); const randomStr = Math.random().toString(36).substring(7); const formatDate = value => { let date = new Date(value * 1000); const day = date.toLocaleString('en-US', { day: '2-digit' }); const month = date.toLocaleString('en-US', { month: 'short' }); const year = date.toLocaleString('en-US', { year: 'numeric' }); return month + ' ' + day + ', ' + year; }; function getUrlKey(name, url) { return ( decodeURIComponent( (new RegExp("[?|&]" + name + "=" + "([^&;]+?)(&|#|;|$)").exec( url ) || [, ""])[1].replace(/\+/g, "%20") ) || null ); } let videoMp4 = ''; let videoHls = ''; if(item.imgArr.length > 0 && item.imgArr[0].url?.includes('media_type=video')){ videoMp4 = getUrlKey('mp4',item.imgArr[0].url); videoHls = getUrlKey('hls',item.imgArr[0].url); } function mediaParse_(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; } const parsedImages = item?.img.map(image => { return mediaParse_(image); }); return `
+${item.imgArr.length}
${item.content}
${item.product.title}
${item.username}
${formatDate(item.created_at)}
`; }()}
${function() { const item = data.originData; const config = data.config; item.imgArr = item.img.map(image => { const width = getUrlKey('width', image); const height = getUrlKey('height', image); return { width, height, rate: (height/width).toFixed(2)*100, url: image }; }); const randomStr = Math.random().toString(36).substring(7); const formatDate = value => { let date = new Date(value * 1000); const day = date.toLocaleString('en-US', { day: '2-digit' }); const month = date.toLocaleString('en-US', { month: 'short' }); const year = date.toLocaleString('en-US', { year: 'numeric' }); return month + ' ' + day + ', ' + year; }; function getUrlKey(name, url) { return ( decodeURIComponent( (new RegExp("[?|&]" + name + "=" + "([^&;]+?)(&|#|;|$)").exec( url ) || [, ""])[1].replace(/\+/g, "%20") ) || null ); } let videoMp4 = ''; let videoHls = ''; if(item.imgArr.length > 0 && item.imgArr[0].url?.includes('media_type=video')){ videoMp4 = getUrlKey('mp4',item.imgArr[0].url); videoHls = getUrlKey('hls',item.imgArr[0].url); } function mediaParse_(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; } const parsedImages = item?.img.map(image => { return mediaParse_(image); }); return `
+${item.imgArr.length}
${item.username}
.${item.iso_code_3}
`; }()}
View more
Wow you reached the bottom
${function(){ return `
No reviews available. The product reviews component has been hidden
Review Flow
` }()}
Customer Reviews
No reviews yet, why don't you leave the first review?
Write a Review
Sign up for our newsletter
Never miss a new season
Thanks for Subscribing!
We will send news to your email.