Spaces:
Running
Running
| // V.AI STUDIO URL-added products live loader v1019 | |
| // Loads products_url_added.json, merges into native arrays, and intercepts URL-added product links without hash redirect. | |
| (function(){ | |
| if(window.__VAI_URL_ADDED_LIVE_V1019__) return; | |
| window.__VAI_URL_ADDED_LIVE_V1019__=true; | |
| var SITE='https://bep40-v-aistudio.static.hf.space'; | |
| var HUB='https://huggingface.co/spaces/bep40/V.AISTUDIO/resolve/main'; | |
| var STORE=[]; | |
| function norm(s){return String(s||'').normalize('NFD').replace(/[\u0300-\u036f]/g,'').replace(/[Đđ]/g,'d').toLowerCase();} | |
| function compact(s){return norm(s).replace(/[^a-z0-9]+/g,'');} | |
| function slugify(s){return norm(s).replace(/[^a-z0-9]+/g,'-').replace(/^-+|-+$/g,'').slice(0,150)||'san-pham-url';} | |
| function money(n){n=Number(n||0);return n?Math.round(n).toLocaleString('vi-VN')+'đ':'LH';} | |
| function cleanSpecs(sp){var out={}; if(!sp||typeof sp!=='object'||Array.isArray(sp))return out; Object.keys(sp).forEach(function(k){var v=sp[k], s=String(k)+' '+String(v); if(!k||v==null)return; if(/\{\{|\}\}|\$\{|mã bảo vệ|ma bao ve|đổi mã khác|doi ma khac/i.test(s))return; out[String(k).trim()]=String(v).trim();}); return out;} | |
| function cleanFeats(arr){var bad=/(trang chu|he thong cua hang|khuyen mai|dang tai du lieu|san pham lien quan|facebook|youtube|gallery popup|binh luan|loai san pham|thuong hieu\s*$)/i; var out=[]; (Array.isArray(arr)?arr:[]).forEach(function(f){var t=String(f||'').replace(/\s+/g,' ').trim(); if(!t||t.length>320||bad.test(norm(t)))return; if(out.indexOf(t)<0)out.push(t);}); return out.slice(0,30);} | |
| function productPath(p){return '/san-pham/'+encodeURIComponent((p&&p.slug)||'san-pham')+'/index.html';} | |
| function canon(p){p=p||{}; var sku=p.sku||p.mod||p.model||''; var name=p.n||p.name||sku||'Sản phẩm'; var sl=p.slug||slugify((sku?sku+' ':'')+name); var pn=Number(p.pn||p.priceNum||0)||0; var price=p.p||p.price||money(pn); var img=p.i||p.image||((p.imgs||p.images||[])[0])||''; var imgs=p.imgs||p.images||[]; if(!Array.isArray(imgs))imgs=[]; if(img&&imgs.indexOf(img)<0)imgs.unshift(img); var url=SITE+'/san-pham/'+sl+'/index.html'; var cat=p.c||p.cat||'Sản phẩm thêm qua URL'; var cs=p.cs||slugify(cat); var specs=cleanSpecs(p.specs); var feats=cleanFeats(p.feats); | |
| if(sl==='canzy-cz-id-078eu'){ | |
| name=p.n||p.name||'CZ-ID 078EU | Canzy | Bếp từ'; sku='CZ-ID 078EU'; cat='Bếp từ'; cs='bep-tu'; pn=Number(p.pn||20980000)||20980000; price=p.p||p.price||'20.980.000đ'; | |
| specs=Object.assign({'Loại sản phẩm':'Bếp từ','Thương hiệu':'Canzy','Model':'CZ-ID 078EU','Xuất xứ':'Indonesia','Công suất':'3000W'},specs); | |
| ['Bếp từ Canzy','Công suất 3000W','Xuất xứ Indonesia'].forEach(function(x){if(feats.indexOf(x)<0)feats.push(x);}); | |
| } | |
| if(sl==='canzy-cz-lt869i-max-bep-bep-tu-canzy-cz-lt869i-max'){ | |
| name='Bếp từ Canzy CZ LT869I Max'; sku='CANZY CZ LT869I MAX BEP'; cat='Bếp từ'; cs='bep-tu'; pn=15980000; price='15.980.000đ'; img=img||'https://bepviet.vn/media/product/9886_a111.png'; imgs=imgs.length?imgs:[img]; | |
| specs=Object.assign({'Số bếp nấu':'2 bếp','Kiểu bếp':'Bếp âm','Công suất tổng':'5200W','Công suất Booster':'2600W mỗi vùng nấu','Mức công suất nấu':'9 mức','Chất liệu mặt bếp':'Kính Vitroceramic','Điều khiển':'Cảm ứng','Kích thước mặt bếp':'730 x 430 mm','Kích thước khoét đá':'685 x 395 mm'},specs); | |
| ['Booster công suất cao cho 2 vùng nấu','Inverter tiết kiệm điện','Khóa bàn phím an toàn','Hẹn giờ nấu tiện lợi'].forEach(function(x){if(feats.indexOf(x)<0)feats.push(x);}); | |
| } | |
| var out=Object.assign({},p,{_url_added:true,n:name,name:name,sku:sku,mod:sku,model:sku,p:price,price:price,pn:pn,priceNum:pn,discPrice:pn,c:cat,cat:cat,cs:cs,ci:p.ci||'fa-box',slug:sl,l:url,url:url,vai_url:url,link:url,i:img,image:img,imgs:imgs,images:imgs,specs:specs,feats:feats,sum:p.sum||p.summary||'',summary:p.sum||p.summary||'',desc:p.desc||p.sum||p.summary||'',brand:p.brand||'',_source_url:p._source_url||p.source_url||''}); | |
| out._idx=norm([out.name,out.sku,out.model,out.brand,out.cat,out.slug,JSON.stringify(out.specs),(out.feats||[]).join(' '),out.sum,out.desc].join(' ')); return out; | |
| } | |
| function key(p){return compact((p&&((p.mod||p.model||p.sku||p.slug||p.n||p.name)))||'');} | |
| function mergeArray(a){if(!Array.isArray(a))return 0; var n=0; STORE.forEach(function(p){var k=key(p); if(!k)return; var idx=a.findIndex(function(x){return key(x)===k||compact(x&&x.slug)===compact(p.slug);}); if(idx>=0)a[idx]=Object.assign({},a[idx],p); else {a.unshift(p); n++;}}); return n;} | |
| function merge(){var n=0; if(Array.isArray(window.D))n+=mergeArray(window.D); if(Array.isArray(window.F))n+=mergeArray(window.F); else if(Array.isArray(window.D))window.F=window.D.slice(); ['PRODUCTS','products','ALL_PRODUCTS','allProducts'].forEach(function(k){if(Array.isArray(window[k]))n+=mergeArray(window[k]);}); try{if(typeof initFilters==='function')initFilters();}catch(e){} try{if(typeof buildFilters==='function')buildFilters();}catch(e){} try{if(typeof updateStats==='function')updateStats();}catch(e){} return n;} | |
| function findIdx(p){var D=window.D||[]; return Array.isArray(D)?D.findIndex(function(x){return key(x)===key(p)||String(x.slug||'')===p.slug;}):-1;} | |
| function findBySlug(sl){sl=String(sl||''); return STORE.find(function(p){return p.slug===sl||compact(p.slug)===compact(sl)||compact(p.sku)===compact(sl);});} | |
| function renderNoRedirectFallback(p){ | |
| if(!p)return false; | |
| if(location.pathname.indexOf('/san-pham/')<0)return false; | |
| try{ | |
| var name=p.name||p.n||p.sku||'Sản phẩm', img=p.image||p.i||((p.imgs||[])[0])||'', price=p.price||p.p||money(p.pn); | |
| var main=document.querySelector('#mainImg'); if(main&&img){main.src=img;main.alt=name;} | |
| var el=document.querySelector('#name'); if(el)el.textContent=name; | |
| el=document.querySelector('#bcName'); if(el)el.textContent=name; | |
| el=document.querySelector('#sku'); if(el)el.textContent=p.sku||p.mod||''; | |
| el=document.querySelector('#cat'); if(el)el.textContent=p.cat||p.c||''; | |
| el=document.querySelector('#price'); if(el)el.textContent=price; | |
| el=document.querySelector('#summary'); if(el)el.textContent=p.summary||p.sum||p.desc||''; | |
| el=document.querySelector('#descText'); if(el)el.textContent=p.desc||p.summary||p.sum||''; | |
| document.title=name+' | V.AI STUDIO'; | |
| try{history.pushState({slug:p.slug},'',productPath(p));}catch(_e){} | |
| window.scrollTo({top:0,behavior:'smooth'}); | |
| return true; | |
| }catch(e){return false;} | |
| } | |
| function openProduct(p,noReload){ | |
| merge(); | |
| var idx=findIdx(p); | |
| if(idx>=0&&typeof window.showDetail==='function'){ | |
| try{window.showDetail(idx); try{history.pushState({slug:p.slug},'',productPath(p));}catch(_e){} return true;}catch(e){} | |
| } | |
| if(renderNoRedirectFallback(p))return true; | |
| if(noReload){ | |
| setTimeout(function(){merge(); var i=findIdx(p); if(i>=0&&typeof window.showDetail==='function'){try{window.showDetail(i); history.pushState({slug:p.slug},'',productPath(p));}catch(e){renderNoRedirectFallback(p);}} else renderNoRedirectFallback(p);},200); | |
| return true; | |
| } | |
| return false; | |
| } | |
| function patchSearch(){if(window.__VAI_URL_ADDED_SEARCH_V1019__)return; var old=window.doSearch; if(typeof old!=='function')return; window.__VAI_URL_ADDED_SEARCH_V1019__=true; window.doSearch=function(){merge(); var r=old.apply(this,arguments); setTimeout(function(){injectCards();},0); return r;};} | |
| function cardHtml(p){var esc=function(s){return String(s==null?'':s).replace(/[&<>"']/g,function(c){return {'&':'&','<':'<','>':'>','"':'"',"'":'''}[c];});}; return '<div class="pi"><img src="'+esc(p.image)+'" alt="'+esc(p.name)+'"><span class="pi-badge">URL</span></div><div class="pb"><div class="pn">'+esc(p.name)+'</div><div class="pp">'+esc(p.price)+'</div><div class="pf"><span>'+esc(p.sku)+'</span><i class="fas fa-arrow-right"></i></div></div>';} | |
| function patchLinks(){if(window.__VAI_URL_ADDED_LINKS_V1019__)return; window.__VAI_URL_ADDED_LINKS_V1019__=true; document.addEventListener('click',function(ev){try{var a=ev.target&&ev.target.closest&&ev.target.closest('a[href]'); if(!a)return; var u=new URL(a.getAttribute('href'),location.origin); if(u.origin!==location.origin)return; var m=u.pathname.match(/\/san-pham\/([^\/]+)\/?(?:index\.html)?/i); if(!m)return; var p=findBySlug(decodeURIComponent(m[1])); if(!p)return; ev.preventDefault(); ev.stopPropagation(); openProduct(p,true);}catch(e){}},true);} | |
| function injectCards(){var q=document.getElementById('q'); var grid=document.getElementById('grid'); if(!q||!grid||!q.value)return; var nq=compact(q.value); if(!nq)return; var text=compact(grid.textContent||''); var hits=STORE.filter(function(p){return compact([p.name,p.sku,p.model,p.mod,p.brand,p.cat,p.slug,p.sum,p.desc].join(' ')).indexOf(nq)>=0;}).slice(0,20); hits.reverse().forEach(function(p){if(text.indexOf(compact(p.name).slice(0,12))>=0||document.querySelector('[data-url-added-slug="'+p.slug+'"]'))return; var card=document.createElement('div'); card.className='pc fade vis'; card.setAttribute('data-url-added-slug',p.slug); card.onclick=function(){openProduct(p,true)}; card.innerHTML=cardHtml(p); grid.insertBefore(card,grid.firstChild);});} | |
| function handleDeep(){var qs=new URLSearchParams(location.search); var sl=qs.get('p')||qs.get('product')||''; if(!sl&&location.hash){var m=location.hash.match(/product=([^&]+)/); if(m)sl=decodeURIComponent(m[1]);} if(!sl)return; var p=findBySlug(sl); if(!p)return; merge(); var idx=findIdx(p); if(idx>=0&&typeof window.showDetail==='function'){try{window.showDetail(idx); history.replaceState({slug:p.slug},'',productPath(p)); return true;}catch(e){}} return renderNoRedirectFallback(p);} | |
| function load(){var q='?v='+Date.now(); var u=(location.origin&&location.origin.indexOf('hf.space')>=0?'/products_url_added.json':SITE+'/products_url_added.json')+q; return fetch(u,{cache:'no-store'}).then(function(r){if(!r.ok)throw new Error(r.status);return r.json();}).catch(function(){return fetch(HUB+'/products_url_added.json'+q,{cache:'no-store'}).then(function(r){return r.json();});}).then(function(list){STORE=(Array.isArray(list)?list:[]).map(canon); window.VAI_URL_ADDED_PRODUCTS=STORE; patchLinks(); var tries=0;(function loop(){merge();patchSearch();patchLinks();injectCards();handleDeep(); if(++tries<240)setTimeout(loop,250);})(); console.log('[VAI URL-added live] loaded no-hash',STORE.length); return STORE;}).catch(function(e){console.warn('[VAI URL-added live] failed',e);});} | |
| window.VAIUrlAddedCompat=window.VAIUrlAddedCompat||{}; window.VAIUrlAddedCompat.load=load; window.VAIUrlAddedCompat.merge=merge; window.VAIUrlAddedCompat.products=function(){return STORE}; window.VAIUrlAddedCompat.open=openProduct; | |
| if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',load); else load(); | |
| })(); |