123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- <!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', {
- childEls: [
- // 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)
- ],
- constructor: function () {
- 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);
- }
- },
- destroy: function () {
- 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;
- }
- },
- getChildEls: function () {
- 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);
- },
- getClassChildEls: function (cls) {
- 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;
- },
- prune: function (childEls, shared) {
- 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>
|