Repository: incubator-weex Updated Branches: refs/heads/0.15-dev ba53cd43d -> 59f54f9c7
* [html5] bind click listener to event tap. * [html5] osName on android should be in lowercase * [html5] release vue-render 0.11.53 * [html5] release v0.11.54 & rm click event object's tow methods. * [html5] add touch events & fix event mapping. * [html5] release v0.11.55 * [html5] update * [html5] fix loading & release v0.11.56 * [html5] use hairlines if 0.5px width is supported. * [html5] fix danger. Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/55378786 Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/55378786 Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/55378786 Branch: refs/heads/0.15-dev Commit: 55378786c0bb714a6e3a172a89f0ef9345546801 Parents: cc9ca19 Author: MrRaindrop <tekk...@gmail.com> Authored: Thu Jun 29 17:37:02 2017 +0800 Committer: MrRaindrop <tekk...@gmail.com> Committed: Thu Jul 13 17:18:52 2017 +0800 ---------------------------------------------------------------------- .../vue/components/scrollable/list/index.js | 3 +- .../vue/components/scrollable/scroller.js | 3 +- .../vue/components/scrollable/waterfall.js | 3 +- .../render/vue/components/slider/slideMixin.js | 17 +- html5/render/vue/core/node.js | 172 ++++++++++++++----- html5/render/vue/env/wx-env.js | 2 +- html5/render/vue/mixins/base.js | 16 +- html5/render/vue/mixins/scrollable.js | 18 +- html5/render/vue/utils/style.js | 30 +++- html5/test/render/vue/core/node.js | 22 ++- package.json | 2 +- packages/weex-vue-render/package.json | 8 +- 12 files changed, 215 insertions(+), 81 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/55378786/html5/render/vue/components/scrollable/list/index.js ---------------------------------------------------------------------- diff --git a/html5/render/vue/components/scrollable/list/index.js b/html5/render/vue/components/scrollable/list/index.js index e781fe9..79e6d7d 100644 --- a/html5/render/vue/components/scrollable/list/index.js +++ b/html5/render/vue/components/scrollable/list/index.js @@ -19,7 +19,6 @@ import { extractComponentStyle, createEventMap } from '../../../core' import { scrollable } from '../../../mixins' // import { validateStyles } from '../../../validator' -import { extend } from '../../../utils' import listMixin from './listMixin' export default { @@ -66,7 +65,7 @@ export default { ref: 'wrapper', attrs: { 'weex-type': 'list' }, staticClass: this.wrapperClass, - on: extend(createEventMap(this), { + on: createEventMap(this, { scroll: this.handleListScroll, touchstart: this.handleTouchStart, touchmove: this.handleTouchMove, http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/55378786/html5/render/vue/components/scrollable/scroller.js ---------------------------------------------------------------------- diff --git a/html5/render/vue/components/scrollable/scroller.js b/html5/render/vue/components/scrollable/scroller.js index 3151fae..1eebab3 100644 --- a/html5/render/vue/components/scrollable/scroller.js +++ b/html5/render/vue/components/scrollable/scroller.js @@ -19,7 +19,6 @@ import { extractComponentStyle, createEventMap } from '../../core' import { scrollable } from '../../mixins' // import { validateStyles } from '../../validator' -import { extend } from '../../utils' import listMixin from './list/listMixin' export default { @@ -80,7 +79,7 @@ export default { return createElement('main', { ref: 'wrapper', attrs: { 'weex-type': 'scroller' }, - on: extend(createEventMap(this), { + on: createEventMap(this, { scroll: this.handleScroll, touchstart: this.handleTouchStart, touchmove: this.handleTouchMove, http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/55378786/html5/render/vue/components/scrollable/waterfall.js ---------------------------------------------------------------------- diff --git a/html5/render/vue/components/scrollable/waterfall.js b/html5/render/vue/components/scrollable/waterfall.js index 2239f00..012c1d2 100644 --- a/html5/render/vue/components/scrollable/waterfall.js +++ b/html5/render/vue/components/scrollable/waterfall.js @@ -23,7 +23,6 @@ */ import { extractComponentStyle, createEventMap } from '../../core' import { scrollable } from '../../mixins' -import { extend } from '../../utils' const NORMAL_GAP_SIZE = 32 const DEFAULT_COLUMN_COUNT = 1 @@ -325,7 +324,7 @@ export default { return createElement('main', { ref: 'wrapper', attrs: { 'weex-type': 'waterfall' }, - on: extend(createEventMap(this), { + on: createEventMap(this, { scroll: this.handleScroll, touchstart: this.handleTouchStart, touchmove: this.handleTouchMove, http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/55378786/html5/render/vue/components/slider/slideMixin.js ---------------------------------------------------------------------- diff --git a/html5/render/vue/components/slider/slideMixin.js b/html5/render/vue/components/slider/slideMixin.js index 73960e5..2b7bfa1 100644 --- a/html5/render/vue/components/slider/slideMixin.js +++ b/html5/render/vue/components/slider/slideMixin.js @@ -19,7 +19,6 @@ import './slider.css' import { throttle, - extend, createEvent, fireLazyload, addTransform, @@ -116,12 +115,16 @@ export default { { ref: 'wrapper', attrs: { 'weex-type': this.isNeighbor ? 'slider-neighbor' : 'slider' }, - on: extend(createEventMap(this, ['scroll', 'scrollstart', 'scrollend']), { - touchstart: this._handleTouchStart, - touchmove: throttle(bind(this._handleTouchMove, this), 25), - touchend: this._handleTouchEnd, - touchcancel: this._handleTouchCancel - }), + on: createEventMap( + this, + ['scroll', 'scrollstart', 'scrollend'], + { + touchstart: this._handleTouchStart, + touchmove: throttle(bind(this._handleTouchMove, this), 25), + touchend: this._handleTouchEnd, + touchcancel: this._handleTouchCancel + } + ), staticClass: 'weex-slider weex-slider-wrapper weex-ct', staticStyle: extractComponentStyle(this) }, http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/55378786/html5/render/vue/core/node.js ---------------------------------------------------------------------- diff --git a/html5/render/vue/core/node.js b/html5/render/vue/core/node.js index 87981d8..d07f3ed 100644 --- a/html5/render/vue/core/node.js +++ b/html5/render/vue/core/node.js @@ -17,7 +17,7 @@ * under the License. */ -import { extend } from '../utils' +import { extend, isArray } from '../utils' /** * remove text nodes in the nodes array. @@ -25,7 +25,7 @@ import { extend } from '../utils' * @return {Array} nodes without text nodes. */ export function trimTextVNodes (vnodes) { - if (Array.isArray(vnodes)) { + if (isArray(vnodes)) { return vnodes.filter(vnode => !!vnode.tag) } return vnodes @@ -54,64 +54,148 @@ function getListeners (vnode, evt) { } const supportedEvents = [ - 'tap', 'click', 'longpress', 'appear', 'disappear', - // 'touchstart', 'touchmove', 'touchend', + '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. - * @param {array} extras: extra events. + * @param {array | object} extras: extra events. You can pass in multiple arguments here. */ -export function createEventMap (context, extras = []) { +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 + const evtName = originalType || listenTo + if (typeof listenTo === 'function') { + handler = listenTo + } + else if (typeof listenTo === 'string') { + 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 + } + let evt = e + if (originalType && evtName !== listenTo) { + evt = extend({}, { type: listenTo }) + // weex didn't provide these two methods for event object. + delete event.preventDefault + delete event.stopPropagation + } + on && on.call(vm, evt) + 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 } } + if (!eventMap[evtName]) { + eventMap[evtName] = [] + } + eventMap[evtName].push(handler) } } - supportedEvents.concat(extras).forEach(bindFunc()) - // bindFunc('tap')('click') + + /** + * 1. Dispatch default supported events directly to user's event listeners. These + * listeners will be triggered before extras event handlers. + */ + supportedEvents.forEach(bindFunc()) + + /** + * 2. component's extra event bindings. This is mostly for the needs of component's + * own special behaviours. These handlers will be processed after the user's + * corresponding event handlers. + */ + if (extras) { + const len = extras.length + for (let i = 0; i < len; i++) { + const extra = extras[i] + if (isArray(extra)) { + extra.forEach(bindFunc()) + } + else if (typeof extra === 'object') { + for (const key in extra) { + bindFunc(key)(extra[key]) + } + } + } + } + + /** + * 3. special binding for click event, which should be a fastclick event without + * 300ms latency. + */ + 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 } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/55378786/html5/render/vue/env/wx-env.js ---------------------------------------------------------------------- diff --git a/html5/render/vue/env/wx-env.js b/html5/render/vue/env/wx-env.js index 4da3174..ecdf2ec 100644 --- a/html5/render/vue/env/wx-env.js +++ b/html5/render/vue/env/wx-env.js @@ -34,7 +34,7 @@ export function initEnv (viewportInfo, envInfo) { osName = 'iOS' } else if (osName.match(/Android/i)) { - osName = 'Android' + osName = 'android' } const osVersion = envInfo.os.version.val const env = { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/55378786/html5/render/vue/mixins/base.js ---------------------------------------------------------------------- diff --git a/html5/render/vue/mixins/base.js b/html5/render/vue/mixins/base.js index aa77d1f..ff31cd0 100644 --- a/html5/render/vue/mixins/base.js +++ b/html5/render/vue/mixins/base.js @@ -37,7 +37,7 @@ import { // import { extractComponentStyle } from '../core' -import config from '../config' +// import config from '../config' let lazyloadWatched = false function watchLazyload () { @@ -139,13 +139,13 @@ export default { return arr }, - _getParentScroller () { - let parent = this - while (parent && config.scrollableTypes.indexOf(parent.$options._componentTag) <= -1) { - parent = parent.$options.parent - } - return parent - }, + // _getParentScroller () { + // let parent = this + // while (parent && config.scrollableTypes.indexOf(parent.$options._componentTag) <= -1) { + // parent = parent.$options.parent + // } + // return parent + // }, _fireLazyload (el) { if (process.env.NODE_ENV === 'development') { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/55378786/html5/render/vue/mixins/scrollable.js ---------------------------------------------------------------------- diff --git a/html5/render/vue/mixins/scrollable.js b/html5/render/vue/mixins/scrollable.js index 4f7b03c..54c87dd 100644 --- a/html5/render/vue/mixins/scrollable.js +++ b/html5/render/vue/mixins/scrollable.js @@ -107,6 +107,14 @@ export default { this._innerWidth = rect.width this._innerHeight = rect.height } + const loadingEl = this._loading && this._loading.$el + const refreshEl = this._refresh && this._refresh.$el + if (loadingEl) { + this._innerHeight -= loadingEl.getBoundingClientRect().height + } + if (refreshEl) { + this._innerHeight -= refreshEl.getBoundingClientRect().height + } // inner width is always the viewport width somehow in horizontal // scoller, therefore the inner width should be reclaculated. if (this.scrollDirection === 'horizontal' && children) { @@ -137,7 +145,7 @@ export default { this._innerLength = innerLength this._loadmoreReset = true } - if (this._loadmoreReset && this.reachBottom()) { + if (this._loadmoreReset && this.reachBottom(this.loadmoreoffset)) { this._loadmoreReset = false this.$emit('loadmore', event) } @@ -149,19 +157,15 @@ export default { return (!!wrapper) && (wrapper.scrollTop <= 0) }, - reachBottom () { + reachBottom (offset) { const wrapper = this.$refs.wrapper const inner = this.$refs.inner - const offset = parseInt(this.loadmoreoffset) * weex.config.env.scale + offset = parseInt(offset || 0) * weex.config.env.scale if (wrapper && inner) { - // const innerRect = inner.getBoundingClientRect() - // const wrapperRect = wrapper.getBoundingClientRect() const key = this.scrollDirection === 'horizontal' ? 'width' : 'height' - // const innerLength = innerRect[key] - // const wrapperLength = wrapperRect[key] const innerLength = this[`_inner${key[0].toUpperCase()}${key.substr(1)}`] const wrapperLength = this[`_wrapper${key[0].toUpperCase()}${key.substr(1)}`] const scrollOffset = this.scrollDirection === 'horizontal' http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/55378786/html5/render/vue/utils/style.js ---------------------------------------------------------------------- diff --git a/html5/render/vue/utils/style.js b/html5/render/vue/utils/style.js index 0d74721..482e01a 100644 --- a/html5/render/vue/utils/style.js +++ b/html5/render/vue/utils/style.js @@ -30,6 +30,29 @@ const noUnitsNumberKeys = [ 'lines' ] +// whether to support using 0.5px to paint 1px width border. +let _supportHairlines: ?boolean +export function supportHairlines () { + if (typeof _supportHairlines === 'undefined') { + const dpr = window.devicePixelRatio + if (dpr && dpr >= 2 && document.documentElement) { + const docElm = document.documentElement + const testElm = document.createElement('div') + const fakeBody = document.createElement('body') + const beforeNode = docElm.firstElementChild || docElm.firstChild + testElm.style.border = '0.5px solid transparent' + fakeBody.appendChild(testElm) + docElm.insertBefore(fakeBody, beforeNode) + _supportHairlines = testElm.offsetHeight === 1 + docElm.removeChild(fakeBody) + } + else { + _supportHairlines = false + } + } + return _supportHairlines +} + /** * remove comments from a cssText. */ @@ -77,7 +100,12 @@ function getUnitScaleMap () { function limitScale (val, limit) { limit = limit || 1 const sign = val === 0 ? 0 : val > 0 ? 1 : -1 - return Math.abs(val) > limit ? val : sign * limit + let newVal = Math.abs(val) > limit ? val : sign * limit + // support 1px device width. + if (newVal === 1 && val < 1 && supportHairlines()) { + newVal = 0.5 + } + return newVal } function parseScale (val: number, unit: string): string { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/55378786/html5/test/render/vue/core/node.js ---------------------------------------------------------------------- diff --git a/html5/test/render/vue/core/node.js b/html5/test/render/vue/core/node.js index 910e390..562a9c7 100644 --- a/html5/test/render/vue/core/node.js +++ b/html5/test/render/vue/core/node.js @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ /* global Event */ import { init } from '../helper/runtime' @@ -31,7 +49,7 @@ init('core node', (Vue, helper) => { * child vnode -> parent vnode. * e.g. div -> foo (whoes root element is the div.) */ - const evt = new Event('click', { bubbles: true }) + const evt = new Event('tap', { bubbles: true }) el.dispatchEvent(evt) helper.registerDone(id, (tracker) => { @@ -49,7 +67,7 @@ init('core node', (Vue, helper) => { * click inner div. should just trigget the inner handler and * shouldn't bubbe to outter div. */ - const evt = new Event('click', { bubbles: true }) + const evt = new Event('tap', { bubbles: true }) inner.dispatchEvent(evt) helper.registerDone(id, (tracker) => { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/55378786/package.json ---------------------------------------------------------------------- diff --git a/package.json b/package.json index 91a2f28..f99aec9 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "subversion": { "browser": "0.5.0", "framework": "0.20.6", - "vue-render": "0.11.52", + "vue-render": "0.11.56", "transformer": ">=0.1.5 <0.5" }, "description": "A framework for building Mobile cross-platform UI", http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/55378786/packages/weex-vue-render/package.json ---------------------------------------------------------------------- diff --git a/packages/weex-vue-render/package.json b/packages/weex-vue-render/package.json index 485a099..6356cca 100644 --- a/packages/weex-vue-render/package.json +++ b/packages/weex-vue-render/package.json @@ -1,16 +1,16 @@ { "name": "weex-vue-render", - "version": "0.11.52", + "version": "0.11.56", "description": "Weex built-in components for Vue 2.x.", "license": "Apache-2.0", "main": "dist/index.js", "repository": { "type": "git", - "url": "g...@github.com:alibaba/weex.git" + "url": "g...@github.com:apache/incubator-weex.git" }, - "homepage": "http://alibaba.github.io/weex/", + "homepage": "http://weex.apache.org/", "bugs": { - "url": "https://github.com/alibaba/weex/issues" + "url": "https://issues.apache.org/jira/browse/WEEX/" }, "keywords": [ "weex",