jenkins-bot has submitted this change and it was merged.

Change subject: Really preserve dynamic state of widgets when infusing
......................................................................


Really preserve dynamic state of widgets when infusing

We missed the case where a parent (or ancestor) of an already-infused
widget with dynamic state is infused. Simplest example:

* HTML is:
  <div id="lay" class="oo-ui-fieldLayout ..." ...>
    <div id="wid" class="oo-ui-textInputWidget ..." ...>
      <input type="text" autofocus />
    </div>
  </div>

* Code is:
  // wid has focus now
  var wid = OO.ui.infuse( 'wid' ); // wid still has focus, this part works
  OO.ui.infuse( 'lay' ) // wid loses focus when its parent is infused

Follow-up to 4373c45db9f287696a2d246f458b142398ccfbe8.

I am really not sure about this now. As far as I can tell it works
correctly, but the code seems way too complex.

Bug: T106313
Change-Id: If07d40ada9ea809957107ce3c60203abf20b73ac
---
M src/Element.js
1 file changed, 28 insertions(+), 4 deletions(-)

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



diff --git a/src/Element.js b/src/Element.js
index 6b770a5..0d743a7 100644
--- a/src/Element.js
+++ b/src/Element.js
@@ -123,7 +123,7 @@
  */
 OO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) {
        // look for a cached result of a previous infusion.
-       var id, $elem, data, cls, parts, parent, obj, top, state;
+       var id, $elem, data, cls, parts, parent, obj, top, state, 
infusedChildren;
        if ( typeof idOrNode === 'string' ) {
                id = idOrNode;
                $elem = $( document.getElementById( id ) );
@@ -134,11 +134,27 @@
        if ( !$elem.length ) {
                throw new Error( 'Widget not found: ' + id );
        }
-       data = $elem.data( 'ooui-infused' ) || $elem[ 0 ].oouiInfused;
+       if ( $elem[ 0 ].oouiInfused ) {
+               $elem = $elem[ 0 ].oouiInfused;
+       }
+       data = $elem.data( 'ooui-infused' );
        if ( data ) {
                // cached!
                if ( data === true ) {
                        throw new Error( 'Circular dependency! ' + id );
+               }
+               if ( domPromise ) {
+                       // pick up dynamic state, like focus, value of form 
inputs, scroll position, etc.
+                       state = data.gatherPreInfuseState( $elem );
+                       // restore dynamic state after the new element is 
re-inserted into DOM under infused parent
+                       domPromise.done( data.restorePreInfuseState.bind( data, 
state ) );
+                       infusedChildren = $elem.data( 'ooui-infused-children' );
+                       if ( infusedChildren && infusedChildren.length ) {
+                               infusedChildren.forEach( function ( data ) {
+                                       var state = data.gatherPreInfuseState( 
$elem );
+                                       domPromise.done( 
data.restorePreInfuseState.bind( data, state ) );
+                               } );
+                       }
                }
                return data;
        }
@@ -191,10 +207,17 @@
        }
        $elem.data( 'ooui-infused', true ); // prevent loops
        data.id = id; // implicit
+       infusedChildren = [];
        data = OO.copy( data, null, function deserialize( value ) {
+               var infused;
                if ( OO.isPlainObject( value ) ) {
                        if ( value.tag ) {
-                               return OO.ui.Element.static.unsafeInfuse( 
value.tag, domPromise );
+                               infused = OO.ui.Element.static.unsafeInfuse( 
value.tag, domPromise );
+                               infusedChildren.push( infused );
+                               // Flatten the structure
+                               infusedChildren.push.apply( infusedChildren, 
infused.$element.data( 'ooui-infused-children' ) || [] );
+                               infused.$element.removeData( 
'ooui-infused-children' );
+                               return infused;
                        }
                        if ( value.html ) {
                                return new OO.ui.HtmlSnippet( value.html );
@@ -218,11 +241,12 @@
                        // This element is now gone from the DOM, but if anyone 
is holding a reference to it,
                        // let's allow them to OO.ui.infuse() it and do what 
they expect (T105828).
                        // Do not use jQuery.data(), as using it on detached 
nodes leaks memory in 1.x line by design.
-                       $elem[ 0 ].oouiInfused = obj;
+                       $elem[ 0 ].oouiInfused = obj.$element;
                }
                top.resolve();
        }
        obj.$element.data( 'ooui-infused', obj );
+       obj.$element.data( 'ooui-infused-children', infusedChildren );
        // set the 'data-ooui' attribute so we can identify infused widgets
        obj.$element.attr( 'data-ooui', '' );
        // restore dynamic state after the new element is inserted into DOM

-- 
To view, visit https://gerrit.wikimedia.org/r/231059
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: If07d40ada9ea809957107ce3c60203abf20b73ac
Gerrit-PatchSet: 6
Gerrit-Project: oojs/ui
Gerrit-Branch: master
Gerrit-Owner: Bartosz Dziewoński <[email protected]>
Gerrit-Reviewer: Bartosz Dziewoński <[email protected]>
Gerrit-Reviewer: Cscott <[email protected]>
Gerrit-Reviewer: Esanders <[email protected]>
Gerrit-Reviewer: Jforrester <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to