PageSourceSearch

https://www.portlandglass.com/brand/_assets/js/o2/opus2.textToSpeech.33ffdb1c267e783cdc4a.js

js portlandglass.com collected 2026-10-07 12:11:27 UTC 19,326 bytes, 2 lines download raw bytes

1"use strict";(self.webpackChunkcrownpeak_opus2=self.webpackChunkcrownpeak_opus2||[]).push([["textToSpeech"],{"./src/js/opus2/text2speech/commonFunctions.ts"(t,e,n){n.d(e,{CommonFunctions:()=>o});var s=n(/*! tslib */"./node_modules/tslib/tslib.es6.mjs"),i=n(/*! ../util/getSessionCorrelationId */"./src/js/opus2/util/getSessionCorrelationId.ts");class o{static getInstance(){var t;return null!==(t=this.instance)&&void 0!==t||(this.instance=new o),this.instance}constructor(){this.blogContainer=null,this.blogText="",this.blogImage=null,this.availableVoices=[],this.textChunks=[],this.currentChunkIndex=0,this.isPaused=!1,this.isPlaying=!1,this.pageUrl="",this.isFirefox=/Firefox/i.test(navigator.userAgent),this.domLookup(),this.pageUrl=window.location.href,this.speechSettingsUtterance={lang:"en-US",rate:1,pitch:.4}}domLookup(){this.blogContainer=document.querySelector(".entry-content"),this.blogImage=document.querySelector(".entry-content img"),this.blogContainer&&(this.blogContainer.style.position="relative"),this.extractTextFromDiv()}extractTextFromDiv(){return this.blogContainer?(this.blogText=this.blogContainer.textContent||this.blogContainer.innerText||"",this.blogText):""}calculatePlaybackDuration(){if(!this.blogText||0===this.blogText.trim().length)return 0;const t=this.blogText.trim().replace(/\s+/g," ").split(/\s+/).filter(t=>t.length>0).length/(150*this.speechSettingsUtterance.rate);return Math.ceil(60*t)}formatDuration(t){if(t<60)return`${t}s`;const e=Math.floor(t/60),n=t%60;return 0===n?`${e}m`:`${e}m ${n}s`}getEstimatedPlaybackTime(){const t=this.calculatePlaybackDuration();return this.formatDuration(t)}getBlogTitle(){const t=document.querySelector(".entry-title");return t&&t.textContent||""}getBlogImage(){return this.blogImage?this.blogImage.src:""}getVoices(){return(0,s.__awaiter)(this,void 0,void 0,function*(){if(globalThis.speechSynthesis)return new Promise(t=>{let e=globalThis.speechSynthesis.getVoices();if(e.length>0)return this.processVoices(e),void t();const n=()=>{e=globalThis.speechSynthesis.getVoices(),e.length>0&&(this.processVoices(e),globalThis.speechSynthesis.removeEventListener("voiceschanged",n),t())};globalThis.speechSynthesis.addEventListener("voiceschanged",n),setTimeout(()=>{globalThis.speechSynthesis.removeEventListener("voiceschanged",n),this.processVoices(globalThis.speechSynthesis.getVoices()),t()},3e3)})})}processVoices(t){this.availableVoices=t;const e=this.availableVoices.filter(t=>t.lang.includes("en-US")),n=e.filter(t=>t.name.includes("Natural")),s=["Ava","Emma","Ana","Aria","Jenny","Michelle"],i=n.filter(t=>s.some(e=>t.name.includes(e)));if(i.length>0){const t=self.crypto.getRandomValues(new Uint32Array(1))[0]%i.length;this.speechSettingsUtterance.voice=i[t]}else if(n.length>0){const t=self.crypto.getRandomValues(new Uint32Array(1))[0]%n.length;this.speechSettingsUtterance.voice=n[t]}else if(e.length>0){const t=self.crypto.getRandomValues(new Uint32Array(1))[0]%e.length;this.speechSettingsUtterance.voice=e[t]}
1}speakText(t){if(!("speechSynthesis"in globalThis))return void console.error("SpeechSynthesis API is not supported in this browser.");const e=this.blogText;if(e.trim())try{globalThis.speechSynthesis.cancel(),this.chunkText(e),this.currentChunkIndex=0,this.playChunk(t)}catch(t){console.error("Error during speech synthesis:",t)}else console.warn("No text provided for speech.")}chunkText(t){const e=t.split(/\s+/);this.textChunks=[];for(let t=0;t<e.length;t+=30)this.textChunks.push(e.slice(t,t+30).join(" "))}playChunk(t){if(this.currentChunkIndex>=this.textChunks.length)return void(this.isPlaying=!1);const e=this.textChunks[this.currentChunkIndex],n=new SpeechSynthesisUtterance(e);n.lang=this.speechSettingsUtterance.lang,n.rate=this.speechSettingsUtterance.rate,n.pitch=this.speechSettingsUtterance.pitch,this.speechSettingsUtterance.voice&&(n.voice=this.speechSettingsUtterance.voice),n.onstart=()=>{this.isPlaying=!0,t&&t.setAttribute("aria-label","Pause blog article audio")},n.onend=()=>{this.isPlaying&&!this.isPaused&&(this.currentChunkIndex++,this.playChunk(t))},n.onerror=e=>{console.error("Speech synthesis error:",e.error),t&&t.setAttribute("aria-label","Play blog article audio")},globalThis.speechSynthesis.speak(n)}pauseSpeech(t){if(this.isPlaying){this.isPlaying=!1,this.isPaused=!0;try{globalThis.speechSynthesis.cancel(),this.isFirefox&&(setTimeout(()=>{globalThis.speechSynthesis.speaking&&globalThis.speechSynthesis.cancel()},50),setTimeout(()=>{globalThis.speechSynthesis.speaking&&(globalThis.speechSynthesis.cancel(),console.warn("Firefox required multiple cancel attempts"))},200)),t&&t.setAttribute("aria-label","Resume blog article audio")}catch(t){console.warn("Error pausing speech:",t)}}}resumeSpeech(t){this.isPaused&&(this.playChunk(t),this.isPaused=!1,this.isPlaying=!0,t&&t.setAttribute("aria-label","Pause blog article audio"))}analyticsEvent(t,e,n,s){var o,a;let r=window.dataLayer;const c=(0,i.getSessionAndCorrelationID)(),l={page_location:this.pageUrl,audio_title:null!=e?e:"",audio_total_time:null!=n?n:0,session_data:null!==(o=c.sessionID)&&void 0!==o?o:"",session_timeStamp:null!==(a=(new Date).toISOString())&&void 0!==a?a:"",event:""};switch(t){case"play":default:l.event="audio_played";break;case"pause":l.event="audio_paused",l.audio_played_duration=s;break;case"end":l.event="audio_ended",l.audio_played_duration=s;break;case"ignored":l.event="audio_ignored",l.audio_played_duration=0}r.push(l)}}},"./src/js/opus2/text2speech/mainT2S.ts"(t,e,n){n.r(e),n.d(e,{TextToSpeechHelper:()=>r});var s=n(/*! tslib */"./node_modules/tslib/tslib.es6.mjs"),i=n(/*! ./commonFunctions */"./src/js/opus2/text2speech/commonFunctions.ts"),o=n(/*! ../util/share */"./src/js/opus2/util/share.ts"),a=n(/*! ../util/device-detection */"./src/js/opus2/util/device-detection.ts");class r{static getInstance(){var t;return null!==(t=this.instance)&&void 0!==t?t:null}static create(){return(0,s.__awaiter)(this,void 0,void 0,function*(){return this.instance||(this.instance=new r,yield this.instance.initialize()),this.instance})}constructor(){this.playButton=null,this.audioDuration=10,this.currentTime=0,this.seekBarInterval=null,this.isPlaying=!1,this.posterImage=null,this.audioDurationText=null,this.parentContainer=null,this.closeButton=null,this.menuContainer=null,this.menuHeight=0,this.commonFunctionInstance=i.CommonFunctions.getInstance()}initialize(){return(0,s.__awaiter)(this,void 0,void 0,function*(){yield this.commonFunctionInstance.getVoices(),this.injectT2SDom(),this.addBeforeUnloadEvent(),this.addScrollListner()})}createImg(t,e){const n=document.createElement("img");return n.src=t,e&&(n.className=e),n}createButton(t){const e=document.createElement("button"),n=document.createElementNS("http://www.w3.org/2000/svg","svg");n.setAttribute("aria-hidden","true");const s=document.createElementNS("http://www.w3.org/2000/svg","use");return s.setAttributeNS("http://www.w3.org/1999/xlink","xlink:href",t),n.appendChild(s),e.appendChild(n),e}createSeekbar(){const t=document.createElement("div");t.className="seekbar";const e=document.createElement("div");return e.className="seekbar-progress",t.appendChild(e),t}injectT2SCss(){document.getElementById("t2s-style")||this.getAudioContainerPosition().then(()=>{const t=document.createElement("style");
1t.id="t2s-style",t.textContent=`\n                .t2s-parent {\n                    position: sticky;\n                    top: ${this.menuHeight}px;\n                    left: 0;\n                    font-family: sans-serif;\n                    margin: 1rem 0;\n                    border-radius: 8px;\n                    box-shadow: 0 2px 6px rgba(0,0,0,0.1);\n                    width: fit-content;\n                }\n                .t2s {\n                    display: flex;\n                    flex-direction: column;\n                    background: #fff;\n                    position: relative;\n\n                    background: rgba(255, 255, 255, 0.4); /* Semi-transparent background */\n                    border-radius: 15px; /* Rounded corners */\n                    backdrop-filter: blur(6px); /* Frosted glass effect */\n                    -webkit-backdrop-filter: blur(6px); /* For Safari support */\n                    border: 1px solid rgba(255, 255, 255, 0.4); /* Subtle border */\n                    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* Soft shadow for depth */\n                    padding: 1rem;\n                    min-width: 300px;\n                    width: fit-content;\n                    text-align: right;\n                }\n                .t2s-close {\n                    position: absolute;\n                    top:-0.5rem;\n                    right:-0.5rem;\n                    cursor: pointer;\n                }\n                .t2s-close img {\n                    width: 20px;\n                    height: 20px;\n                }\n                .t2s-player {\n                    display: flex;\n                    gap: 1rem;\n                }\n                .t2s-player-poster{\n                    width: 4rem;\n                }\n                .t2s-player-poster img {\n                    max-width: 100%;\n                    height: 80px;\n                    object-fit: cover; /* zoom & crop edges */\n                    object-position: center; /* keep centered */\n                    border-radius: 0.25rem;\n                    box-shadow: 4px 4px 14px -4px rgba(0,0,0,0.75);\n                    -webkit-box-shadow: 4px 4px 14px -4px rgba(0,0,0,0.75);\n                    -moz-box-shadow: 4px 4px 14px -4px rgba(0,0,0,0.75);\n                }\n                .t2s-player-container {\n                    flex: 1;\n                    display: flex;\n                    flex-direction: column;\n                    justify-content: center;\n                    text-align: left;\n                }\n                .t2s-player-container-controls {\n                    display: flex;\n                    align-items: center;\n                    gap: 0.5rem;\n                    margin-top: 0.5rem;\n                }\n                .t2s-player-container-controls button {\n                    background: none;\n                    border: none;\n                    cursor: pointer;\n                    width: 20px;\n                    height: 20px;\n                    transition: 200ms ease-in-out;\n                }\n                .t2s-player-container-controls button:hover {\n                    opacity: 0.8;\n                }\n                .t2s-player-container-controls button svg {\n                    width: 20px;\n                    height: 20px;\n                }\n                .t2s span{\n                    font-size: 0.8em;\n                    opacity: 0.8\n                }\n                .seekbar {\n                    flex: 1;\n                    height: 4px;\n                    background: #eee;\n                    border-radius: 2px;\n                    position: relative;\n                }\n                .seekbar-progress {\n                    height: 100%;\n                    width: 0%;\n                    background: var(--primary-500);\n                    border-radius: 2px;\n                }\n                .t2s-footer {\n                    position: absolute;\n                    right: 1rem;\n                    bottom: 0.75rem;\n                    display: flex;\n                    align-items: center;\n                    gap: 0.25rem;\n                }\n                .t2s-footer span{\n                    font-size: 0.6em;\n                    font-style: italic;\n                }\n                .t2s-footer .t2s-brand {\n                    width: 12px;\n                    height: 12px;\n                }\n            `,document.head.appendChild(t)}).catch(t=>{console.warn(t)})}injectT2SDom(){this.injectT2SCss(),this.getAudioDuration();const t=document.querySelector(".entry-content");
1if(!t)return void console.warn("No .entry-content found in DOM");this.parentContainer=document.createElement("div"),this.parentContainer.className="t2s-parent";const e=document.createElement("div");e.className="t2s",this.closeButton=document.createElement("div"),this.closeButton.className="t2s-close",this.closeButton.style.display="none",this.closeButton.addEventListener("click",()=>this.clickedOnClose()),this.closeButton.appendChild(this.createImg("/brand/_assets/images/brand-img/close-circle.svg"));const n=document.createElement("div");n.className="t2s-player-poster";const s=this.commonFunctionInstance.getBlogImage();s?(this.posterImage=this.createImg(s),n.appendChild(this.posterImage)):(this.posterImage=this.createImg("/brand/_assets/images/favicon/apple-touch-icon.png"),this.posterImage.style.width="100%",this.posterImage.style.height="auto",this.posterImage.style.boxShadow="none",n.appendChild(this.posterImage));const i=document.createElement("div");i.className="t2s-player-container-controls",this.playButton=this.createButton("/brand/_assets/images/icons/hero-icon-sprite.svg#play-icon"),this.playButton.id="t2s-playing",this.playButton.addEventListener("click",()=>this.togglePlayButton()),i.appendChild(this.playButton),i.appendChild(this.createSeekbar());const o=document.createElement("div");o.className="t2s-player-container";const a=document.createElement("span");a.textContent=this.commonFunctionInstance.getBlogTitle(),o.appendChild(a),o.appendChild(i);const r=document.createElement("div");r.className="t2s-player",r.appendChild(n),r.appendChild(o);const c=document.createElement("div");c.className="t2s-footer",c.appendChild(this.createImg("/brand/_assets/images/favicon/apple-touch-icon.png","t2s-brand")),this.audioDurationText=document.createElement("span"),this.audioDurationText.textContent=`Estimated Read Time : ${this.commonFunctionInstance.getEstimatedPlaybackTime()}`,this.audioDurationText.className="t2s-summary",c.appendChild(this.audioDurationText),e.appendChild(this.closeButton),e.appendChild(r),e.appendChild(c),this.parentContainer.appendChild(e),t.prepend(this.parentContainer)}togglePlayButton(){this.playButton&&(this.commonFunctionInstance.isPlaying?(this.commonFunctionInstance.pauseSpeech(this.playButton),this.playButton.innerHTML='<svg aria-hidden="true"><use xlink:href="/brand/_assets/images/icons/hero-icon-sprite.svg#play-icon"></use></svg>',this.playButton.id="t2s-playing",this.isPlaying=!1,this.commonFunctionInstance.analyticsEvent("pause",this.commonFunctionInstance.getBlogTitle(),this.commonFunctionInstance.calculatePlaybackDuration(),this.currentTime),this.stopSeekBarProgress()):this.commonFunctionInstance.isPaused?(this.commonFunctionInstance.resumeSpeech(this.playButton),this.playButton.innerHTML='<svg aria-hidden="true"><use xlink:href="/brand/_assets/images/icons/hero-icon-sprite.svg#pause-icon"></use></svg>',this.playButton.id="t2s-paused",this.isPlaying=!0,this.commonFunctionInstance.analyticsEvent("play",this.commonFunctionInstance.getBlogTitle(),this.commonFunctionInstance.calculatePlaybackDuration()),this.startSeekBarProgress()):(this.commonFunctionInstance.speakText(this.playButton),this.playButton.innerHTML='<svg aria-hidden="true"><use xlink:href="/brand/_assets/images/icons/hero-icon-sprite.svg#pause-icon"></use></svg>',this.playButton.id="t2s-paused",this.isPlaying=!0,this.commonFunctionInstance.analyticsEvent("play",this.commonFunctionInstance.getBlogTitle(),this.commonFunctionInstance.calculatePlaybackDuration()),this.startSeekBarProgress()))}startSeekBarProgress(){this.seekBarInterval&&this.stopSeekBarProgress(),this.seekBarInterval=window.setInterval(()=>{this.isPlaying&&this.currentTime<this.audioDuration&&(this.currentTime+=1,this.updateSeekBarVisual(),this.currentTime>=this.audioDuration&&this.onAudioComplete())},1e3)}stopSeekBarProgress(){this.seekBarInterval&&(clearInterval(this.seekBarInterval),this.seekBarInterval=null)}updateSeekBarVisual(){const t=document.querySelector(".seekbar-progress");if(!t)return;const e=this.calculateSeekbarPercent();t.style.width=`${e}%`}calculateSeekbarPercent(){if(this.audioDuration<=0)return 0;const t=this.currentTime/this.audioDuration*100;return Math.min(t,100)}onAudioComplete(){this.currentTime=0,this.isPlaying=!1,this.stopSeekBarProgress(),this.commonFunctionInstance.analyticsEvent("end",this.commonFunctionInstance.getBlogTitle(),this.commonFunctionInstance.calculatePlaybackDuration(),this.commonFunctionInstance.calculatePlaybackDuration()),this.displayPlaybutton(),this.updateSeekBarVisual()}setAudioDuration(t){this.audioDuration=Math.max(t,1),this.currentTime=0,this.updateSeekBarVisual()}getCurrentTime(){return this.currentTime}getAudioDuration(){return this.audioDuration=this.commonFunctionInstance.calculatePlaybackDuration(),this.audioDuration}seekTo(t){this.currentTime=Math.max(0,Math.min(t,this.audioDuration)),this.updateSeekBarVisual()}clickedOnClose(){this.parentContainer&&(this.displayPlaybutton(),globalThis.speechSynthesis.cancel(),this.stopSeekBarProgress(),this.parentContainer.style.position="static");const t=document.querySelector(".t2s-close");t&&t.remove(),0===this.currentTime?this.commonFunctionInstance.analyticsEvent("ignored",this.commonFunctionInstance.getBlogTitle(),this.commonFunctionInstance.calculatePlaybackDuration(),this.commonFunctionInstance.calculatePlaybackDuration()):this.commonFunctionInstance.analyticsEvent("pause",this.commonFunctionInstance.getBlogTitle(),this.commonFunctionInstance.calculatePlaybackDuration(),this.currentTime),globalThis.speechSynthesis.cancel()}addBeforeUnloadEvent(){globalThis.addEventListener("beforeunload",()=>this.beforeunload())}beforeunload(){0===this.currentTime?this.commonFunctionInstance.analyticsEvent("ignored",this.commonFunctionInstance.getBlogTitle(),this.commonFunctionInstance.calculatePlaybackDuration(),this.commonFunctionInstance.calculatePlaybackDuration()):this.commonFunctionInstance.analyticsEvent("pause",this.commonFunctionInstance.getBlogTitle(),this.commonFunctionInstance.calculatePlaybackDuration(),this.currentTime),globalThis.speechSynthesis.cancel()}displayPlaybutton(){this.playButton&&(this.playButton.id="t2s-playing",this.playButton.innerHTML='<svg aria-hidden="true"><use xlink:href="/brand/_assets/images/icons/hero-icon-sprite.svg#play-icon"></use></svg>')}
1addScrollListner(){globalThis.addEventListener("scroll",()=>this.scroll())}getAudioContainerPosition(){return(0,s.__awaiter)(this,void 0,void 0,function*(){var t;const e=null===(t=document.getElementById("conceptCode"))||void 0===t?void 0:t.value,n=yield(0,o.getBrandDetailsFromBrandJson)(e);!(null==n?void 0:n.disable_sticky_header)||(0,a.isTouchDevice)()?(null==n?void 0:n.disable_sticky_header_mobile)&&(0,a.isTouchDevice)()?this.menuHeight=8:(this.menuContainer||(this.menuContainer=document.querySelector(".second-head")),this.menuContainer&&(this.menuHeight=this.menuContainer.getBoundingClientRect().height),this.menuHeight=Math.ceil(this.menuHeight)+8):this.menuHeight=8})}scroll(){if(this.parentContainer){this.parentContainer.getBoundingClientRect().top<=this.menuHeight+16&&"static"!==this.parentContainer.style.position?this.closeButton&&(this.closeButton.style.display="block"):this.closeButton&&(this.closeButton.style.display="none")}}}}}]);
2//# sourceMappingURL=opus2.textToSpeech.33ffdb1c267e783cdc4a.js.map

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.