<!DOCTYPE html>
|
<html>
|
<head>
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
<title>The source code</title>
|
<link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
|
<script type="text/javascript" src="../resources/prettify/prettify.js"></script>
|
<style type="text/css">
|
.highlight { display: block; background-color: #ddd; }
|
</style>
|
<script type="text/javascript">
|
function highlight() {
|
document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
|
}
|
</script>
|
</head>
|
<body onload="prettyPrint(); highlight();">
|
<pre class="prettyprint lang-js"><span id='Ext-util-ElementContainer'>/**
|
</span> * This mixin enables classes to declare relationships to child elements and provides the
|
* mechanics for acquiring the {@link Ext.Element elements} and storing them on an object
|
* instance as properties.
|
*
|
* This class is used by {@link Ext.Component components} and {@link Ext.layout.container.Container container layouts} to
|
* manage their child elements.
|
*
|
* A typical component that uses these features might look something like this:
|
*
|
* Ext.define('Ext.ux.SomeComponent', {
|
* extend: 'Ext.Component',
|
*
|
* childEls: [
|
* 'bodyEl'
|
* ],
|
*
|
* renderTpl: [
|
* '<div id="{id}-bodyEl"></div>'
|
* ],
|
*
|
* // ...
|
* });
|
*
|
* The `childEls` array lists one or more relationships to child elements managed by the
|
* component. The items in this array can be either of the following types:
|
*
|
* - String: the id suffix and property name in one. For example, "bodyEl" in the above
|
* example means a "bodyEl" property will be added to the instance with the result of
|
* {@link Ext#get} given "componentId-bodyEl" where "componentId" is the component instance's
|
* id.
|
* - Object: with a `name` property that names the instance property for the element, and
|
* one of the following additional properties:
|
* - `id`: The full id of the child element.
|
* - `itemId`: The suffix part of the id to which "componentId-" is prepended.
|
* - `select`: A selector that will be passed to {@link Ext#select}.
|
* - `selectNode`: A selector that will be passed to {@link Ext.DomQuery#selectNode}.
|
*
|
* The example above could have used this instead to achieve the same result:
|
*
|
* childEls: [
|
* { name: 'bodyEl', itemId: 'bodyEl' }
|
* ]
|
*
|
* When using `select`, the property will be an instance of {@link Ext.CompositeElement}. In
|
* all other cases, the property will be an {@link Ext.Element} or `null` if not found.
|
*
|
* Care should be taken when using `select` or `selectNode` to find child elements. The
|
* following issues should be considered:
|
*
|
* - Performance: using selectors can be slower than id lookup by a factor 10x or more.
|
* - Over-selecting: selectors are applied after the DOM elements for all children have
|
* been rendered, so selectors can match elements from child components (including nested
|
* versions of the same component) accidentally.
|
*
|
* This above issues are most important when using `select` since it returns multiple
|
* elements.
|
*
|
* **IMPORTANT**
|
* Unlike a `renderTpl` where there is a single value for an instance, `childEls` are aggregated
|
* up the class hierarchy so that they are effectively inherited. In other words, if a
|
* class where to derive from `Ext.ux.SomeComponent` in the example above, it could also
|
* have a `childEls` property in the same way as `Ext.ux.SomeComponent`.
|
*
|
* Ext.define('Ext.ux.AnotherComponent', {
|
* extend: 'Ext.ux.SomeComponent',
|
*
|
* childEls: [
|
* // 'bodyEl' is inherited
|
* 'innerEl'
|
* ],
|
*
|
* renderTpl: [
|
* '<div id="{id}-bodyEl">'
|
* '<div id="{id}-innerEl"></div>'
|
* '</div>'
|
* ],
|
*
|
* // ...
|
* });
|
*
|
* The `renderTpl` contains both child elements and unites them in the desired markup, but
|
* the `childEls` only contains the new child element. The {@link #applyChildEls} method
|
* takes care of looking up all `childEls` for an instance and considers `childEls`
|
* properties on all the super classes and mixins.
|
*
|
* @private
|
*/
|
Ext.define('Ext.util.ElementContainer', {
|
|
<span id='Ext-util-ElementContainer-property-childEls'> childEls: [
|
</span> // empty - this solves a couple problems:
|
// 1. It ensures that all classes have a childEls (avoid null ptr)
|
// 2. It prevents mixins from smashing on their own childEls (these are gathered
|
// specifically)
|
],
|
|
<span id='Ext-util-ElementContainer-method-constructor'> constructor: function () {
|
</span> var me = this,
|
childEls;
|
|
// if we have configured childEls, we need to merge them with those from this
|
// class, its bases and the set of mixins...
|
if (me.hasOwnProperty('childEls')) {
|
childEls = me.childEls;
|
delete me.childEls;
|
|
me.addChildEls.apply(me, childEls);
|
}
|
},
|
|
<span id='Ext-util-ElementContainer-method-destroy'> destroy: function () {
|
</span> var me = this,
|
childEls = me.getChildEls(),
|
child, childName, i, k;
|
|
for (i = childEls.length; i--; ) {
|
childName = childEls[i];
|
if (typeof childName != 'string') {
|
childName = childName.name;
|
}
|
|
child = me[childName];
|
if (child) {
|
me[childName] = null; // better than delete since that changes the "shape"
|
child.remove();
|
}
|
}
|
},
|
|
<span id='Ext-util-ElementContainer-method-addChildEls'> /**
|
</span> * Adds each argument passed to this method to the {@link Ext.AbstractComponent#cfg-childEls childEls} array.
|
*/
|
addChildEls: function () {
|
var me = this,
|
args = arguments;
|
|
if (me.hasOwnProperty('childEls')) {
|
me.childEls.push.apply(me.childEls, args);
|
} else {
|
me.childEls = me.getChildEls().concat(Array.prototype.slice.call(args));
|
}
|
|
me.prune(me.childEls, false);
|
},
|
|
<span id='Ext-util-ElementContainer-method-applyChildEls'> /**
|
</span> * Sets references to elements inside the component.
|
* @private
|
*/
|
applyChildEls: function(el, id) {
|
var me = this,
|
childEls = me.getChildEls(),
|
baseId, childName, i, selector, value;
|
|
baseId = (id || me.id) + '-';
|
for (i = childEls.length; i--; ) {
|
childName = childEls[i];
|
|
if (typeof childName == 'string') {
|
// We don't use Ext.get because that is 3x (or more) slower on IE6-8. Since
|
// we know the el's are children of our el we use getById instead:
|
value = el.getById(baseId + childName);
|
} else {
|
if ((selector = childName.select)) {
|
value = Ext.select(selector, true, el.dom); // a CompositeElement
|
} else if ((selector = childName.selectNode)) {
|
value = Ext.get(Ext.DomQuery.selectNode(selector, el.dom));
|
} else {
|
// see above re:getById...
|
value = el.getById(childName.id || (baseId + childName.itemId));
|
}
|
|
childName = childName.name;
|
}
|
|
me[childName] = value;
|
}
|
},
|
|
<span id='Ext-util-ElementContainer-method-getChildEls'> getChildEls: function () {
|
</span> var me = this,
|
self;
|
|
// If an instance has its own childEls, that is the complete set:
|
if (me.hasOwnProperty('childEls')) {
|
return me.childEls;
|
}
|
|
// Typically, however, the childEls is a class-level concept, so check to see if
|
// we have cached the complete set on the class:
|
self = me.self;
|
return self.$childEls || me.getClassChildEls(self);
|
},
|
|
<span id='Ext-util-ElementContainer-method-getClassChildEls'> getClassChildEls: function (cls) {
|
</span> var me = this,
|
result = cls.$childEls,
|
childEls, i, length, forked, mixin, mixins, name, parts, proto, supr, superMixins;
|
|
if (!result) {
|
// We put the various childEls arrays into parts in the order of superclass,
|
// new mixins and finally from cls. These parts can be null or undefined and
|
// we will skip them later.
|
|
supr = cls.superclass;
|
if (supr) {
|
supr = supr.self;
|
parts = [supr.$childEls || me.getClassChildEls(supr)]; // super+mixins
|
superMixins = supr.prototype.mixins || {};
|
} else {
|
parts = [];
|
superMixins = {};
|
}
|
|
proto = cls.prototype;
|
mixins = proto.mixins; // since we are a mixin, there will be at least us
|
for (name in mixins) {
|
if (mixins.hasOwnProperty(name) && !superMixins.hasOwnProperty(name)) {
|
mixin = mixins[name].self;
|
parts.push(mixin.$childEls || me.getClassChildEls(mixin));
|
}
|
}
|
|
parts.push(proto.hasOwnProperty('childEls') && proto.childEls);
|
|
for (i = 0, length = parts.length; i < length; ++i) {
|
childEls = parts[i];
|
if (childEls && childEls.length) {
|
if (!result) {
|
result = childEls;
|
} else {
|
if (!forked) {
|
forked = true;
|
result = result.slice(0);
|
}
|
result.push.apply(result, childEls);
|
}
|
}
|
}
|
|
cls.$childEls = result = (result ? me.prune(result, !forked) : []);
|
}
|
|
return result;
|
},
|
|
<span id='Ext-util-ElementContainer-method-prune'> prune: function (childEls, shared) {
|
</span> var index = childEls.length,
|
map = {},
|
name;
|
|
while (index--) {
|
name = childEls[index];
|
if (typeof name != 'string') {
|
name = name.name;
|
}
|
|
if (!map[name]) {
|
map[name] = 1;
|
} else {
|
if (shared) {
|
shared = false;
|
childEls = childEls.slice(0);
|
}
|
Ext.Array.erase(childEls, index, 1);
|
}
|
}
|
|
return childEls;
|
},
|
|
<span id='Ext-util-ElementContainer-method-removeChildEls'> /**
|
</span> * Removes items in the childEls array based on the return value of a supplied test
|
* function. The function is called with a entry in childEls and if the test function
|
* return true, that entry is removed. If false, that entry is kept.
|
*
|
* @param {Function} testFn The test function.
|
*/
|
removeChildEls: function (testFn) {
|
var me = this,
|
old = me.getChildEls(),
|
keepers = (me.childEls = []),
|
n, i, cel;
|
|
for (i = 0, n = old.length; i < n; ++i) {
|
cel = old[i];
|
if (!testFn(cel)) {
|
keepers.push(cel);
|
}
|
}
|
}
|
});
|
</pre>
|
</body>
|
</html>
|