messengercustom-servicesmacoslinuxwindowsinboxwhatsappicloudtweetdeckhipchattelegramhangoutsslackgmailskypefacebook-workplaceoutlookemailmicrosoft-teamsdiscord
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
383 lines
11 KiB
383 lines
11 KiB
/** |
|
* @private |
|
* @class Ext.app.bindinspector.Environment |
|
*/ |
|
Ext.define('Ext.app.bindinspector.Environment', { |
|
requires: [ |
|
'Ext.util.Collection' |
|
], |
|
|
|
/* |
|
** Utility methods |
|
*/ |
|
getCmp: function(id) { |
|
return this.components.get(id); |
|
}, |
|
|
|
getVM: function(id) { |
|
return this.viewModels.get(id); |
|
}, |
|
|
|
getInheritedVM: function(comp) { |
|
var vm = comp.viewModel, |
|
parent = comp.parent; |
|
|
|
if (vm) { |
|
return vm; |
|
} |
|
|
|
if (parent) { |
|
return this.getInheritedVM(this.getCmp(parent)); |
|
} |
|
|
|
return null; |
|
}, |
|
|
|
|
|
/* |
|
** Capture methods |
|
*/ |
|
|
|
captureSnapshot: function() { |
|
var all = Ext.ComponentManager.getAll(), |
|
len = all.length, |
|
components = [], |
|
i, comp; |
|
|
|
this.models = {}; |
|
for (i = 0; i < len; ++i) { |
|
comp = all[i]; |
|
// afterRender check is a hack for now |
|
if (comp.afterRender && this.isRootComponent(comp)) { |
|
components.push(this.buildComponent(comp)); |
|
} |
|
} |
|
|
|
return { |
|
isBindData: true, |
|
version: Ext.getVersion().version, |
|
models: this.models, |
|
components: components |
|
}; |
|
}, |
|
|
|
serializeModel: function(Model) { |
|
var models = this.models, |
|
name = Model.entityName; |
|
|
|
if (!models[name]) { |
|
models[name] = Ext.Array.map(Model.getFields(), function(field) { |
|
return { |
|
name: field.getName(), |
|
type: field.getType() |
|
}; |
|
}); |
|
} |
|
}, |
|
|
|
isRootComponent: function(c) { |
|
var owner = c.getRefOwner(); |
|
if (owner || c.isBindInspector || c === Ext.MessageBox || c.is('quicktip')) { |
|
return false; |
|
} |
|
return true; |
|
}, |
|
|
|
buildComponent: function(comp) { |
|
var childItems = comp.getRefItems ? comp.getRefItems() : null, |
|
viewModel = comp.getViewModel(), |
|
bind = comp.getBind(), |
|
id = comp.id, |
|
len, i, o, |
|
child; |
|
|
|
if (bind) { |
|
bind = this.buildBind(bind); |
|
} |
|
o = { |
|
id: id, |
|
xtype: comp.getXType(), |
|
publishes: comp.getPublishes(), |
|
viewModel: viewModel ? this.buildViewModel(viewModel, comp) : null, |
|
bindings: bind || null, |
|
reference: comp.reference || null, |
|
items: [] |
|
}; |
|
|
|
if (childItems) { |
|
for (i = 0, len = childItems.length; i < len; ++i) { |
|
if (childItems[i].afterRender) { |
|
child = this.buildComponent(childItems[i]); |
|
child.parent = id; |
|
o.items.push(child); |
|
} |
|
} |
|
} |
|
return o; |
|
}, |
|
|
|
buildBind: function(bind) { |
|
var out = {}, |
|
key, o, bindInfo, name, stub; |
|
|
|
for (key in bind) { |
|
o = bind[key]; |
|
stub = o.stub; |
|
bindInfo = { |
|
id: o.id, |
|
value: this.serializeValue(o.getRawValue()), |
|
stub: stub ? { |
|
id: stub.id, |
|
name: stub.name |
|
} : null |
|
}; |
|
if (o.isTemplateBinding) { |
|
bindInfo.isTemplateBinding = true; |
|
bindInfo.tokens = []; |
|
Ext.Array.forEach(o.tokens, function(token) { |
|
bindInfo.tokens.push(token.split('.')); |
|
}, this); |
|
bindInfo.descriptor = o.tpl.text; |
|
} else if (o.isMultiBinding) { |
|
bindInfo.isMultiBinding = true; |
|
// TODO: |
|
} else { |
|
if (stub) { |
|
name = this.buildStubName(stub); |
|
bindInfo.tokens = name.split('.'); |
|
bindInfo.descriptor = '{' + name + '}'; |
|
} |
|
} |
|
out[key] = bindInfo; |
|
} |
|
return out; |
|
}, |
|
|
|
buildStubName: function(stub) { |
|
var parent = stub.parent, |
|
name = ''; |
|
|
|
if (parent && !parent.isRootStub) { |
|
name = this.buildStubName(parent) + '.'; |
|
} |
|
return name + stub.name; |
|
}, |
|
|
|
buildViewModel: function(vm, comp) { |
|
var parent = vm.getParent(); |
|
return { |
|
id: vm.getId(), |
|
view: comp.id, |
|
parent: parent ? parent.getId() : null, |
|
data: this.serializeValue(vm.getData(), true), |
|
rootStub: this.buildStub(vm.getRoot()) |
|
}; |
|
}, |
|
|
|
buildStub: function(stub, isLinkChild) { |
|
var o = {}, |
|
children = stub.children, |
|
isLink = stub.isLinkStub, |
|
outChildren = {}, |
|
key, hasAny, child, sameTarget; |
|
|
|
if (!stub.isRootStub) { |
|
o.name = stub.name; |
|
o.parent = stub.parent ? stub.parent.id : null; |
|
o.isLoading = stub.isLoading(); |
|
o.bindCount = (stub.bindings && stub.bindings.length) || 0; |
|
o.cumulativeBindCount = o.bindCount; |
|
o.value = this.serializeValue(stub.getRawValue()); |
|
if (isLink) { |
|
sameTarget = stub.target === stub.owner; |
|
o.linkInfo = { |
|
sameTarget: sameTarget, |
|
descriptor: stub.linkDescriptor, |
|
value: this.serializeValue(stub.binding.getValue()) |
|
}; |
|
isLinkChild = true; |
|
} |
|
} else { |
|
o.name = ''; |
|
o.isLoading = false; |
|
o.bindCount = o.cumulativeBindCount = 0; |
|
} |
|
|
|
if (children) { |
|
for (key in children) { |
|
hasAny = true; |
|
child = this.buildStub(children[key], isLinkChild); |
|
outChildren[key] = child; |
|
o.cumulativeBindCount += child.cumulativeBindCount; |
|
} |
|
} |
|
|
|
if (hasAny) { |
|
o.children = outChildren; |
|
} |
|
return o; |
|
}, |
|
|
|
createModel: function(entityName, data) { |
|
var Model = Ext.app.bindinspector.noconflict[entityName]; |
|
return new Model(data); |
|
}, |
|
|
|
unpackSnapshot: function(data) { |
|
this.components = new Ext.util.Collection(); |
|
this.viewModels = new Ext.util.Collection(); |
|
|
|
Ext.Object.each(data.models, function(key, fields) { |
|
Ext.define('Ext.app.bindinspector.noconflict.' + key, { |
|
extend: 'Ext.app.bindinspector.noconflict.BaseModel', |
|
fields: fields |
|
}); |
|
}); |
|
|
|
Ext.Array.forEach(data.components, function(comp) { |
|
this.unpackComponent(comp, this.components, this.viewModels); |
|
}, this); |
|
this.rootComponents = data.components; |
|
}, |
|
|
|
unpackComponent: function(comp, allComponents, allViewModels) { |
|
var vm = comp.viewModel, |
|
items = comp.items, |
|
bindings = comp.bindings, |
|
len, i, |
|
parentVM, |
|
parentData, data, key, binding; |
|
|
|
allComponents.add(comp); |
|
|
|
if (bindings) { |
|
for (key in bindings) { |
|
binding = bindings[key]; |
|
binding.value = this.deserializeValue(binding.value); |
|
} |
|
} |
|
|
|
if (vm) { |
|
allViewModels.add(vm); |
|
parentVM = this.getVM(vm.parent); |
|
if (parentVM) { |
|
parentData = Ext.Object.chain(parentVM.data); |
|
} |
|
data = this.deserializeValue(vm.data); |
|
if (parentData) { |
|
data = Ext.apply(parentData, data); |
|
} |
|
vm.data = data; |
|
this.deserializeStub(vm.rootStub); |
|
} |
|
|
|
if (items) { |
|
for (i = 0, len = items.length; i < len; ++i) { |
|
this.unpackComponent(items[i], allComponents, allViewModels); |
|
} |
|
} |
|
}, |
|
|
|
serializeValue: function(value, checkHasOwn) { |
|
var info = {}, |
|
type, key, item, childInfo, model; |
|
|
|
if (value && value.constructor === Object) { |
|
type = 'object'; |
|
info.value = {}; |
|
for (key in value) { |
|
if (!(checkHasOwn && !value.hasOwnProperty(key))) { |
|
childInfo = this.serializeValue(value[key], checkHasOwn); |
|
item = { |
|
type: childInfo.type, |
|
value: childInfo.value |
|
}; |
|
if (childInfo.entityName) { |
|
item.entityName = childInfo.entityName; |
|
} |
|
info.value[key] = item; |
|
} |
|
} |
|
} else if (value && value.isModel) { |
|
type = 'model'; |
|
info.entityName = value.entityName; |
|
this.serializeModel(value.self); |
|
info.value = this.serializeValue(value.data); |
|
} else if (value && value.isStore) { |
|
type = 'store'; |
|
model = value.getModel(); |
|
info.entityName = model.entityName; |
|
if (model.entityName) { |
|
this.serializeModel(model); |
|
} |
|
} else if (Ext.isDate(value)) { |
|
type = 'date'; |
|
info.value = Ext.Date.format(value, 'c'); |
|
} else if (Ext.isArray(value)) { |
|
type = 'array'; |
|
info.value = []; |
|
Ext.Array.forEach(value, function(item) { |
|
info.value.push(this.serializeValue(item)); |
|
}, this); |
|
} else { |
|
type = Ext.typeOf(value); |
|
info.value = value; |
|
} |
|
info.type = type; |
|
return info; |
|
}, |
|
|
|
deserializeValue: function(info) { |
|
var type = info.type, |
|
raw = info.value, |
|
out, key; |
|
|
|
if (type === 'null') { |
|
out = null; |
|
} else if (type === 'undefined') { |
|
out = undefined; |
|
} else if (type === 'string' || type === 'boolean' || type === 'number') { |
|
out = raw; |
|
} else if (type === 'date') { |
|
out = Ext.Date.parse(raw, 'c'); |
|
} else if (type === 'object') { |
|
out = {}; |
|
for (key in raw) { |
|
out[key] = this.deserializeValue(raw[key]); |
|
} |
|
} else if (type === 'model') { |
|
out = this.createModel(info.entityName, this.deserializeValue(raw)); |
|
} else if (type === 'store') { |
|
out = { |
|
isStore: true, |
|
entityName: info.entityName |
|
}; |
|
} else if (type === 'array') { |
|
out = []; |
|
Ext.Array.forEach(raw, function(item) { |
|
out.push(this.deserializeValue(item)); |
|
}, this); |
|
} |
|
return out; |
|
}, |
|
|
|
deserializeStub: function(stub) { |
|
var children = stub.children, |
|
linkInfo = stub.linkInfo, |
|
key; |
|
|
|
if (stub.value) { |
|
stub.value = this.deserializeValue(stub.value); |
|
} |
|
|
|
if (linkInfo) { |
|
linkInfo.value = this.deserializeValue(linkInfo.value); |
|
} |
|
|
|
if (children) { |
|
for (key in children) { |
|
this.deserializeStub(children[key]); |
|
} |
|
} |
|
} |
|
}); |