diff options
author | Krinkle <krinkle@users.mediawiki.org> | 2012-02-24 23:22:30 +0000 |
---|---|---|
committer | Krinkle <krinkle@users.mediawiki.org> | 2012-02-24 23:22:30 +0000 |
commit | 57dda2b95e0997165dcc6eba83e5aa101bd10b51 (patch) | |
tree | 31b334896d029eba81386be88be5da966fe53dee /resources/mediawiki | |
parent | 829e60f1bd6ff30e7e863bcaa851a1f52508bea3 (diff) | |
download | mediawikicore-57dda2b95e0997165dcc6eba83e5aa101bd10b51.tar.gz mediawikicore-57dda2b95e0997165dcc6eba83e5aa101bd10b51.zip |
[mw.loader] Refactor addInlineCSS's logic, fixing various bugs
* Using mw.util.addCSS as base to instance of bug 33305 automatically
* Expose as mw.loader.addStyleTag
* Re-use the code in mw.util.addCSS
* Drop the "text > Cdata > element > jQuery object > innerHTML", in favor of setting cssText or appending a text node (html escapement isn't a problem when working with text nodes directly).
* Appending this way also works in IE, no need for the dispose/re-create style-tag logic in the try-catch().
* Follows-up r110988 (fixme)
Notes
Notes:
http://mediawiki.org/wiki/Special:Code/MediaWiki/112370
Diffstat (limited to 'resources/mediawiki')
-rw-r--r-- | resources/mediawiki/mediawiki.js | 76 | ||||
-rw-r--r-- | resources/mediawiki/mediawiki.util.js | 27 |
2 files changed, 61 insertions, 42 deletions
diff --git a/resources/mediawiki/mediawiki.js b/resources/mediawiki/mediawiki.js index 2ed894e19bed..c0e2fdd4e145 100644 --- a/resources/mediawiki/mediawiki.js +++ b/resources/mediawiki/mediawiki.js @@ -389,41 +389,57 @@ var mw = ( function ( $, undefined ) { return $marker; } } - + + /** + * Create a new style tag and add it to the DOM. + * + * @param text String: CSS text + * @param $nextnode mixed: [optional] An Element or jQuery object for an element where + * the style tag should be inserted before. Otherwise appended to the <head>. + * @return HTMLStyleElement + */ + function addStyleTag( text, $nextnode ) { + var s = document.createElement( 'style' ); + s.type = 'text/css'; + s.rel = 'stylesheet'; + // Insert into document before setting cssText (bug 33305) + if ( $nextnode ) { + // If a raw element, create a jQuery object, otherwise use directly + if ( $nextnode.nodeType ) { + $nextnode = $( $nextnode ); + } + $nextnode.before( s ); + } else { + document.getElementsByTagName('head')[0].appendChild( s ); + } + if ( s.styleSheet ) { + s.styleSheet.cssText = text; // IE + } else { + // Safari sometimes borks on null + s.appendChild( document.createTextNode( String( text ) ) ); + } + return s; + } + function addInlineCSS( css, media ) { - var $style = getMarker().prev(), - $newStyle, - attrs = { 'type': 'text/css', 'media': media }; + var $style, style, $newStyle; + $style = getMarker().prev(); if ( $style.is( 'style' ) && $style.data( 'ResourceLoaderDynamicStyleTag' ) === true ) { - // There's already a dynamic <style> tag present, append to it - // This recycling of <style> tags is for bug 31676 (can't have - // more than 32 <style> tags in IE) - - // Also, calling .append() on a <style> tag explodes with a JS error in IE, - // so if the .append() fails we fall back to building a new <style> tag and - // replacing the existing one - try { - // Do cdata sanitization on the provided CSS, and prepend a double newline - css = $( mw.html.element( 'style', {}, new mw.html.Cdata( "\n\n" + css ) ) ).html(); - $style.append( css ); - } catch ( e ) { - // Generate a new tag with the combined CSS - css = $style.html() + "\n\n" + css; - $newStyle = $( mw.html.element( 'style', attrs, new mw.html.Cdata( css ) ) ) - .data( 'ResourceLoaderDynamicStyleTag', true ); - // Prevent a flash of unstyled content by inserting the new tag - // before removing the old one - $style.after( $newStyle ); - $style.remove(); + // There's already a dynamic <style> tag present, append to it. This recycling of + // <style> tags is for bug 31676 (can't have more than 32 <style> tags in IE) + style = $style.get( 0 ); + if ( style.styleSheet ) { + style.styleSheet.cssText += css; // IE + } else { + style.appendChild( document.createTextNode( String( css ) ) ); } } else { - // Create a new <style> tag and insert it - $style = $( mw.html.element( 'style', attrs, new mw.html.Cdata( css ) ) ); - $style.data( 'ResourceLoaderDynamicStyleTag', true ); - getMarker().before( $style ); + $newStyle = $( addStyleTag( css, getMarker() ) ) + .attr( 'media', media ) + .data( 'ResourceLoaderDynamicStyleTag', true ); } } - + function compare( a, b ) { var i; if ( a.length !== b.length ) { @@ -874,6 +890,8 @@ var mw = ( function ( $, undefined ) { /* Public Methods */ return { + addStyleTag: addStyleTag, + /** * Requests dependencies from server, loading and executing when things when ready. */ diff --git a/resources/mediawiki/mediawiki.util.js b/resources/mediawiki/mediawiki.util.js index 277b19457cfb..6edbe5d1d7b8 100644 --- a/resources/mediawiki/mediawiki.util.js +++ b/resources/mediawiki/mediawiki.util.js @@ -149,23 +149,24 @@ }, /** - * Append a new style block to the head + * Append a new style block to the head and return the CSSStyleSheet object. + * Use .ownerNode to access the <style> element, or use mw.loader.addStyleTag. + * This function returns the styleSheet object for convience (due to cross-browsers + * difference as to where it is located). + * @example + * <code> + * var sheet = mw.util.addCSS('.foobar { display: none; }'); + * $(foo).click(function () { + * // Toggle the sheet on and off + * sheet.disabled = !sheet.disabled; + * }); + * </code> * * @param text string CSS to be appended - * @return CSSStyleSheet + * @return CSSStyleSheet (use .ownerNode to get to the <style> element) */ addCSS: function ( text ) { - var s = document.createElement( 'style' ); - s.type = 'text/css'; - s.rel = 'stylesheet'; - // Insert into document before setting cssText (bug 33305) - document.getElementsByTagName('head')[0].appendChild( s ); - if ( s.styleSheet ) { - s.styleSheet.cssText = text; // IE - } else { - // Safari sometimes borks on null - s.appendChild( document.createTextNode( String( text ) ) ); - } + var s = mw.loader.addStyleTag( text ); return s.sheet || s; }, |