Plugin creation is very closely related to DOM manipulation. TinyMCE has its own DOM API, but it is not nearly as comprehensive as the one provided by Prototype. Being used to walk the DOM with convenient methods like up and down, I hated TinyMCE for the lack of those.
As it turned out, you can't use Prototype methods while developing plugins for TinyMCE. Prototype correctly detects that Firefox 3 has implemented ElementExtensions and SpecificElementExtensions: that means Element.extend, used internally by dollar function, just returns the element, passing the stage of augmenting it with handy methods. The magic happens when designMode of document is set to 'On': Firefox doesn't apply these extensions to elements of such document. This results in awful behavior: you can't use Prototype methods on elements because Element.extend won't copy it to element thinking they are present (hey, Firefox already implemented them!), but the browser returns the elements untouched, just old plain HTMLElements.
My solution to this is a slightly different implementation of dollar function:
$t = (function() { var Methods = { }, ByTag = Element.Methods.ByTag; Object.extend(Methods, Element.Methods); Object.extend(Methods, Element.Methods.Simulated); var extend = function(element, force) { if (!element || (element._extendedByPrototype && !force) || element.nodeType != 1 || element == window) return element; var methods = Object.clone(Methods), tagName = element.tagName, property, value; if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); for (property in methods) { value = methods[property]; if (Object.isFunction(value) && !(property in element)) element[property] = value.methodize(); } element._extendedByPrototype = Prototype.emptyFunction; return element; } return extend; })();I gave it a different name because there is no need to override the dollar function: since the parent document of an iframe is not in designMode, it does the job properly most of the time. But in plugin development, usage of $t ensures the elements are extended with all the Prototype sugar. Sometimes (particularly, when you insert an extended element into another) the element loses its extended functions. I don't know why it happens. The workaround is the second parameter to $t, called force. This will force reaugmentation of an element disregarding the _extendedByPrototype property.
2 комментария:
This is wonderful sleuthing. Thanks for putting it on the web for all to share. I have a question, though: on line 17, you have a function call ("cl(property)"), though "cl" is undefined in this scope. Was this a typo, or am I missing something?
Oh, I'm sorry I forgot to delete that. This function, cl, is just a convenient alias for firebug's console.log.
I've updated the message so that future readers won't have troubles.
Отправить комментарий