resourceloader: Simplify CSS loading by removing IE8 hacks
authorOri Livneh <ori@wikimedia.org>
Sat, 18 Jun 2016 22:48:45 +0000 (15:48 -0700)
committerOri Livneh <ori@wikimedia.org>
Wed, 22 Jun 2016 16:05:19 +0000 (09:05 -0700)
* Remove 'isIEto9'. Since we blacklist anything before 9, isIE9 is enough.

* Set the content of style tags and the href attribute of link tags before
  inserting them into the DOM. Previously, we did DOM insertion first, due
  to T35305. I verified that IE9 is not affected.

* Use document.head instead of document.getElementsByTagName( 'head' )[ 0 ].

* Set / extend the contents of link tags via
  node.appendChild( document.createTextNode( ... ) ) this works in IE9, and
  adding CSS in this way does not strip @media queries in the way that
  repeat node.styleSheet.cssText += '...' operations will. This means the
  workarounds put in place to mitigate T108727 can be removed.
  quirksmode confirms that document.createTextNode() is supported in IE9,
  and mentions the issue with style tags as IE8-specific:
  http://quirksmode.org/dom/core/#t01

I created a test page with all the behaviors here:
https://people.wikimedia.org/~ori/If51f8303b/index.html

It loads correctly in IE9:
https://people.wikimedia.org/~ori/If51f8303b/screenshot.png

Change-Id: If51f8303b74fdc8001cfa20ea8b016fdc210b1b1

resources/src/mediawiki/mediawiki.js

index 1203b6a..348b617 100644 (file)
                                cssBuffer = '',
                                cssBufferTimer = null,
                                cssCallbacks = $.Callbacks(),
-                               isIEto9 = 'documentMode' in document && document.documentMode <= 9,
                                isIE9 = document.documentMode === 9;
 
                        function getMarker() {
                         */
                        function newStyleTag( text, nextNode ) {
                                var s = document.createElement( 'style' );
-                               // Support: IE
-                               // Must attach style element to the document before setting cssText (T35305)
+
+                               s.appendChild( document.createTextNode( text ) );
                                if ( nextNode && nextNode.parentNode ) {
                                        nextNode.parentNode.insertBefore( s, nextNode );
                                } else {
                                        document.getElementsByTagName( 'head' )[ 0 ].appendChild( s );
                                }
-                               if ( s.styleSheet ) {
-                                       // Support: IE6-10
-                                       // Old IE ignores appended text nodes, access stylesheet directly.
-                                       s.styleSheet.cssText = text;
-                               } else {
-                                       // Standard behaviour
-                                       s.appendChild( document.createTextNode( text ) );
-                               }
+
                                return s;
                        }
 
                         * @param {Function} [callback]
                         */
                        function addEmbeddedCSS( cssText, callback ) {
-                               var $style, styleEl, newCssText;
+                               var $style, styleEl;
 
                                function fireCallbacks() {
                                        var oldCallbacks = cssCallbacks;
                                //
                                // Support: IE 6-9
                                // Try to re-use existing <style> tags due to the IE stylesheet limit (T33676).
-                               if ( isIEto9 ) {
+                               if ( isIE9 ) {
                                        $style = $( getMarker() ).prev();
                                        // Verify that the element before the marker actually is a <style> tag created
                                        // by mw.loader (not some other style tag, or e.g. a <meta> tag).
                                        if ( $style.data( 'ResourceLoaderDynamicStyleTag' ) ) {
                                                styleEl = $style[ 0 ];
-                                               // Support: IE 6-10
-                                               if ( styleEl.styleSheet ) {
-                                                       try {
-                                                               // Support: IE 9
-                                                               // We can't do styleSheet.cssText += cssText in IE9 because it mangles cssText on
-                                                               // write (removes @media queries). If we read it and used its value, we'd
-                                                               // accidentally apply @media-specific styles to all media. (T108727)
-                                                               if ( isIE9 ) {
-                                                                       newCssText = $style.data( 'ResourceLoaderDynamicStyleTag' ) + cssText;
-                                                                       styleEl.styleSheet.cssText = newCssText;
-                                                                       $style.data( 'ResourceLoaderDynamicStyleTag', newCssText );
-                                                               } else {
-                                                                       styleEl.styleSheet.cssText += cssText;
-                                                               }
-                                                       } catch ( e ) {
-                                                               mw.track( 'resourceloader.exception', { exception: e, source: 'stylesheet' } );
-                                                       }
-                                               } else {
-                                                       styleEl.appendChild( document.createTextNode( cssText ) );
-                                               }
+                                               styleEl.appendChild( document.createTextNode( cssText ) );
                                                fireCallbacks();
                                                return;
                                        }
 
                                $style = $( newStyleTag( cssText, getMarker() ) );
 
-                               if ( isIEto9 ) {
-                                       if ( isIE9 ) {
-                                               $style.data( 'ResourceLoaderDynamicStyleTag', cssText );
-                                       } else {
-                                               $style.data( 'ResourceLoaderDynamicStyleTag', true );
-                                       }
+                               if ( isIE9 ) {
+                                       $style.data( 'ResourceLoaderDynamicStyleTag', true );
                                }
 
                                fireCallbacks();
                         */
                        function addLink( media, url ) {
                                var el = document.createElement( 'link' );
-                               // Support: IE
-                               // Insert in document *before* setting href
-                               $( getMarker() ).before( el );
+
                                el.rel = 'stylesheet';
                                if ( media && media !== 'all' ) {
                                        el.media = media;
                                // If you end up here from an IE exception "SCRIPT: Invalid property value.",
                                // see #addEmbeddedCSS, bug 31676, and bug 47277 for details.
                                el.href = url;
+
+                               $( getMarker() ).before( el );
                        }
 
                        /**