/** * This class is the root stub for managing a `ViewModel`. * @private */Ext.define('Ext.app.bind.RootStub', { extend: 'Ext.app.bind.AbstractStub', requires: [ 'Ext.app.bind.LinkStub', 'Ext.app.bind.Stub' ], isRootStub: true, depth: 0, createRootChild: function (name, direct) { var me = this, owner = me.owner, ownerData = owner.getData(), children = me.children, previous = children && children[name], parentStub = previous ? null : me, parentVM, stub; if (direct || ownerData.hasOwnProperty(name) || !(parentVM = owner.getParent())) { stub = new Ext.app.bind.Stub(owner, name, parentStub); } else { stub = new Ext.app.bind.LinkStub(owner, name, parentStub); stub.link('{' + name + '}', parentVM); } if (previous) { previous.graft(stub); } return stub; }, createStubChild: function(name) { return this.createRootChild(name, true); }, descend: function (path, index) { var me = this, children = me.children, pos = index || 0, name = path[pos++], ret = (children && children[name]) || me.createRootChild(name); if (pos < path.length) { ret = ret.descend(path, pos); } return ret; }, getFullName: function () { return this.fullName || (this.fullName = this.owner.id + ':'); }, // The root Stub is associated with the owner's "data" object getDataObject: function () { return this.owner.data; }, getRawValue: function () { return this.owner.data; }, getValue: function () { return this.owner.data; }, isDescendantOf: function () { return false; }, set: function (value, preventClimb) { //<debug> if (!value || value.constructor !== Object) { Ext.raise('Only an object can be set at the root'); } //</debug> var me = this, children = me.children || (me.children = {}), owner = me.owner, data = owner.data, parentVM = owner.getParent(), stub, v, key, setSelf, created; for (key in value) { //<debug> if (key.indexOf('.') >= 0) { Ext.raise('Value names cannot contain dots'); } //</debug> // Setting the value. // Ensure the Stub exists for the name, and set its value. v = value[key]; if (v !== undefined) { stub = children[key]; setSelf = preventClimb || !me.shouldClimb(key); if (!stub) { stub = me.createRootChild(key, setSelf); created = true; } else if (setSelf && stub.isLinkStub && !stub.getLinkFormulaStub()) { stub = me.insertChild(key); } if (!created || !data.hasOwnProperty(value)) { owner.invalidateChildLinks(key); } stub.set(v, setSelf); } // Clearing the value. Delete the data item // Invalidate the Stub if it exists. else if (data.hasOwnProperty(key)) { delete data[key]; stub = children[key]; if (stub) { if (!stub.isLinkStub && parentVM) { stub = me.createRootChild(key); } owner.invalidateChildLinks(key, true); stub.invalidate(true); } } } }, schedule: Ext.emptyFn, unschedule: Ext.emptyFn, privates: { checkAvailability: function() { // Always available return true; }, insertChild: function(name) { return this.createRootChild(name, true); }, invalidateChildLink: function(name, clear) { var children = this.children, stub = children && children[name]; if (stub && stub.isLinkStub && !stub.getLinkFormulaStub()) { stub = this.createRootChild(name); if (clear) { stub.invalidate(true); } this.owner.invalidateChildLinks(name, clear); } }, shouldClimb: function(name) { var parent = this.owner.getParent(); while (parent) { if (parent.getData().hasOwnProperty(name)) { return true; } parent = parent.getParent(); } return false; } }});