3 This file is part of Ext JS 4
5 Copyright (c) 2011 Sencha Inc
7 Contact: http://www.sencha.com/contact
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
16 * @class Ext.EventManager
17 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
18 * several useful events directly.
19 * See {@link Ext.EventObject} for more details on normalized event objects.
24 // --------------------- onReady ---------------------
27 * Check if we have bound our global onReady listener
30 hasBoundOnReady: false,
33 * Check if fireDocReady has been called
39 * Timer for the document ready event in old IE versions
45 * Checks if we have bound an onreadystatechange event
48 hasOnReadyStateChange: false,
51 * Holds references to any onReady functions
54 readyEvent: new Ext.util.Event(),
57 * Check the ready state for old IE versions
59 * @return {Boolean} True if the document is ready
61 checkReadyState: function(){
62 var me = Ext.EventManager;
64 if(window.attachEvent){
65 // See here for reference: http://javascript.nwbox.com/IEContentLoaded/
70 document.documentElement.doScroll('left');
77 if (document.readyState == 'complete') {
81 me.readyTimeout = setTimeout(arguments.callee, 2);
86 * Binds the appropriate browser event for checking if the DOM has loaded.
89 bindReadyEvent: function(){
90 var me = Ext.EventManager;
91 if (me.hasBoundOnReady) {
95 if (document.addEventListener) {
96 document.addEventListener('DOMContentLoaded', me.fireDocReady, false);
97 // fallback, load will ~always~ fire
98 window.addEventListener('load', me.fireDocReady, false);
100 // check if the document is ready, this will also kick off the scroll checking timer
101 if (!me.checkReadyState()) {
102 document.attachEvent('onreadystatechange', me.checkReadyState);
103 me.hasOnReadyStateChange = true;
105 // fallback, onload will ~always~ fire
106 window.attachEvent('onload', me.fireDocReady, false);
108 me.hasBoundOnReady = true;
112 * We know the document is loaded, so trigger any onReady events.
115 fireDocReady: function(){
116 var me = Ext.EventManager;
118 // only unbind these events once
119 if (!me.hasFiredReady) {
120 me.hasFiredReady = true;
122 if (document.addEventListener) {
123 document.removeEventListener('DOMContentLoaded', me.fireDocReady, false);
124 window.removeEventListener('load', me.fireDocReady, false);
126 if (me.readyTimeout !== null) {
127 clearTimeout(me.readyTimeout);
129 if (me.hasOnReadyStateChange) {
130 document.detachEvent('onreadystatechange', me.checkReadyState);
132 window.detachEvent('onload', me.fireDocReady);
139 me.readyEvent.fire();
144 * Adds a listener to be notified when the document is ready (before onload and before images are loaded). Can be
145 * accessed shorthanded as Ext.onReady().
146 * @param {Function} fn The method the event invokes.
147 * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
148 * @param {boolean} options (optional) Options object as passed to {@link Ext.core.Element#addListener}.
150 onDocumentReady: function(fn, scope, options){
151 options = options || {};
152 var me = Ext.EventManager,
153 readyEvent = me.readyEvent;
155 // force single to be true so our event is only ever fired once.
156 options.single = true;
158 // Document already loaded, let's just fire it
160 readyEvent.addListener(fn, scope, options);
163 options.delay = options.delay || 1;
164 readyEvent.addListener(fn, scope, options);
170 // --------------------- event binding ---------------------
173 * Contains a list of all document mouse downs, so we can ensure they fire even when stopEvent is called.
176 stoppedMouseDownEvent: new Ext.util.Event(),
179 * Options to parse for the 4th argument to addListener.
182 propRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|freezeEvent)$/,
185 * Get the id of the element. If one has not been assigned, automatically assign it.
186 * @param {Mixed} element The element to get the id for.
187 * @return {String} id
189 getId : function(element) {
190 var skipGarbageCollection = false,
193 element = Ext.getDom(element);
195 if (element === document || element === window) {
196 id = element === document ? Ext.documentId : Ext.windowId;
199 id = Ext.id(element);
201 // skip garbage collection for special elements (window, document, iframes)
202 if (element && (element.getElementById || element.navigator)) {
203 skipGarbageCollection = true;
207 Ext.core.Element.addToCache(new Ext.core.Element(element), id);
208 if (skipGarbageCollection) {
209 Ext.cache[id].skipGarbageCollection = true;
216 * Convert a "config style" listener into a set of flat arguments so they can be passed to addListener
218 * @param {Object} element The element the event is for
219 * @param {Object} event The event configuration
220 * @param {Object} isRemove True if a removal should be performed, otherwise an add will be done.
222 prepareListenerConfig: function(element, config, isRemove){
227 // loop over all the keys in the object
228 for (key in config) {
229 if (config.hasOwnProperty(key)) {
230 // if the key is something else then an event option
231 if (!propRe.test(key)) {
233 // if the value is a function it must be something like click: function(){}, scope: this
234 // which means that there might be multiple event listeners with shared options
235 if (Ext.isFunction(value)) {
237 args = [element, key, value, config.scope, config];
239 // if its not a function, it must be an object like click: {fn: function(){}, scope: this}
240 args = [element, key, value.fn, value.scope, value];
243 if (isRemove === true) {
244 me.removeListener.apply(this, args);
246 me.addListener.apply(me, args);
254 * Normalize cross browser event differences
256 * @param {Object} eventName The event name
257 * @param {Object} fn The function to execute
258 * @return {Object} The new event name/function
260 normalizeEvent: function(eventName, fn){
261 if (/mouseenter|mouseleave/.test(eventName) && !Ext.supports.MouseEnterLeave) {
263 fn = Ext.Function.createInterceptor(fn, this.contains, this);
265 eventName = eventName == 'mouseenter' ? 'mouseover' : 'mouseout';
266 } else if (eventName == 'mousewheel' && !Ext.supports.MouseWheel && !Ext.isOpera){
267 eventName = 'DOMMouseScroll';
270 eventName: eventName,
276 * Checks whether the event's relatedTarget is contained inside (or <b>is</b>) the element.
278 * @param {Object} event
280 contains: function(event){
281 var parent = event.browserEvent.currentTarget,
282 child = this.getRelatedTarget(event);
284 if (parent && parent.firstChild) {
286 if (child === parent) {
289 child = child.parentNode;
290 if (child && (child.nodeType != 1)) {
299 * Appends an event handler to an element. The shorthand version {@link #on} is equivalent. Typically you will
300 * use {@link Ext.core.Element#addListener} directly on an Element in favor of calling this version.
301 * @param {String/HTMLElement} el The html element or id to assign the event handler to.
302 * @param {String} eventName The name of the event to listen for.
303 * @param {Function} handler The handler function the event invokes. This function is passed
304 * the following parameters:<ul>
305 * <li>evt : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>
306 * <li>t : Element<div class="sub-desc">The {@link Ext.core.Element Element} which was the target of the event.
307 * Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>
308 * <li>o : Object<div class="sub-desc">The options object from the addListener call.</div></li>
310 * @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>.
311 * @param {Object} options (optional) An object containing handler configuration properties.
312 * This may contain any of the following properties:<ul>
313 * <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>
314 * <li>delegate : String<div class="sub-desc">A simple selector to filter the target or look for a descendant of the target</div></li>
315 * <li>stopEvent : Boolean<div class="sub-desc">True to stop the event. That is stop propagation, and prevent the default action.</div></li>
316 * <li>preventDefault : Boolean<div class="sub-desc">True to prevent the default action</div></li>
317 * <li>stopPropagation : Boolean<div class="sub-desc">True to prevent event propagation</div></li>
318 * <li>normalized : Boolean<div class="sub-desc">False to pass a browser event to the handler function instead of an Ext.EventObject</div></li>
319 * <li>delay : Number<div class="sub-desc">The number of milliseconds to delay the invocation of the handler after te event fires.</div></li>
320 * <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>
321 * <li>buffer : Number<div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
322 * by the specified number of milliseconds. If the event fires again within that time, the original
323 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>
324 * <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>
326 * <p>See {@link Ext.core.Element#addListener} for examples of how to use these options.</p>
328 addListener: function(element, eventName, fn, scope, options){
329 // Check if we've been passed a "config style" event.
330 if (typeof eventName !== 'string') {
331 this.prepareListenerConfig(element, eventName);
335 var dom = Ext.getDom(element),
342 sourceClass: 'Ext.EventManager',
343 sourceMethod: 'addListener',
344 targetElement: element,
345 eventName: eventName,
346 msg: 'Error adding "' + eventName + '\" listener for nonexistent element "' + element + '"'
351 sourceClass: 'Ext.EventManager',
352 sourceMethod: 'addListener',
353 targetElement: element,
354 eventName: eventName,
355 msg: 'Error adding "' + eventName + '\" listener. The handler function is undefined.'
360 // create the wrapper function
361 options = options || {};
363 bind = this.normalizeEvent(eventName, fn);
364 wrap = this.createListenerWrap(dom, eventName, bind.fn, scope, options);
367 if (dom.attachEvent) {
368 dom.attachEvent('on' + bind.eventName, wrap);
370 dom.addEventListener(bind.eventName, wrap, options.capture || false);
373 if (dom == document && eventName == 'mousedown') {
374 this.stoppedMouseDownEvent.addListener(wrap);
377 // add all required data into the event cache
378 this.getEventListenerCache(dom, eventName).push({
386 * Removes an event handler from an element. The shorthand version {@link #un} is equivalent. Typically
387 * you will use {@link Ext.core.Element#removeListener} directly on an Element in favor of calling this version.
388 * @param {String/HTMLElement} el The id or html element from which to remove the listener.
389 * @param {String} eventName The name of the event.
390 * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
391 * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
392 * then this must refer to the same object.
394 removeListener : function(element, eventName, fn, scope) {
395 // handle our listener config object syntax
396 if (typeof eventName !== 'string') {
397 this.prepareListenerConfig(element, eventName, true);
401 var dom = Ext.getDom(element),
402 cache = this.getEventListenerCache(dom, eventName),
403 bindName = this.normalizeEvent(eventName).eventName,
405 listener, wrap, tasks;
411 if (listener && (!fn || listener.fn == fn) && (!scope || listener.scope === scope)) {
412 wrap = listener.wrap;
414 // clear buffered calls
416 clearTimeout(wrap.task);
420 // clear delayed calls
421 j = wrap.tasks && wrap.tasks.length;
424 clearTimeout(wrap.tasks[j]);
429 if (dom.detachEvent) {
430 dom.detachEvent('on' + bindName, wrap);
432 dom.removeEventListener(bindName, wrap, false);
435 if (wrap && dom == document && eventName == 'mousedown') {
436 this.stoppedMouseDownEvent.removeListener(wrap);
439 // remove listener from cache
440 Ext.Array.erase(cache, i, 1);
446 * Removes all event handers from an element. Typically you will use {@link Ext.core.Element#removeAllListeners}
447 * directly on an Element in favor of calling this version.
448 * @param {String/HTMLElement} el The id or html element from which to remove all event handlers.
450 removeAll : function(element){
451 var dom = Ext.getDom(element),
456 cache = this.getElementEventCache(dom);
459 if (cache.hasOwnProperty(ev)) {
460 this.removeListener(dom, ev);
463 Ext.cache[dom.id].events = {};
467 * Recursively removes all previous added listeners from an element and its children. Typically you will use {@link Ext.core.Element#purgeAllListeners}
468 * directly on an Element in favor of calling this version.
469 * @param {String/HTMLElement} el The id or html element from which to remove all event handlers.
470 * @param {String} eventName (optional) The name of the event.
472 purgeElement : function(element, eventName) {
473 var dom = Ext.getDom(element),
477 this.removeListener(dom, eventName);
483 if(dom && dom.childNodes) {
484 for(len = element.childNodes.length; i < len; i++) {
485 this.purgeElement(element.childNodes[i], eventName);
491 * Create the wrapper function for the event
493 * @param {HTMLElement} dom The dom element
494 * @param {String} ename The event name
495 * @param {Function} fn The function to execute
496 * @param {Object} scope The scope to execute callback in
497 * @param {Object} options The options
498 * @return {Function} the wrapper function
500 createListenerWrap : function(dom, ename, fn, scope, options) {
501 options = options || {};
505 return function wrap(e, args) {
506 // Compile the implementation upon first firing
508 f = ['if(!Ext) {return;}'];
510 if(options.buffer || options.delay || options.freezeEvent) {
511 f.push('e = new Ext.EventObjectImpl(e, ' + (options.freezeEvent ? 'true' : 'false' ) + ');');
513 f.push('e = Ext.EventObject.setEvent(e);');
516 if (options.delegate) {
517 f.push('var t = e.getTarget("' + options.delegate + '", this);');
518 f.push('if(!t) {return;}');
520 f.push('var t = e.target;');
523 if (options.target) {
524 f.push('if(e.target !== options.target) {return;}');
527 if(options.stopEvent) {
528 f.push('e.stopEvent();');
530 if(options.preventDefault) {
531 f.push('e.preventDefault();');
533 if(options.stopPropagation) {
534 f.push('e.stopPropagation();');
538 if(options.normalized === false) {
539 f.push('e = e.browserEvent;');
543 f.push('(wrap.task && clearTimeout(wrap.task));');
544 f.push('wrap.task = setTimeout(function(){');
548 f.push('wrap.tasks = wrap.tasks || [];');
549 f.push('wrap.tasks.push(setTimeout(function(){');
552 // finally call the actual handler fn
553 f.push('fn.call(scope || dom, e, t, options);');
556 f.push('Ext.EventManager.removeListener(dom, ename, fn, scope);');
560 f.push('}, ' + options.delay + '));');
564 f.push('}, ' + options.buffer + ');');
567 gen = Ext.functionFactory('e', 'options', 'fn', 'scope', 'ename', 'dom', 'wrap', 'args', f.join('\n'));
570 gen.call(dom, e, options, fn, scope, ename, dom, wrap, args);
575 * Get the event cache for a particular element for a particular event
577 * @param {HTMLElement} element The element
578 * @param {Object} eventName The event name
579 * @return {Array} The events for the element
581 getEventListenerCache : function(element, eventName) {
586 var eventCache = this.getElementEventCache(element);
587 return eventCache[eventName] || (eventCache[eventName] = []);
591 * Gets the event cache for the object
593 * @param {HTMLElement} element The element
594 * @return {Object} The event cache for the object
596 getElementEventCache : function(element) {
600 var elementCache = Ext.cache[this.getId(element)];
601 return elementCache.events || (elementCache.events = {});
604 // --------------------- utility methods ---------------------
605 mouseLeaveRe: /(mouseout|mouseleave)/,
606 mouseEnterRe: /(mouseover|mouseenter)/,
609 * Stop the event (preventDefault and stopPropagation)
610 * @param {Event} The event to stop
612 stopEvent: function(event) {
613 this.stopPropagation(event);
614 this.preventDefault(event);
618 * Cancels bubbling of the event.
619 * @param {Event} The event to stop bubbling.
621 stopPropagation: function(event) {
622 event = event.browserEvent || event;
623 if (event.stopPropagation) {
624 event.stopPropagation();
626 event.cancelBubble = true;
631 * Prevents the browsers default handling of the event.
632 * @param {Event} The event to prevent the default
634 preventDefault: function(event) {
635 event = event.browserEvent || event;
636 if (event.preventDefault) {
637 event.preventDefault();
639 event.returnValue = false;
640 // Some keys events require setting the keyCode to -1 to be prevented
642 // all ctrl + X and F1 -> F12
643 if (event.ctrlKey || event.keyCode > 111 && event.keyCode < 124) {
647 // see this outdated document http://support.microsoft.com/kb/934364/en-us for more info
653 * Gets the related target from the event.
654 * @param {Object} event The event
655 * @return {HTMLElement} The related target.
657 getRelatedTarget: function(event) {
658 event = event.browserEvent || event;
659 var target = event.relatedTarget;
661 if (this.mouseLeaveRe.test(event.type)) {
662 target = event.toElement;
663 } else if (this.mouseEnterRe.test(event.type)) {
664 target = event.fromElement;
667 return this.resolveTextNode(target);
671 * Gets the x coordinate from the event
672 * @param {Object} event The event
673 * @return {Number} The x coordinate
675 getPageX: function(event) {
676 return this.getXY(event)[0];
680 * Gets the y coordinate from the event
681 * @param {Object} event The event
682 * @return {Number} The y coordinate
684 getPageY: function(event) {
685 return this.getXY(event)[1];
689 * Gets the x & ycoordinate from the event
690 * @param {Object} event The event
691 * @return {Array} The x/y coordinate
693 getPageXY: function(event) {
694 event = event.browserEvent || event;
697 doc = document.documentElement,
698 body = document.body;
700 // pageX/pageY not available (undefined, not null), use clientX/clientY instead
702 x = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
703 y = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
709 * Gets the target of the event.
710 * @param {Object} event The event
711 * @return {HTMLElement} target
713 getTarget: function(event) {
714 event = event.browserEvent || event;
715 return this.resolveTextNode(event.target || event.srcElement);
719 * Resolve any text nodes accounting for browser differences.
721 * @param {HTMLElement} node The node
722 * @return {HTMLElement} The resolved node
724 // technically no need to browser sniff this, however it makes no sense to check this every time, for every event, whether the string is equal.
725 resolveTextNode: Ext.isGecko ?
730 // work around firefox bug, https://bugzilla.mozilla.org/show_bug.cgi?id=101197
731 var s = HTMLElement.prototype.toString.call(node);
732 if (s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]') {
735 return node.nodeType == 3 ? node.parentNode: node;
737 return node && node.nodeType == 3 ? node.parentNode: node;
740 // --------------------- custom event binding ---------------------
742 // Keep track of the current width/height
747 * Adds a listener to be notified when the browser window is resized and provides resize event buffering (100 milliseconds),
748 * passes new viewport width and height to handlers.
749 * @param {Function} fn The handler function the window resize event invokes.
750 * @param {Object} scope The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
751 * @param {boolean} options Options object as passed to {@link Ext.core.Element#addListener}
753 onWindowResize: function(fn, scope, options){
754 var resize = this.resizeEvent;
756 this.resizeEvent = resize = new Ext.util.Event();
757 this.on(window, 'resize', this.fireResize, this, {buffer: 100});
759 resize.addListener(fn, scope, options);
763 * Fire the resize event.
766 fireResize: function(){
768 w = Ext.core.Element.getViewWidth(),
769 h = Ext.core.Element.getViewHeight();
771 //whacky problem in IE where the resize event will sometimes fire even though the w/h are the same.
772 if(me.curHeight != h || me.curWidth != w){
775 me.resizeEvent.fire(w, h);
780 * Removes the passed window resize listener.
781 * @param {Function} fn The method the event invokes
782 * @param {Object} scope The scope of handler
784 removeResizeListener: function(fn, scope){
785 if (this.resizeEvent) {
786 this.resizeEvent.removeListener(fn, scope);
790 onWindowUnload: function() {
791 var unload = this.unloadEvent;
793 this.unloadEvent = unload = new Ext.util.Event();
794 this.addListener(window, 'unload', this.fireUnload, this);
799 * Fires the unload event for items bound with onWindowUnload
802 fireUnload: function() {
803 // wrap in a try catch, could have some problems during unload
805 this.removeUnloadListener();
806 // Work around FF3 remembering the last scroll position when refreshing the grid and then losing grid view
808 var gridviews = Ext.ComponentQuery.query('gridview'),
810 ln = gridviews.length;
811 for (; i < ln; i++) {
812 gridviews[i].scrollToTop();
815 // Purge all elements in the cache
819 if (cache.hasOwnProperty(el)) {
820 Ext.EventManager.removeAll(el);
828 * Removes the passed window unload listener.
829 * @param {Function} fn The method the event invokes
830 * @param {Object} scope The scope of handler
832 removeUnloadListener: function(){
833 if (this.unloadEvent) {
834 this.removeListener(window, 'unload', this.fireUnload);
839 * note 1: IE fires ONLY the keydown event on specialkey autorepeat
840 * note 2: Safari < 3.1, Gecko (Mac/Linux) & Opera fire only the keypress event on specialkey autorepeat
841 * (research done by @Jan Wolter at http://unixpapa.com/js/key.html)
844 useKeyDown: Ext.isWebKit ?
845 parseInt(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1], 10) >= 525 :
846 !((Ext.isGecko && !Ext.isWindows) || Ext.isOpera),
849 * Indicates which event to use for getting key presses.
850 * @return {String} The appropriate event name.
852 getKeyEvent: function(){
853 return this.useKeyDown ? 'keydown' : 'keypress';
858 * Alias for {@link Ext.Loader#onReady Ext.Loader.onReady} with withDomReady set to true
862 Ext.onReady = function(fn, scope, options) {
863 Ext.Loader.onReady(fn, scope, true, options);
867 * Alias for {@link Ext.EventManager#onDocumentReady Ext.EventManager.onDocumentReady}
869 * @method onDocumentReady
871 Ext.onDocumentReady = Ext.EventManager.onDocumentReady;
874 * Alias for {@link Ext.EventManager#addListener Ext.EventManager.addListener}
875 * @member Ext.EventManager
878 Ext.EventManager.on = Ext.EventManager.addListener;
881 * Alias for {@link Ext.EventManager#removeListener Ext.EventManager.removeListener}
882 * @member Ext.EventManager
885 Ext.EventManager.un = Ext.EventManager.removeListener;
888 var initExtCss = function() {
889 // find the body element
890 var bd = document.body || document.getElementsByTagName('body')[0],
891 baseCSSPrefix = Ext.baseCSSPrefix,
892 cls = [baseCSSPrefix + 'body'],
900 html = bd.parentNode;
902 //Let's keep this human readable!
904 cls.push(baseCSSPrefix + 'ie');
907 cls.push(baseCSSPrefix + 'ie6');
910 cls.push(baseCSSPrefix + 'ie7');
913 cls.push(baseCSSPrefix + 'ie8');
916 cls.push(baseCSSPrefix + 'ie9');
919 cls.push(baseCSSPrefix + 'gecko');
922 cls.push(baseCSSPrefix + 'gecko3');
925 cls.push(baseCSSPrefix + 'gecko4');
928 cls.push(baseCSSPrefix + 'opera');
931 cls.push(baseCSSPrefix + 'webkit');
934 cls.push(baseCSSPrefix + 'safari');
937 cls.push(baseCSSPrefix + 'safari2');
940 cls.push(baseCSSPrefix + 'safari3');
943 cls.push(baseCSSPrefix + 'safari4');
946 cls.push(baseCSSPrefix + 'chrome');
949 cls.push(baseCSSPrefix + 'mac');
952 cls.push(baseCSSPrefix + 'linux');
954 if (!Ext.supports.CSS3BorderRadius) {
955 cls.push(baseCSSPrefix + 'nbr');
957 if (!Ext.supports.CSS3LinearGradient) {
958 cls.push(baseCSSPrefix + 'nlg');
960 if (!Ext.scopeResetCSS) {
961 cls.push(baseCSSPrefix + 'reset');
964 // add to the parent to allow for selectors x-strict x-border-box, also set the isBorderBox property correctly
966 if (Ext.isStrict && (Ext.isIE6 || Ext.isIE7)) {
967 Ext.isBorderBox = false;
970 Ext.isBorderBox = true;
973 htmlCls.push(baseCSSPrefix + (Ext.isBorderBox ? 'border-box' : 'strict'));
975 htmlCls.push(baseCSSPrefix + 'quirks');
976 if (Ext.isIE && !Ext.isStrict) {
977 Ext.isIEQuirks = true;
980 Ext.fly(html, '_internal').addCls(htmlCls);
983 Ext.fly(bd, '_internal').addCls(cls);
987 Ext.onReady(initExtCss);