blob: 070f3f7404490821a7e743323cfc8e5c494b3cd4 [file] [log] [blame]
/*
* 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.
*/
const _css = `
.weex-indicator {
position: absolute;
z-index: 10;
-webkit-flex-direction: row;
-ms-flex-direction: row;
-moz-box-orient: horizontal;
-moz-box-direction: normal;
flex-direction: row;
-webkit-box-orient: horizontal;
margin: 0;
padding: 0;
}
.weex-indicator-item {
display: inline-block;
position: relative;
border-radius: 50%;
width: 0.266667rem;
height: 0.266667rem;
background-color: #BBBBBB;
}
.weex-indicator-item + .weex-indicator-item {
margin-left: 0.133333rem;
}
.weex-indicator-item-active {
background-color: blue;
}
`
let extractComponentStyle, extend, extendKeys
function getIndicatorItemStyle (spec, isActive) {
const style = {}
style['background-color'] = spec[isActive ? 'itemSelectedColor' : 'itemColor']
style['width'] = style['height'] = spec['itemSize']
return style
}
function _render (context, h) {
const children = []
const mergedStyle = extractComponentStyle(context)
const indicatorSpecStyle = extendKeys(
{},
mergedStyle,
['itemColor', 'itemSelectedColor', 'itemSize']
)
for (let i = 0; i < Number(context.count); ++i) {
const classNames = ['weex-indicator-item weex-el']
let isActive = false
if (i === Number(context.active)) {
classNames.push('weex-indicator-item-active')
isActive = true
}
children.push(h('mark', {
staticClass: classNames.join(' '),
staticStyle: getIndicatorItemStyle(indicatorSpecStyle, isActive)
}))
}
context.$nextTick(function () {
_reLayout(this, _getVirtualRect(this, mergedStyle), _getLtbr(this, mergedStyle))
})
return h('nav', {
attrs: { 'weex-type': 'indicator' },
staticClass: 'weex-indicator weex-ct',
staticStyle: mergedStyle
}, children)
}
/**
* get indicator's virtual rect (width, height), which is the .
*/
function _getVirtualRect (context, mergedStyle) {
const ct = context._getParentRect()
const rect = ['width', 'height'].reduce((pre, key) => {
const msv = mergedStyle && mergedStyle[key]
pre[key] = msv ? parseFloat(msv) : ct[key]
return pre
}, {})
return rect
}
/**
* get indicator's ltbr values (without units).
*/
function _getLtbr (context, mergedStyle) {
return ['left', 'top', 'bottom', 'right'].reduce((pre, key) => {
const msv = mergedStyle && mergedStyle[key]
if (!msv && msv !== 0) { return pre }
pre[key] = parseFloat(msv)
return pre
}, {})
}
/**
* get indicator's rect (width, height).
*/
function _getIndicatorRect (el) {
let width, height
if (el.children.length === 1) {
width = height = window.getComputedStyle(el.children[0])
}
else {
const itemComputedStyle = window.getComputedStyle(el.children[1])
const padding = parseFloat(itemComputedStyle.marginLeft)
height = parseFloat(itemComputedStyle.height)
width = el.children.length * (height + padding) - padding
}
return { width, height }
}
/**
* calculate and reset indicator's width, height, and ltbr.
* @param {object} virtualRect. width and height of indicator's virtual rect box.
* @param {object} ltbr. the user specified left, top, bottom, right pixels (without units).
*/
function _reLayout (context, virtualRect, ltbr) {
const el = context.$el
const rect = _getIndicatorRect(el)
const rectWithPx = Object.keys(rect).reduce((pre, key) => {
pre[key] = rect[key] + 'px'
return pre
}, {})
extend(el.style, rectWithPx)
const axisMap = [{
dir: ltbr.left || ltbr.left === 0
? 'left' : ltbr.right || ltbr.right === 0
? 'right' : 'left',
scale: 'width'
}, {
dir: ltbr.top || ltbr.top === 0
? 'top' : ltbr.bottom || ltbr.bottom === 0
? 'bottom' : 'top',
scale: 'height'
}]
Object.keys(axisMap).forEach(key => {
const { dir, scale } = axisMap[key]
el.style[dir] = (ltbr[dir] || 0) + virtualRect[scale] / 2 - rect[scale] / 2 + 'px'
})
}
const indicator = {
name: 'weex-indicator',
methods: {
show: function () {
this.$el.style.visibility = 'visible'
}
},
data () {
return {
count: 0,
active: 0
}
},
render (createElement) {
const { count, active } = this.$vnode.data.attrs || {}
this.count = count
this.active = active
if (!this.count) { return }
return _render(this, createElement)
},
_css
}
export default {
init (weex) {
extractComponentStyle = weex.extractComponentStyle
extend = weex.utils.extend
extendKeys = weex.utils.extendKeys
weex.registerComponent('indicator', indicator)
}
}