~canonical-ci-engineering/ubuntu-ci-services-itself/graphite-web

« back to all changes in this revision

Viewing changes to webapp/content/js/ext/pkgs/ext-core-debug.js

  • Committer: Package Import Robot
  • Author(s): Jonas Genannt
  • Date: 2013-03-09 16:06:34 UTC
  • Revision ID: package-import@ubuntu.com-20130309160634-p1ei8oxvm3plrbas
Tags: upstream-0.9.10+debian
ImportĀ upstreamĀ versionĀ 0.9.10+debian

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*!
 
2
 * Ext JS Library 3.3.1
 
3
 * Copyright(c) 2006-2010 Sencha Inc.
 
4
 * licensing@sencha.com
 
5
 * http://www.sencha.com/license
 
6
 */
 
7
(function(){
 
8
 
 
9
var EXTUTIL = Ext.util,
 
10
    EACH = Ext.each,
 
11
    TRUE = true,
 
12
    FALSE = false;
 
13
/**
 
14
 * @class Ext.util.Observable
 
15
 * Base class that provides a common interface for publishing events. Subclasses are expected to
 
16
 * to have a property "events" with all the events defined, and, optionally, a property "listeners"
 
17
 * with configured listeners defined.<br>
 
18
 * For example:
 
19
 * <pre><code>
 
20
Employee = Ext.extend(Ext.util.Observable, {
 
21
    constructor: function(config){
 
22
        this.name = config.name;
 
23
        this.addEvents({
 
24
            "fired" : true,
 
25
            "quit" : true
 
26
        });
 
27
 
 
28
        // Copy configured listeners into *this* object so that the base class&#39;s
 
29
        // constructor will add them.
 
30
        this.listeners = config.listeners;
 
31
 
 
32
        // Call our superclass constructor to complete construction process.
 
33
        Employee.superclass.constructor.call(this, config)
 
34
    }
 
35
});
 
36
</code></pre>
 
37
 * This could then be used like this:<pre><code>
 
38
var newEmployee = new Employee({
 
39
    name: employeeName,
 
40
    listeners: {
 
41
        quit: function() {
 
42
            // By default, "this" will be the object that fired the event.
 
43
            alert(this.name + " has quit!");
 
44
        }
 
45
    }
 
46
});
 
47
</code></pre>
 
48
 */
 
49
EXTUTIL.Observable = function(){
 
50
    /**
 
51
     * @cfg {Object} listeners (optional) <p>A config object containing one or more event handlers to be added to this
 
52
     * object during initialization.  This should be a valid listeners config object as specified in the
 
53
     * {@link #addListener} example for attaching multiple handlers at once.</p>
 
54
     * <br><p><b><u>DOM events from ExtJs {@link Ext.Component Components}</u></b></p>
 
55
     * <br><p>While <i>some</i> ExtJs Component classes export selected DOM events (e.g. "click", "mouseover" etc), this
 
56
     * is usually only done when extra value can be added. For example the {@link Ext.DataView DataView}'s
 
57
     * <b><code>{@link Ext.DataView#click click}</code></b> event passing the node clicked on. To access DOM
 
58
     * events directly from a Component's HTMLElement, listeners must be added to the <i>{@link Ext.Component#getEl Element}</i> after the Component
 
59
     * has been rendered. A plugin can simplify this step:<pre><code>
 
60
// Plugin is configured with a listeners config object.
 
61
// The Component is appended to the argument list of all handler functions.
 
62
Ext.DomObserver = Ext.extend(Object, {
 
63
    constructor: function(config) {
 
64
        this.listeners = config.listeners ? config.listeners : config;
 
65
    },
 
66
 
 
67
    // Component passes itself into plugin&#39;s init method
 
68
    init: function(c) {
 
69
        var p, l = this.listeners;
 
70
        for (p in l) {
 
71
            if (Ext.isFunction(l[p])) {
 
72
                l[p] = this.createHandler(l[p], c);
 
73
            } else {
 
74
                l[p].fn = this.createHandler(l[p].fn, c);
 
75
            }
 
76
        }
 
77
 
 
78
        // Add the listeners to the Element immediately following the render call
 
79
        c.render = c.render.{@link Function#createSequence createSequence}(function() {
 
80
            var e = c.getEl();
 
81
            if (e) {
 
82
                e.on(l);
 
83
            }
 
84
        });
 
85
    },
 
86
 
 
87
    createHandler: function(fn, c) {
 
88
        return function(e) {
 
89
            fn.call(this, e, c);
 
90
        };
 
91
    }
 
92
});
 
93
 
 
94
var combo = new Ext.form.ComboBox({
 
95
 
 
96
    // Collapse combo when its element is clicked on
 
97
    plugins: [ new Ext.DomObserver({
 
98
        click: function(evt, comp) {
 
99
            comp.collapse();
 
100
        }
 
101
    })],
 
102
    store: myStore,
 
103
    typeAhead: true,
 
104
    mode: 'local',
 
105
    triggerAction: 'all'
 
106
});
 
107
     * </code></pre></p>
 
108
     */
 
109
    var me = this, e = me.events;
 
110
    if(me.listeners){
 
111
        me.on(me.listeners);
 
112
        delete me.listeners;
 
113
    }
 
114
    me.events = e || {};
 
115
};
 
116
 
 
117
EXTUTIL.Observable.prototype = {
 
118
    // private
 
119
    filterOptRe : /^(?:scope|delay|buffer|single)$/,
 
120
 
 
121
    /**
 
122
     * <p>Fires the specified event with the passed parameters (minus the event name).</p>
 
123
     * <p>An event may be set to bubble up an Observable parent hierarchy (See {@link Ext.Component#getBubbleTarget})
 
124
     * by calling {@link #enableBubble}.</p>
 
125
     * @param {String} eventName The name of the event to fire.
 
126
     * @param {Object...} args Variable number of parameters are passed to handlers.
 
127
     * @return {Boolean} returns false if any of the handlers return false otherwise it returns true.
 
128
     */
 
129
    fireEvent : function(){
 
130
        var a = Array.prototype.slice.call(arguments, 0),
 
131
            ename = a[0].toLowerCase(),
 
132
            me = this,
 
133
            ret = TRUE,
 
134
            ce = me.events[ename],
 
135
            cc,
 
136
            q,
 
137
            c;
 
138
        if (me.eventsSuspended === TRUE) {
 
139
            if (q = me.eventQueue) {
 
140
                q.push(a);
 
141
            }
 
142
        }
 
143
        else if(typeof ce == 'object') {
 
144
            if (ce.bubble){
 
145
                if(ce.fire.apply(ce, a.slice(1)) === FALSE) {
 
146
                    return FALSE;
 
147
                }
 
148
                c = me.getBubbleTarget && me.getBubbleTarget();
 
149
                if(c && c.enableBubble) {
 
150
                    cc = c.events[ename];
 
151
                    if(!cc || typeof cc != 'object' || !cc.bubble) {
 
152
                        c.enableBubble(ename);
 
153
                    }
 
154
                    return c.fireEvent.apply(c, a);
 
155
                }
 
156
            }
 
157
            else {
 
158
                a.shift();
 
159
                ret = ce.fire.apply(ce, a);
 
160
            }
 
161
        }
 
162
        return ret;
 
163
    },
 
164
 
 
165
    /**
 
166
     * Appends an event handler to this object.
 
167
     * @param {String}   eventName The name of the event to listen for.
 
168
     * @param {Function} handler The method the event invokes.
 
169
     * @param {Object}   scope (optional) The scope (<code><b>this</b></code> reference) in which the handler function is executed.
 
170
     * <b>If omitted, defaults to the object which fired the event.</b>
 
171
     * @param {Object}   options (optional) An object containing handler configuration.
 
172
     * properties. This may contain any of the following properties:<ul>
 
173
     * <li><b>scope</b> : Object<div class="sub-desc">The scope (<code><b>this</b></code> reference) in which the handler function is executed.
 
174
     * <b>If omitted, defaults to the object which fired the event.</b></div></li>
 
175
     * <li><b>delay</b> : Number<div class="sub-desc">The number of milliseconds to delay the invocation of the handler after the event fires.</div></li>
 
176
     * <li><b>single</b> : Boolean<div class="sub-desc">True to add a handler to handle just the next firing of the event, and then remove itself.</div></li>
 
177
     * <li><b>buffer</b> : Number<div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
 
178
     * by the specified number of milliseconds. If the event fires again within that time, the original
 
179
     * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>
 
180
     * <li><b>target</b> : Observable<div class="sub-desc">Only call the handler if the event was fired on the target Observable, <i>not</i>
 
181
     * if the event was bubbled up from a child Observable.</div></li>
 
182
     * </ul><br>
 
183
     * <p>
 
184
     * <b>Combining Options</b><br>
 
185
     * Using the options argument, it is possible to combine different types of listeners:<br>
 
186
     * <br>
 
187
     * A delayed, one-time listener.
 
188
     * <pre><code>
 
189
myDataView.on('click', this.onClick, this, {
 
190
single: true,
 
191
delay: 100
 
192
});</code></pre>
 
193
     * <p>
 
194
     * <b>Attaching multiple handlers in 1 call</b><br>
 
195
     * The method also allows for a single argument to be passed which is a config object containing properties
 
196
     * which specify multiple handlers.
 
197
     * <p>
 
198
     * <pre><code>
 
199
myGridPanel.on({
 
200
'click' : {
 
201
    fn: this.onClick,
 
202
    scope: this,
 
203
    delay: 100
 
204
},
 
205
'mouseover' : {
 
206
    fn: this.onMouseOver,
 
207
    scope: this
 
208
},
 
209
'mouseout' : {
 
210
    fn: this.onMouseOut,
 
211
    scope: this
 
212
}
 
213
});</code></pre>
 
214
 * <p>
 
215
 * Or a shorthand syntax:<br>
 
216
 * <pre><code>
 
217
myGridPanel.on({
 
218
'click' : this.onClick,
 
219
'mouseover' : this.onMouseOver,
 
220
'mouseout' : this.onMouseOut,
 
221
 scope: this
 
222
});</code></pre>
 
223
     */
 
224
    addListener : function(eventName, fn, scope, o){
 
225
        var me = this,
 
226
            e,
 
227
            oe,
 
228
            ce;
 
229
            
 
230
        if (typeof eventName == 'object') {
 
231
            o = eventName;
 
232
            for (e in o) {
 
233
                oe = o[e];
 
234
                if (!me.filterOptRe.test(e)) {
 
235
                    me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o);
 
236
                }
 
237
            }
 
238
        } else {
 
239
            eventName = eventName.toLowerCase();
 
240
            ce = me.events[eventName] || TRUE;
 
241
            if (typeof ce == 'boolean') {
 
242
                me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
 
243
            }
 
244
            ce.addListener(fn, scope, typeof o == 'object' ? o : {});
 
245
        }
 
246
    },
 
247
 
 
248
    /**
 
249
     * Removes an event handler.
 
250
     * @param {String}   eventName The type of event the handler was associated with.
 
251
     * @param {Function} handler   The handler to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
 
252
     * @param {Object}   scope     (optional) The scope originally specified for the handler.
 
253
     */
 
254
    removeListener : function(eventName, fn, scope){
 
255
        var ce = this.events[eventName.toLowerCase()];
 
256
        if (typeof ce == 'object') {
 
257
            ce.removeListener(fn, scope);
 
258
        }
 
259
    },
 
260
 
 
261
    /**
 
262
     * Removes all listeners for this object
 
263
     */
 
264
    purgeListeners : function(){
 
265
        var events = this.events,
 
266
            evt,
 
267
            key;
 
268
        for(key in events){
 
269
            evt = events[key];
 
270
            if(typeof evt == 'object'){
 
271
                evt.clearListeners();
 
272
            }
 
273
        }
 
274
    },
 
275
 
 
276
    /**
 
277
     * Adds the specified events to the list of events which this Observable may fire.
 
278
     * @param {Object|String} o Either an object with event names as properties with a value of <code>true</code>
 
279
     * or the first event name string if multiple event names are being passed as separate parameters.
 
280
     * @param {string} Optional. Event name if multiple event names are being passed as separate parameters.
 
281
     * Usage:<pre><code>
 
282
this.addEvents('storeloaded', 'storecleared');
 
283
</code></pre>
 
284
     */
 
285
    addEvents : function(o){
 
286
        var me = this;
 
287
        me.events = me.events || {};
 
288
        if (typeof o == 'string') {
 
289
            var a = arguments,
 
290
                i = a.length;
 
291
            while(i--) {
 
292
                me.events[a[i]] = me.events[a[i]] || TRUE;
 
293
            }
 
294
        } else {
 
295
            Ext.applyIf(me.events, o);
 
296
        }
 
297
    },
 
298
 
 
299
    /**
 
300
     * Checks to see if this object has any listeners for a specified event
 
301
     * @param {String} eventName The name of the event to check for
 
302
     * @return {Boolean} True if the event is being listened for, else false
 
303
     */
 
304
    hasListener : function(eventName){
 
305
        var e = this.events[eventName.toLowerCase()];
 
306
        return typeof e == 'object' && e.listeners.length > 0;
 
307
    },
 
308
 
 
309
    /**
 
310
     * Suspend the firing of all events. (see {@link #resumeEvents})
 
311
     * @param {Boolean} queueSuspended Pass as true to queue up suspended events to be fired
 
312
     * after the {@link #resumeEvents} call instead of discarding all suspended events;
 
313
     */
 
314
    suspendEvents : function(queueSuspended){
 
315
        this.eventsSuspended = TRUE;
 
316
        if(queueSuspended && !this.eventQueue){
 
317
            this.eventQueue = [];
 
318
        }
 
319
    },
 
320
 
 
321
    /**
 
322
     * Resume firing events. (see {@link #suspendEvents})
 
323
     * If events were suspended using the <tt><b>queueSuspended</b></tt> parameter, then all
 
324
     * events fired during event suspension will be sent to any listeners now.
 
325
     */
 
326
    resumeEvents : function(){
 
327
        var me = this,
 
328
            queued = me.eventQueue || [];
 
329
        me.eventsSuspended = FALSE;
 
330
        delete me.eventQueue;
 
331
        EACH(queued, function(e) {
 
332
            me.fireEvent.apply(me, e);
 
333
        });
 
334
    }
 
335
};
 
336
 
 
337
var OBSERVABLE = EXTUTIL.Observable.prototype;
 
338
/**
 
339
 * Appends an event handler to this object (shorthand for {@link #addListener}.)
 
340
 * @param {String}   eventName     The type of event to listen for
 
341
 * @param {Function} handler       The method the event invokes
 
342
 * @param {Object}   scope         (optional) The scope (<code><b>this</b></code> reference) in which the handler function is executed.
 
343
 * <b>If omitted, defaults to the object which fired the event.</b>
 
344
 * @param {Object}   options       (optional) An object containing handler configuration.
 
345
 * @method
 
346
 */
 
347
OBSERVABLE.on = OBSERVABLE.addListener;
 
348
/**
 
349
 * Removes an event handler (shorthand for {@link #removeListener}.)
 
350
 * @param {String}   eventName     The type of event the handler was associated with.
 
351
 * @param {Function} handler       The handler to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
 
352
 * @param {Object}   scope         (optional) The scope originally specified for the handler.
 
353
 * @method
 
354
 */
 
355
OBSERVABLE.un = OBSERVABLE.removeListener;
 
356
 
 
357
/**
 
358
 * Removes <b>all</b> added captures from the Observable.
 
359
 * @param {Observable} o The Observable to release
 
360
 * @static
 
361
 */
 
362
EXTUTIL.Observable.releaseCapture = function(o){
 
363
    o.fireEvent = OBSERVABLE.fireEvent;
 
364
};
 
365
 
 
366
function createTargeted(h, o, scope){
 
367
    return function(){
 
368
        if(o.target == arguments[0]){
 
369
            h.apply(scope, Array.prototype.slice.call(arguments, 0));
 
370
        }
 
371
    };
 
372
};
 
373
 
 
374
function createBuffered(h, o, l, scope){
 
375
    l.task = new EXTUTIL.DelayedTask();
 
376
    return function(){
 
377
        l.task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
 
378
    };
 
379
};
 
380
 
 
381
function createSingle(h, e, fn, scope){
 
382
    return function(){
 
383
        e.removeListener(fn, scope);
 
384
        return h.apply(scope, arguments);
 
385
    };
 
386
};
 
387
 
 
388
function createDelayed(h, o, l, scope){
 
389
    return function(){
 
390
        var task = new EXTUTIL.DelayedTask(),
 
391
            args = Array.prototype.slice.call(arguments, 0);
 
392
        if(!l.tasks) {
 
393
            l.tasks = [];
 
394
        }
 
395
        l.tasks.push(task);
 
396
        task.delay(o.delay || 10, function(){
 
397
            l.tasks.remove(task);
 
398
            h.apply(scope, args);
 
399
        }, scope);
 
400
    };
 
401
};
 
402
 
 
403
EXTUTIL.Event = function(obj, name){
 
404
    this.name = name;
 
405
    this.obj = obj;
 
406
    this.listeners = [];
 
407
};
 
408
 
 
409
EXTUTIL.Event.prototype = {
 
410
    addListener : function(fn, scope, options){
 
411
        var me = this,
 
412
            l;
 
413
        scope = scope || me.obj;
 
414
        if(!me.isListening(fn, scope)){
 
415
            l = me.createListener(fn, scope, options);
 
416
            if(me.firing){ // if we are currently firing this event, don't disturb the listener loop
 
417
                me.listeners = me.listeners.slice(0);
 
418
            }
 
419
            me.listeners.push(l);
 
420
        }
 
421
    },
 
422
 
 
423
    createListener: function(fn, scope, o){
 
424
        o = o || {};
 
425
        scope = scope || this.obj;
 
426
        var l = {
 
427
            fn: fn,
 
428
            scope: scope,
 
429
            options: o
 
430
        }, h = fn;
 
431
        if(o.target){
 
432
            h = createTargeted(h, o, scope);
 
433
        }
 
434
        if(o.delay){
 
435
            h = createDelayed(h, o, l, scope);
 
436
        }
 
437
        if(o.single){
 
438
            h = createSingle(h, this, fn, scope);
 
439
        }
 
440
        if(o.buffer){
 
441
            h = createBuffered(h, o, l, scope);
 
442
        }
 
443
        l.fireFn = h;
 
444
        return l;
 
445
    },
 
446
 
 
447
    findListener : function(fn, scope){
 
448
        var list = this.listeners,
 
449
            i = list.length,
 
450
            l;
 
451
 
 
452
        scope = scope || this.obj;
 
453
        while(i--){
 
454
            l = list[i];
 
455
            if(l){
 
456
                if(l.fn == fn && l.scope == scope){
 
457
                    return i;
 
458
                }
 
459
            }
 
460
        }
 
461
        return -1;
 
462
    },
 
463
 
 
464
    isListening : function(fn, scope){
 
465
        return this.findListener(fn, scope) != -1;
 
466
    },
 
467
 
 
468
    removeListener : function(fn, scope){
 
469
        var index,
 
470
            l,
 
471
            k,
 
472
            me = this,
 
473
            ret = FALSE;
 
474
        if((index = me.findListener(fn, scope)) != -1){
 
475
            if (me.firing) {
 
476
                me.listeners = me.listeners.slice(0);
 
477
            }
 
478
            l = me.listeners[index];
 
479
            if(l.task) {
 
480
                l.task.cancel();
 
481
                delete l.task;
 
482
            }
 
483
            k = l.tasks && l.tasks.length;
 
484
            if(k) {
 
485
                while(k--) {
 
486
                    l.tasks[k].cancel();
 
487
                }
 
488
                delete l.tasks;
 
489
            }
 
490
            me.listeners.splice(index, 1);
 
491
            ret = TRUE;
 
492
        }
 
493
        return ret;
 
494
    },
 
495
 
 
496
    // Iterate to stop any buffered/delayed events
 
497
    clearListeners : function(){
 
498
        var me = this,
 
499
            l = me.listeners,
 
500
            i = l.length;
 
501
        while(i--) {
 
502
            me.removeListener(l[i].fn, l[i].scope);
 
503
        }
 
504
    },
 
505
 
 
506
    fire : function(){
 
507
        var me = this,
 
508
            listeners = me.listeners,
 
509
            len = listeners.length,
 
510
            i = 0,
 
511
            l;
 
512
 
 
513
        if(len > 0){
 
514
            me.firing = TRUE;
 
515
            var args = Array.prototype.slice.call(arguments, 0);
 
516
            for (; i < len; i++) {
 
517
                l = listeners[i];
 
518
                if(l && l.fireFn.apply(l.scope || me.obj || window, args) === FALSE) {
 
519
                    return (me.firing = FALSE);
 
520
                }
 
521
            }
 
522
        }
 
523
        me.firing = FALSE;
 
524
        return TRUE;
 
525
    }
 
526
 
 
527
};
 
528
})();
 
529
/**
 
530
 * @class Ext.DomHelper
 
531
 * <p>The DomHelper class provides a layer of abstraction from DOM and transparently supports creating
 
532
 * elements via DOM or using HTML fragments. It also has the ability to create HTML fragment templates
 
533
 * from your DOM building code.</p>
 
534
 *
 
535
 * <p><b><u>DomHelper element specification object</u></b></p>
 
536
 * <p>A specification object is used when creating elements. Attributes of this object
 
537
 * are assumed to be element attributes, except for 4 special attributes:
 
538
 * <div class="mdetail-params"><ul>
 
539
 * <li><b><tt>tag</tt></b> : <div class="sub-desc">The tag name of the element</div></li>
 
540
 * <li><b><tt>children</tt></b> : or <tt>cn</tt><div class="sub-desc">An array of the
 
541
 * same kind of element definition objects to be created and appended. These can be nested
 
542
 * as deep as you want.</div></li>
 
543
 * <li><b><tt>cls</tt></b> : <div class="sub-desc">The class attribute of the element.
 
544
 * This will end up being either the "class" attribute on a HTML fragment or className
 
545
 * for a DOM node, depending on whether DomHelper is using fragments or DOM.</div></li>
 
546
 * <li><b><tt>html</tt></b> : <div class="sub-desc">The innerHTML for the element</div></li>
 
547
 * </ul></div></p>
 
548
 *
 
549
 * <p><b><u>Insertion methods</u></b></p>
 
550
 * <p>Commonly used insertion methods:
 
551
 * <div class="mdetail-params"><ul>
 
552
 * <li><b><tt>{@link #append}</tt></b> : <div class="sub-desc"></div></li>
 
553
 * <li><b><tt>{@link #insertBefore}</tt></b> : <div class="sub-desc"></div></li>
 
554
 * <li><b><tt>{@link #insertAfter}</tt></b> : <div class="sub-desc"></div></li>
 
555
 * <li><b><tt>{@link #overwrite}</tt></b> : <div class="sub-desc"></div></li>
 
556
 * <li><b><tt>{@link #createTemplate}</tt></b> : <div class="sub-desc"></div></li>
 
557
 * <li><b><tt>{@link #insertHtml}</tt></b> : <div class="sub-desc"></div></li>
 
558
 * </ul></div></p>
 
559
 *
 
560
 * <p><b><u>Example</u></b></p>
 
561
 * <p>This is an example, where an unordered list with 3 children items is appended to an existing
 
562
 * element with id <tt>'my-div'</tt>:<br>
 
563
 <pre><code>
 
564
var dh = Ext.DomHelper; // create shorthand alias
 
565
// specification object
 
566
var spec = {
 
567
    id: 'my-ul',
 
568
    tag: 'ul',
 
569
    cls: 'my-list',
 
570
    // append children after creating
 
571
    children: [     // may also specify 'cn' instead of 'children'
 
572
        {tag: 'li', id: 'item0', html: 'List Item 0'},
 
573
        {tag: 'li', id: 'item1', html: 'List Item 1'},
 
574
        {tag: 'li', id: 'item2', html: 'List Item 2'}
 
575
    ]
 
576
};
 
577
var list = dh.append(
 
578
    'my-div', // the context element 'my-div' can either be the id or the actual node
 
579
    spec      // the specification object
 
580
);
 
581
 </code></pre></p>
 
582
 * <p>Element creation specification parameters in this class may also be passed as an Array of
 
583
 * specification objects. This can be used to insert multiple sibling nodes into an existing
 
584
 * container very efficiently. For example, to add more list items to the example above:<pre><code>
 
585
dh.append('my-ul', [
 
586
    {tag: 'li', id: 'item3', html: 'List Item 3'},
 
587
    {tag: 'li', id: 'item4', html: 'List Item 4'}
 
588
]);
 
589
 * </code></pre></p>
 
590
 *
 
591
 * <p><b><u>Templating</u></b></p>
 
592
 * <p>The real power is in the built-in templating. Instead of creating or appending any elements,
 
593
 * <tt>{@link #createTemplate}</tt> returns a Template object which can be used over and over to
 
594
 * insert new elements. Revisiting the example above, we could utilize templating this time:
 
595
 * <pre><code>
 
596
// create the node
 
597
var list = dh.append('my-div', {tag: 'ul', cls: 'my-list'});
 
598
// get template
 
599
var tpl = dh.createTemplate({tag: 'li', id: 'item{0}', html: 'List Item {0}'});
 
600
 
 
601
for(var i = 0; i < 5, i++){
 
602
    tpl.append(list, [i]); // use template to append to the actual node
 
603
}
 
604
 * </code></pre></p>
 
605
 * <p>An example using a template:<pre><code>
 
606
var html = '<a id="{0}" href="{1}" class="nav">{2}</a>';
 
607
 
 
608
var tpl = new Ext.DomHelper.createTemplate(html);
 
609
tpl.append('blog-roll', ['link1', 'http://www.jackslocum.com/', "Jack&#39;s Site"]);
 
610
tpl.append('blog-roll', ['link2', 'http://www.dustindiaz.com/', "Dustin&#39;s Site"]);
 
611
 * </code></pre></p>
 
612
 *
 
613
 * <p>The same example using named parameters:<pre><code>
 
614
var html = '<a id="{id}" href="{url}" class="nav">{text}</a>';
 
615
 
 
616
var tpl = new Ext.DomHelper.createTemplate(html);
 
617
tpl.append('blog-roll', {
 
618
    id: 'link1',
 
619
    url: 'http://www.jackslocum.com/',
 
620
    text: "Jack&#39;s Site"
 
621
});
 
622
tpl.append('blog-roll', {
 
623
    id: 'link2',
 
624
    url: 'http://www.dustindiaz.com/',
 
625
    text: "Dustin&#39;s Site"
 
626
});
 
627
 * </code></pre></p>
 
628
 *
 
629
 * <p><b><u>Compiling Templates</u></b></p>
 
630
 * <p>Templates are applied using regular expressions. The performance is great, but if
 
631
 * you are adding a bunch of DOM elements using the same template, you can increase
 
632
 * performance even further by {@link Ext.Template#compile "compiling"} the template.
 
633
 * The way "{@link Ext.Template#compile compile()}" works is the template is parsed and
 
634
 * broken up at the different variable points and a dynamic function is created and eval'ed.
 
635
 * The generated function performs string concatenation of these parts and the passed
 
636
 * variables instead of using regular expressions.
 
637
 * <pre><code>
 
638
var html = '<a id="{id}" href="{url}" class="nav">{text}</a>';
 
639
 
 
640
var tpl = new Ext.DomHelper.createTemplate(html);
 
641
tpl.compile();
 
642
 
 
643
//... use template like normal
 
644
 * </code></pre></p>
 
645
 *
 
646
 * <p><b><u>Performance Boost</u></b></p>
 
647
 * <p>DomHelper will transparently create HTML fragments when it can. Using HTML fragments instead
 
648
 * of DOM can significantly boost performance.</p>
 
649
 * <p>Element creation specification parameters may also be strings. If {@link #useDom} is <tt>false</tt>,
 
650
 * then the string is used as innerHTML. If {@link #useDom} is <tt>true</tt>, a string specification
 
651
 * results in the creation of a text node. Usage:</p>
 
652
 * <pre><code>
 
653
Ext.DomHelper.useDom = true; // force it to use DOM; reduces performance
 
654
 * </code></pre>
 
655
 * @singleton
 
656
 */
 
657
Ext.DomHelper = function(){
 
658
    var tempTableEl = null,
 
659
        emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
 
660
        tableRe = /^table|tbody|tr|td$/i,
 
661
        confRe = /tag|children|cn|html$/i,
 
662
        tableElRe = /td|tr|tbody/i,
 
663
        cssRe = /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,
 
664
        endRe = /end/i,
 
665
        pub,
 
666
        // kill repeat to save bytes
 
667
        afterbegin = 'afterbegin',
 
668
        afterend = 'afterend',
 
669
        beforebegin = 'beforebegin',
 
670
        beforeend = 'beforeend',
 
671
        ts = '<table>',
 
672
        te = '</table>',
 
673
        tbs = ts+'<tbody>',
 
674
        tbe = '</tbody>'+te,
 
675
        trs = tbs + '<tr>',
 
676
        tre = '</tr>'+tbe;
 
677
 
 
678
    // private
 
679
    function doInsert(el, o, returnElement, pos, sibling, append){
 
680
        var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));
 
681
        return returnElement ? Ext.get(newNode, true) : newNode;
 
682
    }
 
683
 
 
684
    // build as innerHTML where available
 
685
    function createHtml(o){
 
686
        var b = '',
 
687
            attr,
 
688
            val,
 
689
            key,
 
690
            cn;
 
691
 
 
692
        if(typeof o == "string"){
 
693
            b = o;
 
694
        } else if (Ext.isArray(o)) {
 
695
            for (var i=0; i < o.length; i++) {
 
696
                if(o[i]) {
 
697
                    b += createHtml(o[i]);
 
698
                }
 
699
            };
 
700
        } else {
 
701
            b += '<' + (o.tag = o.tag || 'div');
 
702
            for (attr in o) {
 
703
                val = o[attr];
 
704
                if(!confRe.test(attr)){
 
705
                    if (typeof val == "object") {
 
706
                        b += ' ' + attr + '="';
 
707
                        for (key in val) {
 
708
                            b += key + ':' + val[key] + ';';
 
709
                        };
 
710
                        b += '"';
 
711
                    }else{
 
712
                        b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
 
713
                    }
 
714
                }
 
715
            };
 
716
            // Now either just close the tag or try to add children and close the tag.
 
717
            if (emptyTags.test(o.tag)) {
 
718
                b += '/>';
 
719
            } else {
 
720
                b += '>';
 
721
                if ((cn = o.children || o.cn)) {
 
722
                    b += createHtml(cn);
 
723
                } else if(o.html){
 
724
                    b += o.html;
 
725
                }
 
726
                b += '</' + o.tag + '>';
 
727
            }
 
728
        }
 
729
        return b;
 
730
    }
 
731
 
 
732
    function ieTable(depth, s, h, e){
 
733
        tempTableEl.innerHTML = [s, h, e].join('');
 
734
        var i = -1,
 
735
            el = tempTableEl,
 
736
            ns;
 
737
        while(++i < depth){
 
738
            el = el.firstChild;
 
739
        }
 
740
//      If the result is multiple siblings, then encapsulate them into one fragment.
 
741
        if(ns = el.nextSibling){
 
742
            var df = document.createDocumentFragment();
 
743
            while(el){
 
744
                ns = el.nextSibling;
 
745
                df.appendChild(el);
 
746
                el = ns;
 
747
            }
 
748
            el = df;
 
749
        }
 
750
        return el;
 
751
    }
 
752
 
 
753
    /**
 
754
     * @ignore
 
755
     * Nasty code for IE's broken table implementation
 
756
     */
 
757
    function insertIntoTable(tag, where, el, html) {
 
758
        var node,
 
759
            before;
 
760
 
 
761
        tempTableEl = tempTableEl || document.createElement('div');
 
762
 
 
763
        if(tag == 'td' && (where == afterbegin || where == beforeend) ||
 
764
           !tableElRe.test(tag) && (where == beforebegin || where == afterend)) {
 
765
            return;
 
766
        }
 
767
        before = where == beforebegin ? el :
 
768
                 where == afterend ? el.nextSibling :
 
769
                 where == afterbegin ? el.firstChild : null;
 
770
 
 
771
        if (where == beforebegin || where == afterend) {
 
772
            el = el.parentNode;
 
773
        }
 
774
 
 
775
        if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
 
776
            node = ieTable(4, trs, html, tre);
 
777
        } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
 
778
                   (tag == 'tr' && (where == beforebegin || where == afterend))) {
 
779
            node = ieTable(3, tbs, html, tbe);
 
780
        } else {
 
781
            node = ieTable(2, ts, html, te);
 
782
        }
 
783
        el.insertBefore(node, before);
 
784
        return node;
 
785
    }
 
786
 
 
787
 
 
788
    pub = {
 
789
        /**
 
790
         * Returns the markup for the passed Element(s) config.
 
791
         * @param {Object} o The DOM object spec (and children)
 
792
         * @return {String}
 
793
         */
 
794
        markup : function(o){
 
795
            return createHtml(o);
 
796
        },
 
797
 
 
798
        /**
 
799
         * Applies a style specification to an element.
 
800
         * @param {String/HTMLElement} el The element to apply styles to
 
801
         * @param {String/Object/Function} styles A style specification string e.g. 'width:100px', or object in the form {width:'100px'}, or
 
802
         * a function which returns such a specification.
 
803
         */
 
804
        applyStyles : function(el, styles){
 
805
            if (styles) {
 
806
                var matches;
 
807
 
 
808
                el = Ext.fly(el);
 
809
                if (typeof styles == "function") {
 
810
                    styles = styles.call();
 
811
                }
 
812
                if (typeof styles == "string") {
 
813
                    /**
 
814
                     * Since we're using the g flag on the regex, we need to set the lastIndex.
 
815
                     * This automatically happens on some implementations, but not others, see:
 
816
                     * http://stackoverflow.com/questions/2645273/javascript-regular-expression-literal-persists-between-function-calls
 
817
                     * http://blog.stevenlevithan.com/archives/fixing-javascript-regexp
 
818
                     */
 
819
                    cssRe.lastIndex = 0;
 
820
                    while ((matches = cssRe.exec(styles))) {
 
821
                        el.setStyle(matches[1], matches[2]);
 
822
                    }
 
823
                } else if (typeof styles == "object") {
 
824
                    el.setStyle(styles);
 
825
                }
 
826
            }
 
827
        },
 
828
 
 
829
        /**
 
830
         * Inserts an HTML fragment into the DOM.
 
831
         * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
 
832
         * @param {HTMLElement} el The context element
 
833
         * @param {String} html The HTML fragment
 
834
         * @return {HTMLElement} The new node
 
835
         */
 
836
        insertHtml : function(where, el, html){
 
837
            var hash = {},
 
838
                hashVal,
 
839
                setStart,
 
840
                range,
 
841
                frag,
 
842
                rangeEl,
 
843
                rs;
 
844
 
 
845
            where = where.toLowerCase();
 
846
            // add these here because they are used in both branches of the condition.
 
847
            hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
 
848
            hash[afterend] = ['AfterEnd', 'nextSibling'];
 
849
 
 
850
            if (el.insertAdjacentHTML) {
 
851
                if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
 
852
                    return rs;
 
853
                }
 
854
                // add these two to the hash.
 
855
                hash[afterbegin] = ['AfterBegin', 'firstChild'];
 
856
                hash[beforeend] = ['BeforeEnd', 'lastChild'];
 
857
                if ((hashVal = hash[where])) {
 
858
                    el.insertAdjacentHTML(hashVal[0], html);
 
859
                    return el[hashVal[1]];
 
860
                }
 
861
            } else {
 
862
                range = el.ownerDocument.createRange();
 
863
                setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');
 
864
                if (hash[where]) {
 
865
                    range[setStart](el);
 
866
                    frag = range.createContextualFragment(html);
 
867
                    el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
 
868
                    return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];
 
869
                } else {
 
870
                    rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';
 
871
                    if (el.firstChild) {
 
872
                        range[setStart](el[rangeEl]);
 
873
                        frag = range.createContextualFragment(html);
 
874
                        if(where == afterbegin){
 
875
                            el.insertBefore(frag, el.firstChild);
 
876
                        }else{
 
877
                            el.appendChild(frag);
 
878
                        }
 
879
                    } else {
 
880
                        el.innerHTML = html;
 
881
                    }
 
882
                    return el[rangeEl];
 
883
                }
 
884
            }
 
885
            throw 'Illegal insertion point -> "' + where + '"';
 
886
        },
 
887
 
 
888
        /**
 
889
         * Creates new DOM element(s) and inserts them before el.
 
890
         * @param {Mixed} el The context element
 
891
         * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
 
892
         * @param {Boolean} returnElement (optional) true to return a Ext.Element
 
893
         * @return {HTMLElement/Ext.Element} The new node
 
894
         */
 
895
        insertBefore : function(el, o, returnElement){
 
896
            return doInsert(el, o, returnElement, beforebegin);
 
897
        },
 
898
 
 
899
        /**
 
900
         * Creates new DOM element(s) and inserts them after el.
 
901
         * @param {Mixed} el The context element
 
902
         * @param {Object} o The DOM object spec (and children)
 
903
         * @param {Boolean} returnElement (optional) true to return a Ext.Element
 
904
         * @return {HTMLElement/Ext.Element} The new node
 
905
         */
 
906
        insertAfter : function(el, o, returnElement){
 
907
            return doInsert(el, o, returnElement, afterend, 'nextSibling');
 
908
        },
 
909
 
 
910
        /**
 
911
         * Creates new DOM element(s) and inserts them as the first child of el.
 
912
         * @param {Mixed} el The context element
 
913
         * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
 
914
         * @param {Boolean} returnElement (optional) true to return a Ext.Element
 
915
         * @return {HTMLElement/Ext.Element} The new node
 
916
         */
 
917
        insertFirst : function(el, o, returnElement){
 
918
            return doInsert(el, o, returnElement, afterbegin, 'firstChild');
 
919
        },
 
920
 
 
921
        /**
 
922
         * Creates new DOM element(s) and appends them to el.
 
923
         * @param {Mixed} el The context element
 
924
         * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
 
925
         * @param {Boolean} returnElement (optional) true to return a Ext.Element
 
926
         * @return {HTMLElement/Ext.Element} The new node
 
927
         */
 
928
        append : function(el, o, returnElement){
 
929
            return doInsert(el, o, returnElement, beforeend, '', true);
 
930
        },
 
931
 
 
932
        /**
 
933
         * Creates new DOM element(s) and overwrites the contents of el with them.
 
934
         * @param {Mixed} el The context element
 
935
         * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
 
936
         * @param {Boolean} returnElement (optional) true to return a Ext.Element
 
937
         * @return {HTMLElement/Ext.Element} The new node
 
938
         */
 
939
        overwrite : function(el, o, returnElement){
 
940
            el = Ext.getDom(el);
 
941
            el.innerHTML = createHtml(o);
 
942
            return returnElement ? Ext.get(el.firstChild) : el.firstChild;
 
943
        },
 
944
 
 
945
        createHtml : createHtml
 
946
    };
 
947
    return pub;
 
948
}();
 
949
/**
 
950
 * @class Ext.Template
 
951
 * <p>Represents an HTML fragment template. Templates may be {@link #compile precompiled}
 
952
 * for greater performance.</p>
 
953
 * <p>For example usage {@link #Template see the constructor}.</p>
 
954
 *
 
955
 * @constructor
 
956
 * An instance of this class may be created by passing to the constructor either
 
957
 * a single argument, or multiple arguments:
 
958
 * <div class="mdetail-params"><ul>
 
959
 * <li><b>single argument</b> : String/Array
 
960
 * <div class="sub-desc">
 
961
 * The single argument may be either a String or an Array:<ul>
 
962
 * <li><tt>String</tt> : </li><pre><code>
 
963
var t = new Ext.Template("&lt;div>Hello {0}.&lt;/div>");
 
964
t.{@link #append}('some-element', ['foo']);
 
965
 * </code></pre>
 
966
 * <li><tt>Array</tt> : </li>
 
967
 * An Array will be combined with <code>join('')</code>.
 
968
<pre><code>
 
969
var t = new Ext.Template([
 
970
    '&lt;div name="{id}"&gt;',
 
971
        '&lt;span class="{cls}"&gt;{name:trim} {value:ellipsis(10)}&lt;/span&gt;',
 
972
    '&lt;/div&gt;',
 
973
]);
 
974
t.{@link #compile}();
 
975
t.{@link #append}('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
 
976
</code></pre>
 
977
 * </ul></div></li>
 
978
 * <li><b>multiple arguments</b> : String, Object, Array, ...
 
979
 * <div class="sub-desc">
 
980
 * Multiple arguments will be combined with <code>join('')</code>.
 
981
 * <pre><code>
 
982
var t = new Ext.Template(
 
983
    '&lt;div name="{id}"&gt;',
 
984
        '&lt;span class="{cls}"&gt;{name} {value}&lt;/span&gt;',
 
985
    '&lt;/div&gt;',
 
986
    // a configuration object:
 
987
    {
 
988
        compiled: true,      // {@link #compile} immediately
 
989
        disableFormats: true // See Notes below.
 
990
    }
 
991
);
 
992
 * </code></pre>
 
993
 * <p><b>Notes</b>:</p>
 
994
 * <div class="mdetail-params"><ul>
 
995
 * <li>Formatting and <code>disableFormats</code> are not applicable for Ext Core.</li>
 
996
 * <li>For a list of available format functions, see {@link Ext.util.Format}.</li>
 
997
 * <li><code>disableFormats</code> reduces <code>{@link #apply}</code> time
 
998
 * when no formatting is required.</li>
 
999
 * </ul></div>
 
1000
 * </div></li>
 
1001
 * </ul></div>
 
1002
 * @param {Mixed} config
 
1003
 */
 
1004
Ext.Template = function(html){
 
1005
    var me = this,
 
1006
        a = arguments,
 
1007
        buf = [],
 
1008
        v;
 
1009
 
 
1010
    if (Ext.isArray(html)) {
 
1011
        html = html.join("");
 
1012
    } else if (a.length > 1) {
 
1013
        for(var i = 0, len = a.length; i < len; i++){
 
1014
            v = a[i];
 
1015
            if(typeof v == 'object'){
 
1016
                Ext.apply(me, v);
 
1017
            } else {
 
1018
                buf.push(v);
 
1019
            }
 
1020
        };
 
1021
        html = buf.join('');
 
1022
    }
 
1023
 
 
1024
    /**@private*/
 
1025
    me.html = html;
 
1026
    /**
 
1027
     * @cfg {Boolean} compiled Specify <tt>true</tt> to compile the template
 
1028
     * immediately (see <code>{@link #compile}</code>).
 
1029
     * Defaults to <tt>false</tt>.
 
1030
     */
 
1031
    if (me.compiled) {
 
1032
        me.compile();
 
1033
    }
 
1034
};
 
1035
Ext.Template.prototype = {
 
1036
    /**
 
1037
     * @cfg {RegExp} re The regular expression used to match template variables.
 
1038
     * Defaults to:<pre><code>
 
1039
     * re : /\{([\w-]+)\}/g                                     // for Ext Core
 
1040
     * re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g      // for Ext JS
 
1041
     * </code></pre>
 
1042
     */
 
1043
    re : /\{([\w-]+)\}/g,
 
1044
    /**
 
1045
     * See <code>{@link #re}</code>.
 
1046
     * @type RegExp
 
1047
     * @property re
 
1048
     */
 
1049
 
 
1050
    /**
 
1051
     * Returns an HTML fragment of this template with the specified <code>values</code> applied.
 
1052
     * @param {Object/Array} values
 
1053
     * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
 
1054
     * or an object (i.e. <code>{foo: 'bar'}</code>).
 
1055
     * @return {String} The HTML fragment
 
1056
     */
 
1057
    applyTemplate : function(values){
 
1058
        var me = this;
 
1059
 
 
1060
        return me.compiled ?
 
1061
                me.compiled(values) :
 
1062
                me.html.replace(me.re, function(m, name){
 
1063
                    return values[name] !== undefined ? values[name] : "";
 
1064
                });
 
1065
    },
 
1066
 
 
1067
    /**
 
1068
     * Sets the HTML used as the template and optionally compiles it.
 
1069
     * @param {String} html
 
1070
     * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
 
1071
     * @return {Ext.Template} this
 
1072
     */
 
1073
    set : function(html, compile){
 
1074
        var me = this;
 
1075
        me.html = html;
 
1076
        me.compiled = null;
 
1077
        return compile ? me.compile() : me;
 
1078
    },
 
1079
 
 
1080
    /**
 
1081
     * Compiles the template into an internal function, eliminating the RegEx overhead.
 
1082
     * @return {Ext.Template} this
 
1083
     */
 
1084
    compile : function(){
 
1085
        var me = this,
 
1086
            sep = Ext.isGecko ? "+" : ",";
 
1087
 
 
1088
        function fn(m, name){
 
1089
            name = "values['" + name + "']";
 
1090
            return "'"+ sep + '(' + name + " == undefined ? '' : " + name + ')' + sep + "'";
 
1091
        }
 
1092
 
 
1093
        eval("this.compiled = function(values){ return " + (Ext.isGecko ? "'" : "['") +
 
1094
             me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
 
1095
             (Ext.isGecko ?  "';};" : "'].join('');};"));
 
1096
        return me;
 
1097
    },
 
1098
 
 
1099
    /**
 
1100
     * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
 
1101
     * @param {Mixed} el The context element
 
1102
     * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
 
1103
     * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)
 
1104
     * @return {HTMLElement/Ext.Element} The new node or Element
 
1105
     */
 
1106
    insertFirst: function(el, values, returnElement){
 
1107
        return this.doInsert('afterBegin', el, values, returnElement);
 
1108
    },
 
1109
 
 
1110
    /**
 
1111
     * Applies the supplied values to the template and inserts the new node(s) before el.
 
1112
     * @param {Mixed} el The context element
 
1113
     * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
 
1114
     * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)
 
1115
     * @return {HTMLElement/Ext.Element} The new node or Element
 
1116
     */
 
1117
    insertBefore: function(el, values, returnElement){
 
1118
        return this.doInsert('beforeBegin', el, values, returnElement);
 
1119
    },
 
1120
 
 
1121
    /**
 
1122
     * Applies the supplied values to the template and inserts the new node(s) after el.
 
1123
     * @param {Mixed} el The context element
 
1124
     * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
 
1125
     * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)
 
1126
     * @return {HTMLElement/Ext.Element} The new node or Element
 
1127
     */
 
1128
    insertAfter : function(el, values, returnElement){
 
1129
        return this.doInsert('afterEnd', el, values, returnElement);
 
1130
    },
 
1131
 
 
1132
    /**
 
1133
     * Applies the supplied <code>values</code> to the template and appends
 
1134
     * the new node(s) to the specified <code>el</code>.
 
1135
     * <p>For example usage {@link #Template see the constructor}.</p>
 
1136
     * @param {Mixed} el The context element
 
1137
     * @param {Object/Array} values
 
1138
     * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
 
1139
     * or an object (i.e. <code>{foo: 'bar'}</code>).
 
1140
     * @param {Boolean} returnElement (optional) true to return an Ext.Element (defaults to undefined)
 
1141
     * @return {HTMLElement/Ext.Element} The new node or Element
 
1142
     */
 
1143
    append : function(el, values, returnElement){
 
1144
        return this.doInsert('beforeEnd', el, values, returnElement);
 
1145
    },
 
1146
 
 
1147
    doInsert : function(where, el, values, returnEl){
 
1148
        el = Ext.getDom(el);
 
1149
        var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
 
1150
        return returnEl ? Ext.get(newNode, true) : newNode;
 
1151
    },
 
1152
 
 
1153
    /**
 
1154
     * Applies the supplied values to the template and overwrites the content of el with the new node(s).
 
1155
     * @param {Mixed} el The context element
 
1156
     * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
 
1157
     * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)
 
1158
     * @return {HTMLElement/Ext.Element} The new node or Element
 
1159
     */
 
1160
    overwrite : function(el, values, returnElement){
 
1161
        el = Ext.getDom(el);
 
1162
        el.innerHTML = this.applyTemplate(values);
 
1163
        return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
 
1164
    }
 
1165
};
 
1166
/**
 
1167
 * Alias for {@link #applyTemplate}
 
1168
 * Returns an HTML fragment of this template with the specified <code>values</code> applied.
 
1169
 * @param {Object/Array} values
 
1170
 * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
 
1171
 * or an object (i.e. <code>{foo: 'bar'}</code>).
 
1172
 * @return {String} The HTML fragment
 
1173
 * @member Ext.Template
 
1174
 * @method apply
 
1175
 */
 
1176
Ext.Template.prototype.apply = Ext.Template.prototype.applyTemplate;
 
1177
 
 
1178
/**
 
1179
 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
 
1180
 * @param {String/HTMLElement} el A DOM element or its id
 
1181
 * @param {Object} config A configuration object
 
1182
 * @return {Ext.Template} The created template
 
1183
 * @static
 
1184
 */
 
1185
Ext.Template.from = function(el, config){
 
1186
    el = Ext.getDom(el);
 
1187
    return new Ext.Template(el.value || el.innerHTML, config || '');
 
1188
};
 
1189
/*
 
1190
 * This is code is also distributed under MIT license for use
 
1191
 * with jQuery and prototype JavaScript libraries.
 
1192
 */
 
1193
/**
 
1194
 * @class Ext.DomQuery
 
1195
Provides high performance selector/xpath processing by compiling queries into reusable functions. New pseudo classes and matchers can be plugged. It works on HTML and XML documents (if a content node is passed in).
 
1196
<p>
 
1197
DomQuery supports most of the <a href="http://www.w3.org/TR/2005/WD-css3-selectors-20051215/#selectors">CSS3 selectors spec</a>, along with some custom selectors and basic XPath.</p>
 
1198
 
 
1199
<p>
 
1200
All selectors, attribute filters and pseudos below can be combined infinitely in any order. For example "div.foo:nth-child(odd)[@foo=bar].bar:first" would be a perfectly valid selector. Node filters are processed in the order in which they appear, which allows you to optimize your queries for your document structure.
 
1201
</p>
 
1202
<h4>Element Selectors:</h4>
 
1203
<ul class="list">
 
1204
    <li> <b>*</b> any element</li>
 
1205
    <li> <b>E</b> an element with the tag E</li>
 
1206
    <li> <b>E F</b> All descendent elements of E that have the tag F</li>
 
1207
    <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
 
1208
    <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
 
1209
    <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
 
1210
</ul>
 
1211
<h4>Attribute Selectors:</h4>
 
1212
<p>The use of &#64; and quotes are optional. For example, div[&#64;foo='bar'] is also a valid attribute selector.</p>
 
1213
<ul class="list">
 
1214
    <li> <b>E[foo]</b> has an attribute "foo"</li>
 
1215
    <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
 
1216
    <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
 
1217
    <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
 
1218
    <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
 
1219
    <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
 
1220
    <li> <b>E[foo!=bar]</b> attribute "foo" does not equal "bar"</li>
 
1221
</ul>
 
1222
<h4>Pseudo Classes:</h4>
 
1223
<ul class="list">
 
1224
    <li> <b>E:first-child</b> E is the first child of its parent</li>
 
1225
    <li> <b>E:last-child</b> E is the last child of its parent</li>
 
1226
    <li> <b>E:nth-child(<i>n</i>)</b> E is the <i>n</i>th child of its parent (1 based as per the spec)</li>
 
1227
    <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
 
1228
    <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
 
1229
    <li> <b>E:only-child</b> E is the only child of its parent</li>
 
1230
    <li> <b>E:checked</b> E is an element that is has a checked attribute that is true (e.g. a radio or checkbox) </li>
 
1231
    <li> <b>E:first</b> the first E in the resultset</li>
 
1232
    <li> <b>E:last</b> the last E in the resultset</li>
 
1233
    <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
 
1234
    <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
 
1235
    <li> <b>E:even</b> shortcut for :nth-child(even)</li>
 
1236
    <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
 
1237
    <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
 
1238
    <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
 
1239
    <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
 
1240
    <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
 
1241
    <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
 
1242
    <li> <b>E:any(S1|S2|S2)</b> an E element which matches any of the simple selectors S1, S2 or S3//\\</li>
 
1243
</ul>
 
1244
<h4>CSS Value Selectors:</h4>
 
1245
<ul class="list">
 
1246
    <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
 
1247
    <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
 
1248
    <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
 
1249
    <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
 
1250
    <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
 
1251
    <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
 
1252
</ul>
 
1253
 * @singleton
 
1254
 */
 
1255
Ext.DomQuery = function(){
 
1256
    var cache = {}, 
 
1257
        simpleCache = {}, 
 
1258
        valueCache = {},
 
1259
        nonSpace = /\S/,
 
1260
        trimRe = /^\s+|\s+$/g,
 
1261
        tplRe = /\{(\d+)\}/g,
 
1262
        modeRe = /^(\s?[\/>+~]\s?|\s|$)/,
 
1263
        tagTokenRe = /^(#)?([\w-\*]+)/,
 
1264
        nthRe = /(\d*)n\+?(\d*)/, 
 
1265
        nthRe2 = /\D/,
 
1266
        // This is for IE MSXML which does not support expandos.
 
1267
        // IE runs the same speed using setAttribute, however FF slows way down
 
1268
        // and Safari completely fails so they need to continue to use expandos.
 
1269
        isIE = window.ActiveXObject ? true : false,
 
1270
        key = 30803;
 
1271
    
 
1272
    // this eval is stop the compressor from
 
1273
    // renaming the variable to something shorter
 
1274
    eval("var batch = 30803;");         
 
1275
 
 
1276
    // Retrieve the child node from a particular
 
1277
    // parent at the specified index.
 
1278
    function child(parent, index){
 
1279
        var i = 0,
 
1280
            n = parent.firstChild;
 
1281
        while(n){
 
1282
            if(n.nodeType == 1){
 
1283
               if(++i == index){
 
1284
                   return n;
 
1285
               }
 
1286
            }
 
1287
            n = n.nextSibling;
 
1288
        }
 
1289
        return null;
 
1290
    }
 
1291
 
 
1292
    // retrieve the next element node
 
1293
    function next(n){   
 
1294
        while((n = n.nextSibling) && n.nodeType != 1);
 
1295
        return n;
 
1296
    }
 
1297
 
 
1298
    // retrieve the previous element node 
 
1299
    function prev(n){
 
1300
        while((n = n.previousSibling) && n.nodeType != 1);
 
1301
        return n;
 
1302
    }
 
1303
 
 
1304
    // Mark each child node with a nodeIndex skipping and
 
1305
    // removing empty text nodes.
 
1306
    function children(parent){
 
1307
        var n = parent.firstChild,
 
1308
            nodeIndex = -1,
 
1309
            nextNode;
 
1310
        while(n){
 
1311
            nextNode = n.nextSibling;
 
1312
            // clean worthless empty nodes.
 
1313
            if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
 
1314
                parent.removeChild(n);
 
1315
            }else{
 
1316
                // add an expando nodeIndex
 
1317
                n.nodeIndex = ++nodeIndex;
 
1318
            }
 
1319
            n = nextNode;
 
1320
        }
 
1321
        return this;
 
1322
    }
 
1323
 
 
1324
 
 
1325
    // nodeSet - array of nodes
 
1326
    // cls - CSS Class
 
1327
    function byClassName(nodeSet, cls){
 
1328
        if(!cls){
 
1329
            return nodeSet;
 
1330
        }
 
1331
        var result = [], ri = -1;
 
1332
        for(var i = 0, ci; ci = nodeSet[i]; i++){
 
1333
            if((' '+ci.className+' ').indexOf(cls) != -1){
 
1334
                result[++ri] = ci;
 
1335
            }
 
1336
        }
 
1337
        return result;
 
1338
    };
 
1339
 
 
1340
    function attrValue(n, attr){
 
1341
        // if its an array, use the first node.
 
1342
        if(!n.tagName && typeof n.length != "undefined"){
 
1343
            n = n[0];
 
1344
        }
 
1345
        if(!n){
 
1346
            return null;
 
1347
        }
 
1348
 
 
1349
        if(attr == "for"){
 
1350
            return n.htmlFor;
 
1351
        }
 
1352
        if(attr == "class" || attr == "className"){
 
1353
            return n.className;
 
1354
        }
 
1355
        return n.getAttribute(attr) || n[attr];
 
1356
 
 
1357
    };
 
1358
 
 
1359
 
 
1360
    // ns - nodes
 
1361
    // mode - false, /, >, +, ~
 
1362
    // tagName - defaults to "*"
 
1363
    function getNodes(ns, mode, tagName){
 
1364
        var result = [], ri = -1, cs;
 
1365
        if(!ns){
 
1366
            return result;
 
1367
        }
 
1368
        tagName = tagName || "*";
 
1369
        // convert to array
 
1370
        if(typeof ns.getElementsByTagName != "undefined"){
 
1371
            ns = [ns];
 
1372
        }
 
1373
        
 
1374
        // no mode specified, grab all elements by tagName
 
1375
        // at any depth
 
1376
        if(!mode){
 
1377
            for(var i = 0, ni; ni = ns[i]; i++){
 
1378
                cs = ni.getElementsByTagName(tagName);
 
1379
                for(var j = 0, ci; ci = cs[j]; j++){
 
1380
                    result[++ri] = ci;
 
1381
                }
 
1382
            }
 
1383
        // Direct Child mode (/ or >)
 
1384
        // E > F or E/F all direct children elements of E that have the tag     
 
1385
        } else if(mode == "/" || mode == ">"){
 
1386
            var utag = tagName.toUpperCase();
 
1387
            for(var i = 0, ni, cn; ni = ns[i]; i++){
 
1388
                cn = ni.childNodes;
 
1389
                for(var j = 0, cj; cj = cn[j]; j++){
 
1390
                    if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){
 
1391
                        result[++ri] = cj;
 
1392
                    }
 
1393
                }
 
1394
            }
 
1395
        // Immediately Preceding mode (+)
 
1396
        // E + F all elements with the tag F that are immediately preceded by an element with the tag E
 
1397
        }else if(mode == "+"){
 
1398
            var utag = tagName.toUpperCase();
 
1399
            for(var i = 0, n; n = ns[i]; i++){
 
1400
                while((n = n.nextSibling) && n.nodeType != 1);
 
1401
                if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
 
1402
                    result[++ri] = n;
 
1403
                }
 
1404
            }
 
1405
        // Sibling mode (~)
 
1406
        // E ~ F all elements with the tag F that are preceded by a sibling element with the tag E
 
1407
        }else if(mode == "~"){
 
1408
            var utag = tagName.toUpperCase();
 
1409
            for(var i = 0, n; n = ns[i]; i++){
 
1410
                while((n = n.nextSibling)){
 
1411
                    if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){
 
1412
                        result[++ri] = n;
 
1413
                    }
 
1414
                }
 
1415
            }
 
1416
        }
 
1417
        return result;
 
1418
    }
 
1419
 
 
1420
    function concat(a, b){
 
1421
        if(b.slice){
 
1422
            return a.concat(b);
 
1423
        }
 
1424
        for(var i = 0, l = b.length; i < l; i++){
 
1425
            a[a.length] = b[i];
 
1426
        }
 
1427
        return a;
 
1428
    }
 
1429
 
 
1430
    function byTag(cs, tagName){
 
1431
        if(cs.tagName || cs == document){
 
1432
            cs = [cs];
 
1433
        }
 
1434
        if(!tagName){
 
1435
            return cs;
 
1436
        }
 
1437
        var result = [], ri = -1;
 
1438
        tagName = tagName.toLowerCase();
 
1439
        for(var i = 0, ci; ci = cs[i]; i++){
 
1440
            if(ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName){
 
1441
                result[++ri] = ci;
 
1442
            }
 
1443
        }
 
1444
        return result;
 
1445
    }
 
1446
 
 
1447
    function byId(cs, id){
 
1448
        if(cs.tagName || cs == document){
 
1449
            cs = [cs];
 
1450
        }
 
1451
        if(!id){
 
1452
            return cs;
 
1453
        }
 
1454
        var result = [], ri = -1;
 
1455
        for(var i = 0, ci; ci = cs[i]; i++){
 
1456
            if(ci && ci.id == id){
 
1457
                result[++ri] = ci;
 
1458
                return result;
 
1459
            }
 
1460
        }
 
1461
        return result;
 
1462
    }
 
1463
 
 
1464
    // operators are =, !=, ^=, $=, *=, %=, |= and ~=
 
1465
    // custom can be "{"
 
1466
    function byAttribute(cs, attr, value, op, custom){
 
1467
        var result = [], 
 
1468
            ri = -1, 
 
1469
            useGetStyle = custom == "{",            
 
1470
            fn = Ext.DomQuery.operators[op],        
 
1471
            a,
 
1472
            xml,
 
1473
            hasXml;
 
1474
            
 
1475
        for(var i = 0, ci; ci = cs[i]; i++){
 
1476
            // skip non-element nodes.
 
1477
            if(ci.nodeType != 1){
 
1478
                continue;
 
1479
            }
 
1480
            // only need to do this for the first node
 
1481
            if(!hasXml){
 
1482
                xml = Ext.DomQuery.isXml(ci);
 
1483
                hasXml = true;
 
1484
            }
 
1485
            
 
1486
            // we only need to change the property names if we're dealing with html nodes, not XML
 
1487
            if(!xml){
 
1488
                if(useGetStyle){
 
1489
                    a = Ext.DomQuery.getStyle(ci, attr);
 
1490
                } else if (attr == "class" || attr == "className"){
 
1491
                    a = ci.className;
 
1492
                } else if (attr == "for"){
 
1493
                    a = ci.htmlFor;
 
1494
                } else if (attr == "href"){
 
1495
                    // getAttribute href bug
 
1496
                    // http://www.glennjones.net/Post/809/getAttributehrefbug.htm
 
1497
                    a = ci.getAttribute("href", 2);
 
1498
                } else{
 
1499
                    a = ci.getAttribute(attr);
 
1500
                }
 
1501
            }else{
 
1502
                a = ci.getAttribute(attr);
 
1503
            }
 
1504
            if((fn && fn(a, value)) || (!fn && a)){
 
1505
                result[++ri] = ci;
 
1506
            }
 
1507
        }
 
1508
        return result;
 
1509
    }
 
1510
 
 
1511
    function byPseudo(cs, name, value){
 
1512
        return Ext.DomQuery.pseudos[name](cs, value);
 
1513
    }
 
1514
 
 
1515
    function nodupIEXml(cs){
 
1516
        var d = ++key, 
 
1517
            r;
 
1518
        cs[0].setAttribute("_nodup", d);
 
1519
        r = [cs[0]];
 
1520
        for(var i = 1, len = cs.length; i < len; i++){
 
1521
            var c = cs[i];
 
1522
            if(!c.getAttribute("_nodup") != d){
 
1523
                c.setAttribute("_nodup", d);
 
1524
                r[r.length] = c;
 
1525
            }
 
1526
        }
 
1527
        for(var i = 0, len = cs.length; i < len; i++){
 
1528
            cs[i].removeAttribute("_nodup");
 
1529
        }
 
1530
        return r;
 
1531
    }
 
1532
 
 
1533
    function nodup(cs){
 
1534
        if(!cs){
 
1535
            return [];
 
1536
        }
 
1537
        var len = cs.length, c, i, r = cs, cj, ri = -1;
 
1538
        if(!len || typeof cs.nodeType != "undefined" || len == 1){
 
1539
            return cs;
 
1540
        }
 
1541
        if(isIE && typeof cs[0].selectSingleNode != "undefined"){
 
1542
            return nodupIEXml(cs);
 
1543
        }
 
1544
        var d = ++key;
 
1545
        cs[0]._nodup = d;
 
1546
        for(i = 1; c = cs[i]; i++){
 
1547
            if(c._nodup != d){
 
1548
                c._nodup = d;
 
1549
            }else{
 
1550
                r = [];
 
1551
                for(var j = 0; j < i; j++){
 
1552
                    r[++ri] = cs[j];
 
1553
                }
 
1554
                for(j = i+1; cj = cs[j]; j++){
 
1555
                    if(cj._nodup != d){
 
1556
                        cj._nodup = d;
 
1557
                        r[++ri] = cj;
 
1558
                    }
 
1559
                }
 
1560
                return r;
 
1561
            }
 
1562
        }
 
1563
        return r;
 
1564
    }
 
1565
 
 
1566
    function quickDiffIEXml(c1, c2){
 
1567
        var d = ++key,
 
1568
            r = [];
 
1569
        for(var i = 0, len = c1.length; i < len; i++){
 
1570
            c1[i].setAttribute("_qdiff", d);
 
1571
        }        
 
1572
        for(var i = 0, len = c2.length; i < len; i++){
 
1573
            if(c2[i].getAttribute("_qdiff") != d){
 
1574
                r[r.length] = c2[i];
 
1575
            }
 
1576
        }
 
1577
        for(var i = 0, len = c1.length; i < len; i++){
 
1578
           c1[i].removeAttribute("_qdiff");
 
1579
        }
 
1580
        return r;
 
1581
    }
 
1582
 
 
1583
    function quickDiff(c1, c2){
 
1584
        var len1 = c1.length,
 
1585
                d = ++key,
 
1586
                r = [];
 
1587
        if(!len1){
 
1588
            return c2;
 
1589
        }
 
1590
        if(isIE && typeof c1[0].selectSingleNode != "undefined"){
 
1591
            return quickDiffIEXml(c1, c2);
 
1592
        }        
 
1593
        for(var i = 0; i < len1; i++){
 
1594
            c1[i]._qdiff = d;
 
1595
        }        
 
1596
        for(var i = 0, len = c2.length; i < len; i++){
 
1597
            if(c2[i]._qdiff != d){
 
1598
                r[r.length] = c2[i];
 
1599
            }
 
1600
        }
 
1601
        return r;
 
1602
    }
 
1603
 
 
1604
    function quickId(ns, mode, root, id){
 
1605
        if(ns == root){
 
1606
           var d = root.ownerDocument || root;
 
1607
           return d.getElementById(id);
 
1608
        }
 
1609
        ns = getNodes(ns, mode, "*");
 
1610
        return byId(ns, id);
 
1611
    }
 
1612
 
 
1613
    return {
 
1614
        getStyle : function(el, name){
 
1615
            return Ext.fly(el).getStyle(name);
 
1616
        },
 
1617
        /**
 
1618
         * Compiles a selector/xpath query into a reusable function. The returned function
 
1619
         * takes one parameter "root" (optional), which is the context node from where the query should start.
 
1620
         * @param {String} selector The selector/xpath query
 
1621
         * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
 
1622
         * @return {Function}
 
1623
         */
 
1624
        compile : function(path, type){
 
1625
            type = type || "select";
 
1626
 
 
1627
            // setup fn preamble
 
1628
            var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],
 
1629
                        mode,           
 
1630
                        lastPath,
 
1631
                matchers = Ext.DomQuery.matchers,
 
1632
                matchersLn = matchers.length,
 
1633
                modeMatch,
 
1634
                // accept leading mode switch
 
1635
                lmode = path.match(modeRe);
 
1636
            
 
1637
            if(lmode && lmode[1]){
 
1638
                fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
 
1639
                path = path.replace(lmode[1], "");
 
1640
            }
 
1641
            
 
1642
            // strip leading slashes
 
1643
            while(path.substr(0, 1)=="/"){
 
1644
                path = path.substr(1);
 
1645
            }
 
1646
 
 
1647
            while(path && lastPath != path){
 
1648
                lastPath = path;
 
1649
                var tokenMatch = path.match(tagTokenRe);
 
1650
                if(type == "select"){
 
1651
                    if(tokenMatch){
 
1652
                        // ID Selector
 
1653
                        if(tokenMatch[1] == "#"){
 
1654
                            fn[fn.length] = 'n = quickId(n, mode, root, "'+tokenMatch[2]+'");';                 
 
1655
                        }else{
 
1656
                            fn[fn.length] = 'n = getNodes(n, mode, "'+tokenMatch[2]+'");';
 
1657
                        }
 
1658
                        path = path.replace(tokenMatch[0], "");
 
1659
                    }else if(path.substr(0, 1) != '@'){
 
1660
                        fn[fn.length] = 'n = getNodes(n, mode, "*");';
 
1661
                    }
 
1662
                // type of "simple"
 
1663
                }else{
 
1664
                    if(tokenMatch){
 
1665
                        if(tokenMatch[1] == "#"){
 
1666
                            fn[fn.length] = 'n = byId(n, "'+tokenMatch[2]+'");';
 
1667
                        }else{
 
1668
                            fn[fn.length] = 'n = byTag(n, "'+tokenMatch[2]+'");';
 
1669
                        }
 
1670
                        path = path.replace(tokenMatch[0], "");
 
1671
                    }
 
1672
                }
 
1673
                while(!(modeMatch = path.match(modeRe))){
 
1674
                    var matched = false;
 
1675
                    for(var j = 0; j < matchersLn; j++){
 
1676
                        var t = matchers[j];
 
1677
                        var m = path.match(t.re);
 
1678
                        if(m){
 
1679
                            fn[fn.length] = t.select.replace(tplRe, function(x, i){
 
1680
                                return m[i];
 
1681
                            });
 
1682
                            path = path.replace(m[0], "");
 
1683
                            matched = true;
 
1684
                            break;
 
1685
                        }
 
1686
                    }
 
1687
                    // prevent infinite loop on bad selector
 
1688
                    if(!matched){
 
1689
                        throw 'Error parsing selector, parsing failed at "' + path + '"';
 
1690
                    }
 
1691
                }
 
1692
                if(modeMatch[1]){
 
1693
                    fn[fn.length] = 'mode="'+modeMatch[1].replace(trimRe, "")+'";';
 
1694
                    path = path.replace(modeMatch[1], "");
 
1695
                }
 
1696
            }
 
1697
            // close fn out
 
1698
            fn[fn.length] = "return nodup(n);\n}";
 
1699
            
 
1700
            // eval fn and return it
 
1701
            eval(fn.join(""));
 
1702
            return f;
 
1703
        },
 
1704
 
 
1705
        /**
 
1706
         * Selects a group of elements.
 
1707
         * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
 
1708
         * @param {Node/String} root (optional) The start of the query (defaults to document).
 
1709
         * @return {Array} An Array of DOM elements which match the selector. If there are
 
1710
         * no matches, and empty Array is returned.
 
1711
         */
 
1712
        jsSelect: function(path, root, type){
 
1713
            // set root to doc if not specified.
 
1714
            root = root || document;
 
1715
            
 
1716
            if(typeof root == "string"){
 
1717
                root = document.getElementById(root);
 
1718
            }
 
1719
            var paths = path.split(","),
 
1720
                results = [];
 
1721
                
 
1722
            // loop over each selector
 
1723
            for(var i = 0, len = paths.length; i < len; i++){           
 
1724
                var subPath = paths[i].replace(trimRe, "");
 
1725
                // compile and place in cache
 
1726
                if(!cache[subPath]){
 
1727
                    cache[subPath] = Ext.DomQuery.compile(subPath);
 
1728
                    if(!cache[subPath]){
 
1729
                        throw subPath + " is not a valid selector";
 
1730
                    }
 
1731
                }
 
1732
                var result = cache[subPath](root);
 
1733
                if(result && result != document){
 
1734
                    results = results.concat(result);
 
1735
                }
 
1736
            }
 
1737
            
 
1738
            // if there were multiple selectors, make sure dups
 
1739
            // are eliminated
 
1740
            if(paths.length > 1){
 
1741
                return nodup(results);
 
1742
            }
 
1743
            return results;
 
1744
        },
 
1745
        isXml: function(el) {
 
1746
            var docEl = (el ? el.ownerDocument || el : 0).documentElement;
 
1747
            return docEl ? docEl.nodeName !== "HTML" : false;
 
1748
        },
 
1749
        select : document.querySelectorAll ? function(path, root, type) {
 
1750
            root = root || document;
 
1751
            if (!Ext.DomQuery.isXml(root)) {
 
1752
                try {
 
1753
                    var cs = root.querySelectorAll(path);
 
1754
                    return Ext.toArray(cs);
 
1755
                }
 
1756
                catch (ex) {}           
 
1757
            }       
 
1758
            return Ext.DomQuery.jsSelect.call(this, path, root, type);
 
1759
        } : function(path, root, type) {
 
1760
            return Ext.DomQuery.jsSelect.call(this, path, root, type);
 
1761
        },
 
1762
 
 
1763
        /**
 
1764
         * Selects a single element.
 
1765
         * @param {String} selector The selector/xpath query
 
1766
         * @param {Node} root (optional) The start of the query (defaults to document).
 
1767
         * @return {Element} The DOM element which matched the selector.
 
1768
         */
 
1769
        selectNode : function(path, root){
 
1770
            return Ext.DomQuery.select(path, root)[0];
 
1771
        },
 
1772
 
 
1773
        /**
 
1774
         * Selects the value of a node, optionally replacing null with the defaultValue.
 
1775
         * @param {String} selector The selector/xpath query
 
1776
         * @param {Node} root (optional) The start of the query (defaults to document).
 
1777
         * @param {String} defaultValue
 
1778
         * @return {String}
 
1779
         */
 
1780
        selectValue : function(path, root, defaultValue){
 
1781
            path = path.replace(trimRe, "");
 
1782
            if(!valueCache[path]){
 
1783
                valueCache[path] = Ext.DomQuery.compile(path, "select");
 
1784
            }
 
1785
            var n = valueCache[path](root), v;
 
1786
            n = n[0] ? n[0] : n;
 
1787
                    
 
1788
            // overcome a limitation of maximum textnode size
 
1789
            // Rumored to potentially crash IE6 but has not been confirmed.
 
1790
            // http://reference.sitepoint.com/javascript/Node/normalize
 
1791
            // https://developer.mozilla.org/En/DOM/Node.normalize          
 
1792
            if (typeof n.normalize == 'function') n.normalize();
 
1793
            
 
1794
            v = (n && n.firstChild ? n.firstChild.nodeValue : null);
 
1795
            return ((v === null||v === undefined||v==='') ? defaultValue : v);
 
1796
        },
 
1797
 
 
1798
        /**
 
1799
         * Selects the value of a node, parsing integers and floats. Returns the defaultValue, or 0 if none is specified.
 
1800
         * @param {String} selector The selector/xpath query
 
1801
         * @param {Node} root (optional) The start of the query (defaults to document).
 
1802
         * @param {Number} defaultValue
 
1803
         * @return {Number}
 
1804
         */
 
1805
        selectNumber : function(path, root, defaultValue){
 
1806
            var v = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
 
1807
            return parseFloat(v);
 
1808
        },
 
1809
 
 
1810
        /**
 
1811
         * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
 
1812
         * @param {String/HTMLElement/Array} el An element id, element or array of elements
 
1813
         * @param {String} selector The simple selector to test
 
1814
         * @return {Boolean}
 
1815
         */
 
1816
        is : function(el, ss){
 
1817
            if(typeof el == "string"){
 
1818
                el = document.getElementById(el);
 
1819
            }
 
1820
            var isArray = Ext.isArray(el),
 
1821
                result = Ext.DomQuery.filter(isArray ? el : [el], ss);
 
1822
            return isArray ? (result.length == el.length) : (result.length > 0);
 
1823
        },
 
1824
 
 
1825
        /**
 
1826
         * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
 
1827
         * @param {Array} el An array of elements to filter
 
1828
         * @param {String} selector The simple selector to test
 
1829
         * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
 
1830
         * the selector instead of the ones that match
 
1831
         * @return {Array} An Array of DOM elements which match the selector. If there are
 
1832
         * no matches, and empty Array is returned.
 
1833
         */
 
1834
        filter : function(els, ss, nonMatches){
 
1835
            ss = ss.replace(trimRe, "");
 
1836
            if(!simpleCache[ss]){
 
1837
                simpleCache[ss] = Ext.DomQuery.compile(ss, "simple");
 
1838
            }
 
1839
            var result = simpleCache[ss](els);
 
1840
            return nonMatches ? quickDiff(result, els) : result;
 
1841
        },
 
1842
 
 
1843
        /**
 
1844
         * Collection of matching regular expressions and code snippets.
 
1845
         * Each capture group within () will be replace the {} in the select
 
1846
         * statement as specified by their index.
 
1847
         */
 
1848
        matchers : [{
 
1849
                re: /^\.([\w-]+)/,
 
1850
                select: 'n = byClassName(n, " {1} ");'
 
1851
            }, {
 
1852
                re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
 
1853
                select: 'n = byPseudo(n, "{1}", "{2}");'
 
1854
            },{
 
1855
                re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
 
1856
                select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
 
1857
            }, {
 
1858
                re: /^#([\w-]+)/,
 
1859
                select: 'n = byId(n, "{1}");'
 
1860
            },{
 
1861
                re: /^@([\w-]+)/,
 
1862
                select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
 
1863
            }
 
1864
        ],
 
1865
 
 
1866
        /**
 
1867
         * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
 
1868
         * New operators can be added as long as the match the format <i>c</i>= where <i>c</i> is any character other than space, &gt; &lt;.
 
1869
         */
 
1870
        operators : {
 
1871
            "=" : function(a, v){
 
1872
                return a == v;
 
1873
            },
 
1874
            "!=" : function(a, v){
 
1875
                return a != v;
 
1876
            },
 
1877
            "^=" : function(a, v){
 
1878
                return a && a.substr(0, v.length) == v;
 
1879
            },
 
1880
            "$=" : function(a, v){
 
1881
                return a && a.substr(a.length-v.length) == v;
 
1882
            },
 
1883
            "*=" : function(a, v){
 
1884
                return a && a.indexOf(v) !== -1;
 
1885
            },
 
1886
            "%=" : function(a, v){
 
1887
                return (a % v) == 0;
 
1888
            },
 
1889
            "|=" : function(a, v){
 
1890
                return a && (a == v || a.substr(0, v.length+1) == v+'-');
 
1891
            },
 
1892
            "~=" : function(a, v){
 
1893
                return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
 
1894
            }
 
1895
        },
 
1896
 
 
1897
        /**
 
1898
         * <p>Object hash of "pseudo class" filter functions which are used when filtering selections. Each function is passed
 
1899
         * two parameters:</p><div class="mdetail-params"><ul>
 
1900
         * <li><b>c</b> : Array<div class="sub-desc">An Array of DOM elements to filter.</div></li>
 
1901
         * <li><b>v</b> : String<div class="sub-desc">The argument (if any) supplied in the selector.</div></li>
 
1902
         * </ul></div>
 
1903
         * <p>A filter function returns an Array of DOM elements which conform to the pseudo class.</p>
 
1904
         * <p>In addition to the provided pseudo classes listed above such as <code>first-child</code> and <code>nth-child</code>,
 
1905
         * developers may add additional, custom psuedo class filters to select elements according to application-specific requirements.</p>
 
1906
         * <p>For example, to filter <code>&lt;a></code> elements to only return links to <i>external</i> resources:</p>
 
1907
         * <code><pre>
 
1908
Ext.DomQuery.pseudos.external = function(c, v){
 
1909
    var r = [], ri = -1;
 
1910
    for(var i = 0, ci; ci = c[i]; i++){
 
1911
//      Include in result set only if it's a link to an external resource
 
1912
        if(ci.hostname != location.hostname){
 
1913
            r[++ri] = ci;
 
1914
        }
 
1915
    }
 
1916
    return r;
 
1917
};</pre></code>
 
1918
         * Then external links could be gathered with the following statement:<code><pre>
 
1919
var externalLinks = Ext.select("a:external");
 
1920
</code></pre>
 
1921
         */
 
1922
        pseudos : {
 
1923
            "first-child" : function(c){
 
1924
                var r = [], ri = -1, n;
 
1925
                for(var i = 0, ci; ci = n = c[i]; i++){
 
1926
                    while((n = n.previousSibling) && n.nodeType != 1);
 
1927
                    if(!n){
 
1928
                        r[++ri] = ci;
 
1929
                    }
 
1930
                }
 
1931
                return r;
 
1932
            },
 
1933
 
 
1934
            "last-child" : function(c){
 
1935
                var r = [], ri = -1, n;
 
1936
                for(var i = 0, ci; ci = n = c[i]; i++){
 
1937
                    while((n = n.nextSibling) && n.nodeType != 1);
 
1938
                    if(!n){
 
1939
                        r[++ri] = ci;
 
1940
                    }
 
1941
                }
 
1942
                return r;
 
1943
            },
 
1944
 
 
1945
            "nth-child" : function(c, a) {
 
1946
                var r = [], ri = -1,
 
1947
                        m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a),
 
1948
                        f = (m[1] || 1) - 0, l = m[2] - 0;
 
1949
                for(var i = 0, n; n = c[i]; i++){
 
1950
                    var pn = n.parentNode;
 
1951
                    if (batch != pn._batch) {
 
1952
                        var j = 0;
 
1953
                        for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
 
1954
                            if(cn.nodeType == 1){
 
1955
                               cn.nodeIndex = ++j;
 
1956
                            }
 
1957
                        }
 
1958
                        pn._batch = batch;
 
1959
                    }
 
1960
                    if (f == 1) {
 
1961
                        if (l == 0 || n.nodeIndex == l){
 
1962
                            r[++ri] = n;
 
1963
                        }
 
1964
                    } else if ((n.nodeIndex + l) % f == 0){
 
1965
                        r[++ri] = n;
 
1966
                    }
 
1967
                }
 
1968
 
 
1969
                return r;
 
1970
            },
 
1971
 
 
1972
            "only-child" : function(c){
 
1973
                var r = [], ri = -1;;
 
1974
                for(var i = 0, ci; ci = c[i]; i++){
 
1975
                    if(!prev(ci) && !next(ci)){
 
1976
                        r[++ri] = ci;
 
1977
                    }
 
1978
                }
 
1979
                return r;
 
1980
            },
 
1981
 
 
1982
            "empty" : function(c){
 
1983
                var r = [], ri = -1;
 
1984
                for(var i = 0, ci; ci = c[i]; i++){
 
1985
                    var cns = ci.childNodes, j = 0, cn, empty = true;
 
1986
                    while(cn = cns[j]){
 
1987
                        ++j;
 
1988
                        if(cn.nodeType == 1 || cn.nodeType == 3){
 
1989
                            empty = false;
 
1990
                            break;
 
1991
                        }
 
1992
                    }
 
1993
                    if(empty){
 
1994
                        r[++ri] = ci;
 
1995
                    }
 
1996
                }
 
1997
                return r;
 
1998
            },
 
1999
 
 
2000
            "contains" : function(c, v){
 
2001
                var r = [], ri = -1;
 
2002
                for(var i = 0, ci; ci = c[i]; i++){
 
2003
                    if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
 
2004
                        r[++ri] = ci;
 
2005
                    }
 
2006
                }
 
2007
                return r;
 
2008
            },
 
2009
 
 
2010
            "nodeValue" : function(c, v){
 
2011
                var r = [], ri = -1;
 
2012
                for(var i = 0, ci; ci = c[i]; i++){
 
2013
                    if(ci.firstChild && ci.firstChild.nodeValue == v){
 
2014
                        r[++ri] = ci;
 
2015
                    }
 
2016
                }
 
2017
                return r;
 
2018
            },
 
2019
 
 
2020
            "checked" : function(c){
 
2021
                var r = [], ri = -1;
 
2022
                for(var i = 0, ci; ci = c[i]; i++){
 
2023
                    if(ci.checked == true){
 
2024
                        r[++ri] = ci;
 
2025
                    }
 
2026
                }
 
2027
                return r;
 
2028
            },
 
2029
 
 
2030
            "not" : function(c, ss){
 
2031
                return Ext.DomQuery.filter(c, ss, true);
 
2032
            },
 
2033
 
 
2034
            "any" : function(c, selectors){
 
2035
                var ss = selectors.split('|'),
 
2036
                        r = [], ri = -1, s;
 
2037
                for(var i = 0, ci; ci = c[i]; i++){
 
2038
                    for(var j = 0; s = ss[j]; j++){
 
2039
                        if(Ext.DomQuery.is(ci, s)){
 
2040
                            r[++ri] = ci;
 
2041
                            break;
 
2042
                        }
 
2043
                    }
 
2044
                }
 
2045
                return r;
 
2046
            },
 
2047
 
 
2048
            "odd" : function(c){
 
2049
                return this["nth-child"](c, "odd");
 
2050
            },
 
2051
 
 
2052
            "even" : function(c){
 
2053
                return this["nth-child"](c, "even");
 
2054
            },
 
2055
 
 
2056
            "nth" : function(c, a){
 
2057
                return c[a-1] || [];
 
2058
            },
 
2059
 
 
2060
            "first" : function(c){
 
2061
                return c[0] || [];
 
2062
            },
 
2063
 
 
2064
            "last" : function(c){
 
2065
                return c[c.length-1] || [];
 
2066
            },
 
2067
 
 
2068
            "has" : function(c, ss){
 
2069
                var s = Ext.DomQuery.select,
 
2070
                        r = [], ri = -1;
 
2071
                for(var i = 0, ci; ci = c[i]; i++){
 
2072
                    if(s(ss, ci).length > 0){
 
2073
                        r[++ri] = ci;
 
2074
                    }
 
2075
                }
 
2076
                return r;
 
2077
            },
 
2078
 
 
2079
            "next" : function(c, ss){
 
2080
                var is = Ext.DomQuery.is,
 
2081
                        r = [], ri = -1;
 
2082
                for(var i = 0, ci; ci = c[i]; i++){
 
2083
                    var n = next(ci);
 
2084
                    if(n && is(n, ss)){
 
2085
                        r[++ri] = ci;
 
2086
                    }
 
2087
                }
 
2088
                return r;
 
2089
            },
 
2090
 
 
2091
            "prev" : function(c, ss){
 
2092
                var is = Ext.DomQuery.is,
 
2093
                        r = [], ri = -1;
 
2094
                for(var i = 0, ci; ci = c[i]; i++){
 
2095
                    var n = prev(ci);
 
2096
                    if(n && is(n, ss)){
 
2097
                        r[++ri] = ci;
 
2098
                    }
 
2099
                }
 
2100
                return r;
 
2101
            }
 
2102
        }
 
2103
    };
 
2104
}();
 
2105
 
 
2106
/**
 
2107
 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Ext.DomQuery#select}
 
2108
 * @param {String} path The selector/xpath query
 
2109
 * @param {Node} root (optional) The start of the query (defaults to document).
 
2110
 * @return {Array}
 
2111
 * @member Ext
 
2112
 * @method query
 
2113
 */
 
2114
Ext.query = Ext.DomQuery.select;
 
2115
/**
 
2116
 * @class Ext.util.DelayedTask
 
2117
 * <p> The DelayedTask class provides a convenient way to "buffer" the execution of a method,
 
2118
 * performing setTimeout where a new timeout cancels the old timeout. When called, the
 
2119
 * task will wait the specified time period before executing. If durng that time period,
 
2120
 * the task is called again, the original call will be cancelled. This continues so that
 
2121
 * the function is only called a single time for each iteration.</p>
 
2122
 * <p>This method is especially useful for things like detecting whether a user has finished
 
2123
 * typing in a text field. An example would be performing validation on a keypress. You can
 
2124
 * use this class to buffer the keypress events for a certain number of milliseconds, and
 
2125
 * perform only if they stop for that amount of time.  Usage:</p><pre><code>
 
2126
var task = new Ext.util.DelayedTask(function(){
 
2127
    alert(Ext.getDom('myInputField').value.length);
 
2128
});
 
2129
// Wait 500ms before calling our function. If the user presses another key 
 
2130
// during that 500ms, it will be cancelled and we'll wait another 500ms.
 
2131
Ext.get('myInputField').on('keypress', function(){
 
2132
    task.{@link #delay}(500); 
 
2133
});
 
2134
 * </code></pre> 
 
2135
 * <p>Note that we are using a DelayedTask here to illustrate a point. The configuration
 
2136
 * option <tt>buffer</tt> for {@link Ext.util.Observable#addListener addListener/on} will
 
2137
 * also setup a delayed task for you to buffer events.</p> 
 
2138
 * @constructor The parameters to this constructor serve as defaults and are not required.
 
2139
 * @param {Function} fn (optional) The default function to call.
 
2140
 * @param {Object} scope The default scope (The <code><b>this</b></code> reference) in which the
 
2141
 * function is called. If not specified, <code>this</code> will refer to the browser window.
 
2142
 * @param {Array} args (optional) The default Array of arguments.
 
2143
 */
 
2144
Ext.util.DelayedTask = function(fn, scope, args){
 
2145
    var me = this,
 
2146
        id,     
 
2147
        call = function(){
 
2148
                clearInterval(id);
 
2149
                id = null;
 
2150
                fn.apply(scope, args || []);
 
2151
            };
 
2152
            
 
2153
    /**
 
2154
     * Cancels any pending timeout and queues a new one
 
2155
     * @param {Number} delay The milliseconds to delay
 
2156
     * @param {Function} newFn (optional) Overrides function passed to constructor
 
2157
     * @param {Object} newScope (optional) Overrides scope passed to constructor. Remember that if no scope
 
2158
     * is specified, <code>this</code> will refer to the browser window.
 
2159
     * @param {Array} newArgs (optional) Overrides args passed to constructor
 
2160
     */
 
2161
    me.delay = function(delay, newFn, newScope, newArgs){
 
2162
        me.cancel();
 
2163
        fn = newFn || fn;
 
2164
        scope = newScope || scope;
 
2165
        args = newArgs || args;
 
2166
        id = setInterval(call, delay);
 
2167
    };
 
2168
 
 
2169
    /**
 
2170
     * Cancel the last queued timeout
 
2171
     */
 
2172
    me.cancel = function(){
 
2173
        if(id){
 
2174
            clearInterval(id);
 
2175
            id = null;
 
2176
        }
 
2177
    };
 
2178
};/**
 
2179
 * @class Ext.Element
 
2180
 * <p>Encapsulates a DOM element, adding simple DOM manipulation facilities, normalizing for browser differences.</p>
 
2181
 * <p>All instances of this class inherit the methods of {@link Ext.Fx} making visual effects easily available to all DOM elements.</p>
 
2182
 * <p>Note that the events documented in this class are not Ext events, they encapsulate browser events. To
 
2183
 * access the underlying browser event, see {@link Ext.EventObject#browserEvent}. Some older
 
2184
 * browsers may not support the full range of events. Which events are supported is beyond the control of ExtJs.</p>
 
2185
 * Usage:<br>
 
2186
<pre><code>
 
2187
// by id
 
2188
var el = Ext.get("my-div");
 
2189
 
 
2190
// by DOM element reference
 
2191
var el = Ext.get(myDivElement);
 
2192
</code></pre>
 
2193
 * <b>Animations</b><br />
 
2194
 * <p>When an element is manipulated, by default there is no animation.</p>
 
2195
 * <pre><code>
 
2196
var el = Ext.get("my-div");
 
2197
 
 
2198
// no animation
 
2199
el.setWidth(100);
 
2200
 * </code></pre>
 
2201
 * <p>Many of the functions for manipulating an element have an optional "animate" parameter.  This
 
2202
 * parameter can be specified as boolean (<tt>true</tt>) for default animation effects.</p>
 
2203
 * <pre><code>
 
2204
// default animation
 
2205
el.setWidth(100, true);
 
2206
 * </code></pre>
 
2207
 *
 
2208
 * <p>To configure the effects, an object literal with animation options to use as the Element animation
 
2209
 * configuration object can also be specified. Note that the supported Element animation configuration
 
2210
 * options are a subset of the {@link Ext.Fx} animation options specific to Fx effects.  The supported
 
2211
 * Element animation configuration options are:</p>
 
2212
<pre>
 
2213
Option    Default   Description
 
2214
--------- --------  ---------------------------------------------
 
2215
{@link Ext.Fx#duration duration}  .35       The duration of the animation in seconds
 
2216
{@link Ext.Fx#easing easing}    easeOut   The easing method
 
2217
{@link Ext.Fx#callback callback}  none      A function to execute when the anim completes
 
2218
{@link Ext.Fx#scope scope}     this      The scope (this) of the callback function
 
2219
</pre>
 
2220
 *
 
2221
 * <pre><code>
 
2222
// Element animation options object
 
2223
var opt = {
 
2224
    {@link Ext.Fx#duration duration}: 1,
 
2225
    {@link Ext.Fx#easing easing}: 'elasticIn',
 
2226
    {@link Ext.Fx#callback callback}: this.foo,
 
2227
    {@link Ext.Fx#scope scope}: this
 
2228
};
 
2229
// animation with some options set
 
2230
el.setWidth(100, opt);
 
2231
 * </code></pre>
 
2232
 * <p>The Element animation object being used for the animation will be set on the options
 
2233
 * object as "anim", which allows you to stop or manipulate the animation. Here is an example:</p>
 
2234
 * <pre><code>
 
2235
// using the "anim" property to get the Anim object
 
2236
if(opt.anim.isAnimated()){
 
2237
    opt.anim.stop();
 
2238
}
 
2239
 * </code></pre>
 
2240
 * <p>Also see the <tt>{@link #animate}</tt> method for another animation technique.</p>
 
2241
 * <p><b> Composite (Collections of) Elements</b></p>
 
2242
 * <p>For working with collections of Elements, see {@link Ext.CompositeElement}</p>
 
2243
 * @constructor Create a new Element directly.
 
2244
 * @param {String/HTMLElement} element
 
2245
 * @param {Boolean} forceNew (optional) By default the constructor checks to see if there is already an instance of this element in the cache and if there is it returns the same instance. This will skip that check (useful for extending this class).
 
2246
 */
 
2247
(function(){
 
2248
var DOC = document;
 
2249
 
 
2250
Ext.Element = function(element, forceNew){
 
2251
    var dom = typeof element == "string" ?
 
2252
              DOC.getElementById(element) : element,
 
2253
        id;
 
2254
 
 
2255
    if(!dom) return null;
 
2256
 
 
2257
    id = dom.id;
 
2258
 
 
2259
    if(!forceNew && id && Ext.elCache[id]){ // element object already exists
 
2260
        return Ext.elCache[id].el;
 
2261
    }
 
2262
 
 
2263
    /**
 
2264
     * The DOM element
 
2265
     * @type HTMLElement
 
2266
     */
 
2267
    this.dom = dom;
 
2268
 
 
2269
    /**
 
2270
     * The DOM element ID
 
2271
     * @type String
 
2272
     */
 
2273
    this.id = id || Ext.id(dom);
 
2274
};
 
2275
 
 
2276
var DH = Ext.DomHelper,
 
2277
    El = Ext.Element,
 
2278
    EC = Ext.elCache;
 
2279
 
 
2280
El.prototype = {
 
2281
    /**
 
2282
     * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
 
2283
     * @param {Object} o The object with the attributes
 
2284
     * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
 
2285
     * @return {Ext.Element} this
 
2286
     */
 
2287
    set : function(o, useSet){
 
2288
        var el = this.dom,
 
2289
            attr,
 
2290
            val,
 
2291
            useSet = (useSet !== false) && !!el.setAttribute;
 
2292
 
 
2293
        for (attr in o) {
 
2294
            if (o.hasOwnProperty(attr)) {
 
2295
                val = o[attr];
 
2296
                if (attr == 'style') {
 
2297
                    DH.applyStyles(el, val);
 
2298
                } else if (attr == 'cls') {
 
2299
                    el.className = val;
 
2300
                } else if (useSet) {
 
2301
                    el.setAttribute(attr, val);
 
2302
                } else {
 
2303
                    el[attr] = val;
 
2304
                }
 
2305
            }
 
2306
        }
 
2307
        return this;
 
2308
    },
 
2309
 
 
2310
//  Mouse events
 
2311
    /**
 
2312
     * @event click
 
2313
     * Fires when a mouse click is detected within the element.
 
2314
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2315
     * @param {HtmlElement} t The target of the event.
 
2316
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2317
     */
 
2318
    /**
 
2319
     * @event contextmenu
 
2320
     * Fires when a right click is detected within the element.
 
2321
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2322
     * @param {HtmlElement} t The target of the event.
 
2323
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2324
     */
 
2325
    /**
 
2326
     * @event dblclick
 
2327
     * Fires when a mouse double click is detected within the element.
 
2328
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2329
     * @param {HtmlElement} t The target of the event.
 
2330
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2331
     */
 
2332
    /**
 
2333
     * @event mousedown
 
2334
     * Fires when a mousedown is detected within the element.
 
2335
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2336
     * @param {HtmlElement} t The target of the event.
 
2337
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2338
     */
 
2339
    /**
 
2340
     * @event mouseup
 
2341
     * Fires when a mouseup is detected within the element.
 
2342
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2343
     * @param {HtmlElement} t The target of the event.
 
2344
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2345
     */
 
2346
    /**
 
2347
     * @event mouseover
 
2348
     * Fires when a mouseover is detected within the element.
 
2349
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2350
     * @param {HtmlElement} t The target of the event.
 
2351
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2352
     */
 
2353
    /**
 
2354
     * @event mousemove
 
2355
     * Fires when a mousemove is detected with the element.
 
2356
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2357
     * @param {HtmlElement} t The target of the event.
 
2358
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2359
     */
 
2360
    /**
 
2361
     * @event mouseout
 
2362
     * Fires when a mouseout is detected with the element.
 
2363
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2364
     * @param {HtmlElement} t The target of the event.
 
2365
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2366
     */
 
2367
    /**
 
2368
     * @event mouseenter
 
2369
     * Fires when the mouse enters the element.
 
2370
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2371
     * @param {HtmlElement} t The target of the event.
 
2372
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2373
     */
 
2374
    /**
 
2375
     * @event mouseleave
 
2376
     * Fires when the mouse leaves the element.
 
2377
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2378
     * @param {HtmlElement} t The target of the event.
 
2379
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2380
     */
 
2381
 
 
2382
//  Keyboard events
 
2383
    /**
 
2384
     * @event keypress
 
2385
     * Fires when a keypress is detected within the element.
 
2386
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2387
     * @param {HtmlElement} t The target of the event.
 
2388
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2389
     */
 
2390
    /**
 
2391
     * @event keydown
 
2392
     * Fires when a keydown is detected within the element.
 
2393
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2394
     * @param {HtmlElement} t The target of the event.
 
2395
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2396
     */
 
2397
    /**
 
2398
     * @event keyup
 
2399
     * Fires when a keyup is detected within the element.
 
2400
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2401
     * @param {HtmlElement} t The target of the event.
 
2402
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2403
     */
 
2404
 
 
2405
 
 
2406
//  HTML frame/object events
 
2407
    /**
 
2408
     * @event load
 
2409
     * Fires when the user agent finishes loading all content within the element. Only supported by window, frames, objects and images.
 
2410
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2411
     * @param {HtmlElement} t The target of the event.
 
2412
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2413
     */
 
2414
    /**
 
2415
     * @event unload
 
2416
     * Fires when the user agent removes all content from a window or frame. For elements, it fires when the target element or any of its content has been removed.
 
2417
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2418
     * @param {HtmlElement} t The target of the event.
 
2419
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2420
     */
 
2421
    /**
 
2422
     * @event abort
 
2423
     * Fires when an object/image is stopped from loading before completely loaded.
 
2424
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2425
     * @param {HtmlElement} t The target of the event.
 
2426
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2427
     */
 
2428
    /**
 
2429
     * @event error
 
2430
     * Fires when an object/image/frame cannot be loaded properly.
 
2431
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2432
     * @param {HtmlElement} t The target of the event.
 
2433
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2434
     */
 
2435
    /**
 
2436
     * @event resize
 
2437
     * Fires when a document view is resized.
 
2438
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2439
     * @param {HtmlElement} t The target of the event.
 
2440
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2441
     */
 
2442
    /**
 
2443
     * @event scroll
 
2444
     * Fires when a document view is scrolled.
 
2445
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2446
     * @param {HtmlElement} t The target of the event.
 
2447
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2448
     */
 
2449
 
 
2450
//  Form events
 
2451
    /**
 
2452
     * @event select
 
2453
     * Fires when a user selects some text in a text field, including input and textarea.
 
2454
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2455
     * @param {HtmlElement} t The target of the event.
 
2456
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2457
     */
 
2458
    /**
 
2459
     * @event change
 
2460
     * Fires when a control loses the input focus and its value has been modified since gaining focus.
 
2461
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2462
     * @param {HtmlElement} t The target of the event.
 
2463
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2464
     */
 
2465
    /**
 
2466
     * @event submit
 
2467
     * Fires when a form is submitted.
 
2468
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2469
     * @param {HtmlElement} t The target of the event.
 
2470
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2471
     */
 
2472
    /**
 
2473
     * @event reset
 
2474
     * Fires when a form is reset.
 
2475
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2476
     * @param {HtmlElement} t The target of the event.
 
2477
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2478
     */
 
2479
    /**
 
2480
     * @event focus
 
2481
     * Fires when an element receives focus either via the pointing device or by tab navigation.
 
2482
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2483
     * @param {HtmlElement} t The target of the event.
 
2484
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2485
     */
 
2486
    /**
 
2487
     * @event blur
 
2488
     * Fires when an element loses focus either via the pointing device or by tabbing navigation.
 
2489
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2490
     * @param {HtmlElement} t The target of the event.
 
2491
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2492
     */
 
2493
 
 
2494
//  User Interface events
 
2495
    /**
 
2496
     * @event DOMFocusIn
 
2497
     * Where supported. Similar to HTML focus event, but can be applied to any focusable element.
 
2498
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2499
     * @param {HtmlElement} t The target of the event.
 
2500
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2501
     */
 
2502
    /**
 
2503
     * @event DOMFocusOut
 
2504
     * Where supported. Similar to HTML blur event, but can be applied to any focusable element.
 
2505
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2506
     * @param {HtmlElement} t The target of the event.
 
2507
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2508
     */
 
2509
    /**
 
2510
     * @event DOMActivate
 
2511
     * Where supported. Fires when an element is activated, for instance, through a mouse click or a keypress.
 
2512
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2513
     * @param {HtmlElement} t The target of the event.
 
2514
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2515
     */
 
2516
 
 
2517
//  DOM Mutation events
 
2518
    /**
 
2519
     * @event DOMSubtreeModified
 
2520
     * Where supported. Fires when the subtree is modified.
 
2521
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2522
     * @param {HtmlElement} t The target of the event.
 
2523
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2524
     */
 
2525
    /**
 
2526
     * @event DOMNodeInserted
 
2527
     * Where supported. Fires when a node has been added as a child of another node.
 
2528
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2529
     * @param {HtmlElement} t The target of the event.
 
2530
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2531
     */
 
2532
    /**
 
2533
     * @event DOMNodeRemoved
 
2534
     * Where supported. Fires when a descendant node of the element is removed.
 
2535
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2536
     * @param {HtmlElement} t The target of the event.
 
2537
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2538
     */
 
2539
    /**
 
2540
     * @event DOMNodeRemovedFromDocument
 
2541
     * Where supported. Fires when a node is being removed from a document.
 
2542
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2543
     * @param {HtmlElement} t The target of the event.
 
2544
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2545
     */
 
2546
    /**
 
2547
     * @event DOMNodeInsertedIntoDocument
 
2548
     * Where supported. Fires when a node is being inserted into a document.
 
2549
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2550
     * @param {HtmlElement} t The target of the event.
 
2551
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2552
     */
 
2553
    /**
 
2554
     * @event DOMAttrModified
 
2555
     * Where supported. Fires when an attribute has been modified.
 
2556
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2557
     * @param {HtmlElement} t The target of the event.
 
2558
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2559
     */
 
2560
    /**
 
2561
     * @event DOMCharacterDataModified
 
2562
     * Where supported. Fires when the character data has been modified.
 
2563
     * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.
 
2564
     * @param {HtmlElement} t The target of the event.
 
2565
     * @param {Object} o The options configuration passed to the {@link #addListener} call.
 
2566
     */
 
2567
 
 
2568
    /**
 
2569
     * The default unit to append to CSS values where a unit isn't provided (defaults to px).
 
2570
     * @type String
 
2571
     */
 
2572
    defaultUnit : "px",
 
2573
 
 
2574
    /**
 
2575
     * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
 
2576
     * @param {String} selector The simple selector to test
 
2577
     * @return {Boolean} True if this element matches the selector, else false
 
2578
     */
 
2579
    is : function(simpleSelector){
 
2580
        return Ext.DomQuery.is(this.dom, simpleSelector);
 
2581
    },
 
2582
 
 
2583
    /**
 
2584
     * Tries to focus the element. Any exceptions are caught and ignored.
 
2585
     * @param {Number} defer (optional) Milliseconds to defer the focus
 
2586
     * @return {Ext.Element} this
 
2587
     */
 
2588
    focus : function(defer, /* private */ dom) {
 
2589
        var me = this,
 
2590
            dom = dom || me.dom;
 
2591
        try{
 
2592
            if(Number(defer)){
 
2593
                me.focus.defer(defer, null, [null, dom]);
 
2594
            }else{
 
2595
                dom.focus();
 
2596
            }
 
2597
        }catch(e){}
 
2598
        return me;
 
2599
    },
 
2600
 
 
2601
    /**
 
2602
     * Tries to blur the element. Any exceptions are caught and ignored.
 
2603
     * @return {Ext.Element} this
 
2604
     */
 
2605
    blur : function() {
 
2606
        try{
 
2607
            this.dom.blur();
 
2608
        }catch(e){}
 
2609
        return this;
 
2610
    },
 
2611
 
 
2612
    /**
 
2613
     * Returns the value of the "value" attribute
 
2614
     * @param {Boolean} asNumber true to parse the value as a number
 
2615
     * @return {String/Number}
 
2616
     */
 
2617
    getValue : function(asNumber){
 
2618
        var val = this.dom.value;
 
2619
        return asNumber ? parseInt(val, 10) : val;
 
2620
    },
 
2621
 
 
2622
    /**
 
2623
     * Appends an event handler to this element.  The shorthand version {@link #on} is equivalent.
 
2624
     * @param {String} eventName The name of event to handle.
 
2625
     * @param {Function} fn The handler function the event invokes. This function is passed
 
2626
     * the following parameters:<ul>
 
2627
     * <li><b>evt</b> : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>
 
2628
     * <li><b>el</b> : HtmlElement<div class="sub-desc">The DOM element which was the target of the event.
 
2629
     * Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>
 
2630
     * <li><b>o</b> : Object<div class="sub-desc">The options object from the addListener call.</div></li>
 
2631
     * </ul>
 
2632
     * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the handler function is executed.
 
2633
     * <b>If omitted, defaults to this Element.</b>.
 
2634
     * @param {Object} options (optional) An object containing handler configuration properties.
 
2635
     * This may contain any of the following properties:<ul>
 
2636
     * <li><b>scope</b> Object : <div class="sub-desc">The scope (<code><b>this</b></code> reference) in which the handler function is executed.
 
2637
     * <b>If omitted, defaults to this Element.</b></div></li>
 
2638
     * <li><b>delegate</b> String: <div class="sub-desc">A simple selector to filter the target or look for a descendant of the target. See below for additional details.</div></li>
 
2639
     * <li><b>stopEvent</b> Boolean: <div class="sub-desc">True to stop the event. That is stop propagation, and prevent the default action.</div></li>
 
2640
     * <li><b>preventDefault</b> Boolean: <div class="sub-desc">True to prevent the default action</div></li>
 
2641
     * <li><b>stopPropagation</b> Boolean: <div class="sub-desc">True to prevent event propagation</div></li>
 
2642
     * <li><b>normalized</b> Boolean: <div class="sub-desc">False to pass a browser event to the handler function instead of an Ext.EventObject</div></li>
 
2643
     * <li><b>target</b> Ext.Element: <div class="sub-desc">Only call the handler if the event was fired on the target Element, <i>not</i> if the event was bubbled up from a child node.</div></li>
 
2644
     * <li><b>delay</b> Number: <div class="sub-desc">The number of milliseconds to delay the invocation of the handler after the event fires.</div></li>
 
2645
     * <li><b>single</b> Boolean: <div class="sub-desc">True to add a handler to handle just the next firing of the event, and then remove itself.</div></li>
 
2646
     * <li><b>buffer</b> Number: <div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
 
2647
     * by the specified number of milliseconds. If the event fires again within that time, the original
 
2648
     * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>
 
2649
     * </ul><br>
 
2650
     * <p>
 
2651
     * <b>Combining Options</b><br>
 
2652
     * In the following examples, the shorthand form {@link #on} is used rather than the more verbose
 
2653
     * addListener.  The two are equivalent.  Using the options argument, it is possible to combine different
 
2654
     * types of listeners:<br>
 
2655
     * <br>
 
2656
     * A delayed, one-time listener that auto stops the event and adds a custom argument (forumId) to the
 
2657
     * options object. The options object is available as the third parameter in the handler function.<div style="margin: 5px 20px 20px;">
 
2658
     * Code:<pre><code>
 
2659
el.on('click', this.onClick, this, {
 
2660
    single: true,
 
2661
    delay: 100,
 
2662
    stopEvent : true,
 
2663
    forumId: 4
 
2664
});</code></pre></p>
 
2665
     * <p>
 
2666
     * <b>Attaching multiple handlers in 1 call</b><br>
 
2667
     * The method also allows for a single argument to be passed which is a config object containing properties
 
2668
     * which specify multiple handlers.</p>
 
2669
     * <p>
 
2670
     * Code:<pre><code>
 
2671
el.on({
 
2672
    'click' : {
 
2673
        fn: this.onClick,
 
2674
        scope: this,
 
2675
        delay: 100
 
2676
    },
 
2677
    'mouseover' : {
 
2678
        fn: this.onMouseOver,
 
2679
        scope: this
 
2680
    },
 
2681
    'mouseout' : {
 
2682
        fn: this.onMouseOut,
 
2683
        scope: this
 
2684
    }
 
2685
});</code></pre>
 
2686
     * <p>
 
2687
     * Or a shorthand syntax:<br>
 
2688
     * Code:<pre><code></p>
 
2689
el.on({
 
2690
    'click' : this.onClick,
 
2691
    'mouseover' : this.onMouseOver,
 
2692
    'mouseout' : this.onMouseOut,
 
2693
    scope: this
 
2694
});
 
2695
     * </code></pre></p>
 
2696
     * <p><b>delegate</b></p>
 
2697
     * <p>This is a configuration option that you can pass along when registering a handler for
 
2698
     * an event to assist with event delegation. Event delegation is a technique that is used to
 
2699
     * reduce memory consumption and prevent exposure to memory-leaks. By registering an event
 
2700
     * for a container element as opposed to each element within a container. By setting this
 
2701
     * configuration option to a simple selector, the target element will be filtered to look for
 
2702
     * a descendant of the target.
 
2703
     * For example:<pre><code>
 
2704
// using this markup:
 
2705
&lt;div id='elId'>
 
2706
    &lt;p id='p1'>paragraph one&lt;/p>
 
2707
    &lt;p id='p2' class='clickable'>paragraph two&lt;/p>
 
2708
    &lt;p id='p3'>paragraph three&lt;/p>
 
2709
&lt;/div>
 
2710
// utilize event delegation to registering just one handler on the container element:
 
2711
el = Ext.get('elId');
 
2712
el.on(
 
2713
    'click',
 
2714
    function(e,t) {
 
2715
        // handle click
 
2716
        console.info(t.id); // 'p2'
 
2717
    },
 
2718
    this,
 
2719
    {
 
2720
        // filter the target element to be a descendant with the class 'clickable'
 
2721
        delegate: '.clickable'
 
2722
    }
 
2723
);
 
2724
     * </code></pre></p>
 
2725
     * @return {Ext.Element} this
 
2726
     */
 
2727
    addListener : function(eventName, fn, scope, options){
 
2728
        Ext.EventManager.on(this.dom,  eventName, fn, scope || this, options);
 
2729
        return this;
 
2730
    },
 
2731
 
 
2732
    /**
 
2733
     * Removes an event handler from this element.  The shorthand version {@link #un} is equivalent.
 
2734
     * <b>Note</b>: if a <i>scope</i> was explicitly specified when {@link #addListener adding} the
 
2735
     * listener, the same scope must be specified here.
 
2736
     * Example:
 
2737
     * <pre><code>
 
2738
el.removeListener('click', this.handlerFn);
 
2739
// or
 
2740
el.un('click', this.handlerFn);
 
2741
</code></pre>
 
2742
     * @param {String} eventName The name of the event from which to remove the handler.
 
2743
     * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
 
2744
     * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
 
2745
     * then this must refer to the same object.
 
2746
     * @return {Ext.Element} this
 
2747
     */
 
2748
    removeListener : function(eventName, fn, scope){
 
2749
        Ext.EventManager.removeListener(this.dom,  eventName, fn, scope || this);
 
2750
        return this;
 
2751
    },
 
2752
 
 
2753
    /**
 
2754
     * Removes all previous added listeners from this element
 
2755
     * @return {Ext.Element} this
 
2756
     */
 
2757
    removeAllListeners : function(){
 
2758
        Ext.EventManager.removeAll(this.dom);
 
2759
        return this;
 
2760
    },
 
2761
 
 
2762
    /**
 
2763
     * Recursively removes all previous added listeners from this element and its children
 
2764
     * @return {Ext.Element} this
 
2765
     */
 
2766
    purgeAllListeners : function() {
 
2767
        Ext.EventManager.purgeElement(this, true);
 
2768
        return this;
 
2769
    },
 
2770
    /**
 
2771
     * @private Test if size has a unit, otherwise appends the default
 
2772
     */
 
2773
    addUnits : function(size){
 
2774
        if(size === "" || size == "auto" || size === undefined){
 
2775
            size = size || '';
 
2776
        } else if(!isNaN(size) || !unitPattern.test(size)){
 
2777
            size = size + (this.defaultUnit || 'px');
 
2778
        }
 
2779
        return size;
 
2780
    },
 
2781
 
 
2782
    /**
 
2783
     * <p>Updates the <a href="http://developer.mozilla.org/en/DOM/element.innerHTML">innerHTML</a> of this Element
 
2784
     * from a specified URL. Note that this is subject to the <a href="http://en.wikipedia.org/wiki/Same_origin_policy">Same Origin Policy</a></p>
 
2785
     * <p>Updating innerHTML of an element will <b>not</b> execute embedded <tt>&lt;script></tt> elements. This is a browser restriction.</p>
 
2786
     * @param {Mixed} options. Either a sring containing the URL from which to load the HTML, or an {@link Ext.Ajax#request} options object specifying
 
2787
     * exactly how to request the HTML.
 
2788
     * @return {Ext.Element} this
 
2789
     */
 
2790
    load : function(url, params, cb){
 
2791
        Ext.Ajax.request(Ext.apply({
 
2792
            params: params,
 
2793
            url: url.url || url,
 
2794
            callback: cb,
 
2795
            el: this.dom,
 
2796
            indicatorText: url.indicatorText || ''
 
2797
        }, Ext.isObject(url) ? url : {}));
 
2798
        return this;
 
2799
    },
 
2800
 
 
2801
    /**
 
2802
     * Tests various css rules/browsers to determine if this element uses a border box
 
2803
     * @return {Boolean}
 
2804
     */
 
2805
    isBorderBox : function(){
 
2806
        return Ext.isBorderBox || Ext.isForcedBorderBox || noBoxAdjust[(this.dom.tagName || "").toLowerCase()];
 
2807
    },
 
2808
 
 
2809
    /**
 
2810
     * <p>Removes this element's dom reference.  Note that event and cache removal is handled at {@link Ext#removeNode}</p>
 
2811
     */
 
2812
    remove : function(){
 
2813
        var me = this,
 
2814
            dom = me.dom;
 
2815
 
 
2816
        if (dom) {
 
2817
            delete me.dom;
 
2818
            Ext.removeNode(dom);
 
2819
        }
 
2820
    },
 
2821
 
 
2822
    /**
 
2823
     * Sets up event handlers to call the passed functions when the mouse is moved into and out of the Element.
 
2824
     * @param {Function} overFn The function to call when the mouse enters the Element.
 
2825
     * @param {Function} outFn The function to call when the mouse leaves the Element.
 
2826
     * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the functions are executed. Defaults to the Element's DOM element.
 
2827
     * @param {Object} options (optional) Options for the listener. See {@link Ext.util.Observable#addListener the <tt>options</tt> parameter}.
 
2828
     * @return {Ext.Element} this
 
2829
     */
 
2830
    hover : function(overFn, outFn, scope, options){
 
2831
        var me = this;
 
2832
        me.on('mouseenter', overFn, scope || me.dom, options);
 
2833
        me.on('mouseleave', outFn, scope || me.dom, options);
 
2834
        return me;
 
2835
    },
 
2836
 
 
2837
    /**
 
2838
     * Returns true if this element is an ancestor of the passed element
 
2839
     * @param {HTMLElement/String} el The element to check
 
2840
     * @return {Boolean} True if this element is an ancestor of el, else false
 
2841
     */
 
2842
    contains : function(el){
 
2843
        return !el ? false : Ext.lib.Dom.isAncestor(this.dom, el.dom ? el.dom : el);
 
2844
    },
 
2845
 
 
2846
    /**
 
2847
     * Returns the value of a namespaced attribute from the element's underlying DOM node.
 
2848
     * @param {String} namespace The namespace in which to look for the attribute
 
2849
     * @param {String} name The attribute name
 
2850
     * @return {String} The attribute value
 
2851
     * @deprecated
 
2852
     */
 
2853
    getAttributeNS : function(ns, name){
 
2854
        return this.getAttribute(name, ns);
 
2855
    },
 
2856
 
 
2857
    /**
 
2858
     * Returns the value of an attribute from the element's underlying DOM node.
 
2859
     * @param {String} name The attribute name
 
2860
     * @param {String} namespace (optional) The namespace in which to look for the attribute
 
2861
     * @return {String} The attribute value
 
2862
     */
 
2863
    getAttribute : Ext.isIE ? function(name, ns){
 
2864
        var d = this.dom,
 
2865
            type = typeof d[ns + ":" + name];
 
2866
 
 
2867
        if(['undefined', 'unknown'].indexOf(type) == -1){
 
2868
            return d[ns + ":" + name];
 
2869
        }
 
2870
        return d[name];
 
2871
    } : function(name, ns){
 
2872
        var d = this.dom;
 
2873
        return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name) || d.getAttribute(name) || d[name];
 
2874
    },
 
2875
 
 
2876
    /**
 
2877
    * Update the innerHTML of this element
 
2878
    * @param {String} html The new HTML
 
2879
    * @return {Ext.Element} this
 
2880
     */
 
2881
    update : function(html) {
 
2882
        if (this.dom) {
 
2883
            this.dom.innerHTML = html;
 
2884
        }
 
2885
        return this;
 
2886
    }
 
2887
};
 
2888
 
 
2889
var ep = El.prototype;
 
2890
 
 
2891
El.addMethods = function(o){
 
2892
   Ext.apply(ep, o);
 
2893
};
 
2894
 
 
2895
/**
 
2896
 * Appends an event handler (shorthand for {@link #addListener}).
 
2897
 * @param {String} eventName The name of event to handle.
 
2898
 * @param {Function} fn The handler function the event invokes.
 
2899
 * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function is executed.
 
2900
 * @param {Object} options (optional) An object containing standard {@link #addListener} options
 
2901
 * @member Ext.Element
 
2902
 * @method on
 
2903
 */
 
2904
ep.on = ep.addListener;
 
2905
 
 
2906
/**
 
2907
 * Removes an event handler from this element (see {@link #removeListener} for additional notes).
 
2908
 * @param {String} eventName The name of the event from which to remove the handler.
 
2909
 * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
 
2910
 * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
 
2911
 * then this must refer to the same object.
 
2912
 * @return {Ext.Element} this
 
2913
 * @member Ext.Element
 
2914
 * @method un
 
2915
 */
 
2916
ep.un = ep.removeListener;
 
2917
 
 
2918
/**
 
2919
 * true to automatically adjust width and height settings for box-model issues (default to true)
 
2920
 */
 
2921
ep.autoBoxAdjust = true;
 
2922
 
 
2923
// private
 
2924
var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
 
2925
    docEl;
 
2926
 
 
2927
/**
 
2928
 * @private
 
2929
 */
 
2930
 
 
2931
/**
 
2932
 * Retrieves Ext.Element objects.
 
2933
 * <p><b>This method does not retrieve {@link Ext.Component Component}s.</b> This method
 
2934
 * retrieves Ext.Element objects which encapsulate DOM elements. To retrieve a Component by
 
2935
 * its ID, use {@link Ext.ComponentMgr#get}.</p>
 
2936
 * <p>Uses simple caching to consistently return the same object. Automatically fixes if an
 
2937
 * object was recreated with the same id via AJAX or DOM.</p>
 
2938
 * @param {Mixed} el The id of the node, a DOM Node or an existing Element.
 
2939
 * @return {Element} The Element object (or null if no matching element was found)
 
2940
 * @static
 
2941
 * @member Ext.Element
 
2942
 * @method get
 
2943
 */
 
2944
El.get = function(el){
 
2945
    var ex,
 
2946
        elm,
 
2947
        id;
 
2948
    if(!el){ return null; }
 
2949
    if (typeof el == "string") { // element id
 
2950
        if (!(elm = DOC.getElementById(el))) {
 
2951
            return null;
 
2952
        }
 
2953
        if (EC[el] && EC[el].el) {
 
2954
            ex = EC[el].el;
 
2955
            ex.dom = elm;
 
2956
        } else {
 
2957
            ex = El.addToCache(new El(elm));
 
2958
        }
 
2959
        return ex;
 
2960
    } else if (el.tagName) { // dom element
 
2961
        if(!(id = el.id)){
 
2962
            id = Ext.id(el);
 
2963
        }
 
2964
        if (EC[id] && EC[id].el) {
 
2965
            ex = EC[id].el;
 
2966
            ex.dom = el;
 
2967
        } else {
 
2968
            ex = El.addToCache(new El(el));
 
2969
        }
 
2970
        return ex;
 
2971
    } else if (el instanceof El) {
 
2972
        if(el != docEl){
 
2973
            // refresh dom element in case no longer valid,
 
2974
            // catch case where it hasn't been appended
 
2975
 
 
2976
            // If an el instance is passed, don't pass to getElementById without some kind of id
 
2977
            if (Ext.isIE && (el.id == undefined || el.id == '')) {
 
2978
                el.dom = el.dom;
 
2979
            } else {
 
2980
                el.dom = DOC.getElementById(el.id) || el.dom;
 
2981
            }
 
2982
        }
 
2983
        return el;
 
2984
    } else if(el.isComposite) {
 
2985
        return el;
 
2986
    } else if(Ext.isArray(el)) {
 
2987
        return El.select(el);
 
2988
    } else if(el == DOC) {
 
2989
        // create a bogus element object representing the document object
 
2990
        if(!docEl){
 
2991
            var f = function(){};
 
2992
            f.prototype = El.prototype;
 
2993
            docEl = new f();
 
2994
            docEl.dom = DOC;
 
2995
        }
 
2996
        return docEl;
 
2997
    }
 
2998
    return null;
 
2999
};
 
3000
 
 
3001
El.addToCache = function(el, id){
 
3002
    id = id || el.id;
 
3003
    EC[id] = {
 
3004
        el:  el,
 
3005
        data: {},
 
3006
        events: {}
 
3007
    };
 
3008
    return el;
 
3009
};
 
3010
 
 
3011
// private method for getting and setting element data
 
3012
El.data = function(el, key, value){
 
3013
    el = El.get(el);
 
3014
    if (!el) {
 
3015
        return null;
 
3016
    }
 
3017
    var c = EC[el.id].data;
 
3018
    if(arguments.length == 2){
 
3019
        return c[key];
 
3020
    }else{
 
3021
        return (c[key] = value);
 
3022
    }
 
3023
};
 
3024
 
 
3025
// private
 
3026
// Garbage collection - uncache elements/purge listeners on orphaned elements
 
3027
// so we don't hold a reference and cause the browser to retain them
 
3028
function garbageCollect(){
 
3029
    if(!Ext.enableGarbageCollector){
 
3030
        clearInterval(El.collectorThreadId);
 
3031
    } else {
 
3032
        var eid,
 
3033
            el,
 
3034
            d,
 
3035
            o;
 
3036
 
 
3037
        for(eid in EC){
 
3038
            o = EC[eid];
 
3039
            if(o.skipGC){
 
3040
                continue;
 
3041
            }
 
3042
            el = o.el;
 
3043
            d = el.dom;
 
3044
            // -------------------------------------------------------
 
3045
            // Determining what is garbage:
 
3046
            // -------------------------------------------------------
 
3047
            // !d
 
3048
            // dom node is null, definitely garbage
 
3049
            // -------------------------------------------------------
 
3050
            // !d.parentNode
 
3051
            // no parentNode == direct orphan, definitely garbage
 
3052
            // -------------------------------------------------------
 
3053
            // !d.offsetParent && !document.getElementById(eid)
 
3054
            // display none elements have no offsetParent so we will
 
3055
            // also try to look it up by it's id. However, check
 
3056
            // offsetParent first so we don't do unneeded lookups.
 
3057
            // This enables collection of elements that are not orphans
 
3058
            // directly, but somewhere up the line they have an orphan
 
3059
            // parent.
 
3060
            // -------------------------------------------------------
 
3061
            if(!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))){
 
3062
                if(Ext.enableListenerCollection){
 
3063
                    Ext.EventManager.removeAll(d);
 
3064
                }
 
3065
                delete EC[eid];
 
3066
            }
 
3067
        }
 
3068
        // Cleanup IE Object leaks
 
3069
        if (Ext.isIE) {
 
3070
            var t = {};
 
3071
            for (eid in EC) {
 
3072
                t[eid] = EC[eid];
 
3073
            }
 
3074
            EC = Ext.elCache = t;
 
3075
        }
 
3076
    }
 
3077
}
 
3078
El.collectorThreadId = setInterval(garbageCollect, 30000);
 
3079
 
 
3080
var flyFn = function(){};
 
3081
flyFn.prototype = El.prototype;
 
3082
 
 
3083
// dom is optional
 
3084
El.Flyweight = function(dom){
 
3085
    this.dom = dom;
 
3086
};
 
3087
 
 
3088
El.Flyweight.prototype = new flyFn();
 
3089
El.Flyweight.prototype.isFlyweight = true;
 
3090
El._flyweights = {};
 
3091
 
 
3092
/**
 
3093
 * <p>Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
 
3094
 * the dom node can be overwritten by other code. Shorthand of {@link Ext.Element#fly}</p>
 
3095
 * <p>Use this to make one-time references to DOM elements which are not going to be accessed again either by
 
3096
 * application code, or by Ext's classes. If accessing an element which will be processed regularly, then {@link Ext#get}
 
3097
 * will be more appropriate to take advantage of the caching provided by the Ext.Element class.</p>
 
3098
 * @param {String/HTMLElement} el The dom node or id
 
3099
 * @param {String} named (optional) Allows for creation of named reusable flyweights to prevent conflicts
 
3100
 * (e.g. internally Ext uses "_global")
 
3101
 * @return {Element} The shared Element object (or null if no matching element was found)
 
3102
 * @member Ext.Element
 
3103
 * @method fly
 
3104
 */
 
3105
El.fly = function(el, named){
 
3106
    var ret = null;
 
3107
    named = named || '_global';
 
3108
 
 
3109
    if (el = Ext.getDom(el)) {
 
3110
        (El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
 
3111
        ret = El._flyweights[named];
 
3112
    }
 
3113
    return ret;
 
3114
};
 
3115
 
 
3116
/**
 
3117
 * Retrieves Ext.Element objects.
 
3118
 * <p><b>This method does not retrieve {@link Ext.Component Component}s.</b> This method
 
3119
 * retrieves Ext.Element objects which encapsulate DOM elements. To retrieve a Component by
 
3120
 * its ID, use {@link Ext.ComponentMgr#get}.</p>
 
3121
 * <p>Uses simple caching to consistently return the same object. Automatically fixes if an
 
3122
 * object was recreated with the same id via AJAX or DOM.</p>
 
3123
 * Shorthand of {@link Ext.Element#get}
 
3124
 * @param {Mixed} el The id of the node, a DOM Node or an existing Element.
 
3125
 * @return {Element} The Element object (or null if no matching element was found)
 
3126
 * @member Ext
 
3127
 * @method get
 
3128
 */
 
3129
Ext.get = El.get;
 
3130
 
 
3131
/**
 
3132
 * <p>Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
 
3133
 * the dom node can be overwritten by other code. Shorthand of {@link Ext.Element#fly}</p>
 
3134
 * <p>Use this to make one-time references to DOM elements which are not going to be accessed again either by
 
3135
 * application code, or by Ext's classes. If accessing an element which will be processed regularly, then {@link Ext#get}
 
3136
 * will be more appropriate to take advantage of the caching provided by the Ext.Element class.</p>
 
3137
 * @param {String/HTMLElement} el The dom node or id
 
3138
 * @param {String} named (optional) Allows for creation of named reusable flyweights to prevent conflicts
 
3139
 * (e.g. internally Ext uses "_global")
 
3140
 * @return {Element} The shared Element object (or null if no matching element was found)
 
3141
 * @member Ext
 
3142
 * @method fly
 
3143
 */
 
3144
Ext.fly = El.fly;
 
3145
 
 
3146
// speedy lookup for elements never to box adjust
 
3147
var noBoxAdjust = Ext.isStrict ? {
 
3148
    select:1
 
3149
} : {
 
3150
    input:1, select:1, textarea:1
 
3151
};
 
3152
if(Ext.isIE || Ext.isGecko){
 
3153
    noBoxAdjust['button'] = 1;
 
3154
}
 
3155
 
 
3156
})();
 
3157
/**
 
3158
 * @class Ext.Element
 
3159
 */
 
3160
Ext.Element.addMethods(function(){
 
3161
        var PARENTNODE = 'parentNode',
 
3162
                NEXTSIBLING = 'nextSibling',
 
3163
                PREVIOUSSIBLING = 'previousSibling',
 
3164
                DQ = Ext.DomQuery,
 
3165
                GET = Ext.get;
 
3166
        
 
3167
        return {
 
3168
                /**
 
3169
             * Looks at this node and then at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
 
3170
             * @param {String} selector The simple selector to test
 
3171
             * @param {Number/Mixed} maxDepth (optional) The max depth to search as a number or element (defaults to 50 || document.body)
 
3172
             * @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node
 
3173
             * @return {HTMLElement} The matching DOM node (or null if no match was found)
 
3174
             */
 
3175
            findParent : function(simpleSelector, maxDepth, returnEl){
 
3176
                var p = this.dom,
 
3177
                        b = document.body, 
 
3178
                        depth = 0,                      
 
3179
                        stopEl;         
 
3180
            if(Ext.isGecko && Object.prototype.toString.call(p) == '[object XULElement]') {
 
3181
                return null;
 
3182
            }
 
3183
                maxDepth = maxDepth || 50;
 
3184
                if (isNaN(maxDepth)) {
 
3185
                    stopEl = Ext.getDom(maxDepth);
 
3186
                    maxDepth = Number.MAX_VALUE;
 
3187
                }
 
3188
                while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
 
3189
                    if(DQ.is(p, simpleSelector)){
 
3190
                        return returnEl ? GET(p) : p;
 
3191
                    }
 
3192
                    depth++;
 
3193
                    p = p.parentNode;
 
3194
                }
 
3195
                return null;
 
3196
            },
 
3197
        
 
3198
            /**
 
3199
             * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
 
3200
             * @param {String} selector The simple selector to test
 
3201
             * @param {Number/Mixed} maxDepth (optional) The max depth to
 
3202
                    search as a number or element (defaults to 10 || document.body)
 
3203
             * @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node
 
3204
             * @return {HTMLElement} The matching DOM node (or null if no match was found)
 
3205
             */
 
3206
            findParentNode : function(simpleSelector, maxDepth, returnEl){
 
3207
                var p = Ext.fly(this.dom.parentNode, '_internal');
 
3208
                return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
 
3209
            },
 
3210
        
 
3211
            /**
 
3212
             * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
 
3213
             * This is a shortcut for findParentNode() that always returns an Ext.Element.
 
3214
             * @param {String} selector The simple selector to test
 
3215
             * @param {Number/Mixed} maxDepth (optional) The max depth to
 
3216
                    search as a number or element (defaults to 10 || document.body)
 
3217
             * @return {Ext.Element} The matching DOM node (or null if no match was found)
 
3218
             */
 
3219
            up : function(simpleSelector, maxDepth){
 
3220
                return this.findParentNode(simpleSelector, maxDepth, true);
 
3221
            },
 
3222
        
 
3223
            /**
 
3224
             * Creates a {@link Ext.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
 
3225
             * @param {String} selector The CSS selector
 
3226
             * @return {CompositeElement/CompositeElementLite} The composite element
 
3227
             */
 
3228
            select : function(selector){
 
3229
                return Ext.Element.select(selector, this.dom);
 
3230
            },
 
3231
        
 
3232
            /**
 
3233
             * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
 
3234
             * @param {String} selector The CSS selector
 
3235
             * @return {Array} An array of the matched nodes
 
3236
             */
 
3237
            query : function(selector){
 
3238
                return DQ.select(selector, this.dom);
 
3239
            },
 
3240
        
 
3241
            /**
 
3242
             * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
 
3243
             * @param {String} selector The CSS selector
 
3244
             * @param {Boolean} returnDom (optional) True to return the DOM node instead of Ext.Element (defaults to false)
 
3245
             * @return {HTMLElement/Ext.Element} The child Ext.Element (or DOM node if returnDom = true)
 
3246
             */
 
3247
            child : function(selector, returnDom){
 
3248
                var n = DQ.selectNode(selector, this.dom);
 
3249
                return returnDom ? n : GET(n);
 
3250
            },
 
3251
        
 
3252
            /**
 
3253
             * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
 
3254
             * @param {String} selector The CSS selector
 
3255
             * @param {Boolean} returnDom (optional) True to return the DOM node instead of Ext.Element (defaults to false)
 
3256
             * @return {HTMLElement/Ext.Element} The child Ext.Element (or DOM node if returnDom = true)
 
3257
             */
 
3258
            down : function(selector, returnDom){
 
3259
                var n = DQ.selectNode(" > " + selector, this.dom);
 
3260
                return returnDom ? n : GET(n);
 
3261
            },
 
3262
        
 
3263
                 /**
 
3264
             * Gets the parent node for this element, optionally chaining up trying to match a selector
 
3265
             * @param {String} selector (optional) Find a parent node that matches the passed simple selector
 
3266
             * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element
 
3267
             * @return {Ext.Element/HTMLElement} The parent node or null
 
3268
                 */
 
3269
            parent : function(selector, returnDom){
 
3270
                return this.matchNode(PARENTNODE, PARENTNODE, selector, returnDom);
 
3271
            },
 
3272
        
 
3273
             /**
 
3274
             * Gets the next sibling, skipping text nodes
 
3275
             * @param {String} selector (optional) Find the next sibling that matches the passed simple selector
 
3276
             * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element
 
3277
             * @return {Ext.Element/HTMLElement} The next sibling or null
 
3278
                 */
 
3279
            next : function(selector, returnDom){
 
3280
                return this.matchNode(NEXTSIBLING, NEXTSIBLING, selector, returnDom);
 
3281
            },
 
3282
        
 
3283
            /**
 
3284
             * Gets the previous sibling, skipping text nodes
 
3285
             * @param {String} selector (optional) Find the previous sibling that matches the passed simple selector
 
3286
             * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element
 
3287
             * @return {Ext.Element/HTMLElement} The previous sibling or null
 
3288
                 */
 
3289
            prev : function(selector, returnDom){
 
3290
                return this.matchNode(PREVIOUSSIBLING, PREVIOUSSIBLING, selector, returnDom);
 
3291
            },
 
3292
        
 
3293
        
 
3294
            /**
 
3295
             * Gets the first child, skipping text nodes
 
3296
             * @param {String} selector (optional) Find the next sibling that matches the passed simple selector
 
3297
             * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element
 
3298
             * @return {Ext.Element/HTMLElement} The first child or null
 
3299
                 */
 
3300
            first : function(selector, returnDom){
 
3301
                return this.matchNode(NEXTSIBLING, 'firstChild', selector, returnDom);
 
3302
            },
 
3303
        
 
3304
            /**
 
3305
             * Gets the last child, skipping text nodes
 
3306
             * @param {String} selector (optional) Find the previous sibling that matches the passed simple selector
 
3307
             * @param {Boolean} returnDom (optional) True to return a raw dom node instead of an Ext.Element
 
3308
             * @return {Ext.Element/HTMLElement} The last child or null
 
3309
                 */
 
3310
            last : function(selector, returnDom){
 
3311
                return this.matchNode(PREVIOUSSIBLING, 'lastChild', selector, returnDom);
 
3312
            },
 
3313
            
 
3314
            matchNode : function(dir, start, selector, returnDom){
 
3315
                var n = this.dom[start];
 
3316
                while(n){
 
3317
                    if(n.nodeType == 1 && (!selector || DQ.is(n, selector))){
 
3318
                        return !returnDom ? GET(n) : n;
 
3319
                    }
 
3320
                    n = n[dir];
 
3321
                }
 
3322
                return null;
 
3323
            }   
 
3324
    };
 
3325
}());/**
 
3326
 * @class Ext.Element
 
3327
 */
 
3328
Ext.Element.addMethods(
 
3329
function() {
 
3330
        var GETDOM = Ext.getDom,
 
3331
                GET = Ext.get,
 
3332
                DH = Ext.DomHelper;
 
3333
        
 
3334
        return {
 
3335
            /**
 
3336
             * Appends the passed element(s) to this element
 
3337
             * @param {String/HTMLElement/Array/Element/CompositeElement} el
 
3338
             * @return {Ext.Element} this
 
3339
             */
 
3340
            appendChild: function(el){        
 
3341
                return GET(el).appendTo(this);        
 
3342
            },
 
3343
        
 
3344
            /**
 
3345
             * Appends this element to the passed element
 
3346
             * @param {Mixed} el The new parent element
 
3347
             * @return {Ext.Element} this
 
3348
             */
 
3349
            appendTo: function(el){        
 
3350
                GETDOM(el).appendChild(this.dom);        
 
3351
                return this;
 
3352
            },
 
3353
        
 
3354
            /**
 
3355
             * Inserts this element before the passed element in the DOM
 
3356
             * @param {Mixed} el The element before which this element will be inserted
 
3357
             * @return {Ext.Element} this
 
3358
             */
 
3359
            insertBefore: function(el){                   
 
3360
                (el = GETDOM(el)).parentNode.insertBefore(this.dom, el);
 
3361
                return this;
 
3362
            },
 
3363
        
 
3364
            /**
 
3365
             * Inserts this element after the passed element in the DOM
 
3366
             * @param {Mixed} el The element to insert after
 
3367
             * @return {Ext.Element} this
 
3368
             */
 
3369
            insertAfter: function(el){
 
3370
                (el = GETDOM(el)).parentNode.insertBefore(this.dom, el.nextSibling);
 
3371
                return this;
 
3372
            },
 
3373
        
 
3374
            /**
 
3375
             * Inserts (or creates) an element (or DomHelper config) as the first child of this element
 
3376
             * @param {Mixed/Object} el The id or element to insert or a DomHelper config to create and insert
 
3377
             * @return {Ext.Element} The new child
 
3378
             */
 
3379
            insertFirst: function(el, returnDom){
 
3380
            el = el || {};
 
3381
            if(el.nodeType || el.dom || typeof el == 'string'){ // element
 
3382
                el = GETDOM(el);
 
3383
                this.dom.insertBefore(el, this.dom.firstChild);
 
3384
                return !returnDom ? GET(el) : el;
 
3385
            }else{ // dh config
 
3386
                return this.createChild(el, this.dom.firstChild, returnDom);
 
3387
            }
 
3388
        },
 
3389
        
 
3390
            /**
 
3391
             * Replaces the passed element with this element
 
3392
             * @param {Mixed} el The element to replace
 
3393
             * @return {Ext.Element} this
 
3394
             */
 
3395
            replace: function(el){
 
3396
                el = GET(el);
 
3397
                this.insertBefore(el);
 
3398
                el.remove();
 
3399
                return this;
 
3400
            },
 
3401
        
 
3402
            /**
 
3403
             * Replaces this element with the passed element
 
3404
             * @param {Mixed/Object} el The new element or a DomHelper config of an element to create
 
3405
             * @return {Ext.Element} this
 
3406
             */
 
3407
            replaceWith: function(el){
 
3408
                    var me = this;
 
3409
                
 
3410
            if(el.nodeType || el.dom || typeof el == 'string'){
 
3411
                el = GETDOM(el);
 
3412
                me.dom.parentNode.insertBefore(el, me.dom);
 
3413
            }else{
 
3414
                el = DH.insertBefore(me.dom, el);
 
3415
            }
 
3416
                
 
3417
                delete Ext.elCache[me.id];
 
3418
                Ext.removeNode(me.dom);      
 
3419
                me.id = Ext.id(me.dom = el);
 
3420
                Ext.Element.addToCache(me.isFlyweight ? new Ext.Element(me.dom) : me);     
 
3421
            return me;
 
3422
            },
 
3423
            
 
3424
                /**
 
3425
                 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
 
3426
                 * @param {Object} config DomHelper element config object.  If no tag is specified (e.g., {tag:'input'}) then a div will be
 
3427
                 * automatically generated with the specified attributes.
 
3428
                 * @param {HTMLElement} insertBefore (optional) a child element of this element
 
3429
                 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
 
3430
                 * @return {Ext.Element} The new child element
 
3431
                 */
 
3432
                createChild: function(config, insertBefore, returnDom){
 
3433
                    config = config || {tag:'div'};
 
3434
                    return insertBefore ? 
 
3435
                           DH.insertBefore(insertBefore, config, returnDom !== true) :  
 
3436
                           DH[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config,  returnDom !== true);
 
3437
                },
 
3438
                
 
3439
                /**
 
3440
                 * Creates and wraps this element with another element
 
3441
                 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
 
3442
                 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Ext.Element
 
3443
                 * @return {HTMLElement/Element} The newly created wrapper element
 
3444
                 */
 
3445
                wrap: function(config, returnDom){        
 
3446
                    var newEl = DH.insertBefore(this.dom, config || {tag: "div"}, !returnDom);
 
3447
                    newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
 
3448
                    return newEl;
 
3449
                },
 
3450
                
 
3451
                /**
 
3452
                 * Inserts an html fragment into this element
 
3453
                 * @param {String} where Where to insert the html in relation to this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
 
3454
                 * @param {String} html The HTML fragment
 
3455
                 * @param {Boolean} returnEl (optional) True to return an Ext.Element (defaults to false)
 
3456
                 * @return {HTMLElement/Ext.Element} The inserted node (or nearest related if more than 1 inserted)
 
3457
                 */
 
3458
                insertHtml : function(where, html, returnEl){
 
3459
                    var el = DH.insertHtml(where, this.dom, html);
 
3460
                    return returnEl ? Ext.get(el) : el;
 
3461
                }
 
3462
        };
 
3463
}());/**
 
3464
 * @class Ext.Element
 
3465
 */
 
3466
Ext.Element.addMethods(function(){
 
3467
    // local style camelizing for speed
 
3468
    var supports = Ext.supports,
 
3469
        propCache = {},
 
3470
        camelRe = /(-[a-z])/gi,
 
3471
        view = document.defaultView,
 
3472
        opacityRe = /alpha\(opacity=(.*)\)/i,
 
3473
        trimRe = /^\s+|\s+$/g,
 
3474
        EL = Ext.Element,
 
3475
        spacesRe = /\s+/,
 
3476
        wordsRe = /\w/g,
 
3477
        PADDING = "padding",
 
3478
        MARGIN = "margin",
 
3479
        BORDER = "border",
 
3480
        LEFT = "-left",
 
3481
        RIGHT = "-right",
 
3482
        TOP = "-top",
 
3483
        BOTTOM = "-bottom",
 
3484
        WIDTH = "-width",
 
3485
        MATH = Math,
 
3486
        HIDDEN = 'hidden',
 
3487
        ISCLIPPED = 'isClipped',
 
3488
        OVERFLOW = 'overflow',
 
3489
        OVERFLOWX = 'overflow-x',
 
3490
        OVERFLOWY = 'overflow-y',
 
3491
        ORIGINALCLIP = 'originalClip',
 
3492
        // special markup used throughout Ext when box wrapping elements
 
3493
        borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},
 
3494
        paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},
 
3495
        margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},
 
3496
        data = Ext.Element.data;
 
3497
 
 
3498
 
 
3499
    // private
 
3500
    function camelFn(m, a) {
 
3501
        return a.charAt(1).toUpperCase();
 
3502
    }
 
3503
 
 
3504
    function chkCache(prop) {
 
3505
        return propCache[prop] || (propCache[prop] = prop == 'float' ? (supports.cssFloat ? 'cssFloat' : 'styleFloat') : prop.replace(camelRe, camelFn));
 
3506
    }
 
3507
 
 
3508
    return {
 
3509
        // private  ==> used by Fx
 
3510
        adjustWidth : function(width) {
 
3511
            var me = this;
 
3512
            var isNum = (typeof width == "number");
 
3513
            if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
 
3514
               width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
 
3515
            }
 
3516
            return (isNum && width < 0) ? 0 : width;
 
3517
        },
 
3518
 
 
3519
        // private   ==> used by Fx
 
3520
        adjustHeight : function(height) {
 
3521
            var me = this;
 
3522
            var isNum = (typeof height == "number");
 
3523
            if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
 
3524
               height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
 
3525
            }
 
3526
            return (isNum && height < 0) ? 0 : height;
 
3527
        },
 
3528
 
 
3529
 
 
3530
        /**
 
3531
         * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
 
3532
         * @param {String/Array} className The CSS class to add, or an array of classes
 
3533
         * @return {Ext.Element} this
 
3534
         */
 
3535
        addClass : function(className){
 
3536
            var me = this,
 
3537
                i,
 
3538
                len,
 
3539
                v,
 
3540
                cls = [];
 
3541
            // Separate case is for speed
 
3542
            if (!Ext.isArray(className)) {
 
3543
                if (typeof className == 'string' && !this.hasClass(className)) {
 
3544
                    me.dom.className += " " + className;
 
3545
                }
 
3546
            }
 
3547
            else {
 
3548
                for (i = 0, len = className.length; i < len; i++) {
 
3549
                    v = className[i];
 
3550
                    if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
 
3551
                        cls.push(v);
 
3552
                    }
 
3553
                }
 
3554
                if (cls.length) {
 
3555
                    me.dom.className += " " + cls.join(" ");
 
3556
                }
 
3557
            }
 
3558
            return me;
 
3559
        },
 
3560
 
 
3561
        /**
 
3562
         * Removes one or more CSS classes from the element.
 
3563
         * @param {String/Array} className The CSS class to remove, or an array of classes
 
3564
         * @return {Ext.Element} this
 
3565
         */
 
3566
        removeClass : function(className){
 
3567
            var me = this,
 
3568
                i,
 
3569
                idx,
 
3570
                len,
 
3571
                cls,
 
3572
                elClasses;
 
3573
            if (!Ext.isArray(className)){
 
3574
                className = [className];
 
3575
            }
 
3576
            if (me.dom && me.dom.className) {
 
3577
                elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
 
3578
                for (i = 0, len = className.length; i < len; i++) {
 
3579
                    cls = className[i];
 
3580
                    if (typeof cls == 'string') {
 
3581
                        cls = cls.replace(trimRe, '');
 
3582
                        idx = elClasses.indexOf(cls);
 
3583
                        if (idx != -1) {
 
3584
                            elClasses.splice(idx, 1);
 
3585
                        }
 
3586
                    }
 
3587
                }
 
3588
                me.dom.className = elClasses.join(" ");
 
3589
            }
 
3590
            return me;
 
3591
        },
 
3592
 
 
3593
        /**
 
3594
         * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
 
3595
         * @param {String/Array} className The CSS class to add, or an array of classes
 
3596
         * @return {Ext.Element} this
 
3597
         */
 
3598
        radioClass : function(className){
 
3599
            var cn = this.dom.parentNode.childNodes,
 
3600
                v,
 
3601
                i,
 
3602
                len;
 
3603
            className = Ext.isArray(className) ? className : [className];
 
3604
            for (i = 0, len = cn.length; i < len; i++) {
 
3605
                v = cn[i];
 
3606
                if (v && v.nodeType == 1) {
 
3607
                    Ext.fly(v, '_internal').removeClass(className);
 
3608
                }
 
3609
            };
 
3610
            return this.addClass(className);
 
3611
        },
 
3612
 
 
3613
        /**
 
3614
         * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
 
3615
         * @param {String} className The CSS class to toggle
 
3616
         * @return {Ext.Element} this
 
3617
         */
 
3618
        toggleClass : function(className){
 
3619
            return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
 
3620
        },
 
3621
 
 
3622
        /**
 
3623
         * Checks if the specified CSS class exists on this element's DOM node.
 
3624
         * @param {String} className The CSS class to check for
 
3625
         * @return {Boolean} True if the class exists, else false
 
3626
         */
 
3627
        hasClass : function(className){
 
3628
            return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
 
3629
        },
 
3630
 
 
3631
        /**
 
3632
         * Replaces a CSS class on the element with another.  If the old name does not exist, the new name will simply be added.
 
3633
         * @param {String} oldClassName The CSS class to replace
 
3634
         * @param {String} newClassName The replacement CSS class
 
3635
         * @return {Ext.Element} this
 
3636
         */
 
3637
        replaceClass : function(oldClassName, newClassName){
 
3638
            return this.removeClass(oldClassName).addClass(newClassName);
 
3639
        },
 
3640
 
 
3641
        isStyle : function(style, val) {
 
3642
            return this.getStyle(style) == val;
 
3643
        },
 
3644
 
 
3645
        /**
 
3646
         * Normalizes currentStyle and computedStyle.
 
3647
         * @param {String} property The style property whose value is returned.
 
3648
         * @return {String} The current value of the style property for this element.
 
3649
         */
 
3650
        getStyle : function(){
 
3651
            return view && view.getComputedStyle ?
 
3652
                function(prop){
 
3653
                    var el = this.dom,
 
3654
                        v,
 
3655
                        cs,
 
3656
                        out,
 
3657
                        display;
 
3658
 
 
3659
                    if(el == document){
 
3660
                        return null;
 
3661
                    }
 
3662
                    prop = chkCache(prop);
 
3663
                    out = (v = el.style[prop]) ? v :
 
3664
                           (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
 
3665
                           
 
3666
                    // Ignore cases when the margin is correctly reported as 0, the bug only shows
 
3667
                    // numbers larger.
 
3668
                    if(prop == 'marginRight' && out != '0px' && !supports.correctRightMargin){
 
3669
                        display = el.style.display;
 
3670
                        el.style.display = 'inline-block';
 
3671
                        out = view.getComputedStyle(el, '').marginRight;
 
3672
                        el.style.display = display;
 
3673
                    }
 
3674
                    
 
3675
                    if(prop == 'backgroundColor' && out == 'rgba(0, 0, 0, 0)' && !supports.correctTransparentColor){
 
3676
                        out = 'transparent';
 
3677
                    }
 
3678
                    return out;
 
3679
                } :
 
3680
                function(prop){
 
3681
                    var el = this.dom,
 
3682
                        m,
 
3683
                        cs;
 
3684
 
 
3685
                    if(el == document) return null;
 
3686
                    if (prop == 'opacity') {
 
3687
                        if (el.style.filter.match) {
 
3688
                            if(m = el.style.filter.match(opacityRe)){
 
3689
                                var fv = parseFloat(m[1]);
 
3690
                                if(!isNaN(fv)){
 
3691
                                    return fv ? fv / 100 : 0;
 
3692
                                }
 
3693
                            }
 
3694
                        }
 
3695
                        return 1;
 
3696
                    }
 
3697
                    prop = chkCache(prop);
 
3698
                    return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
 
3699
                };
 
3700
        }(),
 
3701
 
 
3702
        /**
 
3703
         * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
 
3704
         * are convert to standard 6 digit hex color.
 
3705
         * @param {String} attr The css attribute
 
3706
         * @param {String} defaultValue The default value to use when a valid color isn't found
 
3707
         * @param {String} prefix (optional) defaults to #. Use an empty string when working with
 
3708
         * color anims.
 
3709
         */
 
3710
        getColor : function(attr, defaultValue, prefix){
 
3711
            var v = this.getStyle(attr),
 
3712
                color = (typeof prefix != 'undefined') ? prefix : '#',
 
3713
                h;
 
3714
 
 
3715
            if(!v || (/transparent|inherit/.test(v))) {
 
3716
                return defaultValue;
 
3717
            }
 
3718
            if(/^r/.test(v)){
 
3719
                Ext.each(v.slice(4, v.length -1).split(','), function(s){
 
3720
                    h = parseInt(s, 10);
 
3721
                    color += (h < 16 ? '0' : '') + h.toString(16);
 
3722
                });
 
3723
            }else{
 
3724
                v = v.replace('#', '');
 
3725
                color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
 
3726
            }
 
3727
            return(color.length > 5 ? color.toLowerCase() : defaultValue);
 
3728
        },
 
3729
 
 
3730
        /**
 
3731
         * Wrapper for setting style properties, also takes single object parameter of multiple styles.
 
3732
         * @param {String/Object} property The style property to be set, or an object of multiple styles.
 
3733
         * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
 
3734
         * @return {Ext.Element} this
 
3735
         */
 
3736
        setStyle : function(prop, value){
 
3737
            var tmp, style;
 
3738
            
 
3739
            if (typeof prop != 'object') {
 
3740
                tmp = {};
 
3741
                tmp[prop] = value;
 
3742
                prop = tmp;
 
3743
            }
 
3744
            for (style in prop) {
 
3745
                value = prop[style];
 
3746
                style == 'opacity' ?
 
3747
                    this.setOpacity(value) :
 
3748
                    this.dom.style[chkCache(style)] = value;
 
3749
            }
 
3750
            return this;
 
3751
        },
 
3752
 
 
3753
        /**
 
3754
         * Set the opacity of the element
 
3755
         * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
 
3756
         * @param {Boolean/Object} animate (optional) a standard Element animation config object or <tt>true</tt> for
 
3757
         * the default animation (<tt>{duration: .35, easing: 'easeIn'}</tt>)
 
3758
         * @return {Ext.Element} this
 
3759
         */
 
3760
         setOpacity : function(opacity, animate){
 
3761
            var me = this,
 
3762
                s = me.dom.style;
 
3763
 
 
3764
            if(!animate || !me.anim){
 
3765
                if(Ext.isIE){
 
3766
                    var opac = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')' : '',
 
3767
                    val = s.filter.replace(opacityRe, '').replace(trimRe, '');
 
3768
 
 
3769
                    s.zoom = 1;
 
3770
                    s.filter = val + (val.length > 0 ? ' ' : '') + opac;
 
3771
                }else{
 
3772
                    s.opacity = opacity;
 
3773
                }
 
3774
            }else{
 
3775
                me.anim({opacity: {to: opacity}}, me.preanim(arguments, 1), null, .35, 'easeIn');
 
3776
            }
 
3777
            return me;
 
3778
        },
 
3779
 
 
3780
        /**
 
3781
         * Clears any opacity settings from this element. Required in some cases for IE.
 
3782
         * @return {Ext.Element} this
 
3783
         */
 
3784
        clearOpacity : function(){
 
3785
            var style = this.dom.style;
 
3786
            if(Ext.isIE){
 
3787
                if(!Ext.isEmpty(style.filter)){
 
3788
                    style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
 
3789
                }
 
3790
            }else{
 
3791
                style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
 
3792
            }
 
3793
            return this;
 
3794
        },
 
3795
 
 
3796
        /**
 
3797
         * Returns the offset height of the element
 
3798
         * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
 
3799
         * @return {Number} The element's height
 
3800
         */
 
3801
        getHeight : function(contentHeight){
 
3802
            var me = this,
 
3803
                dom = me.dom,
 
3804
                hidden = Ext.isIE && me.isStyle('display', 'none'),
 
3805
                h = MATH.max(dom.offsetHeight, hidden ? 0 : dom.clientHeight) || 0;
 
3806
 
 
3807
            h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");
 
3808
            return h < 0 ? 0 : h;
 
3809
        },
 
3810
 
 
3811
        /**
 
3812
         * Returns the offset width of the element
 
3813
         * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
 
3814
         * @return {Number} The element's width
 
3815
         */
 
3816
        getWidth : function(contentWidth){
 
3817
            var me = this,
 
3818
                dom = me.dom,
 
3819
                hidden = Ext.isIE && me.isStyle('display', 'none'),
 
3820
                w = MATH.max(dom.offsetWidth, hidden ? 0 : dom.clientWidth) || 0;
 
3821
            w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
 
3822
            return w < 0 ? 0 : w;
 
3823
        },
 
3824
 
 
3825
        /**
 
3826
         * Set the width of this Element.
 
3827
         * @param {Mixed} width The new width. This may be one of:<div class="mdetail-params"><ul>
 
3828
         * <li>A Number specifying the new width in this Element's {@link #defaultUnit}s (by default, pixels).</li>
 
3829
         * <li>A String used to set the CSS width style. Animation may <b>not</b> be used.
 
3830
         * </ul></div>
 
3831
         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
 
3832
         * @return {Ext.Element} this
 
3833
         */
 
3834
        setWidth : function(width, animate){
 
3835
            var me = this;
 
3836
            width = me.adjustWidth(width);
 
3837
            !animate || !me.anim ?
 
3838
                me.dom.style.width = me.addUnits(width) :
 
3839
                me.anim({width : {to : width}}, me.preanim(arguments, 1));
 
3840
            return me;
 
3841
        },
 
3842
 
 
3843
        /**
 
3844
         * Set the height of this Element.
 
3845
         * <pre><code>
 
3846
// change the height to 200px and animate with default configuration
 
3847
Ext.fly('elementId').setHeight(200, true);
 
3848
 
 
3849
// change the height to 150px and animate with a custom configuration
 
3850
Ext.fly('elId').setHeight(150, {
 
3851
    duration : .5, // animation will have a duration of .5 seconds
 
3852
    // will change the content to "finished"
 
3853
    callback: function(){ this.{@link #update}("finished"); }
 
3854
});
 
3855
         * </code></pre>
 
3856
         * @param {Mixed} height The new height. This may be one of:<div class="mdetail-params"><ul>
 
3857
         * <li>A Number specifying the new height in this Element's {@link #defaultUnit}s (by default, pixels.)</li>
 
3858
         * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
 
3859
         * </ul></div>
 
3860
         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
 
3861
         * @return {Ext.Element} this
 
3862
         */
 
3863
         setHeight : function(height, animate){
 
3864
            var me = this;
 
3865
            height = me.adjustHeight(height);
 
3866
            !animate || !me.anim ?
 
3867
                me.dom.style.height = me.addUnits(height) :
 
3868
                me.anim({height : {to : height}}, me.preanim(arguments, 1));
 
3869
            return me;
 
3870
        },
 
3871
 
 
3872
        /**
 
3873
         * Gets the width of the border(s) for the specified side(s)
 
3874
         * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
 
3875
         * passing <tt>'lr'</tt> would get the border <b><u>l</u></b>eft width + the border <b><u>r</u></b>ight width.
 
3876
         * @return {Number} The width of the sides passed added together
 
3877
         */
 
3878
        getBorderWidth : function(side){
 
3879
            return this.addStyles(side, borders);
 
3880
        },
 
3881
 
 
3882
        /**
 
3883
         * Gets the width of the padding(s) for the specified side(s)
 
3884
         * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
 
3885
         * passing <tt>'lr'</tt> would get the padding <b><u>l</u></b>eft + the padding <b><u>r</u></b>ight.
 
3886
         * @return {Number} The padding of the sides passed added together
 
3887
         */
 
3888
        getPadding : function(side){
 
3889
            return this.addStyles(side, paddings);
 
3890
        },
 
3891
 
 
3892
        /**
 
3893
         *  Store the current overflow setting and clip overflow on the element - use <tt>{@link #unclip}</tt> to remove
 
3894
         * @return {Ext.Element} this
 
3895
         */
 
3896
        clip : function(){
 
3897
            var me = this,
 
3898
                dom = me.dom;
 
3899
 
 
3900
            if(!data(dom, ISCLIPPED)){
 
3901
                data(dom, ISCLIPPED, true);
 
3902
                data(dom, ORIGINALCLIP, {
 
3903
                    o: me.getStyle(OVERFLOW),
 
3904
                    x: me.getStyle(OVERFLOWX),
 
3905
                    y: me.getStyle(OVERFLOWY)
 
3906
                });
 
3907
                me.setStyle(OVERFLOW, HIDDEN);
 
3908
                me.setStyle(OVERFLOWX, HIDDEN);
 
3909
                me.setStyle(OVERFLOWY, HIDDEN);
 
3910
            }
 
3911
            return me;
 
3912
        },
 
3913
 
 
3914
        /**
 
3915
         *  Return clipping (overflow) to original clipping before <tt>{@link #clip}</tt> was called
 
3916
         * @return {Ext.Element} this
 
3917
         */
 
3918
        unclip : function(){
 
3919
            var me = this,
 
3920
                dom = me.dom;
 
3921
 
 
3922
            if(data(dom, ISCLIPPED)){
 
3923
                data(dom, ISCLIPPED, false);
 
3924
                var o = data(dom, ORIGINALCLIP);
 
3925
                if(o.o){
 
3926
                    me.setStyle(OVERFLOW, o.o);
 
3927
                }
 
3928
                if(o.x){
 
3929
                    me.setStyle(OVERFLOWX, o.x);
 
3930
                }
 
3931
                if(o.y){
 
3932
                    me.setStyle(OVERFLOWY, o.y);
 
3933
                }
 
3934
            }
 
3935
            return me;
 
3936
        },
 
3937
 
 
3938
        // private
 
3939
        addStyles : function(sides, styles){
 
3940
            var ttlSize = 0,
 
3941
                sidesArr = sides.match(wordsRe),
 
3942
                side,
 
3943
                size,
 
3944
                i,
 
3945
                len = sidesArr.length;
 
3946
            for (i = 0; i < len; i++) {
 
3947
                side = sidesArr[i];
 
3948
                size = side && parseInt(this.getStyle(styles[side]), 10);
 
3949
                if (size) {
 
3950
                    ttlSize += MATH.abs(size);
 
3951
                }
 
3952
            }
 
3953
            return ttlSize;
 
3954
        },
 
3955
 
 
3956
        margins : margins
 
3957
    };
 
3958
}()
 
3959
);
 
3960
/**
 
3961
 * @class Ext.Element
 
3962
 */
 
3963
(function(){
 
3964
var D = Ext.lib.Dom,
 
3965
        LEFT = "left",
 
3966
        RIGHT = "right",
 
3967
        TOP = "top",
 
3968
        BOTTOM = "bottom",
 
3969
        POSITION = "position",
 
3970
        STATIC = "static",
 
3971
        RELATIVE = "relative",
 
3972
        AUTO = "auto",
 
3973
        ZINDEX = "z-index";
 
3974
 
 
3975
Ext.Element.addMethods({
 
3976
        /**
 
3977
      * Gets the current X position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
 
3978
      * @return {Number} The X position of the element
 
3979
      */
 
3980
    getX : function(){
 
3981
        return D.getX(this.dom);
 
3982
    },
 
3983
 
 
3984
    /**
 
3985
      * Gets the current Y position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
 
3986
      * @return {Number} The Y position of the element
 
3987
      */
 
3988
    getY : function(){
 
3989
        return D.getY(this.dom);
 
3990
    },
 
3991
 
 
3992
    /**
 
3993
      * Gets the current position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
 
3994
      * @return {Array} The XY position of the element
 
3995
      */
 
3996
    getXY : function(){
 
3997
        return D.getXY(this.dom);
 
3998
    },
 
3999
 
 
4000
    /**
 
4001
      * Returns the offsets of this element from the passed element. Both element must be part of the DOM tree and not have display:none to have page coordinates.
 
4002
      * @param {Mixed} element The element to get the offsets from.
 
4003
      * @return {Array} The XY page offsets (e.g. [100, -200])
 
4004
      */
 
4005
    getOffsetsTo : function(el){
 
4006
        var o = this.getXY(),
 
4007
                e = Ext.fly(el, '_internal').getXY();
 
4008
        return [o[0]-e[0],o[1]-e[1]];
 
4009
    },
 
4010
 
 
4011
    /**
 
4012
     * Sets the X position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
 
4013
     * @param {Number} The X position of the element
 
4014
     * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
 
4015
     * @return {Ext.Element} this
 
4016
     */
 
4017
    setX : function(x, animate){            
 
4018
            return this.setXY([x, this.getY()], this.animTest(arguments, animate, 1));
 
4019
    },
 
4020
 
 
4021
    /**
 
4022
     * Sets the Y position of the element based on page coordinates.  Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
 
4023
     * @param {Number} The Y position of the element
 
4024
     * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
 
4025
     * @return {Ext.Element} this
 
4026
     */
 
4027
    setY : function(y, animate){            
 
4028
            return this.setXY([this.getX(), y], this.animTest(arguments, animate, 1));
 
4029
    },
 
4030
 
 
4031
    /**
 
4032
     * Sets the element's left position directly using CSS style (instead of {@link #setX}).
 
4033
     * @param {String} left The left CSS property value
 
4034
     * @return {Ext.Element} this
 
4035
     */
 
4036
    setLeft : function(left){
 
4037
        this.setStyle(LEFT, this.addUnits(left));
 
4038
        return this;
 
4039
    },
 
4040
 
 
4041
    /**
 
4042
     * Sets the element's top position directly using CSS style (instead of {@link #setY}).
 
4043
     * @param {String} top The top CSS property value
 
4044
     * @return {Ext.Element} this
 
4045
     */
 
4046
    setTop : function(top){
 
4047
        this.setStyle(TOP, this.addUnits(top));
 
4048
        return this;
 
4049
    },
 
4050
 
 
4051
    /**
 
4052
     * Sets the element's CSS right style.
 
4053
     * @param {String} right The right CSS property value
 
4054
     * @return {Ext.Element} this
 
4055
     */
 
4056
    setRight : function(right){
 
4057
        this.setStyle(RIGHT, this.addUnits(right));
 
4058
        return this;
 
4059
    },
 
4060
 
 
4061
    /**
 
4062
     * Sets the element's CSS bottom style.
 
4063
     * @param {String} bottom The bottom CSS property value
 
4064
     * @return {Ext.Element} this
 
4065
     */
 
4066
    setBottom : function(bottom){
 
4067
        this.setStyle(BOTTOM, this.addUnits(bottom));
 
4068
        return this;
 
4069
    },
 
4070
 
 
4071
    /**
 
4072
     * Sets the position of the element in page coordinates, regardless of how the element is positioned.
 
4073
     * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
 
4074
     * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
 
4075
     * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
 
4076
     * @return {Ext.Element} this
 
4077
     */
 
4078
    setXY : function(pos, animate){
 
4079
            var me = this;
 
4080
        if(!animate || !me.anim){
 
4081
            D.setXY(me.dom, pos);
 
4082
        }else{
 
4083
            me.anim({points: {to: pos}}, me.preanim(arguments, 1), 'motion');
 
4084
        }
 
4085
        return me;
 
4086
    },
 
4087
 
 
4088
    /**
 
4089
     * Sets the position of the element in page coordinates, regardless of how the element is positioned.
 
4090
     * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
 
4091
     * @param {Number} x X value for new position (coordinates are page-based)
 
4092
     * @param {Number} y Y value for new position (coordinates are page-based)
 
4093
     * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
 
4094
     * @return {Ext.Element} this
 
4095
     */
 
4096
    setLocation : function(x, y, animate){
 
4097
        return this.setXY([x, y], this.animTest(arguments, animate, 2));
 
4098
    },
 
4099
 
 
4100
    /**
 
4101
     * Sets the position of the element in page coordinates, regardless of how the element is positioned.
 
4102
     * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
 
4103
     * @param {Number} x X value for new position (coordinates are page-based)
 
4104
     * @param {Number} y Y value for new position (coordinates are page-based)
 
4105
     * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
 
4106
     * @return {Ext.Element} this
 
4107
     */
 
4108
    moveTo : function(x, y, animate){
 
4109
        return this.setXY([x, y], this.animTest(arguments, animate, 2));        
 
4110
    },    
 
4111
    
 
4112
    /**
 
4113
     * Gets the left X coordinate
 
4114
     * @param {Boolean} local True to get the local css position instead of page coordinate
 
4115
     * @return {Number}
 
4116
     */
 
4117
    getLeft : function(local){
 
4118
            return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
 
4119
    },
 
4120
 
 
4121
    /**
 
4122
     * Gets the right X coordinate of the element (element X position + element width)
 
4123
     * @param {Boolean} local True to get the local css position instead of page coordinate
 
4124
     * @return {Number}
 
4125
     */
 
4126
    getRight : function(local){
 
4127
            var me = this;
 
4128
            return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
 
4129
    },
 
4130
 
 
4131
    /**
 
4132
     * Gets the top Y coordinate
 
4133
     * @param {Boolean} local True to get the local css position instead of page coordinate
 
4134
     * @return {Number}
 
4135
     */
 
4136
    getTop : function(local) {
 
4137
            return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
 
4138
    },
 
4139
 
 
4140
    /**
 
4141
     * Gets the bottom Y coordinate of the element (element Y position + element height)
 
4142
     * @param {Boolean} local True to get the local css position instead of page coordinate
 
4143
     * @return {Number}
 
4144
     */
 
4145
    getBottom : function(local){
 
4146
            var me = this;
 
4147
            return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
 
4148
    },
 
4149
 
 
4150
    /**
 
4151
    * Initializes positioning on this element. If a desired position is not passed, it will make the
 
4152
    * the element positioned relative IF it is not already positioned.
 
4153
    * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
 
4154
    * @param {Number} zIndex (optional) The zIndex to apply
 
4155
    * @param {Number} x (optional) Set the page X position
 
4156
    * @param {Number} y (optional) Set the page Y position
 
4157
    */
 
4158
    position : function(pos, zIndex, x, y){
 
4159
            var me = this;
 
4160
            
 
4161
        if(!pos && me.isStyle(POSITION, STATIC)){           
 
4162
            me.setStyle(POSITION, RELATIVE);           
 
4163
        } else if(pos) {
 
4164
            me.setStyle(POSITION, pos);
 
4165
        }
 
4166
        if(zIndex){
 
4167
            me.setStyle(ZINDEX, zIndex);
 
4168
        }
 
4169
        if(x || y) me.setXY([x || false, y || false]);
 
4170
    },
 
4171
 
 
4172
    /**
 
4173
    * Clear positioning back to the default when the document was loaded
 
4174
    * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
 
4175
    * @return {Ext.Element} this
 
4176
     */
 
4177
    clearPositioning : function(value){
 
4178
        value = value || '';
 
4179
        this.setStyle({
 
4180
            left : value,
 
4181
            right : value,
 
4182
            top : value,
 
4183
            bottom : value,
 
4184
            "z-index" : "",
 
4185
            position : STATIC
 
4186
        });
 
4187
        return this;
 
4188
    },
 
4189
 
 
4190
    /**
 
4191
    * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
 
4192
    * snapshot before performing an update and then restoring the element.
 
4193
    * @return {Object}
 
4194
    */
 
4195
    getPositioning : function(){
 
4196
        var l = this.getStyle(LEFT);
 
4197
        var t = this.getStyle(TOP);
 
4198
        return {
 
4199
            "position" : this.getStyle(POSITION),
 
4200
            "left" : l,
 
4201
            "right" : l ? "" : this.getStyle(RIGHT),
 
4202
            "top" : t,
 
4203
            "bottom" : t ? "" : this.getStyle(BOTTOM),
 
4204
            "z-index" : this.getStyle(ZINDEX)
 
4205
        };
 
4206
    },
 
4207
    
 
4208
    /**
 
4209
    * Set positioning with an object returned by getPositioning().
 
4210
    * @param {Object} posCfg
 
4211
    * @return {Ext.Element} this
 
4212
     */
 
4213
    setPositioning : function(pc){
 
4214
            var me = this,
 
4215
                style = me.dom.style;
 
4216
                
 
4217
        me.setStyle(pc);
 
4218
        
 
4219
        if(pc.right == AUTO){
 
4220
            style.right = "";
 
4221
        }
 
4222
        if(pc.bottom == AUTO){
 
4223
            style.bottom = "";
 
4224
        }
 
4225
        
 
4226
        return me;
 
4227
    },    
 
4228
        
 
4229
    /**
 
4230
     * Translates the passed page coordinates into left/top css values for this element
 
4231
     * @param {Number/Array} x The page x or an array containing [x, y]
 
4232
     * @param {Number} y (optional) The page y, required if x is not an array
 
4233
     * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
 
4234
     */
 
4235
    translatePoints : function(x, y){                
 
4236
            y = isNaN(x[1]) ? y : x[1];
 
4237
        x = isNaN(x[0]) ? x : x[0];
 
4238
        var me = this,
 
4239
                relative = me.isStyle(POSITION, RELATIVE),
 
4240
                o = me.getXY(),
 
4241
                l = parseInt(me.getStyle(LEFT), 10),
 
4242
                t = parseInt(me.getStyle(TOP), 10);
 
4243
        
 
4244
        l = !isNaN(l) ? l : (relative ? 0 : me.dom.offsetLeft);
 
4245
        t = !isNaN(t) ? t : (relative ? 0 : me.dom.offsetTop);        
 
4246
 
 
4247
        return {left: (x - o[0] + l), top: (y - o[1] + t)}; 
 
4248
    },
 
4249
    
 
4250
    animTest : function(args, animate, i) {
 
4251
        return !!animate && this.preanim ? this.preanim(args, i) : false;
 
4252
    }
 
4253
});
 
4254
})();/**
 
4255
 * @class Ext.Element
 
4256
 */
 
4257
Ext.Element.addMethods({
 
4258
    /**
 
4259
     * Returns true if this element is scrollable.
 
4260
     * @return {Boolean}
 
4261
     */
 
4262
    isScrollable : function(){
 
4263
        var dom = this.dom;
 
4264
        return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
 
4265
    },
 
4266
 
 
4267
    /**
 
4268
     * Scrolls this element the specified scroll point. It does NOT do bounds checking so if you scroll to a weird value it will try to do it. For auto bounds checking, use scroll().
 
4269
     * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
 
4270
     * @param {Number} value The new scroll value.
 
4271
     * @return {Element} this
 
4272
     */
 
4273
    scrollTo : function(side, value){
 
4274
        this.dom["scroll" + (/top/i.test(side) ? "Top" : "Left")] = value;
 
4275
        return this;
 
4276
    },
 
4277
 
 
4278
    /**
 
4279
     * Returns the current scroll position of the element.
 
4280
     * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
 
4281
     */
 
4282
    getScroll : function(){
 
4283
        var d = this.dom, 
 
4284
            doc = document,
 
4285
            body = doc.body,
 
4286
            docElement = doc.documentElement,
 
4287
            l,
 
4288
            t,
 
4289
            ret;
 
4290
 
 
4291
        if(d == doc || d == body){
 
4292
            if(Ext.isIE && Ext.isStrict){
 
4293
                l = docElement.scrollLeft; 
 
4294
                t = docElement.scrollTop;
 
4295
            }else{
 
4296
                l = window.pageXOffset;
 
4297
                t = window.pageYOffset;
 
4298
            }
 
4299
            ret = {left: l || (body ? body.scrollLeft : 0), top: t || (body ? body.scrollTop : 0)};
 
4300
        }else{
 
4301
            ret = {left: d.scrollLeft, top: d.scrollTop};
 
4302
        }
 
4303
        return ret;
 
4304
    }
 
4305
});/**
 
4306
 * @class Ext.Element
 
4307
 */
 
4308
/**
 
4309
 * Visibility mode constant for use with {@link #setVisibilityMode}. Use visibility to hide element
 
4310
 * @static
 
4311
 * @type Number
 
4312
 */
 
4313
Ext.Element.VISIBILITY = 1;
 
4314
/**
 
4315
 * Visibility mode constant for use with {@link #setVisibilityMode}. Use display to hide element
 
4316
 * @static
 
4317
 * @type Number
 
4318
 */
 
4319
Ext.Element.DISPLAY = 2;
 
4320
 
 
4321
/**
 
4322
 * Visibility mode constant for use with {@link #setVisibilityMode}. Use offsets (x and y positioning offscreen)
 
4323
 * to hide element.
 
4324
 * @static
 
4325
 * @type Number
 
4326
 */
 
4327
Ext.Element.OFFSETS = 3;
 
4328
 
 
4329
 
 
4330
Ext.Element.ASCLASS = 4;
 
4331
 
 
4332
/**
 
4333
 * Defaults to 'x-hide-nosize'
 
4334
 * @static
 
4335
 * @type String
 
4336
 */
 
4337
Ext.Element.visibilityCls = 'x-hide-nosize';
 
4338
 
 
4339
Ext.Element.addMethods(function(){
 
4340
    var El = Ext.Element,
 
4341
        OPACITY = "opacity",
 
4342
        VISIBILITY = "visibility",
 
4343
        DISPLAY = "display",
 
4344
        HIDDEN = "hidden",
 
4345
        OFFSETS = "offsets",
 
4346
        ASCLASS = "asclass",
 
4347
        NONE = "none",
 
4348
        NOSIZE = 'nosize',
 
4349
        ORIGINALDISPLAY = 'originalDisplay',
 
4350
        VISMODE = 'visibilityMode',
 
4351
        ISVISIBLE = 'isVisible',
 
4352
        data = El.data,
 
4353
        getDisplay = function(dom){
 
4354
            var d = data(dom, ORIGINALDISPLAY);
 
4355
            if(d === undefined){
 
4356
                data(dom, ORIGINALDISPLAY, d = '');
 
4357
            }
 
4358
            return d;
 
4359
        },
 
4360
        getVisMode = function(dom){
 
4361
            var m = data(dom, VISMODE);
 
4362
            if(m === undefined){
 
4363
                data(dom, VISMODE, m = 1);
 
4364
            }
 
4365
            return m;
 
4366
        };
 
4367
 
 
4368
    return {
 
4369
        /**
 
4370
         * The element's default display mode  (defaults to "")
 
4371
         * @type String
 
4372
         */
 
4373
        originalDisplay : "",
 
4374
        visibilityMode : 1,
 
4375
 
 
4376
        /**
 
4377
         * Sets the element's visibility mode. When setVisible() is called it
 
4378
         * will use this to determine whether to set the visibility or the display property.
 
4379
         * @param {Number} visMode Ext.Element.VISIBILITY or Ext.Element.DISPLAY
 
4380
         * @return {Ext.Element} this
 
4381
         */
 
4382
        setVisibilityMode : function(visMode){
 
4383
            data(this.dom, VISMODE, visMode);
 
4384
            return this;
 
4385
        },
 
4386
 
 
4387
        /**
 
4388
         * Perform custom animation on this element.
 
4389
         * <div><ul class="mdetail-params">
 
4390
         * <li><u>Animation Properties</u></li>
 
4391
         *
 
4392
         * <p>The Animation Control Object enables gradual transitions for any member of an
 
4393
         * element's style object that takes a numeric value including but not limited to
 
4394
         * these properties:</p><div><ul class="mdetail-params">
 
4395
         * <li><tt>bottom, top, left, right</tt></li>
 
4396
         * <li><tt>height, width</tt></li>
 
4397
         * <li><tt>margin, padding</tt></li>
 
4398
         * <li><tt>borderWidth</tt></li>
 
4399
         * <li><tt>opacity</tt></li>
 
4400
         * <li><tt>fontSize</tt></li>
 
4401
         * <li><tt>lineHeight</tt></li>
 
4402
         * </ul></div>
 
4403
         *
 
4404
         *
 
4405
         * <li><u>Animation Property Attributes</u></li>
 
4406
         *
 
4407
         * <p>Each Animation Property is a config object with optional properties:</p>
 
4408
         * <div><ul class="mdetail-params">
 
4409
         * <li><tt>by</tt>*  : relative change - start at current value, change by this value</li>
 
4410
         * <li><tt>from</tt> : ignore current value, start from this value</li>
 
4411
         * <li><tt>to</tt>*  : start at current value, go to this value</li>
 
4412
         * <li><tt>unit</tt> : any allowable unit specification</li>
 
4413
         * <p>* do not specify both <tt>to</tt> and <tt>by</tt> for an animation property</p>
 
4414
         * </ul></div>
 
4415
         *
 
4416
         * <li><u>Animation Types</u></li>
 
4417
         *
 
4418
         * <p>The supported animation types:</p><div><ul class="mdetail-params">
 
4419
         * <li><tt>'run'</tt> : Default
 
4420
         * <pre><code>
 
4421
var el = Ext.get('complexEl');
 
4422
el.animate(
 
4423
    // animation control object
 
4424
    {
 
4425
        borderWidth: {to: 3, from: 0},
 
4426
        opacity: {to: .3, from: 1},
 
4427
        height: {to: 50, from: el.getHeight()},
 
4428
        width: {to: 300, from: el.getWidth()},
 
4429
        top  : {by: - 100, unit: 'px'},
 
4430
    },
 
4431
    0.35,      // animation duration
 
4432
    null,      // callback
 
4433
    'easeOut', // easing method
 
4434
    'run'      // animation type ('run','color','motion','scroll')
 
4435
);
 
4436
         * </code></pre>
 
4437
         * </li>
 
4438
         * <li><tt>'color'</tt>
 
4439
         * <p>Animates transition of background, text, or border colors.</p>
 
4440
         * <pre><code>
 
4441
el.animate(
 
4442
    // animation control object
 
4443
    {
 
4444
        color: { to: '#06e' },
 
4445
        backgroundColor: { to: '#e06' }
 
4446
    },
 
4447
    0.35,      // animation duration
 
4448
    null,      // callback
 
4449
    'easeOut', // easing method
 
4450
    'color'    // animation type ('run','color','motion','scroll')
 
4451
);
 
4452
         * </code></pre>
 
4453
         * </li>
 
4454
         *
 
4455
         * <li><tt>'motion'</tt>
 
4456
         * <p>Animates the motion of an element to/from specific points using optional bezier
 
4457
         * way points during transit.</p>
 
4458
         * <pre><code>
 
4459
el.animate(
 
4460
    // animation control object
 
4461
    {
 
4462
        borderWidth: {to: 3, from: 0},
 
4463
        opacity: {to: .3, from: 1},
 
4464
        height: {to: 50, from: el.getHeight()},
 
4465
        width: {to: 300, from: el.getWidth()},
 
4466
        top  : {by: - 100, unit: 'px'},
 
4467
        points: {
 
4468
            to: [50, 100],  // go to this point
 
4469
            control: [      // optional bezier way points
 
4470
                [ 600, 800],
 
4471
                [-100, 200]
 
4472
            ]
 
4473
        }
 
4474
    },
 
4475
    3000,      // animation duration (milliseconds!)
 
4476
    null,      // callback
 
4477
    'easeOut', // easing method
 
4478
    'motion'   // animation type ('run','color','motion','scroll')
 
4479
);
 
4480
         * </code></pre>
 
4481
         * </li>
 
4482
         * <li><tt>'scroll'</tt>
 
4483
         * <p>Animate horizontal or vertical scrolling of an overflowing page element.</p>
 
4484
         * <pre><code>
 
4485
el.animate(
 
4486
    // animation control object
 
4487
    {
 
4488
        scroll: {to: [400, 300]}
 
4489
    },
 
4490
    0.35,      // animation duration
 
4491
    null,      // callback
 
4492
    'easeOut', // easing method
 
4493
    'scroll'   // animation type ('run','color','motion','scroll')
 
4494
);
 
4495
         * </code></pre>
 
4496
         * </li>
 
4497
         * </ul></div>
 
4498
         *
 
4499
         * </ul></div>
 
4500
         *
 
4501
         * @param {Object} args The animation control args
 
4502
         * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to <tt>.35</tt>)
 
4503
         * @param {Function} onComplete (optional) Function to call when animation completes
 
4504
         * @param {String} easing (optional) {@link Ext.Fx#easing} method to use (defaults to <tt>'easeOut'</tt>)
 
4505
         * @param {String} animType (optional) <tt>'run'</tt> is the default. Can also be <tt>'color'</tt>,
 
4506
         * <tt>'motion'</tt>, or <tt>'scroll'</tt>
 
4507
         * @return {Ext.Element} this
 
4508
         */
 
4509
        animate : function(args, duration, onComplete, easing, animType){
 
4510
            this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
 
4511
            return this;
 
4512
        },
 
4513
 
 
4514
        /*
 
4515
         * @private Internal animation call
 
4516
         */
 
4517
        anim : function(args, opt, animType, defaultDur, defaultEase, cb){
 
4518
            animType = animType || 'run';
 
4519
            opt = opt || {};
 
4520
            var me = this,
 
4521
                anim = Ext.lib.Anim[animType](
 
4522
                    me.dom,
 
4523
                    args,
 
4524
                    (opt.duration || defaultDur) || .35,
 
4525
                    (opt.easing || defaultEase) || 'easeOut',
 
4526
                    function(){
 
4527
                        if(cb) cb.call(me);
 
4528
                        if(opt.callback) opt.callback.call(opt.scope || me, me, opt);
 
4529
                    },
 
4530
                    me
 
4531
                );
 
4532
            opt.anim = anim;
 
4533
            return anim;
 
4534
        },
 
4535
 
 
4536
        // private legacy anim prep
 
4537
        preanim : function(a, i){
 
4538
            return !a[i] ? false : (typeof a[i] == 'object' ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
 
4539
        },
 
4540
 
 
4541
        /**
 
4542
         * Checks whether the element is currently visible using both visibility and display properties.
 
4543
         * @return {Boolean} True if the element is currently visible, else false
 
4544
         */
 
4545
        isVisible : function() {
 
4546
            var me = this,
 
4547
                dom = me.dom,
 
4548
                visible = data(dom, ISVISIBLE);
 
4549
 
 
4550
            if(typeof visible == 'boolean'){ //return the cached value if registered
 
4551
                return visible;
 
4552
            }
 
4553
            //Determine the current state based on display states
 
4554
            visible = !me.isStyle(VISIBILITY, HIDDEN) &&
 
4555
                      !me.isStyle(DISPLAY, NONE) &&
 
4556
                      !((getVisMode(dom) == El.ASCLASS) && me.hasClass(me.visibilityCls || El.visibilityCls));
 
4557
 
 
4558
            data(dom, ISVISIBLE, visible);
 
4559
            return visible;
 
4560
        },
 
4561
 
 
4562
        /**
 
4563
         * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
 
4564
         * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
 
4565
         * @param {Boolean} visible Whether the element is visible
 
4566
         * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
 
4567
         * @return {Ext.Element} this
 
4568
         */
 
4569
        setVisible : function(visible, animate){
 
4570
            var me = this, isDisplay, isVisibility, isOffsets, isNosize,
 
4571
                dom = me.dom,
 
4572
                visMode = getVisMode(dom);
 
4573
 
 
4574
 
 
4575
            // hideMode string override
 
4576
            if (typeof animate == 'string'){
 
4577
                switch (animate) {
 
4578
                    case DISPLAY:
 
4579
                        visMode = El.DISPLAY;
 
4580
                        break;
 
4581
                    case VISIBILITY:
 
4582
                        visMode = El.VISIBILITY;
 
4583
                        break;
 
4584
                    case OFFSETS:
 
4585
                        visMode = El.OFFSETS;
 
4586
                        break;
 
4587
                    case NOSIZE:
 
4588
                    case ASCLASS:
 
4589
                        visMode = El.ASCLASS;
 
4590
                        break;
 
4591
                }
 
4592
                me.setVisibilityMode(visMode);
 
4593
                animate = false;
 
4594
            }
 
4595
 
 
4596
            if (!animate || !me.anim) {
 
4597
                if(visMode == El.ASCLASS ){
 
4598
 
 
4599
                    me[visible?'removeClass':'addClass'](me.visibilityCls || El.visibilityCls);
 
4600
 
 
4601
                } else if (visMode == El.DISPLAY){
 
4602
 
 
4603
                    return me.setDisplayed(visible);
 
4604
 
 
4605
                } else if (visMode == El.OFFSETS){
 
4606
 
 
4607
                    if (!visible){
 
4608
                        me.hideModeStyles = {
 
4609
                            position: me.getStyle('position'),
 
4610
                            top: me.getStyle('top'),
 
4611
                            left: me.getStyle('left')
 
4612
                        };
 
4613
                        me.applyStyles({position: 'absolute', top: '-10000px', left: '-10000px'});
 
4614
                    } else {
 
4615
                        me.applyStyles(me.hideModeStyles || {position: '', top: '', left: ''});
 
4616
                        delete me.hideModeStyles;
 
4617
                    }
 
4618
 
 
4619
                }else{
 
4620
                    me.fixDisplay();
 
4621
                    dom.style.visibility = visible ? "visible" : HIDDEN;
 
4622
                }
 
4623
            }else{
 
4624
                // closure for composites
 
4625
                if(visible){
 
4626
                    me.setOpacity(.01);
 
4627
                    me.setVisible(true);
 
4628
                }
 
4629
                me.anim({opacity: { to: (visible?1:0) }},
 
4630
                        me.preanim(arguments, 1),
 
4631
                        null,
 
4632
                        .35,
 
4633
                        'easeIn',
 
4634
                        function(){
 
4635
                            visible || me.setVisible(false).setOpacity(1);
 
4636
                        });
 
4637
            }
 
4638
            data(dom, ISVISIBLE, visible);  //set logical visibility state
 
4639
            return me;
 
4640
        },
 
4641
 
 
4642
 
 
4643
        /**
 
4644
         * @private
 
4645
         * Determine if the Element has a relevant height and width available based
 
4646
         * upon current logical visibility state
 
4647
         */
 
4648
        hasMetrics  : function(){
 
4649
            var dom = this.dom;
 
4650
            return this.isVisible() || (getVisMode(dom) == El.VISIBILITY);
 
4651
        },
 
4652
 
 
4653
        /**
 
4654
         * Toggles the element's visibility or display, depending on visibility mode.
 
4655
         * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
 
4656
         * @return {Ext.Element} this
 
4657
         */
 
4658
        toggle : function(animate){
 
4659
            var me = this;
 
4660
            me.setVisible(!me.isVisible(), me.preanim(arguments, 0));
 
4661
            return me;
 
4662
        },
 
4663
 
 
4664
        /**
 
4665
         * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
 
4666
         * @param {Mixed} value Boolean value to display the element using its default display, or a string to set the display directly.
 
4667
         * @return {Ext.Element} this
 
4668
         */
 
4669
        setDisplayed : function(value) {
 
4670
            if(typeof value == "boolean"){
 
4671
               value = value ? getDisplay(this.dom) : NONE;
 
4672
            }
 
4673
            this.setStyle(DISPLAY, value);
 
4674
            return this;
 
4675
        },
 
4676
 
 
4677
        // private
 
4678
        fixDisplay : function(){
 
4679
            var me = this;
 
4680
            if(me.isStyle(DISPLAY, NONE)){
 
4681
                me.setStyle(VISIBILITY, HIDDEN);
 
4682
                me.setStyle(DISPLAY, getDisplay(this.dom)); // first try reverting to default
 
4683
                if(me.isStyle(DISPLAY, NONE)){ // if that fails, default to block
 
4684
                    me.setStyle(DISPLAY, "block");
 
4685
                }
 
4686
            }
 
4687
        },
 
4688
 
 
4689
        /**
 
4690
         * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
 
4691
         * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
 
4692
         * @return {Ext.Element} this
 
4693
         */
 
4694
        hide : function(animate){
 
4695
            // hideMode override
 
4696
            if (typeof animate == 'string'){
 
4697
                this.setVisible(false, animate);
 
4698
                return this;
 
4699
            }
 
4700
            this.setVisible(false, this.preanim(arguments, 0));
 
4701
            return this;
 
4702
        },
 
4703
 
 
4704
        /**
 
4705
        * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
 
4706
        * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
 
4707
         * @return {Ext.Element} this
 
4708
         */
 
4709
        show : function(animate){
 
4710
            // hideMode override
 
4711
            if (typeof animate == 'string'){
 
4712
                this.setVisible(true, animate);
 
4713
                return this;
 
4714
            }
 
4715
            this.setVisible(true, this.preanim(arguments, 0));
 
4716
            return this;
 
4717
        }
 
4718
    };
 
4719
}());(function(){
 
4720
    // contants
 
4721
    var NULL = null,
 
4722
        UNDEFINED = undefined,
 
4723
        TRUE = true,
 
4724
        FALSE = false,
 
4725
        SETX = "setX",
 
4726
        SETY = "setY",
 
4727
        SETXY = "setXY",
 
4728
        LEFT = "left",
 
4729
        BOTTOM = "bottom",
 
4730
        TOP = "top",
 
4731
        RIGHT = "right",
 
4732
        HEIGHT = "height",
 
4733
        WIDTH = "width",
 
4734
        POINTS = "points",
 
4735
        HIDDEN = "hidden",
 
4736
        ABSOLUTE = "absolute",
 
4737
        VISIBLE = "visible",
 
4738
        MOTION = "motion",
 
4739
        POSITION = "position",
 
4740
        EASEOUT = "easeOut",
 
4741
        /*
 
4742
         * Use a light flyweight here since we are using so many callbacks and are always assured a DOM element
 
4743
         */
 
4744
        flyEl = new Ext.Element.Flyweight(),
 
4745
        queues = {},
 
4746
        getObject = function(o){
 
4747
            return o || {};
 
4748
        },
 
4749
        fly = function(dom){
 
4750
            flyEl.dom = dom;
 
4751
            flyEl.id = Ext.id(dom);
 
4752
            return flyEl;
 
4753
        },
 
4754
        /*
 
4755
         * Queueing now stored outside of the element due to closure issues
 
4756
         */
 
4757
        getQueue = function(id){
 
4758
            if(!queues[id]){
 
4759
                queues[id] = [];
 
4760
            }
 
4761
            return queues[id];
 
4762
        },
 
4763
        setQueue = function(id, value){
 
4764
            queues[id] = value;
 
4765
        };
 
4766
        
 
4767
//Notifies Element that fx methods are available
 
4768
Ext.enableFx = TRUE;
 
4769
 
 
4770
/**
 
4771
 * @class Ext.Fx
 
4772
 * <p>A class to provide basic animation and visual effects support.  <b>Note:</b> This class is automatically applied
 
4773
 * to the {@link Ext.Element} interface when included, so all effects calls should be performed via {@link Ext.Element}.
 
4774
 * Conversely, since the effects are not actually defined in {@link Ext.Element}, Ext.Fx <b>must</b> be
 
4775
 * {@link Ext#enableFx included} in order for the Element effects to work.</p><br/>
 
4776
 * 
 
4777
 * <p><b><u>Method Chaining</u></b></p>
 
4778
 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
 
4779
 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
 
4780
 * method chain.  The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
 
4781
 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately.  For this reason,
 
4782
 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
 
4783
 * expected results and should be done with care.  Also see <tt>{@link #callback}</tt>.</p><br/>
 
4784
 *
 
4785
 * <p><b><u>Anchor Options for Motion Effects</u></b></p>
 
4786
 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
 
4787
 * that will serve as either the start or end point of the animation.  Following are all of the supported anchor positions:</p>
 
4788
<pre>
 
4789
Value  Description
 
4790
-----  -----------------------------
 
4791
tl     The top left corner
 
4792
t      The center of the top edge
 
4793
tr     The top right corner
 
4794
l      The center of the left edge
 
4795
r      The center of the right edge
 
4796
bl     The bottom left corner
 
4797
b      The center of the bottom edge
 
4798
br     The bottom right corner
 
4799
</pre>
 
4800
 * <b>Note</b>: some Fx methods accept specific custom config parameters.  The options shown in the Config Options
 
4801
 * section below are common options that can be passed to any Fx method unless otherwise noted.</b>
 
4802
 * 
 
4803
 * @cfg {Function} callback A function called when the effect is finished.  Note that effects are queued internally by the
 
4804
 * Fx class, so a callback is not required to specify another effect -- effects can simply be chained together
 
4805
 * and called in sequence (see note for <b><u>Method Chaining</u></b> above), for example:<pre><code>
 
4806
 * el.slideIn().highlight();
 
4807
 * </code></pre>
 
4808
 * The callback is intended for any additional code that should run once a particular effect has completed. The Element
 
4809
 * being operated upon is passed as the first parameter.
 
4810
 * 
 
4811
 * @cfg {Object} scope The scope (<code>this</code> reference) in which the <tt>{@link #callback}</tt> function is executed. Defaults to the browser window.
 
4812
 * 
 
4813
 * @cfg {String} easing A valid Ext.lib.Easing value for the effect:</p><div class="mdetail-params"><ul>
 
4814
 * <li><b><tt>backBoth</tt></b></li>
 
4815
 * <li><b><tt>backIn</tt></b></li>
 
4816
 * <li><b><tt>backOut</tt></b></li>
 
4817
 * <li><b><tt>bounceBoth</tt></b></li>
 
4818
 * <li><b><tt>bounceIn</tt></b></li>
 
4819
 * <li><b><tt>bounceOut</tt></b></li>
 
4820
 * <li><b><tt>easeBoth</tt></b></li>
 
4821
 * <li><b><tt>easeBothStrong</tt></b></li>
 
4822
 * <li><b><tt>easeIn</tt></b></li>
 
4823
 * <li><b><tt>easeInStrong</tt></b></li>
 
4824
 * <li><b><tt>easeNone</tt></b></li>
 
4825
 * <li><b><tt>easeOut</tt></b></li>
 
4826
 * <li><b><tt>easeOutStrong</tt></b></li>
 
4827
 * <li><b><tt>elasticBoth</tt></b></li>
 
4828
 * <li><b><tt>elasticIn</tt></b></li>
 
4829
 * <li><b><tt>elasticOut</tt></b></li>
 
4830
 * </ul></div>
 
4831
 *
 
4832
 * @cfg {String} afterCls A css class to apply after the effect
 
4833
 * @cfg {Number} duration The length of time (in seconds) that the effect should last
 
4834
 * 
 
4835
 * @cfg {Number} endOpacity Only applicable for {@link #fadeIn} or {@link #fadeOut}, a number between
 
4836
 * <tt>0</tt> and <tt>1</tt> inclusive to configure the ending opacity value.
 
4837
 *  
 
4838
 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
 
4839
 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to 
 
4840
 * effects that end with the element being visually hidden, ignored otherwise)
 
4841
 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. <tt>"width:100px"</tt>, or an object
 
4842
 * in the form <tt>{width:"100px"}</tt>, or a function which returns such a specification that will be applied to the
 
4843
 * Element after the effect finishes.
 
4844
 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
 
4845
 * @cfg {Boolean} concurrent Whether to allow subsequently-queued effects to run at the same time as the current effect, or to ensure that they run in sequence
 
4846
 * @cfg {Boolean} stopFx Whether preceding effects should be stopped and removed before running current effect (only applies to non blocking effects)
 
4847
 */
 
4848
Ext.Fx = {
 
4849
    
 
4850
    // private - calls the function taking arguments from the argHash based on the key.  Returns the return value of the function.
 
4851
    //           this is useful for replacing switch statements (for example).
 
4852
    switchStatements : function(key, fn, argHash){
 
4853
        return fn.apply(this, argHash[key]);
 
4854
    },
 
4855
    
 
4856
    /**
 
4857
     * Slides the element into view.  An anchor point can be optionally passed to set the point of
 
4858
     * origin for the slide effect.  This function automatically handles wrapping the element with
 
4859
     * a fixed-size container if needed.  See the Fx class overview for valid anchor point options.
 
4860
     * Usage:
 
4861
     *<pre><code>
 
4862
// default: slide the element in from the top
 
4863
el.slideIn();
 
4864
 
 
4865
// custom: slide the element in from the right with a 2-second duration
 
4866
el.slideIn('r', { duration: 2 });
 
4867
 
 
4868
// common config options shown with default values
 
4869
el.slideIn('t', {
 
4870
    easing: 'easeOut',
 
4871
    duration: .5
 
4872
});
 
4873
</code></pre>
 
4874
     * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
 
4875
     * @param {Object} options (optional) Object literal with any of the Fx config options
 
4876
     * @return {Ext.Element} The Element
 
4877
     */
 
4878
    slideIn : function(anchor, o){ 
 
4879
        o = getObject(o);
 
4880
        var me = this,
 
4881
            dom = me.dom,
 
4882
            st = dom.style,
 
4883
            xy,
 
4884
            r,
 
4885
            b,              
 
4886
            wrap,               
 
4887
            after,
 
4888
            st,
 
4889
            args, 
 
4890
            pt,
 
4891
            bw,
 
4892
            bh;
 
4893
            
 
4894
        anchor = anchor || "t";
 
4895
 
 
4896
        me.queueFx(o, function(){            
 
4897
            xy = fly(dom).getXY();
 
4898
            // fix display to visibility
 
4899
            fly(dom).fixDisplay();            
 
4900
            
 
4901
            // restore values after effect
 
4902
            r = fly(dom).getFxRestore();      
 
4903
            b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
 
4904
            b.right = b.x + b.width;
 
4905
            b.bottom = b.y + b.height;
 
4906
            
 
4907
            // fixed size for slide
 
4908
            fly(dom).setWidth(b.width).setHeight(b.height);            
 
4909
            
 
4910
            // wrap if needed
 
4911
            wrap = fly(dom).fxWrap(r.pos, o, HIDDEN);
 
4912
            
 
4913
            st.visibility = VISIBLE;
 
4914
            st.position = ABSOLUTE;
 
4915
            
 
4916
            // clear out temp styles after slide and unwrap
 
4917
            function after(){
 
4918
                 fly(dom).fxUnwrap(wrap, r.pos, o);
 
4919
                 st.width = r.width;
 
4920
                 st.height = r.height;
 
4921
                 fly(dom).afterFx(o);
 
4922
            }
 
4923
            
 
4924
            // time to calculate the positions        
 
4925
            pt = {to: [b.x, b.y]}; 
 
4926
            bw = {to: b.width};
 
4927
            bh = {to: b.height};
 
4928
                
 
4929
            function argCalc(wrap, style, ww, wh, sXY, sXYval, s1, s2, w, h, p){                    
 
4930
                var ret = {};
 
4931
                fly(wrap).setWidth(ww).setHeight(wh);
 
4932
                if(fly(wrap)[sXY]){
 
4933
                    fly(wrap)[sXY](sXYval);                  
 
4934
                }
 
4935
                style[s1] = style[s2] = "0";                    
 
4936
                if(w){
 
4937
                    ret.width = w;
 
4938
                }
 
4939
                if(h){
 
4940
                    ret.height = h;
 
4941
                }
 
4942
                if(p){
 
4943
                    ret.points = p;
 
4944
                }
 
4945
                return ret;
 
4946
            };
 
4947
 
 
4948
            args = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
 
4949
                    t  : [wrap, st, b.width, 0, NULL, NULL, LEFT, BOTTOM, NULL, bh, NULL],
 
4950
                    l  : [wrap, st, 0, b.height, NULL, NULL, RIGHT, TOP, bw, NULL, NULL],
 
4951
                    r  : [wrap, st, b.width, b.height, SETX, b.right, LEFT, TOP, NULL, NULL, pt],
 
4952
                    b  : [wrap, st, b.width, b.height, SETY, b.bottom, LEFT, TOP, NULL, bh, pt],
 
4953
                    tl : [wrap, st, 0, 0, NULL, NULL, RIGHT, BOTTOM, bw, bh, pt],
 
4954
                    bl : [wrap, st, 0, 0, SETY, b.y + b.height, RIGHT, TOP, bw, bh, pt],
 
4955
                    br : [wrap, st, 0, 0, SETXY, [b.right, b.bottom], LEFT, TOP, bw, bh, pt],
 
4956
                    tr : [wrap, st, 0, 0, SETX, b.x + b.width, LEFT, BOTTOM, bw, bh, pt]
 
4957
                });
 
4958
            
 
4959
            st.visibility = VISIBLE;
 
4960
            fly(wrap).show();
 
4961
 
 
4962
            arguments.callee.anim = fly(wrap).fxanim(args,
 
4963
                o,
 
4964
                MOTION,
 
4965
                .5,
 
4966
                EASEOUT, 
 
4967
                after);
 
4968
        });
 
4969
        return me;
 
4970
    },
 
4971
    
 
4972
    /**
 
4973
     * Slides the element out of view.  An anchor point can be optionally passed to set the end point
 
4974
     * for the slide effect.  When the effect is completed, the element will be hidden (visibility = 
 
4975
     * 'hidden') but block elements will still take up space in the document.  The element must be removed
 
4976
     * from the DOM using the 'remove' config option if desired.  This function automatically handles 
 
4977
     * wrapping the element with a fixed-size container if needed.  See the Fx class overview for valid anchor point options.
 
4978
     * Usage:
 
4979
     *<pre><code>
 
4980
// default: slide the element out to the top
 
4981
el.slideOut();
 
4982
 
 
4983
// custom: slide the element out to the right with a 2-second duration
 
4984
el.slideOut('r', { duration: 2 });
 
4985
 
 
4986
// common config options shown with default values
 
4987
el.slideOut('t', {
 
4988
    easing: 'easeOut',
 
4989
    duration: .5,
 
4990
    remove: false,
 
4991
    useDisplay: false
 
4992
});
 
4993
</code></pre>
 
4994
     * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
 
4995
     * @param {Object} options (optional) Object literal with any of the Fx config options
 
4996
     * @return {Ext.Element} The Element
 
4997
     */
 
4998
    slideOut : function(anchor, o){
 
4999
        o = getObject(o);
 
5000
        var me = this,
 
5001
            dom = me.dom,
 
5002
            st = dom.style,
 
5003
            xy = me.getXY(),
 
5004
            wrap,
 
5005
            r,
 
5006
            b,
 
5007
            a,
 
5008
            zero = {to: 0}; 
 
5009
                    
 
5010
        anchor = anchor || "t";
 
5011
 
 
5012
        me.queueFx(o, function(){
 
5013
            
 
5014
            // restore values after effect
 
5015
            r = fly(dom).getFxRestore(); 
 
5016
            b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight};
 
5017
            b.right = b.x + b.width;
 
5018
            b.bottom = b.y + b.height;
 
5019
                
 
5020
            // fixed size for slide   
 
5021
            fly(dom).setWidth(b.width).setHeight(b.height);
 
5022
 
 
5023
            // wrap if needed
 
5024
            wrap = fly(dom).fxWrap(r.pos, o, VISIBLE);
 
5025
                
 
5026
            st.visibility = VISIBLE;
 
5027
            st.position = ABSOLUTE;
 
5028
            fly(wrap).setWidth(b.width).setHeight(b.height);            
 
5029
 
 
5030
            function after(){
 
5031
                o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                
 
5032
                fly(dom).fxUnwrap(wrap, r.pos, o);
 
5033
                st.width = r.width;
 
5034
                st.height = r.height;
 
5035
                fly(dom).afterFx(o);
 
5036
            }            
 
5037
            
 
5038
            function argCalc(style, s1, s2, p1, v1, p2, v2, p3, v3){                    
 
5039
                var ret = {};
 
5040
                
 
5041
                style[s1] = style[s2] = "0";
 
5042
                ret[p1] = v1;               
 
5043
                if(p2){
 
5044
                    ret[p2] = v2;               
 
5045
                }
 
5046
                if(p3){
 
5047
                    ret[p3] = v3;
 
5048
                }
 
5049
                
 
5050
                return ret;
 
5051
            };
 
5052
            
 
5053
            a = fly(dom).switchStatements(anchor.toLowerCase(), argCalc, {
 
5054
                t  : [st, LEFT, BOTTOM, HEIGHT, zero],
 
5055
                l  : [st, RIGHT, TOP, WIDTH, zero],
 
5056
                r  : [st, LEFT, TOP, WIDTH, zero, POINTS, {to : [b.right, b.y]}],
 
5057
                b  : [st, LEFT, TOP, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
 
5058
                tl : [st, RIGHT, BOTTOM, WIDTH, zero, HEIGHT, zero],
 
5059
                bl : [st, RIGHT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x, b.bottom]}],
 
5060
                br : [st, LEFT, TOP, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.x + b.width, b.bottom]}],
 
5061
                tr : [st, LEFT, BOTTOM, WIDTH, zero, HEIGHT, zero, POINTS, {to : [b.right, b.y]}]
 
5062
            });
 
5063
            
 
5064
            arguments.callee.anim = fly(wrap).fxanim(a,
 
5065
                o,
 
5066
                MOTION,
 
5067
                .5,
 
5068
                EASEOUT, 
 
5069
                after);
 
5070
        });
 
5071
        return me;
 
5072
    },
 
5073
 
 
5074
    /**
 
5075
     * Fades the element out while slowly expanding it in all directions.  When the effect is completed, the 
 
5076
     * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document. 
 
5077
     * The element must be removed from the DOM using the 'remove' config option if desired.
 
5078
     * Usage:
 
5079
     *<pre><code>
 
5080
// default
 
5081
el.puff();
 
5082
 
 
5083
// common config options shown with default values
 
5084
el.puff({
 
5085
    easing: 'easeOut',
 
5086
    duration: .5,
 
5087
    remove: false,
 
5088
    useDisplay: false
 
5089
});
 
5090
</code></pre>
 
5091
     * @param {Object} options (optional) Object literal with any of the Fx config options
 
5092
     * @return {Ext.Element} The Element
 
5093
     */
 
5094
    puff : function(o){
 
5095
        o = getObject(o);
 
5096
        var me = this,
 
5097
            dom = me.dom,
 
5098
            st = dom.style,
 
5099
            width,
 
5100
            height,
 
5101
            r;
 
5102
 
 
5103
        me.queueFx(o, function(){
 
5104
            width = fly(dom).getWidth();
 
5105
            height = fly(dom).getHeight();
 
5106
            fly(dom).clearOpacity();
 
5107
            fly(dom).show();
 
5108
 
 
5109
            // restore values after effect
 
5110
            r = fly(dom).getFxRestore();                   
 
5111
            
 
5112
            function after(){
 
5113
                o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();                  
 
5114
                fly(dom).clearOpacity();  
 
5115
                fly(dom).setPositioning(r.pos);
 
5116
                st.width = r.width;
 
5117
                st.height = r.height;
 
5118
                st.fontSize = '';
 
5119
                fly(dom).afterFx(o);
 
5120
            }   
 
5121
 
 
5122
            arguments.callee.anim = fly(dom).fxanim({
 
5123
                    width : {to : fly(dom).adjustWidth(width * 2)},
 
5124
                    height : {to : fly(dom).adjustHeight(height * 2)},
 
5125
                    points : {by : [-width * .5, -height * .5]},
 
5126
                    opacity : {to : 0},
 
5127
                    fontSize: {to : 200, unit: "%"}
 
5128
                },
 
5129
                o,
 
5130
                MOTION,
 
5131
                .5,
 
5132
                EASEOUT,
 
5133
                 after);
 
5134
        });
 
5135
        return me;
 
5136
    },
 
5137
 
 
5138
    /**
 
5139
     * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
 
5140
     * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still 
 
5141
     * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
 
5142
     * Usage:
 
5143
     *<pre><code>
 
5144
// default
 
5145
el.switchOff();
 
5146
 
 
5147
// all config options shown with default values
 
5148
el.switchOff({
 
5149
    easing: 'easeIn',
 
5150
    duration: .3,
 
5151
    remove: false,
 
5152
    useDisplay: false
 
5153
});
 
5154
</code></pre>
 
5155
     * @param {Object} options (optional) Object literal with any of the Fx config options
 
5156
     * @return {Ext.Element} The Element
 
5157
     */
 
5158
    switchOff : function(o){
 
5159
        o = getObject(o);
 
5160
        var me = this,
 
5161
            dom = me.dom,
 
5162
            st = dom.style,
 
5163
            r;
 
5164
 
 
5165
        me.queueFx(o, function(){
 
5166
            fly(dom).clearOpacity();
 
5167
            fly(dom).clip();
 
5168
 
 
5169
            // restore values after effect
 
5170
            r = fly(dom).getFxRestore();
 
5171
                
 
5172
            function after(){
 
5173
                o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();  
 
5174
                fly(dom).clearOpacity();
 
5175
                fly(dom).setPositioning(r.pos);
 
5176
                st.width = r.width;
 
5177
                st.height = r.height;   
 
5178
                fly(dom).afterFx(o);
 
5179
            };
 
5180
 
 
5181
            fly(dom).fxanim({opacity : {to : 0.3}}, 
 
5182
                NULL, 
 
5183
                NULL, 
 
5184
                .1, 
 
5185
                NULL, 
 
5186
                function(){                                 
 
5187
                    fly(dom).clearOpacity();
 
5188
                        (function(){                            
 
5189
                            fly(dom).fxanim({
 
5190
                                height : {to : 1},
 
5191
                                points : {by : [0, fly(dom).getHeight() * .5]}
 
5192
                            }, 
 
5193
                            o, 
 
5194
                            MOTION, 
 
5195
                            0.3, 
 
5196
                            'easeIn', 
 
5197
                            after);
 
5198
                        }).defer(100);
 
5199
                });
 
5200
        });
 
5201
        return me;
 
5202
    },
 
5203
 
 
5204
    /**
 
5205
     * Highlights the Element by setting a color (applies to the background-color by default, but can be
 
5206
     * changed using the "attr" config option) and then fading back to the original color. If no original
 
5207
     * color is available, you should provide the "endColor" config option which will be cleared after the animation.
 
5208
     * Usage:
 
5209
<pre><code>
 
5210
// default: highlight background to yellow
 
5211
el.highlight();
 
5212
 
 
5213
// custom: highlight foreground text to blue for 2 seconds
 
5214
el.highlight("0000ff", { attr: 'color', duration: 2 });
 
5215
 
 
5216
// common config options shown with default values
 
5217
el.highlight("ffff9c", {
 
5218
    attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
 
5219
    endColor: (current color) or "ffffff",
 
5220
    easing: 'easeIn',
 
5221
    duration: 1
 
5222
});
 
5223
</code></pre>
 
5224
     * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
 
5225
     * @param {Object} options (optional) Object literal with any of the Fx config options
 
5226
     * @return {Ext.Element} The Element
 
5227
     */ 
 
5228
    highlight : function(color, o){
 
5229
        o = getObject(o);
 
5230
        var me = this,
 
5231
            dom = me.dom,
 
5232
            attr = o.attr || "backgroundColor",
 
5233
            a = {},
 
5234
            restore;
 
5235
 
 
5236
        me.queueFx(o, function(){
 
5237
            fly(dom).clearOpacity();
 
5238
            fly(dom).show();
 
5239
 
 
5240
            function after(){
 
5241
                dom.style[attr] = restore;
 
5242
                fly(dom).afterFx(o);
 
5243
            }            
 
5244
            restore = dom.style[attr];
 
5245
            a[attr] = {from: color || "ffff9c", to: o.endColor || fly(dom).getColor(attr) || "ffffff"};
 
5246
            arguments.callee.anim = fly(dom).fxanim(a,
 
5247
                o,
 
5248
                'color',
 
5249
                1,
 
5250
                'easeIn', 
 
5251
                after);
 
5252
        });
 
5253
        return me;
 
5254
    },
 
5255
 
 
5256
   /**
 
5257
    * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
 
5258
    * Usage:
 
5259
<pre><code>
 
5260
// default: a single light blue ripple
 
5261
el.frame();
 
5262
 
 
5263
// custom: 3 red ripples lasting 3 seconds total
 
5264
el.frame("ff0000", 3, { duration: 3 });
 
5265
 
 
5266
// common config options shown with default values
 
5267
el.frame("C3DAF9", 1, {
 
5268
    duration: 1 //duration of each individual ripple.
 
5269
    // Note: Easing is not configurable and will be ignored if included
 
5270
});
 
5271
</code></pre>
 
5272
    * @param {String} color (optional) The color of the border.  Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
 
5273
    * @param {Number} count (optional) The number of ripples to display (defaults to 1)
 
5274
    * @param {Object} options (optional) Object literal with any of the Fx config options
 
5275
    * @return {Ext.Element} The Element
 
5276
    */
 
5277
    frame : function(color, count, o){
 
5278
        o = getObject(o);
 
5279
        var me = this,
 
5280
            dom = me.dom,
 
5281
            proxy,
 
5282
            active;
 
5283
 
 
5284
        me.queueFx(o, function(){
 
5285
            color = color || '#C3DAF9';
 
5286
            if(color.length == 6){
 
5287
                color = '#' + color;
 
5288
            }            
 
5289
            count = count || 1;
 
5290
            fly(dom).show();
 
5291
 
 
5292
            var xy = fly(dom).getXY(),
 
5293
                b = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: dom.offsetWidth, height: dom.offsetHeight},
 
5294
                queue = function(){
 
5295
                    proxy = fly(document.body || document.documentElement).createChild({
 
5296
                        style:{
 
5297
                            position : ABSOLUTE,
 
5298
                            'z-index': 35000, // yee haw
 
5299
                            border : '0px solid ' + color
 
5300
                        }
 
5301
                    });
 
5302
                    return proxy.queueFx({}, animFn);
 
5303
                };
 
5304
            
 
5305
            
 
5306
            arguments.callee.anim = {
 
5307
                isAnimated: true,
 
5308
                stop: function() {
 
5309
                    count = 0;
 
5310
                    proxy.stopFx();
 
5311
                }
 
5312
            };
 
5313
            
 
5314
            function animFn(){
 
5315
                var scale = Ext.isBorderBox ? 2 : 1;
 
5316
                active = proxy.anim({
 
5317
                    top : {from : b.y, to : b.y - 20},
 
5318
                    left : {from : b.x, to : b.x - 20},
 
5319
                    borderWidth : {from : 0, to : 10},
 
5320
                    opacity : {from : 1, to : 0},
 
5321
                    height : {from : b.height, to : b.height + 20 * scale},
 
5322
                    width : {from : b.width, to : b.width + 20 * scale}
 
5323
                },{
 
5324
                    duration: o.duration || 1,
 
5325
                    callback: function() {
 
5326
                        proxy.remove();
 
5327
                        --count > 0 ? queue() : fly(dom).afterFx(o);
 
5328
                    }
 
5329
                });
 
5330
                arguments.callee.anim = {
 
5331
                    isAnimated: true,
 
5332
                    stop: function(){
 
5333
                        active.stop();
 
5334
                    }
 
5335
                };
 
5336
            };
 
5337
            queue();
 
5338
        });
 
5339
        return me;
 
5340
    },
 
5341
 
 
5342
   /**
 
5343
    * Creates a pause before any subsequent queued effects begin.  If there are
 
5344
    * no effects queued after the pause it will have no effect.
 
5345
    * Usage:
 
5346
<pre><code>
 
5347
el.pause(1);
 
5348
</code></pre>
 
5349
    * @param {Number} seconds The length of time to pause (in seconds)
 
5350
    * @return {Ext.Element} The Element
 
5351
    */
 
5352
    pause : function(seconds){        
 
5353
        var dom = this.dom,
 
5354
            t;
 
5355
 
 
5356
        this.queueFx({}, function(){
 
5357
            t = setTimeout(function(){
 
5358
                fly(dom).afterFx({});
 
5359
            }, seconds * 1000);
 
5360
            arguments.callee.anim = {
 
5361
                isAnimated: true,
 
5362
                stop: function(){
 
5363
                    clearTimeout(t);
 
5364
                    fly(dom).afterFx({});
 
5365
                }
 
5366
            };
 
5367
        });
 
5368
        return this;
 
5369
    },
 
5370
 
 
5371
   /**
 
5372
    * Fade an element in (from transparent to opaque).  The ending opacity can be specified
 
5373
    * using the <tt>{@link #endOpacity}</tt> config option.
 
5374
    * Usage:
 
5375
<pre><code>
 
5376
// default: fade in from opacity 0 to 100%
 
5377
el.fadeIn();
 
5378
 
 
5379
// custom: fade in from opacity 0 to 75% over 2 seconds
 
5380
el.fadeIn({ endOpacity: .75, duration: 2});
 
5381
 
 
5382
// common config options shown with default values
 
5383
el.fadeIn({
 
5384
    endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
 
5385
    easing: 'easeOut',
 
5386
    duration: .5
 
5387
});
 
5388
</code></pre>
 
5389
    * @param {Object} options (optional) Object literal with any of the Fx config options
 
5390
    * @return {Ext.Element} The Element
 
5391
    */
 
5392
    fadeIn : function(o){
 
5393
        o = getObject(o);
 
5394
        var me = this,
 
5395
            dom = me.dom,
 
5396
            to = o.endOpacity || 1;
 
5397
        
 
5398
        me.queueFx(o, function(){
 
5399
            fly(dom).setOpacity(0);
 
5400
            fly(dom).fixDisplay();
 
5401
            dom.style.visibility = VISIBLE;
 
5402
            arguments.callee.anim = fly(dom).fxanim({opacity:{to:to}},
 
5403
                o, NULL, .5, EASEOUT, function(){
 
5404
                if(to == 1){
 
5405
                    fly(dom).clearOpacity();
 
5406
                }
 
5407
                fly(dom).afterFx(o);
 
5408
            });
 
5409
        });
 
5410
        return me;
 
5411
    },
 
5412
 
 
5413
   /**
 
5414
    * Fade an element out (from opaque to transparent).  The ending opacity can be specified
 
5415
    * using the <tt>{@link #endOpacity}</tt> config option.  Note that IE may require
 
5416
    * <tt>{@link #useDisplay}:true</tt> in order to redisplay correctly.
 
5417
    * Usage:
 
5418
<pre><code>
 
5419
// default: fade out from the element's current opacity to 0
 
5420
el.fadeOut();
 
5421
 
 
5422
// custom: fade out from the element's current opacity to 25% over 2 seconds
 
5423
el.fadeOut({ endOpacity: .25, duration: 2});
 
5424
 
 
5425
// common config options shown with default values
 
5426
el.fadeOut({
 
5427
    endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
 
5428
    easing: 'easeOut',
 
5429
    duration: .5,
 
5430
    remove: false,
 
5431
    useDisplay: false
 
5432
});
 
5433
</code></pre>
 
5434
    * @param {Object} options (optional) Object literal with any of the Fx config options
 
5435
    * @return {Ext.Element} The Element
 
5436
    */
 
5437
    fadeOut : function(o){
 
5438
        o = getObject(o);
 
5439
        var me = this,
 
5440
            dom = me.dom,
 
5441
            style = dom.style,
 
5442
            to = o.endOpacity || 0;         
 
5443
        
 
5444
        me.queueFx(o, function(){  
 
5445
            arguments.callee.anim = fly(dom).fxanim({ 
 
5446
                opacity : {to : to}},
 
5447
                o, 
 
5448
                NULL, 
 
5449
                .5, 
 
5450
                EASEOUT, 
 
5451
                function(){
 
5452
                    if(to == 0){
 
5453
                        Ext.Element.data(dom, 'visibilityMode') == Ext.Element.DISPLAY || o.useDisplay ? 
 
5454
                            style.display = "none" :
 
5455
                            style.visibility = HIDDEN;
 
5456
                            
 
5457
                        fly(dom).clearOpacity();
 
5458
                    }
 
5459
                    fly(dom).afterFx(o);
 
5460
            });
 
5461
        });
 
5462
        return me;
 
5463
    },
 
5464
 
 
5465
   /**
 
5466
    * Animates the transition of an element's dimensions from a starting height/width
 
5467
    * to an ending height/width.  This method is a convenience implementation of {@link shift}.
 
5468
    * Usage:
 
5469
<pre><code>
 
5470
// change height and width to 100x100 pixels
 
5471
el.scale(100, 100);
 
5472
 
 
5473
// common config options shown with default values.  The height and width will default to
 
5474
// the element&#39;s existing values if passed as null.
 
5475
el.scale(
 
5476
    [element&#39;s width],
 
5477
    [element&#39;s height], {
 
5478
        easing: 'easeOut',
 
5479
        duration: .35
 
5480
    }
 
5481
);
 
5482
</code></pre>
 
5483
    * @param {Number} width  The new width (pass undefined to keep the original width)
 
5484
    * @param {Number} height  The new height (pass undefined to keep the original height)
 
5485
    * @param {Object} options (optional) Object literal with any of the Fx config options
 
5486
    * @return {Ext.Element} The Element
 
5487
    */
 
5488
    scale : function(w, h, o){
 
5489
        this.shift(Ext.apply({}, o, {
 
5490
            width: w,
 
5491
            height: h
 
5492
        }));
 
5493
        return this;
 
5494
    },
 
5495
 
 
5496
   /**
 
5497
    * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
 
5498
    * Any of these properties not specified in the config object will not be changed.  This effect 
 
5499
    * requires that at least one new dimension, position or opacity setting must be passed in on
 
5500
    * the config object in order for the function to have any effect.
 
5501
    * Usage:
 
5502
<pre><code>
 
5503
// slide the element horizontally to x position 200 while changing the height and opacity
 
5504
el.shift({ x: 200, height: 50, opacity: .8 });
 
5505
 
 
5506
// common config options shown with default values.
 
5507
el.shift({
 
5508
    width: [element&#39;s width],
 
5509
    height: [element&#39;s height],
 
5510
    x: [element&#39;s x position],
 
5511
    y: [element&#39;s y position],
 
5512
    opacity: [element&#39;s opacity],
 
5513
    easing: 'easeOut',
 
5514
    duration: .35
 
5515
});
 
5516
</code></pre>
 
5517
    * @param {Object} options  Object literal with any of the Fx config options
 
5518
    * @return {Ext.Element} The Element
 
5519
    */
 
5520
    shift : function(o){
 
5521
        o = getObject(o);
 
5522
        var dom = this.dom,
 
5523
            a = {};
 
5524
                
 
5525
        this.queueFx(o, function(){
 
5526
            for (var prop in o) {
 
5527
                if (o[prop] != UNDEFINED) {                                                 
 
5528
                    a[prop] = {to : o[prop]};                   
 
5529
                }
 
5530
            } 
 
5531
            
 
5532
            a.width ? a.width.to = fly(dom).adjustWidth(o.width) : a;
 
5533
            a.height ? a.height.to = fly(dom).adjustWidth(o.height) : a;   
 
5534
            
 
5535
            if (a.x || a.y || a.xy) {
 
5536
                a.points = a.xy || 
 
5537
                           {to : [ a.x ? a.x.to : fly(dom).getX(),
 
5538
                                   a.y ? a.y.to : fly(dom).getY()]};                  
 
5539
            }
 
5540
 
 
5541
            arguments.callee.anim = fly(dom).fxanim(a,
 
5542
                o, 
 
5543
                MOTION, 
 
5544
                .35, 
 
5545
                EASEOUT, 
 
5546
                function(){
 
5547
                    fly(dom).afterFx(o);
 
5548
                });
 
5549
        });
 
5550
        return this;
 
5551
    },
 
5552
 
 
5553
    /**
 
5554
     * Slides the element while fading it out of view.  An anchor point can be optionally passed to set the 
 
5555
     * ending point of the effect.
 
5556
     * Usage:
 
5557
     *<pre><code>
 
5558
// default: slide the element downward while fading out
 
5559
el.ghost();
 
5560
 
 
5561
// custom: slide the element out to the right with a 2-second duration
 
5562
el.ghost('r', { duration: 2 });
 
5563
 
 
5564
// common config options shown with default values
 
5565
el.ghost('b', {
 
5566
    easing: 'easeOut',
 
5567
    duration: .5,
 
5568
    remove: false,
 
5569
    useDisplay: false
 
5570
});
 
5571
</code></pre>
 
5572
     * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
 
5573
     * @param {Object} options (optional) Object literal with any of the Fx config options
 
5574
     * @return {Ext.Element} The Element
 
5575
     */
 
5576
    ghost : function(anchor, o){
 
5577
        o = getObject(o);
 
5578
        var me = this,
 
5579
            dom = me.dom,
 
5580
            st = dom.style,
 
5581
            a = {opacity: {to: 0}, points: {}},
 
5582
            pt = a.points,
 
5583
            r,
 
5584
            w,
 
5585
            h;
 
5586
            
 
5587
        anchor = anchor || "b";
 
5588
 
 
5589
        me.queueFx(o, function(){
 
5590
            // restore values after effect
 
5591
            r = fly(dom).getFxRestore();
 
5592
            w = fly(dom).getWidth();
 
5593
            h = fly(dom).getHeight();
 
5594
            
 
5595
            function after(){
 
5596
                o.useDisplay ? fly(dom).setDisplayed(FALSE) : fly(dom).hide();   
 
5597
                fly(dom).clearOpacity();
 
5598
                fly(dom).setPositioning(r.pos);
 
5599
                st.width = r.width;
 
5600
                st.height = r.height;
 
5601
                fly(dom).afterFx(o);
 
5602
            }
 
5603
                
 
5604
            pt.by = fly(dom).switchStatements(anchor.toLowerCase(), function(v1,v2){ return [v1, v2];}, {
 
5605
               t  : [0, -h],
 
5606
               l  : [-w, 0],
 
5607
               r  : [w, 0],
 
5608
               b  : [0, h],
 
5609
               tl : [-w, -h],
 
5610
               bl : [-w, h],
 
5611
               br : [w, h],
 
5612
               tr : [w, -h] 
 
5613
            });
 
5614
                
 
5615
            arguments.callee.anim = fly(dom).fxanim(a,
 
5616
                o,
 
5617
                MOTION,
 
5618
                .5,
 
5619
                EASEOUT, after);
 
5620
        });
 
5621
        return me;
 
5622
    },
 
5623
 
 
5624
    /**
 
5625
     * Ensures that all effects queued after syncFx is called on the element are
 
5626
     * run concurrently.  This is the opposite of {@link #sequenceFx}.
 
5627
     * @return {Ext.Element} The Element
 
5628
     */
 
5629
    syncFx : function(){
 
5630
        var me = this;
 
5631
        me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
 
5632
            block : FALSE,
 
5633
            concurrent : TRUE,
 
5634
            stopFx : FALSE
 
5635
        });
 
5636
        return me;
 
5637
    },
 
5638
 
 
5639
    /**
 
5640
     * Ensures that all effects queued after sequenceFx is called on the element are
 
5641
     * run in sequence.  This is the opposite of {@link #syncFx}.
 
5642
     * @return {Ext.Element} The Element
 
5643
     */
 
5644
    sequenceFx : function(){
 
5645
        var me = this;
 
5646
        me.fxDefaults = Ext.apply(me.fxDefaults || {}, {
 
5647
            block : FALSE,
 
5648
            concurrent : FALSE,
 
5649
            stopFx : FALSE
 
5650
        });
 
5651
        return me;
 
5652
    },
 
5653
 
 
5654
    /* @private */
 
5655
    nextFx : function(){        
 
5656
        var ef = getQueue(this.dom.id)[0];
 
5657
        if(ef){
 
5658
            ef.call(this);
 
5659
        }
 
5660
    },
 
5661
 
 
5662
    /**
 
5663
     * Returns true if the element has any effects actively running or queued, else returns false.
 
5664
     * @return {Boolean} True if element has active effects, else false
 
5665
     */
 
5666
    hasActiveFx : function(){
 
5667
        return getQueue(this.dom.id)[0];
 
5668
    },
 
5669
 
 
5670
    /**
 
5671
     * Stops any running effects and clears the element's internal effects queue if it contains
 
5672
     * any additional effects that haven't started yet.
 
5673
     * @return {Ext.Element} The Element
 
5674
     */
 
5675
    stopFx : function(finish){
 
5676
        var me = this,
 
5677
            id = me.dom.id;
 
5678
        if(me.hasActiveFx()){
 
5679
            var cur = getQueue(id)[0];
 
5680
            if(cur && cur.anim){
 
5681
                if(cur.anim.isAnimated){
 
5682
                    setQueue(id, [cur]); //clear
 
5683
                    cur.anim.stop(finish !== undefined ? finish : TRUE);
 
5684
                }else{
 
5685
                    setQueue(id, []);
 
5686
                }
 
5687
            }
 
5688
        }
 
5689
        return me;
 
5690
    },
 
5691
 
 
5692
    /* @private */
 
5693
    beforeFx : function(o){
 
5694
        if(this.hasActiveFx() && !o.concurrent){
 
5695
           if(o.stopFx){
 
5696
               this.stopFx();
 
5697
               return TRUE;
 
5698
           }
 
5699
           return FALSE;
 
5700
        }
 
5701
        return TRUE;
 
5702
    },
 
5703
 
 
5704
    /**
 
5705
     * Returns true if the element is currently blocking so that no other effect can be queued
 
5706
     * until this effect is finished, else returns false if blocking is not set.  This is commonly
 
5707
     * used to ensure that an effect initiated by a user action runs to completion prior to the
 
5708
     * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
 
5709
     * @return {Boolean} True if blocking, else false
 
5710
     */
 
5711
    hasFxBlock : function(){
 
5712
        var q = getQueue(this.dom.id);
 
5713
        return q && q[0] && q[0].block;
 
5714
    },
 
5715
 
 
5716
    /* @private */
 
5717
    queueFx : function(o, fn){
 
5718
        var me = fly(this.dom);
 
5719
        if(!me.hasFxBlock()){
 
5720
            Ext.applyIf(o, me.fxDefaults);
 
5721
            if(!o.concurrent){
 
5722
                var run = me.beforeFx(o);
 
5723
                fn.block = o.block;
 
5724
                getQueue(me.dom.id).push(fn);
 
5725
                if(run){
 
5726
                    me.nextFx();
 
5727
                }
 
5728
            }else{
 
5729
                fn.call(me);
 
5730
            }
 
5731
        }
 
5732
        return me;
 
5733
    },
 
5734
 
 
5735
    /* @private */
 
5736
    fxWrap : function(pos, o, vis){ 
 
5737
        var dom = this.dom,
 
5738
            wrap,
 
5739
            wrapXY;
 
5740
        if(!o.wrap || !(wrap = Ext.getDom(o.wrap))){            
 
5741
            if(o.fixPosition){
 
5742
                wrapXY = fly(dom).getXY();
 
5743
            }
 
5744
            var div = document.createElement("div");
 
5745
            div.style.visibility = vis;
 
5746
            wrap = dom.parentNode.insertBefore(div, dom);
 
5747
            fly(wrap).setPositioning(pos);
 
5748
            if(fly(wrap).isStyle(POSITION, "static")){
 
5749
                fly(wrap).position("relative");
 
5750
            }
 
5751
            fly(dom).clearPositioning('auto');
 
5752
            fly(wrap).clip();
 
5753
            wrap.appendChild(dom);
 
5754
            if(wrapXY){
 
5755
                fly(wrap).setXY(wrapXY);
 
5756
            }
 
5757
        }
 
5758
        return wrap;
 
5759
    },
 
5760
 
 
5761
    /* @private */
 
5762
    fxUnwrap : function(wrap, pos, o){      
 
5763
        var dom = this.dom;
 
5764
        fly(dom).clearPositioning();
 
5765
        fly(dom).setPositioning(pos);
 
5766
        if(!o.wrap){
 
5767
            var pn = fly(wrap).dom.parentNode;
 
5768
            pn.insertBefore(dom, wrap); 
 
5769
            fly(wrap).remove();
 
5770
        }
 
5771
    },
 
5772
 
 
5773
    /* @private */
 
5774
    getFxRestore : function(){
 
5775
        var st = this.dom.style;
 
5776
        return {pos: this.getPositioning(), width: st.width, height : st.height};
 
5777
    },
 
5778
 
 
5779
    /* @private */
 
5780
    afterFx : function(o){
 
5781
        var dom = this.dom,
 
5782
            id = dom.id;
 
5783
        if(o.afterStyle){
 
5784
            fly(dom).setStyle(o.afterStyle);            
 
5785
        }
 
5786
        if(o.afterCls){
 
5787
            fly(dom).addClass(o.afterCls);
 
5788
        }
 
5789
        if(o.remove == TRUE){
 
5790
            fly(dom).remove();
 
5791
        }
 
5792
        if(o.callback){
 
5793
            o.callback.call(o.scope, fly(dom));
 
5794
        }
 
5795
        if(!o.concurrent){
 
5796
            getQueue(id).shift();
 
5797
            fly(dom).nextFx();
 
5798
        }
 
5799
    },
 
5800
 
 
5801
    /* @private */
 
5802
    fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
 
5803
        animType = animType || 'run';
 
5804
        opt = opt || {};
 
5805
        var anim = Ext.lib.Anim[animType](
 
5806
                this.dom, 
 
5807
                args,
 
5808
                (opt.duration || defaultDur) || .35,
 
5809
                (opt.easing || defaultEase) || EASEOUT,
 
5810
                cb,            
 
5811
                this
 
5812
            );
 
5813
        opt.anim = anim;
 
5814
        return anim;
 
5815
    }
 
5816
};
 
5817
 
 
5818
// backwards compat
 
5819
Ext.Fx.resize = Ext.Fx.scale;
 
5820
 
 
5821
//When included, Ext.Fx is automatically applied to Element so that all basic
 
5822
//effects are available directly via the Element API
 
5823
Ext.Element.addMethods(Ext.Fx);
 
5824
})();
 
5825
/**
 
5826
 * @class Ext.CompositeElementLite
 
5827
 * <p>This class encapsulates a <i>collection</i> of DOM elements, providing methods to filter
 
5828
 * members, or to perform collective actions upon the whole set.</p>
 
5829
 * <p>Although they are not listed, this class supports all of the methods of {@link Ext.Element} and
 
5830
 * {@link Ext.Fx}. The methods from these classes will be performed on all the elements in this collection.</p>
 
5831
 * Example:<pre><code>
 
5832
var els = Ext.select("#some-el div.some-class");
 
5833
// or select directly from an existing element
 
5834
var el = Ext.get('some-el');
 
5835
el.select('div.some-class');
 
5836
 
 
5837
els.setWidth(100); // all elements become 100 width
 
5838
els.hide(true); // all elements fade out and hide
 
5839
// or
 
5840
els.setWidth(100).hide(true);
 
5841
</code>
 
5842
 */
 
5843
Ext.CompositeElementLite = function(els, root){
 
5844
    /**
 
5845
     * <p>The Array of DOM elements which this CompositeElement encapsulates. Read-only.</p>
 
5846
     * <p>This will not <i>usually</i> be accessed in developers' code, but developers wishing
 
5847
     * to augment the capabilities of the CompositeElementLite class may use it when adding
 
5848
     * methods to the class.</p>
 
5849
     * <p>For example to add the <code>nextAll</code> method to the class to <b>add</b> all
 
5850
     * following siblings of selected elements, the code would be</p><code><pre>
 
5851
Ext.override(Ext.CompositeElementLite, {
 
5852
    nextAll: function() {
 
5853
        var els = this.elements, i, l = els.length, n, r = [], ri = -1;
 
5854
 
 
5855
//      Loop through all elements in this Composite, accumulating
 
5856
//      an Array of all siblings.
 
5857
        for (i = 0; i < l; i++) {
 
5858
            for (n = els[i].nextSibling; n; n = n.nextSibling) {
 
5859
                r[++ri] = n;
 
5860
            }
 
5861
        }
 
5862
 
 
5863
//      Add all found siblings to this Composite
 
5864
        return this.add(r);
 
5865
    }
 
5866
});</pre></code>
 
5867
     * @type Array
 
5868
     * @property elements
 
5869
     */
 
5870
    this.elements = [];
 
5871
    this.add(els, root);
 
5872
    this.el = new Ext.Element.Flyweight();
 
5873
};
 
5874
 
 
5875
Ext.CompositeElementLite.prototype = {
 
5876
    isComposite: true,
 
5877
 
 
5878
    // private
 
5879
    getElement : function(el){
 
5880
        // Set the shared flyweight dom property to the current element
 
5881
        var e = this.el;
 
5882
        e.dom = el;
 
5883
        e.id = el.id;
 
5884
        return e;
 
5885
    },
 
5886
 
 
5887
    // private
 
5888
    transformElement : function(el){
 
5889
        return Ext.getDom(el);
 
5890
    },
 
5891
 
 
5892
    /**
 
5893
     * Returns the number of elements in this Composite.
 
5894
     * @return Number
 
5895
     */
 
5896
    getCount : function(){
 
5897
        return this.elements.length;
 
5898
    },
 
5899
    /**
 
5900
     * Adds elements to this Composite object.
 
5901
     * @param {Mixed} els Either an Array of DOM elements to add, or another Composite object who's elements should be added.
 
5902
     * @return {CompositeElement} This Composite object.
 
5903
     */
 
5904
    add : function(els, root){
 
5905
        var me = this,
 
5906
            elements = me.elements;
 
5907
        if(!els){
 
5908
            return this;
 
5909
        }
 
5910
        if(typeof els == "string"){
 
5911
            els = Ext.Element.selectorFunction(els, root);
 
5912
        }else if(els.isComposite){
 
5913
            els = els.elements;
 
5914
        }else if(!Ext.isIterable(els)){
 
5915
            els = [els];
 
5916
        }
 
5917
 
 
5918
        for(var i = 0, len = els.length; i < len; ++i){
 
5919
            elements.push(me.transformElement(els[i]));
 
5920
        }
 
5921
        return me;
 
5922
    },
 
5923
 
 
5924
    invoke : function(fn, args){
 
5925
        var me = this,
 
5926
            els = me.elements,
 
5927
            len = els.length,
 
5928
            e,
 
5929
            i;
 
5930
 
 
5931
        for(i = 0; i < len; i++) {
 
5932
            e = els[i];
 
5933
            if(e){
 
5934
                Ext.Element.prototype[fn].apply(me.getElement(e), args);
 
5935
            }
 
5936
        }
 
5937
        return me;
 
5938
    },
 
5939
    /**
 
5940
     * Returns a flyweight Element of the dom element object at the specified index
 
5941
     * @param {Number} index
 
5942
     * @return {Ext.Element}
 
5943
     */
 
5944
    item : function(index){
 
5945
        var me = this,
 
5946
            el = me.elements[index],
 
5947
            out = null;
 
5948
 
 
5949
        if(el){
 
5950
            out = me.getElement(el);
 
5951
        }
 
5952
        return out;
 
5953
    },
 
5954
 
 
5955
    // fixes scope with flyweight
 
5956
    addListener : function(eventName, handler, scope, opt){
 
5957
        var els = this.elements,
 
5958
            len = els.length,
 
5959
            i, e;
 
5960
 
 
5961
        for(i = 0; i<len; i++) {
 
5962
            e = els[i];
 
5963
            if(e) {
 
5964
                Ext.EventManager.on(e, eventName, handler, scope || e, opt);
 
5965
            }
 
5966
        }
 
5967
        return this;
 
5968
    },
 
5969
    /**
 
5970
     * <p>Calls the passed function for each element in this composite.</p>
 
5971
     * @param {Function} fn The function to call. The function is passed the following parameters:<ul>
 
5972
     * <li><b>el</b> : Element<div class="sub-desc">The current Element in the iteration.
 
5973
     * <b>This is the flyweight (shared) Ext.Element instance, so if you require a
 
5974
     * a reference to the dom node, use el.dom.</b></div></li>
 
5975
     * <li><b>c</b> : Composite<div class="sub-desc">This Composite object.</div></li>
 
5976
     * <li><b>idx</b> : Number<div class="sub-desc">The zero-based index in the iteration.</div></li>
 
5977
     * </ul>
 
5978
     * @param {Object} scope (optional) The scope (<i>this</i> reference) in which the function is executed. (defaults to the Element)
 
5979
     * @return {CompositeElement} this
 
5980
     */
 
5981
    each : function(fn, scope){
 
5982
        var me = this,
 
5983
            els = me.elements,
 
5984
            len = els.length,
 
5985
            i, e;
 
5986
 
 
5987
        for(i = 0; i<len; i++) {
 
5988
            e = els[i];
 
5989
            if(e){
 
5990
                e = this.getElement(e);
 
5991
                if(fn.call(scope || e, e, me, i) === false){
 
5992
                    break;
 
5993
                }
 
5994
            }
 
5995
        }
 
5996
        return me;
 
5997
    },
 
5998
 
 
5999
    /**
 
6000
    * Clears this Composite and adds the elements passed.
 
6001
    * @param {Mixed} els Either an array of DOM elements, or another Composite from which to fill this Composite.
 
6002
    * @return {CompositeElement} this
 
6003
    */
 
6004
    fill : function(els){
 
6005
        var me = this;
 
6006
        me.elements = [];
 
6007
        me.add(els);
 
6008
        return me;
 
6009
    },
 
6010
 
 
6011
    /**
 
6012
     * Filters this composite to only elements that match the passed selector.
 
6013
     * @param {String/Function} selector A string CSS selector or a comparison function.
 
6014
     * The comparison function will be called with the following arguments:<ul>
 
6015
     * <li><code>el</code> : Ext.Element<div class="sub-desc">The current DOM element.</div></li>
 
6016
     * <li><code>index</code> : Number<div class="sub-desc">The current index within the collection.</div></li>
 
6017
     * </ul>
 
6018
     * @return {CompositeElement} this
 
6019
     */
 
6020
    filter : function(selector){
 
6021
        var els = [],
 
6022
            me = this,
 
6023
            fn = Ext.isFunction(selector) ? selector
 
6024
                : function(el){
 
6025
                    return el.is(selector);
 
6026
                };
 
6027
 
 
6028
        me.each(function(el, self, i) {
 
6029
            if (fn(el, i) !== false) {
 
6030
                els[els.length] = me.transformElement(el);
 
6031
            }
 
6032
        });
 
6033
        
 
6034
        me.elements = els;
 
6035
        return me;
 
6036
    },
 
6037
 
 
6038
    /**
 
6039
     * Find the index of the passed element within the composite collection.
 
6040
     * @param el {Mixed} The id of an element, or an Ext.Element, or an HtmlElement to find within the composite collection.
 
6041
     * @return Number The index of the passed Ext.Element in the composite collection, or -1 if not found.
 
6042
     */
 
6043
    indexOf : function(el){
 
6044
        return this.elements.indexOf(this.transformElement(el));
 
6045
    },
 
6046
 
 
6047
    /**
 
6048
    * Replaces the specified element with the passed element.
 
6049
    * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
 
6050
    * to replace.
 
6051
    * @param {Mixed} replacement The id of an element or the Element itself.
 
6052
    * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
 
6053
    * @return {CompositeElement} this
 
6054
    */
 
6055
    replaceElement : function(el, replacement, domReplace){
 
6056
        var index = !isNaN(el) ? el : this.indexOf(el),
 
6057
            d;
 
6058
        if(index > -1){
 
6059
            replacement = Ext.getDom(replacement);
 
6060
            if(domReplace){
 
6061
                d = this.elements[index];
 
6062
                d.parentNode.insertBefore(replacement, d);
 
6063
                Ext.removeNode(d);
 
6064
            }
 
6065
            this.elements.splice(index, 1, replacement);
 
6066
        }
 
6067
        return this;
 
6068
    },
 
6069
 
 
6070
    /**
 
6071
     * Removes all elements.
 
6072
     */
 
6073
    clear : function(){
 
6074
        this.elements = [];
 
6075
    }
 
6076
};
 
6077
 
 
6078
Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
 
6079
 
 
6080
/**
 
6081
 * @private
 
6082
 * Copies all of the functions from Ext.Element's prototype onto CompositeElementLite's prototype.
 
6083
 * This is called twice - once immediately below, and once again after additional Ext.Element
 
6084
 * are added in Ext JS
 
6085
 */
 
6086
Ext.CompositeElementLite.importElementMethods = function() {
 
6087
    var fnName,
 
6088
        ElProto = Ext.Element.prototype,
 
6089
        CelProto = Ext.CompositeElementLite.prototype;
 
6090
 
 
6091
    for (fnName in ElProto) {
 
6092
        if (typeof ElProto[fnName] == 'function'){
 
6093
            (function(fnName) {
 
6094
                CelProto[fnName] = CelProto[fnName] || function() {
 
6095
                    return this.invoke(fnName, arguments);
 
6096
                };
 
6097
            }).call(CelProto, fnName);
 
6098
 
 
6099
        }
 
6100
    }
 
6101
};
 
6102
 
 
6103
Ext.CompositeElementLite.importElementMethods();
 
6104
 
 
6105
if(Ext.DomQuery){
 
6106
    Ext.Element.selectorFunction = Ext.DomQuery.select;
 
6107
}
 
6108
 
 
6109
/**
 
6110
 * Selects elements based on the passed CSS selector to enable {@link Ext.Element Element} methods
 
6111
 * to be applied to many related elements in one statement through the returned {@link Ext.CompositeElement CompositeElement} or
 
6112
 * {@link Ext.CompositeElementLite CompositeElementLite} object.
 
6113
 * @param {String/Array} selector The CSS selector or an array of elements
 
6114
 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
 
6115
 * @return {CompositeElementLite/CompositeElement}
 
6116
 * @member Ext.Element
 
6117
 * @method select
 
6118
 */
 
6119
Ext.Element.select = function(selector, root){
 
6120
    var els;
 
6121
    if(typeof selector == "string"){
 
6122
        els = Ext.Element.selectorFunction(selector, root);
 
6123
    }else if(selector.length !== undefined){
 
6124
        els = selector;
 
6125
    }else{
 
6126
        throw "Invalid selector";
 
6127
    }
 
6128
    return new Ext.CompositeElementLite(els);
 
6129
};
 
6130
/**
 
6131
 * Selects elements based on the passed CSS selector to enable {@link Ext.Element Element} methods
 
6132
 * to be applied to many related elements in one statement through the returned {@link Ext.CompositeElement CompositeElement} or
 
6133
 * {@link Ext.CompositeElementLite CompositeElementLite} object.
 
6134
 * @param {String/Array} selector The CSS selector or an array of elements
 
6135
 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
 
6136
 * @return {CompositeElementLite/CompositeElement}
 
6137
 * @member Ext
 
6138
 * @method select
 
6139
 */
 
6140
Ext.select = Ext.Element.select;
 
6141
(function(){
 
6142
    var BEFOREREQUEST = "beforerequest",
 
6143
        REQUESTCOMPLETE = "requestcomplete",
 
6144
        REQUESTEXCEPTION = "requestexception",
 
6145
        UNDEFINED = undefined,
 
6146
        LOAD = 'load',
 
6147
        POST = 'POST',
 
6148
        GET = 'GET',
 
6149
        WINDOW = window;
 
6150
 
 
6151
    /**
 
6152
     * @class Ext.data.Connection
 
6153
     * @extends Ext.util.Observable
 
6154
     * <p>The class encapsulates a connection to the page's originating domain, allowing requests to be made
 
6155
     * either to a configured URL, or to a URL specified at request time.</p>
 
6156
     * <p>Requests made by this class are asynchronous, and will return immediately. No data from
 
6157
     * the server will be available to the statement immediately following the {@link #request} call.
 
6158
     * To process returned data, use a
 
6159
     * <a href="#request-option-success" ext:member="request-option-success" ext:cls="Ext.data.Connection">success callback</a>
 
6160
     * in the request options object,
 
6161
     * or an {@link #requestcomplete event listener}.</p>
 
6162
     * <p><h3>File Uploads</h3><a href="#request-option-isUpload" ext:member="request-option-isUpload" ext:cls="Ext.data.Connection">File uploads</a> are not performed using normal "Ajax" techniques, that
 
6163
     * is they are <b>not</b> performed using XMLHttpRequests. Instead the form is submitted in the standard
 
6164
     * manner with the DOM <tt>&lt;form></tt> element temporarily modified to have its
 
6165
     * <a href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">target</a> set to refer
 
6166
     * to a dynamically generated, hidden <tt>&lt;iframe></tt> which is inserted into the document
 
6167
     * but removed after the return data has been gathered.</p>
 
6168
     * <p>The server response is parsed by the browser to create the document for the IFRAME. If the
 
6169
     * server is using JSON to send the return object, then the
 
6170
     * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">Content-Type</a> header
 
6171
     * must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.</p>
 
6172
     * <p>Characters which are significant to an HTML parser must be sent as HTML entities, so encode
 
6173
     * "&lt;" as "&amp;lt;", "&amp;" as "&amp;amp;" etc.</p>
 
6174
     * <p>The response text is retrieved from the document, and a fake XMLHttpRequest object
 
6175
     * is created containing a <tt>responseText</tt> property in order to conform to the
 
6176
     * requirements of event handlers and callbacks.</p>
 
6177
     * <p>Be aware that file upload packets are sent with the content type <a href="http://www.faqs.org/rfcs/rfc2388.html">multipart/form</a>
 
6178
     * and some server technologies (notably JEE) may require some custom processing in order to
 
6179
     * retrieve parameter names and parameter values from the packet content.</p>
 
6180
     * <p>Also note that it's not possible to check the response code of the hidden iframe, so the success handler will ALWAYS fire.</p>
 
6181
     * @constructor
 
6182
     * @param {Object} config a configuration object.
 
6183
     */
 
6184
    Ext.data.Connection = function(config){
 
6185
        Ext.apply(this, config);
 
6186
        this.addEvents(
 
6187
            /**
 
6188
             * @event beforerequest
 
6189
             * Fires before a network request is made to retrieve a data object.
 
6190
             * @param {Connection} conn This Connection object.
 
6191
             * @param {Object} options The options config object passed to the {@link #request} method.
 
6192
             */
 
6193
            BEFOREREQUEST,
 
6194
            /**
 
6195
             * @event requestcomplete
 
6196
             * Fires if the request was successfully completed.
 
6197
             * @param {Connection} conn This Connection object.
 
6198
             * @param {Object} response The XHR object containing the response data.
 
6199
             * See <a href="http://www.w3.org/TR/XMLHttpRequest/">The XMLHttpRequest Object</a>
 
6200
             * for details.
 
6201
             * @param {Object} options The options config object passed to the {@link #request} method.
 
6202
             */
 
6203
            REQUESTCOMPLETE,
 
6204
            /**
 
6205
             * @event requestexception
 
6206
             * Fires if an error HTTP status was returned from the server.
 
6207
             * See <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">HTTP Status Code Definitions</a>
 
6208
             * for details of HTTP status codes.
 
6209
             * @param {Connection} conn This Connection object.
 
6210
             * @param {Object} response The XHR object containing the response data.
 
6211
             * See <a href="http://www.w3.org/TR/XMLHttpRequest/">The XMLHttpRequest Object</a>
 
6212
             * for details.
 
6213
             * @param {Object} options The options config object passed to the {@link #request} method.
 
6214
             */
 
6215
            REQUESTEXCEPTION
 
6216
        );
 
6217
        Ext.data.Connection.superclass.constructor.call(this);
 
6218
    };
 
6219
 
 
6220
    Ext.extend(Ext.data.Connection, Ext.util.Observable, {
 
6221
        /**
 
6222
         * @cfg {String} url (Optional) <p>The default URL to be used for requests to the server. Defaults to undefined.</p>
 
6223
         * <p>The <code>url</code> config may be a function which <i>returns</i> the URL to use for the Ajax request. The scope
 
6224
         * (<code><b>this</b></code> reference) of the function is the <code>scope</code> option passed to the {@link #request} method.</p>
 
6225
         */
 
6226
        /**
 
6227
         * @cfg {Object} extraParams (Optional) An object containing properties which are used as
 
6228
         * extra parameters to each request made by this object. (defaults to undefined)
 
6229
         */
 
6230
        /**
 
6231
         * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
 
6232
         *  to each request made by this object. (defaults to undefined)
 
6233
         */
 
6234
        /**
 
6235
         * @cfg {String} method (Optional) The default HTTP method to be used for requests.
 
6236
         * (defaults to undefined; if not set, but {@link #request} params are present, POST will be used;
 
6237
         * otherwise, GET will be used.)
 
6238
         */
 
6239
        /**
 
6240
         * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
 
6241
         */
 
6242
        timeout : 30000,
 
6243
        /**
 
6244
         * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
 
6245
         * @type Boolean
 
6246
         */
 
6247
        autoAbort:false,
 
6248
 
 
6249
        /**
 
6250
         * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
 
6251
         * @type Boolean
 
6252
         */
 
6253
        disableCaching: true,
 
6254
 
 
6255
        /**
 
6256
         * @cfg {String} disableCachingParam (Optional) Change the parameter which is sent went disabling caching
 
6257
         * through a cache buster. Defaults to '_dc'
 
6258
         * @type String
 
6259
         */
 
6260
        disableCachingParam: '_dc',
 
6261
 
 
6262
        /**
 
6263
         * <p>Sends an HTTP request to a remote server.</p>
 
6264
         * <p><b>Important:</b> Ajax server requests are asynchronous, and this call will
 
6265
         * return before the response has been received. Process any returned data
 
6266
         * in a callback function.</p>
 
6267
         * <pre><code>
 
6268
Ext.Ajax.request({
 
6269
   url: 'ajax_demo/sample.json',
 
6270
   success: function(response, opts) {
 
6271
      var obj = Ext.decode(response.responseText);
 
6272
      console.dir(obj);
 
6273
   },
 
6274
   failure: function(response, opts) {
 
6275
      console.log('server-side failure with status code ' + response.status);
 
6276
   }
 
6277
});
 
6278
         * </code></pre>
 
6279
         * <p>To execute a callback function in the correct scope, use the <tt>scope</tt> option.</p>
 
6280
         * @param {Object} options An object which may contain the following properties:<ul>
 
6281
         * <li><b>url</b> : String/Function (Optional)<div class="sub-desc">The URL to
 
6282
         * which to send the request, or a function to call which returns a URL string. The scope of the
 
6283
         * function is specified by the <tt>scope</tt> option. Defaults to the configured
 
6284
         * <tt>{@link #url}</tt>.</div></li>
 
6285
         * <li><b>params</b> : Object/String/Function (Optional)<div class="sub-desc">
 
6286
         * An object containing properties which are used as parameters to the
 
6287
         * request, a url encoded string or a function to call to get either. The scope of the function
 
6288
         * is specified by the <tt>scope</tt> option.</div></li>
 
6289
         * <li><b>method</b> : String (Optional)<div class="sub-desc">The HTTP method to use
 
6290
         * for the request. Defaults to the configured method, or if no method was configured,
 
6291
         * "GET" if no parameters are being sent, and "POST" if parameters are being sent.  Note that
 
6292
         * the method name is case-sensitive and should be all caps.</div></li>
 
6293
         * <li><b>callback</b> : Function (Optional)<div class="sub-desc">The
 
6294
         * function to be called upon receipt of the HTTP response. The callback is
 
6295
         * called regardless of success or failure and is passed the following
 
6296
         * parameters:<ul>
 
6297
         * <li><b>options</b> : Object<div class="sub-desc">The parameter to the request call.</div></li>
 
6298
         * <li><b>success</b> : Boolean<div class="sub-desc">True if the request succeeded.</div></li>
 
6299
         * <li><b>response</b> : Object<div class="sub-desc">The XMLHttpRequest object containing the response data.
 
6300
         * See <a href="http://www.w3.org/TR/XMLHttpRequest/">http://www.w3.org/TR/XMLHttpRequest/</a> for details about
 
6301
         * accessing elements of the response.</div></li>
 
6302
         * </ul></div></li>
 
6303
         * <li><a id="request-option-success"></a><b>success</b> : Function (Optional)<div class="sub-desc">The function
 
6304
         * to be called upon success of the request. The callback is passed the following
 
6305
         * parameters:<ul>
 
6306
         * <li><b>response</b> : Object<div class="sub-desc">The XMLHttpRequest object containing the response data.</div></li>
 
6307
         * <li><b>options</b> : Object<div class="sub-desc">The parameter to the request call.</div></li>
 
6308
         * </ul></div></li>
 
6309
         * <li><b>failure</b> : Function (Optional)<div class="sub-desc">The function
 
6310
         * to be called upon failure of the request. The callback is passed the
 
6311
         * following parameters:<ul>
 
6312
         * <li><b>response</b> : Object<div class="sub-desc">The XMLHttpRequest object containing the response data.</div></li>
 
6313
         * <li><b>options</b> : Object<div class="sub-desc">The parameter to the request call.</div></li>
 
6314
         * </ul></div></li>
 
6315
         * <li><b>scope</b> : Object (Optional)<div class="sub-desc">The scope in
 
6316
         * which to execute the callbacks: The "this" object for the callback function. If the <tt>url</tt>, or <tt>params</tt> options were
 
6317
         * specified as functions from which to draw values, then this also serves as the scope for those function calls.
 
6318
         * Defaults to the browser window.</div></li>
 
6319
         * <li><b>timeout</b> : Number (Optional)<div class="sub-desc">The timeout in milliseconds to be used for this request. Defaults to 30 seconds.</div></li>
 
6320
         * <li><b>form</b> : Element/HTMLElement/String (Optional)<div class="sub-desc">The <tt>&lt;form&gt;</tt>
 
6321
         * Element or the id of the <tt>&lt;form&gt;</tt> to pull parameters from.</div></li>
 
6322
         * <li><a id="request-option-isUpload"></a><b>isUpload</b> : Boolean (Optional)<div class="sub-desc"><b>Only meaningful when used
 
6323
         * with the <tt>form</tt> option</b>.
 
6324
         * <p>True if the form object is a file upload (will be set automatically if the form was
 
6325
         * configured with <b><tt>enctype</tt></b> "multipart/form-data").</p>
 
6326
         * <p>File uploads are not performed using normal "Ajax" techniques, that is they are <b>not</b>
 
6327
         * performed using XMLHttpRequests. Instead the form is submitted in the standard manner with the
 
6328
         * DOM <tt>&lt;form></tt> element temporarily modified to have its
 
6329
         * <a href="http://www.w3.org/TR/REC-html40/present/frames.html#adef-target">target</a> set to refer
 
6330
         * to a dynamically generated, hidden <tt>&lt;iframe></tt> which is inserted into the document
 
6331
         * but removed after the return data has been gathered.</p>
 
6332
         * <p>The server response is parsed by the browser to create the document for the IFRAME. If the
 
6333
         * server is using JSON to send the return object, then the
 
6334
         * <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17">Content-Type</a> header
 
6335
         * must be set to "text/html" in order to tell the browser to insert the text unchanged into the document body.</p>
 
6336
         * <p>The response text is retrieved from the document, and a fake XMLHttpRequest object
 
6337
         * is created containing a <tt>responseText</tt> property in order to conform to the
 
6338
         * requirements of event handlers and callbacks.</p>
 
6339
         * <p>Be aware that file upload packets are sent with the content type <a href="http://www.faqs.org/rfcs/rfc2388.html">multipart/form</a>
 
6340
         * and some server technologies (notably JEE) may require some custom processing in order to
 
6341
         * retrieve parameter names and parameter values from the packet content.</p>
 
6342
         * </div></li>
 
6343
         * <li><b>headers</b> : Object (Optional)<div class="sub-desc">Request
 
6344
         * headers to set for the request.</div></li>
 
6345
         * <li><b>xmlData</b> : Object (Optional)<div class="sub-desc">XML document
 
6346
         * to use for the post. Note: This will be used instead of params for the post
 
6347
         * data. Any params will be appended to the URL.</div></li>
 
6348
         * <li><b>jsonData</b> : Object/String (Optional)<div class="sub-desc">JSON
 
6349
         * data to use as the post. Note: This will be used instead of params for the post
 
6350
         * data. Any params will be appended to the URL.</div></li>
 
6351
         * <li><b>disableCaching</b> : Boolean (Optional)<div class="sub-desc">True
 
6352
         * to add a unique cache-buster param to GET requests.</div></li>
 
6353
         * </ul></p>
 
6354
         * <p>The options object may also contain any other property which might be needed to perform
 
6355
         * postprocessing in a callback because it is passed to callback functions.</p>
 
6356
         * @return {Number} transactionId The id of the server transaction. This may be used
 
6357
         * to cancel the request.
 
6358
         */
 
6359
        request : function(o){
 
6360
            var me = this;
 
6361
            if(me.fireEvent(BEFOREREQUEST, me, o)){
 
6362
                if (o.el) {
 
6363
                    if(!Ext.isEmpty(o.indicatorText)){
 
6364
                        me.indicatorText = '<div class="loading-indicator">'+o.indicatorText+"</div>";
 
6365
                    }
 
6366
                    if(me.indicatorText) {
 
6367
                        Ext.getDom(o.el).innerHTML = me.indicatorText;
 
6368
                    }
 
6369
                    o.success = (Ext.isFunction(o.success) ? o.success : function(){}).createInterceptor(function(response) {
 
6370
                        Ext.getDom(o.el).innerHTML = response.responseText;
 
6371
                    });
 
6372
                }
 
6373
 
 
6374
                var p = o.params,
 
6375
                    url = o.url || me.url,
 
6376
                    method,
 
6377
                    cb = {success: me.handleResponse,
 
6378
                          failure: me.handleFailure,
 
6379
                          scope: me,
 
6380
                          argument: {options: o},
 
6381
                          timeout : Ext.num(o.timeout, me.timeout)
 
6382
                    },
 
6383
                    form,
 
6384
                    serForm;
 
6385
 
 
6386
 
 
6387
                if (Ext.isFunction(p)) {
 
6388
                    p = p.call(o.scope||WINDOW, o);
 
6389
                }
 
6390
 
 
6391
                p = Ext.urlEncode(me.extraParams, Ext.isObject(p) ? Ext.urlEncode(p) : p);
 
6392
 
 
6393
                if (Ext.isFunction(url)) {
 
6394
                    url = url.call(o.scope || WINDOW, o);
 
6395
                }
 
6396
 
 
6397
                if((form = Ext.getDom(o.form))){
 
6398
                    url = url || form.action;
 
6399
                     if(o.isUpload || (/multipart\/form-data/i.test(form.getAttribute("enctype")))) {
 
6400
                         return me.doFormUpload.call(me, o, p, url);
 
6401
                     }
 
6402
                    serForm = Ext.lib.Ajax.serializeForm(form);
 
6403
                    p = p ? (p + '&' + serForm) : serForm;
 
6404
                }
 
6405
 
 
6406
                method = o.method || me.method || ((p || o.xmlData || o.jsonData) ? POST : GET);
 
6407
 
 
6408
                if(method === GET && (me.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
 
6409
                    var dcp = o.disableCachingParam || me.disableCachingParam;
 
6410
                    url = Ext.urlAppend(url, dcp + '=' + (new Date().getTime()));
 
6411
                }
 
6412
 
 
6413
                o.headers = Ext.apply(o.headers || {}, me.defaultHeaders || {});
 
6414
 
 
6415
                if(o.autoAbort === true || me.autoAbort) {
 
6416
                    me.abort();
 
6417
                }
 
6418
 
 
6419
                if((method == GET || o.xmlData || o.jsonData) && p){
 
6420
                    url = Ext.urlAppend(url, p);
 
6421
                    p = '';
 
6422
                }
 
6423
                return (me.transId = Ext.lib.Ajax.request(method, url, cb, p, o));
 
6424
            }else{
 
6425
                return o.callback ? o.callback.apply(o.scope, [o,UNDEFINED,UNDEFINED]) : null;
 
6426
            }
 
6427
        },
 
6428
 
 
6429
        /**
 
6430
         * Determine whether this object has a request outstanding.
 
6431
         * @param {Number} transactionId (Optional) defaults to the last transaction
 
6432
         * @return {Boolean} True if there is an outstanding request.
 
6433
         */
 
6434
        isLoading : function(transId){
 
6435
            return transId ? Ext.lib.Ajax.isCallInProgress(transId) : !! this.transId;
 
6436
        },
 
6437
 
 
6438
        /**
 
6439
         * Aborts any outstanding request.
 
6440
         * @param {Number} transactionId (Optional) defaults to the last transaction
 
6441
         */
 
6442
        abort : function(transId){
 
6443
            if(transId || this.isLoading()){
 
6444
                Ext.lib.Ajax.abort(transId || this.transId);
 
6445
            }
 
6446
        },
 
6447
 
 
6448
        // private
 
6449
        handleResponse : function(response){
 
6450
            this.transId = false;
 
6451
            var options = response.argument.options;
 
6452
            response.argument = options ? options.argument : null;
 
6453
            this.fireEvent(REQUESTCOMPLETE, this, response, options);
 
6454
            if(options.success){
 
6455
                options.success.call(options.scope, response, options);
 
6456
            }
 
6457
            if(options.callback){
 
6458
                options.callback.call(options.scope, options, true, response);
 
6459
            }
 
6460
        },
 
6461
 
 
6462
        // private
 
6463
        handleFailure : function(response, e){
 
6464
            this.transId = false;
 
6465
            var options = response.argument.options;
 
6466
            response.argument = options ? options.argument : null;
 
6467
            this.fireEvent(REQUESTEXCEPTION, this, response, options, e);
 
6468
            if(options.failure){
 
6469
                options.failure.call(options.scope, response, options);
 
6470
            }
 
6471
            if(options.callback){
 
6472
                options.callback.call(options.scope, options, false, response);
 
6473
            }
 
6474
        },
 
6475
 
 
6476
        // private
 
6477
        doFormUpload : function(o, ps, url){
 
6478
            var id = Ext.id(),
 
6479
                doc = document,
 
6480
                frame = doc.createElement('iframe'),
 
6481
                form = Ext.getDom(o.form),
 
6482
                hiddens = [],
 
6483
                hd,
 
6484
                encoding = 'multipart/form-data',
 
6485
                buf = {
 
6486
                    target: form.target,
 
6487
                    method: form.method,
 
6488
                    encoding: form.encoding,
 
6489
                    enctype: form.enctype,
 
6490
                    action: form.action
 
6491
                };
 
6492
 
 
6493
            /*
 
6494
             * Originally this behaviour was modified for Opera 10 to apply the secure URL after
 
6495
             * the frame had been added to the document. It seems this has since been corrected in
 
6496
             * Opera so the behaviour has been reverted, the URL will be set before being added.
 
6497
             */
 
6498
            Ext.fly(frame).set({
 
6499
                id: id,
 
6500
                name: id,
 
6501
                cls: 'x-hidden',
 
6502
                src: Ext.SSL_SECURE_URL
 
6503
            }); 
 
6504
 
 
6505
            doc.body.appendChild(frame);
 
6506
 
 
6507
            // This is required so that IE doesn't pop the response up in a new window.
 
6508
            if(Ext.isIE){
 
6509
               document.frames[id].name = id;
 
6510
            }
 
6511
 
 
6512
 
 
6513
            Ext.fly(form).set({
 
6514
                target: id,
 
6515
                method: POST,
 
6516
                enctype: encoding,
 
6517
                encoding: encoding,
 
6518
                action: url || buf.action
 
6519
            });
 
6520
 
 
6521
            // add dynamic params
 
6522
            Ext.iterate(Ext.urlDecode(ps, false), function(k, v){
 
6523
                hd = doc.createElement('input');
 
6524
                Ext.fly(hd).set({
 
6525
                    type: 'hidden',
 
6526
                    value: v,
 
6527
                    name: k
 
6528
                });
 
6529
                form.appendChild(hd);
 
6530
                hiddens.push(hd);
 
6531
            });
 
6532
 
 
6533
            function cb(){
 
6534
                var me = this,
 
6535
                    // bogus response object
 
6536
                    r = {responseText : '',
 
6537
                         responseXML : null,
 
6538
                         argument : o.argument},
 
6539
                    doc,
 
6540
                    firstChild;
 
6541
 
 
6542
                try{
 
6543
                    doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;
 
6544
                    if(doc){
 
6545
                        if(doc.body){
 
6546
                            if(/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)){ // json response wrapped in textarea
 
6547
                                r.responseText = firstChild.value;
 
6548
                            }else{
 
6549
                                r.responseText = doc.body.innerHTML;
 
6550
                            }
 
6551
                        }
 
6552
                        //in IE the document may still have a body even if returns XML.
 
6553
                        r.responseXML = doc.XMLDocument || doc;
 
6554
                    }
 
6555
                }
 
6556
                catch(e) {}
 
6557
 
 
6558
                Ext.EventManager.removeListener(frame, LOAD, cb, me);
 
6559
 
 
6560
                me.fireEvent(REQUESTCOMPLETE, me, r, o);
 
6561
 
 
6562
                function runCallback(fn, scope, args){
 
6563
                    if(Ext.isFunction(fn)){
 
6564
                        fn.apply(scope, args);
 
6565
                    }
 
6566
                }
 
6567
 
 
6568
                runCallback(o.success, o.scope, [r, o]);
 
6569
                runCallback(o.callback, o.scope, [o, true, r]);
 
6570
 
 
6571
                if(!me.debugUploads){
 
6572
                    setTimeout(function(){Ext.removeNode(frame);}, 100);
 
6573
                }
 
6574
            }
 
6575
 
 
6576
            Ext.EventManager.on(frame, LOAD, cb, this);
 
6577
            form.submit();
 
6578
 
 
6579
            Ext.fly(form).set(buf);
 
6580
            Ext.each(hiddens, function(h) {
 
6581
                Ext.removeNode(h);
 
6582
            });
 
6583
        }
 
6584
    });
 
6585
})();
 
6586
 
 
6587
/**
 
6588
 * @class Ext.Ajax
 
6589
 * @extends Ext.data.Connection
 
6590
 * <p>The global Ajax request class that provides a simple way to make Ajax requests
 
6591
 * with maximum flexibility.</p>
 
6592
 * <p>Since Ext.Ajax is a singleton, you can set common properties/events for it once
 
6593
 * and override them at the request function level only if necessary.</p>
 
6594
 * <p>Common <b>Properties</b> you may want to set are:<div class="mdetail-params"><ul>
 
6595
 * <li><b><tt>{@link #method}</tt></b><p class="sub-desc"></p></li>
 
6596
 * <li><b><tt>{@link #extraParams}</tt></b><p class="sub-desc"></p></li>
 
6597
 * <li><b><tt>{@link #url}</tt></b><p class="sub-desc"></p></li>
 
6598
 * </ul></div>
 
6599
 * <pre><code>
 
6600
// Default headers to pass in every request
 
6601
Ext.Ajax.defaultHeaders = {
 
6602
    'Powered-By': 'Ext'
 
6603
};
 
6604
 * </code></pre>
 
6605
 * </p>
 
6606
 * <p>Common <b>Events</b> you may want to set are:<div class="mdetail-params"><ul>
 
6607
 * <li><b><tt>{@link Ext.data.Connection#beforerequest beforerequest}</tt></b><p class="sub-desc"></p></li>
 
6608
 * <li><b><tt>{@link Ext.data.Connection#requestcomplete requestcomplete}</tt></b><p class="sub-desc"></p></li>
 
6609
 * <li><b><tt>{@link Ext.data.Connection#requestexception requestexception}</tt></b><p class="sub-desc"></p></li>
 
6610
 * </ul></div>
 
6611
 * <pre><code>
 
6612
// Example: show a spinner during all Ajax requests
 
6613
Ext.Ajax.on('beforerequest', this.showSpinner, this);
 
6614
Ext.Ajax.on('requestcomplete', this.hideSpinner, this);
 
6615
Ext.Ajax.on('requestexception', this.hideSpinner, this);
 
6616
 * </code></pre>
 
6617
 * </p>
 
6618
 * <p>An example request:</p>
 
6619
 * <pre><code>
 
6620
// Basic request
 
6621
Ext.Ajax.{@link Ext.data.Connection#request request}({
 
6622
   url: 'foo.php',
 
6623
   success: someFn,
 
6624
   failure: otherFn,
 
6625
   headers: {
 
6626
       'my-header': 'foo'
 
6627
   },
 
6628
   params: { foo: 'bar' }
 
6629
});
 
6630
 
 
6631
// Simple ajax form submission
 
6632
Ext.Ajax.{@link Ext.data.Connection#request request}({
 
6633
    form: 'some-form',
 
6634
    params: 'foo=bar'
 
6635
});
 
6636
 * </code></pre>
 
6637
 * </p>
 
6638
 * @singleton
 
6639
 */
 
6640
Ext.Ajax = new Ext.data.Connection({
 
6641
    /**
 
6642
     * @cfg {String} url @hide
 
6643
     */
 
6644
    /**
 
6645
     * @cfg {Object} extraParams @hide
 
6646
     */
 
6647
    /**
 
6648
     * @cfg {Object} defaultHeaders @hide
 
6649
     */
 
6650
    /**
 
6651
     * @cfg {String} method (Optional) @hide
 
6652
     */
 
6653
    /**
 
6654
     * @cfg {Number} timeout (Optional) @hide
 
6655
     */
 
6656
    /**
 
6657
     * @cfg {Boolean} autoAbort (Optional) @hide
 
6658
     */
 
6659
 
 
6660
    /**
 
6661
     * @cfg {Boolean} disableCaching (Optional) @hide
 
6662
     */
 
6663
 
 
6664
    /**
 
6665
     * @property  disableCaching
 
6666
     * True to add a unique cache-buster param to GET requests. (defaults to true)
 
6667
     * @type Boolean
 
6668
     */
 
6669
    /**
 
6670
     * @property  url
 
6671
     * The default URL to be used for requests to the server. (defaults to undefined)
 
6672
     * If the server receives all requests through one URL, setting this once is easier than
 
6673
     * entering it on every request.
 
6674
     * @type String
 
6675
     */
 
6676
    /**
 
6677
     * @property  extraParams
 
6678
     * An object containing properties which are used as extra parameters to each request made
 
6679
     * by this object (defaults to undefined). Session information and other data that you need
 
6680
     * to pass with each request are commonly put here.
 
6681
     * @type Object
 
6682
     */
 
6683
    /**
 
6684
     * @property  defaultHeaders
 
6685
     * An object containing request headers which are added to each request made by this object
 
6686
     * (defaults to undefined).
 
6687
     * @type Object
 
6688
     */
 
6689
    /**
 
6690
     * @property  method
 
6691
     * The default HTTP method to be used for requests. Note that this is case-sensitive and
 
6692
     * should be all caps (defaults to undefined; if not set but params are present will use
 
6693
     * <tt>"POST"</tt>, otherwise will use <tt>"GET"</tt>.)
 
6694
     * @type String
 
6695
     */
 
6696
    /**
 
6697
     * @property  timeout
 
6698
     * The timeout in milliseconds to be used for requests. (defaults to 30000)
 
6699
     * @type Number
 
6700
     */
 
6701
 
 
6702
    /**
 
6703
     * @property  autoAbort
 
6704
     * Whether a new request should abort any pending requests. (defaults to false)
 
6705
     * @type Boolean
 
6706
     */
 
6707
    autoAbort : false,
 
6708
 
 
6709
    /**
 
6710
     * Serialize the passed form into a url encoded string
 
6711
     * @param {String/HTMLElement} form
 
6712
     * @return {String}
 
6713
     */
 
6714
    serializeForm : function(form){
 
6715
        return Ext.lib.Ajax.serializeForm(form);
 
6716
    }
 
6717
});
 
6718
/**
 
6719
 * @class Ext.util.JSON
 
6720
 * Modified version of Douglas Crockford"s json.js that doesn"t
 
6721
 * mess with the Object prototype
 
6722
 * http://www.json.org/js.html
 
6723
 * @singleton
 
6724
 */
 
6725
Ext.util.JSON = new (function(){
 
6726
    var useHasOwn = !!{}.hasOwnProperty,
 
6727
        isNative = function() {
 
6728
            var useNative = null;
 
6729
 
 
6730
            return function() {
 
6731
                if (useNative === null) {
 
6732
                    useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
 
6733
                }
 
6734
        
 
6735
                return useNative;
 
6736
            };
 
6737
        }(),
 
6738
        pad = function(n) {
 
6739
            return n < 10 ? "0" + n : n;
 
6740
        },
 
6741
        doDecode = function(json){
 
6742
            return eval("(" + json + ")");    
 
6743
        },
 
6744
        doEncode = function(o){
 
6745
            if(!Ext.isDefined(o) || o === null){
 
6746
                return "null";
 
6747
            }else if(Ext.isArray(o)){
 
6748
                return encodeArray(o);
 
6749
            }else if(Ext.isDate(o)){
 
6750
                return Ext.util.JSON.encodeDate(o);
 
6751
            }else if(Ext.isString(o)){
 
6752
                return encodeString(o);
 
6753
            }else if(typeof o == "number"){
 
6754
                //don't use isNumber here, since finite checks happen inside isNumber
 
6755
                return isFinite(o) ? String(o) : "null";
 
6756
            }else if(Ext.isBoolean(o)){
 
6757
                return String(o);
 
6758
            }else {
 
6759
                var a = ["{"], b, i, v;
 
6760
                for (i in o) {
 
6761
                    // don't encode DOM objects
 
6762
                    if(!o.getElementsByTagName){
 
6763
                        if(!useHasOwn || o.hasOwnProperty(i)) {
 
6764
                            v = o[i];
 
6765
                            switch (typeof v) {
 
6766
                            case "undefined":
 
6767
                            case "function":
 
6768
                            case "unknown":
 
6769
                                break;
 
6770
                            default:
 
6771
                                if(b){
 
6772
                                    a.push(',');
 
6773
                                }
 
6774
                                a.push(doEncode(i), ":",
 
6775
                                        v === null ? "null" : doEncode(v));
 
6776
                                b = true;
 
6777
                            }
 
6778
                        }
 
6779
                    }
 
6780
                }
 
6781
                a.push("}");
 
6782
                return a.join("");
 
6783
            }    
 
6784
        },
 
6785
        m = {
 
6786
            "\b": '\\b',
 
6787
            "\t": '\\t',
 
6788
            "\n": '\\n',
 
6789
            "\f": '\\f',
 
6790
            "\r": '\\r',
 
6791
            '"' : '\\"',
 
6792
            "\\": '\\\\'
 
6793
        },
 
6794
        encodeString = function(s){
 
6795
            if (/["\\\x00-\x1f]/.test(s)) {
 
6796
                return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
 
6797
                    var c = m[b];
 
6798
                    if(c){
 
6799
                        return c;
 
6800
                    }
 
6801
                    c = b.charCodeAt();
 
6802
                    return "\\u00" +
 
6803
                        Math.floor(c / 16).toString(16) +
 
6804
                        (c % 16).toString(16);
 
6805
                }) + '"';
 
6806
            }
 
6807
            return '"' + s + '"';
 
6808
        },
 
6809
        encodeArray = function(o){
 
6810
            var a = ["["], b, i, l = o.length, v;
 
6811
                for (i = 0; i < l; i += 1) {
 
6812
                    v = o[i];
 
6813
                    switch (typeof v) {
 
6814
                        case "undefined":
 
6815
                        case "function":
 
6816
                        case "unknown":
 
6817
                            break;
 
6818
                        default:
 
6819
                            if (b) {
 
6820
                                a.push(',');
 
6821
                            }
 
6822
                            a.push(v === null ? "null" : Ext.util.JSON.encode(v));
 
6823
                            b = true;
 
6824
                    }
 
6825
                }
 
6826
                a.push("]");
 
6827
                return a.join("");
 
6828
        };
 
6829
 
 
6830
    /**
 
6831
     * <p>Encodes a Date. This returns the actual string which is inserted into the JSON string as the literal expression.
 
6832
     * <b>The returned value includes enclosing double quotation marks.</b></p>
 
6833
     * <p>The default return format is "yyyy-mm-ddThh:mm:ss".</p>
 
6834
     * <p>To override this:</p><pre><code>
 
6835
Ext.util.JSON.encodeDate = function(d) {
 
6836
    return d.format('"Y-m-d"');
 
6837
};
 
6838
</code></pre>
 
6839
     * @param {Date} d The Date to encode
 
6840
     * @return {String} The string literal to use in a JSON string.
 
6841
     */
 
6842
    this.encodeDate = function(o){
 
6843
        return '"' + o.getFullYear() + "-" +
 
6844
                pad(o.getMonth() + 1) + "-" +
 
6845
                pad(o.getDate()) + "T" +
 
6846
                pad(o.getHours()) + ":" +
 
6847
                pad(o.getMinutes()) + ":" +
 
6848
                pad(o.getSeconds()) + '"';
 
6849
    };
 
6850
 
 
6851
    /**
 
6852
     * Encodes an Object, Array or other value
 
6853
     * @param {Mixed} o The variable to encode
 
6854
     * @return {String} The JSON string
 
6855
     */
 
6856
    this.encode = function() {
 
6857
        var ec;
 
6858
        return function(o) {
 
6859
            if (!ec) {
 
6860
                // setup encoding function on first access
 
6861
                ec = isNative() ? JSON.stringify : doEncode;
 
6862
            }
 
6863
            return ec(o);
 
6864
        };
 
6865
    }();
 
6866
 
 
6867
 
 
6868
    /**
 
6869
     * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError unless the safe option is set.
 
6870
     * @param {String} json The JSON string
 
6871
     * @return {Object} The resulting object
 
6872
     */
 
6873
    this.decode = function() {
 
6874
        var dc;
 
6875
        return function(json) {
 
6876
            if (!dc) {
 
6877
                // setup decoding function on first access
 
6878
                dc = isNative() ? JSON.parse : doDecode;
 
6879
            }
 
6880
            return dc(json);
 
6881
        };
 
6882
    }();
 
6883
 
 
6884
})();
 
6885
/**
 
6886
 * Shorthand for {@link Ext.util.JSON#encode}
 
6887
 * @param {Mixed} o The variable to encode
 
6888
 * @return {String} The JSON string
 
6889
 * @member Ext
 
6890
 * @method encode
 
6891
 */
 
6892
Ext.encode = Ext.util.JSON.encode;
 
6893
/**
 
6894
 * Shorthand for {@link Ext.util.JSON#decode}
 
6895
 * @param {String} json The JSON string
 
6896
 * @param {Boolean} safe (optional) Whether to return null or throw an exception if the JSON is invalid.
 
6897
 * @return {Object} The resulting object
 
6898
 * @member Ext
 
6899
 * @method decode
 
6900
 */
 
6901
Ext.decode = Ext.util.JSON.decode;
 
6902
/**
 
6903
 * @class Ext.EventManager
 
6904
 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
 
6905
 * several useful events directly.
 
6906
 * See {@link Ext.EventObject} for more details on normalized event objects.
 
6907
 * @singleton
 
6908
 */
 
6909
Ext.EventManager = function(){
 
6910
    var docReadyEvent,
 
6911
        docReadyProcId,
 
6912
        docReadyState = false,
 
6913
        DETECT_NATIVE = Ext.isGecko || Ext.isWebKit || Ext.isSafari,
 
6914
        E = Ext.lib.Event,
 
6915
        D = Ext.lib.Dom,
 
6916
        DOC = document,
 
6917
        WINDOW = window,
 
6918
        DOMCONTENTLOADED = "DOMContentLoaded",
 
6919
        COMPLETE = 'complete',
 
6920
        propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
 
6921
        /*
 
6922
         * This cache is used to hold special js objects, the document and window, that don't have an id. We need to keep
 
6923
         * a reference to them so we can look them up at a later point.
 
6924
         */
 
6925
        specialElCache = [];
 
6926
 
 
6927
     function getId(el){
 
6928
        var id = false,
 
6929
            i = 0,
 
6930
            len = specialElCache.length,
 
6931
            skip = false,
 
6932
            o;
 
6933
            
 
6934
        if (el) {
 
6935
            if (el.getElementById || el.navigator) {
 
6936
                // look up the id
 
6937
                for(; i < len; ++i){
 
6938
                    o = specialElCache[i];
 
6939
                    if(o.el === el){
 
6940
                        id = o.id;
 
6941
                        break;
 
6942
                    }
 
6943
                }
 
6944
                if(!id){
 
6945
                    // for browsers that support it, ensure that give the el the same id
 
6946
                    id = Ext.id(el);
 
6947
                    specialElCache.push({
 
6948
                        id: id,
 
6949
                        el: el
 
6950
                    });
 
6951
                    skip = true;
 
6952
                }
 
6953
            }else{
 
6954
                id = Ext.id(el);
 
6955
            }
 
6956
            if(!Ext.elCache[id]){
 
6957
                Ext.Element.addToCache(new Ext.Element(el), id);
 
6958
                if(skip){
 
6959
                    Ext.elCache[id].skipGC = true;
 
6960
                }
 
6961
            }
 
6962
        }
 
6963
        return id;
 
6964
     }
 
6965
 
 
6966
    /// There is some jquery work around stuff here that isn't needed in Ext Core.
 
6967
    function addListener(el, ename, fn, task, wrap, scope){
 
6968
        el = Ext.getDom(el);
 
6969
        var id = getId(el),
 
6970
            es = Ext.elCache[id].events,
 
6971
            wfn;
 
6972
 
 
6973
        wfn = E.on(el, ename, wrap);
 
6974
        es[ename] = es[ename] || [];
 
6975
 
 
6976
        /* 0 = Original Function,
 
6977
           1 = Event Manager Wrapped Function,
 
6978
           2 = Scope,
 
6979
           3 = Adapter Wrapped Function,
 
6980
           4 = Buffered Task
 
6981
        */
 
6982
        es[ename].push([fn, wrap, scope, wfn, task]);
 
6983
 
 
6984
        // this is a workaround for jQuery and should somehow be removed from Ext Core in the future
 
6985
        // without breaking ExtJS.
 
6986
 
 
6987
        // workaround for jQuery
 
6988
        if(el.addEventListener && ename == "mousewheel"){
 
6989
            var args = ["DOMMouseScroll", wrap, false];
 
6990
            el.addEventListener.apply(el, args);
 
6991
            Ext.EventManager.addListener(WINDOW, 'unload', function(){
 
6992
                el.removeEventListener.apply(el, args);
 
6993
            });
 
6994
        }
 
6995
 
 
6996
        // fix stopped mousedowns on the document
 
6997
        if(el == DOC && ename == "mousedown"){
 
6998
            Ext.EventManager.stoppedMouseDownEvent.addListener(wrap);
 
6999
        }
 
7000
    }
 
7001
 
 
7002
    function doScrollChk(){
 
7003
        /* Notes:
 
7004
             'doScroll' will NOT work in a IFRAME/FRAMESET.
 
7005
             The method succeeds but, a DOM query done immediately after -- FAILS.
 
7006
          */
 
7007
        if(window != top){
 
7008
            return false;
 
7009
        }
 
7010
 
 
7011
        try{
 
7012
            DOC.documentElement.doScroll('left');
 
7013
        }catch(e){
 
7014
             return false;
 
7015
        }
 
7016
 
 
7017
        fireDocReady();
 
7018
        return true;
 
7019
    }
 
7020
    /**
 
7021
     * @return {Boolean} True if the document is in a 'complete' state (or was determined to
 
7022
     * be true by other means). If false, the state is evaluated again until canceled.
 
7023
     */
 
7024
    function checkReadyState(e){
 
7025
 
 
7026
        if(Ext.isIE && doScrollChk()){
 
7027
            return true;
 
7028
        }
 
7029
        if(DOC.readyState == COMPLETE){
 
7030
            fireDocReady();
 
7031
            return true;
 
7032
        }
 
7033
        docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
 
7034
        return false;
 
7035
    }
 
7036
 
 
7037
    var styles;
 
7038
    function checkStyleSheets(e){
 
7039
        styles || (styles = Ext.query('style, link[rel=stylesheet]'));
 
7040
        if(styles.length == DOC.styleSheets.length){
 
7041
            fireDocReady();
 
7042
            return true;
 
7043
        }
 
7044
        docReadyState || (docReadyProcId = setTimeout(arguments.callee, 2));
 
7045
        return false;
 
7046
    }
 
7047
 
 
7048
    function OperaDOMContentLoaded(e){
 
7049
        DOC.removeEventListener(DOMCONTENTLOADED, arguments.callee, false);
 
7050
        checkStyleSheets();
 
7051
    }
 
7052
 
 
7053
    function fireDocReady(e){
 
7054
        if(!docReadyState){
 
7055
            docReadyState = true; //only attempt listener removal once
 
7056
 
 
7057
            if(docReadyProcId){
 
7058
                clearTimeout(docReadyProcId);
 
7059
            }
 
7060
            if(DETECT_NATIVE) {
 
7061
                DOC.removeEventListener(DOMCONTENTLOADED, fireDocReady, false);
 
7062
            }
 
7063
            if(Ext.isIE && checkReadyState.bindIE){  //was this was actually set ??
 
7064
                DOC.detachEvent('onreadystatechange', checkReadyState);
 
7065
            }
 
7066
            E.un(WINDOW, "load", arguments.callee);
 
7067
        }
 
7068
        if(docReadyEvent && !Ext.isReady){
 
7069
            Ext.isReady = true;
 
7070
            docReadyEvent.fire();
 
7071
            docReadyEvent.listeners = [];
 
7072
        }
 
7073
 
 
7074
    }
 
7075
 
 
7076
    function initDocReady(){
 
7077
        docReadyEvent || (docReadyEvent = new Ext.util.Event());
 
7078
        if (DETECT_NATIVE) {
 
7079
            DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
 
7080
        }
 
7081
        /*
 
7082
         * Handle additional (exceptional) detection strategies here
 
7083
         */
 
7084
        if (Ext.isIE){
 
7085
            //Use readystatechange as a backup AND primary detection mechanism for a FRAME/IFRAME
 
7086
            //See if page is already loaded
 
7087
            if(!checkReadyState()){
 
7088
                checkReadyState.bindIE = true;
 
7089
                DOC.attachEvent('onreadystatechange', checkReadyState);
 
7090
            }
 
7091
 
 
7092
        }else if(Ext.isOpera ){
 
7093
            /* Notes:
 
7094
               Opera needs special treatment needed here because CSS rules are NOT QUITE
 
7095
               available after DOMContentLoaded is raised.
 
7096
            */
 
7097
 
 
7098
            //See if page is already loaded and all styleSheets are in place
 
7099
            (DOC.readyState == COMPLETE && checkStyleSheets()) ||
 
7100
                DOC.addEventListener(DOMCONTENTLOADED, OperaDOMContentLoaded, false);
 
7101
 
 
7102
        }else if (Ext.isWebKit){
 
7103
            //Fallback for older Webkits without DOMCONTENTLOADED support
 
7104
            checkReadyState();
 
7105
        }
 
7106
        // no matter what, make sure it fires on load
 
7107
        E.on(WINDOW, "load", fireDocReady);
 
7108
    }
 
7109
 
 
7110
    function createTargeted(h, o){
 
7111
        return function(){
 
7112
            var args = Ext.toArray(arguments);
 
7113
            if(o.target == Ext.EventObject.setEvent(args[0]).target){
 
7114
                h.apply(this, args);
 
7115
            }
 
7116
        };
 
7117
    }
 
7118
 
 
7119
    function createBuffered(h, o, task){
 
7120
        return function(e){
 
7121
            // create new event object impl so new events don't wipe out properties
 
7122
            task.delay(o.buffer, h, null, [new Ext.EventObjectImpl(e)]);
 
7123
        };
 
7124
    }
 
7125
 
 
7126
    function createSingle(h, el, ename, fn, scope){
 
7127
        return function(e){
 
7128
            Ext.EventManager.removeListener(el, ename, fn, scope);
 
7129
            h(e);
 
7130
        };
 
7131
    }
 
7132
 
 
7133
    function createDelayed(h, o, fn){
 
7134
        return function(e){
 
7135
            var task = new Ext.util.DelayedTask(h);
 
7136
            if(!fn.tasks) {
 
7137
                fn.tasks = [];
 
7138
            }
 
7139
            fn.tasks.push(task);
 
7140
            task.delay(o.delay || 10, h, null, [new Ext.EventObjectImpl(e)]);
 
7141
        };
 
7142
    }
 
7143
 
 
7144
    function listen(element, ename, opt, fn, scope){
 
7145
        var o = (!opt || typeof opt == "boolean") ? {} : opt,
 
7146
            el = Ext.getDom(element), task;
 
7147
 
 
7148
        fn = fn || o.fn;
 
7149
        scope = scope || o.scope;
 
7150
 
 
7151
        if(!el){
 
7152
            throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
 
7153
        }
 
7154
        function h(e){
 
7155
            // prevent errors while unload occurring
 
7156
            if(!Ext){// !window[xname]){  ==> can't we do this?
 
7157
                return;
 
7158
            }
 
7159
            e = Ext.EventObject.setEvent(e);
 
7160
            var t;
 
7161
            if (o.delegate) {
 
7162
                if(!(t = e.getTarget(o.delegate, el))){
 
7163
                    return;
 
7164
                }
 
7165
            } else {
 
7166
                t = e.target;
 
7167
            }
 
7168
            if (o.stopEvent) {
 
7169
                e.stopEvent();
 
7170
            }
 
7171
            if (o.preventDefault) {
 
7172
               e.preventDefault();
 
7173
            }
 
7174
            if (o.stopPropagation) {
 
7175
                e.stopPropagation();
 
7176
            }
 
7177
            if (o.normalized === false) {
 
7178
                e = e.browserEvent;
 
7179
            }
 
7180
 
 
7181
            fn.call(scope || el, e, t, o);
 
7182
        }
 
7183
        if(o.target){
 
7184
            h = createTargeted(h, o);
 
7185
        }
 
7186
        if(o.delay){
 
7187
            h = createDelayed(h, o, fn);
 
7188
        }
 
7189
        if(o.single){
 
7190
            h = createSingle(h, el, ename, fn, scope);
 
7191
        }
 
7192
        if(o.buffer){
 
7193
            task = new Ext.util.DelayedTask(h);
 
7194
            h = createBuffered(h, o, task);
 
7195
        }
 
7196
 
 
7197
        addListener(el, ename, fn, task, h, scope);
 
7198
        return h;
 
7199
    }
 
7200
 
 
7201
    var pub = {
 
7202
        /**
 
7203
         * Appends an event handler to an element.  The shorthand version {@link #on} is equivalent.  Typically you will
 
7204
         * use {@link Ext.Element#addListener} directly on an Element in favor of calling this version.
 
7205
         * @param {String/HTMLElement} el The html element or id to assign the event handler to.
 
7206
         * @param {String} eventName The name of the event to listen for.
 
7207
         * @param {Function} handler The handler function the event invokes. This function is passed
 
7208
         * the following parameters:<ul>
 
7209
         * <li>evt : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>
 
7210
         * <li>t : Element<div class="sub-desc">The {@link Ext.Element Element} which was the target of the event.
 
7211
         * Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>
 
7212
         * <li>o : Object<div class="sub-desc">The options object from the addListener call.</div></li>
 
7213
         * </ul>
 
7214
         * @param {Object} scope (optional) The scope (<b><code>this</code></b> reference) in which the handler function is executed. <b>Defaults to the Element</b>.
 
7215
         * @param {Object} options (optional) An object containing handler configuration properties.
 
7216
         * This may contain any of the following properties:<ul>
 
7217
         * <li>scope : Object<div class="sub-desc">The scope (<b><code>this</code></b> reference) in which the handler function is executed. <b>Defaults to the Element</b>.</div></li>
 
7218
         * <li>delegate : String<div class="sub-desc">A simple selector to filter the target or look for a descendant of the target</div></li>
 
7219
         * <li>stopEvent : Boolean<div class="sub-desc">True to stop the event. That is stop propagation, and prevent the default action.</div></li>
 
7220
         * <li>preventDefault : Boolean<div class="sub-desc">True to prevent the default action</div></li>
 
7221
         * <li>stopPropagation : Boolean<div class="sub-desc">True to prevent event propagation</div></li>
 
7222
         * <li>normalized : Boolean<div class="sub-desc">False to pass a browser event to the handler function instead of an Ext.EventObject</div></li>
 
7223
         * <li>delay : Number<div class="sub-desc">The number of milliseconds to delay the invocation of the handler after te event fires.</div></li>
 
7224
         * <li>single : Boolean<div class="sub-desc">True to add a handler to handle just the next firing of the event, and then remove itself.</div></li>
 
7225
         * <li>buffer : Number<div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
 
7226
         * by the specified number of milliseconds. If the event fires again within that time, the original
 
7227
         * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>
 
7228
         * <li>target : Element<div class="sub-desc">Only call the handler if the event was fired on the target Element, <i>not</i> if the event was bubbled up from a child node.</div></li>
 
7229
         * </ul><br>
 
7230
         * <p>See {@link Ext.Element#addListener} for examples of how to use these options.</p>
 
7231
         */
 
7232
        addListener : function(element, eventName, fn, scope, options){
 
7233
            if(typeof eventName == 'object'){
 
7234
                var o = eventName, e, val;
 
7235
                for(e in o){
 
7236
                    val = o[e];
 
7237
                    if(!propRe.test(e)){
 
7238
                        if(Ext.isFunction(val)){
 
7239
                            // shared options
 
7240
                            listen(element, e, o, val, o.scope);
 
7241
                        }else{
 
7242
                            // individual options
 
7243
                            listen(element, e, val);
 
7244
                        }
 
7245
                    }
 
7246
                }
 
7247
            } else {
 
7248
                listen(element, eventName, options, fn, scope);
 
7249
            }
 
7250
        },
 
7251
 
 
7252
        /**
 
7253
         * Removes an event handler from an element.  The shorthand version {@link #un} is equivalent.  Typically
 
7254
         * you will use {@link Ext.Element#removeListener} directly on an Element in favor of calling this version.
 
7255
         * @param {String/HTMLElement} el The id or html element from which to remove the listener.
 
7256
         * @param {String} eventName The name of the event.
 
7257
         * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
 
7258
         * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
 
7259
         * then this must refer to the same object.
 
7260
         */
 
7261
        removeListener : function(el, eventName, fn, scope){
 
7262
            el = Ext.getDom(el);
 
7263
            var id = getId(el),
 
7264
                f = el && (Ext.elCache[id].events)[eventName] || [],
 
7265
                wrap, i, l, k, len, fnc;
 
7266
 
 
7267
            for (i = 0, len = f.length; i < len; i++) {
 
7268
 
 
7269
                /* 0 = Original Function,
 
7270
                   1 = Event Manager Wrapped Function,
 
7271
                   2 = Scope,
 
7272
                   3 = Adapter Wrapped Function,
 
7273
                   4 = Buffered Task
 
7274
                */
 
7275
                if (Ext.isArray(fnc = f[i]) && fnc[0] == fn && (!scope || fnc[2] == scope)) {
 
7276
                    if(fnc[4]) {
 
7277
                        fnc[4].cancel();
 
7278
                    }
 
7279
                    k = fn.tasks && fn.tasks.length;
 
7280
                    if(k) {
 
7281
                        while(k--) {
 
7282
                            fn.tasks[k].cancel();
 
7283
                        }
 
7284
                        delete fn.tasks;
 
7285
                    }
 
7286
                    wrap = fnc[1];
 
7287
                    E.un(el, eventName, E.extAdapter ? fnc[3] : wrap);
 
7288
 
 
7289
                    // jQuery workaround that should be removed from Ext Core
 
7290
                    if(wrap && el.addEventListener && eventName == "mousewheel"){
 
7291
                        el.removeEventListener("DOMMouseScroll", wrap, false);
 
7292
                    }
 
7293
 
 
7294
                    // fix stopped mousedowns on the document
 
7295
                    if(wrap && el == DOC && eventName == "mousedown"){
 
7296
                        Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
 
7297
                    }
 
7298
 
 
7299
                    f.splice(i, 1);
 
7300
                    if (f.length === 0) {
 
7301
                        delete Ext.elCache[id].events[eventName];
 
7302
                    }
 
7303
                    for (k in Ext.elCache[id].events) {
 
7304
                        return false;
 
7305
                    }
 
7306
                    Ext.elCache[id].events = {};
 
7307
                    return false;
 
7308
                }
 
7309
            }
 
7310
        },
 
7311
 
 
7312
        /**
 
7313
         * Removes all event handers from an element.  Typically you will use {@link Ext.Element#removeAllListeners}
 
7314
         * directly on an Element in favor of calling this version.
 
7315
         * @param {String/HTMLElement} el The id or html element from which to remove all event handlers.
 
7316
         */
 
7317
        removeAll : function(el){
 
7318
            el = Ext.getDom(el);
 
7319
            var id = getId(el),
 
7320
                ec = Ext.elCache[id] || {},
 
7321
                es = ec.events || {},
 
7322
                f, i, len, ename, fn, k, wrap;
 
7323
 
 
7324
            for(ename in es){
 
7325
                if(es.hasOwnProperty(ename)){
 
7326
                    f = es[ename];
 
7327
                    /* 0 = Original Function,
 
7328
                       1 = Event Manager Wrapped Function,
 
7329
                       2 = Scope,
 
7330
                       3 = Adapter Wrapped Function,
 
7331
                       4 = Buffered Task
 
7332
                    */
 
7333
                    for (i = 0, len = f.length; i < len; i++) {
 
7334
                        fn = f[i];
 
7335
                        if(fn[4]) {
 
7336
                            fn[4].cancel();
 
7337
                        }
 
7338
                        if(fn[0].tasks && (k = fn[0].tasks.length)) {
 
7339
                            while(k--) {
 
7340
                                fn[0].tasks[k].cancel();
 
7341
                            }
 
7342
                            delete fn.tasks;
 
7343
                        }
 
7344
                        wrap =  fn[1];
 
7345
                        E.un(el, ename, E.extAdapter ? fn[3] : wrap);
 
7346
 
 
7347
                        // jQuery workaround that should be removed from Ext Core
 
7348
                        if(el.addEventListener && wrap && ename == "mousewheel"){
 
7349
                            el.removeEventListener("DOMMouseScroll", wrap, false);
 
7350
                        }
 
7351
 
 
7352
                        // fix stopped mousedowns on the document
 
7353
                        if(wrap && el == DOC &&  ename == "mousedown"){
 
7354
                            Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
 
7355
                        }
 
7356
                    }
 
7357
                }
 
7358
            }
 
7359
            if (Ext.elCache[id]) {
 
7360
                Ext.elCache[id].events = {};
 
7361
            }
 
7362
        },
 
7363
 
 
7364
        getListeners : function(el, eventName) {
 
7365
            el = Ext.getDom(el);
 
7366
            var id = getId(el),
 
7367
                ec = Ext.elCache[id] || {},
 
7368
                es = ec.events || {},
 
7369
                results = [];
 
7370
            if (es && es[eventName]) {
 
7371
                return es[eventName];
 
7372
            } else {
 
7373
                return null;
 
7374
            }
 
7375
        },
 
7376
 
 
7377
        purgeElement : function(el, recurse, eventName) {
 
7378
            el = Ext.getDom(el);
 
7379
            var id = getId(el),
 
7380
                ec = Ext.elCache[id] || {},
 
7381
                es = ec.events || {},
 
7382
                i, f, len;
 
7383
            if (eventName) {
 
7384
                if (es && es.hasOwnProperty(eventName)) {
 
7385
                    f = es[eventName];
 
7386
                    for (i = 0, len = f.length; i < len; i++) {
 
7387
                        Ext.EventManager.removeListener(el, eventName, f[i][0]);
 
7388
                    }
 
7389
                }
 
7390
            } else {
 
7391
                Ext.EventManager.removeAll(el);
 
7392
            }
 
7393
            if (recurse && el && el.childNodes) {
 
7394
                for (i = 0, len = el.childNodes.length; i < len; i++) {
 
7395
                    Ext.EventManager.purgeElement(el.childNodes[i], recurse, eventName);
 
7396
                }
 
7397
            }
 
7398
        },
 
7399
 
 
7400
        _unload : function() {
 
7401
            var el;
 
7402
            for (el in Ext.elCache) {
 
7403
                Ext.EventManager.removeAll(el);
 
7404
            }
 
7405
            delete Ext.elCache;
 
7406
            delete Ext.Element._flyweights;
 
7407
 
 
7408
            // Abort any outstanding Ajax requests
 
7409
            var c,
 
7410
                conn,
 
7411
                tid,
 
7412
                ajax = Ext.lib.Ajax;
 
7413
            (typeof ajax.conn == 'object') ? conn = ajax.conn : conn = {};
 
7414
            for (tid in conn) {
 
7415
                c = conn[tid];
 
7416
                if (c) {
 
7417
                    ajax.abort({conn: c, tId: tid});
 
7418
                }
 
7419
            }
 
7420
        },
 
7421
        /**
 
7422
         * Adds a listener to be notified when the document is ready (before onload and before images are loaded). Can be
 
7423
         * accessed shorthanded as Ext.onReady().
 
7424
         * @param {Function} fn The method the event invokes.
 
7425
         * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
 
7426
         * @param {boolean} options (optional) Options object as passed to {@link Ext.Element#addListener}. It is recommended that the options
 
7427
         * <code>{single: true}</code> be used so that the handler is removed on first invocation.
 
7428
         */
 
7429
        onDocumentReady : function(fn, scope, options){
 
7430
            if (Ext.isReady) { // if it already fired or document.body is present
 
7431
                docReadyEvent || (docReadyEvent = new Ext.util.Event());
 
7432
                docReadyEvent.addListener(fn, scope, options);
 
7433
                docReadyEvent.fire();
 
7434
                docReadyEvent.listeners = [];
 
7435
            } else {
 
7436
                if (!docReadyEvent) {
 
7437
                    initDocReady();
 
7438
                }
 
7439
                options = options || {};
 
7440
                options.delay = options.delay || 1;
 
7441
                docReadyEvent.addListener(fn, scope, options);
 
7442
            }
 
7443
        },
 
7444
 
 
7445
        /**
 
7446
         * Forces a document ready state transition for the framework.  Used when Ext is loaded
 
7447
         * into a DOM structure AFTER initial page load (Google API or other dynamic load scenario.
 
7448
         * Any pending 'onDocumentReady' handlers will be fired (if not already handled).
 
7449
         */
 
7450
        fireDocReady  : fireDocReady
 
7451
    };
 
7452
     /**
 
7453
     * Appends an event handler to an element.  Shorthand for {@link #addListener}.
 
7454
     * @param {String/HTMLElement} el The html element or id to assign the event handler to
 
7455
     * @param {String} eventName The name of the event to listen for.
 
7456
     * @param {Function} handler The handler function the event invokes.
 
7457
     * @param {Object} scope (optional) (<code>this</code> reference) in which the handler function executes. <b>Defaults to the Element</b>.
 
7458
     * @param {Object} options (optional) An object containing standard {@link #addListener} options
 
7459
     * @member Ext.EventManager
 
7460
     * @method on
 
7461
     */
 
7462
    pub.on = pub.addListener;
 
7463
    /**
 
7464
     * Removes an event handler from an element.  Shorthand for {@link #removeListener}.
 
7465
     * @param {String/HTMLElement} el The id or html element from which to remove the listener.
 
7466
     * @param {String} eventName The name of the event.
 
7467
     * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #on} call.</b>
 
7468
     * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
 
7469
     * then this must refer to the same object.
 
7470
     * @member Ext.EventManager
 
7471
     * @method un
 
7472
     */
 
7473
    pub.un = pub.removeListener;
 
7474
 
 
7475
    pub.stoppedMouseDownEvent = new Ext.util.Event();
 
7476
    return pub;
 
7477
}();
 
7478
/**
 
7479
  * Adds a listener to be notified when the document is ready (before onload and before images are loaded). Shorthand of {@link Ext.EventManager#onDocumentReady}.
 
7480
  * @param {Function} fn The method the event invokes.
 
7481
  * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
 
7482
  * @param {boolean} options (optional) Options object as passed to {@link Ext.Element#addListener}. It is recommended that the options
 
7483
  * <code>{single: true}</code> be used so that the handler is removed on first invocation.
 
7484
  * @member Ext
 
7485
  * @method onReady
 
7486
 */
 
7487
Ext.onReady = Ext.EventManager.onDocumentReady;
 
7488
 
 
7489
 
 
7490
//Initialize doc classes
 
7491
(function(){
 
7492
    var initExtCss = function() {
 
7493
        // find the body element
 
7494
        var bd = document.body || document.getElementsByTagName('body')[0];
 
7495
        if (!bd) {
 
7496
            return false;
 
7497
        }
 
7498
        
 
7499
        var cls = [' ',
 
7500
                Ext.isIE ? "ext-ie " + (Ext.isIE6 ? 'ext-ie6' : (Ext.isIE7 ? 'ext-ie7' : 'ext-ie8'))
 
7501
                : Ext.isGecko ? "ext-gecko " + (Ext.isGecko2 ? 'ext-gecko2' : 'ext-gecko3')
 
7502
                : Ext.isOpera ? "ext-opera"
 
7503
                : Ext.isWebKit ? "ext-webkit" : ""];
 
7504
 
 
7505
        if (Ext.isSafari) {
 
7506
            cls.push("ext-safari " + (Ext.isSafari2 ? 'ext-safari2' : (Ext.isSafari3 ? 'ext-safari3' : 'ext-safari4')));
 
7507
        } else if(Ext.isChrome) {
 
7508
            cls.push("ext-chrome");
 
7509
        }
 
7510
 
 
7511
        if (Ext.isMac) {
 
7512
            cls.push("ext-mac");
 
7513
        }
 
7514
        if (Ext.isLinux) {
 
7515
            cls.push("ext-linux");
 
7516
        }
 
7517
 
 
7518
        // add to the parent to allow for selectors like ".ext-strict .ext-ie"
 
7519
        if (Ext.isStrict || Ext.isBorderBox) {
 
7520
            var p = bd.parentNode;
 
7521
            if (p) {
 
7522
                Ext.fly(p, '_internal').addClass(((Ext.isStrict && Ext.isIE ) || (!Ext.enableForcedBoxModel && !Ext.isIE)) ? ' ext-strict' : ' ext-border-box');
 
7523
            }
 
7524
        }
 
7525
        // Forced border box model class applied to all elements. Bypassing javascript based box model adjustments
 
7526
        // in favor of css.  This is for non-IE browsers.
 
7527
        if (Ext.enableForcedBoxModel && !Ext.isIE) {
 
7528
            Ext.isForcedBorderBox = true;
 
7529
            cls.push("ext-forced-border-box");
 
7530
        }
 
7531
        
 
7532
        Ext.fly(bd, '_internal').addClass(cls);
 
7533
        return true;
 
7534
    };
 
7535
    
 
7536
    if (!initExtCss()) {
 
7537
        Ext.onReady(initExtCss);
 
7538
    }
 
7539
})();
 
7540
 
 
7541
/**
 
7542
 * Code used to detect certain browser feature/quirks/bugs at startup.
 
7543
 */
 
7544
(function(){
 
7545
    var supports = Ext.apply(Ext.supports, {
 
7546
        /**
 
7547
         * In Webkit, there is an issue with getting the margin right property, see
 
7548
         * https://bugs.webkit.org/show_bug.cgi?id=13343
 
7549
         */
 
7550
        correctRightMargin: true,
 
7551
        
 
7552
        /**
 
7553
         * Webkit browsers return rgba(0, 0, 0) when a transparent color is used
 
7554
         */
 
7555
        correctTransparentColor: true,
 
7556
        
 
7557
        /**
 
7558
         * IE uses styleFloat, not cssFloat for the float property.
 
7559
         */
 
7560
        cssFloat: true
 
7561
    });
 
7562
    
 
7563
    var supportTests = function(){
 
7564
            var div = document.createElement('div'),
 
7565
                doc = document,
 
7566
                view,
 
7567
                last;
 
7568
                
 
7569
            div.innerHTML = '<div style="height:30px;width:50px;"><div style="height:20px;width:20px;"></div></div><div style="float:left;background-color:transparent;">';
 
7570
            doc.body.appendChild(div);
 
7571
            last = div.lastChild;
 
7572
            
 
7573
            if((view = doc.defaultView)){
 
7574
                if(view.getComputedStyle(div.firstChild.firstChild, null).marginRight != '0px'){
 
7575
                    supports.correctRightMargin = false;
 
7576
                }
 
7577
                if(view.getComputedStyle(last, null).backgroundColor != 'transparent'){
 
7578
                    supports.correctTransparentColor = false;
 
7579
                }
 
7580
            }
 
7581
            supports.cssFloat = !!last.style.cssFloat;
 
7582
            doc.body.removeChild(div);
 
7583
    };
 
7584
    
 
7585
    if (Ext.isReady) {
 
7586
        supportTests();    
 
7587
    } else {
 
7588
        Ext.onReady(supportTests);
 
7589
    }
 
7590
})();
 
7591
 
 
7592
 
 
7593
/**
 
7594
 * @class Ext.EventObject
 
7595
 * Just as {@link Ext.Element} wraps around a native DOM node, Ext.EventObject
 
7596
 * wraps the browser's native event-object normalizing cross-browser differences,
 
7597
 * such as which mouse button is clicked, keys pressed, mechanisms to stop
 
7598
 * event-propagation along with a method to prevent default actions from taking place.
 
7599
 * <p>For example:</p>
 
7600
 * <pre><code>
 
7601
function handleClick(e, t){ // e is not a standard event object, it is a Ext.EventObject
 
7602
    e.preventDefault();
 
7603
    var target = e.getTarget(); // same as t (the target HTMLElement)
 
7604
    ...
 
7605
}
 
7606
var myDiv = {@link Ext#get Ext.get}("myDiv");  // get reference to an {@link Ext.Element}
 
7607
myDiv.on(         // 'on' is shorthand for addListener
 
7608
    "click",      // perform an action on click of myDiv
 
7609
    handleClick   // reference to the action handler
 
7610
);
 
7611
// other methods to do the same:
 
7612
Ext.EventManager.on("myDiv", 'click', handleClick);
 
7613
Ext.EventManager.addListener("myDiv", 'click', handleClick);
 
7614
 </code></pre>
 
7615
 * @singleton
 
7616
 */
 
7617
Ext.EventObject = function(){
 
7618
    var E = Ext.lib.Event,
 
7619
        clickRe = /(dbl)?click/,
 
7620
        // safari keypress events for special keys return bad keycodes
 
7621
        safariKeys = {
 
7622
            3 : 13, // enter
 
7623
            63234 : 37, // left
 
7624
            63235 : 39, // right
 
7625
            63232 : 38, // up
 
7626
            63233 : 40, // down
 
7627
            63276 : 33, // page up
 
7628
            63277 : 34, // page down
 
7629
            63272 : 46, // delete
 
7630
            63273 : 36, // home
 
7631
            63275 : 35  // end
 
7632
        },
 
7633
        // normalize button clicks
 
7634
        btnMap = Ext.isIE ? {1:0,4:1,2:2} : {0:0,1:1,2:2};
 
7635
 
 
7636
    Ext.EventObjectImpl = function(e){
 
7637
        if(e){
 
7638
            this.setEvent(e.browserEvent || e);
 
7639
        }
 
7640
    };
 
7641
 
 
7642
    Ext.EventObjectImpl.prototype = {
 
7643
           /** @private */
 
7644
        setEvent : function(e){
 
7645
            var me = this;
 
7646
            if(e == me || (e && e.browserEvent)){ // already wrapped
 
7647
                return e;
 
7648
            }
 
7649
            me.browserEvent = e;
 
7650
            if(e){
 
7651
                // normalize buttons
 
7652
                me.button = e.button ? btnMap[e.button] : (e.which ? e.which - 1 : -1);
 
7653
                if(clickRe.test(e.type) && me.button == -1){
 
7654
                    me.button = 0;
 
7655
                }
 
7656
                me.type = e.type;
 
7657
                me.shiftKey = e.shiftKey;
 
7658
                // mac metaKey behaves like ctrlKey
 
7659
                me.ctrlKey = e.ctrlKey || e.metaKey || false;
 
7660
                me.altKey = e.altKey;
 
7661
                // in getKey these will be normalized for the mac
 
7662
                me.keyCode = e.keyCode;
 
7663
                me.charCode = e.charCode;
 
7664
                // cache the target for the delayed and or buffered events
 
7665
                me.target = E.getTarget(e);
 
7666
                // same for XY
 
7667
                me.xy = E.getXY(e);
 
7668
            }else{
 
7669
                me.button = -1;
 
7670
                me.shiftKey = false;
 
7671
                me.ctrlKey = false;
 
7672
                me.altKey = false;
 
7673
                me.keyCode = 0;
 
7674
                me.charCode = 0;
 
7675
                me.target = null;
 
7676
                me.xy = [0, 0];
 
7677
            }
 
7678
            return me;
 
7679
        },
 
7680
 
 
7681
        /**
 
7682
         * Stop the event (preventDefault and stopPropagation)
 
7683
         */
 
7684
        stopEvent : function(){
 
7685
            var me = this;
 
7686
            if(me.browserEvent){
 
7687
                if(me.browserEvent.type == 'mousedown'){
 
7688
                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
 
7689
                }
 
7690
                E.stopEvent(me.browserEvent);
 
7691
            }
 
7692
        },
 
7693
 
 
7694
        /**
 
7695
         * Prevents the browsers default handling of the event.
 
7696
         */
 
7697
        preventDefault : function(){
 
7698
            if(this.browserEvent){
 
7699
                E.preventDefault(this.browserEvent);
 
7700
            }
 
7701
        },
 
7702
 
 
7703
        /**
 
7704
         * Cancels bubbling of the event.
 
7705
         */
 
7706
        stopPropagation : function(){
 
7707
            var me = this;
 
7708
            if(me.browserEvent){
 
7709
                if(me.browserEvent.type == 'mousedown'){
 
7710
                    Ext.EventManager.stoppedMouseDownEvent.fire(me);
 
7711
                }
 
7712
                E.stopPropagation(me.browserEvent);
 
7713
            }
 
7714
        },
 
7715
 
 
7716
        /**
 
7717
         * Gets the character code for the event.
 
7718
         * @return {Number}
 
7719
         */
 
7720
        getCharCode : function(){
 
7721
            return this.charCode || this.keyCode;
 
7722
        },
 
7723
 
 
7724
        /**
 
7725
         * Returns a normalized keyCode for the event.
 
7726
         * @return {Number} The key code
 
7727
         */
 
7728
        getKey : function(){
 
7729
            return this.normalizeKey(this.keyCode || this.charCode);
 
7730
        },
 
7731
 
 
7732
        // private
 
7733
        normalizeKey: function(k){
 
7734
            return Ext.isSafari ? (safariKeys[k] || k) : k;
 
7735
        },
 
7736
 
 
7737
        /**
 
7738
         * Gets the x coordinate of the event.
 
7739
         * @return {Number}
 
7740
         */
 
7741
        getPageX : function(){
 
7742
            return this.xy[0];
 
7743
        },
 
7744
 
 
7745
        /**
 
7746
         * Gets the y coordinate of the event.
 
7747
         * @return {Number}
 
7748
         */
 
7749
        getPageY : function(){
 
7750
            return this.xy[1];
 
7751
        },
 
7752
 
 
7753
        /**
 
7754
         * Gets the page coordinates of the event.
 
7755
         * @return {Array} The xy values like [x, y]
 
7756
         */
 
7757
        getXY : function(){
 
7758
            return this.xy;
 
7759
        },
 
7760
 
 
7761
        /**
 
7762
         * Gets the target for the event.
 
7763
         * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
 
7764
         * @param {Number/Mixed} maxDepth (optional) The max depth to
 
7765
                search as a number or element (defaults to 10 || document.body)
 
7766
         * @param {Boolean} returnEl (optional) True to return a Ext.Element object instead of DOM node
 
7767
         * @return {HTMLelement}
 
7768
         */
 
7769
        getTarget : function(selector, maxDepth, returnEl){
 
7770
            return selector ? Ext.fly(this.target).findParent(selector, maxDepth, returnEl) : (returnEl ? Ext.get(this.target) : this.target);
 
7771
        },
 
7772
 
 
7773
        /**
 
7774
         * Gets the related target.
 
7775
         * @return {HTMLElement}
 
7776
         */
 
7777
        getRelatedTarget : function(){
 
7778
            return this.browserEvent ? E.getRelatedTarget(this.browserEvent) : null;
 
7779
        },
 
7780
 
 
7781
        /**
 
7782
         * Normalizes mouse wheel delta across browsers
 
7783
         * @return {Number} The delta
 
7784
         */
 
7785
        getWheelDelta : function(){
 
7786
            var e = this.browserEvent;
 
7787
            var delta = 0;
 
7788
            if(e.wheelDelta){ /* IE/Opera. */
 
7789
                delta = e.wheelDelta/120;
 
7790
            }else if(e.detail){ /* Mozilla case. */
 
7791
                delta = -e.detail/3;
 
7792
            }
 
7793
            return delta;
 
7794
        },
 
7795
 
 
7796
        /**
 
7797
        * Returns true if the target of this event is a child of el.  Unless the allowEl parameter is set, it will return false if if the target is el.
 
7798
        * Example usage:<pre><code>
 
7799
        // Handle click on any child of an element
 
7800
        Ext.getBody().on('click', function(e){
 
7801
            if(e.within('some-el')){
 
7802
                alert('Clicked on a child of some-el!');
 
7803
            }
 
7804
        });
 
7805
 
 
7806
        // Handle click directly on an element, ignoring clicks on child nodes
 
7807
        Ext.getBody().on('click', function(e,t){
 
7808
            if((t.id == 'some-el') && !e.within(t, true)){
 
7809
                alert('Clicked directly on some-el!');
 
7810
            }
 
7811
        });
 
7812
        </code></pre>
 
7813
         * @param {Mixed} el The id, DOM element or Ext.Element to check
 
7814
         * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
 
7815
         * @param {Boolean} allowEl {optional} true to also check if the passed element is the target or related target
 
7816
         * @return {Boolean}
 
7817
         */
 
7818
        within : function(el, related, allowEl){
 
7819
            if(el){
 
7820
                var t = this[related ? "getRelatedTarget" : "getTarget"]();
 
7821
                return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
 
7822
            }
 
7823
            return false;
 
7824
        }
 
7825
     };
 
7826
 
 
7827
    return new Ext.EventObjectImpl();
 
7828
}();
 
7829
/**
 
7830
 * @class Ext.Loader
 
7831
 * @singleton
 
7832
 * Simple class to help load JavaScript files on demand
 
7833
 */
 
7834
Ext.Loader = Ext.apply({}, {
 
7835
    /**
 
7836
     * Loads a given set of .js files. Calls the callback function when all files have been loaded
 
7837
     * Set preserveOrder to true to ensure non-parallel loading of files if load order is important
 
7838
     * @param {Array} fileList Array of all files to load
 
7839
     * @param {Function} callback Callback to call after all files have been loaded
 
7840
     * @param {Object} scope The scope to call the callback in
 
7841
     * @param {Boolean} preserveOrder True to make files load in serial, one after the other (defaults to false)
 
7842
     */
 
7843
    load: function(fileList, callback, scope, preserveOrder) {
 
7844
        var scope       = scope || this,
 
7845
            head        = document.getElementsByTagName("head")[0],
 
7846
            fragment    = document.createDocumentFragment(),
 
7847
            numFiles    = fileList.length,
 
7848
            loadedFiles = 0,
 
7849
            me          = this;
 
7850
        
 
7851
        /**
 
7852
         * Loads a particular file from the fileList by index. This is used when preserving order
 
7853
         */
 
7854
        var loadFileIndex = function(index) {
 
7855
            head.appendChild(
 
7856
                me.buildScriptTag(fileList[index], onFileLoaded)
 
7857
            );
 
7858
        };
 
7859
        
 
7860
        /**
 
7861
         * Callback function which is called after each file has been loaded. This calls the callback
 
7862
         * passed to load once the final file in the fileList has been loaded
 
7863
         */
 
7864
        var onFileLoaded = function() {
 
7865
            loadedFiles ++;
 
7866
            
 
7867
            //if this was the last file, call the callback, otherwise load the next file
 
7868
            if (numFiles == loadedFiles && typeof callback == 'function') {
 
7869
                callback.call(scope);
 
7870
            } else {
 
7871
                if (preserveOrder === true) {
 
7872
                    loadFileIndex(loadedFiles);
 
7873
                }
 
7874
            }
 
7875
        };
 
7876
        
 
7877
        if (preserveOrder === true) {
 
7878
            loadFileIndex.call(this, 0);
 
7879
        } else {
 
7880
            //load each file (most browsers will do this in parallel)
 
7881
            Ext.each(fileList, function(file, index) {
 
7882
                fragment.appendChild(
 
7883
                    this.buildScriptTag(file, onFileLoaded)
 
7884
                );  
 
7885
            }, this);
 
7886
            
 
7887
            head.appendChild(fragment);
 
7888
        }
 
7889
    },
 
7890
    
 
7891
    /**
 
7892
     * @private
 
7893
     * Creates and returns a script tag, but does not place it into the document. If a callback function
 
7894
     * is passed, this is called when the script has been loaded
 
7895
     * @param {String} filename The name of the file to create a script tag for
 
7896
     * @param {Function} callback Optional callback, which is called when the script has been loaded
 
7897
     * @return {Element} The new script ta
 
7898
     */
 
7899
    buildScriptTag: function(filename, callback) {
 
7900
        var script  = document.createElement('script');
 
7901
        script.type = "text/javascript";
 
7902
        script.src  = filename;
 
7903
        
 
7904
        //IE has a different way of handling &lt;script&gt; loads, so we need to check for it here
 
7905
        if (script.readyState) {
 
7906
            script.onreadystatechange = function() {
 
7907
                if (script.readyState == "loaded" || script.readyState == "complete") {
 
7908
                    script.onreadystatechange = null;
 
7909
                    callback();
 
7910
                }
 
7911
            };
 
7912
        } else {
 
7913
            script.onload = callback;
 
7914
        }    
 
7915
        
 
7916
        return script;
 
7917
    }
 
7918
});