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 e190be59..88792106 100644 Binary files a/lms-plugins/mediacms-moodle/dist/mediacms-moodle-v1.0.0.zip and b/lms-plugins/mediacms-moodle/dist/mediacms-moodle-v1.0.0.zip differ diff --git a/lms-plugins/mediacms-moodle/filter/mediacms/launch.php b/lms-plugins/mediacms-moodle/filter/mediacms/launch.php index 78f0af56..6b0d9b26 100644 --- a/lms-plugins/mediacms-moodle/filter/mediacms/launch.php +++ b/lms-plugins/mediacms-moodle/filter/mediacms/launch.php @@ -31,7 +31,8 @@ $show_media_page = optional_param('show_media_page', '', PARAM_TEXT); // Get configuration $mediacmsurl = get_config('filter_mediacms', 'mediacmsurl'); $ltitoolid = get_config('filter_mediacms', 'ltitoolid'); -$share_embedded_media = (int)(bool)get_config('filter_mediacms', 'share_embedded_media'); +$share_raw = get_config('filter_mediacms', 'share_embedded_media'); +$share_embedded_media = ($share_raw === false) ? 1 : (int)(bool)$share_raw; if (empty($mediacmsurl)) { die('MediaCMS URL not configured'); diff --git a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/iframeembed.min.js b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/iframeembed.min.js index 60b60306..81a092fb 100755 --- a/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/iframeembed.min.js +++ b/lms-plugins/mediacms-moodle/tiny/mediacms/amd/build/iframeembed.min.js @@ -1,3 +1,3 @@ -define("tiny_mediacms/iframeembed",["exports","core/templates","core/str","core/modal_events","./common","./iframemodal","./selectors","./options"],(function(_exports,_templates,_str,ModalEvents,_common,_iframemodal,_selectors,_options){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_templates=_interopRequireDefault(_templates),ModalEvents=function(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(ModalEvents),_iframemodal=_interopRequireDefault(_iframemodal),_selectors=_interopRequireDefault(_selectors);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 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})); +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) {