From ba74c4e6147775d0d1615515fc26451c96114793 Mon Sep 17 00:00:00 2001 From: Markos Gogoulos Date: Tue, 21 Apr 2026 11:58:55 +0300 Subject: [PATCH] a --- .../dist/mediacms-moodle-v1.0.0.zip | Bin 174772 -> 175478 bytes .../filter/mediacms/launch.php | 3 +- .../mediacms/amd/build/iframeembed.min.js | 2 +- .../mediacms/amd/build/iframeembed.min.js.map | 2 +- .../tiny/mediacms/amd/build/plugin.min.js | 2 +- .../tiny/mediacms/amd/build/plugin.min.js.map | 2 +- .../tiny/mediacms/amd/src/iframeembed.js | 7 +++ .../tiny/mediacms/amd/src/plugin.js | 46 ++++++++++++++---- 8 files changed, 49 insertions(+), 15 deletions(-) diff --git a/lms-plugins/mediacms-moodle/dist/mediacms-moodle-v1.0.0.zip b/lms-plugins/mediacms-moodle/dist/mediacms-moodle-v1.0.0.zip index e190be5940abc2c105bbe397f6f05d2fe6d64d12..887921069a2d565871e5bc4007fe7095a1abc40f 100644 GIT binary patch delta 28099 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 db69BOoQfJ38bV<(7wGr3C=52{0VNjf{{U4-N]*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"),showRelated:"1"===urlObj.searchParams.get("showRelated"),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"),showRelated:"1"===urlObj.searchParams.get("showRelated"),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)}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("showRelated",options.showRelated?"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 url.toString()}async getTemplateContext(){var _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)||{},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!==autoConvertOptions[key]?autoConvertOptions[key]:fallback},width=this.isUpdating&&data.width?data.width:560,height=this.isUpdating&&data.height?data.height:315;return{elementid:this.editor.getElement().id,isupdating:this.isUpdating,url:data.url||"",showTitle:getDefault("showTitle"),linkTitle:getDefault("linkTitle"),showRelated:getDefault("showRelated"),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$showRelated2,_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$showRelated,_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,showRelated:null===(_parsed$showRelated=null==parsed?void 0:parsed.showRelated)||void 0===_parsed$showRelated||_parsed$showRelated,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+)?)/),maxWidth=maxWidthMatch?parseInt(maxWidthMatch[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,showRelated:null===(_parsed$showRelated2=null==parsed?void 0:parsed.showRelated)||void 0===_parsed$showRelated2||_parsed$showRelated2,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,showRelated:form.querySelector(_selectors.default.IFRAME.elements.showRelated).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){let viewUrl;viewUrl=parsed.isGeneric||parsed.isLtiLaunch?parsed.rawUrl:"".concat(parsed.baseUrl,"/view?m=").concat(parsed.videoId);const linkText=(str=>{const div=document.createElement("div");return div.textContent=str,div.innerHTML})(viewUrl),hrefUrl=viewUrl.replace(/"/g,""");return'")}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){let viewUrl;viewUrl=parsed.isGeneric||parsed.isLtiLaunch?parsed.rawUrl:"".concat(parsed.baseUrl,"/view?m=").concat(parsed.videoId);const 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;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.showRelated,_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);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"),showRelated:"1"===urlObj.searchParams.get("showRelated"),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"),showRelated:"1"===urlObj.searchParams.get("showRelated"),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)}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("showRelated",options.showRelated?"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()}async getTemplateContext(){var _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)||{},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!==autoConvertOptions[key]?autoConvertOptions[key]:fallback},width=this.isUpdating&&data.width?data.width:560,height=this.isUpdating&&data.height?data.height:315;return{elementid:this.editor.getElement().id,isupdating:this.isUpdating,url:data.url||"",showTitle:getDefault("showTitle"),linkTitle:getDefault("linkTitle"),showRelated:getDefault("showRelated"),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$showRelated2,_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$showRelated,_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,showRelated:null===(_parsed$showRelated=null==parsed?void 0:parsed.showRelated)||void 0===_parsed$showRelated||_parsed$showRelated,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+)?)/),maxWidth=maxWidthMatch?parseInt(maxWidthMatch[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,showRelated:null===(_parsed$showRelated2=null==parsed?void 0:parsed.showRelated)||void 0===_parsed$showRelated2||_parsed$showRelated2,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,showRelated:form.querySelector(_selectors.default.IFRAME.elements.showRelated).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){let viewUrl;viewUrl=parsed.isGeneric||parsed.isLtiLaunch?parsed.rawUrl:"".concat(parsed.baseUrl,"/view?m=").concat(parsed.videoId);const 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){let viewUrl;viewUrl=parsed.isGeneric||parsed.isLtiLaunch?parsed.rawUrl:"".concat(parsed.baseUrl,"/view?m=").concat(parsed.videoId);const 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;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.showRelated,_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 741486c3..ae309519 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\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 showRelated: urlObj.searchParams.get('showRelated') === '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 showRelated: urlObj.searchParams.get('showRelated') === '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 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('showRelated', options.showRelated ? '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 return url.toString();\n }\n\n async getTemplateContext(data = {}) {\n const editorData = getData(this.editor);\n const autoConvertOptions = editorData?.autoConvertOptions || {};\n\n const getDefault = (key, fallback = true) => {\n if (this.isUpdating && data[key] !== undefined) {\n return data[key];\n }\n return autoConvertOptions[key] !== undefined\n ? autoConvertOptions[key]\n : fallback;\n };\n\n const width = (this.isUpdating && data.width) ? data.width : 560;\n const height = (this.isUpdating && data.height) ? data.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 showRelated: getDefault('showRelated'),\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 showRelated: parsed?.showRelated ?? 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 const maxWidth = maxWidthMatch ? parseInt(maxWidthMatch[1]) : 560;\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 showRelated: parsed?.showRelated ?? 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 showRelated: form.querySelector(\n Selectors.IFRAME.elements.showRelated,\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 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 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 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 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 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.showRelated,\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":["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","showRelated","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","buildEmbedUrl","options","token","courseid","search","set","startAtEnabled","data","editorData","autoConvertOptions","getDefault","key","fallback","_this","isUpdating","undefined","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","rw","parseFloat","rh","round","getFormValues","root","form","Selectors","IFRAME","elements","checked","viewUrl","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","forEach","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\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 showRelated: urlObj.searchParams.get('showRelated') === '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 showRelated: urlObj.searchParams.get('showRelated') === '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 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('showRelated', options.showRelated ? '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 async getTemplateContext(data = {}) {\n const editorData = getData(this.editor);\n const autoConvertOptions = editorData?.autoConvertOptions || {};\n\n const getDefault = (key, fallback = true) => {\n if (this.isUpdating && data[key] !== undefined) {\n return data[key];\n }\n return autoConvertOptions[key] !== undefined\n ? autoConvertOptions[key]\n : fallback;\n };\n\n const width = (this.isUpdating && data.width) ? data.width : 560;\n const height = (this.isUpdating && data.height) ? data.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 showRelated: getDefault('showRelated'),\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 showRelated: parsed?.showRelated ?? 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 const maxWidth = maxWidthMatch ? parseInt(maxWidthMatch[1]) : 560;\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 showRelated: parsed?.showRelated ?? 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 showRelated: form.querySelector(\n Selectors.IFRAME.elements.showRelated,\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 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 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 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 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 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.showRelated,\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":["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","showRelated","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","buildEmbedUrl","options","token","courseid","search","set","startAtEnabled","data","editorData","autoConvertOptions","getDefault","key","fallback","_this","isUpdating","undefined","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","rw","parseFloat","rh","round","getFormValues","root","form","Selectors","IFRAME","elements","checked","viewUrl","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","forEach","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 diff --git a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/plugin.min.js b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/plugin.min.js index ded41247..e44304e7 100755 --- a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/plugin.min.js +++ b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/plugin.min.js @@ -5,6 +5,6 @@ define("tiny_mediacms/plugin",["exports","editor_tiny/loader","editor_tiny/utils * @module tiny_mediacms/plugin * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,Commands=_interopRequireWildcard(Commands),Configuration=_interopRequireWildcard(Configuration),Options=_interopRequireWildcard(Options);const isMediaCMSUrl=url=>{if(!url)return!1;try{const urlObj=new URL(url);return("/embed"===urlObj.pathname||"/view"===urlObj.pathname)&&urlObj.searchParams.has("m")}catch(e){return!1}},convertUrlsToIframes=html=>{const tempDiv=document.createElement("div");tempDiv.innerHTML=html;const nodesToReplace=[],walk=el=>{for(const child of Array.from(el.childNodes))if(child.nodeType===Node.TEXT_NODE){const url=child.textContent.trim();isMediaCMSUrl(url)&&nodesToReplace.push({node:child,url:url})}else child.nodeType===Node.ELEMENT_NODE&&"a"!==child.tagName.toLowerCase()&&walk(child)};return walk(tempDiv),nodesToReplace.forEach((_ref=>{let{node:node,url:url}=_ref;const wrapper=document.createElement("div");wrapper.innerHTML=(url=>{let embedUrl=url;try{const urlObj=new URL(url);"/view"===urlObj.pathname&&(urlObj.pathname="/embed",embedUrl=urlObj.toString())}catch(e){}return''})(url);const iframe=wrapper.firstChild;iframe&&node.parentNode.replaceChild(iframe,node)})),tempDiv.innerHTML};var _default=new Promise((async resolve=>{const[tinyMCE,setupCommands,pluginMetadata]=await Promise.all([(0,_loader.getTinyMCE)(),Commands.getSetup(),(0,_utils.getPluginMetadata)(_common.component,_common.pluginName)]);tinyMCE.PluginManager.add("".concat(_common.component,"/plugin"),(editor=>(Options.register(editor),setupCommands(editor),(0,_autoconvert.setupAutoConvert)(editor),editor.on("BeforeSetContent",(e=>{e.content&&"string"==typeof e.content&&(e.content=convertUrlsToIframes(e.content))})),editor.on("GetContent",(e=>{if("html"===e.format){const tempDiv=document.createElement("div");tempDiv.innerHTML=e.content,tempDiv.querySelectorAll(".tiny-mediacms-edit-btn").forEach((btn=>btn.remove())),tempDiv.querySelectorAll(".tiny-mediacms-iframe-wrapper, .tiny-iframe-responsive").forEach((wrapper=>{const iframe=wrapper.querySelector("iframe");iframe&&wrapper.parentNode.insertBefore(iframe,wrapper),wrapper.remove()})),e.content=tempDiv.innerHTML}})),pluginMetadata))),resolve(["".concat(_common.component,"/plugin"),Configuration])}));return _exports.default=_default,_exports.default})); + */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,Commands=_interopRequireWildcard(Commands),Configuration=_interopRequireWildcard(Configuration),Options=_interopRequireWildcard(Options);const isMediaCMSUrl=url=>{if(!url)return!1;try{const urlObj=new URL(url);return("/embed"===urlObj.pathname||"/view"===urlObj.pathname)&&urlObj.searchParams.has("m")}catch(e){return!1}},convertUrlsToIframes=html=>{const tempDiv=document.createElement("div");tempDiv.innerHTML=html;const nodesToReplace=[],walk=el=>{for(const child of Array.from(el.childNodes))if(child.nodeType===Node.TEXT_NODE){const url=child.textContent.trim();isMediaCMSUrl(url)&&nodesToReplace.push({node:child,url:url})}else child.nodeType===Node.ELEMENT_NODE&&"a"!==child.tagName.toLowerCase()&&walk(child)};return walk(tempDiv),nodesToReplace.forEach((_ref=>{let{node:node,url:url}=_ref;const wrapper=document.createElement("div");wrapper.innerHTML=(url=>{let embedUrl=url,width=560,height=315;try{const urlObj=new URL(url);"/view"===urlObj.pathname&&(urlObj.pathname="/embed");const w=parseInt(urlObj.searchParams.get("width")),h=parseInt(urlObj.searchParams.get("height"));w>0&&(width=w),h>0&&(height=h),embedUrl=urlObj.toString()}catch(e){}const style="width:100%;max-width:".concat(width,"px;height:auto;")+"aspect-ratio:".concat(width," / ").concat(height,";display:block;margin:0 auto;border:0;");return'')})(url);const iframe=wrapper.firstChild;iframe&&node.parentNode.replaceChild(iframe,node)})),tempDiv.innerHTML};var _default=new Promise((async resolve=>{const[tinyMCE,setupCommands,pluginMetadata]=await Promise.all([(0,_loader.getTinyMCE)(),Commands.getSetup(),(0,_utils.getPluginMetadata)(_common.component,_common.pluginName)]);tinyMCE.PluginManager.add("".concat(_common.component,"/plugin"),(editor=>(Options.register(editor),setupCommands(editor),(0,_autoconvert.setupAutoConvert)(editor),editor.on("BeforeSetContent",(e=>{e.content&&"string"==typeof e.content&&(e.content=convertUrlsToIframes(e.content))})),editor.on("GetContent",(e=>{if("html"===e.format){const tempDiv=document.createElement("div");tempDiv.innerHTML=e.content,tempDiv.querySelectorAll(".tiny-mediacms-edit-btn").forEach((btn=>btn.remove())),tempDiv.querySelectorAll("iframe").forEach((iframe=>{const src=iframe.getAttribute("src");if(isMediaCMSUrl(src)){const wrapper=iframe.closest(".tiny-mediacms-iframe-wrapper")||iframe.closest(".tiny-iframe-responsive"),p=document.createElement("p");p.appendChild(document.createTextNode(src)),wrapper?(wrapper.parentNode.insertBefore(p,wrapper),wrapper.remove()):(iframe.parentNode.insertBefore(p,iframe),iframe.remove())}})),tempDiv.querySelectorAll(".tiny-mediacms-iframe-wrapper, .tiny-iframe-responsive").forEach((wrapper=>{const iframe=wrapper.querySelector("iframe");iframe&&wrapper.parentNode.insertBefore(iframe,wrapper),wrapper.remove()})),e.content=tempDiv.innerHTML}})),pluginMetadata))),resolve(["".concat(_common.component,"/plugin"),Configuration])}));return _exports.default=_default,_exports.default})); //# sourceMappingURL=plugin.min.js.map \ No newline at end of file diff --git a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/plugin.min.js.map b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/plugin.min.js.map index ee844ff6..133ebb53 100755 --- a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/plugin.min.js.map +++ b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/plugin.min.js.map @@ -1 +1 @@ -{"version":3,"file":"plugin.min.js","sources":["../src/plugin.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tiny Media plugin for Moodle.\n *\n * @module tiny_mediacms/plugin\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {getTinyMCE} from 'editor_tiny/loader';\nimport {getPluginMetadata} from 'editor_tiny/utils';\n\nimport {component, pluginName} from './common';\nimport * as Commands from './commands';\nimport * as Configuration from './configuration';\nimport * as Options from './options';\nimport {setupAutoConvert} from './autoconvert';\n\n/**\n * Check if a URL is a MediaCMS URL (embed or view).\n *\n * @param {string} url - The URL to check\n * @returns {boolean} True if it's a MediaCMS URL\n */\nconst isMediaCMSUrl = (url) => {\n if (!url) {\n return false;\n }\n try {\n const urlObj = new URL(url);\n // Match both /embed and /view paths with ?m= parameter\n return (urlObj.pathname === '/embed' || urlObj.pathname === '/view') && urlObj.searchParams.has('m');\n } catch (e) {\n return false;\n }\n};\n\n/**\n * Convert a MediaCMS URL (embed or view) to an iframe HTML string.\n * If it's a view URL, it will be converted to embed URL.\n *\n * @param {string} url - The MediaCMS URL\n * @returns {string} The iframe HTML\n */\nconst mediaCMSUrlToIframe = (url) => {\n // Convert view URL to embed URL if needed\n let embedUrl = url;\n try {\n const urlObj = new URL(url);\n if (urlObj.pathname === '/view') {\n urlObj.pathname = '/embed';\n embedUrl = urlObj.toString();\n }\n } catch (e) {\n // Keep original URL if parsing fails\n }\n\n return ``;\n};\n\n/**\n * Convert standalone MediaCMS URL text nodes to iframes.\n * Uses DOM traversal so URLs inside tags (text links) are never touched.\n *\n * @param {string} html - Raw HTML string from the editor\n * @returns {string} HTML with standalone URLs replaced by iframe HTML\n */\nconst convertUrlsToIframes = (html) => {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = html;\n\n const nodesToReplace = [];\n const walk = (el) => {\n for (const child of Array.from(el.childNodes)) {\n if (child.nodeType === Node.TEXT_NODE) {\n const url = child.textContent.trim();\n if (isMediaCMSUrl(url)) {\n nodesToReplace.push({node: child, url});\n }\n } else if (child.nodeType === Node.ELEMENT_NODE && child.tagName.toLowerCase() !== 'a') {\n walk(child);\n }\n // Do not recurse into tags — text links must be preserved as-is\n }\n };\n walk(tempDiv);\n\n nodesToReplace.forEach(({node, url}) => {\n const wrapper = document.createElement('div');\n wrapper.innerHTML = mediaCMSUrlToIframe(url);\n const iframe = wrapper.firstChild;\n if (iframe) {\n node.parentNode.replaceChild(iframe, node);\n }\n });\n\n return tempDiv.innerHTML;\n};\n\n// eslint-disable-next-line no-async-promise-executor\nexport default new Promise(async(resolve) => {\n const [\n tinyMCE,\n setupCommands,\n pluginMetadata,\n ] = await Promise.all([\n getTinyMCE(),\n Commands.getSetup(),\n getPluginMetadata(component, pluginName),\n ]);\n\n tinyMCE.PluginManager.add(`${component}/plugin`, (editor) => {\n // Register options.\n Options.register(editor);\n\n // Setup the Commands (buttons, menu items, and so on).\n setupCommands(editor);\n\n // Setup auto-conversion of pasted MediaCMS URLs.\n setupAutoConvert(editor);\n\n // Convert standalone MediaCMS URL text nodes to iframes when loading content.\n // Text links () are preserved because DOM traversal skips tags.\n editor.on('BeforeSetContent', (e) => {\n if (e.content && typeof e.content === 'string') {\n e.content = convertUrlsToIframes(e.content);\n }\n });\n\n // Clean up editor-only overlay elements when saving, preserving iframe HTML with its\n // responsive styles (max-width, aspect-ratio) so dimensions survive the round-trip.\n editor.on('GetContent', (e) => {\n if (e.format === 'html') {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = e.content;\n\n // Remove edit buttons added by the overlay system (editor-only UI)\n tempDiv.querySelectorAll('.tiny-mediacms-edit-btn').forEach(btn => btn.remove());\n\n // Unwrap overlay divs, keeping the iframe HTML intact with its responsive styles\n tempDiv.querySelectorAll('.tiny-mediacms-iframe-wrapper, .tiny-iframe-responsive').forEach(wrapper => {\n const iframe = wrapper.querySelector('iframe');\n if (iframe) {\n wrapper.parentNode.insertBefore(iframe, wrapper);\n }\n wrapper.remove();\n });\n\n e.content = tempDiv.innerHTML;\n }\n });\n\n return pluginMetadata;\n });\n\n // Resolve the Media Plugin and include configuration.\n resolve([`${component}/plugin`, Configuration]);\n});\n"],"names":["isMediaCMSUrl","url","urlObj","URL","pathname","searchParams","has","e","convertUrlsToIframes","html","tempDiv","document","createElement","innerHTML","nodesToReplace","walk","el","child","Array","from","childNodes","nodeType","Node","TEXT_NODE","textContent","trim","push","node","ELEMENT_NODE","tagName","toLowerCase","forEach","_ref","wrapper","embedUrl","toString","mediaCMSUrlToIframe","iframe","firstChild","parentNode","replaceChild","Promise","async","tinyMCE","setupCommands","pluginMetadata","all","Commands","getSetup","component","pluginName","PluginManager","add","editor","Options","register","on","content","format","querySelectorAll","btn","remove","querySelector","insertBefore","resolve","Configuration"],"mappings":";;;;;;;oOAqCMA,cAAiBC,UACdA,WACM,YAGDC,OAAS,IAAIC,IAAIF,YAEK,WAApBC,OAAOE,UAA6C,UAApBF,OAAOE,WAAyBF,OAAOG,aAAaC,IAAI,KAClG,MAAOC,UACE,IAoCTC,qBAAwBC,aACpBC,QAAUC,SAASC,cAAc,OACvCF,QAAQG,UAAYJ,WAEdK,eAAiB,GACjBC,KAAQC,SACL,MAAMC,SAASC,MAAMC,KAAKH,GAAGI,eAC1BH,MAAMI,WAAaC,KAAKC,UAAW,OAC7BtB,IAAMgB,MAAMO,YAAYC,OAC1BzB,cAAcC,MACda,eAAeY,KAAK,CAACC,KAAMV,MAAOhB,IAAAA,WAE/BgB,MAAMI,WAAaC,KAAKM,cAAgD,MAAhCX,MAAMY,QAAQC,eAC7Df,KAAKE,eAKjBF,KAAKL,SAELI,eAAeiB,SAAQC,WAACL,KAACA,KAAD1B,IAAOA,gBACrBgC,QAAUtB,SAASC,cAAc,OACvCqB,QAAQpB,UA/CaZ,CAAAA,UAErBiC,SAAWjC,cAELC,OAAS,IAAIC,IAAIF,KACC,UAApBC,OAAOE,WACPF,OAAOE,SAAW,SAClB8B,SAAWhC,OAAOiC,YAExB,MAAO5B,UAIF,uBAAgB2B,wCAAhB,6IAkCiBE,CAAoBnC,WAClCoC,OAASJ,QAAQK,WACnBD,QACAV,KAAKY,WAAWC,aAAaH,OAAQV,SAItCjB,QAAQG,wBAIJ,IAAI4B,SAAQC,MAAAA,gBAEnBC,QACAC,cACAC,sBACMJ,QAAQK,IAAI,EAClB,wBACAC,SAASC,YACT,4BAAkBC,kBAAWC,sBAGjCP,QAAQQ,cAAcC,cAAOH,8BAAqBI,SAE9CC,QAAQC,SAASF,QAGjBT,cAAcS,0CAGGA,QAIjBA,OAAOG,GAAG,oBAAqBjD,IACvBA,EAAEkD,SAAgC,iBAAdlD,EAAEkD,UACtBlD,EAAEkD,QAAUjD,qBAAqBD,EAAEkD,aAM3CJ,OAAOG,GAAG,cAAejD,OACJ,SAAbA,EAAEmD,OAAmB,OACfhD,QAAUC,SAASC,cAAc,OACvCF,QAAQG,UAAYN,EAAEkD,QAGtB/C,QAAQiD,iBAAiB,2BAA2B5B,SAAQ6B,KAAOA,IAAIC,WAGvEnD,QAAQiD,iBAAiB,0DAA0D5B,SAAQE,gBACjFI,OAASJ,QAAQ6B,cAAc,UACjCzB,QACAJ,QAAQM,WAAWwB,aAAa1B,OAAQJ,SAE5CA,QAAQ4B,YAGZtD,EAAEkD,QAAU/C,QAAQG,cAIrBgC,kBAIXmB,QAAQ,WAAIf,6BAAoBgB"} \ No newline at end of file +{"version":3,"file":"plugin.min.js","sources":["../src/plugin.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Tiny Media plugin for Moodle.\n *\n * @module tiny_mediacms/plugin\n * @copyright 2022 Andrew Lyons \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport {getTinyMCE} from 'editor_tiny/loader';\nimport {getPluginMetadata} from 'editor_tiny/utils';\n\nimport {component, pluginName} from './common';\nimport * as Commands from './commands';\nimport * as Configuration from './configuration';\nimport * as Options from './options';\nimport {setupAutoConvert} from './autoconvert';\n\n/**\n * Check if a URL is a MediaCMS URL (embed or view).\n *\n * @param {string} url - The URL to check\n * @returns {boolean} True if it's a MediaCMS URL\n */\nconst isMediaCMSUrl = (url) => {\n if (!url) {\n return false;\n }\n try {\n const urlObj = new URL(url);\n // Match both /embed and /view paths with ?m= parameter\n return (urlObj.pathname === '/embed' || urlObj.pathname === '/view') && urlObj.searchParams.has('m');\n } catch (e) {\n return false;\n }\n};\n\n/**\n * Convert a MediaCMS URL (embed or view) to an iframe HTML string.\n * If it's a view URL, it will be converted to embed URL.\n *\n * @param {string} url - The MediaCMS URL\n * @returns {string} The iframe HTML\n */\nconst mediaCMSUrlToIframe = (url) => {\n let embedUrl = url;\n let width = 560;\n let height = 315;\n try {\n const urlObj = new URL(url);\n if (urlObj.pathname === '/view') {\n urlObj.pathname = '/embed';\n }\n const w = parseInt(urlObj.searchParams.get('width'));\n const h = parseInt(urlObj.searchParams.get('height'));\n if (w > 0) {\n width = w;\n }\n if (h > 0) {\n height = h;\n }\n embedUrl = urlObj.toString();\n } catch (e) {\n // Keep defaults if parsing fails\n }\n\n const style = `width:100%;max-width:${width}px;height:auto;` +\n `aspect-ratio:${width} / ${height};display:block;margin:0 auto;border:0;`;\n return ``;\n};\n\n/**\n * Convert standalone MediaCMS URL text nodes to iframes.\n * Uses DOM traversal so URLs inside tags (text links) are never touched.\n *\n * @param {string} html - Raw HTML string from the editor\n * @returns {string} HTML with standalone URLs replaced by iframe HTML\n */\nconst convertUrlsToIframes = (html) => {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = html;\n\n const nodesToReplace = [];\n const walk = (el) => {\n for (const child of Array.from(el.childNodes)) {\n if (child.nodeType === Node.TEXT_NODE) {\n const url = child.textContent.trim();\n if (isMediaCMSUrl(url)) {\n nodesToReplace.push({node: child, url});\n }\n } else if (child.nodeType === Node.ELEMENT_NODE && child.tagName.toLowerCase() !== 'a') {\n walk(child);\n }\n // Do not recurse into tags — text links must be preserved as-is\n }\n };\n walk(tempDiv);\n\n nodesToReplace.forEach(({node, url}) => {\n const wrapper = document.createElement('div');\n wrapper.innerHTML = mediaCMSUrlToIframe(url);\n const iframe = wrapper.firstChild;\n if (iframe) {\n node.parentNode.replaceChild(iframe, node);\n }\n });\n\n return tempDiv.innerHTML;\n};\n\n// eslint-disable-next-line no-async-promise-executor\nexport default new Promise(async(resolve) => {\n const [\n tinyMCE,\n setupCommands,\n pluginMetadata,\n ] = await Promise.all([\n getTinyMCE(),\n Commands.getSetup(),\n getPluginMetadata(component, pluginName),\n ]);\n\n tinyMCE.PluginManager.add(`${component}/plugin`, (editor) => {\n // Register options.\n Options.register(editor);\n\n // Setup the Commands (buttons, menu items, and so on).\n setupCommands(editor);\n\n // Setup auto-conversion of pasted MediaCMS URLs.\n setupAutoConvert(editor);\n\n // Convert standalone MediaCMS URL text nodes to iframes when loading content.\n // Text links () are preserved because DOM traversal skips tags.\n editor.on('BeforeSetContent', (e) => {\n if (e.content && typeof e.content === 'string') {\n e.content = convertUrlsToIframes(e.content);\n }\n });\n\n // Convert MediaCMS iframes back to plain embed URLs when saving.\n // Width/height are encoded in the URL params so the filter and BeforeSetContent\n // can reconstruct the correct responsive iframe on next load.\n editor.on('GetContent', (e) => {\n if (e.format === 'html') {\n const tempDiv = document.createElement('div');\n tempDiv.innerHTML = e.content;\n\n tempDiv.querySelectorAll('.tiny-mediacms-edit-btn').forEach(btn => btn.remove());\n\n tempDiv.querySelectorAll('iframe').forEach(iframe => {\n const src = iframe.getAttribute('src');\n if (isMediaCMSUrl(src)) {\n const wrapper = iframe.closest('.tiny-mediacms-iframe-wrapper') ||\n iframe.closest('.tiny-iframe-responsive');\n const p = document.createElement('p');\n p.appendChild(document.createTextNode(src));\n if (wrapper) {\n wrapper.parentNode.insertBefore(p, wrapper);\n wrapper.remove();\n } else {\n iframe.parentNode.insertBefore(p, iframe);\n iframe.remove();\n }\n }\n });\n\n tempDiv.querySelectorAll('.tiny-mediacms-iframe-wrapper, .tiny-iframe-responsive').forEach(wrapper => {\n const iframe = wrapper.querySelector('iframe');\n if (iframe) {\n wrapper.parentNode.insertBefore(iframe, wrapper);\n }\n wrapper.remove();\n });\n\n e.content = tempDiv.innerHTML;\n }\n });\n\n return pluginMetadata;\n });\n\n // Resolve the Media Plugin and include configuration.\n resolve([`${component}/plugin`, Configuration]);\n});\n"],"names":["isMediaCMSUrl","url","urlObj","URL","pathname","searchParams","has","e","convertUrlsToIframes","html","tempDiv","document","createElement","innerHTML","nodesToReplace","walk","el","child","Array","from","childNodes","nodeType","Node","TEXT_NODE","textContent","trim","push","node","ELEMENT_NODE","tagName","toLowerCase","forEach","_ref","wrapper","embedUrl","width","height","w","parseInt","get","h","toString","style","mediaCMSUrlToIframe","iframe","firstChild","parentNode","replaceChild","Promise","async","tinyMCE","setupCommands","pluginMetadata","all","Commands","getSetup","component","pluginName","PluginManager","add","editor","Options","register","on","content","format","querySelectorAll","btn","remove","src","getAttribute","closest","p","appendChild","createTextNode","insertBefore","querySelector","resolve","Configuration"],"mappings":";;;;;;;oOAqCMA,cAAiBC,UACdA,WACM,YAGDC,OAAS,IAAIC,IAAIF,YAEK,WAApBC,OAAOE,UAA6C,UAApBF,OAAOE,WAAyBF,OAAOG,aAAaC,IAAI,KAClG,MAAOC,UACE,IA8CTC,qBAAwBC,aACpBC,QAAUC,SAASC,cAAc,OACvCF,QAAQG,UAAYJ,WAEdK,eAAiB,GACjBC,KAAQC,SACL,MAAMC,SAASC,MAAMC,KAAKH,GAAGI,eAC1BH,MAAMI,WAAaC,KAAKC,UAAW,OAC7BtB,IAAMgB,MAAMO,YAAYC,OAC1BzB,cAAcC,MACda,eAAeY,KAAK,CAACC,KAAMV,MAAOhB,IAAAA,WAE/BgB,MAAMI,WAAaC,KAAKM,cAAgD,MAAhCX,MAAMY,QAAQC,eAC7Df,KAAKE,eAKjBF,KAAKL,SAELI,eAAeiB,SAAQC,WAACL,KAACA,KAAD1B,IAAOA,gBACrBgC,QAAUtB,SAASC,cAAc,OACvCqB,QAAQpB,UAzDaZ,CAAAA,UACrBiC,SAAWjC,IACXkC,MAAQ,IACRC,OAAS,cAEHlC,OAAS,IAAIC,IAAIF,KACC,UAApBC,OAAOE,WACPF,OAAOE,SAAW,gBAEhBiC,EAAIC,SAASpC,OAAOG,aAAakC,IAAI,UACrCC,EAAIF,SAASpC,OAAOG,aAAakC,IAAI,WACvCF,EAAI,IACJF,MAAQE,GAERG,EAAI,IACJJ,OAASI,GAEbN,SAAWhC,OAAOuC,WACpB,MAAOlC,UAIHmC,MAAQ,+BAAwBP,gDAClBA,oBAAWC,uDACxB,uBAAgBF,6BAAoBC,2BAAkBC,8BAC/CM,sDAgCUC,CAAoB1C,WAClC2C,OAASX,QAAQY,WACnBD,QACAjB,KAAKmB,WAAWC,aAAaH,OAAQjB,SAItCjB,QAAQG,wBAIJ,IAAImC,SAAQC,MAAAA,gBAEnBC,QACAC,cACAC,sBACMJ,QAAQK,IAAI,EAClB,wBACAC,SAASC,YACT,4BAAkBC,kBAAWC,sBAGjCP,QAAQQ,cAAcC,cAAOH,8BAAqBI,SAE9CC,QAAQC,SAASF,QAGjBT,cAAcS,0CAGGA,QAIjBA,OAAOG,GAAG,oBAAqBxD,IACvBA,EAAEyD,SAAgC,iBAAdzD,EAAEyD,UACtBzD,EAAEyD,QAAUxD,qBAAqBD,EAAEyD,aAO3CJ,OAAOG,GAAG,cAAexD,OACJ,SAAbA,EAAE0D,OAAmB,OACfvD,QAAUC,SAASC,cAAc,OACvCF,QAAQG,UAAYN,EAAEyD,QAEtBtD,QAAQwD,iBAAiB,2BAA2BnC,SAAQoC,KAAOA,IAAIC,WAEvE1D,QAAQwD,iBAAiB,UAAUnC,SAAQa,eACjCyB,IAAMzB,OAAO0B,aAAa,UAC5BtE,cAAcqE,KAAM,OACdpC,QAAUW,OAAO2B,QAAQ,kCACf3B,OAAO2B,QAAQ,2BACzBC,EAAI7D,SAASC,cAAc,KACjC4D,EAAEC,YAAY9D,SAAS+D,eAAeL,MAClCpC,SACAA,QAAQa,WAAW6B,aAAaH,EAAGvC,SACnCA,QAAQmC,WAERxB,OAAOE,WAAW6B,aAAaH,EAAG5B,QAClCA,OAAOwB,cAKnB1D,QAAQwD,iBAAiB,0DAA0DnC,SAAQE,gBACjFW,OAASX,QAAQ2C,cAAc,UACjChC,QACAX,QAAQa,WAAW6B,aAAa/B,OAAQX,SAE5CA,QAAQmC,YAGZ7D,EAAEyD,QAAUtD,QAAQG,cAIrBuC,kBAIXyB,QAAQ,WAAIrB,6BAAoBsB"} \ No newline at end of file diff --git a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/src/iframeembed.js b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/src/iframeembed.js index 32501907..d33e307e 100755 --- a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/src/iframeembed.js +++ b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/src/iframeembed.js @@ -180,6 +180,13 @@ export default class IframeEmbed { } } + if (options.width) { + url.searchParams.set('width', options.width); + } + if (options.height) { + url.searchParams.set('height', options.height); + } + return url.toString(); } diff --git a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/src/plugin.js b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/src/plugin.js index adf935d8..29173b5d 100755 --- a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/src/plugin.js +++ b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/src/plugin.js @@ -56,21 +56,31 @@ const isMediaCMSUrl = (url) => { * @returns {string} The iframe HTML */ const mediaCMSUrlToIframe = (url) => { - // Convert view URL to embed URL if needed let embedUrl = url; + let width = 560; + let height = 315; try { const urlObj = new URL(url); if (urlObj.pathname === '/view') { urlObj.pathname = '/embed'; - embedUrl = urlObj.toString(); } + const w = parseInt(urlObj.searchParams.get('width')); + const h = parseInt(urlObj.searchParams.get('height')); + if (w > 0) { + width = w; + } + if (h > 0) { + height = h; + } + embedUrl = urlObj.toString(); } catch (e) { - // Keep original URL if parsing fails + // Keep defaults if parsing fails } - return ``; + const style = `width:100%;max-width:${width}px;height:auto;` + + `aspect-ratio:${width} / ${height};display:block;margin:0 auto;border:0;`; + return ``; }; /** @@ -142,17 +152,33 @@ export default new Promise(async(resolve) => { } }); - // Clean up editor-only overlay elements when saving, preserving iframe HTML with its - // responsive styles (max-width, aspect-ratio) so dimensions survive the round-trip. + // Convert MediaCMS iframes back to plain embed URLs when saving. + // Width/height are encoded in the URL params so the filter and BeforeSetContent + // can reconstruct the correct responsive iframe on next load. editor.on('GetContent', (e) => { if (e.format === 'html') { const tempDiv = document.createElement('div'); tempDiv.innerHTML = e.content; - // Remove edit buttons added by the overlay system (editor-only UI) tempDiv.querySelectorAll('.tiny-mediacms-edit-btn').forEach(btn => btn.remove()); - // Unwrap overlay divs, keeping the iframe HTML intact with its responsive styles + tempDiv.querySelectorAll('iframe').forEach(iframe => { + const src = iframe.getAttribute('src'); + if (isMediaCMSUrl(src)) { + const wrapper = iframe.closest('.tiny-mediacms-iframe-wrapper') || + iframe.closest('.tiny-iframe-responsive'); + const p = document.createElement('p'); + p.appendChild(document.createTextNode(src)); + if (wrapper) { + wrapper.parentNode.insertBefore(p, wrapper); + wrapper.remove(); + } else { + iframe.parentNode.insertBefore(p, iframe); + iframe.remove(); + } + } + }); + tempDiv.querySelectorAll('.tiny-mediacms-iframe-wrapper, .tiny-iframe-responsive').forEach(wrapper => { const iframe = wrapper.querySelector('iframe'); if (iframe) {

').concat(linkText,"