Low-level plugin event helper API
Can be used to listen to tap evens (i.e. click/touch), preventing their bubbling, or preventing normal execution. To stop either bubbling or normal execution, callback should explicitly return false. By default, bubbling and normal execution is not prevented. onTap() adds a listener to a click or touch event to element wrapped with event helper. captureTap() installs a capture phase listener and callback returning false at that moment intercepts tap before any action is taken by other listeners (i.e. PolyGerrit buttons). Sample code ``` js Gerrit.install(plugin => { plugin.hook('reply-text').onAttached(element => { if (!element.content) { return; } plugin.eventHelper(element.content).onTap(() => { console.log('reply test tapped!'); }); plugin.eventHelper(element.content).captureTap(() => { // Prevent onTap() handler from being called. return false; }); }); }); ``` Change-Id: Ie10169e2c801ce85590e4f700e6041e9c8a02bff
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (C) 2017 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||||
|
|
||||||
|
<dom-module id="gr-event-helper">
|
||||||
|
<script src="gr-event-helper.js"></script>
|
||||||
|
</dom-module>
|
@@ -0,0 +1,69 @@
|
|||||||
|
// Copyright (C) 2017 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
(function(window) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function GrEventHelper(element) {
|
||||||
|
this.element = element;
|
||||||
|
this._unsubscribers = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a callback to element click or touch.
|
||||||
|
* The callback may return false to prevent event bubbling.
|
||||||
|
* @param {function(Event):boolean} callback
|
||||||
|
* @return {function()} Unsubscribe function.
|
||||||
|
*/
|
||||||
|
GrEventHelper.prototype.onTap = function(callback) {
|
||||||
|
return this._listen(this.element, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a callback to element click or touch ahead of normal flow.
|
||||||
|
* Callback is installed on parent during capture phase.
|
||||||
|
* https://www.w3.org/TR/DOM-Level-3-Events/#event-flow
|
||||||
|
* The callback may return false to cancel regular event listeners.
|
||||||
|
* @param {function(Event):boolean} callback
|
||||||
|
* @return {function()} Unsubscribe function.
|
||||||
|
*/
|
||||||
|
GrEventHelper.prototype.captureTap = function(callback) {
|
||||||
|
return this._listen(this.element.parentElement, callback, {capture: true});
|
||||||
|
};
|
||||||
|
|
||||||
|
GrEventHelper.prototype._listen = function(container, callback, opt_options) {
|
||||||
|
const capture = opt_options && opt_options.capture;
|
||||||
|
const handler = e => {
|
||||||
|
if (e.path.indexOf(this.element) !== -1) {
|
||||||
|
let mayContinue = true;
|
||||||
|
try {
|
||||||
|
mayContinue = callback(e);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn(`Plugin error handing event: ${e}`);
|
||||||
|
}
|
||||||
|
if (mayContinue === false) {
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
container.addEventListener('tap', handler, capture);
|
||||||
|
const unsubscribe = () =>
|
||||||
|
container.removeEventListener('tap', handler, capture);
|
||||||
|
this._unsubscribers.push(unsubscribe);
|
||||||
|
return unsubscribe;
|
||||||
|
};
|
||||||
|
|
||||||
|
window.GrEventHelper = GrEventHelper;
|
||||||
|
})(window);
|
@@ -0,0 +1,96 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<!--
|
||||||
|
Copyright (C) 2017 The Android Open Source Project
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||||
|
<title>gr-event-helper</title>
|
||||||
|
|
||||||
|
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
|
||||||
|
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||||||
|
<link rel="import" href="../../../test/common-test-setup.html"/>
|
||||||
|
<link rel="import" href="gr-event-helper.html"/>
|
||||||
|
|
||||||
|
<script>void(0);</script>
|
||||||
|
|
||||||
|
<dom-element id="some-element">
|
||||||
|
<script>
|
||||||
|
Polymer({
|
||||||
|
is: 'some-element',
|
||||||
|
properties: {
|
||||||
|
fooBar: {
|
||||||
|
type: Object,
|
||||||
|
notify: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</dom-element>
|
||||||
|
|
||||||
|
<test-fixture id="basic">
|
||||||
|
<template>
|
||||||
|
<some-element></some-element>
|
||||||
|
</template>
|
||||||
|
</test-fixture>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
suite('gr-event-helper tests', () => {
|
||||||
|
let element;
|
||||||
|
let instance;
|
||||||
|
let sandbox;
|
||||||
|
|
||||||
|
setup(() => {
|
||||||
|
sandbox = sinon.sandbox.create();
|
||||||
|
element = fixture('basic');
|
||||||
|
instance = new GrEventHelper(element);
|
||||||
|
});
|
||||||
|
|
||||||
|
teardown(() => {
|
||||||
|
sandbox.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('onTap()', done => {
|
||||||
|
instance.onTap(() => {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
element.fire('tap');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('onTap() cancel', () => {
|
||||||
|
const tapStub = sandbox.stub();
|
||||||
|
element.parentElement.addEventListener('tap', tapStub);
|
||||||
|
instance.onTap(() => false);
|
||||||
|
element.fire('tap');
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
assert.isFalse(tapStub.called);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('captureTap()', done => {
|
||||||
|
instance.captureTap(() => {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
element.fire('tap');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('captureTap() cancels tap()', () => {
|
||||||
|
const tapStub = sandbox.stub();
|
||||||
|
element.addEventListener('tap', tapStub);
|
||||||
|
instance.captureTap(() => false);
|
||||||
|
element.fire('tap');
|
||||||
|
flushAsynchronousOperations();
|
||||||
|
assert.isFalse(tapStub.called);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
@@ -19,6 +19,7 @@ limitations under the License.
|
|||||||
<link rel="import" href="../../core/gr-reporting/gr-reporting.html">
|
<link rel="import" href="../../core/gr-reporting/gr-reporting.html">
|
||||||
<link rel="import" href="../../plugins/gr-attribute-helper/gr-attribute-helper.html">
|
<link rel="import" href="../../plugins/gr-attribute-helper/gr-attribute-helper.html">
|
||||||
<link rel="import" href="../../plugins/gr-dom-hooks/gr-dom-hooks.html">
|
<link rel="import" href="../../plugins/gr-dom-hooks/gr-dom-hooks.html">
|
||||||
|
<link rel="import" href="../../plugins/gr-event-helper/gr-event-helper.html">
|
||||||
<link rel="import" href="../../plugins/gr-popup-interface/gr-popup-interface.html">
|
<link rel="import" href="../../plugins/gr-popup-interface/gr-popup-interface.html">
|
||||||
<link rel="import" href="../../plugins/gr-theme-api/gr-theme-api.html">
|
<link rel="import" href="../../plugins/gr-theme-api/gr-theme-api.html">
|
||||||
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
|
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
|
||||||
|
@@ -198,6 +198,10 @@
|
|||||||
return new GrAttributeHelper(element);
|
return new GrAttributeHelper(element);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Plugin.prototype.eventHelper = function(element) {
|
||||||
|
return new GrEventHelper(element);
|
||||||
|
};
|
||||||
|
|
||||||
Plugin.prototype.popup = function(moduleName) {
|
Plugin.prototype.popup = function(moduleName) {
|
||||||
if (typeof moduleName !== 'string') {
|
if (typeof moduleName !== 'string') {
|
||||||
throw new Error('deprecated, use deprecated.popup');
|
throw new Error('deprecated, use deprecated.popup');
|
||||||
|
@@ -38,16 +38,16 @@ limitations under the License.
|
|||||||
'admin/gr-create-group-dialog/gr-create-group-dialog_test.html',
|
'admin/gr-create-group-dialog/gr-create-group-dialog_test.html',
|
||||||
'admin/gr-create-pointer-dialog/gr-create-pointer-dialog_test.html',
|
'admin/gr-create-pointer-dialog/gr-create-pointer-dialog_test.html',
|
||||||
'admin/gr-create-project-dialog/gr-create-project-dialog_test.html',
|
'admin/gr-create-project-dialog/gr-create-project-dialog_test.html',
|
||||||
'admin/gr-group/gr-group_test.html',
|
|
||||||
'admin/gr-group-audit-log/gr-group-audit-log_test.html',
|
'admin/gr-group-audit-log/gr-group-audit-log_test.html',
|
||||||
'admin/gr-group-members/gr-group-members_test.html',
|
'admin/gr-group-members/gr-group-members_test.html',
|
||||||
|
'admin/gr-group/gr-group_test.html',
|
||||||
'admin/gr-permission/gr-permission_test.html',
|
'admin/gr-permission/gr-permission_test.html',
|
||||||
'admin/gr-plugin-list/gr-plugin-list_test.html',
|
'admin/gr-plugin-list/gr-plugin-list_test.html',
|
||||||
'admin/gr-project/gr-project_test.html',
|
|
||||||
'admin/gr-project-access/gr-project-access_test.html',
|
'admin/gr-project-access/gr-project-access_test.html',
|
||||||
'admin/gr-project-commands/gr-project-commands_test.html',
|
'admin/gr-project-commands/gr-project-commands_test.html',
|
||||||
'admin/gr-project-detail-list/gr-project-detail-list_test.html',
|
'admin/gr-project-detail-list/gr-project-detail-list_test.html',
|
||||||
'admin/gr-project-list/gr-project-list_test.html',
|
'admin/gr-project-list/gr-project-list_test.html',
|
||||||
|
'admin/gr-project/gr-project_test.html',
|
||||||
'admin/gr-rule-editor/gr-rule-editor_test.html',
|
'admin/gr-rule-editor/gr-rule-editor_test.html',
|
||||||
'change-list/gr-change-list-item/gr-change-list-item_test.html',
|
'change-list/gr-change-list-item/gr-change-list-item_test.html',
|
||||||
'change-list/gr-change-list-view/gr-change-list-view_test.html',
|
'change-list/gr-change-list-view/gr-change-list-view_test.html',
|
||||||
@@ -55,8 +55,8 @@ limitations under the License.
|
|||||||
'change/gr-account-entry/gr-account-entry_test.html',
|
'change/gr-account-entry/gr-account-entry_test.html',
|
||||||
'change/gr-account-list/gr-account-list_test.html',
|
'change/gr-account-list/gr-account-list_test.html',
|
||||||
'change/gr-change-actions/gr-change-actions_test.html',
|
'change/gr-change-actions/gr-change-actions_test.html',
|
||||||
'change/gr-change-metadata/gr-change-metadata_test.html',
|
|
||||||
'change/gr-change-metadata/gr-change-metadata-it_test.html',
|
'change/gr-change-metadata/gr-change-metadata-it_test.html',
|
||||||
|
'change/gr-change-metadata/gr-change-metadata_test.html',
|
||||||
'change/gr-change-view/gr-change-view_test.html',
|
'change/gr-change-view/gr-change-view_test.html',
|
||||||
'change/gr-comment-list/gr-comment-list_test.html',
|
'change/gr-comment-list/gr-comment-list_test.html',
|
||||||
'change/gr-commit-info/gr-commit-info_test.html',
|
'change/gr-commit-info/gr-commit-info_test.html',
|
||||||
@@ -65,22 +65,22 @@ limitations under the License.
|
|||||||
'change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html',
|
'change/gr-confirm-rebase-dialog/gr-confirm-rebase-dialog_test.html',
|
||||||
'change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.html',
|
'change/gr-confirm-revert-dialog/gr-confirm-revert-dialog_test.html',
|
||||||
'change/gr-download-dialog/gr-download-dialog_test.html',
|
'change/gr-download-dialog/gr-download-dialog_test.html',
|
||||||
'change/gr-label-scores/gr-label-scores_test.html',
|
|
||||||
'change/gr-label-score-row/gr-label-score-row_test.html',
|
|
||||||
'change/gr-file-list/gr-file-list_test.html',
|
|
||||||
'change/gr-file-list-header/gr-file-list-header_test.html',
|
'change/gr-file-list-header/gr-file-list-header_test.html',
|
||||||
|
'change/gr-file-list/gr-file-list_test.html',
|
||||||
|
'change/gr-label-score-row/gr-label-score-row_test.html',
|
||||||
|
'change/gr-label-scores/gr-label-scores_test.html',
|
||||||
'change/gr-message/gr-message_test.html',
|
'change/gr-message/gr-message_test.html',
|
||||||
'change/gr-messages-list/gr-messages-list_test.html',
|
'change/gr-messages-list/gr-messages-list_test.html',
|
||||||
'change/gr-related-changes-list/gr-related-changes-list_test.html',
|
'change/gr-related-changes-list/gr-related-changes-list_test.html',
|
||||||
'change/gr-reply-dialog/gr-reply-dialog_test.html',
|
|
||||||
'change/gr-reply-dialog/gr-reply-dialog-it_test.html',
|
'change/gr-reply-dialog/gr-reply-dialog-it_test.html',
|
||||||
|
'change/gr-reply-dialog/gr-reply-dialog_test.html',
|
||||||
'change/gr-reviewer-list/gr-reviewer-list_test.html',
|
'change/gr-reviewer-list/gr-reviewer-list_test.html',
|
||||||
'core/gr-account-dropdown/gr-account-dropdown_test.html',
|
'core/gr-account-dropdown/gr-account-dropdown_test.html',
|
||||||
'core/gr-error-manager/gr-error-manager_test.html',
|
'core/gr-error-manager/gr-error-manager_test.html',
|
||||||
'core/gr-main-header/gr-main-header_test.html',
|
'core/gr-main-header/gr-main-header_test.html',
|
||||||
'core/gr-navigation/gr-navigation_test.html',
|
'core/gr-navigation/gr-navigation_test.html',
|
||||||
'core/gr-router/gr-router_test.html',
|
|
||||||
'core/gr-reporting/gr-reporting_test.html',
|
'core/gr-reporting/gr-reporting_test.html',
|
||||||
|
'core/gr-router/gr-router_test.html',
|
||||||
'core/gr-search-bar/gr-search-bar_test.html',
|
'core/gr-search-bar/gr-search-bar_test.html',
|
||||||
'diff/gr-comment-api/gr-comment-api_test.html',
|
'diff/gr-comment-api/gr-comment-api_test.html',
|
||||||
'diff/gr-diff-builder/gr-diff-builder_test.html',
|
'diff/gr-diff-builder/gr-diff-builder_test.html',
|
||||||
@@ -102,6 +102,7 @@ limitations under the License.
|
|||||||
'diff/gr-syntax-layer/gr-syntax-layer_test.html',
|
'diff/gr-syntax-layer/gr-syntax-layer_test.html',
|
||||||
'diff/gr-syntax-lib-loader/gr-syntax-lib-loader_test.html',
|
'diff/gr-syntax-lib-loader/gr-syntax-lib-loader_test.html',
|
||||||
'plugins/gr-attribute-helper/gr-attribute-helper_test.html',
|
'plugins/gr-attribute-helper/gr-attribute-helper_test.html',
|
||||||
|
'plugins/gr-event-helper/gr-event-helper_test.html',
|
||||||
'plugins/gr-external-style/gr-external-style_test.html',
|
'plugins/gr-external-style/gr-external-style_test.html',
|
||||||
'plugins/gr-plugin-host/gr-plugin-host_test.html',
|
'plugins/gr-plugin-host/gr-plugin-host_test.html',
|
||||||
'plugins/gr-popup-interface/gr-plugin-popup_test.html',
|
'plugins/gr-popup-interface/gr-plugin-popup_test.html',
|
||||||
@@ -119,9 +120,8 @@ limitations under the License.
|
|||||||
'shared/gr-account-label/gr-account-label_test.html',
|
'shared/gr-account-label/gr-account-label_test.html',
|
||||||
'shared/gr-account-link/gr-account-link_test.html',
|
'shared/gr-account-link/gr-account-link_test.html',
|
||||||
'shared/gr-alert/gr-alert_test.html',
|
'shared/gr-alert/gr-alert_test.html',
|
||||||
'shared/gr-autocomplete/gr-autocomplete_test.html',
|
|
||||||
'shared/gr-textarea/gr-textarea_test.html',
|
|
||||||
'shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown_test.html',
|
'shared/gr-autocomplete-dropdown/gr-autocomplete-dropdown_test.html',
|
||||||
|
'shared/gr-autocomplete/gr-autocomplete_test.html',
|
||||||
'shared/gr-avatar/gr-avatar_test.html',
|
'shared/gr-avatar/gr-avatar_test.html',
|
||||||
'shared/gr-button/gr-button_test.html',
|
'shared/gr-button/gr-button_test.html',
|
||||||
'shared/gr-change-star/gr-change-star_test.html',
|
'shared/gr-change-star/gr-change-star_test.html',
|
||||||
@@ -133,20 +133,21 @@ limitations under the License.
|
|||||||
'shared/gr-editable-content/gr-editable-content_test.html',
|
'shared/gr-editable-content/gr-editable-content_test.html',
|
||||||
'shared/gr-editable-label/gr-editable-label_test.html',
|
'shared/gr-editable-label/gr-editable-label_test.html',
|
||||||
'shared/gr-formatted-text/gr-formatted-text_test.html',
|
'shared/gr-formatted-text/gr-formatted-text_test.html',
|
||||||
'shared/gr-page-nav/gr-page-nav_test.html',
|
|
||||||
'shared/gr-js-api-interface/gr-change-actions-js-api_test.html',
|
'shared/gr-js-api-interface/gr-change-actions-js-api_test.html',
|
||||||
'shared/gr-js-api-interface/gr-change-reply-js-api_test.html',
|
'shared/gr-js-api-interface/gr-change-reply-js-api_test.html',
|
||||||
'shared/gr-js-api-interface/gr-js-api-interface_test.html',
|
'shared/gr-js-api-interface/gr-js-api-interface_test.html',
|
||||||
'shared/gr-linked-chip/gr-linked-chip_test.html',
|
'shared/gr-linked-chip/gr-linked-chip_test.html',
|
||||||
'shared/gr-linked-text/gr-linked-text_test.html',
|
'shared/gr-linked-text/gr-linked-text_test.html',
|
||||||
'shared/gr-list-view/gr-list-view_test.html',
|
'shared/gr-list-view/gr-list-view_test.html',
|
||||||
|
'shared/gr-page-nav/gr-page-nav_test.html',
|
||||||
'shared/gr-rest-api-interface/gr-auth_test.html',
|
'shared/gr-rest-api-interface/gr-auth_test.html',
|
||||||
'shared/gr-rest-api-interface/gr-rest-api-interface_test.html',
|
'shared/gr-rest-api-interface/gr-rest-api-interface_test.html',
|
||||||
'shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html',
|
'shared/gr-rest-api-interface/gr-reviewer-updates-parser_test.html',
|
||||||
'shared/gr-select/gr-select_test.html',
|
'shared/gr-select/gr-select_test.html',
|
||||||
'shared/gr-storage/gr-storage_test.html',
|
'shared/gr-storage/gr-storage_test.html',
|
||||||
'shared/gr-tooltip/gr-tooltip_test.html',
|
'shared/gr-textarea/gr-textarea_test.html',
|
||||||
'shared/gr-tooltip-content/gr-tooltip-content_test.html',
|
'shared/gr-tooltip-content/gr-tooltip-content_test.html',
|
||||||
|
'shared/gr-tooltip/gr-tooltip_test.html',
|
||||||
];
|
];
|
||||||
for (let file of elements) {
|
for (let file of elements) {
|
||||||
file = elementsPath + file;
|
file = elementsPath + file;
|
||||||
|
Reference in New Issue
Block a user