Repository: incubator-weex Updated Branches: refs/heads/0.16-dev 495fc6b24 -> b11c4e113
* [html5] bind click listener to event tap. Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/a35c690c Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/a35c690c Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/a35c690c Branch: refs/heads/0.16-dev Commit: a35c690c1f4e3d43ed93151215bdbe9457942d91 Parents: d20e0d8 Author: MrRaindrop <tekk...@gmail.com> Authored: Thu Jun 29 17:37:02 2017 +0800 Committer: MrRaindrop <tekk...@gmail.com> Committed: Thu Jun 29 17:37:02 2017 +0800 ---------------------------------------------------------------------- html5/render/vue/core/node.js | 122 +++++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 38 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/a35c690c/html5/render/vue/core/node.js ---------------------------------------------------------------------- diff --git a/html5/render/vue/core/node.js b/html5/render/vue/core/node.js index 87981d8..196d061 100644 --- a/html5/render/vue/core/node.js +++ b/html5/render/vue/core/node.js @@ -54,10 +54,25 @@ function getListeners (vnode, evt) { } const supportedEvents = [ - 'tap', 'click', 'longpress', 'appear', 'disappear', + 'longpress', 'appear', 'disappear', // 'touchstart', 'touchmove', 'touchend', 'panstart', 'panmove', 'panend', 'swipe', 'longpress' ] + +/** + * is a element in a '<a>' tag? + * @param {HTMLElement} el + */ +function isInANode (el) { + let parent = el.parentNode + while (parent && parent !== document.body) { + if (parent.tagName.toLowerCase() === 'a') { + return true + } + parent = parent.parentNode + } +} + /** * emit native events to enable v-on. * @param {VComponent} context: which one to emit a event on. @@ -66,52 +81,83 @@ const supportedEvents = [ export function createEventMap (context, extras = []) { const eventMap = {} /** - * bind name with evt event. e.g. bind 'click' with 'tap' event. + * Bind some original type event to your specified type event handler. + * e.g. bind 'tap' event to 'click' event listener: bindFunc('tap')('click'). + * Or bind certian event with your specified handler: bindFunc('click', someFunction) */ - const bindFunc = (evt) => { - return name => { - const evtType = evt || name - eventMap[evtType] = function (e) { - /** - * allow original bubbling. - * use '_triggered' to control actural bubbling. - */ - if (e._triggered) { - return - } - // but should trigger the closest parent which has bound the - // event handler. - let vm = context - while (vm) { - const ons = getListeners(vm.$vnode, name) - const len = ons.length - let idx = 0 - while (idx < len) { - let on = ons[idx] - if (on && on.fn) { - on = on.fn - } - on && on.call(vm, - evtType === name ? e : extend({}, e, { type: name }) - ) - idx++ + const bindFunc = (originalType) => { + return listenTo => { + let handler + if (typeof listenTo === 'function') { + handler = listenTo + } + else if (typeof listenTo === 'string') { + if (!originalType) { originalType = listenTo } + handler = function (e) { + /** + * allow original bubbling. + * use '_triggered' to control actural bubbling. + */ + if (e._triggered) { + return } - - // once a parent node (or self node) has triggered the handler, - // then it stops bubble immediately, and a '_triggered' object is set. - if (len > 0) { - e._triggered = { - el: vm.$el + // but should trigger the closest parent which has bound the + // event handler. + let vm = context + while (vm) { + const ons = getListeners(vm.$vnode, listenTo) + const len = ons.length + if (len > 0) { + let idx = 0 + while (idx < len) { + let on = ons[idx] + if (on && on.fn) { + on = on.fn + } + on && on.call(vm, + originalType === listenTo ? e : extend({}, e, { type: listenTo }) + ) + idx++ + } + // once a parent node (or self node) has triggered the handler, then + // it stops bubbling immediately, and a '_triggered' object is set. + e._triggered = { + el: vm.$el + } + return } - return + vm = vm.$parent } - vm = vm.$parent } } + eventMap[originalType] = handler } } supportedEvents.concat(extras).forEach(bindFunc()) - // bindFunc('tap')('click') + bindFunc('tap')('click') + /** + * Special treatment for click event: + * we already use tap to trigger click event, so the click event should: + * 1. trigger none of any vm's click listeners. + * 2. prevent default behaviour for a `<a>` element. + * This means the click event should always be swallowed in silence. + */ + bindFunc('click')(function (e) { + if (e._triggered) { + return + } + let vm = context + while (vm) { + const ons = getListeners(vm.$vnode, 'click') + const len = ons.length + if (len > 0 && vm.$el && isInANode(vm.$el)) { + e.preventDefault() + e._triggered = { el: vm.$el } + return + } + vm = vm.$parent + } + }) return eventMap }