GlobalEvents.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. /**
  2. * An `{@link Ext.mixin.Observable Observable}` through which Ext fires global events.
  3. *
  4. * Ext.on() and Ext.un() are shorthand for {@link #addListener} and {@link #removeListener}
  5. * on this Observable. For example, to listen for the idle event:
  6. *
  7. * Ext.on('idle', function() {
  8. * // do something
  9. * });
  10. */
  11. Ext.define('Ext.GlobalEvents', {
  12. extend: 'Ext.mixin.Observable',
  13. alternateClassName: 'Ext.globalEvents', // for compat with Ext JS 4.2 and earlier
  14. requires: [
  15. 'Ext.dom.Element'
  16. ],
  17. observableType: 'global',
  18. singleton: true,
  19. /**
  20. * @private
  21. */
  22. resizeBuffer: 100,
  23. /**
  24. * @event added
  25. * Fires when a Component is added to a Container.
  26. * @param {Ext.Component} component
  27. */
  28. /**
  29. * @event beforeresponsiveupdate
  30. * Fires before {@link Ext.mixin.Responsive} perform any updates in response to
  31. * dynamic changes. This is prior to refreshing `responsiveFormulas`.
  32. * @param {Object} context The context object used by `responsiveConfig` expressions.
  33. * @since 5.0.1
  34. */
  35. /**
  36. * @event beginresponsiveupdate
  37. * Fires when {@link Ext.mixin.Responsive} is about to perform updates in response to
  38. * dynamic changes. At this point all `responsiveFormulas` have been refreshed.
  39. * @param {Object} context The context object used by `responsiveConfig` expressions.
  40. * @since 5.0.1
  41. */
  42. /**
  43. * @event responsiveupdate
  44. * Fires after {@link Ext.mixin.Responsive} has performed updates in response to
  45. * dynamic changes.
  46. * @param {Object} context The context object used by `responsiveConfig` expressions.
  47. * @since 5.0.1
  48. */
  49. /**
  50. * @event collapse
  51. * Fires when a Component is collapsed (e.g., a panel).
  52. * @param {Ext.Component} component
  53. */
  54. /**
  55. * @event expand
  56. * Fires when a Component is expanded (e.g., a panel).
  57. * @param {Ext.Component} component
  58. */
  59. /**
  60. * @event hide
  61. * Fires when a Component is hidden.
  62. * @param {Ext.Component} component
  63. */
  64. /**
  65. * @event idle
  66. * Fires when an event handler finishes its run, just before returning to
  67. * browser control.
  68. *
  69. * This includes DOM event handlers, Ajax (including JSONP) event handlers,
  70. * and {@link Ext.util.TaskRunner TaskRunners}
  71. *
  72. * When called at the tail of a DOM event, the event object is passed as the
  73. * sole parameter.
  74. *
  75. * This can be useful for performing cleanup, or update tasks which need to
  76. * happen only after all code in an event handler has been run, but which
  77. * should not be executed in a timer due to the intervening browser
  78. * reflow/repaint which would take place.
  79. */
  80. /**
  81. * @event onlinechange
  82. * Fires when the online status of the page changes. See {@link Ext#method-isOnline}
  83. * @param {Boolean} online `true` if in an online state.
  84. *
  85. * @since 6.2.1
  86. */
  87. /**
  88. * @event removed
  89. * Fires when a Component is removed from a Container.
  90. * @param {Ext.Component} component
  91. */
  92. /**
  93. * @event resize
  94. * Fires when the browser window is resized. To avoid running resize handlers
  95. * too often resulting in sluggish window resizing, the resize event uses a buffer
  96. * of 100 milliseconds in the Classic toolkit, and fires on animation frame
  97. * in the Modern toolkit.
  98. * @param {Number} width The new width
  99. * @param {Number} height The new height
  100. */
  101. /**
  102. * @event show
  103. * Fires when a Component is shown.
  104. * @param {Ext.Component} component
  105. */
  106. /**
  107. * @event beforebindnotify
  108. * Fires before a scheduled set of bindings are fired. This allows interested parties
  109. * to react and do any required work.
  110. * @param {Ext.util.Scheduler} scheduler The scheduler triggering the bindings.
  111. *
  112. * @private
  113. * @since 5.1.0
  114. */
  115. /**
  116. * @event mousedown
  117. * A mousedown listener on the document that is immune to stopPropagation()
  118. * used in cases where we need to know if a mousedown event occurred on the
  119. * document regardless of whether some other handler tried to stop it. An
  120. * example where this is useful is a menu that needs to be hidden whenever
  121. * there is a mousedown event on the document.
  122. * @param {Ext.event.Event} e The event object
  123. */
  124. /**
  125. * @event mouseup
  126. * A mouseup listener on the document that is immune to stopPropagation()
  127. * used in cases where we need to know if a mouseup event occurred on the
  128. * document regardless of whether some other handler tried to stop it. An
  129. * example where this is useful is a component which enters a "pressed" state
  130. * upon mousedown, and needs to exit that state even if the mouse exits
  131. * before being released.
  132. * @param {Ext.event.Event} e The event object
  133. */
  134. /**
  135. * @property {Object} idleEventMask
  136. * This object holds event names for events that should not trigger an `idle` event
  137. * following their dispatch.
  138. * @private
  139. * @since 5.0.0
  140. */
  141. idleEventMask: {
  142. mousemove: 1,
  143. touchmove: 1,
  144. pointermove: 1,
  145. MSPointerMove: 1,
  146. unload: 1
  147. },
  148. // @private
  149. windowListeners: {
  150. resize: {
  151. fn: 'fireResize'
  152. }
  153. },
  154. constructor: function() {
  155. var me = this;
  156. me.callParent();
  157. Ext.onInternalReady(function() {
  158. // using a closure here instead of attaching the event directly to the
  159. // attachListeners method gives us a chance to override the method
  160. me.attachListeners();
  161. });
  162. },
  163. setPressedComponent: function(component, e) {
  164. var me = this,
  165. pressedComponent = me.pressedComponent;
  166. if (pressedComponent && pressedComponent.onRelease) {
  167. pressedComponent.onRelease(e);
  168. }
  169. me.pressedComponent = component;
  170. if (component) {
  171. me.pressedScrollStart = Ext.on({
  172. scrollstart: function () {
  173. me.setPressedComponent(null, e);
  174. },
  175. destroyable: true
  176. });
  177. }
  178. else {
  179. me.pressedScrollStart = Ext.destroy(me.pressedScrollStart);
  180. }
  181. },
  182. attachListeners: function() {
  183. var me = this,
  184. win = Ext.getWin(),
  185. winListeners = me.windowListeners;
  186. me.onlineState = Ext.isOnline();
  187. // Capture width/height to compare later in fireResize
  188. me.curHeight = Ext.Element.getViewportHeight();
  189. me.curWidth = Ext.Element.getViewportWidth();
  190. win.on({
  191. scope: me,
  192. online: 'handleOnlineChange',
  193. offline: 'handleOnlineChange'
  194. });
  195. // This function is not entirely harmless but since it is not directly related
  196. // to any component, element, or other destructible entity and effectively cannot
  197. // be cleaned up, we have to pretend it's OK for this timer to go unnoticed.
  198. //<debug>
  199. me.fireResize.$skipTimerCheck = true;
  200. //</debug>
  201. // IE8 does its own thing
  202. if (winListeners) {
  203. winListeners.scope = me;
  204. // CSS layouts only require buffering to the next animation frame
  205. if (Ext.isModern) {
  206. winListeners.resize.onFrame = true;
  207. }
  208. else {
  209. winListeners.resize.buffer = me.resizeBuffer;
  210. }
  211. win.on(winListeners);
  212. }
  213. Ext.getDoc().on({
  214. touchstart: 'fireMouseDown',
  215. mousedown: 'fireMouseDown',
  216. mouseup: 'fireMouseUp',
  217. touchend: 'fireMouseUp',
  218. drop: 'fireMouseUp',
  219. dragend: 'fireMouseUp',
  220. scope: me
  221. });
  222. },
  223. fireMouseDown: function(e) {
  224. this.fireEvent('mousedown', e);
  225. // Synchronize floated component ordering.
  226. // Note that this is an ASAP method and will complete asynchronously
  227. // after this event has finished.
  228. Ext.ComponentManager.handleDocumentMouseDown(e);
  229. },
  230. fireMouseUp: function(e) {
  231. this.fireEvent('mouseup', e);
  232. this.setPressedComponent(null, e);
  233. },
  234. fireResize: function() {
  235. var me = this,
  236. Element = Ext.Element,
  237. w = Element.getViewportWidth(),
  238. h = Element.getViewportHeight();
  239. // In IE the resize event will sometimes fire even though the w/h are the same.
  240. if (me.curHeight !== h || me.curWidth !== w) {
  241. me.curHeight = h;
  242. me.curWidth = w;
  243. if (me.hasListeners.resize) {
  244. me.fireEvent('resize', w, h);
  245. }
  246. }
  247. },
  248. handleOnlineChange: function() {
  249. var online = Ext.isOnline();
  250. if (online !== this.onlineState) {
  251. this.onlineState = online;
  252. this.fireEvent('onlinechange', online);
  253. }
  254. }
  255. }, function(GlobalEvents) {
  256. /**
  257. * @member Ext
  258. * @method on
  259. * Shorthand for {@link Ext.GlobalEvents#addListener}.
  260. * @inheritdoc Ext.mixin.Observable#addListener
  261. */
  262. Ext.on = function() {
  263. return GlobalEvents.addListener.apply(GlobalEvents, arguments);
  264. };
  265. /**
  266. * @member Ext
  267. * @method un
  268. * Shorthand for {@link Ext.GlobalEvents#removeListener}.
  269. * @inheritdoc Ext.mixin.Observable#removeListener
  270. */
  271. Ext.un = function() {
  272. return GlobalEvents.removeListener.apply(GlobalEvents, arguments);
  273. };
  274. /**
  275. * @member Ext
  276. * @method fireEvent
  277. * Shorthand for {@link Ext.GlobalEvents#fireEvent}.
  278. * @inheritdoc Ext.mixin.Observable#fireEvent
  279. *
  280. * @since 6.2.0
  281. */
  282. Ext.fireEvent = function() {
  283. return GlobalEvents.fireEvent.apply(GlobalEvents, arguments);
  284. };
  285. /**
  286. * @member Ext
  287. * @method fireIdle
  288. * Fires the global `idle` event if there are any listeners registered.
  289. *
  290. * @since 6.5.1
  291. * @private
  292. */
  293. Ext.fireIdle = function () {
  294. if (GlobalEvents.hasListeners.idle && !Ext._suppressIdle) {
  295. GlobalEvents.fireEventArgs('idle');
  296. }
  297. Ext._suppressIdle = false;
  298. };
  299. Ext._suppressIdle = false;
  300. });