/**
* An `{@link Ext.mixin.Observable Observable}` through which Ext fires global events.
*
* Ext.on() and Ext.un() are shorthand for {@link #addListener} and {@link #removeListener}
* on this Observable. For example, to listen for the idle event:
*
* Ext.on('idle', function() {
* // do something
* });
*/
Ext.define('Ext.GlobalEvents', {
extend: 'Ext.mixin.Observable',
alternateClassName: 'Ext.globalEvents', // for compat with Ext JS 4.2 and earlier
requires: [
'Ext.dom.Element'
],
observableType: 'global',
singleton: true,
/**
* @private
*/
resizeBuffer: 100,
/**
* @event added
* Fires when a Component is added to a Container.
* @param {Ext.Component} component
*/
/**
* @event beforeresponsiveupdate
* Fires before {@link Ext.mixin.Responsive} perform any updates in response to
* dynamic changes. This is prior to refreshing `responsiveFormulas`.
* @param {Object} context The context object used by `responsiveConfig` expressions.
* @since 5.0.1
*/
/**
* @event beginresponsiveupdate
* Fires when {@link Ext.mixin.Responsive} is about to perform updates in response to
* dynamic changes. At this point all `responsiveFormulas` have been refreshed.
* @param {Object} context The context object used by `responsiveConfig` expressions.
* @since 5.0.1
*/
/**
* @event responsiveupdate
* Fires after {@link Ext.mixin.Responsive} has performed updates in response to
* dynamic changes.
* @param {Object} context The context object used by `responsiveConfig` expressions.
* @since 5.0.1
*/
/**
* @event collapse
* Fires when a Component is collapsed (e.g., a panel).
* @param {Ext.Component} component
*/
/**
* @event expand
* Fires when a Component is expanded (e.g., a panel).
* @param {Ext.Component} component
*/
/**
* @event hide
* Fires when a Component is hidden.
* @param {Ext.Component} component
*/
/**
* @event idle
* Fires when an event handler finishes its run, just before returning to
* browser control.
*
* This includes DOM event handlers, Ajax (including JSONP) event handlers,
* and {@link Ext.util.TaskRunner TaskRunners}
*
* When called at the tail of a DOM event, the event object is passed as the
* sole parameter.
*
* This can be useful for performing cleanup, or update tasks which need to
* happen only after all code in an event handler has been run, but which
* should not be executed in a timer due to the intervening browser
* reflow/repaint which would take place.
*/
/**
* @event onlinechange
* Fires when the online status of the page changes. See {@link Ext#method-isOnline}
* @param {Boolean} online `true` if in an online state.
*
* @since 6.2.1
*/
/**
* @event removed
* Fires when a Component is removed from a Container.
* @param {Ext.Component} component
*/
/**
* @event resize
* Fires when the browser window is resized. To avoid running resize handlers
* too often resulting in sluggish window resizing, the resize event uses a buffer
* of 100 milliseconds in the Classic toolkit, and fires on animation frame
* in the Modern toolkit.
* @param {Number} width The new width
* @param {Number} height The new height
*/
/**
* @event show
* Fires when a Component is shown.
* @param {Ext.Component} component
*/
/**
* @event beforebindnotify
* Fires before a scheduled set of bindings are fired. This allows interested parties
* to react and do any required work.
*
* @private
* @since 5.1.0
*/
/**
* @event mousedown
* A mousedown listener on the document that is immune to stopPropagation()
* used in cases where we need to know if a mousedown event occurred on the
* document regardless of whether some other handler tried to stop it. An
* example where this is useful is a menu that needs to be hidden whenever
* there is a mousedown event on the document.
* @param {Ext.event.Event} e The event object
*/
/**
* @event mouseup
* A mouseup listener on the document that is immune to stopPropagation()
* used in cases where we need to know if a mouseup event occurred on the
* document regardless of whether some other handler tried to stop it. An
* example where this is useful is a component which enters a "pressed" state
* upon mousedown, and needs to exit that state even if the mouse exits
* before being released.
* @param {Ext.event.Event} e The event object
*/
/**
* @property {Object} idleEventMask
* This object holds event names for events that should not trigger an `idle` event
* following their dispatch.
* @private
* @since 5.0.0
*/
idleEventMask: {
mousemove: 1,
touchmove: 1,
pointermove: 1,
MSPointerMove: 1,
unload: 1
},
// @private
windowListeners: {
resize: {
fn: 'fireResize'
}
},
constructor: function() {
var me = this;
me.callParent();
Ext.onInternalReady(function() {
// using a closure here instead of attaching the event directly to the
// attachListeners method gives us a chance to override the method
me.attachListeners();
});
},
setPressedComponent: function(component, e) {
var me = this,
pressedComponent = me.pressedComponent;
if (pressedComponent && pressedComponent.onRelease) {
pressedComponent.onRelease(e);
}
me.pressedComponent = component;
if (component) {
me.pressedScrollStart = Ext.on({
scrollstart: function() {
me.setPressedComponent(null, e);
},
destroyable: true
});
}
else {
me.pressedScrollStart = Ext.destroy(me.pressedScrollStart);
}
},
attachListeners: function() {
var me = this,
win = Ext.getWin(),
winListeners = me.windowListeners;
me.onlineState = Ext.isOnline();
// Capture width/height to compare later in fireResize
me.curHeight = Ext.Element.getViewportHeight();
me.curWidth = Ext.Element.getViewportWidth();
win.on({
scope: me,
online: 'handleOnlineChange',
offline: 'handleOnlineChange'
});
// This function is not entirely harmless but since it is not directly related
// to any component, element, or other destructible entity and effectively cannot
// be cleaned up, we have to pretend it's OK for this timer to go unnoticed.
//<debug>
me.fireResize.$skipTimerCheck = true;
//</debug>
// IE8 does its own thing
if (winListeners) {
winListeners.scope = me;
// CSS layouts only require buffering to the next animation frame
if (Ext.isModern) {
winListeners.resize.onFrame = true;
}
else {
winListeners.resize.buffer = me.resizeBuffer;
}
win.on(winListeners);
}
Ext.getDoc().on({
touchstart: 'fireMouseDown',
mousedown: 'fireMouseDown',
mouseup: 'fireMouseUp',
touchend: 'fireMouseUp',
drop: 'fireMouseUp',
dragend: 'fireMouseUp',
scope: me
});
},
fireMouseDown: function(e) {
this.fireEvent('mousedown', e);
// Synchronize floated component ordering.
// Note that this is an ASAP method and will complete asynchronously
// after this event has finished.
Ext.ComponentManager.handleDocumentMouseDown(e);
},
fireMouseUp: function(e) {
this.fireEvent('mouseup', e);
this.setPressedComponent(null, e);
},
fireResize: function() {
var me = this,
Element = Ext.Element,
w = Element.getViewportWidth(),
h = Element.getViewportHeight();
// In IE the resize event will sometimes fire even though the w/h are the same.
if (me.curHeight !== h || me.curWidth !== w) {
me.curHeight = h;
me.curWidth = w;
if (me.hasListeners.resize) {
me.fireEvent('resize', w, h);
}
}
},
handleOnlineChange: function() {
var online = Ext.isOnline();
if (online !== this.onlineState) {
this.onlineState = online;
this.fireEvent('onlinechange', online);
}
}
}, function(GlobalEvents) {
Ext.hasListeners = GlobalEvents.hasListeners;
/**
* @member Ext
* @method on
* Shorthand for {@link Ext.GlobalEvents#addListener}.
* @inheritdoc Ext.mixin.Observable#addListener
*/
Ext.on = function() {
return GlobalEvents.addListener.apply(GlobalEvents, arguments);
};
/**
* @member Ext
* @method un
* Shorthand for {@link Ext.GlobalEvents#removeListener}.
* @inheritdoc Ext.mixin.Observable#removeListener
*/
Ext.un = function() {
return GlobalEvents.removeListener.apply(GlobalEvents, arguments);
};
/**
* @member Ext
* @method fireEvent
* Shorthand for {@link Ext.GlobalEvents#fireEvent}.
* @inheritdoc Ext.mixin.Observable#fireEvent
*
* @since 6.2.0
*/
Ext.fireEvent = function() {
return GlobalEvents.fireEvent.apply(GlobalEvents, arguments);
};
/**
* @member Ext
* @method fireIdle
* Fires the global `idle` event if there are any listeners registered.
*
* @since 6.5.1
* @private
*/
Ext.fireIdle = function() {
if (GlobalEvents.hasListeners.idle && !Ext._suppressIdle) {
GlobalEvents.fireEventArgs('idle');
}
Ext._suppressIdle = false;
};
Ext._suppressIdle = false;
});