-
Notifications
You must be signed in to change notification settings - Fork 25.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): Add event delegation library to queue up events and repla…
…y them when the application is ready (#55121) This adds the JSAction library from the Wiz framework to core/primitives. PR Close #55121
- Loading branch information
1 parent
840c375
commit 666d646
Showing
31 changed files
with
8,069 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
load("//tools:defaults.bzl", "ts_library", "tsec_test") | ||
|
||
package(default_visibility = ["//visibility:public"]) | ||
|
||
ts_library( | ||
name = "event-dispatch", | ||
srcs = glob( | ||
[ | ||
"**/*.ts", | ||
], | ||
), | ||
module_name = "@angular/core/primitives/event-dispatch", | ||
) | ||
|
||
tsec_test( | ||
name = "tsec_test", | ||
target = "event-dispatch", | ||
tsconfig = "//packages:tsec_config", | ||
) | ||
|
||
filegroup( | ||
name = "files_for_docgen", | ||
srcs = glob([ | ||
"*.ts", | ||
"src/**/*.ts", | ||
]), | ||
visibility = ["//visibility:public"], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
|
||
export {Dispatcher, registerDispatcher} from './src/dispatcher'; | ||
export {EventContractContainer} from './src/event_contract_container'; | ||
export {EventContract} from './src/eventcontract'; | ||
export {bootstrapEventContract} from './src/register_events'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
import * as eventLib from './event'; | ||
import * as eventInfoLib from './event_info'; | ||
import {EventType} from './event_type'; | ||
|
||
/** | ||
* Update `EventInfo` to be `eventType = 'click'` and sets `a11yClickKey` if it | ||
* is a a11y click. | ||
*/ | ||
export function updateEventInfoForA11yClick(eventInfo: eventInfoLib.EventInfo) { | ||
if (!eventLib.isActionKeyEvent(eventInfoLib.getEvent(eventInfo))) { | ||
return; | ||
} | ||
eventInfoLib.setA11yClickKey(eventInfo, true); | ||
// A 'click' triggered by a DOM keypress should be mapped to the 'click' | ||
// jsaction. | ||
eventInfoLib.setEventType(eventInfo, EventType.CLICK); | ||
} | ||
|
||
/** | ||
* Call `preventDefault` on an a11y click if it is space key or to prevent the | ||
* browser's default action for native HTML controls. | ||
*/ | ||
export function preventDefaultForA11yClick(eventInfo: eventInfoLib.EventInfo) { | ||
if (!eventInfoLib.getA11yClickKey(eventInfo) || | ||
(!eventLib.isSpaceKeyEvent(eventInfoLib.getEvent(eventInfo)) && | ||
!eventLib.shouldCallPreventDefaultOnNativeHtmlControl( | ||
eventInfoLib.getEvent(eventInfo), | ||
))) { | ||
return; | ||
} | ||
eventLib.preventDefault(eventInfoLib.getEvent(eventInfo)); | ||
} | ||
|
||
/** | ||
* Sets the `action` to `clickonly` for a click event that is not an a11y click | ||
* and if there is not already a click action. | ||
*/ | ||
export function populateClickOnlyAction( | ||
eventInfo: eventInfoLib.EventInfo, | ||
actionMap: {[key: string]: string}, | ||
) { | ||
if (eventInfoLib.getEventType(eventInfo) === EventType.CLICK && | ||
// No a11y clicks should map to 'clickonly'. | ||
!eventInfoLib.getA11yClickKey(eventInfo) && !actionMap[EventType.CLICK] && | ||
actionMap[EventType.CLICKONLY]) { | ||
// A 'click' triggered by a DOM click should be mapped to the 'click' | ||
// jsaction, if available, or else fallback to the 'clickonly' jsaction. | ||
// If 'click' and 'clickonly' jsactions are used together, 'click' will | ||
// prevail. | ||
eventInfoLib.setEventType(eventInfo, EventType.CLICKONLY); | ||
eventInfoLib.setAction(eventInfo, actionMap[EventType.CLICKONLY]); | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
packages/core/primitives/event-dispatch/src/accessibility.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
/** | ||
* Defines special EventInfo and Event properties used when | ||
* A11Y_SUPPORT_IN_DISPATCHER is enabled. | ||
*/ | ||
export enum Attribute { | ||
/** | ||
* An event-type set when the event contract detects a KEYDOWN event but | ||
* doesn't know if the key press can be treated like a click. The dispatcher | ||
* will use this event-type to parse the keypress and handle it accordingly. | ||
*/ | ||
MAYBE_CLICK_EVENT_TYPE = 'maybe_click', | ||
|
||
/** | ||
* A property added to a dispatched event that had the MAYBE_CLICK_EVENTTYPE | ||
* event-type but could not be used as a click. The dispatcher sets this | ||
* property for non-global dispatches before it retriggers the event and it | ||
* signifies that the event contract should not dispatch this event globally. | ||
*/ | ||
SKIP_GLOBAL_DISPATCH = 'a11ysgd', | ||
|
||
/** | ||
* A property added to a dispatched event that had the MAYBE_CLICK_EVENTTYPE | ||
* event-type but could not be used as a click. The dispatcher sets this | ||
* property before it retriggers the event and it signifies that the event | ||
* contract should not look at CLICK actions for KEYDOWN events. | ||
*/ | ||
SKIP_A11Y_CHECK = 'a11ysc', | ||
} | ||
|
||
declare global { | ||
interface Event { | ||
[Attribute.MAYBE_CLICK_EVENT_TYPE]?: boolean; | ||
[Attribute.SKIP_GLOBAL_DISPATCH]?: boolean; | ||
[Attribute.SKIP_A11Y_CHECK]?: boolean; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
export enum Attribute { | ||
/** | ||
* The jsaction attribute defines a mapping of a DOM event to a | ||
* generic event (aka jsaction), to which the actual event handlers | ||
* that implement the behavior of the application are bound. The | ||
* value is a semicolon separated list of colon separated pairs of | ||
* an optional DOM event name and a jsaction name. If the optional | ||
* DOM event name is omitted, 'click' is assumed. The jsaction names | ||
* are dot separated pairs of a namespace and a simple jsaction | ||
* name. If the namespace is absent, it is taken from the closest | ||
* ancestor element with a jsnamespace attribute, if there is | ||
* any. If there is no ancestor with a jsnamespace attribute, the | ||
* simple name is assumed to be the jsaction name. | ||
* | ||
* Used by EventContract. | ||
*/ | ||
JSACTION = 'jsaction', | ||
|
||
/** | ||
* The jsnamespace attribute provides the namespace part of the | ||
* jaction names occurring in the jsaction attribute where it's | ||
* missing. | ||
* | ||
* Used by EventContract. | ||
*/ | ||
JSNAMESPACE = 'jsnamespace', | ||
|
||
/** | ||
* The oi attribute is a log impression tag for impression logging | ||
* and action tracking. For an element that carries a jsaction | ||
* attribute, the element is identified for the purpose of | ||
* impression logging and click tracking by the dot separated path | ||
* of all oi attributes in the chain of ancestors of the element. | ||
* | ||
* Used by ActionFlow. | ||
*/ | ||
OI = 'oi', | ||
|
||
/** | ||
* The ved attribute is an encoded ClickTrackingCGI proto to track | ||
* visual elements. | ||
* | ||
* Used by ActionFlow. | ||
*/ | ||
VED = 'ved', | ||
|
||
/** | ||
* The vet attribute is the visual element type used to identify tracked | ||
* visual elements. | ||
*/ | ||
VET = 'vet', | ||
|
||
/** | ||
* Support for iteration on reprocessing. | ||
* | ||
* Used by ActionFlow. | ||
*/ | ||
JSINSTANCE = 'jsinstance', | ||
|
||
/** | ||
* All click jsactions that happen on the element that carries this | ||
* attribute or its descendants are automatically logged. | ||
* Impressions of jsactions on these elements are tracked too, if | ||
* requested by the impression() method of ActionFlow. | ||
* | ||
* Used by ActionFlow. | ||
*/ | ||
JSTRACK = 'jstrack' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
import {Property} from './property'; | ||
|
||
/** | ||
* Map from jsaction annotation to a parsed map from event name to action name. | ||
*/ | ||
const parseCache: {[key: string]: {[key: string]: string}} = {}; | ||
|
||
/** | ||
* Reads the jsaction parser cache from the given DOM Element. | ||
* | ||
* @param element . | ||
* @return Map from event to qualified name of the jsaction bound to it. | ||
*/ | ||
export function get(element: Element): {[key: string]: string} { | ||
// @ts-ignore | ||
return element[Property.JSACTION]; | ||
} | ||
|
||
/** | ||
* Writes the jsaction parser cache to the given DOM Element. | ||
* | ||
* @param element . | ||
* @param actionMap Map from event to qualified name of the jsaction bound to | ||
* it. | ||
*/ | ||
export function set(element: Element, actionMap: {[key: string]: string}) { | ||
// @ts-ignore | ||
element[Property.JSACTION] = actionMap; | ||
} | ||
|
||
/** | ||
* Looks up the parsed action map from the source jsaction attribute value. | ||
* | ||
* @param text Unparsed jsaction attribute value. | ||
* @return Parsed jsaction attribute value, if already present in the cache. | ||
*/ | ||
export function getParsed(text: string): {[key: string]: string}|undefined { | ||
return parseCache[text]; | ||
} | ||
|
||
/** | ||
* Inserts the parse result for the given source jsaction value into the cache. | ||
* | ||
* @param text Unparsed jsaction attribute value. | ||
* @param parsed Attribute value parsed into the action map. | ||
*/ | ||
export function setParsed(text: string, parsed: {[key: string]: string}) { | ||
parseCache[text] = parsed; | ||
} | ||
|
||
/** | ||
* Clears the jsaction parser cache from the given DOM Element. | ||
* | ||
* @param element . | ||
*/ | ||
export function clear(element: Element) { | ||
if (Property.JSACTION in element) { | ||
delete element[Property.JSACTION]; | ||
} | ||
} | ||
|
||
/** | ||
* Reads the cached jsaction namespace from the given DOM | ||
* Element. Undefined means there is no cached value; null is a cached | ||
* jsnamespace attribute that's absent. | ||
* | ||
* @param element . | ||
* @return . | ||
*/ | ||
export function getNamespace(element: Element): string|null|undefined { | ||
// @ts-ignore | ||
return element[Property.JSNAMESPACE]; | ||
} | ||
|
||
/** | ||
* Writes the cached jsaction namespace to the given DOM Element. Null | ||
* represents a jsnamespace attribute that's absent. | ||
* | ||
* @param element . | ||
* @param jsnamespace . | ||
*/ | ||
export function setNamespace(element: Element, jsnamespace: string|null) { | ||
// @ts-ignore | ||
element[Property.JSNAMESPACE] = jsnamespace; | ||
} | ||
|
||
/** | ||
* Clears the cached jsaction namespace from the given DOM Element. | ||
* | ||
* @param element . | ||
*/ | ||
export function clearNamespace(element: Element) { | ||
if (Property.JSNAMESPACE in element) { | ||
delete element[Property.JSNAMESPACE]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** | ||
* @license | ||
* Copyright Google LLC All Rights Reserved. | ||
* | ||
* Use of this source code is governed by an MIT-style license that can be | ||
* found in the LICENSE file at https://angular.io/license | ||
*/ | ||
|
||
export const Char = { | ||
/** | ||
* The separator between the namespace and the action name in the | ||
* jsaction attribute value. | ||
*/ | ||
NAMESPACE_ACTION_SEPARATOR: '.', | ||
|
||
/** | ||
* The separator between the event name and action in the jsaction | ||
* attribute value. | ||
*/ | ||
EVENT_ACTION_SEPARATOR: ':', | ||
|
||
/** | ||
* The separator between the logged oi attribute values in the &oi= | ||
* URL parameter value. | ||
*/ | ||
OI_SEPARATOR: '.', | ||
|
||
/** | ||
* The separator between the key and the value pairs in the &cad= | ||
* URL parameter value. | ||
*/ | ||
CAD_KEY_VALUE_SEPARATOR: ':', | ||
|
||
/** | ||
* The separator between the key-value pairs in the &cad= URL | ||
* parameter value. | ||
*/ | ||
CAD_SEPARATOR: ',', | ||
}; |
Oops, something went wrong.