From 256a182378961b7f8b9bcfd638ff43891425677d Mon Sep 17 00:00:00 2001 From: Markos Gogoulos Date: Thu, 7 May 2026 14:14:59 +0300 Subject: [PATCH] wtv --- .../mediacms-moodle/tiny/mediacms/amd/build/iframeembed.min.js | 2 +- .../tiny/mediacms/amd/build/iframeembed.min.js.map | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/iframeembed.min.js b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/iframeembed.min.js index ac8da881..35e46b6f 100755 --- a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/iframeembed.min.js +++ b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/iframeembed.min.js @@ -1,3 +1,3 @@ -define("tiny_mediacms/iframeembed",["exports","core/templates","core/str","core/modal_events","./common","./iframemodal","./selectors","./options"],(function(_exports,_templates,_str,ModalEvents,_common,_iframemodal,_selectors,_options){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_templates=_interopRequireDefault(_templates),ModalEvents=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(ModalEvents),_iframemodal=_interopRequireDefault(_iframemodal),_selectors=_interopRequireDefault(_selectors);const PREFS_FIELDS=["showTitle","linkTitle","showUserAvatar","width","height"];return _exports.default=class{constructor(editor){_defineProperty(this,"editor",null),_defineProperty(this,"currentModal",null),_defineProperty(this,"isUpdating",!1),_defineProperty(this,"selectedIframe",null),_defineProperty(this,"debounceTimer",null),_defineProperty(this,"iframeLibraryUrl","https://temp.web357.com/mediacms/deic-mediacms-embed-videos.html"),this.editor=editor}parseInput(input){if(!input||!input.trim())return null;const iframeMatch=(input=input.trim()).match(/]*src=["']([^"']+)["'][^>]*>/i);return iframeMatch?this.parseEmbedUrl(iframeMatch[1]):input.startsWith("http://")||input.startsWith("https://")?this.parseVideoUrl(input):null}parseVideoUrl(url){try{const urlObj=new URL(url),baseUrl="".concat(urlObj.protocol,"//").concat(urlObj.host);if("/view"===urlObj.pathname&&urlObj.searchParams.has("m"))return{baseUrl:baseUrl,videoId:urlObj.searchParams.get("m"),isEmbed:!1};if("/embed"===urlObj.pathname&&urlObj.searchParams.has("m")){const tParam=urlObj.searchParams.get("t"),widthParam=urlObj.searchParams.get("width"),heightParam=urlObj.searchParams.get("height");return{baseUrl:baseUrl,videoId:urlObj.searchParams.get("m"),isEmbed:!0,showTitle:"1"===urlObj.searchParams.get("showTitle"),linkTitle:"1"===urlObj.searchParams.get("linkTitle"),showUserAvatar:"1"===urlObj.searchParams.get("showUserAvatar"),width:widthParam?parseInt(widthParam):null,height:heightParam?parseInt(heightParam):null,startAt:tParam?this.secondsToTimeString(parseInt(tParam)):null}}if(urlObj.pathname.includes("/filter/mediacms/launch.php")&&urlObj.searchParams.has("token")){const tParam=urlObj.searchParams.get("t"),widthParam=urlObj.searchParams.get("width"),heightParam=urlObj.searchParams.get("height");return{baseUrl:baseUrl,videoId:urlObj.searchParams.get("token"),rawUrl:url,isLtiLaunch:!0,showTitle:"1"===urlObj.searchParams.get("showTitle"),linkTitle:"1"===urlObj.searchParams.get("linkTitle"),showUserAvatar:"1"===urlObj.searchParams.get("showUserAvatar"),width:widthParam?parseInt(widthParam):null,height:heightParam?parseInt(heightParam):null,startAt:tParam?this.secondsToTimeString(parseInt(tParam)):null}}return{baseUrl:baseUrl,rawUrl:url,isGeneric:!0}}catch(e){return null}}parseEmbedUrl(url){return this.parseVideoUrl(url)}secondsToTimeString(seconds){const mins=Math.floor(seconds/60),secs=seconds%60;return"".concat(mins,":").concat(secs.toString().padStart(2,"0"))}timeStringToSeconds(timeStr){if(!timeStr||!timeStr.trim())return null;if((timeStr=timeStr.trim()).includes(":")){const parts=timeStr.split(":");return 60*(parseInt(parts[0])||0)+(parseInt(parts[1])||0)}const secs=parseInt(timeStr);return isNaN(secs)?null:secs}parseWidthHeight(value){if(!value)return null;const parsed=parseInt(value.trim());return isNaN(parsed)?null:parsed}computeAspectRatioCSS(values){const w=values.width||560,h=values.height||315;return"".concat(w," / ").concat(h)}buildTextLinkUrl(parsed,options){let viewUrl;if(viewUrl=parsed.isGeneric||parsed.isLtiLaunch?parsed.rawUrl:"".concat(parsed.baseUrl,"/view?m=").concat(parsed.videoId),options.startAtEnabled&&options.startAt){const seconds=this.timeStringToSeconds(options.startAt);if(null!==seconds&&seconds>0){const url=new URL(viewUrl);url.searchParams.set("t",seconds.toString()),viewUrl=url.toString()}}return viewUrl}buildEmbedUrl(parsed,options){if(parsed.isGeneric)return parsed.rawUrl;let url;if(parsed.isLtiLaunch){url=new URL(parsed.rawUrl);const token=url.searchParams.get("token"),courseid=url.searchParams.get("courseid");url.search="",url.searchParams.set("token",token),courseid&&url.searchParams.set("courseid",courseid)}else url=new URL("".concat(parsed.baseUrl,"/embed")),url.searchParams.set("m",parsed.videoId);if(url.searchParams.set("showTitle",options.showTitle?"1":"0"),url.searchParams.set("showUserAvatar",options.showUserAvatar?"1":"0"),url.searchParams.set("linkTitle",options.linkTitle?"1":"0"),options.startAtEnabled&&options.startAt){const seconds=this.timeStringToSeconds(options.startAt);null!==seconds&&seconds>0&&url.searchParams.set("t",seconds.toString())}return options.width&&url.searchParams.set("width",options.width),options.height&&url.searchParams.set("height",options.height),url.toString()}savePrefs(values){try{const prefs={};PREFS_FIELDS.forEach((k=>{void 0!==values[k]&&(prefs[k]=values[k])})),localStorage.setItem("tiny_mediacms_embed_prefs",JSON.stringify(prefs))}catch(_){}}loadPrefs(){try{return JSON.parse(localStorage.getItem("tiny_mediacms_embed_prefs")||"null")||{}}catch(_){return{}}}async getTemplateContext(){var _savedPrefs$width,_savedPrefs$height,_this=this;let data=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};const editorData=(0,_options.getData)(this.editor),autoConvertOptions=(null==editorData?void 0:editorData.autoConvertOptions)||{},savedPrefs=this.loadPrefs(),getDefault=function(key){let fallback=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return _this.isUpdating&&void 0!==data[key]?data[key]:void 0!==savedPrefs[key]?savedPrefs[key]:void 0!==autoConvertOptions[key]?autoConvertOptions[key]:fallback},width=this.isUpdating&&data.width?data.width:null!==(_savedPrefs$width=savedPrefs.width)&&void 0!==_savedPrefs$width?_savedPrefs$width:560,height=this.isUpdating&&data.height?data.height:null!==(_savedPrefs$height=savedPrefs.height)&&void 0!==_savedPrefs$height?_savedPrefs$height:315;return{elementid:this.editor.getElement().id,isupdating:this.isUpdating,url:data.url||"",showTitle:getDefault("showTitle"),linkTitle:getDefault("linkTitle"),showUserAvatar:getDefault("showUserAvatar"),textLinkOnly:data.textLinkOnly||!1,startAtEnabled:data.startAtEnabled||!1,startAt:data.startAt||"0:00",width:width,height:height}}async displayDialogue(){this.selectedIframe=this.getSelectedIframe();const data=this.getCurrentIframeData();this.isUpdating=null!==data,this.currentModal=await _iframemodal.default.create({title:(0,_str.getString)("iframemodaltitle",_common.component),templateContext:await this.getTemplateContext(data||{})}),await this.registerEventListeners(this.currentModal)}getSelectedIframe(){const node=this.editor.selection.getNode();if("a"===node.nodeName.toLowerCase()&&"true"===node.getAttribute("data-mediacms-textlink"))return node;if("iframe"===node.nodeName.toLowerCase())return node;const iframe=node.querySelector("iframe");if(iframe)return iframe;const wrapper=node.closest(".tiny-mediacms-iframe-wrapper")||node.closest(".tiny-iframe-responsive");if(wrapper)return wrapper.querySelector("iframe");const textLink=node.closest('a[data-mediacms-textlink="true"]');return textLink||null}getCurrentIframeData(){var _parsed$showTitle2,_parsed$linkTitle2,_parsed$showUserAvata2;if(!this.selectedIframe)return null;if("a"===this.selectedIframe.nodeName.toLowerCase()&&"true"===this.selectedIframe.getAttribute("data-mediacms-textlink")){var _parsed$showTitle,_parsed$linkTitle,_parsed$showUserAvata;const href=this.selectedIframe.getAttribute("href"),parsed=this.parseInput(href);return{url:href,width:(null==parsed?void 0:parsed.width)||560,height:(null==parsed?void 0:parsed.height)||315,showTitle:null===(_parsed$showTitle=null==parsed?void 0:parsed.showTitle)||void 0===_parsed$showTitle||_parsed$showTitle,linkTitle:null===(_parsed$linkTitle=null==parsed?void 0:parsed.linkTitle)||void 0===_parsed$linkTitle||_parsed$linkTitle,showUserAvatar:null===(_parsed$showUserAvata=null==parsed?void 0:parsed.showUserAvatar)||void 0===_parsed$showUserAvata||_parsed$showUserAvata,responsive:!0,textLinkOnly:!0,startAtEnabled:null!==(null==parsed?void 0:parsed.startAt),startAt:(null==parsed?void 0:parsed.startAt)||"0:00"}}const src=this.selectedIframe.getAttribute("src"),parsed=this.parseInput(src),style=this.selectedIframe.getAttribute("style")||"",maxWidthMatch=style.match(/max-width:\s*(\d+(?:\.\d+)?)px/),aspectRatioMatch=style.match(/aspect-ratio:\s*(\d+(?:\.\d+)?)\s*\/\s*(\d+(?:\.\d+)?)/);let maxWidth=maxWidthMatch?parseInt(maxWidthMatch[1]):null;if(!maxWidth){const wrapper=this.selectedIframe.closest(".tiny-mediacms-iframe-wrapper"),wrapperMatch=(wrapper&&wrapper.getAttribute("style")||"").match(/max-width:\s*(\d+(?:\.\d+)?)px/);maxWidth=wrapperMatch?parseInt(wrapperMatch[1]):560}let height=315;if(aspectRatioMatch){const rw=parseFloat(aspectRatioMatch[1]),rh=parseFloat(aspectRatioMatch[2]);rw>0&&(height=Math.round(maxWidth*rh/rw))}return{url:src,width:maxWidth,height:height,showTitle:null===(_parsed$showTitle2=null==parsed?void 0:parsed.showTitle)||void 0===_parsed$showTitle2||_parsed$showTitle2,linkTitle:null===(_parsed$linkTitle2=null==parsed?void 0:parsed.linkTitle)||void 0===_parsed$linkTitle2||_parsed$linkTitle2,showUserAvatar:null===(_parsed$showUserAvata2=null==parsed?void 0:parsed.showUserAvatar)||void 0===_parsed$showUserAvata2||_parsed$showUserAvata2,startAtEnabled:!(null==parsed||!parsed.startAt),startAt:(null==parsed?void 0:parsed.startAt)||"0:00"}}getFormValues(root){const form=root.querySelector(_selectors.default.IFRAME.elements.form);return{url:form.querySelector(_selectors.default.IFRAME.elements.url).value.trim(),showTitle:form.querySelector(_selectors.default.IFRAME.elements.showTitle).checked,linkTitle:form.querySelector(_selectors.default.IFRAME.elements.linkTitle).checked,showUserAvatar:form.querySelector(_selectors.default.IFRAME.elements.showUserAvatar).checked,textLinkOnly:form.querySelector(_selectors.default.IFRAME.elements.textLinkOnly).checked,startAtEnabled:form.querySelector(_selectors.default.IFRAME.elements.startAtEnabled).checked,startAt:form.querySelector(_selectors.default.IFRAME.elements.startAt).value.trim(),width:this.parseWidthHeight(form.querySelector(_selectors.default.IFRAME.elements.width).value),height:this.parseWidthHeight(form.querySelector(_selectors.default.IFRAME.elements.height).value)}}async generateIframeHtml(values){const parsed=this.parseInput(values.url);if(!parsed)return"";if(values.textLinkOnly){const viewUrl=this.buildTextLinkUrl(parsed,values),linkText=(str=>{const div=document.createElement("div");return div.textContent=str,div.innerHTML})(viewUrl),hrefUrl=viewUrl.replace(/"/g,""");return'

').concat(linkText,"

")}const context={src:this.buildEmbedUrl(parsed,values),maxWidth:values.width||560,height:values.height||315,aspectRatioCSS:this.computeAspectRatioCSS(values)},{html:html}=await _templates.default.renderForPromise("tiny_mediacms/iframe_embed_output",context);return html}async updatePreview(root){let updateUrlField=arguments.length>1&&void 0!==arguments[1]&&arguments[1];const values=this.getFormValues(root),previewContainer=root.querySelector(_selectors.default.IFRAME.elements.preview),urlWarning=root.querySelector(_selectors.default.IFRAME.elements.urlWarning);if(!values.url)return previewContainer.innerHTML='Enter a video URL to see preview',void urlWarning.classList.add("d-none");const parsed=this.parseInput(values.url);if(!parsed)return previewContainer.innerHTML='Invalid URL format',void urlWarning.classList.remove("d-none");urlWarning.classList.add("d-none");const embedUrl=this.buildEmbedUrl(parsed,values);if(updateUrlField&&!parsed.isGeneric){root.querySelector(_selectors.default.IFRAME.elements.form).querySelector(_selectors.default.IFRAME.elements.url).value=embedUrl}if(values.textLinkOnly){const viewUrl=this.buildTextLinkUrl(parsed,values),linkText=(str=>{const div=document.createElement("div");return div.textContent=str,div.innerHTML})(viewUrl),hrefUrl=viewUrl.replace(/"/g,""");previewContainer.innerHTML='\n
\n Text link preview:
\n ').concat(linkText,"\n
\n ")}else{const previewWidth=Math.min(values.width||560,400),previewHeight=Math.round(previewWidth*(values.height||315)/(values.width||560));previewContainer.innerHTML='\n \n \n ')}}handleInputChange(root){let updateUrlField=arguments.length>1&&void 0!==arguments[1]&&arguments[1];clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout((()=>{this.updatePreview(root,updateUrlField)}),500)}handleWidthChange(root){const form=root.querySelector(_selectors.default.IFRAME.elements.form),widthInput=form.querySelector(_selectors.default.IFRAME.elements.width),heightInput=form.querySelector(_selectors.default.IFRAME.elements.height),newWidth=parseInt(widthInput.value);!isNaN(newWidth)&&newWidth>0&&(heightInput.value=Math.round(9*newWidth/16)),this.handleInputChange(root)}handleHeightChange(root){this.handleInputChange(root)}async handleDialogueSubmission(modal){const root=modal.getRoot()[0],values=this.getFormValues(root);if(!values.url)return;this.savePrefs(values);const html=await this.generateIframeHtml(values);if(html)if(this.isUpdating&&this.selectedIframe){const wrapper=this.selectedIframe.closest(".tiny-mediacms-iframe-wrapper")||this.selectedIframe.closest(".tiny-iframe-responsive"),paragraphWrapper=wrapper?wrapper.closest("p"):this.selectedIframe.closest("p");paragraphWrapper?paragraphWrapper.outerHTML=html:wrapper?wrapper.outerHTML=html:this.selectedIframe.outerHTML=html,this.isUpdating=!1,setTimeout((()=>{this.editor.getBody().querySelectorAll("p:empty, p:blank").forEach((p=>{""!==p.innerHTML.trim()&&"
"!==p.innerHTML||p.remove()}))}),10),this.editor.fire("Change")}else{const node=this.editor.selection.getNode();"P"===node.nodeName&&""===node.innerHTML.trim()?node.outerHTML=html:this.editor.insertContent(html),setTimeout((()=>{this.editor.getBody().querySelectorAll("p").forEach((p=>{""!==p.innerHTML.trim()&&"
"!==p.innerHTML||p.remove()}))}),50)}}async handleRemove(modal){const confirmMessage=await(0,_str.getString)("removeiframeconfirm",_common.component);if(window.confirm(confirmMessage)){if(this.selectedIframe){const wrapper=this.selectedIframe.closest(".tiny-mediacms-iframe-wrapper")||this.selectedIframe.closest(".tiny-iframe-responsive");wrapper?wrapper.remove():this.selectedIframe.remove()}this.isUpdating=!1,modal.hide()}}async registerEventListeners(modal){await modal.getBody();const $root=modal.getRoot(),root=$root[0],form=root.querySelector(_selectors.default.IFRAME.elements.form);form.querySelector(_selectors.default.IFRAME.elements.url).addEventListener("input",(()=>this.handleInputChange(root))),[_selectors.default.IFRAME.elements.showTitle,_selectors.default.IFRAME.elements.linkTitle,_selectors.default.IFRAME.elements.showUserAvatar,_selectors.default.IFRAME.elements.startAtEnabled].forEach((selector=>{form.querySelector(selector).addEventListener("change",(()=>this.handleInputChange(root,!0)))})),form.querySelector(_selectors.default.IFRAME.elements.textLinkOnly).addEventListener("change",(()=>this.handleInputChange(root,!1))),form.querySelector(_selectors.default.IFRAME.elements.startAt).addEventListener("input",(()=>this.handleInputChange(root,!0))),form.querySelector(_selectors.default.IFRAME.elements.width).addEventListener("input",(()=>this.handleWidthChange(root))),form.querySelector(_selectors.default.IFRAME.elements.height).addEventListener("input",(()=>this.handleHeightChange(root))),$root.on(ModalEvents.save,(()=>this.handleDialogueSubmission(modal))),$root.on(ModalEvents.hidden,(()=>{this.currentModal.destroy()}));const removeBtn=root.querySelector(_selectors.default.IFRAME.actions.remove);removeBtn&&removeBtn.addEventListener("click",(()=>this.handleRemove(modal)));form.querySelector(_selectors.default.IFRAME.elements.url).value&&this.updatePreview(root);const iframeLibraryTabBtn=form.querySelector(_selectors.default.IFRAME.elements.tabIframeLibraryBtn);if(iframeLibraryTabBtn){iframeLibraryTabBtn.addEventListener("click",(e=>{e.preventDefault(),e.stopPropagation(),this.switchToIframeLibraryTab(root),setTimeout((()=>this.handleIframeLibraryTabClick(root)),100)})),iframeLibraryTabBtn.addEventListener("shown.bs.tab",(()=>this.handleIframeLibraryTabClick(root)));const $iframeLibraryTabBtn=window.jQuery?window.jQuery(iframeLibraryTabBtn):null;$iframeLibraryTabBtn&&$iframeLibraryTabBtn.on("shown.bs.tab",(()=>this.handleIframeLibraryTabClick(root)))}const urlTabBtn=form.querySelector(_selectors.default.IFRAME.elements.tabUrlBtn);urlTabBtn&&urlTabBtn.addEventListener("click",(e=>{e.preventDefault(),e.stopPropagation(),this.switchToUrlTab(root)}));const uploadMediaBtn=form.querySelector(_selectors.default.IFRAME.elements.tabUploadMediaBtn);uploadMediaBtn&&uploadMediaBtn.addEventListener("click",(e=>{e.preventDefault(),e.stopPropagation(),this.switchToIframeLibraryTab(root);let uploadUrl="";const ltiConfig=(0,_options.getLti)(this.editor);if(ltiConfig&<iConfig.contentItemUrl)try{const urlObj=new URL(ltiConfig.contentItemUrl);urlObj.searchParams.set("action","upload"),uploadUrl=urlObj.toString()}catch(err){}if(!uploadUrl){let baseUrl="";try{const editorData=(0,_options.getData)(this.editor);editorData&&editorData.mediacmsBaseUrl&&(baseUrl=editorData.mediacmsBaseUrl)}catch(err){}if(!baseUrl)try{const urlObj=new URL(this.iframeLibraryUrl);baseUrl="".concat(urlObj.protocol,"//").concat(urlObj.host)}catch(err){}baseUrl=baseUrl.replace(/\/$/,""),uploadUrl=baseUrl?"".concat(baseUrl,"/upload"):""}if(uploadUrl){const pane=form.querySelector(_selectors.default.IFRAME.elements.paneIframeLibrary);if(pane){const iframeEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryFrame),placeholderEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryPlaceholder),loadingEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryLoading);if(placeholderEl&&placeholderEl.classList.add("d-none"),loadingEl&&loadingEl.classList.remove("d-none"),iframeEl){iframeEl.classList.add("d-none");const loadHandler=()=>{this.handleIframeLibraryLoad(root),iframeEl.removeEventListener("load",loadHandler)};iframeEl.addEventListener("load",loadHandler),iframeEl.src=uploadUrl}}}})),this.registerIframeLibraryEventListeners(root),this.isUpdating?setTimeout((()=>this.updatePreview(root)),100):setTimeout((()=>this.handleIframeLibraryTabClick(root)),100)}switchToUrlTab(root){const form=root.querySelector(_selectors.default.IFRAME.elements.form),urlTabBtn=form.querySelector(_selectors.default.IFRAME.elements.tabUrlBtn),urlTabItem=form.querySelector(".tiny_iframecms_tab_url_item"),iframeLibraryTabBtn=form.querySelector(_selectors.default.IFRAME.elements.tabIframeLibraryBtn),urlPane=form.querySelector(_selectors.default.IFRAME.elements.paneUrl),iframeLibraryPane=form.querySelector(_selectors.default.IFRAME.elements.paneIframeLibrary);urlTabItem&&(urlTabItem.style.display=""),urlTabBtn&&(urlTabBtn.classList.add("active"),urlTabBtn.setAttribute("aria-selected","true")),iframeLibraryTabBtn&&(iframeLibraryTabBtn.classList.remove("active"),iframeLibraryTabBtn.setAttribute("aria-selected","false")),urlPane&&urlPane.classList.add("show","active"),iframeLibraryPane&&iframeLibraryPane.classList.remove("show","active")}switchToIframeLibraryTab(root){const form=root.querySelector(_selectors.default.IFRAME.elements.form),urlTabBtn=form.querySelector(_selectors.default.IFRAME.elements.tabUrlBtn),urlTabItem=form.querySelector(".tiny_iframecms_tab_url_item"),iframeLibraryTabBtn=form.querySelector(_selectors.default.IFRAME.elements.tabIframeLibraryBtn),urlPane=form.querySelector(_selectors.default.IFRAME.elements.paneUrl),iframeLibraryPane=form.querySelector(_selectors.default.IFRAME.elements.paneIframeLibrary);urlTabItem&&(urlTabItem.style.display="none"),urlTabBtn&&(urlTabBtn.classList.remove("active"),urlTabBtn.setAttribute("aria-selected","false")),iframeLibraryTabBtn&&(iframeLibraryTabBtn.classList.add("active"),iframeLibraryTabBtn.setAttribute("aria-selected","true")),urlPane&&urlPane.classList.remove("show","active"),iframeLibraryPane&&iframeLibraryPane.classList.add("show","active")}registerIframeLibraryEventListeners(root){window.addEventListener("message",(event=>{this.handleIframeLibraryMessage(root,event)}))}handleIframeLibraryTabClick(root){this.loadIframeLibrary(root)}loadIframeLibrary(root){const ltiConfig=(0,_options.getLti)(this.editor);null!=ltiConfig&<iConfig.contentItemUrl?this.loadIframeLibraryViaLti(root):this.loadIframeLibraryStatic(root)}loadIframeLibraryViaLti(root){const pane=root.querySelector(_selectors.default.IFRAME.elements.form).querySelector(_selectors.default.IFRAME.elements.paneIframeLibrary);if(!pane)return;const placeholderEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryPlaceholder),loadingEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryLoading),iframeEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryFrame);if(!iframeEl)return;placeholderEl&&placeholderEl.classList.add("d-none"),loadingEl&&loadingEl.classList.remove("d-none"),iframeEl.classList.add("d-none");iframeEl.addEventListener("load",(()=>{this.handleIframeLibraryLoad(root)}));const ltiConfig=(0,_options.getLti)(this.editor);iframeEl.src=ltiConfig.contentItemUrl}loadIframeLibraryStatic(root){const pane=root.querySelector(_selectors.default.IFRAME.elements.form).querySelector(_selectors.default.IFRAME.elements.paneIframeLibrary);if(!pane)return;const placeholderEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryPlaceholder),loadingEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryLoading),iframeEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryFrame);if(!iframeEl)return;placeholderEl&&placeholderEl.classList.add("d-none"),loadingEl&&loadingEl.classList.remove("d-none"),iframeEl.classList.add("d-none");const loadHandler=()=>{iframeEl.src===this.iframeLibraryUrl&&(this.handleIframeLibraryLoad(root),iframeEl.removeEventListener("load",loadHandler))};iframeEl.addEventListener("load",loadHandler),iframeEl.src=this.iframeLibraryUrl}handleIframeLibraryLoad(root){const pane=root.querySelector(_selectors.default.IFRAME.elements.form).querySelector(_selectors.default.IFRAME.elements.paneIframeLibrary);if(!pane)return;const placeholderEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryPlaceholder),loadingEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryLoading),iframeEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryFrame);placeholderEl&&placeholderEl.classList.add("d-none"),loadingEl&&loadingEl.classList.add("d-none"),iframeEl&&iframeEl.classList.remove("d-none")}handleIframeLibraryMessage(root,event){const data=event.data;if(data)if("videoSelected"===data.type&&data.embedUrl)this.selectIframeLibraryVideo(root,data.embedUrl,data.videoId);else if("ltiDeepLinkingResponse"!==data.type&&"LtiDeepLinkingResponse"!==data.messageType)if("selectMedia"!==data.action&&"mediaSelected"!==data.action);else{const embedUrl=data.embedUrl||data.url||"";embedUrl&&this.selectIframeLibraryVideo(root,embedUrl)}else{const contentItems=data.content_items||data.contentItems||[];if(contentItems.length>0){const item=contentItems[0],embedUrl=item.url||item.embed_url||item.embedUrl||"",videoId=item.id||item.mediaId||"";embedUrl&&this.selectIframeLibraryVideo(root,embedUrl,videoId)}}}selectIframeLibraryVideo(root,embedUrl){root.querySelector(_selectors.default.IFRAME.elements.form).querySelector(_selectors.default.IFRAME.elements.url).value=embedUrl;const configureTabItem=root.querySelector(".tiny_iframecms_tab_url_item");configureTabItem&&(configureTabItem.style.display=""),this.switchToUrlTab(root),this.updatePreview(root)}},_exports.default})); +define("tiny_mediacms/iframeembed",["exports","core/templates","core/str","core/modal_events","./common","./iframemodal","./selectors","./options"],(function(_exports,_templates,_str,ModalEvents,_common,_iframemodal,_selectors,_options){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_templates=_interopRequireDefault(_templates),ModalEvents=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(ModalEvents),_iframemodal=_interopRequireDefault(_iframemodal),_selectors=_interopRequireDefault(_selectors);const PREFS_FIELDS=["showTitle","linkTitle","showUserAvatar","width","height","textLinkOnly"];return _exports.default=class{constructor(editor){_defineProperty(this,"editor",null),_defineProperty(this,"currentModal",null),_defineProperty(this,"isUpdating",!1),_defineProperty(this,"selectedIframe",null),_defineProperty(this,"debounceTimer",null),_defineProperty(this,"iframeLibraryUrl","https://temp.web357.com/mediacms/deic-mediacms-embed-videos.html"),this.editor=editor}parseInput(input){if(!input||!input.trim())return null;const iframeMatch=(input=input.trim()).match(/]*src=["']([^"']+)["'][^>]*>/i);return iframeMatch?this.parseEmbedUrl(iframeMatch[1]):input.startsWith("http://")||input.startsWith("https://")?this.parseVideoUrl(input):null}parseVideoUrl(url){try{const urlObj=new URL(url),baseUrl="".concat(urlObj.protocol,"//").concat(urlObj.host);if("/view"===urlObj.pathname&&urlObj.searchParams.has("m"))return{baseUrl:baseUrl,videoId:urlObj.searchParams.get("m"),isEmbed:!1};if("/embed"===urlObj.pathname&&urlObj.searchParams.has("m")){const tParam=urlObj.searchParams.get("t"),widthParam=urlObj.searchParams.get("width"),heightParam=urlObj.searchParams.get("height");return{baseUrl:baseUrl,videoId:urlObj.searchParams.get("m"),isEmbed:!0,showTitle:"1"===urlObj.searchParams.get("showTitle"),linkTitle:"1"===urlObj.searchParams.get("linkTitle"),showUserAvatar:"1"===urlObj.searchParams.get("showUserAvatar"),width:widthParam?parseInt(widthParam):null,height:heightParam?parseInt(heightParam):null,startAt:tParam?this.secondsToTimeString(parseInt(tParam)):null}}if(urlObj.pathname.includes("/filter/mediacms/launch.php")&&urlObj.searchParams.has("token")){const tParam=urlObj.searchParams.get("t"),widthParam=urlObj.searchParams.get("width"),heightParam=urlObj.searchParams.get("height");return{baseUrl:baseUrl,videoId:urlObj.searchParams.get("token"),rawUrl:url,isLtiLaunch:!0,showTitle:"1"===urlObj.searchParams.get("showTitle"),linkTitle:"1"===urlObj.searchParams.get("linkTitle"),showUserAvatar:"1"===urlObj.searchParams.get("showUserAvatar"),width:widthParam?parseInt(widthParam):null,height:heightParam?parseInt(heightParam):null,startAt:tParam?this.secondsToTimeString(parseInt(tParam)):null}}return{baseUrl:baseUrl,rawUrl:url,isGeneric:!0}}catch(e){return null}}parseEmbedUrl(url){return this.parseVideoUrl(url)}secondsToTimeString(seconds){const mins=Math.floor(seconds/60),secs=seconds%60;return"".concat(mins,":").concat(secs.toString().padStart(2,"0"))}timeStringToSeconds(timeStr){if(!timeStr||!timeStr.trim())return null;if((timeStr=timeStr.trim()).includes(":")){const parts=timeStr.split(":");return 60*(parseInt(parts[0])||0)+(parseInt(parts[1])||0)}const secs=parseInt(timeStr);return isNaN(secs)?null:secs}parseWidthHeight(value){if(!value)return null;const parsed=parseInt(value.trim());return isNaN(parsed)?null:parsed}computeAspectRatioCSS(values){const w=values.width||560,h=values.height||315;return"".concat(w," / ").concat(h)}buildTextLinkUrl(parsed,options){let viewUrl;if(viewUrl=parsed.isGeneric||parsed.isLtiLaunch?parsed.rawUrl:"".concat(parsed.baseUrl,"/view?m=").concat(parsed.videoId),options.startAtEnabled&&options.startAt){const seconds=this.timeStringToSeconds(options.startAt);if(null!==seconds&&seconds>0){const url=new URL(viewUrl);url.searchParams.set("t",seconds.toString()),viewUrl=url.toString()}}return viewUrl}buildEmbedUrl(parsed,options){if(parsed.isGeneric)return parsed.rawUrl;let url;if(parsed.isLtiLaunch){url=new URL(parsed.rawUrl);const token=url.searchParams.get("token"),courseid=url.searchParams.get("courseid");url.search="",url.searchParams.set("token",token),courseid&&url.searchParams.set("courseid",courseid)}else url=new URL("".concat(parsed.baseUrl,"/embed")),url.searchParams.set("m",parsed.videoId);if(url.searchParams.set("showTitle",options.showTitle?"1":"0"),url.searchParams.set("showUserAvatar",options.showUserAvatar?"1":"0"),url.searchParams.set("linkTitle",options.linkTitle?"1":"0"),options.startAtEnabled&&options.startAt){const seconds=this.timeStringToSeconds(options.startAt);null!==seconds&&seconds>0&&url.searchParams.set("t",seconds.toString())}return options.width&&url.searchParams.set("width",options.width),options.height&&url.searchParams.set("height",options.height),url.toString()}signalShare(values){const parsed=this.parseInput(values.url);if(!parsed||parsed.isGeneric||!parsed.videoId)return;const editorData=(0,_options.getData)(this.editor),baseUrl=parsed.isLtiLaunch?(null==editorData?void 0:editorData.mediacmsBaseUrl)||"":parsed.baseUrl;if(!baseUrl)return;const ltiConfig=(0,_options.getLti)(this.editor),courseId=(null==ltiConfig?void 0:ltiConfig.courseId)||0;fetch("".concat(baseUrl,"/api/v1/media/").concat(parsed.videoId,"/share"),{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({courseid:courseId})}).catch((()=>{}))}savePrefs(values){try{const prefs={};PREFS_FIELDS.forEach((k=>{void 0!==values[k]&&(prefs[k]=values[k])})),localStorage.setItem("tiny_mediacms_embed_prefs",JSON.stringify(prefs))}catch(_){}}loadPrefs(){try{return JSON.parse(localStorage.getItem("tiny_mediacms_embed_prefs")||"null")||{}}catch(_){return{}}}async getTemplateContext(){var _savedPrefs$width,_savedPrefs$height,_this=this;let data=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};const editorData=(0,_options.getData)(this.editor),autoConvertOptions=(null==editorData?void 0:editorData.autoConvertOptions)||{},savedPrefs=this.loadPrefs(),getDefault=function(key){let fallback=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return _this.isUpdating&&void 0!==data[key]?data[key]:void 0!==savedPrefs[key]?savedPrefs[key]:void 0!==autoConvertOptions[key]?autoConvertOptions[key]:fallback},width=this.isUpdating&&data.width?data.width:null!==(_savedPrefs$width=savedPrefs.width)&&void 0!==_savedPrefs$width?_savedPrefs$width:560,height=this.isUpdating&&data.height?data.height:null!==(_savedPrefs$height=savedPrefs.height)&&void 0!==_savedPrefs$height?_savedPrefs$height:315;return{elementid:this.editor.getElement().id,isupdating:this.isUpdating,url:data.url||"",showTitle:getDefault("showTitle"),linkTitle:getDefault("linkTitle"),showUserAvatar:getDefault("showUserAvatar"),textLinkOnly:getDefault("textLinkOnly",!1),startAtEnabled:data.startAtEnabled||!1,startAt:data.startAt||"0:00",width:width,height:height}}async displayDialogue(){this.selectedIframe=this.getSelectedIframe();const data=this.getCurrentIframeData();this.isUpdating=null!==data,this.currentModal=await _iframemodal.default.create({title:(0,_str.getString)("iframemodaltitle",_common.component),templateContext:await this.getTemplateContext(data||{})}),await this.registerEventListeners(this.currentModal)}getSelectedIframe(){const node=this.editor.selection.getNode();if("a"===node.nodeName.toLowerCase()&&"true"===node.getAttribute("data-mediacms-textlink"))return node;if("iframe"===node.nodeName.toLowerCase())return node;const iframe=node.querySelector("iframe");if(iframe)return iframe;const wrapper=node.closest(".tiny-mediacms-iframe-wrapper")||node.closest(".tiny-iframe-responsive");if(wrapper)return wrapper.querySelector("iframe");const textLink=node.closest('a[data-mediacms-textlink="true"]');return textLink||null}getCurrentIframeData(){var _parsed$showTitle2,_parsed$linkTitle2,_parsed$showUserAvata2;if(!this.selectedIframe)return null;if("a"===this.selectedIframe.nodeName.toLowerCase()&&"true"===this.selectedIframe.getAttribute("data-mediacms-textlink")){var _parsed$showTitle,_parsed$linkTitle,_parsed$showUserAvata;const href=this.selectedIframe.getAttribute("href"),parsed=this.parseInput(href);return{url:href,width:(null==parsed?void 0:parsed.width)||560,height:(null==parsed?void 0:parsed.height)||315,showTitle:null===(_parsed$showTitle=null==parsed?void 0:parsed.showTitle)||void 0===_parsed$showTitle||_parsed$showTitle,linkTitle:null===(_parsed$linkTitle=null==parsed?void 0:parsed.linkTitle)||void 0===_parsed$linkTitle||_parsed$linkTitle,showUserAvatar:null===(_parsed$showUserAvata=null==parsed?void 0:parsed.showUserAvatar)||void 0===_parsed$showUserAvata||_parsed$showUserAvata,responsive:!0,textLinkOnly:!0,startAtEnabled:null!==(null==parsed?void 0:parsed.startAt),startAt:(null==parsed?void 0:parsed.startAt)||"0:00"}}const src=this.selectedIframe.getAttribute("src"),parsed=this.parseInput(src),style=this.selectedIframe.getAttribute("style")||"",maxWidthMatch=style.match(/max-width:\s*(\d+(?:\.\d+)?)px/),aspectRatioMatch=style.match(/aspect-ratio:\s*(\d+(?:\.\d+)?)\s*\/\s*(\d+(?:\.\d+)?)/);let maxWidth=maxWidthMatch?parseInt(maxWidthMatch[1]):null;if(!maxWidth){const wrapper=this.selectedIframe.closest(".tiny-mediacms-iframe-wrapper"),wrapperMatch=(wrapper&&wrapper.getAttribute("style")||"").match(/max-width:\s*(\d+(?:\.\d+)?)px/);maxWidth=wrapperMatch?parseInt(wrapperMatch[1]):560}let height=315;if(aspectRatioMatch){const rw=parseFloat(aspectRatioMatch[1]),rh=parseFloat(aspectRatioMatch[2]);rw>0&&(height=Math.round(maxWidth*rh/rw))}return{url:src,width:maxWidth,height:height,showTitle:null===(_parsed$showTitle2=null==parsed?void 0:parsed.showTitle)||void 0===_parsed$showTitle2||_parsed$showTitle2,linkTitle:null===(_parsed$linkTitle2=null==parsed?void 0:parsed.linkTitle)||void 0===_parsed$linkTitle2||_parsed$linkTitle2,showUserAvatar:null===(_parsed$showUserAvata2=null==parsed?void 0:parsed.showUserAvatar)||void 0===_parsed$showUserAvata2||_parsed$showUserAvata2,startAtEnabled:!(null==parsed||!parsed.startAt),startAt:(null==parsed?void 0:parsed.startAt)||"0:00"}}getFormValues(root){const form=root.querySelector(_selectors.default.IFRAME.elements.form);return{url:form.querySelector(_selectors.default.IFRAME.elements.url).value.trim(),showTitle:form.querySelector(_selectors.default.IFRAME.elements.showTitle).checked,linkTitle:form.querySelector(_selectors.default.IFRAME.elements.linkTitle).checked,showUserAvatar:form.querySelector(_selectors.default.IFRAME.elements.showUserAvatar).checked,textLinkOnly:form.querySelector(_selectors.default.IFRAME.elements.textLinkOnly).checked,startAtEnabled:form.querySelector(_selectors.default.IFRAME.elements.startAtEnabled).checked,startAt:form.querySelector(_selectors.default.IFRAME.elements.startAt).value.trim(),width:this.parseWidthHeight(form.querySelector(_selectors.default.IFRAME.elements.width).value),height:this.parseWidthHeight(form.querySelector(_selectors.default.IFRAME.elements.height).value)}}async generateIframeHtml(values){const parsed=this.parseInput(values.url);if(!parsed)return"";if(values.textLinkOnly){const viewUrl=this.buildTextLinkUrl(parsed,values),linkText=(str=>{const div=document.createElement("div");return div.textContent=str,div.innerHTML})(viewUrl),hrefUrl=viewUrl.replace(/"/g,""");return'

').concat(linkText,"

")}const context={src:this.buildEmbedUrl(parsed,values),maxWidth:values.width||560,height:values.height||315,aspectRatioCSS:this.computeAspectRatioCSS(values)},{html:html}=await _templates.default.renderForPromise("tiny_mediacms/iframe_embed_output",context);return html}async updatePreview(root){let updateUrlField=arguments.length>1&&void 0!==arguments[1]&&arguments[1];const values=this.getFormValues(root),previewContainer=root.querySelector(_selectors.default.IFRAME.elements.preview),urlWarning=root.querySelector(_selectors.default.IFRAME.elements.urlWarning);if(!values.url)return previewContainer.innerHTML='Enter a video URL to see preview',void urlWarning.classList.add("d-none");const parsed=this.parseInput(values.url);if(!parsed)return previewContainer.innerHTML='Invalid URL format',void urlWarning.classList.remove("d-none");urlWarning.classList.add("d-none");const embedUrl=this.buildEmbedUrl(parsed,values);if(updateUrlField&&!parsed.isGeneric){root.querySelector(_selectors.default.IFRAME.elements.form).querySelector(_selectors.default.IFRAME.elements.url).value=embedUrl}if(values.textLinkOnly){const viewUrl=this.buildTextLinkUrl(parsed,values),linkText=(str=>{const div=document.createElement("div");return div.textContent=str,div.innerHTML})(viewUrl),hrefUrl=viewUrl.replace(/"/g,""");previewContainer.innerHTML='\n
\n Text link preview:
\n ').concat(linkText,"\n
\n ")}else{const previewWidth=Math.min(values.width||560,400),previewHeight=Math.round(previewWidth*(values.height||315)/(values.width||560));previewContainer.innerHTML='\n \n \n ')}}handleInputChange(root){let updateUrlField=arguments.length>1&&void 0!==arguments[1]&&arguments[1];clearTimeout(this.debounceTimer),this.debounceTimer=setTimeout((()=>{this.updatePreview(root,updateUrlField)}),500)}handleWidthChange(root){const form=root.querySelector(_selectors.default.IFRAME.elements.form),widthInput=form.querySelector(_selectors.default.IFRAME.elements.width),heightInput=form.querySelector(_selectors.default.IFRAME.elements.height),newWidth=parseInt(widthInput.value);!isNaN(newWidth)&&newWidth>0&&(heightInput.value=Math.round(9*newWidth/16)),this.handleInputChange(root)}handleHeightChange(root){this.handleInputChange(root)}async handleDialogueSubmission(modal){const root=modal.getRoot()[0],values=this.getFormValues(root);if(!values.url)return;this.savePrefs(values),this.signalShare(values);const html=await this.generateIframeHtml(values);if(html)if(this.isUpdating&&this.selectedIframe){const wrapper=this.selectedIframe.closest(".tiny-mediacms-iframe-wrapper")||this.selectedIframe.closest(".tiny-iframe-responsive"),paragraphWrapper=wrapper?wrapper.closest("p"):this.selectedIframe.closest("p");paragraphWrapper?paragraphWrapper.outerHTML=html:wrapper?wrapper.outerHTML=html:this.selectedIframe.outerHTML=html,this.isUpdating=!1,setTimeout((()=>{this.editor.getBody().querySelectorAll("p:empty, p:blank").forEach((p=>{""!==p.innerHTML.trim()&&"
"!==p.innerHTML||p.remove()}))}),10),this.editor.fire("Change")}else{const node=this.editor.selection.getNode();"P"===node.nodeName&&""===node.innerHTML.trim()?node.outerHTML=html:this.editor.insertContent(html),setTimeout((()=>{this.editor.getBody().querySelectorAll("p").forEach((p=>{""!==p.innerHTML.trim()&&"
"!==p.innerHTML||p.remove()}))}),50)}}async handleRemove(modal){const confirmMessage=await(0,_str.getString)("removeiframeconfirm",_common.component);if(window.confirm(confirmMessage)){if(this.selectedIframe){const wrapper=this.selectedIframe.closest(".tiny-mediacms-iframe-wrapper")||this.selectedIframe.closest(".tiny-iframe-responsive");wrapper?wrapper.remove():this.selectedIframe.remove()}this.isUpdating=!1,modal.hide()}}async registerEventListeners(modal){await modal.getBody();const $root=modal.getRoot(),root=$root[0],form=root.querySelector(_selectors.default.IFRAME.elements.form);form.querySelector(_selectors.default.IFRAME.elements.url).addEventListener("input",(()=>this.handleInputChange(root))),[_selectors.default.IFRAME.elements.showTitle,_selectors.default.IFRAME.elements.linkTitle,_selectors.default.IFRAME.elements.showUserAvatar,_selectors.default.IFRAME.elements.startAtEnabled].forEach((selector=>{form.querySelector(selector).addEventListener("change",(()=>this.handleInputChange(root,!0)))})),form.querySelector(_selectors.default.IFRAME.elements.textLinkOnly).addEventListener("change",(()=>this.handleInputChange(root,!1))),form.querySelector(_selectors.default.IFRAME.elements.startAt).addEventListener("input",(()=>this.handleInputChange(root,!0))),form.querySelector(_selectors.default.IFRAME.elements.width).addEventListener("input",(()=>this.handleWidthChange(root))),form.querySelector(_selectors.default.IFRAME.elements.height).addEventListener("input",(()=>this.handleHeightChange(root))),$root.on(ModalEvents.save,(()=>this.handleDialogueSubmission(modal))),$root.on(ModalEvents.hidden,(()=>{this.currentModal.destroy()}));const removeBtn=root.querySelector(_selectors.default.IFRAME.actions.remove);removeBtn&&removeBtn.addEventListener("click",(()=>this.handleRemove(modal)));form.querySelector(_selectors.default.IFRAME.elements.url).value&&this.updatePreview(root);const iframeLibraryTabBtn=form.querySelector(_selectors.default.IFRAME.elements.tabIframeLibraryBtn);if(iframeLibraryTabBtn){iframeLibraryTabBtn.addEventListener("click",(e=>{e.preventDefault(),e.stopPropagation(),this.switchToIframeLibraryTab(root),setTimeout((()=>this.handleIframeLibraryTabClick(root)),100)})),iframeLibraryTabBtn.addEventListener("shown.bs.tab",(()=>this.handleIframeLibraryTabClick(root)));const $iframeLibraryTabBtn=window.jQuery?window.jQuery(iframeLibraryTabBtn):null;$iframeLibraryTabBtn&&$iframeLibraryTabBtn.on("shown.bs.tab",(()=>this.handleIframeLibraryTabClick(root)))}const urlTabBtn=form.querySelector(_selectors.default.IFRAME.elements.tabUrlBtn);urlTabBtn&&urlTabBtn.addEventListener("click",(e=>{e.preventDefault(),e.stopPropagation(),this.switchToUrlTab(root)}));const uploadMediaBtn=form.querySelector(_selectors.default.IFRAME.elements.tabUploadMediaBtn);uploadMediaBtn&&uploadMediaBtn.addEventListener("click",(e=>{e.preventDefault(),e.stopPropagation(),this.switchToIframeLibraryTab(root);let uploadUrl="";const ltiConfig=(0,_options.getLti)(this.editor);if(ltiConfig&<iConfig.contentItemUrl)try{const urlObj=new URL(ltiConfig.contentItemUrl);urlObj.searchParams.set("action","upload"),uploadUrl=urlObj.toString()}catch(err){}if(!uploadUrl){let baseUrl="";try{const editorData=(0,_options.getData)(this.editor);editorData&&editorData.mediacmsBaseUrl&&(baseUrl=editorData.mediacmsBaseUrl)}catch(err){}if(!baseUrl)try{const urlObj=new URL(this.iframeLibraryUrl);baseUrl="".concat(urlObj.protocol,"//").concat(urlObj.host)}catch(err){}baseUrl=baseUrl.replace(/\/$/,""),uploadUrl=baseUrl?"".concat(baseUrl,"/upload"):""}if(uploadUrl){const pane=form.querySelector(_selectors.default.IFRAME.elements.paneIframeLibrary);if(pane){const iframeEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryFrame),placeholderEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryPlaceholder),loadingEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryLoading);if(placeholderEl&&placeholderEl.classList.add("d-none"),loadingEl&&loadingEl.classList.remove("d-none"),iframeEl){iframeEl.classList.add("d-none");const loadHandler=()=>{this.handleIframeLibraryLoad(root),iframeEl.removeEventListener("load",loadHandler)};iframeEl.addEventListener("load",loadHandler),iframeEl.src=uploadUrl}}}})),this.registerIframeLibraryEventListeners(root),this.isUpdating?setTimeout((()=>this.updatePreview(root)),100):setTimeout((()=>this.handleIframeLibraryTabClick(root)),100)}switchToUrlTab(root){const form=root.querySelector(_selectors.default.IFRAME.elements.form),urlTabBtn=form.querySelector(_selectors.default.IFRAME.elements.tabUrlBtn),urlTabItem=form.querySelector(".tiny_iframecms_tab_url_item"),iframeLibraryTabBtn=form.querySelector(_selectors.default.IFRAME.elements.tabIframeLibraryBtn),urlPane=form.querySelector(_selectors.default.IFRAME.elements.paneUrl),iframeLibraryPane=form.querySelector(_selectors.default.IFRAME.elements.paneIframeLibrary);urlTabItem&&(urlTabItem.style.display=""),urlTabBtn&&(urlTabBtn.classList.add("active"),urlTabBtn.setAttribute("aria-selected","true")),iframeLibraryTabBtn&&(iframeLibraryTabBtn.classList.remove("active"),iframeLibraryTabBtn.setAttribute("aria-selected","false")),urlPane&&urlPane.classList.add("show","active"),iframeLibraryPane&&iframeLibraryPane.classList.remove("show","active")}switchToIframeLibraryTab(root){const form=root.querySelector(_selectors.default.IFRAME.elements.form),urlTabBtn=form.querySelector(_selectors.default.IFRAME.elements.tabUrlBtn),urlTabItem=form.querySelector(".tiny_iframecms_tab_url_item"),iframeLibraryTabBtn=form.querySelector(_selectors.default.IFRAME.elements.tabIframeLibraryBtn),urlPane=form.querySelector(_selectors.default.IFRAME.elements.paneUrl),iframeLibraryPane=form.querySelector(_selectors.default.IFRAME.elements.paneIframeLibrary);urlTabItem&&(urlTabItem.style.display="none"),urlTabBtn&&(urlTabBtn.classList.remove("active"),urlTabBtn.setAttribute("aria-selected","false")),iframeLibraryTabBtn&&(iframeLibraryTabBtn.classList.add("active"),iframeLibraryTabBtn.setAttribute("aria-selected","true")),urlPane&&urlPane.classList.remove("show","active"),iframeLibraryPane&&iframeLibraryPane.classList.add("show","active")}registerIframeLibraryEventListeners(root){window.addEventListener("message",(event=>{this.handleIframeLibraryMessage(root,event)}))}handleIframeLibraryTabClick(root){this.loadIframeLibrary(root)}loadIframeLibrary(root){const ltiConfig=(0,_options.getLti)(this.editor);null!=ltiConfig&<iConfig.contentItemUrl?this.loadIframeLibraryViaLti(root):this.loadIframeLibraryStatic(root)}loadIframeLibraryViaLti(root){const pane=root.querySelector(_selectors.default.IFRAME.elements.form).querySelector(_selectors.default.IFRAME.elements.paneIframeLibrary);if(!pane)return;const placeholderEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryPlaceholder),loadingEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryLoading),iframeEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryFrame);if(!iframeEl)return;placeholderEl&&placeholderEl.classList.add("d-none"),loadingEl&&loadingEl.classList.remove("d-none"),iframeEl.classList.add("d-none");iframeEl.addEventListener("load",(()=>{this.handleIframeLibraryLoad(root)}));const ltiConfig=(0,_options.getLti)(this.editor);iframeEl.src=ltiConfig.contentItemUrl}loadIframeLibraryStatic(root){const pane=root.querySelector(_selectors.default.IFRAME.elements.form).querySelector(_selectors.default.IFRAME.elements.paneIframeLibrary);if(!pane)return;const placeholderEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryPlaceholder),loadingEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryLoading),iframeEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryFrame);if(!iframeEl)return;placeholderEl&&placeholderEl.classList.add("d-none"),loadingEl&&loadingEl.classList.remove("d-none"),iframeEl.classList.add("d-none");const loadHandler=()=>{iframeEl.src===this.iframeLibraryUrl&&(this.handleIframeLibraryLoad(root),iframeEl.removeEventListener("load",loadHandler))};iframeEl.addEventListener("load",loadHandler),iframeEl.src=this.iframeLibraryUrl}handleIframeLibraryLoad(root){const pane=root.querySelector(_selectors.default.IFRAME.elements.form).querySelector(_selectors.default.IFRAME.elements.paneIframeLibrary);if(!pane)return;const placeholderEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryPlaceholder),loadingEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryLoading),iframeEl=pane.querySelector(_selectors.default.IFRAME.elements.iframeLibraryFrame);placeholderEl&&placeholderEl.classList.add("d-none"),loadingEl&&loadingEl.classList.add("d-none"),iframeEl&&iframeEl.classList.remove("d-none")}handleIframeLibraryMessage(root,event){const data=event.data;if(data)if("videoSelected"===data.type&&data.embedUrl)this.selectIframeLibraryVideo(root,data.embedUrl,data.videoId);else if("ltiDeepLinkingResponse"!==data.type&&"LtiDeepLinkingResponse"!==data.messageType)if("selectMedia"!==data.action&&"mediaSelected"!==data.action);else{const embedUrl=data.embedUrl||data.url||"";embedUrl&&this.selectIframeLibraryVideo(root,embedUrl)}else{const contentItems=data.content_items||data.contentItems||[];if(contentItems.length>0){const item=contentItems[0],embedUrl=item.url||item.embed_url||item.embedUrl||"",videoId=item.id||item.mediaId||"";embedUrl&&this.selectIframeLibraryVideo(root,embedUrl,videoId)}}}selectIframeLibraryVideo(root,embedUrl){root.querySelector(_selectors.default.IFRAME.elements.form).querySelector(_selectors.default.IFRAME.elements.url).value=embedUrl;const configureTabItem=root.querySelector(".tiny_iframecms_tab_url_item");configureTabItem&&(configureTabItem.style.display=""),this.switchToUrlTab(root),this.updatePreview(root)}},_exports.default})); //# sourceMappingURL=iframeembed.min.js.map \ No newline at end of file diff --git a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/iframeembed.min.js.map b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/iframeembed.min.js.map index 66efd3ea..c1ca50a6 100755 --- a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/iframeembed.min.js.map +++ b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/iframeembed.min.js.map @@ -1 +1 @@ -{"version":3,"file":"iframeembed.min.js","sources":["../src/iframeembed.js"],"sourcesContent":["import Templates from 'core/templates';\nimport { getString } from 'core/str';\nimport * as ModalEvents from 'core/modal_events';\nimport { component } from './common';\nimport IframeModal from './iframemodal';\nimport Selectors from './selectors';\nimport { getLti, getData } from './options';\n\nconst PREFS_KEY = 'tiny_mediacms_embed_prefs';\nconst PREFS_FIELDS = ['showTitle', 'linkTitle', 'showUserAvatar', 'width', 'height'];\n\nexport default class IframeEmbed {\n editor = null;\n currentModal = null;\n isUpdating = false;\n selectedIframe = null;\n debounceTimer = null;\n iframeLibraryUrl =\n 'https://temp.web357.com/mediacms/deic-mediacms-embed-videos.html';\n\n constructor(editor) {\n this.editor = editor;\n }\n\n parseInput(input) {\n if (!input || !input.trim()) {\n return null;\n }\n\n input = input.trim();\n\n const iframeMatch = input.match(\n /]*src=[\"']([^\"']+)[\"'][^>]*>/i,\n );\n if (iframeMatch) {\n return this.parseEmbedUrl(iframeMatch[1]);\n }\n\n if (input.startsWith('http://') || input.startsWith('https://')) {\n return this.parseVideoUrl(input);\n }\n\n return null;\n }\n\n parseVideoUrl(url) {\n try {\n const urlObj = new URL(url);\n const baseUrl = `${urlObj.protocol}//${urlObj.host}`;\n\n if (urlObj.pathname === '/view' && urlObj.searchParams.has('m')) {\n return {\n baseUrl: baseUrl,\n videoId: urlObj.searchParams.get('m'),\n isEmbed: false,\n };\n }\n\n if (urlObj.pathname === '/embed' && urlObj.searchParams.has('m')) {\n const tParam = urlObj.searchParams.get('t');\n const widthParam = urlObj.searchParams.get('width');\n const heightParam = urlObj.searchParams.get('height');\n return {\n baseUrl: baseUrl,\n videoId: urlObj.searchParams.get('m'),\n isEmbed: true,\n showTitle: urlObj.searchParams.get('showTitle') === '1',\n linkTitle: urlObj.searchParams.get('linkTitle') === '1',\n showUserAvatar:\n urlObj.searchParams.get('showUserAvatar') === '1',\n width: widthParam ? parseInt(widthParam) : null,\n height: heightParam ? parseInt(heightParam) : null,\n startAt: tParam\n ? this.secondsToTimeString(parseInt(tParam))\n : null,\n };\n }\n\n if (urlObj.pathname.includes('/filter/mediacms/launch.php') && urlObj.searchParams.has('token')) {\n const tParam = urlObj.searchParams.get('t');\n const widthParam = urlObj.searchParams.get('width');\n const heightParam = urlObj.searchParams.get('height');\n\n return {\n baseUrl: baseUrl,\n videoId: urlObj.searchParams.get('token'),\n rawUrl: url,\n isLtiLaunch: true,\n showTitle: urlObj.searchParams.get('showTitle') === '1',\n linkTitle: urlObj.searchParams.get('linkTitle') === '1',\n showUserAvatar: urlObj.searchParams.get('showUserAvatar') === '1',\n width: widthParam ? parseInt(widthParam) : null,\n height: heightParam ? parseInt(heightParam) : null,\n startAt: tParam ? this.secondsToTimeString(parseInt(tParam)) : null,\n };\n }\n\n return {\n baseUrl: baseUrl,\n rawUrl: url,\n isGeneric: true,\n };\n } catch (e) {\n return null;\n }\n }\n\n parseEmbedUrl(url) {\n return this.parseVideoUrl(url);\n }\n\n secondsToTimeString(seconds) {\n const mins = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n }\n\n timeStringToSeconds(timeStr) {\n if (!timeStr || !timeStr.trim()) {\n return null;\n }\n timeStr = timeStr.trim();\n\n if (timeStr.includes(':')) {\n const parts = timeStr.split(':');\n const mins = parseInt(parts[0]) || 0;\n const secs = parseInt(parts[1]) || 0;\n return mins * 60 + secs;\n }\n\n const secs = parseInt(timeStr);\n return isNaN(secs) ? null : secs;\n }\n\n parseWidthHeight(value) {\n if (!value) {\n return null;\n }\n const parsed = parseInt(value.trim());\n return isNaN(parsed) ? null : parsed;\n }\n\n computeAspectRatioCSS(values) {\n const w = values.width || 560;\n const h = values.height || 315;\n return `${w} / ${h}`;\n }\n\n buildTextLinkUrl(parsed, options) {\n let viewUrl;\n if (parsed.isGeneric || parsed.isLtiLaunch) {\n viewUrl = parsed.rawUrl;\n } else {\n viewUrl = `${parsed.baseUrl}/view?m=${parsed.videoId}`;\n }\n\n if (options.startAtEnabled && options.startAt) {\n const seconds = this.timeStringToSeconds(options.startAt);\n if (seconds !== null && seconds > 0) {\n const url = new URL(viewUrl);\n url.searchParams.set('t', seconds.toString());\n viewUrl = url.toString();\n }\n }\n\n return viewUrl;\n }\n\n buildEmbedUrl(parsed, options) {\n if (parsed.isGeneric) {\n return parsed.rawUrl;\n }\n\n let url;\n if (parsed.isLtiLaunch) {\n url = new URL(parsed.rawUrl);\n const token = url.searchParams.get('token');\n const courseid = url.searchParams.get('courseid');\n url.search = '';\n url.searchParams.set('token', token);\n if (courseid) {\n url.searchParams.set('courseid', courseid);\n }\n } else {\n url = new URL(`${parsed.baseUrl}/embed`);\n url.searchParams.set('m', parsed.videoId);\n }\n\n url.searchParams.set('showTitle', options.showTitle ? '1' : '0');\n url.searchParams.set(\n 'showUserAvatar',\n options.showUserAvatar ? '1' : '0',\n );\n url.searchParams.set('linkTitle', options.linkTitle ? '1' : '0');\n\n if (options.startAtEnabled && options.startAt) {\n const seconds = this.timeStringToSeconds(options.startAt);\n if (seconds !== null && seconds > 0) {\n url.searchParams.set('t', seconds.toString());\n }\n }\n\n if (options.width) {\n url.searchParams.set('width', options.width);\n }\n if (options.height) {\n url.searchParams.set('height', options.height);\n }\n\n return url.toString();\n }\n\n savePrefs(values) {\n try {\n const prefs = {};\n PREFS_FIELDS.forEach(k => { if (values[k] !== undefined) { prefs[k] = values[k]; } });\n localStorage.setItem(PREFS_KEY, JSON.stringify(prefs));\n } catch (_) { /* localStorage unavailable */ }\n }\n\n loadPrefs() {\n try {\n return JSON.parse(localStorage.getItem(PREFS_KEY) || 'null') || {};\n } catch (_) { return {}; }\n }\n\n async getTemplateContext(data = {}) {\n const editorData = getData(this.editor);\n const autoConvertOptions = editorData?.autoConvertOptions || {};\n const savedPrefs = this.loadPrefs();\n\n const getDefault = (key, fallback = true) => {\n if (this.isUpdating && data[key] !== undefined) {\n return data[key];\n }\n if (savedPrefs[key] !== undefined) { return savedPrefs[key]; }\n return autoConvertOptions[key] !== undefined\n ? autoConvertOptions[key]\n : fallback;\n };\n\n const width = (this.isUpdating && data.width) ? data.width\n : (savedPrefs.width ?? 560);\n const height = (this.isUpdating && data.height) ? data.height\n : (savedPrefs.height ?? 315);\n\n return {\n elementid: this.editor.getElement().id,\n isupdating: this.isUpdating,\n url: data.url || '',\n showTitle: getDefault('showTitle'),\n linkTitle: getDefault('linkTitle'),\n showUserAvatar: getDefault('showUserAvatar'),\n textLinkOnly: data.textLinkOnly || false,\n startAtEnabled: data.startAtEnabled || false,\n startAt: data.startAt || '0:00',\n width,\n height,\n };\n }\n\n async displayDialogue() {\n this.selectedIframe = this.getSelectedIframe();\n const data = this.getCurrentIframeData();\n this.isUpdating = data !== null;\n\n this.currentModal = await IframeModal.create({\n title: getString('iframemodaltitle', component),\n templateContext: await this.getTemplateContext(data || {}),\n });\n\n await this.registerEventListeners(this.currentModal);\n }\n\n getSelectedIframe() {\n const node = this.editor.selection.getNode();\n\n if (node.nodeName.toLowerCase() === 'a' && node.getAttribute('data-mediacms-textlink') === 'true') {\n return node;\n }\n\n if (node.nodeName.toLowerCase() === 'iframe') {\n return node;\n }\n\n const iframe = node.querySelector('iframe');\n if (iframe) {\n return iframe;\n }\n\n const wrapper =\n node.closest('.tiny-mediacms-iframe-wrapper') ||\n node.closest('.tiny-iframe-responsive');\n if (wrapper) {\n return wrapper.querySelector('iframe');\n }\n\n const textLink = node.closest('a[data-mediacms-textlink=\"true\"]');\n if (textLink) {\n return textLink;\n }\n\n return null;\n }\n\n getCurrentIframeData() {\n if (!this.selectedIframe) {\n return null;\n }\n\n if (this.selectedIframe.nodeName.toLowerCase() === 'a' &&\n this.selectedIframe.getAttribute('data-mediacms-textlink') === 'true') {\n const href = this.selectedIframe.getAttribute('href');\n const parsed = this.parseInput(href);\n\n return {\n url: href,\n width: parsed?.width || 560,\n height: parsed?.height || 315,\n showTitle: parsed?.showTitle ?? true,\n linkTitle: parsed?.linkTitle ?? true,\n showUserAvatar: parsed?.showUserAvatar ?? true,\n responsive: true,\n textLinkOnly: true,\n startAtEnabled: parsed?.startAt !== null,\n startAt: parsed?.startAt || '0:00',\n };\n }\n\n const src = this.selectedIframe.getAttribute('src');\n const parsed = this.parseInput(src);\n\n // Parse responsive dimensions from inline style\n const style = this.selectedIframe.getAttribute('style') || '';\n const maxWidthMatch = style.match(/max-width:\\s*(\\d+(?:\\.\\d+)?)px/);\n const aspectRatioMatch = style.match(/aspect-ratio:\\s*(\\d+(?:\\.\\d+)?)\\s*\\/\\s*(\\d+(?:\\.\\d+)?)/);\n\n // Fall back to wrapper's max-width for content saved with the new template\n // where max-width lives on the wrapper div rather than the iframe style.\n let maxWidth = maxWidthMatch ? parseInt(maxWidthMatch[1]) : null;\n if (!maxWidth) {\n const wrapper = this.selectedIframe.closest('.tiny-mediacms-iframe-wrapper');\n const wrapperStyle = wrapper ? (wrapper.getAttribute('style') || '') : '';\n const wrapperMatch = wrapperStyle.match(/max-width:\\s*(\\d+(?:\\.\\d+)?)px/);\n maxWidth = wrapperMatch ? parseInt(wrapperMatch[1]) : 560;\n }\n let height = 315;\n\n if (aspectRatioMatch) {\n const rw = parseFloat(aspectRatioMatch[1]);\n const rh = parseFloat(aspectRatioMatch[2]);\n if (rw > 0) {\n height = Math.round(maxWidth * rh / rw);\n }\n }\n\n return {\n url: src,\n width: maxWidth,\n height,\n showTitle: parsed?.showTitle ?? true,\n linkTitle: parsed?.linkTitle ?? true,\n showUserAvatar: parsed?.showUserAvatar ?? true,\n startAtEnabled: !!(parsed?.startAt),\n startAt: parsed?.startAt || '0:00',\n };\n }\n\n getFormValues(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n\n return {\n url: form.querySelector(Selectors.IFRAME.elements.url).value.trim(),\n showTitle: form.querySelector(Selectors.IFRAME.elements.showTitle)\n .checked,\n linkTitle: form.querySelector(Selectors.IFRAME.elements.linkTitle)\n .checked,\n showUserAvatar: form.querySelector(\n Selectors.IFRAME.elements.showUserAvatar,\n ).checked,\n textLinkOnly: form.querySelector(Selectors.IFRAME.elements.textLinkOnly)\n .checked,\n startAtEnabled: form.querySelector(\n Selectors.IFRAME.elements.startAtEnabled,\n ).checked,\n startAt: form\n .querySelector(Selectors.IFRAME.elements.startAt)\n .value.trim(),\n width: this.parseWidthHeight(\n form.querySelector(Selectors.IFRAME.elements.width).value,\n ),\n height: this.parseWidthHeight(\n form.querySelector(Selectors.IFRAME.elements.height).value,\n ),\n };\n }\n\n async generateIframeHtml(values) {\n const parsed = this.parseInput(values.url);\n if (!parsed) {\n return '';\n }\n\n if (values.textLinkOnly) {\n const viewUrl = this.buildTextLinkUrl(parsed, values);\n\n const escapeHtml = (str) => {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n };\n\n const linkText = escapeHtml(viewUrl);\n const hrefUrl = viewUrl.replace(/\"/g, '"');\n\n return `

${linkText}

`;\n }\n\n const embedUrl = this.buildEmbedUrl(parsed, values);\n\n const context = {\n src: embedUrl,\n maxWidth: values.width || 560,\n height: values.height || 315,\n aspectRatioCSS: this.computeAspectRatioCSS(values),\n };\n\n const { html } = await Templates.renderForPromise(\n 'tiny_mediacms/iframe_embed_output',\n context,\n );\n return html;\n }\n\n async updatePreview(root, updateUrlField = false) {\n const values = this.getFormValues(root);\n const previewContainer = root.querySelector(\n Selectors.IFRAME.elements.preview,\n );\n const urlWarning = root.querySelector(\n Selectors.IFRAME.elements.urlWarning,\n );\n\n if (!values.url) {\n previewContainer.innerHTML =\n 'Enter a video URL to see preview';\n urlWarning.classList.add('d-none');\n return;\n }\n\n const parsed = this.parseInput(values.url);\n if (!parsed) {\n previewContainer.innerHTML =\n 'Invalid URL format';\n urlWarning.classList.remove('d-none');\n return;\n }\n\n urlWarning.classList.add('d-none');\n const embedUrl = this.buildEmbedUrl(parsed, values);\n\n if (updateUrlField && !parsed.isGeneric) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n const urlInput = form.querySelector(Selectors.IFRAME.elements.url);\n urlInput.value = embedUrl;\n }\n\n if (values.textLinkOnly) {\n const viewUrl = this.buildTextLinkUrl(parsed, values);\n\n const escapeHtml = (str) => {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n };\n\n const linkText = escapeHtml(viewUrl);\n const hrefUrl = viewUrl.replace(/\"/g, '"');\n\n previewContainer.innerHTML = `\n
\n Text link preview:
\n ${linkText}\n
\n `;\n } else {\n const previewWidth = Math.min(values.width || 560, 400);\n const previewHeight = Math.round(previewWidth * (values.height || 315) / (values.width || 560));\n\n previewContainer.innerHTML = `\n \n \n `;\n }\n }\n\n handleInputChange(root, updateUrlField = false) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n this.updatePreview(root, updateUrlField);\n }, 500);\n }\n\n handleWidthChange(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n const widthInput = form.querySelector(Selectors.IFRAME.elements.width);\n const heightInput = form.querySelector(Selectors.IFRAME.elements.height);\n const newWidth = parseInt(widthInput.value);\n if (!isNaN(newWidth) && newWidth > 0) {\n heightInput.value = Math.round(newWidth * 9 / 16);\n }\n this.handleInputChange(root);\n }\n\n handleHeightChange(root) {\n this.handleInputChange(root);\n }\n\n async handleDialogueSubmission(modal) {\n const root = modal.getRoot()[0];\n const values = this.getFormValues(root);\n\n if (!values.url) {\n return;\n }\n\n this.savePrefs(values);\n const html = await this.generateIframeHtml(values);\n if (html) {\n if (this.isUpdating && this.selectedIframe) {\n const wrapper =\n this.selectedIframe.closest(\n '.tiny-mediacms-iframe-wrapper',\n ) || this.selectedIframe.closest('.tiny-iframe-responsive');\n\n const paragraphWrapper = wrapper ? wrapper.closest('p') : this.selectedIframe.closest('p');\n\n if (paragraphWrapper) {\n paragraphWrapper.outerHTML = html;\n } else if (wrapper) {\n wrapper.outerHTML = html;\n } else {\n this.selectedIframe.outerHTML = html;\n }\n this.isUpdating = false;\n\n setTimeout(() => {\n const body = this.editor.getBody();\n const emptyPs = body.querySelectorAll('p:empty, p:blank');\n emptyPs.forEach(p => {\n if (p.innerHTML.trim() === '' || p.innerHTML === '
') {\n p.remove();\n }\n });\n }, 10);\n\n this.editor.fire('Change');\n } else {\n const node = this.editor.selection.getNode();\n if (node.nodeName === 'P' && node.innerHTML.trim() === '') {\n node.outerHTML = html;\n } else {\n this.editor.insertContent(html);\n }\n setTimeout(() => {\n const body = this.editor.getBody();\n body.querySelectorAll('p').forEach(p => {\n if (p.innerHTML.trim() === '' || p.innerHTML === '
') {\n p.remove();\n }\n });\n }, 50);\n }\n }\n }\n\n async handleRemove(modal) {\n const confirmMessage = await getString(\n 'removeiframeconfirm',\n component,\n );\n\n // eslint-disable-next-line no-alert\n if (!window.confirm(confirmMessage)) {\n return;\n }\n\n if (this.selectedIframe) {\n const wrapper =\n this.selectedIframe.closest('.tiny-mediacms-iframe-wrapper') ||\n this.selectedIframe.closest('.tiny-iframe-responsive');\n if (wrapper) {\n wrapper.remove();\n } else {\n this.selectedIframe.remove();\n }\n }\n\n this.isUpdating = false;\n modal.hide();\n }\n\n async registerEventListeners(modal) {\n await modal.getBody();\n const $root = modal.getRoot();\n const root = $root[0];\n\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n\n form.querySelector(Selectors.IFRAME.elements.url).addEventListener(\n 'input',\n () => this.handleInputChange(root),\n );\n\n [\n Selectors.IFRAME.elements.showTitle,\n Selectors.IFRAME.elements.linkTitle,\n Selectors.IFRAME.elements.showUserAvatar,\n Selectors.IFRAME.elements.startAtEnabled,\n ].forEach((selector) => {\n form.querySelector(selector).addEventListener('change', () =>\n this.handleInputChange(root, true),\n );\n });\n\n form.querySelector(Selectors.IFRAME.elements.textLinkOnly).addEventListener('change', () =>\n this.handleInputChange(root, false),\n );\n\n form.querySelector(Selectors.IFRAME.elements.startAt).addEventListener(\n 'input',\n () => this.handleInputChange(root, true),\n );\n\n form.querySelector(Selectors.IFRAME.elements.width).addEventListener(\n 'input',\n () => this.handleWidthChange(root),\n );\n form.querySelector(Selectors.IFRAME.elements.height).addEventListener(\n 'input',\n () => this.handleHeightChange(root),\n );\n\n $root.on(ModalEvents.save, () => this.handleDialogueSubmission(modal));\n $root.on(ModalEvents.hidden, () => {\n this.currentModal.destroy();\n });\n\n const removeBtn = root.querySelector(Selectors.IFRAME.actions.remove);\n if (removeBtn) {\n removeBtn.addEventListener('click', () => this.handleRemove(modal));\n }\n\n const urlInput = form.querySelector(Selectors.IFRAME.elements.url);\n if (urlInput.value) {\n this.updatePreview(root);\n }\n\n const iframeLibraryTabBtn = form.querySelector(\n Selectors.IFRAME.elements.tabIframeLibraryBtn,\n );\n if (iframeLibraryTabBtn) {\n iframeLibraryTabBtn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n\n this.switchToIframeLibraryTab(root);\n\n setTimeout(() => this.handleIframeLibraryTabClick(root), 100);\n });\n iframeLibraryTabBtn.addEventListener('shown.bs.tab', () =>\n this.handleIframeLibraryTabClick(root),\n );\n const $iframeLibraryTabBtn = window.jQuery\n ? window.jQuery(iframeLibraryTabBtn)\n : null;\n if ($iframeLibraryTabBtn) {\n $iframeLibraryTabBtn.on('shown.bs.tab', () =>\n this.handleIframeLibraryTabClick(root),\n );\n }\n }\n\n const urlTabBtn = form.querySelector(\n Selectors.IFRAME.elements.tabUrlBtn,\n );\n if (urlTabBtn) {\n urlTabBtn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n\n this.switchToUrlTab(root);\n });\n }\n\n const uploadMediaBtn = form.querySelector(\n Selectors.IFRAME.elements.tabUploadMediaBtn,\n );\n if (uploadMediaBtn) {\n uploadMediaBtn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n\n this.switchToIframeLibraryTab(root);\n\n let uploadUrl = '';\n const ltiConfig = getLti(this.editor);\n\n if (ltiConfig && ltiConfig.contentItemUrl) {\n try {\n const urlObj = new URL(ltiConfig.contentItemUrl);\n urlObj.searchParams.set('action', 'upload');\n uploadUrl = urlObj.toString();\n } catch (err) {\n // eslint-disable-next-line no-unused-vars\n }\n }\n\n if (!uploadUrl) {\n let baseUrl = '';\n try {\n const editorData = getData(this.editor);\n if (editorData && editorData.mediacmsBaseUrl) {\n baseUrl = editorData.mediacmsBaseUrl;\n }\n } catch (err) {\n // eslint-disable-next-line no-unused-vars\n }\n\n if (!baseUrl) {\n try {\n const urlObj = new URL(this.iframeLibraryUrl);\n baseUrl = `${urlObj.protocol}//${urlObj.host}`;\n } catch (err) {\n // eslint-disable-next-line no-unused-vars\n }\n }\n\n baseUrl = baseUrl.replace(/\\/$/, '');\n uploadUrl = baseUrl ? `${baseUrl}/upload` : '';\n }\n\n if (uploadUrl) {\n const pane = form.querySelector(Selectors.IFRAME.elements.paneIframeLibrary);\n if (pane) {\n const iframeEl = pane.querySelector(Selectors.IFRAME.elements.iframeLibraryFrame);\n const placeholderEl = pane.querySelector(Selectors.IFRAME.elements.iframeLibraryPlaceholder);\n const loadingEl = pane.querySelector(Selectors.IFRAME.elements.iframeLibraryLoading);\n\n if (placeholderEl) {\n placeholderEl.classList.add('d-none');\n }\n if (loadingEl) {\n loadingEl.classList.remove('d-none');\n }\n if (iframeEl) {\n iframeEl.classList.add('d-none');\n\n const loadHandler = () => {\n this.handleIframeLibraryLoad(root);\n iframeEl.removeEventListener('load', loadHandler);\n };\n iframeEl.addEventListener('load', loadHandler);\n iframeEl.src = uploadUrl;\n }\n }\n }\n });\n }\n\n this.registerIframeLibraryEventListeners(root);\n\n if (this.isUpdating) {\n setTimeout(() => this.updatePreview(root), 100);\n } else {\n setTimeout(() => this.handleIframeLibraryTabClick(root), 100);\n }\n }\n\n switchToUrlTab(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n\n const urlTabBtn = form.querySelector(\n Selectors.IFRAME.elements.tabUrlBtn,\n );\n const urlTabItem = form.querySelector('.tiny_iframecms_tab_url_item');\n const iframeLibraryTabBtn = form.querySelector(\n Selectors.IFRAME.elements.tabIframeLibraryBtn,\n );\n\n const urlPane = form.querySelector(Selectors.IFRAME.elements.paneUrl);\n const iframeLibraryPane = form.querySelector(\n Selectors.IFRAME.elements.paneIframeLibrary,\n );\n\n if (urlTabItem) {\n urlTabItem.style.display = '';\n }\n\n if (urlTabBtn) {\n urlTabBtn.classList.add('active');\n urlTabBtn.setAttribute('aria-selected', 'true');\n }\n if (iframeLibraryTabBtn) {\n iframeLibraryTabBtn.classList.remove('active');\n iframeLibraryTabBtn.setAttribute('aria-selected', 'false');\n }\n\n if (urlPane) {\n urlPane.classList.add('show', 'active');\n }\n if (iframeLibraryPane) {\n iframeLibraryPane.classList.remove('show', 'active');\n }\n }\n\n switchToIframeLibraryTab(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n\n const urlTabBtn = form.querySelector(\n Selectors.IFRAME.elements.tabUrlBtn,\n );\n const urlTabItem = form.querySelector('.tiny_iframecms_tab_url_item');\n const iframeLibraryTabBtn = form.querySelector(\n Selectors.IFRAME.elements.tabIframeLibraryBtn,\n );\n\n const urlPane = form.querySelector(Selectors.IFRAME.elements.paneUrl);\n const iframeLibraryPane = form.querySelector(\n Selectors.IFRAME.elements.paneIframeLibrary,\n );\n\n if (urlTabItem) {\n urlTabItem.style.display = 'none';\n }\n\n if (urlTabBtn) {\n urlTabBtn.classList.remove('active');\n urlTabBtn.setAttribute('aria-selected', 'false');\n }\n if (iframeLibraryTabBtn) {\n iframeLibraryTabBtn.classList.add('active');\n iframeLibraryTabBtn.setAttribute('aria-selected', 'true');\n }\n\n if (urlPane) {\n urlPane.classList.remove('show', 'active');\n }\n if (iframeLibraryPane) {\n iframeLibraryPane.classList.add('show', 'active');\n }\n }\n\n registerIframeLibraryEventListeners(root) {\n window.addEventListener('message', (event) => {\n this.handleIframeLibraryMessage(root, event);\n });\n }\n\n handleIframeLibraryTabClick(root) {\n this.loadIframeLibrary(root);\n }\n\n loadIframeLibrary(root) {\n const ltiConfig = getLti(this.editor);\n if (ltiConfig?.contentItemUrl) {\n this.loadIframeLibraryViaLti(root);\n } else {\n this.loadIframeLibraryStatic(root);\n }\n }\n\n loadIframeLibraryViaLti(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n const pane = form.querySelector(\n Selectors.IFRAME.elements.paneIframeLibrary,\n );\n\n if (!pane) {\n return;\n }\n\n const placeholderEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryPlaceholder,\n );\n const loadingEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryLoading,\n );\n const iframeEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryFrame,\n );\n\n if (!iframeEl) {\n return;\n }\n\n if (placeholderEl) {\n placeholderEl.classList.add('d-none');\n }\n if (loadingEl) {\n loadingEl.classList.remove('d-none');\n }\n iframeEl.classList.add('d-none');\n\n const loadHandler = () => {\n this.handleIframeLibraryLoad(root);\n };\n iframeEl.addEventListener('load', loadHandler);\n\n const ltiConfig = getLti(this.editor);\n iframeEl.src = ltiConfig.contentItemUrl;\n }\n\n loadIframeLibraryStatic(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n const pane = form.querySelector(\n Selectors.IFRAME.elements.paneIframeLibrary,\n );\n\n if (!pane) {\n return;\n }\n\n const placeholderEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryPlaceholder,\n );\n const loadingEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryLoading,\n );\n const iframeEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryFrame,\n );\n\n if (!iframeEl) {\n return;\n }\n\n if (placeholderEl) {\n placeholderEl.classList.add('d-none');\n }\n if (loadingEl) {\n loadingEl.classList.remove('d-none');\n }\n iframeEl.classList.add('d-none');\n\n const loadHandler = () => {\n if (iframeEl.src === this.iframeLibraryUrl) {\n this.handleIframeLibraryLoad(root);\n iframeEl.removeEventListener('load', loadHandler);\n }\n };\n iframeEl.addEventListener('load', loadHandler);\n\n iframeEl.src = this.iframeLibraryUrl;\n }\n\n handleIframeLibraryLoad(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n const pane = form.querySelector(\n Selectors.IFRAME.elements.paneIframeLibrary,\n );\n\n if (!pane) {\n return;\n }\n\n const placeholderEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryPlaceholder,\n );\n const loadingEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryLoading,\n );\n const iframeEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryFrame,\n );\n\n if (placeholderEl) {\n placeholderEl.classList.add('d-none');\n }\n if (loadingEl) {\n loadingEl.classList.add('d-none');\n }\n if (iframeEl) {\n iframeEl.classList.remove('d-none');\n }\n }\n\n handleIframeLibraryMessage(root, event) {\n const data = event.data;\n\n if (!data) {\n return;\n }\n\n if (data.type === 'videoSelected' && data.embedUrl) {\n this.selectIframeLibraryVideo(root, data.embedUrl, data.videoId);\n return;\n }\n\n if (\n data.type === 'ltiDeepLinkingResponse' ||\n data.messageType === 'LtiDeepLinkingResponse'\n ) {\n const contentItems = data.content_items || data.contentItems || [];\n if (contentItems.length > 0) {\n const item = contentItems[0];\n const embedUrl =\n item.url || item.embed_url || item.embedUrl || '';\n const videoId = item.id || item.mediaId || '';\n if (embedUrl) {\n this.selectIframeLibraryVideo(root, embedUrl, videoId);\n }\n }\n return;\n }\n\n if (data.action === 'selectMedia' || data.action === 'mediaSelected') {\n const embedUrl = data.embedUrl || data.url || '';\n if (embedUrl) {\n this.selectIframeLibraryVideo(root, embedUrl);\n }\n return;\n }\n }\n\n selectIframeLibraryVideo(root, embedUrl) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n\n const urlInput = form.querySelector(Selectors.IFRAME.elements.url);\n urlInput.value = embedUrl;\n\n const configureTabItem = root.querySelector('.tiny_iframecms_tab_url_item');\n if (configureTabItem) {\n configureTabItem.style.display = '';\n }\n\n this.switchToUrlTab(root);\n this.updatePreview(root);\n }\n}\n"],"names":["PREFS_FIELDS","constructor","editor","parseInput","input","trim","iframeMatch","match","this","parseEmbedUrl","startsWith","parseVideoUrl","url","urlObj","URL","baseUrl","protocol","host","pathname","searchParams","has","videoId","get","isEmbed","tParam","widthParam","heightParam","showTitle","linkTitle","showUserAvatar","width","parseInt","height","startAt","secondsToTimeString","includes","rawUrl","isLtiLaunch","isGeneric","e","seconds","mins","Math","floor","secs","toString","padStart","timeStringToSeconds","timeStr","parts","split","isNaN","parseWidthHeight","value","parsed","computeAspectRatioCSS","values","w","h","buildTextLinkUrl","options","viewUrl","startAtEnabled","set","buildEmbedUrl","token","courseid","search","savePrefs","prefs","forEach","k","undefined","localStorage","setItem","JSON","stringify","_","loadPrefs","parse","getItem","data","editorData","autoConvertOptions","savedPrefs","getDefault","key","fallback","_this","isUpdating","elementid","getElement","id","isupdating","textLinkOnly","selectedIframe","getSelectedIframe","getCurrentIframeData","currentModal","IframeModal","create","title","component","templateContext","getTemplateContext","registerEventListeners","node","selection","getNode","nodeName","toLowerCase","getAttribute","iframe","querySelector","wrapper","closest","textLink","href","responsive","src","style","maxWidthMatch","aspectRatioMatch","maxWidth","wrapperMatch","rw","parseFloat","rh","round","getFormValues","root","form","Selectors","IFRAME","elements","checked","linkText","str","div","document","createElement","textContent","innerHTML","escapeHtml","hrefUrl","replace","context","aspectRatioCSS","html","Templates","renderForPromise","updateUrlField","previewContainer","preview","urlWarning","classList","add","remove","embedUrl","previewWidth","min","previewHeight","handleInputChange","clearTimeout","debounceTimer","setTimeout","updatePreview","handleWidthChange","widthInput","heightInput","newWidth","handleHeightChange","modal","getRoot","generateIframeHtml","paragraphWrapper","outerHTML","getBody","querySelectorAll","p","fire","insertContent","confirmMessage","window","confirm","hide","$root","addEventListener","selector","on","ModalEvents","save","handleDialogueSubmission","hidden","destroy","removeBtn","actions","handleRemove","iframeLibraryTabBtn","tabIframeLibraryBtn","preventDefault","stopPropagation","switchToIframeLibraryTab","handleIframeLibraryTabClick","$iframeLibraryTabBtn","jQuery","urlTabBtn","tabUrlBtn","switchToUrlTab","uploadMediaBtn","tabUploadMediaBtn","uploadUrl","ltiConfig","contentItemUrl","err","mediacmsBaseUrl","iframeLibraryUrl","pane","paneIframeLibrary","iframeEl","iframeLibraryFrame","placeholderEl","iframeLibraryPlaceholder","loadingEl","iframeLibraryLoading","loadHandler","handleIframeLibraryLoad","removeEventListener","registerIframeLibraryEventListeners","urlTabItem","urlPane","paneUrl","iframeLibraryPane","display","setAttribute","event","handleIframeLibraryMessage","loadIframeLibrary","loadIframeLibraryViaLti","loadIframeLibraryStatic","type","selectIframeLibraryVideo","messageType","action","contentItems","content_items","length","item","embed_url","mediaId","configureTabItem"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"iframeembed.min.js","sources":["../src/iframeembed.js"],"sourcesContent":["import Templates from 'core/templates';\nimport { getString } from 'core/str';\nimport * as ModalEvents from 'core/modal_events';\nimport { component } from './common';\nimport IframeModal from './iframemodal';\nimport Selectors from './selectors';\nimport { getLti, getData } from './options';\n\nconst PREFS_KEY = 'tiny_mediacms_embed_prefs';\nconst PREFS_FIELDS = ['showTitle', 'linkTitle', 'showUserAvatar', 'width', 'height', 'textLinkOnly'];\n\nexport default class IframeEmbed {\n editor = null;\n currentModal = null;\n isUpdating = false;\n selectedIframe = null;\n debounceTimer = null;\n iframeLibraryUrl =\n 'https://temp.web357.com/mediacms/deic-mediacms-embed-videos.html';\n\n constructor(editor) {\n this.editor = editor;\n }\n\n parseInput(input) {\n if (!input || !input.trim()) {\n return null;\n }\n\n input = input.trim();\n\n const iframeMatch = input.match(\n /]*src=[\"']([^\"']+)[\"'][^>]*>/i,\n );\n if (iframeMatch) {\n return this.parseEmbedUrl(iframeMatch[1]);\n }\n\n if (input.startsWith('http://') || input.startsWith('https://')) {\n return this.parseVideoUrl(input);\n }\n\n return null;\n }\n\n parseVideoUrl(url) {\n try {\n const urlObj = new URL(url);\n const baseUrl = `${urlObj.protocol}//${urlObj.host}`;\n\n if (urlObj.pathname === '/view' && urlObj.searchParams.has('m')) {\n return {\n baseUrl: baseUrl,\n videoId: urlObj.searchParams.get('m'),\n isEmbed: false,\n };\n }\n\n if (urlObj.pathname === '/embed' && urlObj.searchParams.has('m')) {\n const tParam = urlObj.searchParams.get('t');\n const widthParam = urlObj.searchParams.get('width');\n const heightParam = urlObj.searchParams.get('height');\n return {\n baseUrl: baseUrl,\n videoId: urlObj.searchParams.get('m'),\n isEmbed: true,\n showTitle: urlObj.searchParams.get('showTitle') === '1',\n linkTitle: urlObj.searchParams.get('linkTitle') === '1',\n showUserAvatar:\n urlObj.searchParams.get('showUserAvatar') === '1',\n width: widthParam ? parseInt(widthParam) : null,\n height: heightParam ? parseInt(heightParam) : null,\n startAt: tParam\n ? this.secondsToTimeString(parseInt(tParam))\n : null,\n };\n }\n\n if (urlObj.pathname.includes('/filter/mediacms/launch.php') && urlObj.searchParams.has('token')) {\n const tParam = urlObj.searchParams.get('t');\n const widthParam = urlObj.searchParams.get('width');\n const heightParam = urlObj.searchParams.get('height');\n\n return {\n baseUrl: baseUrl,\n videoId: urlObj.searchParams.get('token'),\n rawUrl: url,\n isLtiLaunch: true,\n showTitle: urlObj.searchParams.get('showTitle') === '1',\n linkTitle: urlObj.searchParams.get('linkTitle') === '1',\n showUserAvatar: urlObj.searchParams.get('showUserAvatar') === '1',\n width: widthParam ? parseInt(widthParam) : null,\n height: heightParam ? parseInt(heightParam) : null,\n startAt: tParam ? this.secondsToTimeString(parseInt(tParam)) : null,\n };\n }\n\n return {\n baseUrl: baseUrl,\n rawUrl: url,\n isGeneric: true,\n };\n } catch (e) {\n return null;\n }\n }\n\n parseEmbedUrl(url) {\n return this.parseVideoUrl(url);\n }\n\n secondsToTimeString(seconds) {\n const mins = Math.floor(seconds / 60);\n const secs = seconds % 60;\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n }\n\n timeStringToSeconds(timeStr) {\n if (!timeStr || !timeStr.trim()) {\n return null;\n }\n timeStr = timeStr.trim();\n\n if (timeStr.includes(':')) {\n const parts = timeStr.split(':');\n const mins = parseInt(parts[0]) || 0;\n const secs = parseInt(parts[1]) || 0;\n return mins * 60 + secs;\n }\n\n const secs = parseInt(timeStr);\n return isNaN(secs) ? null : secs;\n }\n\n parseWidthHeight(value) {\n if (!value) {\n return null;\n }\n const parsed = parseInt(value.trim());\n return isNaN(parsed) ? null : parsed;\n }\n\n computeAspectRatioCSS(values) {\n const w = values.width || 560;\n const h = values.height || 315;\n return `${w} / ${h}`;\n }\n\n buildTextLinkUrl(parsed, options) {\n let viewUrl;\n if (parsed.isGeneric || parsed.isLtiLaunch) {\n viewUrl = parsed.rawUrl;\n } else {\n viewUrl = `${parsed.baseUrl}/view?m=${parsed.videoId}`;\n }\n\n if (options.startAtEnabled && options.startAt) {\n const seconds = this.timeStringToSeconds(options.startAt);\n if (seconds !== null && seconds > 0) {\n const url = new URL(viewUrl);\n url.searchParams.set('t', seconds.toString());\n viewUrl = url.toString();\n }\n }\n\n return viewUrl;\n }\n\n buildEmbedUrl(parsed, options) {\n if (parsed.isGeneric) {\n return parsed.rawUrl;\n }\n\n let url;\n if (parsed.isLtiLaunch) {\n url = new URL(parsed.rawUrl);\n const token = url.searchParams.get('token');\n const courseid = url.searchParams.get('courseid');\n url.search = '';\n url.searchParams.set('token', token);\n if (courseid) {\n url.searchParams.set('courseid', courseid);\n }\n } else {\n url = new URL(`${parsed.baseUrl}/embed`);\n url.searchParams.set('m', parsed.videoId);\n }\n\n url.searchParams.set('showTitle', options.showTitle ? '1' : '0');\n url.searchParams.set(\n 'showUserAvatar',\n options.showUserAvatar ? '1' : '0',\n );\n url.searchParams.set('linkTitle', options.linkTitle ? '1' : '0');\n\n if (options.startAtEnabled && options.startAt) {\n const seconds = this.timeStringToSeconds(options.startAt);\n if (seconds !== null && seconds > 0) {\n url.searchParams.set('t', seconds.toString());\n }\n }\n\n if (options.width) {\n url.searchParams.set('width', options.width);\n }\n if (options.height) {\n url.searchParams.set('height', options.height);\n }\n\n return url.toString();\n }\n\n signalShare(values) {\n const parsed = this.parseInput(values.url);\n if (!parsed || parsed.isGeneric || !parsed.videoId) {\n return;\n }\n\n const editorData = getData(this.editor);\n const baseUrl = parsed.isLtiLaunch\n ? (editorData?.mediacmsBaseUrl || '')\n : parsed.baseUrl;\n\n if (!baseUrl) {\n return;\n }\n\n const ltiConfig = getLti(this.editor);\n const courseId = ltiConfig?.courseId || 0;\n\n fetch(`${baseUrl}/api/v1/media/${parsed.videoId}/share`, {\n method: 'POST',\n credentials: 'include',\n headers: {'Content-Type': 'application/json'},\n body: JSON.stringify({courseid: courseId}),\n }).catch(() => {});\n }\n\n savePrefs(values) {\n try {\n const prefs = {};\n PREFS_FIELDS.forEach(k => { if (values[k] !== undefined) { prefs[k] = values[k]; } });\n localStorage.setItem(PREFS_KEY, JSON.stringify(prefs));\n } catch (_) { /* localStorage unavailable */ }\n }\n\n loadPrefs() {\n try {\n return JSON.parse(localStorage.getItem(PREFS_KEY) || 'null') || {};\n } catch (_) { return {}; }\n }\n\n async getTemplateContext(data = {}) {\n const editorData = getData(this.editor);\n const autoConvertOptions = editorData?.autoConvertOptions || {};\n const savedPrefs = this.loadPrefs();\n\n const getDefault = (key, fallback = true) => {\n if (this.isUpdating && data[key] !== undefined) {\n return data[key];\n }\n if (savedPrefs[key] !== undefined) { return savedPrefs[key]; }\n return autoConvertOptions[key] !== undefined\n ? autoConvertOptions[key]\n : fallback;\n };\n\n const width = (this.isUpdating && data.width) ? data.width\n : (savedPrefs.width ?? 560);\n const height = (this.isUpdating && data.height) ? data.height\n : (savedPrefs.height ?? 315);\n\n return {\n elementid: this.editor.getElement().id,\n isupdating: this.isUpdating,\n url: data.url || '',\n showTitle: getDefault('showTitle'),\n linkTitle: getDefault('linkTitle'),\n showUserAvatar: getDefault('showUserAvatar'),\n textLinkOnly: getDefault('textLinkOnly', false),\n startAtEnabled: data.startAtEnabled || false,\n startAt: data.startAt || '0:00',\n width,\n height,\n };\n }\n\n async displayDialogue() {\n this.selectedIframe = this.getSelectedIframe();\n const data = this.getCurrentIframeData();\n this.isUpdating = data !== null;\n\n this.currentModal = await IframeModal.create({\n title: getString('iframemodaltitle', component),\n templateContext: await this.getTemplateContext(data || {}),\n });\n\n await this.registerEventListeners(this.currentModal);\n }\n\n getSelectedIframe() {\n const node = this.editor.selection.getNode();\n\n if (node.nodeName.toLowerCase() === 'a' && node.getAttribute('data-mediacms-textlink') === 'true') {\n return node;\n }\n\n if (node.nodeName.toLowerCase() === 'iframe') {\n return node;\n }\n\n const iframe = node.querySelector('iframe');\n if (iframe) {\n return iframe;\n }\n\n const wrapper =\n node.closest('.tiny-mediacms-iframe-wrapper') ||\n node.closest('.tiny-iframe-responsive');\n if (wrapper) {\n return wrapper.querySelector('iframe');\n }\n\n const textLink = node.closest('a[data-mediacms-textlink=\"true\"]');\n if (textLink) {\n return textLink;\n }\n\n return null;\n }\n\n getCurrentIframeData() {\n if (!this.selectedIframe) {\n return null;\n }\n\n if (this.selectedIframe.nodeName.toLowerCase() === 'a' &&\n this.selectedIframe.getAttribute('data-mediacms-textlink') === 'true') {\n const href = this.selectedIframe.getAttribute('href');\n const parsed = this.parseInput(href);\n\n return {\n url: href,\n width: parsed?.width || 560,\n height: parsed?.height || 315,\n showTitle: parsed?.showTitle ?? true,\n linkTitle: parsed?.linkTitle ?? true,\n showUserAvatar: parsed?.showUserAvatar ?? true,\n responsive: true,\n textLinkOnly: true,\n startAtEnabled: parsed?.startAt !== null,\n startAt: parsed?.startAt || '0:00',\n };\n }\n\n const src = this.selectedIframe.getAttribute('src');\n const parsed = this.parseInput(src);\n\n // Parse responsive dimensions from inline style\n const style = this.selectedIframe.getAttribute('style') || '';\n const maxWidthMatch = style.match(/max-width:\\s*(\\d+(?:\\.\\d+)?)px/);\n const aspectRatioMatch = style.match(/aspect-ratio:\\s*(\\d+(?:\\.\\d+)?)\\s*\\/\\s*(\\d+(?:\\.\\d+)?)/);\n\n // Fall back to wrapper's max-width for content saved with the new template\n // where max-width lives on the wrapper div rather than the iframe style.\n let maxWidth = maxWidthMatch ? parseInt(maxWidthMatch[1]) : null;\n if (!maxWidth) {\n const wrapper = this.selectedIframe.closest('.tiny-mediacms-iframe-wrapper');\n const wrapperStyle = wrapper ? (wrapper.getAttribute('style') || '') : '';\n const wrapperMatch = wrapperStyle.match(/max-width:\\s*(\\d+(?:\\.\\d+)?)px/);\n maxWidth = wrapperMatch ? parseInt(wrapperMatch[1]) : 560;\n }\n let height = 315;\n\n if (aspectRatioMatch) {\n const rw = parseFloat(aspectRatioMatch[1]);\n const rh = parseFloat(aspectRatioMatch[2]);\n if (rw > 0) {\n height = Math.round(maxWidth * rh / rw);\n }\n }\n\n return {\n url: src,\n width: maxWidth,\n height,\n showTitle: parsed?.showTitle ?? true,\n linkTitle: parsed?.linkTitle ?? true,\n showUserAvatar: parsed?.showUserAvatar ?? true,\n startAtEnabled: !!(parsed?.startAt),\n startAt: parsed?.startAt || '0:00',\n };\n }\n\n getFormValues(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n\n return {\n url: form.querySelector(Selectors.IFRAME.elements.url).value.trim(),\n showTitle: form.querySelector(Selectors.IFRAME.elements.showTitle)\n .checked,\n linkTitle: form.querySelector(Selectors.IFRAME.elements.linkTitle)\n .checked,\n showUserAvatar: form.querySelector(\n Selectors.IFRAME.elements.showUserAvatar,\n ).checked,\n textLinkOnly: form.querySelector(Selectors.IFRAME.elements.textLinkOnly)\n .checked,\n startAtEnabled: form.querySelector(\n Selectors.IFRAME.elements.startAtEnabled,\n ).checked,\n startAt: form\n .querySelector(Selectors.IFRAME.elements.startAt)\n .value.trim(),\n width: this.parseWidthHeight(\n form.querySelector(Selectors.IFRAME.elements.width).value,\n ),\n height: this.parseWidthHeight(\n form.querySelector(Selectors.IFRAME.elements.height).value,\n ),\n };\n }\n\n async generateIframeHtml(values) {\n const parsed = this.parseInput(values.url);\n if (!parsed) {\n return '';\n }\n\n if (values.textLinkOnly) {\n const viewUrl = this.buildTextLinkUrl(parsed, values);\n\n const escapeHtml = (str) => {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n };\n\n const linkText = escapeHtml(viewUrl);\n const hrefUrl = viewUrl.replace(/\"/g, '"');\n\n return `

${linkText}

`;\n }\n\n const embedUrl = this.buildEmbedUrl(parsed, values);\n\n const context = {\n src: embedUrl,\n maxWidth: values.width || 560,\n height: values.height || 315,\n aspectRatioCSS: this.computeAspectRatioCSS(values),\n };\n\n const { html } = await Templates.renderForPromise(\n 'tiny_mediacms/iframe_embed_output',\n context,\n );\n return html;\n }\n\n async updatePreview(root, updateUrlField = false) {\n const values = this.getFormValues(root);\n const previewContainer = root.querySelector(\n Selectors.IFRAME.elements.preview,\n );\n const urlWarning = root.querySelector(\n Selectors.IFRAME.elements.urlWarning,\n );\n\n if (!values.url) {\n previewContainer.innerHTML =\n 'Enter a video URL to see preview';\n urlWarning.classList.add('d-none');\n return;\n }\n\n const parsed = this.parseInput(values.url);\n if (!parsed) {\n previewContainer.innerHTML =\n 'Invalid URL format';\n urlWarning.classList.remove('d-none');\n return;\n }\n\n urlWarning.classList.add('d-none');\n const embedUrl = this.buildEmbedUrl(parsed, values);\n\n if (updateUrlField && !parsed.isGeneric) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n const urlInput = form.querySelector(Selectors.IFRAME.elements.url);\n urlInput.value = embedUrl;\n }\n\n if (values.textLinkOnly) {\n const viewUrl = this.buildTextLinkUrl(parsed, values);\n\n const escapeHtml = (str) => {\n const div = document.createElement('div');\n div.textContent = str;\n return div.innerHTML;\n };\n\n const linkText = escapeHtml(viewUrl);\n const hrefUrl = viewUrl.replace(/\"/g, '"');\n\n previewContainer.innerHTML = `\n
\n Text link preview:
\n ${linkText}\n
\n `;\n } else {\n const previewWidth = Math.min(values.width || 560, 400);\n const previewHeight = Math.round(previewWidth * (values.height || 315) / (values.width || 560));\n\n previewContainer.innerHTML = `\n \n \n `;\n }\n }\n\n handleInputChange(root, updateUrlField = false) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = setTimeout(() => {\n this.updatePreview(root, updateUrlField);\n }, 500);\n }\n\n handleWidthChange(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n const widthInput = form.querySelector(Selectors.IFRAME.elements.width);\n const heightInput = form.querySelector(Selectors.IFRAME.elements.height);\n const newWidth = parseInt(widthInput.value);\n if (!isNaN(newWidth) && newWidth > 0) {\n heightInput.value = Math.round(newWidth * 9 / 16);\n }\n this.handleInputChange(root);\n }\n\n handleHeightChange(root) {\n this.handleInputChange(root);\n }\n\n async handleDialogueSubmission(modal) {\n const root = modal.getRoot()[0];\n const values = this.getFormValues(root);\n\n if (!values.url) {\n return;\n }\n\n this.savePrefs(values);\n this.signalShare(values);\n const html = await this.generateIframeHtml(values);\n if (html) {\n if (this.isUpdating && this.selectedIframe) {\n const wrapper =\n this.selectedIframe.closest(\n '.tiny-mediacms-iframe-wrapper',\n ) || this.selectedIframe.closest('.tiny-iframe-responsive');\n\n const paragraphWrapper = wrapper ? wrapper.closest('p') : this.selectedIframe.closest('p');\n\n if (paragraphWrapper) {\n paragraphWrapper.outerHTML = html;\n } else if (wrapper) {\n wrapper.outerHTML = html;\n } else {\n this.selectedIframe.outerHTML = html;\n }\n this.isUpdating = false;\n\n setTimeout(() => {\n const body = this.editor.getBody();\n const emptyPs = body.querySelectorAll('p:empty, p:blank');\n emptyPs.forEach(p => {\n if (p.innerHTML.trim() === '' || p.innerHTML === '
') {\n p.remove();\n }\n });\n }, 10);\n\n this.editor.fire('Change');\n } else {\n const node = this.editor.selection.getNode();\n if (node.nodeName === 'P' && node.innerHTML.trim() === '') {\n node.outerHTML = html;\n } else {\n this.editor.insertContent(html);\n }\n setTimeout(() => {\n const body = this.editor.getBody();\n body.querySelectorAll('p').forEach(p => {\n if (p.innerHTML.trim() === '' || p.innerHTML === '
') {\n p.remove();\n }\n });\n }, 50);\n }\n }\n }\n\n async handleRemove(modal) {\n const confirmMessage = await getString(\n 'removeiframeconfirm',\n component,\n );\n\n // eslint-disable-next-line no-alert\n if (!window.confirm(confirmMessage)) {\n return;\n }\n\n if (this.selectedIframe) {\n const wrapper =\n this.selectedIframe.closest('.tiny-mediacms-iframe-wrapper') ||\n this.selectedIframe.closest('.tiny-iframe-responsive');\n if (wrapper) {\n wrapper.remove();\n } else {\n this.selectedIframe.remove();\n }\n }\n\n this.isUpdating = false;\n modal.hide();\n }\n\n async registerEventListeners(modal) {\n await modal.getBody();\n const $root = modal.getRoot();\n const root = $root[0];\n\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n\n form.querySelector(Selectors.IFRAME.elements.url).addEventListener(\n 'input',\n () => this.handleInputChange(root),\n );\n\n [\n Selectors.IFRAME.elements.showTitle,\n Selectors.IFRAME.elements.linkTitle,\n Selectors.IFRAME.elements.showUserAvatar,\n Selectors.IFRAME.elements.startAtEnabled,\n ].forEach((selector) => {\n form.querySelector(selector).addEventListener('change', () =>\n this.handleInputChange(root, true),\n );\n });\n\n form.querySelector(Selectors.IFRAME.elements.textLinkOnly).addEventListener('change', () =>\n this.handleInputChange(root, false),\n );\n\n form.querySelector(Selectors.IFRAME.elements.startAt).addEventListener(\n 'input',\n () => this.handleInputChange(root, true),\n );\n\n form.querySelector(Selectors.IFRAME.elements.width).addEventListener(\n 'input',\n () => this.handleWidthChange(root),\n );\n form.querySelector(Selectors.IFRAME.elements.height).addEventListener(\n 'input',\n () => this.handleHeightChange(root),\n );\n\n $root.on(ModalEvents.save, () => this.handleDialogueSubmission(modal));\n $root.on(ModalEvents.hidden, () => {\n this.currentModal.destroy();\n });\n\n const removeBtn = root.querySelector(Selectors.IFRAME.actions.remove);\n if (removeBtn) {\n removeBtn.addEventListener('click', () => this.handleRemove(modal));\n }\n\n const urlInput = form.querySelector(Selectors.IFRAME.elements.url);\n if (urlInput.value) {\n this.updatePreview(root);\n }\n\n const iframeLibraryTabBtn = form.querySelector(\n Selectors.IFRAME.elements.tabIframeLibraryBtn,\n );\n if (iframeLibraryTabBtn) {\n iframeLibraryTabBtn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n\n this.switchToIframeLibraryTab(root);\n\n setTimeout(() => this.handleIframeLibraryTabClick(root), 100);\n });\n iframeLibraryTabBtn.addEventListener('shown.bs.tab', () =>\n this.handleIframeLibraryTabClick(root),\n );\n const $iframeLibraryTabBtn = window.jQuery\n ? window.jQuery(iframeLibraryTabBtn)\n : null;\n if ($iframeLibraryTabBtn) {\n $iframeLibraryTabBtn.on('shown.bs.tab', () =>\n this.handleIframeLibraryTabClick(root),\n );\n }\n }\n\n const urlTabBtn = form.querySelector(\n Selectors.IFRAME.elements.tabUrlBtn,\n );\n if (urlTabBtn) {\n urlTabBtn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n\n this.switchToUrlTab(root);\n });\n }\n\n const uploadMediaBtn = form.querySelector(\n Selectors.IFRAME.elements.tabUploadMediaBtn,\n );\n if (uploadMediaBtn) {\n uploadMediaBtn.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n\n this.switchToIframeLibraryTab(root);\n\n let uploadUrl = '';\n const ltiConfig = getLti(this.editor);\n\n if (ltiConfig && ltiConfig.contentItemUrl) {\n try {\n const urlObj = new URL(ltiConfig.contentItemUrl);\n urlObj.searchParams.set('action', 'upload');\n uploadUrl = urlObj.toString();\n } catch (err) {\n // eslint-disable-next-line no-unused-vars\n }\n }\n\n if (!uploadUrl) {\n let baseUrl = '';\n try {\n const editorData = getData(this.editor);\n if (editorData && editorData.mediacmsBaseUrl) {\n baseUrl = editorData.mediacmsBaseUrl;\n }\n } catch (err) {\n // eslint-disable-next-line no-unused-vars\n }\n\n if (!baseUrl) {\n try {\n const urlObj = new URL(this.iframeLibraryUrl);\n baseUrl = `${urlObj.protocol}//${urlObj.host}`;\n } catch (err) {\n // eslint-disable-next-line no-unused-vars\n }\n }\n\n baseUrl = baseUrl.replace(/\\/$/, '');\n uploadUrl = baseUrl ? `${baseUrl}/upload` : '';\n }\n\n if (uploadUrl) {\n const pane = form.querySelector(Selectors.IFRAME.elements.paneIframeLibrary);\n if (pane) {\n const iframeEl = pane.querySelector(Selectors.IFRAME.elements.iframeLibraryFrame);\n const placeholderEl = pane.querySelector(Selectors.IFRAME.elements.iframeLibraryPlaceholder);\n const loadingEl = pane.querySelector(Selectors.IFRAME.elements.iframeLibraryLoading);\n\n if (placeholderEl) {\n placeholderEl.classList.add('d-none');\n }\n if (loadingEl) {\n loadingEl.classList.remove('d-none');\n }\n if (iframeEl) {\n iframeEl.classList.add('d-none');\n\n const loadHandler = () => {\n this.handleIframeLibraryLoad(root);\n iframeEl.removeEventListener('load', loadHandler);\n };\n iframeEl.addEventListener('load', loadHandler);\n iframeEl.src = uploadUrl;\n }\n }\n }\n });\n }\n\n this.registerIframeLibraryEventListeners(root);\n\n if (this.isUpdating) {\n setTimeout(() => this.updatePreview(root), 100);\n } else {\n setTimeout(() => this.handleIframeLibraryTabClick(root), 100);\n }\n }\n\n switchToUrlTab(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n\n const urlTabBtn = form.querySelector(\n Selectors.IFRAME.elements.tabUrlBtn,\n );\n const urlTabItem = form.querySelector('.tiny_iframecms_tab_url_item');\n const iframeLibraryTabBtn = form.querySelector(\n Selectors.IFRAME.elements.tabIframeLibraryBtn,\n );\n\n const urlPane = form.querySelector(Selectors.IFRAME.elements.paneUrl);\n const iframeLibraryPane = form.querySelector(\n Selectors.IFRAME.elements.paneIframeLibrary,\n );\n\n if (urlTabItem) {\n urlTabItem.style.display = '';\n }\n\n if (urlTabBtn) {\n urlTabBtn.classList.add('active');\n urlTabBtn.setAttribute('aria-selected', 'true');\n }\n if (iframeLibraryTabBtn) {\n iframeLibraryTabBtn.classList.remove('active');\n iframeLibraryTabBtn.setAttribute('aria-selected', 'false');\n }\n\n if (urlPane) {\n urlPane.classList.add('show', 'active');\n }\n if (iframeLibraryPane) {\n iframeLibraryPane.classList.remove('show', 'active');\n }\n }\n\n switchToIframeLibraryTab(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n\n const urlTabBtn = form.querySelector(\n Selectors.IFRAME.elements.tabUrlBtn,\n );\n const urlTabItem = form.querySelector('.tiny_iframecms_tab_url_item');\n const iframeLibraryTabBtn = form.querySelector(\n Selectors.IFRAME.elements.tabIframeLibraryBtn,\n );\n\n const urlPane = form.querySelector(Selectors.IFRAME.elements.paneUrl);\n const iframeLibraryPane = form.querySelector(\n Selectors.IFRAME.elements.paneIframeLibrary,\n );\n\n if (urlTabItem) {\n urlTabItem.style.display = 'none';\n }\n\n if (urlTabBtn) {\n urlTabBtn.classList.remove('active');\n urlTabBtn.setAttribute('aria-selected', 'false');\n }\n if (iframeLibraryTabBtn) {\n iframeLibraryTabBtn.classList.add('active');\n iframeLibraryTabBtn.setAttribute('aria-selected', 'true');\n }\n\n if (urlPane) {\n urlPane.classList.remove('show', 'active');\n }\n if (iframeLibraryPane) {\n iframeLibraryPane.classList.add('show', 'active');\n }\n }\n\n registerIframeLibraryEventListeners(root) {\n window.addEventListener('message', (event) => {\n this.handleIframeLibraryMessage(root, event);\n });\n }\n\n handleIframeLibraryTabClick(root) {\n this.loadIframeLibrary(root);\n }\n\n loadIframeLibrary(root) {\n const ltiConfig = getLti(this.editor);\n if (ltiConfig?.contentItemUrl) {\n this.loadIframeLibraryViaLti(root);\n } else {\n this.loadIframeLibraryStatic(root);\n }\n }\n\n loadIframeLibraryViaLti(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n const pane = form.querySelector(\n Selectors.IFRAME.elements.paneIframeLibrary,\n );\n\n if (!pane) {\n return;\n }\n\n const placeholderEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryPlaceholder,\n );\n const loadingEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryLoading,\n );\n const iframeEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryFrame,\n );\n\n if (!iframeEl) {\n return;\n }\n\n if (placeholderEl) {\n placeholderEl.classList.add('d-none');\n }\n if (loadingEl) {\n loadingEl.classList.remove('d-none');\n }\n iframeEl.classList.add('d-none');\n\n const loadHandler = () => {\n this.handleIframeLibraryLoad(root);\n };\n iframeEl.addEventListener('load', loadHandler);\n\n const ltiConfig = getLti(this.editor);\n iframeEl.src = ltiConfig.contentItemUrl;\n }\n\n loadIframeLibraryStatic(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n const pane = form.querySelector(\n Selectors.IFRAME.elements.paneIframeLibrary,\n );\n\n if (!pane) {\n return;\n }\n\n const placeholderEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryPlaceholder,\n );\n const loadingEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryLoading,\n );\n const iframeEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryFrame,\n );\n\n if (!iframeEl) {\n return;\n }\n\n if (placeholderEl) {\n placeholderEl.classList.add('d-none');\n }\n if (loadingEl) {\n loadingEl.classList.remove('d-none');\n }\n iframeEl.classList.add('d-none');\n\n const loadHandler = () => {\n if (iframeEl.src === this.iframeLibraryUrl) {\n this.handleIframeLibraryLoad(root);\n iframeEl.removeEventListener('load', loadHandler);\n }\n };\n iframeEl.addEventListener('load', loadHandler);\n\n iframeEl.src = this.iframeLibraryUrl;\n }\n\n handleIframeLibraryLoad(root) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n const pane = form.querySelector(\n Selectors.IFRAME.elements.paneIframeLibrary,\n );\n\n if (!pane) {\n return;\n }\n\n const placeholderEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryPlaceholder,\n );\n const loadingEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryLoading,\n );\n const iframeEl = pane.querySelector(\n Selectors.IFRAME.elements.iframeLibraryFrame,\n );\n\n if (placeholderEl) {\n placeholderEl.classList.add('d-none');\n }\n if (loadingEl) {\n loadingEl.classList.add('d-none');\n }\n if (iframeEl) {\n iframeEl.classList.remove('d-none');\n }\n }\n\n handleIframeLibraryMessage(root, event) {\n const data = event.data;\n\n if (!data) {\n return;\n }\n\n if (data.type === 'videoSelected' && data.embedUrl) {\n this.selectIframeLibraryVideo(root, data.embedUrl, data.videoId);\n return;\n }\n\n if (\n data.type === 'ltiDeepLinkingResponse' ||\n data.messageType === 'LtiDeepLinkingResponse'\n ) {\n const contentItems = data.content_items || data.contentItems || [];\n if (contentItems.length > 0) {\n const item = contentItems[0];\n const embedUrl =\n item.url || item.embed_url || item.embedUrl || '';\n const videoId = item.id || item.mediaId || '';\n if (embedUrl) {\n this.selectIframeLibraryVideo(root, embedUrl, videoId);\n }\n }\n return;\n }\n\n if (data.action === 'selectMedia' || data.action === 'mediaSelected') {\n const embedUrl = data.embedUrl || data.url || '';\n if (embedUrl) {\n this.selectIframeLibraryVideo(root, embedUrl);\n }\n return;\n }\n }\n\n selectIframeLibraryVideo(root, embedUrl) {\n const form = root.querySelector(Selectors.IFRAME.elements.form);\n\n const urlInput = form.querySelector(Selectors.IFRAME.elements.url);\n urlInput.value = embedUrl;\n\n const configureTabItem = root.querySelector('.tiny_iframecms_tab_url_item');\n if (configureTabItem) {\n configureTabItem.style.display = '';\n }\n\n this.switchToUrlTab(root);\n this.updatePreview(root);\n }\n}\n"],"names":["PREFS_FIELDS","constructor","editor","parseInput","input","trim","iframeMatch","match","this","parseEmbedUrl","startsWith","parseVideoUrl","url","urlObj","URL","baseUrl","protocol","host","pathname","searchParams","has","videoId","get","isEmbed","tParam","widthParam","heightParam","showTitle","linkTitle","showUserAvatar","width","parseInt","height","startAt","secondsToTimeString","includes","rawUrl","isLtiLaunch","isGeneric","e","seconds","mins","Math","floor","secs","toString","padStart","timeStringToSeconds","timeStr","parts","split","isNaN","parseWidthHeight","value","parsed","computeAspectRatioCSS","values","w","h","buildTextLinkUrl","options","viewUrl","startAtEnabled","set","buildEmbedUrl","token","courseid","search","signalShare","editorData","mediacmsBaseUrl","ltiConfig","courseId","fetch","method","credentials","headers","body","JSON","stringify","catch","savePrefs","prefs","forEach","k","undefined","localStorage","setItem","_","loadPrefs","parse","getItem","data","autoConvertOptions","savedPrefs","getDefault","key","fallback","_this","isUpdating","elementid","getElement","id","isupdating","textLinkOnly","selectedIframe","getSelectedIframe","getCurrentIframeData","currentModal","IframeModal","create","title","component","templateContext","getTemplateContext","registerEventListeners","node","selection","getNode","nodeName","toLowerCase","getAttribute","iframe","querySelector","wrapper","closest","textLink","href","responsive","src","style","maxWidthMatch","aspectRatioMatch","maxWidth","wrapperMatch","rw","parseFloat","rh","round","getFormValues","root","form","Selectors","IFRAME","elements","checked","linkText","str","div","document","createElement","textContent","innerHTML","escapeHtml","hrefUrl","replace","context","aspectRatioCSS","html","Templates","renderForPromise","updateUrlField","previewContainer","preview","urlWarning","classList","add","remove","embedUrl","previewWidth","min","previewHeight","handleInputChange","clearTimeout","debounceTimer","setTimeout","updatePreview","handleWidthChange","widthInput","heightInput","newWidth","handleHeightChange","modal","getRoot","generateIframeHtml","paragraphWrapper","outerHTML","getBody","querySelectorAll","p","fire","insertContent","confirmMessage","window","confirm","hide","$root","addEventListener","selector","on","ModalEvents","save","handleDialogueSubmission","hidden","destroy","removeBtn","actions","handleRemove","iframeLibraryTabBtn","tabIframeLibraryBtn","preventDefault","stopPropagation","switchToIframeLibraryTab","handleIframeLibraryTabClick","$iframeLibraryTabBtn","jQuery","urlTabBtn","tabUrlBtn","switchToUrlTab","uploadMediaBtn","tabUploadMediaBtn","uploadUrl","contentItemUrl","err","iframeLibraryUrl","pane","paneIframeLibrary","iframeEl","iframeLibraryFrame","placeholderEl","iframeLibraryPlaceholder","loadingEl","iframeLibraryLoading","loadHandler","handleIframeLibraryLoad","removeEventListener","registerIframeLibraryEventListeners","urlTabItem","urlPane","paneUrl","iframeLibraryPane","display","setAttribute","event","handleIframeLibraryMessage","loadIframeLibrary","loadIframeLibraryViaLti","loadIframeLibraryStatic","type","selectIframeLibraryVideo","messageType","action","contentItems","content_items","length","item","embed_url","mediaId","configureTabItem"],"mappings":"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"} \ No newline at end of file