Best JavaScript code snippet using stryker-parent
eventtargettester.js
Source:eventtargettester.js
1// Copyright 2012 The Closure Library Authors. All Rights Reserved.2//3// Licensed under the Apache License, Version 2.0 (the "License");4// you may not use this file except in compliance with the License.5// You may obtain a copy of the License at6//7// http://www.apache.org/licenses/LICENSE-2.08//9// Unless required by applicable law or agreed to in writing, software10// distributed under the License is distributed on an "AS-IS" BASIS,11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.12// See the License for the specific language governing permissions and13// limitations under the License.14/**15 * @fileoverview goog.events.EventTarget tester.16 */17goog.provide('goog.events.eventTargetTester');18goog.setTestOnly('goog.events.eventTargetTester');19goog.provide('goog.events.eventTargetTester.KeyType');20goog.setTestOnly('goog.events.eventTargetTester.KeyType');21goog.provide('goog.events.eventTargetTester.UnlistenReturnType');22goog.setTestOnly('goog.events.eventTargetTester.UnlistenReturnType');23goog.require('goog.array');24goog.require('goog.events');25goog.require('goog.events.Event');26goog.require('goog.events.EventTarget');27goog.require('goog.testing.asserts');28goog.require('goog.testing.recordFunction');29/**30 * Setup step for the test functions. This needs to be called from the31 * test setUp.32 * @param {function():!goog.events.Listenable} listenableFactoryFn Function33 * that will return a new Listenable instance each time it is called.34 * @param {Function} listenFn Function that, given the same signature35 * as goog.events.listen, will add listener to the given event36 * target.37 * @param {Function} unlistenFn Function that, given the same38 * signature as goog.events.unlisten, will remove listener from39 * the given event target.40 * @param {Function} unlistenByKeyFn Function that, given 241 * parameters: src and key, will remove the corresponding42 * listener.43 * @param {Function} listenOnceFn Function that, given the same44 * signature as goog.events.listenOnce, will add a one-time45 * listener to the given event target.46 * @param {Function} dispatchEventFn Function that, given the same47 * signature as goog.events.dispatchEvent, will dispatch the event48 * on the given event target.49 * @param {Function} removeAllFn Function that, given the same50 * signature as goog.events.removeAll, will remove all listeners51 * according to the contract of goog.events.removeAll.52 * @param {Function} getListenersFn Function that, given the same53 * signature as goog.events.getListeners, will retrieve listeners.54 * @param {Function} getListenerFn Function that, given the same55 * signature as goog.events.getListener, will retrieve the56 * listener object.57 * @param {Function} hasListenerFn Function that, given the same58 * signature as goog.events.hasListener, will determine whether59 * listeners exist.60 * @param {goog.events.eventTargetTester.KeyType} listenKeyType The61 * key type returned by listen call.62 * @param {goog.events.eventTargetTester.UnlistenReturnType}63 * unlistenFnReturnType64 * Whether we should check return value from65 * unlisten call. If unlisten does not return a value, this should66 * be set to false.67 * @param {boolean} objectListenerSupported Whether listener of type68 * Object is supported.69 */70goog.events.eventTargetTester.setUp = function(71 listenableFactoryFn,72 listenFn, unlistenFn, unlistenByKeyFn, listenOnceFn,73 dispatchEventFn, removeAllFn,74 getListenersFn, getListenerFn, hasListenerFn,75 listenKeyType, unlistenFnReturnType, objectListenerSupported) {76 listenableFactory = listenableFactoryFn;77 listen = listenFn;78 unlisten = unlistenFn;79 unlistenByKey = unlistenByKeyFn;80 listenOnce = listenOnceFn;81 dispatchEvent = dispatchEventFn;82 removeAll = removeAllFn;83 getListeners = getListenersFn;84 getListener = getListenerFn;85 hasListener = hasListenerFn;86 keyType = listenKeyType;87 unlistenReturnType = unlistenFnReturnType;88 objectTypeListenerSupported = objectListenerSupported;89 listeners = [];90 for (var i = 0; i < goog.events.eventTargetTester.MAX_; i++) {91 listeners[i] = createListener();92 }93 eventTargets = [];94 for (i = 0; i < goog.events.eventTargetTester.MAX_; i++) {95 eventTargets[i] = listenableFactory();96 }97};98/**99 * Teardown step for the test functions. This needs to be called from100 * test teardown.101 */102goog.events.eventTargetTester.tearDown = function() {103 for (var i = 0; i < goog.events.eventTargetTester.MAX_; i++) {104 goog.dispose(eventTargets[i]);105 }106};107/**108 * The type of key returned by key-returning functions (listen).109 * @enum {number}110 */111goog.events.eventTargetTester.KeyType = {112 /**113 * Returns number for key.114 */115 NUMBER: 0,116 /**117 * Returns undefined (no return value).118 */119 UNDEFINED: 1120};121/**122 * The type of unlisten function's return value.123 */124goog.events.eventTargetTester.UnlistenReturnType = {125 /**126 * Returns boolean indicating whether unlisten is successful.127 */128 BOOLEAN: 0,129 /**130 * Returns undefind (no return value).131 */132 UNDEFINED: 1133};134/**135 * Expando property used on "listener" function to determine if a136 * listener has already been checked. This is what allows us to137 * implement assertNoOtherListenerIsCalled.138 * @type {string}139 */140goog.events.eventTargetTester.ALREADY_CHECKED_PROP = '__alreadyChecked';141/**142 * Expando property used on "listener" function to record the number143 * of times it has been called the last time assertListenerIsCalled is144 * done. This allows us to verify that it has not been called more145 * times in assertNoOtherListenerIsCalled.146 */147goog.events.eventTargetTester.NUM_CALLED_PROP = '__numCalled';148/**149 * The maximum number of initialized event targets (in eventTargets150 * array) and listeners (in listeners array).151 * @type {number}152 * @private153 */154goog.events.eventTargetTester.MAX_ = 10;155/**156 * Contains test event types.157 * @enum {string}158 */159var EventType = {160 A: goog.events.getUniqueId('a'),161 B: goog.events.getUniqueId('b'),162 C: goog.events.getUniqueId('c')163};164var listen, unlisten, unlistenByKey, listenOnce, dispatchEvent;165var removeAll, getListeners, getListener, hasListener;166var keyType, unlistenReturnType, objectTypeListenerSupported;167var eventTargets, listeners;168/**169 * Custom event object for testing.170 * @constructor171 * @extends {goog.events.Event}172 */173var TestEvent = function() {174 goog.base(this, EventType.A);175};176goog.inherits(TestEvent, goog.events.Event);177/**178 * Creates a listener that executes the given function (optional).179 * @param {!Function=} opt_listenerFn The optional function to execute.180 * @return {!Function} The listener function.181 */182function createListener(opt_listenerFn) {183 return goog.testing.recordFunction(opt_listenerFn);184}185/**186 * Asserts that the given listener is called numCount number of times.187 * @param {!Function} listener The listener to check.188 * @param {number} numCount The number of times. See also the times()189 * function below.190 */191function assertListenerIsCalled(listener, numCount) {192 assertEquals('Listeners is not called the correct number of times.',193 numCount, listener.getCallCount());194 listener[goog.events.eventTargetTester.ALREADY_CHECKED_PROP] = true;195 listener[goog.events.eventTargetTester.NUM_CALLED_PROP] = numCount;196}197/**198 * Asserts that no other listeners, other than those verified via199 * assertListenerIsCalled, have been called since the last200 * resetListeners().201 */202function assertNoOtherListenerIsCalled() {203 goog.array.forEach(listeners, function(l, index) {204 if (!l[goog.events.eventTargetTester.ALREADY_CHECKED_PROP]) {205 assertEquals(206 'Listeners ' + index + ' is unexpectedly called.',207 0, l.getCallCount());208 } else {209 assertEquals(210 'Listeners ' + index + ' is unexpectedly called.',211 l[goog.events.eventTargetTester.NUM_CALLED_PROP], l.getCallCount());212 }213 });214}215/**216 * Resets all listeners call count to 0.217 */218function resetListeners() {219 goog.array.forEach(listeners, function(l) {220 l.reset();221 l[goog.events.eventTargetTester.ALREADY_CHECKED_PROP] = false;222 });223}224/**225 * The number of times a listener should have been executed. This226 * exists to make assertListenerIsCalled more readable. This is used227 * like so: assertListenerIsCalled(listener, times(2));228 * @param {number} n The number of times a listener should have been229 * executed.230 * @return {number} The number n.231 */232function times(n) {233 return n;234}235function testNoListener() {236 dispatchEvent(eventTargets[0], EventType.A);237 assertNoOtherListenerIsCalled();238}239function testOneListener() {240 listen(eventTargets[0], EventType.A, listeners[0]);241 dispatchEvent(eventTargets[0], EventType.A);242 assertListenerIsCalled(listeners[0], times(1));243 assertNoOtherListenerIsCalled();244 resetListeners();245 dispatchEvent(eventTargets[0], EventType.B);246 dispatchEvent(eventTargets[0], EventType.C);247 assertNoOtherListenerIsCalled();248}249function testTwoListenersOfSameType() {250 var key1 = listen(eventTargets[0], EventType.A, listeners[0]);251 var key2 = listen(eventTargets[0], EventType.A, listeners[1]);252 if (keyType == goog.events.eventTargetTester.KeyType.NUMBER) {253 assertNotEquals(key1, key2);254 } else {255 assertUndefined(key1);256 assertUndefined(key2);257 }258 dispatchEvent(eventTargets[0], EventType.A);259 assertListenerIsCalled(listeners[0], times(1));260 assertListenerIsCalled(listeners[1], times(1));261 assertNoOtherListenerIsCalled();262}263function testInstallingSameListeners() {264 var key1 = listen(eventTargets[0], EventType.A, listeners[0]);265 var key2 = listen(eventTargets[0], EventType.A, listeners[0]);266 var key3 = listen(eventTargets[0], EventType.B, listeners[0]);267 if (keyType == goog.events.eventTargetTester.KeyType.NUMBER) {268 assertEquals(key1, key2);269 assertNotEquals(key1, key3);270 } else {271 assertUndefined(key1);272 assertUndefined(key2);273 assertUndefined(key3);274 }275 dispatchEvent(eventTargets[0], EventType.A);276 assertListenerIsCalled(listeners[0], times(1));277 dispatchEvent(eventTargets[0], EventType.B);278 assertListenerIsCalled(listeners[0], times(2));279 assertNoOtherListenerIsCalled();280}281function testScope() {282 listeners[0] = createListener(function(e) {283 assertEquals('Wrong scope with undefined scope', eventTargets[0], this);284 });285 listeners[1] = createListener(function(e) {286 assertEquals('Wrong scope with null scope', eventTargets[0], this);287 });288 var scope = {};289 listeners[2] = createListener(function(e) {290 assertEquals('Wrong scope with specific scope object', scope, this);291 });292 listen(eventTargets[0], EventType.A, listeners[0]);293 listen(eventTargets[0], EventType.A, listeners[1], false, null);294 listen(eventTargets[0], EventType.A, listeners[2], false, scope);295 dispatchEvent(eventTargets[0], EventType.A);296 assertListenerIsCalled(listeners[0], times(1));297 assertListenerIsCalled(listeners[1], times(1));298 assertListenerIsCalled(listeners[2], times(1));299}300function testDispatchEventDoesNotThrowWithDisposedEventTarget() {301 goog.dispose(eventTargets[0]);302 assertTrue(dispatchEvent(eventTargets[0], EventType.A));303}304function testDispatchEventWithObjectLiteral() {305 listen(eventTargets[0], EventType.A, listeners[0]);306 assertTrue(dispatchEvent(eventTargets[0], {type: EventType.A}));307 assertListenerIsCalled(listeners[0], times(1));308 assertNoOtherListenerIsCalled();309}310function testDispatchEventWithCustomEventObject() {311 listen(eventTargets[0], EventType.A, listeners[0]);312 var e = new TestEvent();313 assertTrue(dispatchEvent(eventTargets[0], e));314 assertListenerIsCalled(listeners[0], times(1));315 assertNoOtherListenerIsCalled();316 var actualEvent = listeners[0].getLastCall().getArgument(0);317 assertEquals(e, actualEvent);318 assertEquals(eventTargets[0], actualEvent.target);319}320function testDisposingEventTargetRemovesListeners() {321 if (!(listenableFactory() instanceof goog.events.EventTarget)) {322 return;323 }324 listen(eventTargets[0], EventType.A, listeners[0]);325 goog.dispose(eventTargets[0]);326 dispatchEvent(eventTargets[0], EventType.A);327 assertNoOtherListenerIsCalled();328}329/**330 * Unlisten/unlistenByKey should still work after disposal. There are331 * many circumstances when this is actually necessary. For example, a332 * user may have listened to an event target and stored the key333 * (e.g. in a goog.events.EventHandler) and only unlisten after the334 * target has been disposed.335 */336function testUnlistenWorksAfterDisposal() {337 var key = listen(eventTargets[0], EventType.A, listeners[0]);338 goog.dispose(eventTargets[0]);339 unlisten(eventTargets[0], EventType.A, listeners[1]);340 if (unlistenByKey) {341 unlistenByKey(eventTargets[0], key);342 }343}344function testRemovingListener() {345 var ret1 = unlisten(eventTargets[0], EventType.A, listeners[0]);346 listen(eventTargets[0], EventType.A, listeners[0]);347 var ret2 = unlisten(eventTargets[0], EventType.A, listeners[1]);348 var ret3 = unlisten(eventTargets[0], EventType.B, listeners[0]);349 var ret4 = unlisten(eventTargets[1], EventType.A, listeners[0]);350 dispatchEvent(eventTargets[0], EventType.A);351 assertListenerIsCalled(listeners[0], times(1));352 var ret5 = unlisten(eventTargets[0], EventType.A, listeners[0]);353 var ret6 = unlisten(eventTargets[0], EventType.A, listeners[0]);354 dispatchEvent(eventTargets[0], EventType.A);355 assertListenerIsCalled(listeners[0], times(1));356 assertNoOtherListenerIsCalled();357 if (unlistenReturnType ==358 goog.events.eventTargetTester.UnlistenReturnType.BOOLEAN) {359 assertFalse(ret1);360 assertFalse(ret2);361 assertFalse(ret3);362 assertFalse(ret4);363 assertTrue(ret5);364 assertFalse(ret6);365 } else {366 assertUndefined(ret1);367 assertUndefined(ret2);368 assertUndefined(ret3);369 assertUndefined(ret4);370 assertUndefined(ret5);371 assertUndefined(ret6);372 }373}374function testCapture() {375 eventTargets[0].setParentEventTarget(eventTargets[1]);376 eventTargets[1].setParentEventTarget(eventTargets[2]);377 eventTargets[9].setParentEventTarget(eventTargets[0]);378 var ordering = 0;379 listeners[0] = createListener(380 function(e) {381 assertEquals(eventTargets[2], e.currentTarget);382 assertEquals(eventTargets[0], e.target);383 assertEquals('First capture listener is not called first', 0, ordering);384 ordering++;385 });386 listeners[1] = createListener(387 function(e) {388 assertEquals(eventTargets[1], e.currentTarget);389 assertEquals(eventTargets[0], e.target);390 assertEquals('2nd capture listener is not called 2nd', 1, ordering);391 ordering++;392 });393 listeners[2] = createListener(394 function(e) {395 assertEquals(eventTargets[0], e.currentTarget);396 assertEquals(eventTargets[0], e.target);397 assertEquals('3rd capture listener is not called 3rd', 2, ordering);398 ordering++;399 });400 listen(eventTargets[2], EventType.A, listeners[0], true);401 listen(eventTargets[1], EventType.A, listeners[1], true);402 listen(eventTargets[0], EventType.A, listeners[2], true);403 // These should not be called.404 listen(eventTargets[3], EventType.A, listeners[3], true);405 listen(eventTargets[0], EventType.B, listeners[4], true);406 listen(eventTargets[0], EventType.C, listeners[5], true);407 listen(eventTargets[1], EventType.B, listeners[6], true);408 listen(eventTargets[1], EventType.C, listeners[7], true);409 listen(eventTargets[2], EventType.B, listeners[8], true);410 listen(eventTargets[2], EventType.C, listeners[9], true);411 dispatchEvent(eventTargets[0], EventType.A);412 assertListenerIsCalled(listeners[0], times(1));413 assertListenerIsCalled(listeners[1], times(1));414 assertListenerIsCalled(listeners[2], times(1));415 assertNoOtherListenerIsCalled();416}417function testBubble() {418 eventTargets[0].setParentEventTarget(eventTargets[1]);419 eventTargets[1].setParentEventTarget(eventTargets[2]);420 eventTargets[9].setParentEventTarget(eventTargets[0]);421 var ordering = 0;422 listeners[0] = createListener(423 function(e) {424 assertEquals(eventTargets[0], e.currentTarget);425 assertEquals(eventTargets[0], e.target);426 assertEquals('First bubble listener is not called first', 0, ordering);427 ordering++;428 });429 listeners[1] = createListener(430 function(e) {431 assertEquals(eventTargets[1], e.currentTarget);432 assertEquals(eventTargets[0], e.target);433 assertEquals('2nd bubble listener is not called 2nd', 1, ordering);434 ordering++;435 });436 listeners[2] = createListener(437 function(e) {438 assertEquals(eventTargets[2], e.currentTarget);439 assertEquals(eventTargets[0], e.target);440 assertEquals('3rd bubble listener is not called 3rd', 2, ordering);441 ordering++;442 });443 listen(eventTargets[0], EventType.A, listeners[0]);444 listen(eventTargets[1], EventType.A, listeners[1]);445 listen(eventTargets[2], EventType.A, listeners[2]);446 // These should not be called.447 listen(eventTargets[3], EventType.A, listeners[3]);448 listen(eventTargets[0], EventType.B, listeners[4]);449 listen(eventTargets[0], EventType.C, listeners[5]);450 listen(eventTargets[1], EventType.B, listeners[6]);451 listen(eventTargets[1], EventType.C, listeners[7]);452 listen(eventTargets[2], EventType.B, listeners[8]);453 listen(eventTargets[2], EventType.C, listeners[9]);454 dispatchEvent(eventTargets[0], EventType.A);455 assertListenerIsCalled(listeners[0], times(1));456 assertListenerIsCalled(listeners[1], times(1));457 assertListenerIsCalled(listeners[2], times(1));458 assertNoOtherListenerIsCalled();459}460function testCaptureAndBubble() {461 eventTargets[0].setParentEventTarget(eventTargets[1]);462 eventTargets[1].setParentEventTarget(eventTargets[2]);463 listen(eventTargets[0], EventType.A, listeners[0], true);464 listen(eventTargets[1], EventType.A, listeners[1], true);465 listen(eventTargets[2], EventType.A, listeners[2], true);466 listen(eventTargets[0], EventType.A, listeners[3]);467 listen(eventTargets[1], EventType.A, listeners[4]);468 listen(eventTargets[2], EventType.A, listeners[5]);469 dispatchEvent(eventTargets[0], EventType.A);470 assertListenerIsCalled(listeners[0], times(1));471 assertListenerIsCalled(listeners[1], times(1));472 assertListenerIsCalled(listeners[2], times(1));473 assertListenerIsCalled(listeners[3], times(1));474 assertListenerIsCalled(listeners[4], times(1));475 assertListenerIsCalled(listeners[5], times(1));476 assertNoOtherListenerIsCalled();477}478function testPreventDefaultByReturningFalse() {479 listeners[0] = createListener(function(e) { return false; });480 listeners[1] = createListener(function(e) { return true; });481 listen(eventTargets[0], EventType.A, listeners[0]);482 listen(eventTargets[0], EventType.A, listeners[1]);483 var result = dispatchEvent(eventTargets[0], EventType.A);484 assertFalse(result);485}486function testPreventDefault() {487 listeners[0] = createListener(function(e) { e.preventDefault(); });488 listeners[1] = createListener(function(e) { return true; });489 listen(eventTargets[0], EventType.A, listeners[0]);490 listen(eventTargets[0], EventType.A, listeners[1]);491 var result = dispatchEvent(eventTargets[0], EventType.A);492 assertFalse(result);493}494function testPreventDefaultAtCapture() {495 listeners[0] = createListener(function(e) { e.preventDefault(); });496 listeners[1] = createListener(function(e) { return true; });497 listen(eventTargets[0], EventType.A, listeners[0], true);498 listen(eventTargets[0], EventType.A, listeners[1], true);499 var result = dispatchEvent(eventTargets[0], EventType.A);500 assertFalse(result);501}502function testStopPropagation() {503 eventTargets[0].setParentEventTarget(eventTargets[1]);504 eventTargets[1].setParentEventTarget(eventTargets[2]);505 listeners[0] = createListener(function(e) { e.stopPropagation(); });506 listen(eventTargets[0], EventType.A, listeners[0]);507 listen(eventTargets[0], EventType.A, listeners[1]);508 listen(eventTargets[1], EventType.A, listeners[2]);509 listen(eventTargets[2], EventType.A, listeners[3]);510 dispatchEvent(eventTargets[0], EventType.A);511 assertListenerIsCalled(listeners[0], times(1));512 assertListenerIsCalled(listeners[1], times(1));513 assertNoOtherListenerIsCalled();514}515function testStopPropagation2() {516 eventTargets[0].setParentEventTarget(eventTargets[1]);517 eventTargets[1].setParentEventTarget(eventTargets[2]);518 listeners[1] = createListener(function(e) { e.stopPropagation(); });519 listen(eventTargets[0], EventType.A, listeners[0]);520 listen(eventTargets[0], EventType.A, listeners[1]);521 listen(eventTargets[1], EventType.A, listeners[2]);522 listen(eventTargets[2], EventType.A, listeners[3]);523 dispatchEvent(eventTargets[0], EventType.A);524 assertListenerIsCalled(listeners[0], times(1));525 assertListenerIsCalled(listeners[1], times(1));526 assertNoOtherListenerIsCalled();527}528function testStopPropagation3() {529 eventTargets[0].setParentEventTarget(eventTargets[1]);530 eventTargets[1].setParentEventTarget(eventTargets[2]);531 listeners[2] = createListener(function(e) { e.stopPropagation(); });532 listen(eventTargets[0], EventType.A, listeners[0]);533 listen(eventTargets[0], EventType.A, listeners[1]);534 listen(eventTargets[1], EventType.A, listeners[2]);535 listen(eventTargets[2], EventType.A, listeners[3]);536 dispatchEvent(eventTargets[0], EventType.A);537 assertListenerIsCalled(listeners[0], times(1));538 assertListenerIsCalled(listeners[1], times(1));539 assertListenerIsCalled(listeners[2], times(1));540 assertNoOtherListenerIsCalled();541}542function testStopPropagationAtCapture() {543 eventTargets[0].setParentEventTarget(eventTargets[1]);544 eventTargets[1].setParentEventTarget(eventTargets[2]);545 listeners[0] = createListener(function(e) { e.stopPropagation(); });546 listen(eventTargets[2], EventType.A, listeners[0], true);547 listen(eventTargets[1], EventType.A, listeners[1], true);548 listen(eventTargets[0], EventType.A, listeners[2], true);549 listen(eventTargets[0], EventType.A, listeners[3]);550 listen(eventTargets[1], EventType.A, listeners[4]);551 listen(eventTargets[2], EventType.A, listeners[5]);552 dispatchEvent(eventTargets[0], EventType.A);553 assertListenerIsCalled(listeners[0], times(1));554 assertNoOtherListenerIsCalled();555}556function testHandleEvent() {557 if (!objectTypeListenerSupported) {558 return;559 }560 var obj = {};561 obj.handleEvent = goog.testing.recordFunction();562 listen(eventTargets[0], EventType.A, obj);563 dispatchEvent(eventTargets[0], EventType.A);564 assertEquals(1, obj.handleEvent.getCallCount());565}566function testListenOnce() {567 if (!listenOnce) {568 return;569 }570 listenOnce(eventTargets[0], EventType.A, listeners[0], true);571 listenOnce(eventTargets[0], EventType.A, listeners[1]);572 listenOnce(eventTargets[0], EventType.B, listeners[2]);573 dispatchEvent(eventTargets[0], EventType.A);574 assertListenerIsCalled(listeners[0], times(1));575 assertListenerIsCalled(listeners[1], times(1));576 assertListenerIsCalled(listeners[2], times(0));577 assertNoOtherListenerIsCalled();578 resetListeners();579 dispatchEvent(eventTargets[0], EventType.A);580 assertListenerIsCalled(listeners[0], times(0));581 assertListenerIsCalled(listeners[1], times(0));582 assertListenerIsCalled(listeners[2], times(0));583 dispatchEvent(eventTargets[0], EventType.B);584 assertListenerIsCalled(listeners[2], times(1));585 assertNoOtherListenerIsCalled();586}587function testUnlistenInListen() {588 listeners[1] = createListener(589 function(e) {590 unlisten(eventTargets[0], EventType.A, listeners[1]);591 unlisten(eventTargets[0], EventType.A, listeners[2]);592 });593 listen(eventTargets[0], EventType.A, listeners[0]);594 listen(eventTargets[0], EventType.A, listeners[1]);595 listen(eventTargets[0], EventType.A, listeners[2]);596 listen(eventTargets[0], EventType.A, listeners[3]);597 dispatchEvent(eventTargets[0], EventType.A);598 assertListenerIsCalled(listeners[0], times(1));599 assertListenerIsCalled(listeners[1], times(1));600 assertListenerIsCalled(listeners[2], times(0));601 assertListenerIsCalled(listeners[3], times(1));602 assertNoOtherListenerIsCalled();603 resetListeners();604 dispatchEvent(eventTargets[0], EventType.A);605 assertListenerIsCalled(listeners[0], times(1));606 assertListenerIsCalled(listeners[1], times(0));607 assertListenerIsCalled(listeners[2], times(0));608 assertListenerIsCalled(listeners[3], times(1));609 assertNoOtherListenerIsCalled();610}611function testUnlistenByKeyInListen() {612 if (!unlistenByKey) {613 return;614 }615 var key1, key2;616 listeners[1] = createListener(617 function(e) {618 unlistenByKey(eventTargets[0], key1);619 unlistenByKey(eventTargets[0], key2);620 });621 listen(eventTargets[0], EventType.A, listeners[0]);622 key1 = listen(eventTargets[0], EventType.A, listeners[1]);623 key2 = listen(eventTargets[0], EventType.A, listeners[2]);624 listen(eventTargets[0], EventType.A, listeners[3]);625 dispatchEvent(eventTargets[0], EventType.A);626 assertListenerIsCalled(listeners[0], times(1));627 assertListenerIsCalled(listeners[1], times(1));628 assertListenerIsCalled(listeners[2], times(0));629 assertListenerIsCalled(listeners[3], times(1));630 assertNoOtherListenerIsCalled();631 resetListeners();632 dispatchEvent(eventTargets[0], EventType.A);633 assertListenerIsCalled(listeners[0], times(1));634 assertListenerIsCalled(listeners[1], times(0));635 assertListenerIsCalled(listeners[2], times(0));636 assertListenerIsCalled(listeners[3], times(1));637 assertNoOtherListenerIsCalled();638}639function testSetParentEventTarget() {640 assertNull(eventTargets[0].getParentEventTarget());641 eventTargets[0].setParentEventTarget(eventTargets[1]);642 assertEquals(eventTargets[1], eventTargets[0].getParentEventTarget());643 assertNull(eventTargets[1].getParentEventTarget());644 eventTargets[0].setParentEventTarget(null);645 assertNull(eventTargets[0].getParentEventTarget());646}647function testListenOnceAfterListenDoesNotChangeExistingListener() {648 if (!listenOnce) {649 return;650 }651 listen(eventTargets[0], EventType.A, listeners[0]);652 listenOnce(eventTargets[0], EventType.A, listeners[0]);653 dispatchEvent(eventTargets[0], EventType.A);654 dispatchEvent(eventTargets[0], EventType.A);655 dispatchEvent(eventTargets[0], EventType.A);656 assertListenerIsCalled(listeners[0], times(3));657 assertNoOtherListenerIsCalled();658}659function testListenOnceAfterListenOnceDoesNotChangeExistingListener() {660 if (!listenOnce) {661 return;662 }663 listenOnce(eventTargets[0], EventType.A, listeners[0]);664 listenOnce(eventTargets[0], EventType.A, listeners[0]);665 dispatchEvent(eventTargets[0], EventType.A);666 dispatchEvent(eventTargets[0], EventType.A);667 dispatchEvent(eventTargets[0], EventType.A);668 assertListenerIsCalled(listeners[0], times(1));669 assertNoOtherListenerIsCalled();670}671function testListenAfterListenOnceRemoveOnceness() {672 if (!listenOnce) {673 return;674 }675 listenOnce(eventTargets[0], EventType.A, listeners[0]);676 listen(eventTargets[0], EventType.A, listeners[0]);677 dispatchEvent(eventTargets[0], EventType.A);678 dispatchEvent(eventTargets[0], EventType.A);679 dispatchEvent(eventTargets[0], EventType.A);680 assertListenerIsCalled(listeners[0], times(3));681 assertNoOtherListenerIsCalled();682}683function testUnlistenAfterListenOnce() {684 if (!listenOnce) {685 return;686 }687 listenOnce(eventTargets[0], EventType.A, listeners[0]);688 unlisten(eventTargets[0], EventType.A, listeners[0]);689 dispatchEvent(eventTargets[0], EventType.A);690 listen(eventTargets[0], EventType.A, listeners[0]);691 listenOnce(eventTargets[0], EventType.A, listeners[0]);692 unlisten(eventTargets[0], EventType.A, listeners[0]);693 dispatchEvent(eventTargets[0], EventType.A);694 listenOnce(eventTargets[0], EventType.A, listeners[0]);695 listen(eventTargets[0], EventType.A, listeners[0]);696 unlisten(eventTargets[0], EventType.A, listeners[0]);697 dispatchEvent(eventTargets[0], EventType.A);698 listenOnce(eventTargets[0], EventType.A, listeners[0]);699 listenOnce(eventTargets[0], EventType.A, listeners[0]);700 unlisten(eventTargets[0], EventType.A, listeners[0]);701 dispatchEvent(eventTargets[0], EventType.A);702 assertNoOtherListenerIsCalled();703}704function testRemoveAllWithType() {705 if (!removeAll) {706 return;707 }708 listen(eventTargets[0], EventType.A, listeners[0], true);709 listen(eventTargets[0], EventType.A, listeners[1]);710 listen(eventTargets[0], EventType.C, listeners[2], true);711 listen(eventTargets[0], EventType.C, listeners[3]);712 listen(eventTargets[0], EventType.B, listeners[4], true);713 listen(eventTargets[0], EventType.B, listeners[5], true);714 listen(eventTargets[0], EventType.B, listeners[6]);715 listen(eventTargets[0], EventType.B, listeners[7]);716 assertEquals(4, removeAll(eventTargets[0], EventType.B));717 dispatchEvent(eventTargets[0], EventType.A);718 dispatchEvent(eventTargets[0], EventType.B);719 dispatchEvent(eventTargets[0], EventType.C);720 assertListenerIsCalled(listeners[0], times(1));721 assertListenerIsCalled(listeners[1], times(1));722 assertListenerIsCalled(listeners[2], times(1));723 assertListenerIsCalled(listeners[3], times(1));724 assertNoOtherListenerIsCalled();725}726function testRemoveAll() {727 if (!removeAll) {728 return;729 }730 listen(eventTargets[0], EventType.A, listeners[0], true);731 listen(eventTargets[0], EventType.A, listeners[1]);732 listen(eventTargets[0], EventType.C, listeners[2], true);733 listen(eventTargets[0], EventType.C, listeners[3]);734 listen(eventTargets[0], EventType.B, listeners[4], true);735 listen(eventTargets[0], EventType.B, listeners[5], true);736 listen(eventTargets[0], EventType.B, listeners[6]);737 listen(eventTargets[0], EventType.B, listeners[7]);738 assertEquals(8, removeAll(eventTargets[0]));739 dispatchEvent(eventTargets[0], EventType.A);740 dispatchEvent(eventTargets[0], EventType.B);741 dispatchEvent(eventTargets[0], EventType.C);742 assertNoOtherListenerIsCalled();743}744function testRemoveAllCallsMarkAsRemoved() {745 if (!removeAll) {746 return;747 }748 var key0 = listen(eventTargets[0], EventType.A, listeners[0]);749 var key1 = listen(eventTargets[1], EventType.A, listeners[1]);750 assertNotNullNorUndefined(key0.listener);751 assertFalse(key0.removed);752 assertNotNullNorUndefined(key1.listener);753 assertFalse(key1.removed);754 assertEquals(1, removeAll(eventTargets[0]));755 assertNull(key0.listener);756 assertTrue(key0.removed);757 assertNotNullNorUndefined(key1.listener);758 assertFalse(key1.removed);759 assertEquals(1, removeAll(eventTargets[1]));760 assertNull(key1.listener);761 assertTrue(key1.removed);762}763function testGetListeners() {764 if (!getListeners) {765 return;766 }767 listen(eventTargets[0], EventType.A, listeners[0], true);768 listen(eventTargets[0], EventType.A, listeners[1], true);769 listen(eventTargets[0], EventType.A, listeners[2]);770 listen(eventTargets[0], EventType.A, listeners[3]);771 var l = getListeners(eventTargets[0], EventType.A, true);772 assertEquals(2, l.length);773 assertEquals(listeners[0], l[0].listener);774 assertEquals(listeners[1], l[1].listener);775 l = getListeners(eventTargets[0], EventType.A, false);776 assertEquals(2, l.length);777 assertEquals(listeners[2], l[0].listener);778 assertEquals(listeners[3], l[1].listener);779 l = getListeners(eventTargets[0], EventType.B, true);780 assertEquals(0, l.length);781}782function testGetListener() {783 if (!getListener) {784 return;785 }786 listen(eventTargets[0], EventType.A, listeners[0], true);787 assertNotNull(getListener(eventTargets[0], EventType.A, listeners[0], true));788 assertNull(789 getListener(eventTargets[0], EventType.A, listeners[0], true, {}));790 assertNull(getListener(eventTargets[1], EventType.A, listeners[0], true));791 assertNull(getListener(eventTargets[0], EventType.B, listeners[0], true));792 assertNull(getListener(eventTargets[0], EventType.A, listeners[1], true));793}794function testHasListener() {795 if (!hasListener) {796 return;797 }798 assertFalse(hasListener(eventTargets[0]));799 listen(eventTargets[0], EventType.A, listeners[0], true);800 assertTrue(hasListener(eventTargets[0]));801 assertTrue(hasListener(eventTargets[0], EventType.A));802 assertTrue(hasListener(eventTargets[0], EventType.A, true));803 assertTrue(hasListener(eventTargets[0], undefined, true));804 assertFalse(hasListener(eventTargets[0], EventType.A, false));805 assertFalse(hasListener(eventTargets[0], undefined, false));806 assertFalse(hasListener(eventTargets[0], EventType.B));807 assertFalse(hasListener(eventTargets[0], EventType.B, true));808 assertFalse(hasListener(eventTargets[1]));809}810function testFiringEventBeforeDisposeInternalWorks() {811 /**812 * @extends {goog.events.EventTarget}813 * @constructor814 */815 var MockTarget = function() {816 goog.base(this);817 };818 goog.inherits(MockTarget, goog.events.EventTarget);819 MockTarget.prototype.disposeInternal = function() {820 dispatchEvent(this, EventType.A);821 goog.base(this, 'disposeInternal');822 };823 var t = new MockTarget();824 try {825 listen(t, EventType.A, listeners[0]);826 t.dispose();827 assertListenerIsCalled(listeners[0], times(1));828 } catch (e) {829 goog.dispose(t);830 }831}832function testLoopDetection() {833 var target = listenableFactory();834 target.setParentEventTarget(target);835 try {836 target.dispatchEvent('string');837 fail('expected error');838 } catch (e) {839 assertContains('infinite', e.message);840 }...
PseudoEvents.js
Source:PseudoEvents.js
1/*!2 * ${copyright}3 */4sap.ui.define(['sap/ui/events/KeyCodes', 'sap/ui/thirdparty/jquery'], function(KeyCodes, jQuery) {5 "use strict";6 /**7 * @namespace8 * @since 1.589 * @alias module:sap/ui/events/PseudoEvents10 * @public11 */12 var PseudoEvents = {};13 /**14 * Convenience method to check an event for a certain combination of modifier keys15 *16 * @private17 */18 function checkModifierKeys(oEvent, bCtrlKey, bAltKey, bShiftKey) {19 return oEvent.shiftKey == bShiftKey && oEvent.altKey == bAltKey && getCtrlKey(oEvent) == bCtrlKey;20 }21 /**22 * Convenience method to check an event for any modifier key23 *24 * @private25 */26 function hasModifierKeys(oEvent) {27 return oEvent.shiftKey || oEvent.altKey || getCtrlKey(oEvent);28 }29 /**30 * Convenience method for handling of Ctrl key, meta key etc.31 *32 * @private33 */34 function getCtrlKey(oEvent) {35 return !!(oEvent.metaKey || oEvent.ctrlKey); // double negation doesn't have effect on boolean but ensures null and undefined are equivalent to false.36 }37 /**38 * Enumeration of all so called "pseudo events", a useful classification39 * of standard browser events as implied by SAP product standards.40 *41 * Whenever a browser event is recognized as one or more pseudo events, then this42 * classification is attached to the original {@link jQuery.Event} object and thereby43 * delivered to any jQuery-style listeners registered for that browser event.44 *45 * Pure JavaScript listeners can evaluate the classification information using46 * the {@link module:sap/ui/events/jquery/EventExtension#isPseudoType} method.47 *48 * Instead of using the procedure as described above, the SAPUI5 controls and elements49 * should simply implement an <code>on<i>pseudo-event</i>(oEvent)</code> method. It will50 * be invoked only when that specific pseudo event has been recognized. This simplifies event51 * dispatching even further.52 *53 * @enum {object}54 * @public55 */56 PseudoEvents.events = { // IMPORTANT: update the public documentation when extending this list57 /* Pseudo keyboard events */58 /**59 * Pseudo event for keyboard arrow down without modifiers (Ctrl, Alt or Shift)60 * @public61 */62 sapdown: {63 sName: "sapdown",64 aTypes: ["keydown"],65 fnCheck: function(oEvent) {66 return (oEvent.key ? (oEvent.key === "ArrowDown" || oEvent.key === "Down") : oEvent.keyCode == KeyCodes.ARROW_DOWN) && !hasModifierKeys(oEvent);67 }68 },69 /**70 * Pseudo event for keyboard arrow down with modifiers (Ctrl, Alt or Shift)71 * @public72 */73 sapdownmodifiers: {74 sName: "sapdownmodifiers",75 aTypes: ["keydown"],76 fnCheck: function(oEvent) {77 return (oEvent.key ? (oEvent.key === "ArrowDown" || oEvent.key === "Down") : oEvent.keyCode == KeyCodes.ARROW_DOWN) && hasModifierKeys(oEvent);78 }79 },80 /**81 * Pseudo event for pseudo 'show' event (F4, Alt + down-Arrow)82 * @public83 */84 sapshow: {85 sName: "sapshow",86 aTypes: ["keydown"],87 fnCheck: function(oEvent) {88 if (oEvent.key) {89 return (oEvent.key === "F4" && !hasModifierKeys(oEvent)) ||90 ((oEvent.key === "ArrowDown" || oEvent.key === "Down") && checkModifierKeys(oEvent, /*Ctrl*/ false, /*Alt*/ true, /*Shift*/ false));91 }92 return (oEvent.keyCode == KeyCodes.F4 && !hasModifierKeys(oEvent)) ||93 (oEvent.keyCode == KeyCodes.ARROW_DOWN && checkModifierKeys(oEvent, /*Ctrl*/ false, /*Alt*/ true, /*Shift*/ false));94 }95 },96 /**97 * Pseudo event for keyboard arrow up without modifiers (Ctrl, Alt or Shift)98 * @public99 */100 sapup: {101 sName: "sapup",102 aTypes: ["keydown"],103 fnCheck: function(oEvent) {104 return (oEvent.key ? (oEvent.key === "ArrowUp" || oEvent.key === "Up") : oEvent.keyCode == KeyCodes.ARROW_UP) && !hasModifierKeys(oEvent);105 }106 },107 /**108 * Pseudo event for keyboard arrow up with modifiers (Ctrl, Alt or Shift)109 * @public110 */111 sapupmodifiers: {112 sName: "sapupmodifiers",113 aTypes: ["keydown"],114 fnCheck: function(oEvent) {115 return (oEvent.key ? (oEvent.key === "ArrowUp" || oEvent.key === "Up") : oEvent.keyCode == KeyCodes.ARROW_UP) && hasModifierKeys(oEvent);116 }117 },118 /**119 * Pseudo event for pseudo 'hide' event (Alt + up-Arrow)120 * @public121 */122 saphide: {123 sName: "saphide",124 aTypes: ["keydown"],125 fnCheck: function(oEvent) {126 return (oEvent.key ? (oEvent.key === "ArrowUp" || oEvent.key === "Up") : oEvent.keyCode == KeyCodes.ARROW_UP) && checkModifierKeys(oEvent, /*Ctrl*/ false, /*Alt*/ true, /*Shift*/ false);127 }128 },129 /**130 * Pseudo event for keyboard arrow left without modifiers (Ctrl, Alt or Shift)131 * @public132 */133 sapleft: {134 sName: "sapleft",135 aTypes: ["keydown"],136 fnCheck: function(oEvent) {137 return (oEvent.key ? (oEvent.key === "ArrowLeft" || oEvent.key === "Left") : oEvent.keyCode == KeyCodes.ARROW_LEFT) && !hasModifierKeys(oEvent);138 }139 },140 /**141 * Pseudo event for keyboard arrow left with modifiers (Ctrl, Alt or Shift)142 * @public143 */144 sapleftmodifiers: {145 sName: "sapleftmodifiers",146 aTypes: ["keydown"],147 fnCheck: function(oEvent) {148 return (oEvent.key ? (oEvent.key === "ArrowLeft" || oEvent.key === "Left") : oEvent.keyCode == KeyCodes.ARROW_LEFT) && hasModifierKeys(oEvent);149 }150 },151 /**152 * Pseudo event for keyboard arrow right without modifiers (Ctrl, Alt or Shift)153 * @public154 */155 sapright: {156 sName: "sapright",157 aTypes: ["keydown"],158 fnCheck: function(oEvent) {159 return (oEvent.key ? (oEvent.key === "ArrowRight" || oEvent.key === "Right") : oEvent.keyCode == KeyCodes.ARROW_RIGHT) && !hasModifierKeys(oEvent);160 }161 },162 /**163 * Pseudo event for keyboard arrow right with modifiers (Ctrl, Alt or Shift)164 * @public165 */166 saprightmodifiers: {167 sName: "saprightmodifiers",168 aTypes: ["keydown"],169 fnCheck: function(oEvent) {170 return (oEvent.key ? (oEvent.key === "ArrowRight" || oEvent.key === "Right") : oEvent.keyCode == KeyCodes.ARROW_RIGHT) && hasModifierKeys(oEvent);171 }172 },173 /**174 * Pseudo event for keyboard Home/Pos1 with modifiers (Ctrl, Alt or Shift)175 * @public176 */177 saphome: {178 sName: "saphome",179 aTypes: ["keydown"],180 fnCheck: function(oEvent) {181 return (oEvent.key ? oEvent.key === "Home" : oEvent.keyCode == KeyCodes.HOME) && !hasModifierKeys(oEvent);182 }183 },184 /**185 * Pseudo event for keyboard Home/Pos1 without modifiers (Ctrl, Alt or Shift)186 * @public187 */188 saphomemodifiers: {189 sName: "saphomemodifiers",190 aTypes: ["keydown"],191 fnCheck: function(oEvent) {192 return (oEvent.key ? oEvent.key === "Home" : oEvent.keyCode == KeyCodes.HOME) && hasModifierKeys(oEvent);193 }194 },195 /**196 * Pseudo event for pseudo top event197 * @public198 */199 saptop: {200 sName: "saptop",201 aTypes: ["keydown"],202 fnCheck: function(oEvent) {203 return (oEvent.key ? oEvent.key === "Home" : oEvent.keyCode == KeyCodes.HOME) && checkModifierKeys(oEvent, /*Ctrl*/ true, /*Alt*/ false, /*Shift*/ false);204 }205 },206 /**207 * Pseudo event for keyboard End without modifiers (Ctrl, Alt or Shift)208 * @public209 */210 sapend: {211 sName: "sapend",212 aTypes: ["keydown"],213 fnCheck: function(oEvent) {214 return (oEvent.key ? oEvent.key === "End" : oEvent.keyCode == KeyCodes.END) && !hasModifierKeys(oEvent);215 }216 },217 /**218 * Pseudo event for keyboard End with modifiers (Ctrl, Alt or Shift)219 * @public220 */221 sapendmodifiers: {222 sName: "sapendmodifiers",223 aTypes: ["keydown"],224 fnCheck: function(oEvent) {225 return (oEvent.key ? oEvent.key === "End" : oEvent.keyCode == KeyCodes.END) && hasModifierKeys(oEvent);226 }227 },228 /**229 * Pseudo event for pseudo bottom event230 * @public231 */232 sapbottom: {233 sName: "sapbottom",234 aTypes: ["keydown"],235 fnCheck: function(oEvent) {236 return (oEvent.key ? oEvent.key === "End" : oEvent.keyCode == KeyCodes.END) && checkModifierKeys(oEvent, /*Ctrl*/ true, /*Alt*/ false, /*Shift*/ false);237 }238 },239 /**240 * Pseudo event for keyboard page up without modifiers (Ctrl, Alt or Shift)241 * @public242 */243 sappageup: {244 sName: "sappageup",245 aTypes: ["keydown"],246 fnCheck: function(oEvent) {247 return (oEvent.key ? oEvent.key === "PageUp" : oEvent.keyCode == KeyCodes.PAGE_UP) && !hasModifierKeys(oEvent);248 }249 },250 /**251 * Pseudo event for keyboard page up with modifiers (Ctrl, Alt or Shift)252 * @public253 */254 sappageupmodifiers: {255 sName: "sappageupmodifiers",256 aTypes: ["keydown"],257 fnCheck: function(oEvent) {258 return (oEvent.key ? oEvent.key === "PageUp" : oEvent.keyCode == KeyCodes.PAGE_UP) && hasModifierKeys(oEvent);259 }260 },261 /**262 * Pseudo event for keyboard page down without modifiers (Ctrl, Alt or Shift)263 * @public264 */265 sappagedown: {266 sName: "sappagedown",267 aTypes: ["keydown"],268 fnCheck: function(oEvent) {269 return (oEvent.key ? oEvent.key === "PageDown" : oEvent.keyCode == KeyCodes.PAGE_DOWN) && !hasModifierKeys(oEvent);270 }271 },272 /**273 * Pseudo event for keyboard page down with modifiers (Ctrl, Alt or Shift)274 * @public275 */276 sappagedownmodifiers: {277 sName: "sappagedownmodifiers",278 aTypes: ["keydown"],279 fnCheck: function(oEvent) {280 return (oEvent.key ? oEvent.key === "PageDown" : oEvent.keyCode == KeyCodes.PAGE_DOWN) && hasModifierKeys(oEvent);281 }282 },283 /**284 * Pseudo event for pseudo 'select' event... space, enter, ... without modifiers (Ctrl, Alt or Shift)285 * @public286 */287 sapselect: {288 sName: "sapselect",289 aTypes: ["keydown"],290 fnCheck: function(oEvent) {291 if (oEvent.key) {292 // "Spacebar" is IE only293 return (oEvent.key === "Enter" || oEvent.key === "Spacebar" || oEvent.key === " ") && !hasModifierKeys(oEvent);294 }295 return (oEvent.keyCode == KeyCodes.ENTER || oEvent.keyCode == KeyCodes.SPACE) && !hasModifierKeys(oEvent);296 }297 },298 /**299 * Pseudo event for pseudo 'select' event... space, enter, ... with modifiers (Ctrl, Alt or Shift)300 * @public301 */302 sapselectmodifiers: {303 sName: "sapselectmodifiers",304 aTypes: ["keydown"],305 fnCheck: function(oEvent) {306 if (oEvent.key) {307 // "Spacebar" is IE only308 return (oEvent.key === "Enter" || oEvent.key === "Spacebar" || oEvent.key === " ") && hasModifierKeys(oEvent);309 }310 return (oEvent.keyCode == KeyCodes.ENTER || oEvent.keyCode == KeyCodes.SPACE) && hasModifierKeys(oEvent);311 }312 },313 /**314 * Pseudo event for keyboard space without modifiers (Ctrl, Alt or Shift)315 * @public316 */317 sapspace: {318 sName: "sapspace",319 aTypes: ["keydown"],320 fnCheck: function(oEvent) {321 // "Spacebar" is IE only322 return (oEvent.key ? (oEvent.key === "Spacebar" || oEvent.key === " ") : oEvent.keyCode == KeyCodes.SPACE) && !hasModifierKeys(oEvent);323 }324 },325 /**326 * Pseudo event for keyboard space with modifiers (Ctrl, Alt or Shift)327 * @public328 */329 sapspacemodifiers: {330 sName: "sapspacemodifiers",331 aTypes: ["keydown"],332 fnCheck: function(oEvent) {333 // "Spacebar" is IE only334 return (oEvent.key ? (oEvent.key === "Spacebar" || oEvent.key === " ") : oEvent.keyCode == KeyCodes.SPACE) && hasModifierKeys(oEvent);335 }336 },337 /**338 * Pseudo event for keyboard enter without modifiers (Ctrl, Alt or Shift)339 * @public340 */341 sapenter: {342 sName: "sapenter",343 aTypes: ["keydown"],344 fnCheck: function(oEvent) {345 return (oEvent.key ? oEvent.key === "Enter" : oEvent.keyCode == KeyCodes.ENTER) && !hasModifierKeys(oEvent);346 }347 },348 /**349 * Pseudo event for keyboard enter with modifiers (Ctrl, Alt or Shift)350 * @public351 */352 sapentermodifiers: {353 sName: "sapentermodifiers",354 aTypes: ["keydown"],355 fnCheck: function(oEvent) {356 return (oEvent.key ? oEvent.key === "Enter" : oEvent.keyCode == KeyCodes.ENTER) && hasModifierKeys(oEvent);357 }358 },359 /**360 * Pseudo event for keyboard backspace without modifiers (Ctrl, Alt or Shift)361 * @public362 */363 sapbackspace: {364 sName: "sapbackspace",365 aTypes: ["keydown"],366 fnCheck: function(oEvent) {367 return (oEvent.key ? oEvent.key === "Backspace" : oEvent.keyCode == KeyCodes.BACKSPACE) && !hasModifierKeys(oEvent);368 }369 },370 /**371 * Pseudo event for keyboard backspace with modifiers (Ctrl, Alt or Shift)372 * @public373 */374 sapbackspacemodifiers: {375 sName: "sapbackspacemodifiers",376 aTypes: ["keydown"],377 fnCheck: function(oEvent) {378 return (oEvent.key ? oEvent.key === "Backspace" : oEvent.keyCode == KeyCodes.BACKSPACE) && hasModifierKeys(oEvent);379 }380 },381 /**382 * Pseudo event for keyboard delete without modifiers (Ctrl, Alt or Shift)383 * @public384 */385 sapdelete: {386 sName: "sapdelete",387 aTypes: ["keydown"],388 fnCheck: function(oEvent) {389 // "Del" is IE only390 return (oEvent.key ? oEvent.key === "Delete" || oEvent.key === "Del" : oEvent.keyCode == KeyCodes.DELETE) && !hasModifierKeys(oEvent);391 }392 },393 /**394 * Pseudo event for keyboard delete with modifiers (Ctrl, Alt or Shift)395 * @public396 */397 sapdeletemodifiers: {398 sName: "sapdeletemodifiers",399 aTypes: ["keydown"],400 fnCheck: function(oEvent) {401 // "Del" is IE only402 return (oEvent.key ? oEvent.key === "Delete" || oEvent.key === "Del" : oEvent.keyCode == KeyCodes.DELETE) && hasModifierKeys(oEvent);403 }404 },405 /**406 * Pseudo event for pseudo expand event (keyboard numpad +) without modifiers (Ctrl, Alt or Shift)407 * @public408 */409 sapexpand: {410 sName: "sapexpand",411 aTypes: ["keydown"],412 fnCheck: function(oEvent) {413 return (oEvent.key ? (oEvent.key === "+" || oEvent.key === "Add") && oEvent.location === "NUMPAD" : oEvent.keyCode == KeyCodes.NUMPAD_PLUS) && !hasModifierKeys(oEvent);414 }415 },416 /**417 * Pseudo event for pseudo expand event (keyboard numpad +) with modifiers (Ctrl, Alt or Shift)418 * @public419 */420 sapexpandmodifiers: {421 sName: "sapexpandmodifiers",422 aTypes: ["keydown"],423 fnCheck: function(oEvent) {424 return (oEvent.key ? (oEvent.key === "+" || oEvent.key === "Add") && oEvent.location === "NUMPAD" : oEvent.keyCode == KeyCodes.NUMPAD_PLUS) && hasModifierKeys(oEvent);425 }426 },427 /**428 * Pseudo event for pseudo collapse event (keyboard numpad -) without modifiers (Ctrl, Alt or Shift)429 * @public430 */431 sapcollapse: {432 sName: "sapcollapse",433 aTypes: ["keydown"],434 fnCheck: function(oEvent) {435 return (oEvent.key ? (oEvent.key === "-" || oEvent.key === "Subtract") && oEvent.location === "NUMPAD" : oEvent.keyCode == KeyCodes.NUMPAD_MINUS) && !hasModifierKeys(oEvent);436 }437 },438 /**439 * Pseudo event for pseudo collapse event (keyboard numpad -) with modifiers (Ctrl, Alt or Shift)440 * @public441 */442 sapcollapsemodifiers: {443 sName: "sapcollapsemodifiers",444 aTypes: ["keydown"],445 fnCheck: function(oEvent) {446 return (oEvent.key ? (oEvent.key === "-" || oEvent.key === "Subtract") && oEvent.location === "NUMPAD" : oEvent.keyCode == KeyCodes.NUMPAD_MINUS) && hasModifierKeys(oEvent);447 }448 },449 /**450 * Pseudo event for pseudo collapse event (keyboard numpad *)451 * @public452 */453 sapcollapseall: {454 sName: "sapcollapseall",455 aTypes: ["keydown"],456 fnCheck: function(oEvent) {457 return (oEvent.key ? (oEvent.key === "*" || oEvent.key === "Multiply") && oEvent.location === "NUMPAD" : oEvent.keyCode == KeyCodes.NUMPAD_ASTERISK) && !hasModifierKeys(oEvent);458 }459 },460 /**461 * Pseudo event for keyboard escape462 * @public463 */464 sapescape: {465 sName: "sapescape",466 aTypes: ["keydown"],467 fnCheck: function(oEvent) {468 // "Esc" is IE only469 return (oEvent.key ? oEvent.key === "Escape" || oEvent.key === "Esc" : oEvent.keyCode == KeyCodes.ESCAPE) && !hasModifierKeys(oEvent);470 }471 },472 /**473 * Pseudo event for keyboard tab (TAB + no modifier)474 * @public475 */476 saptabnext: {477 sName: "saptabnext",478 aTypes: ["keydown"],479 fnCheck: function(oEvent) {480 return (oEvent.key ? oEvent.key === "Tab" : oEvent.keyCode == KeyCodes.TAB) && !hasModifierKeys(oEvent);481 }482 },483 /**484 * Pseudo event for keyboard tab (TAB + shift modifier)485 * @public486 */487 saptabprevious: {488 sName: "saptabprevious",489 aTypes: ["keydown"],490 fnCheck: function(oEvent) {491 return (oEvent.key ? oEvent.key === "Tab" : oEvent.keyCode == KeyCodes.TAB) && checkModifierKeys(oEvent, /*Ctrl*/ false, /*Alt*/ false, /*Shift*/ true);492 }493 },494 /**495 * Pseudo event for pseudo skip forward (F6 + no modifier)496 * @public497 */498 sapskipforward: {499 sName: "sapskipforward",500 aTypes: ["keydown"],501 fnCheck: function(oEvent) {502 return (oEvent.key ? oEvent.key === "F6" : oEvent.keyCode == KeyCodes.F6) && !hasModifierKeys(oEvent);503 }504 },505 /**506 * Pseudo event for pseudo skip back (F6 + shift modifier)507 * @public508 */509 sapskipback: {510 sName: "sapskipback",511 aTypes: ["keydown"],512 fnCheck: function(oEvent) {513 return (oEvent.key ? oEvent.key === "F6" : oEvent.keyCode == KeyCodes.F6) && checkModifierKeys(oEvent, /*Ctrl*/ false, /*Alt*/ false, /*Shift*/ true);514 }515 },516 //// contextmenu Shift-F10 hack517 //{sName: "sapcontextmenu", aTypes: ["keydown"], fnCheck: function(oEvent) {518 // return oEvent.key === "F10" && checkModifierKeys(oEvent, /*Ctrl*/false, /*Alt*/false, /*Shift*/true);519 //}},520 /**521 * Pseudo event for pseudo 'decrease' event without modifiers (Ctrl, Alt or Shift)522 * @public523 */524 sapdecrease: {525 sName: "sapdecrease",526 aTypes: ["keydown"],527 fnCheck: function(oEvent) {528 var bRtl = sap.ui.getCore().getConfiguration().getRTL();529 if (oEvent.key) {530 if (bRtl) {531 return (oEvent.key === "ArrowRight" || oEvent.key === "Right" || oEvent.key === "ArrowDown" || oEvent.key === "Down") && !hasModifierKeys(oEvent);532 } else {533 return (oEvent.key === "ArrowLeft" || oEvent.key === "Left" || oEvent.key === "ArrowDown" || oEvent.key === "Down") && !hasModifierKeys(oEvent);534 }535 }536 var iPreviousKey = bRtl ? KeyCodes.ARROW_RIGHT : KeyCodes.ARROW_LEFT;537 return (oEvent.keyCode == iPreviousKey || oEvent.keyCode == KeyCodes.ARROW_DOWN) && !hasModifierKeys(oEvent);538 }539 },540 /**541 * Pseudo event for pressing the '-' (minus) sign.542 * @public543 */544 sapminus: {545 sName: "sapminus",546 aTypes: ["keypress"],547 fnCheck: function(oEvent) {548 return (oEvent.key ? (oEvent.key === '-' || oEvent.key === 'Subtract') : String.fromCharCode(oEvent.which) == '-');549 }550 },551 /**552 * Pseudo event for pseudo 'decrease' event with modifiers (Ctrl, Alt or Shift)553 * @public554 */555 sapdecreasemodifiers: {556 sName: "sapdecreasemodifiers",557 aTypes: ["keydown"],558 fnCheck: function(oEvent) {559 var bRtl = sap.ui.getCore().getConfiguration().getRTL();560 if (oEvent.key) {561 if (bRtl) {562 return (oEvent.key === "ArrowRight" || oEvent.key === "Right" || oEvent.key === "ArrowDown" || oEvent.key === "Down") && hasModifierKeys(oEvent);563 } else {564 return (oEvent.key === "ArrowLeft" || oEvent.key === "Left" || oEvent.key === "ArrowDown" || oEvent.key === "Down") && hasModifierKeys(oEvent);565 }566 }567 var iPreviousKey = bRtl ? KeyCodes.ARROW_RIGHT : KeyCodes.ARROW_LEFT;568 return (oEvent.keyCode == iPreviousKey || oEvent.keyCode == KeyCodes.ARROW_DOWN) && hasModifierKeys(oEvent);569 }570 },571 /**572 * Pseudo event for pseudo 'increase' event without modifiers (Ctrl, Alt or Shift)573 * @public574 */575 sapincrease: {576 sName: "sapincrease",577 aTypes: ["keydown"],578 fnCheck: function(oEvent) {579 var bRtl = sap.ui.getCore().getConfiguration().getRTL();580 var iNextKey;581 if (oEvent.key) {582 if (bRtl) {583 return (oEvent.key === "ArrowLeft" || oEvent.key === "Left" || oEvent.key === "ArrowUp" || oEvent.key === "Up") && !hasModifierKeys(oEvent);584 } else {585 return (oEvent.key === "ArrowRight" || oEvent.key === "Right" || oEvent.key === "ArrowUp" || oEvent.key === "Up") && !hasModifierKeys(oEvent);586 }587 }588 iNextKey = bRtl ? KeyCodes.ARROW_LEFT : KeyCodes.ARROW_RIGHT;589 return (oEvent.keyCode == iNextKey || oEvent.keyCode == KeyCodes.ARROW_UP) && !hasModifierKeys(oEvent);590 }591 },592 /**593 * Pseudo event for pressing the '+' (plus) sign.594 * @public595 */596 sapplus: {597 sName: "sapplus",598 aTypes: ["keypress"],599 fnCheck: function(oEvent) {600 return (oEvent.key ? (oEvent.key === '+' || oEvent.key === 'Add') : String.fromCharCode(oEvent.which) == '+');601 }602 },603 /**604 * Pseudo event for pseudo 'increase' event with modifiers (Ctrl, Alt or Shift)605 * @public606 */607 sapincreasemodifiers: {608 sName: "sapincreasemodifiers",609 aTypes: ["keydown"],610 fnCheck: function(oEvent) {611 var bRtl = sap.ui.getCore().getConfiguration().getRTL();612 if (oEvent.key) {613 if (bRtl) {614 return (oEvent.key === "ArrowLeft" || oEvent.key === "Left" || oEvent.key === "ArrowUp" || oEvent.key === "Up") && hasModifierKeys(oEvent);615 } else {616 return (oEvent.key === "ArrowRight" || oEvent.key === "Right" || oEvent.key === "ArrowUp" || oEvent.key === "Up") && hasModifierKeys(oEvent);617 }618 }619 var iNextKey = bRtl ? KeyCodes.ARROW_LEFT : KeyCodes.ARROW_RIGHT;620 return (oEvent.keyCode == iNextKey || oEvent.keyCode == KeyCodes.ARROW_UP) && hasModifierKeys(oEvent);621 }622 },623 /**624 * Pseudo event for pseudo 'previous' event without modifiers (Ctrl, Alt or Shift)625 * @public626 */627 sapprevious: {628 sName: "sapprevious",629 aTypes: ["keydown"],630 fnCheck: function(oEvent) {631 var bRtl = sap.ui.getCore().getConfiguration().getRTL();632 if (oEvent.key) {633 if (bRtl) {634 return (oEvent.key === "ArrowRight" || oEvent.key === "Right" || oEvent.key === "ArrowUp" || oEvent.key === "Up") && !hasModifierKeys(oEvent);635 } else {636 return (oEvent.key === "ArrowLeft" || oEvent.key === "Left" || oEvent.key === "ArrowUp" || oEvent.key === "Up") && !hasModifierKeys(oEvent);637 }638 }639 var iPreviousKey = bRtl ? KeyCodes.ARROW_RIGHT : KeyCodes.ARROW_LEFT;640 return (oEvent.keyCode == iPreviousKey || oEvent.keyCode == KeyCodes.ARROW_UP) && !hasModifierKeys(oEvent);641 }642 },643 /**644 * Pseudo event for pseudo 'previous' event with modifiers (Ctrl, Alt or Shift)645 * @public646 */647 sappreviousmodifiers: {648 sName: "sappreviousmodifiers",649 aTypes: ["keydown"],650 fnCheck: function(oEvent) {651 var bRtl = sap.ui.getCore().getConfiguration().getRTL();652 if (oEvent.key) {653 if (bRtl) {654 return (oEvent.key === "ArrowRight" || oEvent.key === "Right" || oEvent.key === "ArrowUp" || oEvent.key === "Up") && hasModifierKeys(oEvent);655 } else {656 return (oEvent.key === "ArrowLeft" || oEvent.key === "Left" || oEvent.key === "ArrowUp" || oEvent.key === "Up") && hasModifierKeys(oEvent);657 }658 }659 var iPreviousKey = bRtl ? KeyCodes.ARROW_RIGHT : KeyCodes.ARROW_LEFT;660 return (oEvent.keyCode == iPreviousKey || oEvent.keyCode == KeyCodes.ARROW_UP) && hasModifierKeys(oEvent);661 }662 },663 /**664 * Pseudo event for pseudo 'next' event without modifiers (Ctrl, Alt or Shift)665 * @public666 */667 sapnext: {668 sName: "sapnext",669 aTypes: ["keydown"],670 fnCheck: function(oEvent) {671 var bRtl = sap.ui.getCore().getConfiguration().getRTL();672 if (oEvent.key) {673 if (bRtl) {674 return (oEvent.key === "ArrowLeft" || oEvent.key === "Left" || oEvent.key === "ArrowDown" || oEvent.key === "Down") && !hasModifierKeys(oEvent);675 } else {676 return (oEvent.key === "ArrowRight" || oEvent.key === "Right" || oEvent.key === "ArrowDown" || oEvent.key === "Down") && !hasModifierKeys(oEvent);677 }678 }679 var iNextKey = bRtl ? KeyCodes.ARROW_LEFT : KeyCodes.ARROW_RIGHT;680 return (oEvent.keyCode == iNextKey || oEvent.keyCode == KeyCodes.ARROW_DOWN) && !hasModifierKeys(oEvent);681 }682 },683 /**684 * Pseudo event for pseudo 'next' event with modifiers (Ctrl, Alt or Shift)685 * @public686 */687 sapnextmodifiers: {688 sName: "sapnextmodifiers",689 aTypes: ["keydown"],690 fnCheck: function(oEvent) {691 var bRtl = sap.ui.getCore().getConfiguration().getRTL();692 if (oEvent.key) {693 if (bRtl) {694 return (oEvent.key === "ArrowLeft" || oEvent.key === "Left" || oEvent.key === "ArrowDown" || oEvent.key === "Down") && hasModifierKeys(oEvent);695 } else {696 return (oEvent.key === "ArrowRight" || oEvent.key === "Right" || oEvent.key === "ArrowDown" || oEvent.key === "Down") && hasModifierKeys(oEvent);697 }698 }699 var iNextKey = bRtl ? KeyCodes.ARROW_LEFT : KeyCodes.ARROW_RIGHT;700 return (oEvent.keyCode == iNextKey || oEvent.keyCode == KeyCodes.ARROW_DOWN) && hasModifierKeys(oEvent);701 }702 },703 //// pseudo hotkey event704 //{sName: "saphotkey", aTypes: ["keydown"], fnCheck: function(oEvent) {705 // return false;706 //}},707 /* TODO: hotkeys: all other events could be hotkeys708 if(UCF_KeyboardHelper.bIsValidHotkey(iKey, bCtrl, bAlt, bShift)) {709 if (iKey == KeyCodes.F1 && bNoModifiers) {710 //special handling for FF - in IE the help is handeled by onHelp711 if (UCF_System.sDevice == "ff1") {712 this.fireSapEvent(this.E_SAP_EVENTS.hotkey, oEvent);713 }714 }715 else if (bCtrlOnly && iKey == KeyCodes.C && document.selection) {716 //handle ctrl+c centrally if text is selected to allow to copy it instead of firing the hotkey717 var oTextRange = document.selection.createRange();718 if (!oTextRange || oTextRange.text.length <= 0) {719 this.fireSapEvent(this.E_SAP_EVENTS.hotkey, oEvent);720 }721 }722 else {723 this.fireSapEvent(this.E_SAP_EVENTS.hotkey, oEvent);724 }725 }726 */727 /*728 * Other pseudo events729 * @public730 */731 /**732 * Pseudo event indicating delayed double click (e.g. for inline edit)733 * @public734 */735 sapdelayeddoubleclick: {736 sName: "sapdelayeddoubleclick",737 aTypes: ["click"],738 fnCheck: function(oEvent) {739 var element = jQuery(oEvent.target);740 var currentTimestamp = oEvent.timeStamp;741 var data = element.data("sapdelayeddoubleclick_lastClickTimestamp");742 var lastTimestamp = data || 0;743 element.data("sapdelayeddoubleclick_lastClickTimestamp", currentTimestamp);744 var diff = currentTimestamp - lastTimestamp;745 return (diff >= 300 && diff <= 1300);746 }747 }748 };749 /**750 * Ordered array of the {@link module:sap/ui/events/PseudoEvents.events}.751 *752 * Order is significant as some check methods rely on the fact that they are tested before other methods.753 * The array is processed during event analysis (when classifying browser events as pseudo events).754 * @public755 */756 PseudoEvents.order = ["sapdown", "sapdownmodifiers", "sapshow", "sapup", "sapupmodifiers", "saphide", "sapleft", "sapleftmodifiers", "sapright", "saprightmodifiers", "saphome", "saphomemodifiers", "saptop", "sapend", "sapendmodifiers", "sapbottom", "sappageup", "sappageupmodifiers", "sappagedown", "sappagedownmodifiers", "sapselect", "sapselectmodifiers", "sapspace", "sapspacemodifiers", "sapenter", "sapentermodifiers", "sapexpand", "sapbackspace", "sapbackspacemodifiers", "sapdelete", "sapdeletemodifiers", "sapexpandmodifiers", "sapcollapse", "sapcollapsemodifiers", "sapcollapseall", "sapescape", "saptabnext", "saptabprevious", "sapskipforward", "sapskipback", "sapprevious", "sappreviousmodifiers", "sapnext", "sapnextmodifiers", "sapdecrease", "sapminus", "sapdecreasemodifiers", "sapincrease", "sapplus", "sapincreasemodifiers", "sapdelayeddoubleclick"];757 /**758 * Function for initialization of an Array containing all basic event types of the available pseudo events.759 * @private760 * @ui5-restricted sap.ui.core761 */762 PseudoEvents.getBasicTypes = function() {763 var mEvents = PseudoEvents.events,764 aResult = [];765 for (var sName in mEvents) {766 if (mEvents[sName].aTypes) {767 for (var j = 0, js = mEvents[sName].aTypes.length; j < js; j++) {768 var sType = mEvents[sName].aTypes[j];769 if (aResult.indexOf(sType) == -1) {770 aResult.push(sType);771 }772 }773 }774 }775 this.getBasicTypes = function() {776 return aResult.slice();777 };778 return aResult;779 };780 /**781 * Array containing all basic event types of the available pseudo events.782 * @private783 * @ui5-restricted sap.ui.core784 */785 PseudoEvents.addEvent = function(oEvent) {786 PseudoEvents.events[oEvent.sName] = oEvent;787 PseudoEvents.order.push(oEvent.sName);788 };789 return PseudoEvents;...
event-target-shim.mjs
Source:event-target-shim.mjs
1/**2 * @author Toru Nagashima <https://github.com/mysticatea>3 * @copyright 2015 Toru Nagashima. All rights reserved.4 * See LICENSE file in root directory for full license.5 */6/**7 * @typedef {object} PrivateData8 * @property {EventTarget} eventTarget The event target.9 * @property {{type:string}} event The original event object.10 * @property {number} eventPhase The current event phase.11 * @property {EventTarget|null} currentTarget The current event target.12 * @property {boolean} canceled The flag to prevent default.13 * @property {boolean} stopped The flag to stop propagation.14 * @property {boolean} immediateStopped The flag to stop propagation immediately.15 * @property {Function|null} passiveListener The listener if the current listener is passive. Otherwise this is null.16 * @property {number} timeStamp The unix time.17 * @private18 */19/**20 * Private data for event wrappers.21 * @type {WeakMap<Event, PrivateData>}22 * @private23 */24const privateData = new WeakMap();25/**26 * Cache for wrapper classes.27 * @type {WeakMap<Object, Function>}28 * @private29 */30const wrappers = new WeakMap();31/**32 * Get private data.33 * @param {Event} event The event object to get private data.34 * @returns {PrivateData} The private data of the event.35 * @private36 */37function pd(event) {38 const retv = privateData.get(event);39 console.assert(40 retv != null,41 "'this' is expected an Event object, but got",42 event43 );44 return retv45}46/**47 * https://dom.spec.whatwg.org/#set-the-canceled-flag48 * @param data {PrivateData} private data.49 */50function setCancelFlag(data) {51 if (data.passiveListener != null) {52 if (53 typeof console !== "undefined" &&54 typeof console.error === "function"55 ) {56 console.error(57 "Unable to preventDefault inside passive event listener invocation.",58 data.passiveListener59 );60 }61 return62 }63 if (!data.event.cancelable) {64 return65 }66 data.canceled = true;67 if (typeof data.event.preventDefault === "function") {68 data.event.preventDefault();69 }70}71/**72 * @see https://dom.spec.whatwg.org/#interface-event73 * @private74 */75/**76 * The event wrapper.77 * @constructor78 * @param {EventTarget} eventTarget The event target of this dispatching.79 * @param {Event|{type:string}} event The original event to wrap.80 */81function Event(eventTarget, event) {82 privateData.set(this, {83 eventTarget,84 event,85 eventPhase: 2,86 currentTarget: eventTarget,87 canceled: false,88 stopped: false,89 immediateStopped: false,90 passiveListener: null,91 timeStamp: event.timeStamp || Date.now(),92 });93 // https://heycam.github.io/webidl/#Unforgeable94 Object.defineProperty(this, "isTrusted", { value: false, enumerable: true });95 // Define accessors96 const keys = Object.keys(event);97 for (let i = 0; i < keys.length; ++i) {98 const key = keys[i];99 if (!(key in this)) {100 Object.defineProperty(this, key, defineRedirectDescriptor(key));101 }102 }103}104// Should be enumerable, but class methods are not enumerable.105Event.prototype = {106 /**107 * The type of this event.108 * @type {string}109 */110 get type() {111 return pd(this).event.type112 },113 /**114 * The target of this event.115 * @type {EventTarget}116 */117 get target() {118 return pd(this).eventTarget119 },120 /**121 * The target of this event.122 * @type {EventTarget}123 */124 get currentTarget() {125 return pd(this).currentTarget126 },127 /**128 * @returns {EventTarget[]} The composed path of this event.129 */130 composedPath() {131 const currentTarget = pd(this).currentTarget;132 if (currentTarget == null) {133 return []134 }135 return [currentTarget]136 },137 /**138 * Constant of NONE.139 * @type {number}140 */141 get NONE() {142 return 0143 },144 /**145 * Constant of CAPTURING_PHASE.146 * @type {number}147 */148 get CAPTURING_PHASE() {149 return 1150 },151 /**152 * Constant of AT_TARGET.153 * @type {number}154 */155 get AT_TARGET() {156 return 2157 },158 /**159 * Constant of BUBBLING_PHASE.160 * @type {number}161 */162 get BUBBLING_PHASE() {163 return 3164 },165 /**166 * The target of this event.167 * @type {number}168 */169 get eventPhase() {170 return pd(this).eventPhase171 },172 /**173 * Stop event bubbling.174 * @returns {void}175 */176 stopPropagation() {177 const data = pd(this);178 data.stopped = true;179 if (typeof data.event.stopPropagation === "function") {180 data.event.stopPropagation();181 }182 },183 /**184 * Stop event bubbling.185 * @returns {void}186 */187 stopImmediatePropagation() {188 const data = pd(this);189 data.stopped = true;190 data.immediateStopped = true;191 if (typeof data.event.stopImmediatePropagation === "function") {192 data.event.stopImmediatePropagation();193 }194 },195 /**196 * The flag to be bubbling.197 * @type {boolean}198 */199 get bubbles() {200 return Boolean(pd(this).event.bubbles)201 },202 /**203 * The flag to be cancelable.204 * @type {boolean}205 */206 get cancelable() {207 return Boolean(pd(this).event.cancelable)208 },209 /**210 * Cancel this event.211 * @returns {void}212 */213 preventDefault() {214 setCancelFlag(pd(this));215 },216 /**217 * The flag to indicate cancellation state.218 * @type {boolean}219 */220 get defaultPrevented() {221 return pd(this).canceled222 },223 /**224 * The flag to be composed.225 * @type {boolean}226 */227 get composed() {228 return Boolean(pd(this).event.composed)229 },230 /**231 * The unix time of this event.232 * @type {number}233 */234 get timeStamp() {235 return pd(this).timeStamp236 },237 /**238 * The target of this event.239 * @type {EventTarget}240 * @deprecated241 */242 get srcElement() {243 return pd(this).eventTarget244 },245 /**246 * The flag to stop event bubbling.247 * @type {boolean}248 * @deprecated249 */250 get cancelBubble() {251 return pd(this).stopped252 },253 set cancelBubble(value) {254 if (!value) {255 return256 }257 const data = pd(this);258 data.stopped = true;259 if (typeof data.event.cancelBubble === "boolean") {260 data.event.cancelBubble = true;261 }262 },263 /**264 * The flag to indicate cancellation state.265 * @type {boolean}266 * @deprecated267 */268 get returnValue() {269 return !pd(this).canceled270 },271 set returnValue(value) {272 if (!value) {273 setCancelFlag(pd(this));274 }275 },276 /**277 * Initialize this event object. But do nothing under event dispatching.278 * @param {string} type The event type.279 * @param {boolean} [bubbles=false] The flag to be possible to bubble up.280 * @param {boolean} [cancelable=false] The flag to be possible to cancel.281 * @deprecated282 */283 initEvent() {284 // Do nothing.285 },286};287// `constructor` is not enumerable.288Object.defineProperty(Event.prototype, "constructor", {289 value: Event,290 configurable: true,291 writable: true,292});293// Ensure `event instanceof window.Event` is `true`.294if (typeof window !== "undefined" && typeof window.Event !== "undefined") {295 Object.setPrototypeOf(Event.prototype, window.Event.prototype);296 // Make association for wrappers.297 wrappers.set(window.Event.prototype, Event);298}299/**300 * Get the property descriptor to redirect a given property.301 * @param {string} key Property name to define property descriptor.302 * @returns {PropertyDescriptor} The property descriptor to redirect the property.303 * @private304 */305function defineRedirectDescriptor(key) {306 return {307 get() {308 return pd(this).event[key]309 },310 set(value) {311 pd(this).event[key] = value;312 },313 configurable: true,314 enumerable: true,315 }316}317/**318 * Get the property descriptor to call a given method property.319 * @param {string} key Property name to define property descriptor.320 * @returns {PropertyDescriptor} The property descriptor to call the method property.321 * @private322 */323function defineCallDescriptor(key) {324 return {325 value() {326 const event = pd(this).event;327 return event[key].apply(event, arguments)328 },329 configurable: true,330 enumerable: true,331 }332}333/**334 * Define new wrapper class.335 * @param {Function} BaseEvent The base wrapper class.336 * @param {Object} proto The prototype of the original event.337 * @returns {Function} The defined wrapper class.338 * @private339 */340function defineWrapper(BaseEvent, proto) {341 const keys = Object.keys(proto);342 if (keys.length === 0) {343 return BaseEvent344 }345 /** CustomEvent */346 function CustomEvent(eventTarget, event) {347 BaseEvent.call(this, eventTarget, event);348 }349 CustomEvent.prototype = Object.create(BaseEvent.prototype, {350 constructor: { value: CustomEvent, configurable: true, writable: true },351 });352 // Define accessors.353 for (let i = 0; i < keys.length; ++i) {354 const key = keys[i];355 if (!(key in BaseEvent.prototype)) {356 const descriptor = Object.getOwnPropertyDescriptor(proto, key);357 const isFunc = typeof descriptor.value === "function";358 Object.defineProperty(359 CustomEvent.prototype,360 key,361 isFunc362 ? defineCallDescriptor(key)363 : defineRedirectDescriptor(key)364 );365 }366 }367 return CustomEvent368}369/**370 * Get the wrapper class of a given prototype.371 * @param {Object} proto The prototype of the original event to get its wrapper.372 * @returns {Function} The wrapper class.373 * @private374 */375function getWrapper(proto) {376 if (proto == null || proto === Object.prototype) {377 return Event378 }379 let wrapper = wrappers.get(proto);380 if (wrapper == null) {381 wrapper = defineWrapper(getWrapper(Object.getPrototypeOf(proto)), proto);382 wrappers.set(proto, wrapper);383 }384 return wrapper385}386/**387 * Wrap a given event to management a dispatching.388 * @param {EventTarget} eventTarget The event target of this dispatching.389 * @param {Object} event The event to wrap.390 * @returns {Event} The wrapper instance.391 * @private392 */393function wrapEvent(eventTarget, event) {394 const Wrapper = getWrapper(Object.getPrototypeOf(event));395 return new Wrapper(eventTarget, event)396}397/**398 * Get the immediateStopped flag of a given event.399 * @param {Event} event The event to get.400 * @returns {boolean} The flag to stop propagation immediately.401 * @private402 */403function isStopped(event) {404 return pd(event).immediateStopped405}406/**407 * Set the current event phase of a given event.408 * @param {Event} event The event to set current target.409 * @param {number} eventPhase New event phase.410 * @returns {void}411 * @private412 */413function setEventPhase(event, eventPhase) {414 pd(event).eventPhase = eventPhase;415}416/**417 * Set the current target of a given event.418 * @param {Event} event The event to set current target.419 * @param {EventTarget|null} currentTarget New current target.420 * @returns {void}421 * @private422 */423function setCurrentTarget(event, currentTarget) {424 pd(event).currentTarget = currentTarget;425}426/**427 * Set a passive listener of a given event.428 * @param {Event} event The event to set current target.429 * @param {Function|null} passiveListener New passive listener.430 * @returns {void}431 * @private432 */433function setPassiveListener(event, passiveListener) {434 pd(event).passiveListener = passiveListener;435}436/**437 * @typedef {object} ListenerNode438 * @property {Function} listener439 * @property {1|2|3} listenerType440 * @property {boolean} passive441 * @property {boolean} once442 * @property {ListenerNode|null} next443 * @private444 */445/**446 * @type {WeakMap<object, Map<string, ListenerNode>>}447 * @private448 */449const listenersMap = new WeakMap();450// Listener types451const CAPTURE = 1;452const BUBBLE = 2;453const ATTRIBUTE = 3;454/**455 * Check whether a given value is an object or not.456 * @param {any} x The value to check.457 * @returns {boolean} `true` if the value is an object.458 */459function isObject(x) {460 return x !== null && typeof x === "object" //eslint-disable-line no-restricted-syntax461}462/**463 * Get listeners.464 * @param {EventTarget} eventTarget The event target to get.465 * @returns {Map<string, ListenerNode>} The listeners.466 * @private467 */468function getListeners(eventTarget) {469 const listeners = listenersMap.get(eventTarget);470 if (listeners == null) {471 throw new TypeError(472 "'this' is expected an EventTarget object, but got another value."473 )474 }475 return listeners476}477/**478 * Get the property descriptor for the event attribute of a given event.479 * @param {string} eventName The event name to get property descriptor.480 * @returns {PropertyDescriptor} The property descriptor.481 * @private482 */483function defineEventAttributeDescriptor(eventName) {484 return {485 get() {486 const listeners = getListeners(this);487 let node = listeners.get(eventName);488 while (node != null) {489 if (node.listenerType === ATTRIBUTE) {490 return node.listener491 }492 node = node.next;493 }494 return null495 },496 set(listener) {497 if (typeof listener !== "function" && !isObject(listener)) {498 listener = null; // eslint-disable-line no-param-reassign499 }500 const listeners = getListeners(this);501 // Traverse to the tail while removing old value.502 let prev = null;503 let node = listeners.get(eventName);504 while (node != null) {505 if (node.listenerType === ATTRIBUTE) {506 // Remove old value.507 if (prev !== null) {508 prev.next = node.next;509 } else if (node.next !== null) {510 listeners.set(eventName, node.next);511 } else {512 listeners.delete(eventName);513 }514 } else {515 prev = node;516 }517 node = node.next;518 }519 // Add new value.520 if (listener !== null) {521 const newNode = {522 listener,523 listenerType: ATTRIBUTE,524 passive: false,525 once: false,526 next: null,527 };528 if (prev === null) {529 listeners.set(eventName, newNode);530 } else {531 prev.next = newNode;532 }533 }534 },535 configurable: true,536 enumerable: true,537 }538}539/**540 * Define an event attribute (e.g. `eventTarget.onclick`).541 * @param {Object} eventTargetPrototype The event target prototype to define an event attrbite.542 * @param {string} eventName The event name to define.543 * @returns {void}544 */545function defineEventAttribute(eventTargetPrototype, eventName) {546 Object.defineProperty(547 eventTargetPrototype,548 `on${eventName}`,549 defineEventAttributeDescriptor(eventName)550 );551}552/**553 * Define a custom EventTarget with event attributes.554 * @param {string[]} eventNames Event names for event attributes.555 * @returns {EventTarget} The custom EventTarget.556 * @private557 */558function defineCustomEventTarget(eventNames) {559 /** CustomEventTarget */560 function CustomEventTarget() {561 EventTarget.call(this);562 }563 CustomEventTarget.prototype = Object.create(EventTarget.prototype, {564 constructor: {565 value: CustomEventTarget,566 configurable: true,567 writable: true,568 },569 });570 for (let i = 0; i < eventNames.length; ++i) {571 defineEventAttribute(CustomEventTarget.prototype, eventNames[i]);572 }573 return CustomEventTarget574}575/**576 * EventTarget.577 *578 * - This is constructor if no arguments.579 * - This is a function which returns a CustomEventTarget constructor if there are arguments.580 *581 * For example:582 *583 * class A extends EventTarget {}584 * class B extends EventTarget("message") {}585 * class C extends EventTarget("message", "error") {}586 * class D extends EventTarget(["message", "error"]) {}587 */588function EventTarget() {589 /*eslint-disable consistent-return */590 if (this instanceof EventTarget) {591 listenersMap.set(this, new Map());592 return593 }594 if (arguments.length === 1 && Array.isArray(arguments[0])) {595 return defineCustomEventTarget(arguments[0])596 }597 if (arguments.length > 0) {598 const types = new Array(arguments.length);599 for (let i = 0; i < arguments.length; ++i) {600 types[i] = arguments[i];601 }602 return defineCustomEventTarget(types)603 }604 throw new TypeError("Cannot call a class as a function")605 /*eslint-enable consistent-return */606}607// Should be enumerable, but class methods are not enumerable.608EventTarget.prototype = {609 /**610 * Add a given listener to this event target.611 * @param {string} eventName The event name to add.612 * @param {Function} listener The listener to add.613 * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.614 * @returns {void}615 */616 addEventListener(eventName, listener, options) {617 if (listener == null) {618 return619 }620 if (typeof listener !== "function" && !isObject(listener)) {621 throw new TypeError("'listener' should be a function or an object.")622 }623 const listeners = getListeners(this);624 const optionsIsObj = isObject(options);625 const capture = optionsIsObj626 ? Boolean(options.capture)627 : Boolean(options);628 const listenerType = capture ? CAPTURE : BUBBLE;629 const newNode = {630 listener,631 listenerType,632 passive: optionsIsObj && Boolean(options.passive),633 once: optionsIsObj && Boolean(options.once),634 next: null,635 };636 // Set it as the first node if the first node is null.637 let node = listeners.get(eventName);638 if (node === undefined) {639 listeners.set(eventName, newNode);640 return641 }642 // Traverse to the tail while checking duplication..643 let prev = null;644 while (node != null) {645 if (646 node.listener === listener &&647 node.listenerType === listenerType648 ) {649 // Should ignore duplication.650 return651 }652 prev = node;653 node = node.next;654 }655 // Add it.656 prev.next = newNode;657 },658 /**659 * Remove a given listener from this event target.660 * @param {string} eventName The event name to remove.661 * @param {Function} listener The listener to remove.662 * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.663 * @returns {void}664 */665 removeEventListener(eventName, listener, options) {666 if (listener == null) {667 return668 }669 const listeners = getListeners(this);670 const capture = isObject(options)671 ? Boolean(options.capture)672 : Boolean(options);673 const listenerType = capture ? CAPTURE : BUBBLE;674 let prev = null;675 let node = listeners.get(eventName);676 while (node != null) {677 if (678 node.listener === listener &&679 node.listenerType === listenerType680 ) {681 if (prev !== null) {682 prev.next = node.next;683 } else if (node.next !== null) {684 listeners.set(eventName, node.next);685 } else {686 listeners.delete(eventName);687 }688 return689 }690 prev = node;691 node = node.next;692 }693 },694 /**695 * Dispatch a given event.696 * @param {Event|{type:string}} event The event to dispatch.697 * @returns {boolean} `false` if canceled.698 */699 dispatchEvent(event) {700 if (event == null || typeof event.type !== "string") {701 throw new TypeError('"event.type" should be a string.')702 }703 // If listeners aren't registered, terminate.704 const listeners = getListeners(this);705 const eventName = event.type;706 let node = listeners.get(eventName);707 if (node == null) {708 return true709 }710 // Since we cannot rewrite several properties, so wrap object.711 const wrappedEvent = wrapEvent(this, event);712 // This doesn't process capturing phase and bubbling phase.713 // This isn't participating in a tree.714 let prev = null;715 while (node != null) {716 // Remove this listener if it's once717 if (node.once) {718 if (prev !== null) {719 prev.next = node.next;720 } else if (node.next !== null) {721 listeners.set(eventName, node.next);722 } else {723 listeners.delete(eventName);724 }725 } else {726 prev = node;727 }728 // Call this listener729 setPassiveListener(730 wrappedEvent,731 node.passive ? node.listener : null732 );733 if (typeof node.listener === "function") {734 try {735 node.listener.call(this, wrappedEvent);736 } catch (err) {737 if (738 typeof console !== "undefined" &&739 typeof console.error === "function"740 ) {741 console.error(err);742 }743 }744 } else if (745 node.listenerType !== ATTRIBUTE &&746 typeof node.listener.handleEvent === "function"747 ) {748 node.listener.handleEvent(wrappedEvent);749 }750 // Break if `event.stopImmediatePropagation` was called.751 if (isStopped(wrappedEvent)) {752 break753 }754 node = node.next;755 }756 setPassiveListener(wrappedEvent, null);757 setEventPhase(wrappedEvent, 0);758 setCurrentTarget(wrappedEvent, null);759 return !wrappedEvent.defaultPrevented760 },761};762// `constructor` is not enumerable.763Object.defineProperty(EventTarget.prototype, "constructor", {764 value: EventTarget,765 configurable: true,766 writable: true,767});768// Ensure `eventTarget instanceof window.EventTarget` is `true`.769if (770 typeof window !== "undefined" &&771 typeof window.EventTarget !== "undefined"772) {773 Object.setPrototypeOf(EventTarget.prototype, window.EventTarget.prototype);774}775export default EventTarget;776export { defineEventAttribute, EventTarget };...
BMapLib.js
Source:BMapLib.js
1/**2 * @fileoverview é§æ§å®³é¦æ¿æµAPIæµå¬©æ¬¢éå°îé£ï¿½3 * å§ãå¬é®ä½¸å½²æµ£è·¨æ¤closure compileré¨ådvanced妯â³ç´¡æ©æ¶îé嬬ç¼4 * @author Baidu Map Api Group 5 * @version 1.26 */7/** 8 * @namespace BMapé¨å¬å¢éå¡´ibrary绫诲æ½éæ§æ¹ªBMapLibéèæç»æ´ªæ£¿æ¶ï¿½9 */10window['BMapLib'] = window['BMapLib'] || {};11window['BMapLib']['EventWrapper'] = window['BMapLib']['EventWrapper'] || {};12(function(){13/**14 * æµå¬©æ¬¢çä½½îé£ã§æ®éæ¬â¬ä½ºè¢«15 * @class EventWrapper16 */17var EventWrapper = window['BMapLib']['EventWrapper'];18/**19 * 娣诲å§DOMæµå¬©æ¬¢é©ææéè¥æ20 * @param {HTMLElement} DOMéåªç¤21 * @param {String} æµå¬©æ¬¢éå¶Ð22 * @param {Function} æµå¬©æ¬¢æ¾¶åæéè¥æ23 * @returns {MapsEventListener} æµå¬©æ¬¢é©ææçµç¡
è24 */25EventWrapper['addDomListener'] = function(instance, eventName, handler) {26 if (instance.addEventListener) {27 instance.addEventListener(eventName, handler, false);28 }29 else if (instance.attachEvent) {30 instance.attachEvent('on' + eventName, handler);31 }32 else {33 instance['on' + eventName] = handler;34 }35 return new MapsEventListener(instance, eventName, handler, MapsEventListener.DOM_EVENT);36};37/**38 * 娣诲å§DOMæµå¬©æ¬¢é©ææéè¥æéå±½å±éé¢ç²éµÑîæ¶â¬å¨ï¿½39 * @param {HTMLElement} DOMéåªç¤40 * @param {String} æµå¬©æ¬¢éå¶Ð41 * @param {Function} æµå¬©æ¬¢æ¾¶åæéè¥æ42 * @returns {MapsEventListener} æµå¬©æ¬¢é©ææçµç¡
è43 */44EventWrapper['addDomListenerOnce'] = function(instance, eventName, handler) {45 var eventListener = EventWrapper['addDomListener'](instance, eventName, function(){46 // ç»å©æ«47 EventWrapper['removeListener'](eventListener);48 return handler.apply(this, arguments);49 });50 return eventListener;51};52/**53 * 娣诲å§é¦æ¿æµæµå¬©æ¬¢é©ææéè¥æ54 * @param {Object} ç¹ç°ç·¥55 * @param {String} æµå¬©æ¬¢éå¶Ð56 * @param {Function} æµå¬©æ¬¢æ¾¶åæéè¥æ57 * @returns {MapsEventListener} æµå¬©æ¬¢é©ææçµç¡
è58 */59EventWrapper['addListener'] = function(instance, eventName, handler) {60 instance.addEventListener(eventName, handler);61 return new MapsEventListener(instance, eventName, handler, MapsEventListener.MAP_EVENT);62};63/**64 * 娣诲å§é¦æ¿æµæµå¬©æ¬¢é©ææéè¥æéå±½å±éé¢ç²éµÑîæ¶â¬å¨ï¿½65 * @param {Object} éâ¬ç佺æ´éîæ®ç¹ç°ç·¥66 * @param {String} æµå¬©æ¬¢éå¶Ð67 * @param {Function} æµå¬©æ¬¢æ¾¶åæéè¥æ68 * @returns {MapsEventListener} æµå¬©æ¬¢é©ææçµç¡
è69 */70EventWrapper['addListenerOnce'] = function(instance, eventName, handler){71 var eventListener = EventWrapper['addListener'](instance, eventName, function(){72 // ç»å©æ«73 EventWrapper['removeListener'](eventListener);74 return handler.apply(this, arguments);75 });76 return eventListener;77};78/**79 * ç»å©æ«éç°ç¾ç¹ç°ç·¥é¨å¬å¢éå¤ç°¨æµ åæ®éµâ¬éå¤æ´éîå±é�80 * @param {Object} éâ¬ç佺Щéãå¢éå¤ç°¨æµ åæ´éîæ®ç¹ç°ç·¥81 * @returns {None}82 */83EventWrapper['clearInstanceListeners'] = function(instance) {84 var listeners = instance._e_ || {};85 for (var i in listeners) {86 EventWrapper['removeListener'](listeners[i]);87 }88 instance._e_ = {};89};90/**91 * ç»å©æ«éç°ç¾ç¹ç°ç·¥éç°ç¾æµå¬©æ¬¢é¨å¬å¢éå¤æ´éîå±é�92 * @param {Object} éâ¬ç佺Щéãå£ç¹æ°«ç°¨æµ åæ´éîæ®ç¹ç°ç·¥93 * @param {String} éâ¬ç佺Щéãæ®æµå¬©æ¬¢é�94 * @returns {None}95 */96EventWrapper['clearListeners'] = function(instance, eventName) {97 var listeners = instance._e_ || {};98 for (var i in listeners) {99 if (listeners[i]._eventName == eventName) {100 EventWrapper['removeListener'](listeners[i]);101 }102 }103};104/**105 * ç»å©æ«éç°ç¾é¨åªç°¨æµ åæ´éîå±é�106 * @param {MapsEventListener} éâ¬ç佺Щéãæ®æµå¬©æ¬¢é©ææçµç¡
è107 * @returns {None}108 */109EventWrapper['removeListener'] = function(listener) {110 var instance = listener._instance;111 var eventName = listener._eventName;112 var handler = listener._handler;113 var listeners = instance._e_ || {};114 for (var i in listeners) {115 if (listeners[i]._guid == listener._guid) {116 if (listener._eventType == MapsEventListener.DOM_EVENT) {117 // DOMæµå¬©æ¬¢118 if (instance.removeEventListener) {119 instance.removeEventListener(eventName, handler, false);120 }121 else if (instance.detachEvent) {122 instance.detachEvent('on' + eventName, handler);123 }124 else {125 instance['on' + eventName] = null;126 }127 }128 else if (listener._eventType == MapsEventListener.MAP_EVENT) {129 // é¦æ¿æµæµå¬©æ¬¢130 instance.removeEventListener(eventName, handler);131 }132 delete listeners[i];133 }134 }135};136/**137 * çï¹å½éç°ç¾æµå¬©æ¬¢138 * @param {Object} çï¹å½æµå¬©æ¬¢é¨å«çæ¸å¬ªî®ç�139 * @param {String} çï¹å½æµå¬©æ¬¢é¨å«æç»ï¿½140 * @param {Object} é·îç¾æ¶å¤ç°¨æµ 跺弬é帮ç´éîâ¬ï¿½141 * @returns {None}142 */143EventWrapper['trigger'] = function(instance, eventName) {144 var listeners = instance._e_ || {};145 for (var i in listeners) {146 if (listeners[i]._eventName == eventName) {147 var args = Array.prototype.slice.call(arguments, 2);148 listeners[i]._handler.apply(instance, args);149 }150 }151};152/**153 * æµå¬©æ¬¢é©ææ绫�154 * @constructor155 * @ignore156 * @private157 * @param {Object} çµç¡
èç¹ç°ç·¥158 * @param {string} æµå¬©æ¬¢éå¶Ð159 * @param {Function} æµå¬©æ¬¢é©ææéè¥æ160 * @param {EventTypes} æµå¬©æ¬¢ç»«è¯²ç·161 */162function MapsEventListener(instance, eventName, handler, eventType){163 this._instance = instance;164 this._eventName = eventName;165 this._handler = handler;166 this._eventType = eventType;167 this._guid = MapsEventListener._guid ++;168 this._instance._e_ = this._instance._e_ || {};169 this._instance._e_[this._guid] = this;170}171MapsEventListener._guid = 1;172MapsEventListener.DOM_EVENT = 1;173MapsEventListener.MAP_EVENT = 2;...
midifile.js
Source:midifile.js
1/*2class to parse the .mid file format3(depends on stream.js)4*/5function MidiFile(data) {6 function readChunk(stream) {7 var id = stream.read(4);8 var length = stream.readInt32();9 return {10 'id': id,11 'length': length,12 'data': stream.read(length)13 };14 }15 16 var lastEventTypeByte;17 18 function readEvent(stream) {19 var event = {};20 event.deltaTime = stream.readVarInt();21 var eventTypeByte = stream.readInt8();22 if ((eventTypeByte & 0xf0) == 0xf0) {23 /* system / meta event */24 if (eventTypeByte == 0xff) {25 /* meta event */26 event.type = 'meta';27 var subtypeByte = stream.readInt8();28 var length = stream.readVarInt();29 switch(subtypeByte) {30 case 0x00:31 event.subtype = 'sequenceNumber';32 if (length != 2) throw "Expected length for sequenceNumber event is 2, got " + length;33 event.number = stream.readInt16();34 return event;35 case 0x01:36 event.subtype = 'text';37 event.text = stream.read(length);38 return event;39 case 0x02:40 event.subtype = 'copyrightNotice';41 event.text = stream.read(length);42 return event;43 case 0x03:44 event.subtype = 'trackName';45 event.text = stream.read(length);46 return event;47 case 0x04:48 event.subtype = 'instrumentName';49 event.text = stream.read(length);50 return event;51 case 0x05:52 event.subtype = 'lyrics';53 event.text = stream.read(length);54 return event;55 case 0x06:56 event.subtype = 'marker';57 event.text = stream.read(length);58 return event;59 case 0x07:60 event.subtype = 'cuePoint';61 event.text = stream.read(length);62 return event;63 case 0x20:64 event.subtype = 'midiChannelPrefix';65 if (length != 1) throw "Expected length for midiChannelPrefix event is 1, got " + length;66 event.channel = stream.readInt8();67 return event;68 case 0x2f:69 event.subtype = 'endOfTrack';70 if (length != 0) throw "Expected length for endOfTrack event is 0, got " + length;71 return event;72 case 0x51:73 event.subtype = 'setTempo';74 if (length != 3) throw "Expected length for setTempo event is 3, got " + length;75 event.microsecondsPerBeat = (76 (stream.readInt8() << 16)77 + (stream.readInt8() << 8)78 + stream.readInt8()79 )80 return event;81 case 0x54:82 event.subtype = 'smpteOffset';83 if (length != 5) throw "Expected length for smpteOffset event is 5, got " + length;84 var hourByte = stream.readInt8();85 event.frameRate = {86 0x00: 24, 0x20: 25, 0x40: 29, 0x60: 3087 }[hourByte & 0x60];88 event.hour = hourByte & 0x1f;89 event.min = stream.readInt8();90 event.sec = stream.readInt8();91 event.frame = stream.readInt8();92 event.subframe = stream.readInt8();93 return event;94 case 0x58:95 event.subtype = 'timeSignature';96 if (length != 4) throw "Expected length for timeSignature event is 4, got " + length;97 event.numerator = stream.readInt8();98 event.denominator = Math.pow(2, stream.readInt8());99 event.metronome = stream.readInt8();100 event.thirtyseconds = stream.readInt8();101 return event;102 case 0x59:103 event.subtype = 'keySignature';104 if (length != 2) throw "Expected length for keySignature event is 2, got " + length;105 event.key = stream.readInt8(true);106 event.scale = stream.readInt8();107 return event;108 case 0x7f:109 event.subtype = 'sequencerSpecific';110 event.data = stream.read(length);111 return event;112 default:113 // console.log("Unrecognised meta event subtype: " + subtypeByte);114 event.subtype = 'unknown'115 event.data = stream.read(length);116 return event;117 }118 event.data = stream.read(length);119 return event;120 } else if (eventTypeByte == 0xf0) {121 event.type = 'sysEx';122 var length = stream.readVarInt();123 event.data = stream.read(length);124 return event;125 } else if (eventTypeByte == 0xf7) {126 event.type = 'dividedSysEx';127 var length = stream.readVarInt();128 event.data = stream.read(length);129 return event;130 } else {131 throw "Unrecognised MIDI event type byte: " + eventTypeByte;132 }133 } else {134 /* channel event */135 var param1;136 if ((eventTypeByte & 0x80) == 0) {137 /* running status - reuse lastEventTypeByte as the event type.138 eventTypeByte is actually the first parameter139 */140 param1 = eventTypeByte;141 eventTypeByte = lastEventTypeByte;142 } else {143 param1 = stream.readInt8();144 lastEventTypeByte = eventTypeByte;145 }146 var eventType = eventTypeByte >> 4;147 event.channel = eventTypeByte & 0x0f;148 event.type = 'channel';149 switch (eventType) {150 case 0x08:151 event.subtype = 'noteOff';152 event.noteNumber = param1;153 event.velocity = stream.readInt8();154 return event;155 case 0x09:156 event.noteNumber = param1;157 event.velocity = stream.readInt8();158 if (event.velocity == 0) {159 event.subtype = 'noteOff';160 } else {161 event.subtype = 'noteOn';162 }163 return event;164 case 0x0a:165 event.subtype = 'noteAftertouch';166 event.noteNumber = param1;167 event.amount = stream.readInt8();168 return event;169 case 0x0b:170 event.subtype = 'controller';171 event.controllerType = param1;172 event.value = stream.readInt8();173 return event;174 case 0x0c:175 event.subtype = 'programChange';176 event.programNumber = param1;177 return event;178 case 0x0d:179 event.subtype = 'channelAftertouch';180 event.amount = param1;181 return event;182 case 0x0e:183 event.subtype = 'pitchBend';184 event.value = param1 + (stream.readInt8() << 7);185 return event;186 default:187 throw "Unrecognised MIDI event type: " + eventType188 /* 189 console.log("Unrecognised MIDI event type: " + eventType);190 stream.readInt8();191 event.subtype = 'unknown';192 return event;193 */194 }195 }196 }197 198 stream = Stream(data);199 var headerChunk = readChunk(stream);200 if (headerChunk.id != 'MThd' || headerChunk.length != 6) {201 throw "Bad .mid file - header not found";202 }203 var headerStream = Stream(headerChunk.data);204 var formatType = headerStream.readInt16();205 var trackCount = headerStream.readInt16();206 var timeDivision = headerStream.readInt16();207 208 if (timeDivision & 0x8000) {209 throw "Expressing time division in SMTPE frames is not supported yet"210 } else {211 ticksPerBeat = timeDivision;212 }213 214 var header = {215 'formatType': formatType,216 'trackCount': trackCount,217 'ticksPerBeat': ticksPerBeat218 }219 var tracks = [];220 for (var i = 0; i < header.trackCount; i++) {221 tracks[i] = [];222 var trackChunk = readChunk(stream);223 if (trackChunk.id != 'MTrk') {224 throw "Unexpected chunk - expected MTrk, got "+ trackChunk.id;225 }226 var trackStream = Stream(trackChunk.data);227 while (!trackStream.eof()) {228 var event = readEvent(trackStream);229 tracks[i].push(event);230 //console.log(event);231 }232 }233 234 return {235 'header': header,236 'tracks': tracks237 }...
DomEventMixin.js
Source:DomEventMixin.js
1if (typeof window.RadControlsNamespace == "undefined")2{3 window.RadControlsNamespace = {};4}5if (6 typeof(window.RadControlsNamespace.DomEventMixin) == "undefined" ||7 typeof(window.RadControlsNamespace.DomEventMixin.Version) == null ||8 window.RadControlsNamespace.DomEventMixin.Version < 39 )10{ 11 12 RadControlsNamespace.DomEventMixin = 13 {14 Version : 3, // Change the version when make changes. Change the value in the IF also15 16 Initialize : function(obj)17 {18 obj.CreateEventHandler = this.CreateEventHandler;19 obj.AttachDomEvent = this.AttachDomEvent;20 obj.DetachDomEvent = this.DetachDomEvent;21 obj.DisposeDomEventHandlers = this.DisposeDomEventHandlers;22 obj._domEventHandlingEnabled = true;23 obj.EnableDomEventHandling = this.EnableDomEventHandling;24 obj.DisableDomEventHandling = this.DisableDomEventHandling;25 26 obj.RemoveHandlerRegister = this.RemoveHandlerRegister;27 obj.GetHandlerRegister = this.GetHandlerRegister;28 obj.AddHandlerRegister = this.AddHandlerRegister;29 obj.handlerRegisters = [];30 },31 32 EnableDomEventHandling : function ()33 {34 this._domEventHandlingEnabled = true;35 },36 37 DisableDomEventHandling : function ()38 {39 this._domEventHandlingEnabled = false;40 },41 42 CreateEventHandler : function (methodName, fireIfDisabled)43 {44 var instance = this;45 return function (e)46 {47 if (!instance._domEventHandlingEnabled && !fireIfDisabled)48 {49 return;50 }51 52 return instance[methodName](e || window.event);53 }54 },55 56 AttachDomEvent : function(element, eventName, eventHandlerName, fireIfDisabled)57 {58 var eventHandler = this.CreateEventHandler(eventHandlerName, fireIfDisabled);59 // if such entry exist already - detach it first60 var oldRegister = this.GetHandlerRegister(element, eventName, eventHandlerName);61 if (oldRegister != null)62 {63 this.DetachDomEvent(oldRegister.Element, oldRegister.EventName, eventHandlerName);64 }65 66 // register the new entry67 var eventRegister = { 68 "Element" : element, 69 "EventName" : eventName, 70 "HandlerName" : eventHandlerName, 71 "Handler" : eventHandler 72 };73 this.AddHandlerRegister(eventRegister);74 75 // now do the "real" job76 if (element.addEventListener)77 {78 element.addEventListener(eventName, eventHandler, false);79 }80 else if (element.attachEvent)81 {82 element.attachEvent("on" + eventName, eventHandler);83 }84 },85 86 87 DetachDomEvent : function(element, eventName, eventHandler)88 {89 var eventRegister = null;90 var eventHandlerName = "";91 if (typeof eventHandler == "string") 92 {93 eventHandlerName = eventHandler;94 eventRegister = this.GetHandlerRegister(element, eventName, eventHandlerName);95 if(eventRegister == null)96 return;97 eventHandler = eventRegister.Handler;98 }99 100 if (!element)101 {102 return;103 }104 105 if (element.removeEventListener)106 {107 element.removeEventListener(eventName, eventHandler, false);108 }109 else if (element.detachEvent)110 {111 element.detachEvent("on" + eventName, eventHandler);112 }113 114 if (eventRegister != null && eventHandlerName != "")115 {116 this.RemoveHandlerRegister(eventRegister);117 eventRegister = null;118 }119 },120 121 DisposeDomEventHandlers : function()122 {123 for (var i=0; i < this.handlerRegisters.length; i ++)124 {125 var eventRegister = this.handlerRegisters[i];126 if (eventRegister != null)127 {128 this.DetachDomEvent(129 eventRegister.Element, 130 eventRegister.EventName, 131 eventRegister.Handler);132 }133 }134 135 this.handlerRegisters = [];136 },137 RemoveHandlerRegister : function(eventRegister)138 {139 try {140 var regIndex = eventRegister.index;141 for (var i in eventRegister)142 {143 eventRegister[i] = null;144 }145 this.handlerRegisters[regIndex] = null;146 } catch (e) {}147 },148 GetHandlerRegister : function(element, eventName, handlerName)149 {150 for (var i=0; i < this.handlerRegisters.length; i ++)151 {152 var eventRegister = this.handlerRegisters[i];153 if (eventRegister != null &&154 eventRegister.Element == element && 155 eventRegister.EventName == eventName &&156 eventRegister.HandlerName == handlerName 157 )158 {159 return this.handlerRegisters[i];160 }161 }162 163 return null;164 },165 166 AddHandlerRegister : function(props)167 {168 props.index = this.handlerRegisters.length;169 this.handlerRegisters[this.handlerRegisters.length] = props;170 }171 }172 173 RadControlsNamespace.DomEvent = {};174 175 RadControlsNamespace.DomEvent.PreventDefault = function (e)176 {177 if (!e) return true;178 179 if (e.preventDefault)180 {181 e.preventDefault();182 }183 184 e.returnValue = false;185 return false;186 }187 188 RadControlsNamespace.DomEvent.StopPropagation = function (e)189 {190 if (!e) return;191 192 if (e.stopPropagation)193 {194 e.stopPropagation();195 }196 else197 {198 e.cancelBubble = true;199 }200 }201 202 RadControlsNamespace.DomEvent.GetTarget = function (e)203 {204 if (!e) return null;205 206 return e.target || e.srcElement;207 }208 209 210 RadControlsNamespace.DomEvent.GetRelatedTarget = function (e)211 {212 if (!e) return null;213 214 return e.relatedTarget || (e.type == "mouseout" ? e.toElement : e.fromElement);215 }216 217 RadControlsNamespace.DomEvent.GetKeyCode = function (e)218 {219 if (!e) return 0;220 221 return e.which || e.keyCode;222 }223}224//BEGIN_ATLAS_NOTIFY225if (typeof(Sys) != "undefined")226{227 if (Sys.Application != null && Sys.Application.notifyScriptLoaded != null)228 {229 Sys.Application.notifyScriptLoaded();230 }231}...
translation_events.js
Source:translation_events.js
1// -*- mode: Javascript; js-indent-level: 4; -*-2// Copyright 2013 Massachusetts Institute of Technology. All rights reserved.3/**4 * @fileoverview Visual blocks editor for App Inventor5 * Methods to handle Internationalization for AI2 Blockseditor.6 *7 * @author mckinney@mit.edu (Andrew F. McKinney)8 */9'use strict';10goog.provide('Blockly.TranslationEvents');11Blockly.TranslationEvents.map = {};12Blockly.TranslationEvents.haveEvent = function(eventName) {13 return Blockly.TranslationEvents.map[eventName] != undefined;14}15Blockly.TranslationEvents.addEvent = function(eventName, eventValue, eventDescription) {16 if (!Blockly.TranslationEvents.haveEvent(eventName)) {17 Blockly.TranslationEvents.map[eventName] = [eventValue, eventDescription];18 }19}20/**21 * eventList is an array list of event with format [eventValue, eventName, eventDescription]22 */23Blockly.TranslationEvents.addEvents = function(eventList) {24 for(var i = 0; i < eventList.length; i++) {25 var eventValue = eventList[i][0];26 var eventName = eventList[i][1];27 var eventDescription = eventList[i][2];28 Blockly.TranslationEvents.addEvent(eventName, eventValue, eventDescription);29 }30}31Blockly.TranslationEvents.updateEvent = function(eventName, eventValue, eventDescription) {32 if (Blockly.TranslationEvents.haveEvent(eventName)) {33 var decription = eventDescription;34 if (eventDescription == '') {35 decription = Blockly.TranslationEvents.map[eventName][1];36 }37 Blockly.TranslationEvents.map[eventName] = [eventValue, decription];38 } else {39 Blockly.TranslationEvents.addEvent(eventName, eventValue, eventDescription);40 }41}42/**43 * eventList is an array list of event with format [eventValue, eventName]44 */45Blockly.TranslationEvents.updateEvents = function(eventList) {46 for(var i = 0; i < eventList.length; i++) {47 var eventValue = eventList[i][0];48 var eventName = eventList[i][1];49 var eventDescription = eventList[i][2];50 Blockly.TranslationEvents.updateEvent(eventName, eventValue, eventDescription);51 }52}53Blockly.TranslationEvents.getEventValue = function(eventName) {54 if (!Blockly.TranslationEvents.haveEvent(eventName)) {55 return '';56 }57 return Blockly.TranslationEvents.map[eventName][0];58}59Blockly.TranslationEvents.getEventDescription = function(eventName) {60 if (!Blockly.TranslationEvents.haveEvent(eventName)) {61 return '';62 }63 return Blockly.TranslationEvents.map[eventName][1];64}65/**66 * Update event map 67 *68 * { "key": "EVENT-NAME",69 * "value": "EVENT-VALUE",70 * "decription": "EVENT-DESCRIPTION",71 * }72 *73 */74Blockly.TranslationEvents.updateEventMap = function(typeDescription) {75 var eventName = typeDescription.key;76 var eventValue = typeDescription.value;77 var eventDescription = typeDescription.description;78 Blockly.TranslationEvents.updateEvent(eventName, eventValue, eventDescription); 79}80/**81 * Update event map 82 *83 * typeJsonString has the following format (where upper-case strings are84 * non-terminals and lower-case strings are literals):85 * [86 * { "key": "EVENT-NAME",87 * "value": "EVENT-VALUE",88 * "decription": "EVENT-DESCRIPTION",89 * },+90 * ]91 */92Blockly.TranslationEvents.updateMap = function(jsonString) {93 var events = JSON.parse(jsonString);94 95 for (var i = 0, typeDescription; typeDescription = events[i]; i++) {96 Blockly.TranslationEvents.updateEventMap(typeDescription); 97 }...
jquery.tap.js
Source:jquery.tap.js
1(function($, specialEventName) {2 'use strict';3 /**4 * Native event names for creating custom one.5 *6 * @type {Object}7 */8 var nativeEvent = Object.create(null);9 /**10 * Get current time.11 *12 * @return {Number}13 */14 var getTime = function() {15 return new Date().getTime();16 };17 nativeEvent.original = 'click';18 if ('ontouchstart' in document) {19 nativeEvent.start = 'touchstart';20 nativeEvent.end = 'touchend';21 } else {22 nativeEvent.start = 'mousedown';23 nativeEvent.end = 'mouseup';24 }25 $.event.special[specialEventName] = {26 setup: function(data, namespaces, eventHandle) {27 var $element = $(this);28 var eventData = {};29 $element30 // Remove all handlers that were set for an original event.31 .off(nativeEvent.original)32 // Prevent default actions.33 .on(nativeEvent.original, false)34 // Split original event by two different and collect an information35 // on every phase.36 .on(nativeEvent.start + ' ' + nativeEvent.end, function(event) {37 // Handle the event system of touchscreen devices.38 eventData.event = event.originalEvent.changedTouches ? event.originalEvent.changedTouches[0] : event;39 })40 .on(nativeEvent.start, function(event) {41 // Stop execution if an event is simulated.42 if (event.which && event.which !== 1) {43 return;44 }45 eventData.target = event.target;46 eventData.pageX = eventData.event.pageX;47 eventData.pageY = eventData.event.pageY;48 eventData.time = getTime();49 })50 .on(nativeEvent.end, function(event) {51 // Compare properties from two phases.52 if (53 // The target should be the same.54 eventData.target === event.target &&55 // Time between first and last phases should be less than 750 ms.56 getTime() - eventData.time < 750 &&57 // Coordinates, when event ends, should be the same as they were58 // on start.59 (60 eventData.pageX === eventData.event.pageX &&61 eventData.pageY === eventData.event.pageY62 )63 ) {64 event.type = specialEventName;65 event.pageX = eventData.event.pageX;66 event.pageY = eventData.event.pageY;67 eventHandle.call(this, event);68 // If an event wasn't prevented then execute original actions.69 if (!event.isDefaultPrevented()) {70 $element71 // Remove prevention of default actions.72 .off(nativeEvent.original)73 // Bring the action.74 .trigger(nativeEvent.original);75 }76 }77 });78 },79 remove: function() {80 $(this).off(nativeEvent.start + ' ' + nativeEvent.end);81 }82 };83 $.fn[specialEventName] = function(fn) {84 return this[fn ? 'on' : 'trigger'](specialEventName, fn);85 };...
Using AI Code Generation
1var Parent = require('stryker-parent');2var parent = new Parent();3parent.on('test', function (data) {4 console.log(data);5});6var Child = require('stryker-child');7var child = new Child();8child.on('test', function (data) {9 console.log(data);10});11var Child = require('stryker-child');12var child = new Child();13child.on('test', function (data) {14 console.log(data);15});16var Child = require('stryker-child');17var child = new Child();18child.on('test', function (data) {19 console.log(data);20});21var Child = require('stryker-child');22var child = new Child();23child.on('test', function (data) {24 console.log(data);25});26var Child = require('stryker-child');27var child = new Child();28child.on('test', function (data) {29 console.log(data);30});31var Child = require('stryker-child');32var child = new Child();33child.on('test', function (data) {34 console.log(data);35});36var Child = require('stryker-child');37var child = new Child();38child.on('test', function (data) {39 console.log(data);40});41var Child = require('stryker-child');42var child = new Child();43child.on('test', function (data) {44 console.log(data);45});46var Child = require('stryker-child');47var child = new Child();48child.on('test', function (data) {49 console.log(data);50});51var Child = require('stryker-child');52var child = new Child();53child.on('test', function (data) {54 console.log(data);55});56var Child = require('stryker-child');57var child = new Child();58child.on('test', function (data) {
Using AI Code Generation
1const strykerParent = require('stryker-parent');2strykerParent.on('event', function (event) {3 console.log(event);4});5const strykerParent = require('stryker-parent');6strykerParent.on('event', function (event) {7 console.log(event);8});
Using AI Code Generation
1const event = require('stryker-parent/event');2event.on('test', function(){3 console.log('test');4});5event.emit('test');6const event = require('stryker-parent/event');7event.on('test', function(){8 console.log('test');9});10event.emit('test');11const event = require('stryker-parent/event');12event.on('test', function(){13 console.log('test2');14});15event.emit('test');16const event = require('stryker-parent/event');17event.on('test', function(){18 console.log('test2');19});20event.emit('test');
Using AI Code Generation
1var stryker_parent = require('stryker-parent');2stryker_parent.event.on('test', function (data) {3 console.log('received data from parent: ' + data);4});5var stryker_child = require('stryker-child');6stryker_child.event.on('test', function (data) {7 console.log('received data from child: ' + data);8});9var child_process = require('child_process');10var stryker_child = child_process.fork('stryker-child.js');11var stryker_parent = require('stryker-parent');12stryker_child.on('message', function (data) {13 stryker_parent.event.emit('test', data);14});15var child_process = require('child_process');16var stryker_child = child_process.fork('stryker-child.js');17var stryker_parent = require('stryker-parent');18stryker_child.on('message', function (data) {19 stryker_parent.event.emit('test', data);20});21var child_process = require('child_process');22var stryker_child = child_process.fork('stryker-child.js');23var stryker_parent = require('stryker-parent');24stryker_child.on('message', function (data) {25 stryker_parent.event.emit('test', data);26});27var child_process = require('child_process');28var stryker_child = child_process.fork('stryker-child.js');29var stryker_parent = require('stryker-parent');30stryker_child.on('message', function (data) {31 stryker_parent.event.emit('test', data);32});33var child_process = require('child_process');34var stryker_child = child_process.fork('stryker-child.js');35var stryker_parent = require('stryker-parent');36stryker_child.on('message', function (data) {37 stryker_parent.event.emit('test', data);38});39var child_process = require('child_process');40var stryker_child = child_process.fork('stryker-child.js');41var stryker_parent = require('stryker-parent');42stryker_child.on('message', function
Using AI Code Generation
1const strykerParent = require('stryker-parent');2strykerParent.on('test', (data) => {3 console.log('test event', data);4});5### `strykerParent.emit(eventName, data)`6### `strykerParent.on(eventName, callback)`7### `strykerParent.once(eventName, callback)`8### `strykerParent.removeListener(eventName, callback)`9### `strykerParent.removeAllListeners(eventName)`10### `strykerParent.emitAsync(eventName, data)`11### `strykerParent.emitAsync(eventName, data)`12### `strykerParent.emitAsync(eventName, data)`13### `strykerParent.emitAsync(eventName, data)`14### `strykerParent.emitAsync(eventName, data)`15### `strykerParent.emitAsync(eventName, data)`16### `strykerParent.emitAsync(eventName, data)`17### `strykerParent.emitAsync(eventName, data)`18### `strykerParent.emitAsync(eventName, data)`19### `strykerParent.emitAsync(eventName, data)`
Using AI Code Generation
1var parent = require('stryker-parent');2parent.on('test', function (data) {3 console.log('test event received with data: ' + data);4});5parent.emit('test', 'Hello World');6var parent = require('stryker-parent');7parent.on('test', function (data) {8 console.log('test event received with data: ' + data);9});10var parent = require('stryker-parent');11parent.promise('test', 'Hello World').then(function (data) {12 console.log('test promise received with data: ' + data);13});14var parent = require('stryker-parent');15parent.promise('test', 'Hello World').then(function (data) {16 console.log('test promise received with data: ' + data);17});18Copyright (c) 2014-2015, Stryker-mutator
Using AI Code Generation
1var stryker = require('stryker-parent');2var event = stryker.event;3var child = stryker.child;4var childProcess = child.fork('./child.js');5event.on('test', function (data) {6 console.log(data);7});8var stryker = require('stryker-parent');9var event = stryker.event;10var child = stryker.child;11event.emit('test', 'hello world');
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!