nuke-components
Advanced tools
Comparing version 0.0.22 to 0.0.23
{ | ||
"name": "nuke-components", | ||
"version": "0.0.22", | ||
"version": "0.0.23", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
/* @jsx createElement */ | ||
'use strict'; | ||
import {Component, createElement, findDOMNode} from 'weex-rx'; | ||
import {Dimensions, env} from 'nuke-core'; | ||
import {env} from 'nuke-core'; | ||
import View from './View'; | ||
const isWeex = env.isWeex; | ||
import View from './View'; | ||
import throttle from './throttle'; | ||
const isWeb = env.isWeb; | ||
const DEFAULT_END_REACHED_THRESHOLD = 500; | ||
const DEFAULT_SCROLL_CALLBACK_THROTTLE = 50; | ||
const FULL_WIDTH = 750; | ||
let dimensionsHeightRem = Dimensions.get('window').height; | ||
class ScrollView extends Component { | ||
static defaultProps = { | ||
scrollEventThrottle: DEFAULT_SCROLL_CALLBACK_THROTTLE, | ||
onEndReachedThreshold: DEFAULT_END_REACHED_THRESHOLD, | ||
showsHorizontalScrollIndicator: true, | ||
showsVerticalScrollIndicator: true, | ||
className: 'rx-scrollview', | ||
}; | ||
onScroll = () => { | ||
let self = this; | ||
if (!isWeex) { | ||
if (!self.ScrollViewDom) { | ||
self.ScrollViewDom = findDOMNode(this.refs.scroller); | ||
self.ScrollViewBodyDom = findDOMNode(this.refs.scrollerBody); | ||
self.scrollHeight = self.ScrollViewDom.offsetHeight; | ||
} | ||
// 时时卷上去的高度 | ||
self.lastScrollTop = self.scrollTop || 0; | ||
self.scrollTop = self.ScrollViewDom.scrollTop; | ||
lastScrollDistance = 0; | ||
lastScrollContentSize = 0; | ||
// 计算出可视列表高度 | ||
self.scrollBodyHeight = self.ScrollViewBodyDom.offsetHeight; | ||
handleScroll = (e) => { | ||
if ((self.scrollBodyHeight - self.scrollTop - self.scrollHeight) < self.loadMoreOffset && !self.canLoading && self.scrollBodyHeight != self.oldScrollBodyHeight) { | ||
self.canLoading = true; | ||
} else { | ||
self.canLoading = false; | ||
if (isWeb) { | ||
if (this.props.onScroll) { | ||
this.props.onScroll(e); | ||
} | ||
if (self.canLoading && self.scrollTop > self.lastScrollTop) { | ||
self.canLoading = false; | ||
if (self.oldScrollBodyHeight != self.scrollBodyHeight) { | ||
self.oldScrollBodyHeight = self.scrollBodyHeight; | ||
self.loadmore(); | ||
if (this.props.onEndReached) { | ||
if (!this.scrollerNode) { | ||
this.scrollerNode = findDOMNode(this.refs.scroller); | ||
this.scrollerContentNode = findDOMNode(this.refs.contentContainer); | ||
this.scrollerNodeSize = this.props.horizontal ? this.scrollerNode.offsetWidth : this.scrollerNode.offsetHeight; | ||
} | ||
} | ||
if (self.props.onScroll) { | ||
self.props.onScroll(); | ||
let scrollContentSize = this.props.horizontal ? this.scrollerContentNode.offsetWidth : this.scrollerContentNode.offsetHeight; | ||
let scrollDistance = this.props.horizontal ? this.scrollerNode.scrollLeft : this.scrollerNode.scrollTop; | ||
let isEndReached = (scrollContentSize - scrollDistance - this.scrollerNodeSize) < this.props.onEndReachedThreshold; | ||
let isScrollToEnd = scrollDistance > this.lastScrollDistance; | ||
let isLoadedMoreContent = scrollContentSize != this.lastScrollContentSize; | ||
if (isEndReached && isScrollToEnd && isLoadedMoreContent) { | ||
this.lastScrollContentSize = scrollContentSize; | ||
this.props.onEndReached(e); | ||
} | ||
this.lastScrollDistance = scrollDistance; | ||
} | ||
} | ||
} | ||
// Reset scroll state, only for web now. | ||
resetScroll = (options) => { | ||
if (isWeb) { | ||
this.lastScrollContentSize = 0; | ||
this.lastScrollDistance = 0; | ||
} | ||
} | ||
scrollTo = (place) => { | ||
scrollTo = (options) => { | ||
let self = this; | ||
let x = place.x; | ||
let y = place.y; | ||
if (!x) { | ||
x = 0; | ||
} | ||
let width; | ||
if (typeof(x) == 'string' && x.split('rem').length) { | ||
width = parseInt(x.split('rem')[0]); | ||
} else { | ||
width = parseInt(x); | ||
} | ||
if (!isWeex) { | ||
width = document.documentElement.clientWidth / 750 * width; | ||
} | ||
if (!y) { | ||
y = 0; | ||
} | ||
let height; | ||
if (typeof(y) == 'string' && y.split('rem').length) { | ||
height = parseInt(y.split('rem')[0]); | ||
} else { | ||
height = parseInt(y); | ||
} | ||
if (!isWeex) { | ||
height = document.documentElement.clientWidth / 750 * height; | ||
} | ||
let x = parseInt(options.x); | ||
let y = parseInt(options.y); | ||
if (isWeex) { | ||
let domModule = '@weex-module/dom'; | ||
let dom = require(domModule); | ||
let scroller = findDOMNode(self.refs.scroller); | ||
if (!width) { | ||
width = height; | ||
} | ||
dom.scrollToElement(scroller.ref, { | ||
offset: width | ||
let dom = require('@weex-module/dom'); | ||
let contentContainer = findDOMNode(this.refs.contentContainer); | ||
dom.scrollToElement(contentContainer.ref, { | ||
offset: x || y || 0 | ||
}); | ||
} else { | ||
findDOMNode(self.refs.scroller).scrollTop = height; | ||
findDOMNode(self.refs.scroller).scrollLeft = width; | ||
} | ||
} | ||
let pixelRatio = document.documentElement.clientWidth / FULL_WIDTH; | ||
showScrollbar() { | ||
if (this.props.showScrollIndicator == true) { | ||
return true; | ||
} else { | ||
return false; | ||
if (x >= 0) { | ||
findDOMNode(this.refs.scroller).scrollLeft = pixelRatio * x; | ||
} | ||
if (y >= 0) { | ||
findDOMNode(this.refs.scroller).scrollTop = pixelRatio * y; | ||
} | ||
} | ||
@@ -107,77 +90,93 @@ } | ||
let props = this.props; | ||
let self = this; | ||
let { | ||
id, | ||
style, | ||
scrollEventThrottle, | ||
showsHorizontalScrollIndicator, | ||
showsVerticalScrollIndicator, | ||
onRefresh, | ||
onEndReached, | ||
onEndReachedThreshold, | ||
} = this.props; | ||
self.loadmore = props.onLoadMore; | ||
if (!self.loadmore) { | ||
self.loadmore = function() {}; | ||
// In weex must be int value | ||
onEndReachedThreshold = parseInt(onEndReachedThreshold, 10); | ||
const contentContainerStyle = [ | ||
this.props.horizontal && styles.contentContainerHorizontal, | ||
this.props.contentContainerStyle, | ||
]; | ||
// bugfix: fix scrollview flex in ios 78 | ||
if (!isWeex && !this.props.horizontal) { | ||
contentContainerStyle.push(styles.containerWebStyle); | ||
} | ||
self.loadMoreOffset = props.loadMoreOffset || props.loadmoreoffset || 500; | ||
self.throttleNum = props.throttle || 100; | ||
props.style = { | ||
...styles.base, | ||
...props.style | ||
}; | ||
if (this.props.style) { | ||
let childLayoutProps = ['alignItems', 'justifyContent'] | ||
.filter((prop) => this.props.style[prop] !== undefined); | ||
if (props.horizontal) { | ||
self.scrollBoxWidthRem = 0; | ||
if (props.children.length) { | ||
props.children.map(function(item) { | ||
let itemWidth = item.props.style.width; | ||
if (itemWidth) { | ||
self.scrollBoxWidthRem += parseInt(itemWidth.split('rem')[0]); | ||
} | ||
}); | ||
} else { | ||
self.scrollBoxWidthRem += parseInt(props.children.props.style.width.split('rem')[0]); | ||
if (childLayoutProps.length !== 0) { | ||
console.warn( | ||
'ScrollView child layout (' + JSON.stringify(childLayoutProps) + | ||
') must be applied through the contentContainerStyle prop.' | ||
); | ||
} | ||
// styles.scrollBox.width = '' + self.scrollBoxWidthRem + 'rem'; | ||
let showScrollbar = self.showScrollbar(); | ||
} | ||
if (isWeex) { | ||
return <scroller {...props} showScrollbar={showScrollbar} scrollDirection="horizontal"> | ||
<View ref="scroller" t="scroll-view-2" style={styles.scrollBox}> | ||
{props.children} | ||
</View> | ||
</scroller>; | ||
} else { | ||
const contentContainer = | ||
<View | ||
ref="contentContainer" | ||
style={contentContainerStyle}> | ||
{this.props.children} | ||
</View>; | ||
// web 隐藏 scroller 滚动条 | ||
if (!showScrollbar && !document.getElementById('ScrollViewStyle')) { | ||
let style = document.createElement('style'); | ||
style.id = 'ScrollViewStyle'; | ||
document.head.appendChild(style); | ||
style.innerHTML = '.scroller::-webkit-scrollbar{display: none;}'; | ||
} | ||
const baseStyle = this.props.horizontal ? styles.baseHorizontal : styles.baseVertical; | ||
return <View ref="scroller" className="scroller" {...props} > | ||
<View style={styles.scrollBox} t="scroll-view-2"> | ||
{props.children} | ||
</View> | ||
</View>; | ||
} | ||
const scrollerStyle = { | ||
...baseStyle, | ||
...this.props.style | ||
}; | ||
let showsScrollIndicator = this.props.horizontal ? showsHorizontalScrollIndicator : showsVerticalScrollIndicator; | ||
if (isWeex) { | ||
return ( | ||
<scroller | ||
id={id} | ||
style={scrollerStyle} | ||
showScrollbar={showsScrollIndicator} | ||
onLoadmore={onEndReached} | ||
onRefresh = {onRefresh} | ||
loadmoreoffset={onEndReachedThreshold} | ||
scrollDirection={this.props.horizontal ? 'horizontal' : 'vertical'} | ||
> | ||
{this.props.children} | ||
</scroller> | ||
); | ||
} else { | ||
props.style.webkitOverflowScrolling = 'touch'; | ||
// 解决embed 标签引入一个页面,页面由大scroller组成,此时高度需要减去父级bar等因素的问题 | ||
// | ||
// if (!props.style.height) { | ||
// props.style.height = Dimensions.get('window').height; | ||
// } | ||
let handleScroll = this.handleScroll; | ||
if (scrollEventThrottle) { | ||
handleScroll = throttle(handleScroll, scrollEventThrottle); | ||
} | ||
if (isWeex) { | ||
return <scroller {...props} onLoadMore={self.loadmore} loadmoreoffset={self.loadMoreOffset} > | ||
<View ref="scroller" t="scroll-view-1"> | ||
{props.children} | ||
</View> | ||
</scroller>; | ||
} else { | ||
return <View ref="scroller" {...props} onScroll={throttle(self.onScroll, self.throttleNum)}> | ||
<View ref="scrollerBody" t="scroll-view-1">{props.children}</View> | ||
</View>; | ||
if (!showsScrollIndicator && !document.getElementById('rx-scrollview-style')) { | ||
let styleNode = document.createElement('style'); | ||
styleNode.id = 'rx-scrollview-style'; | ||
document.head.appendChild(styleNode); | ||
styleNode.innerHTML = `.${this.props.className}::-webkit-scrollbar{display: none;}`; | ||
} | ||
scrollerStyle.webkitOverflowScrolling = 'touch'; | ||
scrollerStyle.overflow = 'scroll'; | ||
return ( | ||
<View {...this.props} ref="scroller" style={scrollerStyle} onScroll={handleScroll}> | ||
{contentContainer} | ||
</View> | ||
); | ||
} | ||
@@ -187,14 +186,42 @@ } | ||
function throttle(func, wait) { | ||
var ctx, args, rtn, timeoutID; | ||
var last = 0; | ||
function call() { | ||
timeoutID = 0; | ||
last = +new Date(); | ||
rtn = func.apply(ctx, args); | ||
ctx = null; | ||
args = null; | ||
} | ||
return function throttled() { | ||
ctx = this; | ||
args = arguments; | ||
var delta = new Date() - last; | ||
if (!timeoutID) | ||
if (delta >= wait) call(); | ||
else timeoutID = setTimeout(call, wait - delta); | ||
return rtn; | ||
}; | ||
} | ||
const styles = { | ||
base: { | ||
overflow: 'scroll', | ||
display: 'block', | ||
baseVertical: { | ||
flex: 1, | ||
flexDirection: 'column', | ||
}, | ||
scrollBox: { | ||
// width: '2000rem', | ||
// justifyContent:'center', | ||
flexDirection:'row' | ||
baseHorizontal: { | ||
flex: 1, | ||
flexDirection: 'row', | ||
}, | ||
contentContainerHorizontal: { | ||
flexDirection: 'row', | ||
}, | ||
containerWebStyle: { | ||
display: 'block', | ||
} | ||
}; | ||
export default ScrollView; | ||
export default ScrollView; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
19426
683
1