enyo.Control.absoluteShowing

I'm trying to use enyo.Control.absoluteShowing to improve performance in a mobile application by deferring some tasks, reflows, etc. for components that have already been instantiated and rendered into the DOM but are not currently showing. This is pretty similar to what absoluteShowing is used for by enyo.DataList, but I've ran into a little complication.

It seems when altering the showing state of a component, the onShowingChange event only waterfalls when a component changes from hidden, to showing. When altering a component from showing to hiding, however, propagation of the waterfalled event seems to be stopped.

I've done some looking around in the source and I'm pretty sure this can be solved by overriding enyo.Control.sendShowingChangedEvent, but that means I have to do that for every component in my application. Is there any recommended way to go about something like this?

Comments

  • As a little update, I've currently implemented the following mixin, which allows a control to defer tasks while it's not showing according to the absoluteShowing property.

    I'm currently duck-punching the enyo.Control prototype to work a bit different than the default. If anyone has suggestions on a cleaner way to do this, let me know.
    (function(enyo) {
    
        //* Override sendShowingChangedEvent to also send events when a view is
        //* being hidden.
        enyo.Control.prototype.sendShowingChangedEvent = function(wasShowing) {
            var isShowing = this.get("showing"),
                parent = this.parent;
    
            // Make sure that we don't trigger the waterfall when this method
            // is arbitrarily called during _create_.
            if (wasShowing !== true && wasShowing !== false) {
                return;
            }
    
            // We're only showing if our parent's are all showing as well.
            if (isShowing && parent) {
                isShowing = parent.getAbsoluteShowing(true);
            }
    
            this.waterfall("onShowingChanged", {
                originator: this,
                showing: isShowing
            });
        };
    
        //* Override showingChangedHandler to alter the event as needed
        enyo.Control.prototype.showingChangedHandler = function(inSender, inEvent) {
            // Don't propagate an event saying we're visible when the current
            // sub-tree is actually hidden.
            if (inEvent.showing && !this.getShowing()) {
                // Send new accurate event.
                this.sendShowingChangedEvent();
                return true;
            }
            // Proceed waterfalling as normal
            else {
                return false;
            }
        };
    
        hln.ui.AbsoluteShowingSupport = {
            name: "hln.ui.AbsoluteShowingSupport",
            importProps: enyo.inherit(function(sup) {
                return function() {
                    // Queued actions to execute when showing.
                    // Object of format { method: arguments }, where the method is
                    // defined on the current scope.
                    this._showingQueue = {};
                    sup.apply(this, arguments);
                };
            }),
            rendered: enyo.inherit(function(sup) {
                return function() {
                    this.set("absoluteShowing", this.getAbsoluteShowing({
                        ignoreBounds: true
                    }));
                    if (this.get("absoluteShowing")) {
                        this._removeFromShowingQueue("rendered", arguments);
                        sup.apply(this, arguments);
                    } else {
                        this._addToShowingQueue("rendered", arguments);
                    }
                };
            }),
            showingChangedHandler: enyo.inherit(function(sup) {
                return function(inSender, inEvent) {
                    // Valid state, set absoluteShowing and continue waterfall.
                    if (!sup.apply(this, arguments)) {
                        this.set("absoluteShowing", inEvent.showing);
                        return false;
                    }
                    // Invalid state, stop propagation.
                    return true;
                };
            }),
            absoluteShowingChanged: function() {
                if (this.get("absoluteShowing")) {
                    this.onAbsoluteShowing();
                } else {
                    // You can define a callback for tasks to execute when hiding.
                    (typeof foo == "function") && this.onAbsoluteHidden();
                }
            },
            // Execute queued tasks when showing
            onAbsoluteShowing: enyo.inherit(function(sup) {
                return function() {
                    var queue = this._showingQueue,
                        method;
    
                    sup.apply(this, arguments);
                    for (method in queue) {
                        this[method].apply(this, queue[method] || []);
                        delete queue[method];
                    }
                };
            }),
            _addToShowingQueue: function(method, args) {
                this._showingQueue[method] = args;
            },
            _removeFromShowingQueue: function(method) {
                delete this._showingQueue[method];
            }
        };
    }(enyo));
  • Have you taken a look at enyo.Control.extend()? :)
  • Actually, no I haven't. I'll go check it out, thanks.
Sign In or Register to comment.