PageSourceSearch

https://coffee-labo.co.jp/wp-content/cache/min/1/wp-content/plugin…/js/coffee-labo-ai-search.js?ver=1790126336

js coffee-labo.co.jp collected 2026-09-24 22:21:45 UTC 18,856 bytes, 27 lines download raw bytes

1(()=>{'use strict';const runtimeKey='__clwmcpAiSearchRuntime';const existingRuntime=window[runtimeKey];if(existingRuntime&&typeof existingRuntime.refresh==='function'){existingRuntime.refresh(document);return}
2const config=window.CoffeeLaboAISearchConfig||{};const isFreeMode=String(config.mode||'free')!=='openai';const runtime={refresh:()=>{}};const placement={widget:null,variant:null,answered:!1};const placementExperiment='ai_position_6063_v1';const placementMetric=(action)=>{if(!config.analytics||!placement.variant)return;window.__clwmcpAnalyticsRuntime?.send('ai_placement',{content_type:placement.variant,content_id:action,experiment_id:placementExperiment,})};const initializePlacement=(widget)=>{if(!config.placementExperiment||placement.widget||location.pathname.replace(/\/$/,'')!=='/recommended-coffee-beans'||widget.dataset.postId!=='6063'||widget.dataset.context!=='article'||widget.dataset.clwmcpAiCollapsible!=='1')return;const content=document.querySelector('.post_content');if(!content||widget.parentElement!==content||content.querySelectorAll('[data-clwmcp-ai]').length!==1)return;const title='結論:コーヒー豆を買うなら「ラボカフェ」「珈琲きゃろっと」「土居珈琲」がおすすめ';const heading=[...content.querySelectorAll('h2')].find(node=>node.textContent.trim()===title);if(!heading||heading.parentElement!==content)return;let anchor=heading.nextElementSibling;while(anchor&&anchor.tagName!=='H2'){const list=anchor.querySelector('ul');if(list&&list.children.length===3&&['ラボカフェ','珈琲きゃろっと','土居珈琲'].every((name,i)=>list.children[i].textContent.includes(name)))break;anchor=anchor.nextElementSibling}
3if(!anchor||anchor.tagName==='H2'||widget.contains(anchor))return;const key='coffee-labo:'+placementExperiment;const variants=['article_end','after_top3'];const maxAge=30*24*60*60*1000;let variant;try{const saved=JSON.parse(localStorage.getItem(key)||'null');if(saved&&variants.includes(saved.variant)&&saved.expires>Date.now()&&saved.expires<=Date.now()+maxAge){variant=saved.variant}else{const bytes=new Uint8Array(1);crypto.getRandomValues(bytes);variant=variants[bytes[0]%2];const record=JSON.stringify({variant,expires:Date.now()+maxAge});localStorage.setItem(key,record);if(localStorage.getItem(key)!==record)return}}catch(_){return}
4if(variant==='after_top3')anchor.after(widget);placement.widget=widget;placement.variant=variant;widget.dataset.aiPlacement=variant;placementMetric('assigned');const commerceHosts=new Set(['coffee-labo.co.jp','shop.coffee-labo.co.jp']);const affiliateHosts=['a8.net','moshimo.com','amazon.co.jp','amzn.to','rakuten.co.jp','rakuten.ne.jp','a.r10.to','shopping.yahoo.co.jp','accesstrade.net','valuecommerce.com','afi-b.com','affitch.com','felmat.net','rentracks.jp'];document.addEventListener('click',(event)=>{if(!placement.answered)return;const link=event.target?.closest?.('a[href]');if(!link||!content.contains(link))return;let url;try{url=new URL(link.href,location.href)}catch(_){return}
5if(!['http:','https:'].includes(url.protocol))return;if(commerceHosts.has(url.hostname)&&/^\/(shop|products|collections|lp)(\/|$)/.test(url.pathname)){placementMetric('shop_click_after_answer')}else if(affiliateHosts.some(host=>url.hostname===host||url.hostname.endsWith('.'+host))){placementMetric('affiliate_click_after_answer')}})};const pushMetric=(event,widget,extra={})=>
5{if(!config.analytics)return;const analytics=window.__clwmcpAnalyticsRuntime;if(!analytics||typeof analytics.send!=='function')return;analytics.send(event,{ai_search_context:widget.dataset.context||'article',ai_search_mode:String(config.mode||'free'),...extra,});if(widget===placement.widget){if(event==='ai_answer_success')placement.answered=!0;placementMetric(event)}};const element=(tag,className='',text='')=>{const node=document.createElement(tag);if(className)node.className=className;if(text)node.textContent=text;return node};const heading=(className,text,level=3)=>{const node=element('div',className,text);node.setAttribute('role','heading');node.setAttribute('aria-level',String(level));return node};const setBusy=(widget,busy)=>{const input=widget.querySelector('[data-clwmcp-ai-input]');const submit=widget.querySelector('[data-clwmcp-ai-submit]');widget.dataset.clwmcpAiBusy=busy?'1':'0';if(input)input.disabled=busy;if(submit){submit.disabled=busy;submit.textContent=busy?(isFreeMode?'検索中…':'回答中…'):(isFreeMode?'記事から探す':'質問する')}
6widget.setAttribute('aria-busy',busy?'true':'false')};const showStatus=(widget,message,type='loading')=>{const status=widget.querySelector('[data-clwmcp-ai-status]');if(!status)return;status.hidden=!1;status.className=`clwmcp-ai__status clwmcp-ai__status--${type}`;status.replaceChildren();if(type==='loading')status.appendChild(element('span','clwmcp-ai__spinner'));status.appendChild(document.createTextNode(message))};const hideStatus=(widget)=>{const status=widget.querySelector('[data-clwmcp-ai-status]');if(status){status.hidden=!0;status.replaceChildren()}};const focusWithoutScroll=(input)=>{try{input.focus({preventScroll:!0})}catch(_){input.focus()}};const isPanelExpanded=(widget)=>widget.dataset.clwmcpAiCollapsed!=='1';const setPanelExpanded=(widget,expanded,options={})=>{if(widget.dataset.clwmcpAiCollapsible!=='1')return;const panel=widget.querySelector('[data-clwmcp-ai-panel]');const toggle=widget.querySelector('[data-clwmcp-ai-toggle]');if(!panel||!toggle)return;const previous=isPanelExpanded(widget);const next=Boolean(expanded);const label=next?'質問欄を閉じる':'質問欄を開く';widget.dataset.clwmcpAiCollapsed=next?'0':'1';panel.hidden=!next;toggle.setAttribute('aria-expanded',next?'true':'false');toggle.setAttribute('aria-label',label);const labelNode=toggle.querySelector('[data-clwmcp-ai-toggle-label]');if(labelNode)labelNode.textContent=label;if(next)initializeTurnstile(widget);if(options.track&&previous!==next){pushMetric(next?'ai_search_expand':'ai_search_collapse',widget)}
7if(next&&options.focus){const input=widget.querySelector('[data-clwmcp-ai-input]');if(input){const focusInput=()=>focusWithoutScroll(input);if(typeof window.requestAnimationFrame==='function'){window.requestAnimationFrame(focusInput)}else{window.setTimeout(focusInput,0)}}}};const fillQuestion=(widget,question)=>{const input=widget.querySelector('[data-clwmcp-ai-input]');if(!input)return!1;input.value=String(question||'');input.dispatchEvent(new Event('input',{bubbles:!0}));hideStatus(widget);focusWithoutScroll(input);if(typeof input.setSelectionRange==='function'){const end=input.value.length;input.setSelectionRange(end,end)}
8return!0};const getTurnstileToken=(widget)=>{const direct=String(widget.dataset.turnstileToken||'');if(direct)return direct;const container=widget.querySelector('[data-clwmcp-turnstile]');const widgetId=container?.dataset.turnstileWidgetId;if(widgetId!==undefined&&window.turnstile&&typeof window.turnstile.getResponse==='function'){try{return String(window.turnstile.getResponse(widgetId)||'')}catch(_){}}
9const field=widget.querySelector('input[name="cf-turnstile-response"]');return String(field?.value||'')};const renderTurnstile=(widget)=>{if(!config.turnstileEnabled)return;const container=widget.querySelector('[data-clwmcp-turnstile]');if(!container||container.dataset.turnstileRendered==='1')return;if(!window.turnstile||typeof window.turnstile.render!=='function')return;const doRender=()=>{if(container.dataset.turnstileRendered==='1')return;try{const widgetId=window.turnstile.render(container,{sitekey:String(config.turnstileSiteKey||''),action:String(config.turnstileAction||'coffee_labo_ai'),theme:'auto',size:'flexible',callback:(token)=>{widget.dataset.turnstileToken=String(token||'');widget.dataset.turnstileError=''},'expired-callback':()=>{widget.dataset.turnstileToken=''},'timeout-callback':()=>{widget.dataset.turnstileToken=''},'error-callback':()=>{widget.dataset.turnstileToken='';widget.dataset.turnstileError='1'},});container.dataset.turnstileWidgetId=String(widgetId);container.dataset.turnstileRendered='1';widget.dataset.turnstileError=''}catch(_){widget.dataset.turnstileError='1'}};doRender()};
9const initializeTurnstile=(widget)=>{if(!config.turnstileEnabled)return;if(!String(config.turnstileSiteKey||'')){widget.dataset.turnstileError='1';return}
10const container=widget.querySelector('[data-clwmcp-turnstile]');if(!container||container.dataset.turnstileRendered==='1')return;const tryRender=()=>{try{renderTurnstile(widget)}catch(_){widget.dataset.turnstileError='1'}
11return container.dataset.turnstileRendered==='1'};if(tryRender()||container.dataset.turnstileInitializing==='1')return;container.dataset.turnstileInitializing='1';let attempts=0;const timer=window.setInterval(()=>{attempts+=1;const rendered=tryRender();if(rendered||attempts>=100){window.clearInterval(timer);delete container.dataset.turnstileInitializing;if(!rendered)widget.dataset.turnstileError='1'}},100)};const resetTurnstile=(widget)=>{if(!config.turnstileEnabled||!window.turnstile||typeof window.turnstile.reset!=='function')return;const container=widget.querySelector('[data-clwmcp-turnstile]');const widgetId=container?.dataset.turnstileWidgetId;widget.dataset.turnstileToken='';if(widgetId===undefined)return;try{window.turnstile.reset(widgetId)}catch(_){widget.dataset.turnstileError='1'}};const scrollResultIntoView=(result)=>{const reveal=()=>{const rect=result.getBoundingClientRect();const viewportHeight=window.innerHeight||document.documentElement.clientHeight||0;const needsScroll=rect.top<80||(viewportHeight>0&&rect.top>viewportHeight*0.72);if(!needsScroll)return;const reduceMotion=window.matchMedia&&window.matchMedia('(prefers-reduced-motion: reduce)').matches;try{result.scrollIntoView({behavior:reduceMotion?'auto':'smooth',block:'start',})}catch(_){result.scrollIntoView()}};if(typeof window.requestAnimationFrame==='function'){window.requestAnimationFrame(()=>window.requestAnimationFrame(reveal))}else{window.setTimeout(reveal,0)}};const renderResult=(widget,data)=>{const result=widget.querySelector('[data-clwmcp-ai-result]');if(!result)return;setPanelExpanded(widget,!0,{track:!1,focus:!1});result.replaceChildren();result.hidden=!1;const answerSection=element('div','clwmcp-ai__answer');answerSection.appendChild(heading('clwmcp-ai__answer-title',isFreeMode?'関連する記事本文':'回答'));answerSection.appendChild(element('p','clwmcp-ai__answer-text',String(data.answer||'')));result.appendChild(answerSection);if(data.response_mode==='free_fallback'){result.appendChild(element('p','clwmcp-ai__mode-note','現在はAI回答の代わりに、記事本文の関連箇所を表示しています。'))}
12if(data.safety_note){result.appendChild(element('p','clwmcp-ai__safety',String(data.safety_note)))}
13const sources=Array.isArray(data.sources)?data.sources:[];if(sources.length){const sourceSection=element('div','clwmcp-ai__sources');sourceSection.appendChild(heading('clwmcp-ai__sources-title',isFreeMode?'参考・関連の記事':'参考にした記事'));const list=element('ul','clwmcp-ai__source-list');sources.forEach((source,index)=>{const item=element('li','clwmcp-ai__source-item');const sourceUrl=String(source.url||'').trim();if(sourceUrl){const link=element('a','clwmcp-ai__source-link');link.href=sourceUrl;link.textContent=String(source.title||'参考記事');link.addEventListener('click',()=>{pushMetric('ai_source_click',widget,{ai_source_position:index+1,})});item.appendChild(link)}else{item.appendChild(element('span','clwmcp-ai__source-title',String(source.title||'参考記事')))}
14if(source.excerpt)item.appendChild(element('p','clwmcp-ai__source-excerpt',String(source.excerpt)));list.appendChild(item)});sourceSection.appendChild(list);result.appendChild(sourceSection)}
15if(data.shop_cta?.url){const ctaWrap=element('div','clwmcp-ai__cta');const cta=element('a','clwmcp-ai__cta-link',String(data.shop_cta.label||'ラボカフェを見る'));cta.href=String(data.shop_cta.url);cta.addEventListener('click',()=>pushMetric('ai_labocafe_product_click',widget));ctaWrap.appendChild(cta);result.appendChild(ctaWrap)}
16const followUps=Array.isArray(data.follow_up_questions)?data.follow_up_questions:[];if(followUps.length){const followSection=element('div','clwmcp-ai__followups');followSection.appendChild(element('p','clwmcp-ai__followups-label','é
16–¢é€£ã™ã‚‹è³ªå•'));const followList=element('div','clwmcp-ai__followups-list');followUps.forEach((question)=>{const button=element('button','clwmcp-ai__followup',String(question));button.type='button';button.dataset.clwmcpAiFollowup=String(question);followList.appendChild(button)});followSection.appendChild(followList);result.appendChild(followSection)}
17scrollResultIntoView(result)};const submitQuestion=async(widget,question)=>{const turnstileToken=getTurnstileToken(widget);if(config.turnstileEnabled&&!turnstileToken){const message=widget.dataset.turnstileError==='1'?'安全確認を読み込めませんでした。ページを再読み込みして再度お試しください。':'安全確認が完了してから、もう一度お試しください。';showStatus(widget,message,'error');return}
18const result=widget.querySelector('[data-clwmcp-ai-result]');if(result)result.hidden=!0;setBusy(widget,!0);showStatus(widget,config.messages?.loading||'記事を調べて回答を作成しています…');pushMetric('ai_search_submit',widget);const controller=new AbortController();const timer=window.setTimeout(()=>controller.abort(),Number(config.timeoutMs||42000));try{const response=await fetch(String(config.restUrl||''),{method:'POST',credentials:'same-origin',headers:{Accept:'application/json','Content-Type':'application/json',},body:JSON.stringify({question,post_id:Number(widget.dataset.postId||0),token:String(widget.dataset.token||''),turnstile_token:turnstileToken,channel:'widget',}),signal:controller.signal,});let payload=null;try{payload=await response.json()}catch(_){}
19if(!response.ok){throw new Error(payload?.message||config.messages?.genericError||'回答を取得できませんでした。')}
20hideStatus(widget);renderResult(widget,payload||{});pushMetric(payload?.insufficient?'ai_answer_no_result':'ai_answer_success',widget,{ai_answer_intent:String(payload?.intent||'other'),ai_response_mode:String(payload?.response_mode||config.mode||'free'),ai_answer_source_count:Array.isArray(payload?.sources)?payload.sources.length:0,})}catch(error){const message=error?.name==='AbortError'?'回答に時間がかかっています。質問を短くして再度お試しください。':String(error?.message||config.messages?.genericError||'回答を取得できませんでした。');showStatus(widget,message,'error');pushMetric('ai_search_error',widget,{ai_search_error_type:error?.name==='AbortError'?'timeout':'request',})}finally{window.clearTimeout(timer);resetTurnstile(widget);setBusy(widget,!1)}};const submitFromWidget=(widget,isFollowUp=!1)=>{if(widget.dataset.clwmcpAiBusy==='1')return;setPanelExpanded(widget,!0,{track:!1,focus:!1});const form=widget.querySelector('[data-clwmcp-ai-form]');const input=widget.querySelector('[data-clwmcp-ai-input]');if(!form||!input)return;const question=String(input.value||'').trim();if(question.length<6){showStatus(widget,'質問は6文字以上で入力してください。','error');focusWithoutScroll(input);return}
21if(isFollowUp)pushMetric('ai_followup_submit',widget);void submitQuestion(widget,question)};const initializedWidgets=new WeakSet();const initializeWidget=(widget)=>{if(!widget||initializedWidgets.has(widget))return;const form=widget.querySelector('[data-clwmcp-ai-form]');const input=widget.querySelector('[data-clwmcp-ai-input]');if(!form||!input)return;initializedWidgets.add(widget);initializePlacement(widget);if(widget.dataset.clwmcpAiCollapsible==='1'){setPanelExpanded(widget,isPanelExpanded(widget),{track:!1,focus:!1})}else{initializeTurnstile(widget)}
22if('IntersectionObserver' in window){const observer=new IntersectionObserver((entries)=>{if(entries.some((entry)=>entry.isIntersecting)){pushMetric('ai_search_view',widget);observer.disconnect()}},{threshold:0.25});observer.observe(widget)}else{pushMetric('ai_search_view',widget)}};const initializeWidgets=(root=document)=>{const widgets=[];if(root&&typeof root.matches==='function'&&root.matches('[data-clwmcp-ai]')){widgets.push(root)}
23if(root&&typeof root.closest==='function'){const owner=root.closest('[data-clwmcp-ai]');if(owner)widgets.push(owner)}
24if(root&&typeof root.querySelectorAll==='function'){root.querySelectorAll('[data-clwmcp-ai]').forEach((widget)=>widgets.push(widget))}
24[...new Set(widgets)].forEach(initializeWidget)};const handleClick=(event)=>{const target=event.target;if(!target||typeof target.closest!=='function')return;const toggle=target.closest('[data-clwmcp-ai-toggle]');if(toggle){const widget=toggle.closest('[data-clwmcp-ai]');if(!widget)return;event.preventDefault();initializeWidget(widget);setPanelExpanded(widget,!isPanelExpanded(widget),{track:!0,focus:!isPanelExpanded(widget),});return}
25const submit=target.closest('[data-clwmcp-ai-submit]');if(submit){const widget=submit.closest('[data-clwmcp-ai]');if(!widget)return;event.preventDefault();initializeWidget(widget);submitFromWidget(widget);return}
26const suggestion=target.closest('[data-clwmcp-ai-suggestion]');if(suggestion){const widget=suggestion.closest('[data-clwmcp-ai]');if(!widget)return;event.preventDefault();initializeWidget(widget);fillQuestion(widget,suggestion.dataset.clwmcpAiSuggestion||suggestion.textContent||'');return}
27const followUp=target.closest('[data-clwmcp-ai-followup]');if(followUp){const widget=followUp.closest('[data-clwmcp-ai]');if(!widget)return;event.preventDefault();initializeWidget(widget);if(!fillQuestion(widget,followUp.dataset.clwmcpAiFollowup||followUp.textContent||''))return;submitFromWidget(widget,!0)}};const handleSubmit=(event)=>{const form=event.target;if(!form||typeof form.matches!=='function'||!form.matches('[data-clwmcp-ai-form]'))return;event.preventDefault();const widget=form.closest('[data-clwmcp-ai]');if(!widget)return;initializeWidget(widget);submitFromWidget(widget)};document.addEventListener('click',handleClick,!0);document.addEventListener('submit',handleSubmit,!0);window.addEventListener('pageshow',()=>initializeWidgets(document));let observing=!1;const start=()=>{initializeWidgets(document);if(observing||!document.documentElement||!('MutationObserver' in window))return;observing=!0;const observer=new MutationObserver((mutations)=>{mutations.forEach((mutation)=>{mutation.addedNodes.forEach((node)=>initializeWidgets(node))})});observer.observe(document.documentElement,{childList:!0,subtree:!0})};runtime.refresh=initializeWidgets;window[runtimeKey]=runtime;if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',start,{once:!0})}else{start()}})()

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.