1if(!customElements.get("review-summary")){class ReviewSummary extends HTMLElement{connectedCallback(){this.toggleBtn=this.querySelector("[data-rs-toggle]"),this.panel=this.querySelector("[data-rs-panel]"),this.hist=this.querySelector("[data-rs-hist]"),this.scaleMax=parseFloat(this.dataset.scaleMax)||5,this.mergeAll=this.dataset.mergeAll==="true",this.addEventListener("mouseenter",()=>this.open()),this.addEventListener("mouseleave",()=>this.close()),this.addEventListener("focusin",()=>this.open()),this.addEventListener("focusout",e=>{this.contains(e.relatedTarget)||this.close()}),this.toggleBtn&&this.toggleBtn.addEventListener("click",()=>this.toggle()),this.allLink=this.querySelector("[data-rs-all]"),this.allLink&&this.allLink.addEventListener("click",e=>this.seeAllReviews(e)),this.mergeAll?this.fetchAggregate():(this.readPageBadge(),(this.dataset.showHistogram==="true"||this.dataset.token)&&this.fetchLive())}toggle(){this.panel&&(this.panel.hidden?this.open():this.close())}open(){this.panel&&(this.panel.hidden=!1,this.classList.add("rev-sum--open"),this.toggleBtn&&this.toggleBtn.setAttribute("aria-expanded","true"))}close(){this.panel&&(this.panel.hidden=!0,this.classList.remove("rev-sum--open"),this.toggleBtn&&this.toggleBtn.setAttribute("aria-expanded","false"))}findReviewsTarget(){const carousel=document.querySelector(".jdgm-carousel-wrapper, .jdgm-carousel");if(carousel)return carousel;const href=this.allLink&&this.allLink.getAttribute("href");if(href&&href.charAt(0)==="#"&&href.length>1){const el=document.getElementById(href.slice(1));if(el)return el}const selectors=["#judgeme_product_reviews",".jdgm-rev-widg",".jdgm-review-widget",".jdgm-all-reviews-widget",".jdgm-widget","[data-jdgm-widget]"];for(const sel of selectors){const el=document.querySelector(sel);if(el)return el}return null}seeAllReviews(e){const target=this.findReviewsTarget();target&&(e.preventDefault(),target.scrollIntoView({behavior:"smooth",block:"start"}))}setRating(rating){if(!(rating>0))return;const rounded=Math.round(rating*10)/10;this.querySelectorAll("[data-rs-rating]").forEach(el=>{el.textContent=rounded.toFixed(1)});const pct=Math.max(0,Math.min(100,rating/this.scaleMax*100));this.querySelectorAll("[data-rs-stars-fg]").forEach(el=>{el.style.width=pct+"%"})}setCount(count){if(!(count>=0)||Number.isNaN(count))return;const formatted=count.toLocaleString();this.querySelectorAll("[data-rs-count], [data-rs-total]").forEach(el=>{el.textContent=formatted})}renderHistogram(byStar){if(!this.hist||!byStar)return;const stars=[5,4,3,2,1],totalFreq=stars.reduce((sum,s)=>sum+(byStar[s]&&byStar[s].freq||0),0);let rendered=!1;stars.forEach(star=>{const row=this.hist.querySelector('[data-rs-row="'+star+'"]');if(!row)return;const entry=byStar[star]||{};let pct=entry.pct;(pct==null||Number.isNaN(pct))&&totalFreq>0&&(pct=(entry.freq||0)/totalFreq*100),(pct==null||Number.isNaN(pct))&&(pct=0);const fill=row.querySelector("[data-rs-fill]"),label=row.querySelector("[data-rs-pct]");fill&&(fill.style.width=pct+"%"),label&&(label.textContent=Math.round(pct)+"%"),rendered=!0}),rendered&&(this.hist.hidden=!1)}readPageBadge(){const badge=document.querySelector(".jdgm-prev-badge[data-average-rating], .jdgm-prev-badge[data-number-of-reviews]");if(!badge)return;const rating=parseFloat(badge.getAttribute("data-average-rating")),count=parseInt(badge.getAttribute("data-number-of-reviews"),10);rating>0&&this.setRating(rating),count>=0&&this.setCount(count)}unwrap(text){const str=String(text??"").trim();try{const json=JSON.parse(str);if(json&&typeof json=="object"&&typeof json.widget=="string")return json.widget;if(typeof json=="string")return json}catch{}return str}parseNumber(text){if(text==null)return NaN;const str=String(text).trim();try{const json=JSON.parse(str);if(typeof json=="number")return json;if(json&&typeof json=="object"){const keys=["average_rating","rating","average","value","count","number_of_reviews","reviews_count","total"];for(const k of keys)if(typeof json[k]=="number")return json[k];for(const k in json)if(typeof json[k]=="number")return json[k]}}catch{}const m=str.replace(/,/g,"").match(/[\d.]+/);return m?parseFloat(m[0]):NaN}async fetchAggregate(){const token=(this.dataset.token||"").trim();if(!token)return;
1const shops=[this.dataset.shop,this.dataset.shopAlt].filter(Boolean),base="https://api.judge.me/api/v1/widgets/";for(const shop of shops){const q="?shop_domain="+encodeURIComponent(shop)+"&api_token="+encodeURIComponent(token);try{const wantHist=this.hist&&this.dataset.showHistogram==="true",[ratingRes,countRes,pageRes]=await Promise.all([fetch(base+"all_reviews_rating"+q,{headers:{Accept:"application/json"}}),fetch(base+"all_reviews_count"+q,{headers:{Accept:"application/json"}}),wantHist?fetch(base+"all_reviews_page"+q,{headers:{Accept:"application/json"}}):Promise.resolve(null)]);let ok=!1;if(ratingRes&&ratingRes.ok){const rating=this.parseNumber(this.unwrap(await ratingRes.text()));rating>0&&(this.setRating(rating),ok=!0)}if(countRes&&countRes.ok){const count=this.parseNumber(this.unwrap(await countRes.text()));count>=0&&!Number.isNaN(count)&&(this.setCount(count),ok=!0)}if(pageRes&&pageRes.ok){const raw=await pageRes.text();let headerHtml=raw;try{const json=JSON.parse(raw);headerHtml=json.all_reviews_header||json.widget||json.all_reviews||raw}catch{}const byStar=this.parseHistogram(headerHtml);byStar&&this.renderHistogram(byStar)}if(ok)return}catch{}}}async fetchLive(){const token=(this.dataset.token||"").trim(),id=this.dataset.productId;if(!token||!id)return;const shops=[this.dataset.shop,this.dataset.shopAlt].filter(Boolean);for(const shop of shops)try{const url="https://api.judge.me/api/v1/widgets/product_review?shop_domain="+encodeURIComponent(shop)+"&api_token="+encodeURIComponent(token)+"&external_id="+encodeURIComponent(id)+"&per_page=1",res=await fetch(url,{headers:{Accept:"application/json"}});if(!res.ok)continue;const data=await res.json();if(data&&data.widget&&this.applyWidget(data.widget))return}catch{}}applyWidget(html){let doc;try{doc=new DOMParser().parseFromString(html,"text/html")}catch{return!1}const widg=doc.querySelector("[data-average-rating]")||doc.querySelector(".jdgm-rev-widg");if(widg){const rating=parseFloat(widg.getAttribute("data-average-rating")),count=parseInt(widg.getAttribute("data-number-of-reviews"),10);rating>0&&this.setRating(rating),count>=0&&this.setCount(count)}const freqByStar=this.parseHistogram(doc);return freqByStar&&this.renderHistogram(freqByStar),!0}parseHistogram(htmlOrDoc){let doc=htmlOrDoc;if(typeof htmlOrDoc=="string")try{doc=new DOMParser().parseFromString(htmlOrDoc,"text/html")}catch{return null}if(!doc||!doc.querySelectorAll)return null;const byStar={};let found=!1;return doc.querySelectorAll('.jdgm-histogram__row, .jdgm-histogram tr, [class*="histogram__row"]').forEach((row,index)=>{let star=parseInt(row.getAttribute("data-rating"),10);if(!star){const labelled=row.querySelector("[data-rating]");labelled&&(star=parseInt(labelled.getAttribute("data-rating"),10))}if(!star){const m=(row.textContent||"").match(/([1-5])\s*star/i);m&&(star=parseInt(m[1],10))}star||(star=5-index);let freq=parseInt(row.getAttribute("data-frequency"),10);if(Number.isNaN(freq)){const freqEl=row.querySelector("[data-frequency], .jdgm-histogram__frequency");freqEl&&(freq=parseInt(freqEl.getAttribute("data-frequency"),10),Number.isNaN(freq)&&(freq=parseInt((freqEl.textContent||"").replace(/[^0-9]/g,""),10)))}let pct=parseFloat(row.getAttribute("data-percentage"));if(Number.isNaN(pct)){const pctEl=row.querySelector("[data-percentage], .jdgm-histogram__percentage");pctEl&&(pct=parseFloat(pctEl.getAttribute("data-percentage")),Number.isNaN(pct)&&(pct=parseFloat((pctEl.textContent||"").replace(/[^0-9.]/g,""))))}Number.isNaN(freq)&&Number.isNaN(pct)||star>=1&&star<=5&&(byStar[star]={freq:Number.isNaN(freq)?null:freq,pct:Number.isNaN(pct)?null:pct},found=!0)}),found?byStar:null}}customElements.define("review-summary",ReviewSummary)} 2//# sourceMappingURL=/cdn/shop/t/956/assets/review-summary.js.map?v=132099224287427359021781866546
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.