Wednesday, December 4, 2013

YUI2 Rich text editor and IE11


Doesn't work so much.  Editor uses a (slightly modified) version of the YAHOO.env.ua object internally.  This doesn't recognise IE11 because they've got rid of the MSIE string in the user agent.

The patch is in the browser property of editor:

+            if (navigator.userAgent.indexOf('Trident/7') !== -1) {
+                //rv:11.0)
+                try {
+                    br.ie = parseFloat(navigator.userAgent.match(/rv:([\d\.]+)\
+                } catch (e) {}
+
+            }



Trident is the 'IE', rv:11.0 is the version.

It all seems to work again after this.  The UA sniffs that were needed before still appear to be required.

Goodbye, afternoon, tracking that down and checking it all...

Update

OK, not quite.  That was part of it, but there's some other goodies too.  The MS changes page here lists some of the changes, though not sure it's all of them.

Firstly, selection has changed (http://msdn.microsoft.com/en-us/library/ie/ff975315(v=vs.85).aspx) - it now implements IHTMLSelection. In editor's getRange method there's a check for IE:

            if (this.browser.ie) {
                try {
                    return sel.createRange();
                } catch (e2) {
                    return null;
                }
            }

            if (sel.rangeCount > 0) {
                return sel.getRangeAt(0);
            }
            return null;

createRange() doesn't exist in IE11, but sel.rangeCount and sel.getRangeAt() do, so we can patch with:

            if (this.browser.ie && this.browser.ie < 11) {
                try {
                    return sel.createRange();
                } catch (e2) {
                    return null;
                }
            }

            if (sel.rangeCount > 0) {
                return sel.getRangeAt(0);
            }
            return null;


Secondly, something about readystate has changed, although I'm not quite clear how this works it's way through to the editor exactly, but it's a problem.  In Editor's _checkLoaded() method, we have:

            try {
                if (this._getDoc() && this._getDoc().body) {
                    if (this.browser.ie) {
                        if (this._getDoc().body.readyState == 'complete') {
                            init = true;
                        }
                    } else {
                        if (this._getDoc().body._rteLoaded === true) {
                            init = true;
                        }
                    }
                }
            }

But this._getDoc().body.readyState never seems to happen, (while _rteLoaded does), so the Editor never gets init-ed.  Again, changing this to

            try {
                if (this._getDoc() && this._getDoc().body) {
                    if (this.browser.ie && this.browser.ie < 11) {
                        if (this._getDoc().body.readyState == 'complete') {
                            init = true;
                        }
                    } else {
                        if (this._getDoc().body._rteLoaded === true) {
                            init = true;
                        }
                    }
                }
            }

(note the version number) seems to fix it.

Finally, it seems like window.event has gone, which breaks _getSelectedElement().  Again, changing

        _getSelectedElement: function() {
            var doc = this._getDoc(),
                range = null,
                sel = null,
                elm = null,
                check = true;

            if (this.browser.ie) {
                this.currentEvent = this._getWindow().event; //Event utility assumes window.event, so we need to reset it to this._getWindow().event;
                range = this._getRange();
to


        _getSelectedElement: function() {
            var doc = this._getDoc(),
                range = null,
                sel = null,
                elm = null,
                check = true;

            if (this.browser.ie && this.browser.ie < 11) {
                this.currentEvent = this._getWindow().event; //Event utility assumes window.event, so we need to reset it to this._getWindow().event;
                range = this._getRange();


fixes it for us.


Incidentally, I also moved the original patch at the top of this page out of Editor's browser property to update YAHOO.env.ua:

if (YAHOO.env.ua.ie === 0 && navigator.userAgent.indexOf('Trident/7') !== -1) {
    // version is in a string like this: rv:11.0)
    try {
        YAHOO.env.ua.ie = parseFloat(navigator.userAgent.match(/rv:([\d\.]+)\)/)[1]);
    } catch (e) {}
 }

No comments:

Post a Comment