For the sake of remembering myself of what I did, not being an expert in JavaScript coding but still needing to fix that placeholder bug in Dokeos, I'm writing this part as a real log, not really a well-presented article, but I'm still publishing it in case it would help someone else.
In Dokeos, we use FCKeditor. The first problem that comes to mind is that I don't know exactly which version. I didn't integrate it, but based on this feature request, we use 2.2, while the current version (as of today) is 2.6.2. So there are considerable differences here. Julio is working on integrating version 2.6.2 for Dokeos 1.8.6, but I had to get working faster than that on the placeholder bug, that is, with the features we have added (as plugins or new developments) to Dokeos, you are able to insert a MP3 or a video into an HTML document. Well, this only works for adding resources, and the update feature doesn't work (it does with the MP3 player, but not the video).
Some of the assumptions I'm taking below might be wrong, but the overall objective of this precise article (as opposed to all other articles on this blog) does not seek the truth but rather the effectiveness of debugging this tool.
As I don't know anything about FCKeditor, I'm pretty much starting from scratch. I'm using the Firefox Firebug extension to see what's happening in my code by putting breaks in the editor/js/fckeditorcode_gecko_1.js file, which is apparently where most things are happening.
FCKeditor works this way: you include the generic FCKeditor file from inside a document and call a function that will display the editor. The generic file is most likely fckeditor/fckeditor_1.js
This file includes fckeditor/editor/js/fck_startup.js, which checks which browser is used and loads either of the two pairs of files below:
- fckeditor/editor/js/fckeditorcode_gecko_1.js
- fckeditor/editor/js/fckeditorcode_gecko_2.js
- fckeditor/editor/js/fckeditorcode_ie_1.js
- fckeditor/editor/js/fckeditorcode_ie_2.js
- fckeditor/editor/js/fckeditorcode_gecko_1.js
- fckeditor/editor/js/fckeditorcode_gecko_2.js
- fckeditor/editor/js/fckeditorcode_ie_1.js
- fckeditor/editor/js/fckeditorcode_ie_2.js
FCKFlashProcessor.ProcessDocument=function(A) { ...It looks like this function is called automatically from the editor when someone opens a new page for edtion. This function goes through the DOM element given and looks for EMBED or OBJECT tags, then disects them to find those resources we know are managed by plugins. I have considerably updated this code already, and right now it looks like this (pretty ugly):
var FCKFlashProcessor=new Object(); FCKFlashProcessor.ProcessDocument=function(A) { //Treating tags first is a dirty hack. Because tags are enclosed into <object> tags, // and because we treat <object> tags afterwards, we can do whatever we want here with embed tags // inside the <object> tag and then remove the object tag when we get to it to "clean" it. var B=A.getElementsByTagName('EMBED'); var C; var i=B.length-1; while (i>=0&&(C=B[i--])){ if(C.parentNode && C.parentNode != null) { //check if the parent of this tag is an <object> tag. If so, just leave the process //to the code in the next section, that treats objects specifically if(C.parentNode.nodeName.toString().toLowerCase() == 'object') continue; if (C.src.endsWith('.swf',true)){ var D=C.cloneNode(true); if (FCKBrowserInfo.IsIE){ D.setAttribute('scale',C.getAttribute('scale')); D.setAttribute('play',C.getAttribute('play')); D.setAttribute('loop',C.getAttribute('loop')); D.setAttribute('menu',C.getAttribute('menu')); }; var E=FCKDocumentProcessors_CreateFakeImage('FCK__Flash',D); E.setAttribute('_fckflash','true',0); FCKFlashProcessor.RefreshView(E,C); C.parentNode.insertBefore(E,C); C.parentNode.removeChild(C); } else if (C.src.search('/.flv&/') || C.src.search('/.avi&/') || C.src.search('/.mpg&/') || C.src.search('/.mpeg&/') || C.src.search('/.mov&/') || C.src.search('/.wmv&/') || C.src.search('/.rm&/')){ var D=C.cloneNode(true); if (FCKBrowserInfo.IsIE){ D.setAttribute('scale',C.getAttribute('scale')); D.setAttribute('play',C.getAttribute('play')); D.setAttribute('loop',C.getAttribute('loop')); D.setAttribute('menu',C.getAttribute('menu')); }; var E=FCKDocumentProcessors_CreateFakeImage('FCK__Video',D); E.setAttribute('_fckVideo','true',0); FCKFlashProcessor.RefreshView(E,C); C.parentNode.insertBefore(E,C); C.parentNode.removeChild(C); }; }; }; var B=A.getElementsByTagName('OBJECT'); var C; var i=B.length-1; while (i>=0&&(C=B[i--])){ //look for the <param name="movie" ...> child var F; var j=C.childNodes.length-1; var treated = false; while (j>=0 && (F=C.childNodes[j--]) && treated == false){ if(C.parentNode && C.parentNode!=null && F.name && F.name.toString() == 'movie') { if(F.value.toString()!='' && F.value.toString().length>1) { //we have found an attribute <param name="movie" ...> var Fval = F.value.toString(); if (Fval.endsWith('.mp3',true)){ var D=C.cloneNode(true); if (FCKBrowserInfo.IsIE){ D.setAttribute('scale',C.getAttribute('scale')); D.setAttribute('play',C.getAttribute('play')); D.setAttribute('loop',C.getAttribute('loop')); D.setAttribute('menu',C.getAttribute('menu')); }; var E=FCKDocumentProcessors_CreateFakeImage('FCK__MP3',D); E.setAttribute('_fckmp3','true',0); FCKFlashProcessor.RefreshView(E,C); C.parentNode.insertBefore(E,C); C.parentNode.removeChild(C); treated = true; }else if (Fval.search('/.avi&/') || Fval.search('/.mpg&/') || Fval.search('/.mpeg&/') || Fval.search('/.mov&/') || Fval.search('/.wmv&/') || Fval.search('/.rm&/')){ var D=C.cloneNode(true); if (FCKBrowserInfo.IsIE){ D.setAttribute('scale',C.getAttribute('scale')); D.setAttribute('play',C.getAttribute('play')); D.setAttribute('loop',C.getAttribute('loop')); D.setAttribute('menu',C.getAttribute('menu')); }; var E=FCKDocumentProcessors_CreateFakeImage('FCK__Video',D); E.setAttribute('_fckVideo','true',0); FCKFlashProcessor.RefreshView(E,C); C.parentNode.insertBefore(E,C); C.parentNode.removeChild(C); treated = true; }; } } else if(C.parentNode && C.parentNode!=null && F.name && F.name.toString() == 'FlashVars') { if(F.value.toString().length>1) { //we have found an attribute <param name="FlashVars" ...> var Fval = F.value.toString(); if (Fval.endsWith('.mp3',true)){ var D=C.cloneNode(true); if (FCKBrowserInfo.IsIE){ D.setAttribute('scale',C.getAttribute('scale')); D.setAttribute('play',C.getAttribute('play')); D.setAttribute('loop',C.getAttribute('loop')); D.setAttribute('menu',C.getAttribute('menu')); }; var E=FCKDocumentProcessors_CreateFakeImage('FCK__MP3',D); E.setAttribute('_fckmp3','true',0); FCKFlashProcessor.RefreshView(E,C); C.parentNode.insertBefore(E,C); C.parentNode.removeChild(C); treated = true; }else if (Fval.search('/.flv&/')) { var D=C.cloneNode(true); if (FCKBrowserInfo.IsIE){ D.setAttribute('scale',C.getAttribute('scale')); D.setAttribute('play',C.getAttribute('play')); D.setAttribute('loop',C.getAttribute('loop')); D.setAttribute('menu',C.getAttribute('menu')); }; var E=FCKDocumentProcessors_CreateFakeImage('FCK__Video_flv',D); E.setAttribute('_fckVideo','true',0); FCKFlashProcessor.RefreshView(E,C); C.parentNode.insertBefore(E,C); C.parentNode.removeChild(C); treated = true; }else if ( Fval.search('/.avi&/') || Fval.search('/.mpg&/') || Fval.search('/.mpeg&/') || Fval.search('/.mov&/') || Fval.search('/.wmv&/') || Fval.search('/.rm&/')){ var D=C.cloneNode(true); if (FCKBrowserInfo.IsIE){ D.setAttribute('scale',C.getAttribute('scale')); D.setAttribute('play',C.getAttribute('play')); D.setAttribute('loop',C.getAttribute('loop')); D.setAttribute('menu',C.getAttribute('menu')); }; var E=FCKDocumentProcessors_CreateFakeImage('FCK__Video',D); E.setAttribute('_fckVideo','true',0); FCKFlashProcessor.RefreshView(E,C); C.parentNode.insertBefore(E,C); C.parentNode.removeChild(C); treated = true; }; } } } }; };So the problems are that:
- I'm not sure which part of the code actually gets the right tags out of the document when trying to guess the resource type
- This code still doesn't handle videos resizing correctly (the video disappears with as little as selecting it).