1 include('uki.js');
  2 include('attachment.js');
  3 include('dom/event.js');
  4 
  5 /**
  6  * Collection performs group operations on uki.view objects.
  7  * <p>Behaves much like result jQuery(dom nodes).
  8  * Most methods are chainable like .attr('text', 'somevalue').bind('click', function() { ... })</p>
  9  *
 10  * <p>Its easier to call uki([view1, view2]) or uki('selector') instead of creating collection directly</p>
 11  *
 12  * @author voloko
 13  * @constructor
 14  * @class
 15  */
 16 uki.Collection = function( elems ) {
 17     this.length = 0;
 18 	Array.prototype.push.apply( this, elems );
 19 };
 20 
 21 uki.fn = uki.Collection.prototype = new function() {
 22     var proto = this;
 23     
 24     /**#@+ @memberOf uki.Collection# */
 25     /**
 26      * Iterates trough all items within itself
 27      *
 28      * @function
 29      *
 30      * @param {function(this:uki.view.Base, number, uki.view.Base)} callback Callback to call for every item
 31      * @returns {uki.view.Collection} self
 32      */
 33     this.each = function( callback ) {
 34         return uki.each( this, callback );        
 35     };
 36 
 37     /**
 38      * Creates a new uki.Collection populated with found items
 39      *
 40      * @function
 41      *
 42      * @param {function(uki.view.Base, number):boolean} callback Callback to call for every item
 43      * @returns {uki.view.Collection} created collection
 44      */
 45     this.grep = function( callback ) {
 46         return new uki.Collection( uki.grep(this, callback) );
 47     };
 48 
 49     /**
 50      * Sets an attribute on all views or gets the value of the attribute on the first view
 51      *
 52      * @example
 53      * c.attr('text', 'my text') // sets text to 'my text' on all collection views
 54      * c.attr('name') // gets name attribute on the first view
 55      *
 56      * @function
 57      *
 58      * @param {string} name Name of the attribute
 59      * @param {object=} value Value to set
 60      * @returns {uki.view.Collection|Object} Self or attribute value
 61      */
 62     this.attr = function( name, value ) {
 63         if (value !== undefined) {
 64             for (var i=this.length-1; i >= 0; i--) {
 65                 uki.attr( this[i], name, value );
 66             };
 67             return this;
 68         } else {
 69             return this[0] ? uki.attr( this[0], name ) : "";
 70         }
 71     };
 72 
 73     /**
 74      * Finds views within collection context
 75      * @example
 76      * c.find('Button')
 77      *
 78      * @function
 79      *
 80      * @param {string} selector 
 81      * @returns {uki.view.Collection} Collection of found items
 82      */
 83     this.find = function( selector ) {
 84         return uki.find( selector, this );
 85     };
 86 
 87     /**
 88      * Attaches all child views to dom container
 89      *
 90      * @function
 91      *
 92      * @param {Element} dom Container dom element
 93      * @param {uki.geometry.Rect} rect Default size
 94      * @returns {uki.view.Collection} self
 95      */
 96     this.attachTo = function( dom, rect ) {
 97         this.each(function() {
 98             new uki.Attachment( dom, this, rect );
 99         });
100         return this;
101     };
102 
103     /**
104      * Appends views to the first item in collection
105      *
106      * @function
107      *
108      * @param {Array.<uki.view.Base>} views Views to append
109      * @returns {uki.view.Collection} self
110      */
111     this.append = function( views ) {
112         var target = this[0];
113         if (!target) return this;
114 		
115         views = views.length !== undefined ? views : [views];
116 		
117         for (var i = views.length-1; i >= 0; i--) {
118             target.appendChild(views[i]);
119         };
120 		
121         return this;
122     };
123     
124     this.appendTo = function( target ) {
125         target = uki(target)[0];
126         this.each(function() {
127             target.appendChild(this);
128         });
129         return this;	
130         
131     };
132 
133     /**#@-*/
134 
135     /**
136      * @function
137      */
138     uki.Collection.addAttrs = function(attrNames) {
139         uki.each(attrNames, function(i, name) {
140             proto[name] = function( value ) { return this.attr( name, value ); };
141         });
142     };
143 
144     /** @function
145     @name uki.Collection#html */
146     /** @function
147     @name uki.Collection#text */
148     /** @function
149     @name uki.Collection#background */
150     /** @function
151     @name uki.Collection#value */
152     /** @function
153     @name uki.Collection#rect */
154     /** @function
155     @name uki.Collection#checked */
156     /** @function
157     @name uki.Collection#anchors */
158     /** @function
159     @name uki.Collection#childViews */
160     /** @function
161     @name uki.Collection#typeName */
162     /** @function
163     @name uki.Collection#id */
164     /** @function
165     @name uki.Collection#name */
166     /** @function
167     @name uki.Collection#visible */
168     /** @function
169     @name uki.Collection#disabled */
170     /** @function
171     @name uki.Collection#focusable */
172     /** @function
173     @name uki.Collection#style */
174     uki.Collection.addAttrs('dom html text background value rect checked anchors childViews typeName id name visible disabled focusable style draggable textSelectable width height minX maxX minY maxY left top x y contentsSize'.split(' '));
175     
176     
177     /** @function
178     @name uki.Collection#parent */
179     /** @function
180     @name uki.Collection#next */
181     /** @function
182     @name uki.Collection#prev */
183     uki.each([
184         ['parent', 'parent'],
185         ['next', 'nextView'],
186         ['prev', 'prevView']
187     ], function(i, desc) {
188         proto[ desc[0] ] = function() {
189             return new uki.Collection( uki.unique( uki.map(this, desc[1]) ) );
190         };
191     });
192     
193 
194     /** @function
195     @name uki.Collection#bind */
196     /** @function
197     @name uki.Collection#unload */
198     /** @function
199     @name uki.Collection#trigger */
200     /** @function
201     @name uki.Collection#layout */
202     /** @function
203     @name uki.Collection#appendChild */
204     /** @function
205     @name uki.Collection#removeChild */
206     /** @function
207     @name uki.Collection#insertBefore */
208     /** @function
209     @name uki.Collection#addRow */
210     /** @function
211     @name uki.Collection#removeRow */
212     /** @function
213     @name uki.Collection#resizeToContents */
214     /** @function
215     @name uki.Collection#toggle */
216     uki.each('bind unbind trigger layout appendChild removeChild insertBefore addRow removeRow resizeToContents toggle'.split(' '), function(i, name) {
217         proto[name] = function() { 
218             for (var i=this.length-1; i >=0; i--) {
219                 this[i][name].apply(this[i], arguments);
220             };
221             return this;
222         };
223     });
224 
225      /** @function
226     @name uki.Collection#blur */
227     /** @function
228     @name uki.Collection#focus */
229     /** @function
230     @name uki.Collection#load */
231     /** @function
232     @name uki.Collection#resize */
233     /** @function
234     @name uki.Collection#scroll */
235     /** @function
236     @name uki.Collection#unload */
237     /** @function
238     @name uki.Collection#click */
239     /** @function
240     @name uki.Collection#dblclick */
241     /** @function
242     @name uki.Collection#mousedown */
243     /** @function
244     @name uki.Collection#mouseup */
245     /** @function
246     @name uki.Collection#mousemove */
247     /** @function
248     @name uki.Collection#mouseover */
249     /** @function
250     @name uki.Collection#mouseout */
251     /** @function
252     @name uki.Collection#mouseenter */
253     /** @function
254     @name uki.Collection#mouseleave */
255     /** @function
256     @name uki.Collection#change */
257     /** @function
258     @name uki.Collection#select */
259     /** @function
260     @name uki.Collection#submit */
261     /** @function
262     @name uki.Collection#keydown */
263     /** @function
264     @name uki.Collection#keypress */
265     /** @function
266     @name uki.Collection#keyup */
267     /** @function
268     @name uki.Collection#error */
269     uki.each( uki.dom.events, function(i, name){
270     	proto[name] = function( handler ){
271     	    if (handler) {
272         		this.bind(name, handler);
273     	    } else {
274                 for (var i=this.length-1; i >=0; i--) {
275                     this[i][name] ? this[i][name]() : this[i].trigger(name);
276                 };
277     	    }
278     		return this;
279     	};
280     });
281 };
282 
283