[MediaWiki-commits] [Gerrit] Make CSS transplantation in OO.ui.Frame actually wait for CSS - change (oojs/ui)

2013-11-25 Thread jenkins-bot (Code Review)
jenkins-bot has submitted this change and it was merged.

Change subject: Make CSS transplantation in OO.ui.Frame actually wait for CSS
..


Make CSS transplantation in OO.ui.Frame actually wait for CSS

Before e9ca44c86, there was code in place that waited for the CSS
to load and fired 'initialize' asynchronously. It was initially removed
because it was deemed unnecessary, but with later changes it has become
necessary again. The original approach also didn't work in Chrome.

This commit completely rewrites the CSS transplantation code to
correctly wait for CSS to be loaded before emitting 'initialize',
and to unbreak image URL references by no longer inlining same-origin
styles.

The new code transplants style tags directly, while link tags
are rewritten as style@import url(..); #foo { ... }/style. We then
insert a div id=foo into the document and wait for it to get styled,
which will only happen after the @import has finished. For the styling
of #foo we use font-family, because it allows us to set arbitrary
string values.

Additionally, we have to use visiblity: hidden; to hide windows
initially, because display: none; causes the iframe to not load in
Firefox. We reapply display: none; after the iframe initializes.

Bug: 56630
Change-Id: I76688a5ad7bd144c5e46064119f607060e76f0d9
---
M src/OO.ui.Frame.js
M src/OO.ui.Window.js
M src/styles/OO.ui.Window.css
3 files changed, 104 insertions(+), 61 deletions(-)

Approvals:
  Krinkle: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/src/OO.ui.Frame.js b/src/OO.ui.Frame.js
index 3c6fb32..6a761fe 100644
--- a/src/OO.ui.Frame.js
+++ b/src/OO.ui.Frame.js
@@ -42,6 +42,76 @@
  * @event initialize
  */
 
+/* Static Methods */
+
+/**
+ * Transplant the CSS styles from as parent document to a frame's document.
+ *
+ * This loops over the style sheets in the parent document, and copies their 
nodes to the
+ * frame's document. It then polls the document to see when all styles have 
loaded, and once they
+ * have, invokes the callback.
+ *
+ * For details of how we arrived at the strategy used in this function, see 
#load.
+ *
+ * @static
+ * @method
+ * @inheritable
+ * @param {HTMLDocument} parentDoc Document to transplant styles from
+ * @param {HTMLDocument} frameDoc Document to transplant styles to
+ * @param {Function} [callback] Callback to execute once styles have loaded
+ */
+OO.ui.Frame.static.transplantStyles = function ( parentDoc, frameDoc, callback 
) {
+   var i, numSheets, styleNode, newNode, timeout, pollNodeId, 
$pendingPollNodes,
+   $pollNodes = $( [] ),
+   // Fake font-family value
+   fontFamily = 'oo-ui-frame-transplantStyles-loaded';
+
+   for ( i = 0, numSheets = parentDoc.styleSheets.length; i  numSheets; 
i++ ) {
+   styleNode = parentDoc.styleSheets[i].ownerNode;
+   if ( callback  styleNode.nodeName.toLowerCase() === 'link' ) {
+   // External stylesheet
+   // Create a node with a unique ID that we're going to 
monitor to see when the CSS
+   // has loaded
+   pollNodeId = 'oo-ui-frame-transplantStyles-loaded-' + i;
+   $pollNodes = $pollNodes.add( $( 'div', frameDoc )
+   .attr( 'id', pollNodeId )
+   .appendTo( frameDoc.body )
+   );
+
+   // Add style@import url(...); #pollNodeId { 
font-family: ... }/style
+   // The font-family rule will only take effect once the 
@import finishes
+   newNode = frameDoc.createElement( 'style' );
+   newNode.textContent = '@import url(' + styleNode.href + 
');\n' +
+   '#' + pollNodeId + ' { font-family: ' + 
fontFamily + '; }';
+   } else {
+   // Not an external stylesheet, or no polling required; 
just copy the node over
+   newNode = frameDoc.importNode( styleNode, true );
+   }
+   frameDoc.head.appendChild( newNode );
+   }
+
+   if ( callback ) {
+   // Poll every 100ms until all external stylesheets have loaded
+   $pendingPollNodes = $pollNodes;
+   timeout = setTimeout( function pollExternalStylesheets() {
+   while (
+   $pendingPollNodes.length  0 
+   $pendingPollNodes.eq( 0 ).css( 'font-family' ) 
=== fontFamily
+   ) {
+   $pendingPollNodes = $pendingPollNodes.slice( 1 
);
+   }
+
+   if ( $pendingPollNodes.length === 0 ) {
+   // We're done!
+   $pollNodes.remove();
+   callback();
+  

[MediaWiki-commits] [Gerrit] Make CSS transplantation in OO.ui.Frame actually wait for CSS - change (oojs/ui)

2013-11-19 Thread Catrope (Code Review)
Catrope has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/96431


Change subject: Make CSS transplantation in OO.ui.Frame actually wait for CSS
..

Make CSS transplantation in OO.ui.Frame actually wait for CSS

Before e9ca44c86, there was code in place that waited for the CSS
to load and fired 'initialize' asynchronously. It was initially removed
because it was deemed unnecessary, but with later changes it has become
necessary again. The original approach also didn't work in Chrome.

This commit completely rewrites the CSS transplantation code to
correctly wait for CSS to be loaded before emitting 'initialize',
and to unbreak image URL references by no longer inlining same-origin
styles.

The new code transplants style tags directly, while link tags
are rewritten as style@import url(..); #foo { ... }/style. We then
insert a div id=foo into the document and wait for it to get styled,
which will only happen after the @import has finished. For the styling
of #foo we use font-family, because it allows us to set arbitrary
string values.

Additionally, we have to use visiblity: hidden; to hide windows
initially, because display: none; causes the iframe to not load in
Firefox. We reapply display: none; after the iframe initializes.

Bug: 56630
Change-Id: I76688a5ad7bd144c5e46064119f607060e76f0d9
---
M src/OO.ui.Frame.js
M src/OO.ui.Window.js
M src/styles/OO.ui.Window.css
3 files changed, 103 insertions(+), 61 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/oojs/ui refs/changes/31/96431/1

diff --git a/src/OO.ui.Frame.js b/src/OO.ui.Frame.js
index 3c6fb32..78146d4 100644
--- a/src/OO.ui.Frame.js
+++ b/src/OO.ui.Frame.js
@@ -42,6 +42,76 @@
  * @event initialize
  */
 
+/* Static Methods */
+
+/**
+ * Transplant the CSS styles from as parent document to a frame's document.
+ *
+ * This loops over the style sheets in the parent document, and copies their 
nodes to the
+ * frame's document. It then polls the document to see when all styles have 
loaded, and once they
+ * have, invokes the callback.
+ *
+ * For details of how we arrived at the strategy used in this function, see 
#load.
+ *
+ * @static
+ * @method
+ * @inheritable
+ * @param {HTMLDocument} parentDoc Document to transplant styles from
+ * @param {HTMLDocument} frameDoc Document to transplant styles to
+ * @param {Function} [callback] Callback to execute once styles have loaded
+ */
+OO.ui.Frame.static.transplantStyles = function ( parentDoc, frameDoc, callback 
) {
+   var i, numSheets, styleNode, newNode, timeout, pollNodeId,
+   $pollNodes = $( [] ),
+   // Fake font-family value
+   fontFamily = 'oo-ui-frame-transplantStyles-loaded';
+
+   for ( i = 0, numSheets = parentDoc.styleSheets.length; i  numSheets; 
i++ ) {
+   styleNode = parentDoc.styleSheets[i].ownerNode;
+   if ( callback  styleNode.nodeName.toLowerCase() === 'link' ) {
+   // External stylesheet
+   // Create a node with a unique ID that we're going to 
monitor to see when the CSS
+   // has loaded
+   pollNodeId = 'oo-ui-frame-transplantStyles-loaded-' + i;
+   $pollNodes = $pollNodes.add( $( 'div', frameDoc )
+   .attr( 'id', pollNodeId )
+   .appendTo( frameDoc.body )
+   );
+
+   // Add style@import url(...); #pollNodeId { 
font-family: ... }/style
+   // The font-family rule will only take effect once the 
@import finishes
+   newNode = frameDoc.createElement( 'style' );
+   newNode.textContent = '@import url(' + styleNode.href + 
');\n' +
+   '#' + pollNodeId + ' { font-family: ' + 
fontFamily + '; }';
+   } else {
+   // Not an external stylesheet, or no polling required; 
just copy the node over
+   newNode = frameDoc.importNode( styleNode, true );
+   }
+   frameDoc.head.appendChild( newNode );
+   }
+
+   if ( callback ) {
+   // Poll every 100ms until all external stylesheets have loaded
+   timeout = setTimeout( function pollExternalStylesheets() {
+   var i, len, doneLoading = true;
+   for ( i = 0, len = $pollNodes.length; i  len; i++ ) {
+   if ( $pollNodes.eq( i ).css( 'font-family' ) 
!== fontFamily ) {
+   // This one hasn't loaded yet
+   doneLoading = false;
+   break;
+   }
+   }
+
+   if ( doneLoading ) {
+   $pollNodes.remove();
+