-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.js
More file actions
129 lines (119 loc) · 3.18 KB
/
Copy pathindex.js
File metadata and controls
129 lines (119 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
var ispinner = require('ispinner')
var domify = require('domify')
var debounce = require('debounce')
var template = require('./template.html')
var events = require('event')
var Emitter = require('emitter')
var computedStyle = require('computed-style')
/**
* Init more with element(for insertAfter), callback ,and scrollable
*
* @param {Function} fn callback function that should return promise
* @param {Element} el
* @param {Element} scrollable [optional] default to el.parentNode
* @api public
*/
function More(el, fn, scrollable) {
if (!(this instanceof More)) return new More(el, fn, scrollable)
this.el = el
this.paddingBottom = parseInt(computedStyle(el, 'padding-bottom'), 10)
this.callback = fn
this.div = domify(template)
insertAfter(this.el, this.div)
this.spin = ispinner(this.div.querySelector('.more-refresh'), {width: '20px'})
scrollable = scrollable || el.parentNode
this.scrollable = scrollable
this._onscroll = debounce(this.onscroll.bind(this), 16)
events.bind(scrollable, 'scroll', this._onscroll)
}
Emitter(More.prototype)
/**
* On scroll event handler
*
* @api private
*/
More.prototype.onscroll = function (e) {
if (this.loading || this._disabled) return Promise.resolve(null)
if (!check(this.el, this.scrollable, this.paddingBottom) && e !== true) return
this.div.style.visibility = 'visible'
// var h = computedStyle(this.el, 'height')
this.loading = true
var self = this
var cb = function () {
self.loading = false
self.div.style.visibility = 'hidden'
setTimeout(function () {
self.emit('load')
}, 20)
}
var res = this.callback(cb)
if (res && typeof res.then === 'function') {
return res.then(cb, cb)
}
return Promise.resolve(null)
}
/**
* Disable loading more data
*
* @api public
*/
More.prototype.disable = function () {
this._disabled = true
this.div.style.display = 'none'
this.loading = false
}
/**
* Enable for loading more data
*
* @public
*/
More.prototype.enable = function () {
this._disabled = false
this.div.style.display = 'block'
this.div.style.visibility = 'hidden'
this.loading = false
}
/**
* Force more to start loading
*
* @return {undefined}
* @api public
*/
More.prototype.load = function () {
return this.onscroll(true)
}
/**
* Remove the appended element and unbind event
*
* @return {undefined}
* @api public
*/
More.prototype.remove = function () {
events.unbind(this.scrollable, 'scroll', this._onscroll)
this.div.parentNode.removeChild(this.div)
}
/**
* check if scrollable scroll to end
*/
function check(el, scrollable, pb) {
var rect = el.getBoundingClientRect()
var dis = rect.top + el.clientHeight - pb
if (scrollable === window) {
// viewport height
var vh = Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
if (dis <= vh) return true
} else {
var sh = scrollable.getBoundingClientRect().top + scrollable.clientHeight
if (dis <= sh) return true
}
return false
}
function insertAfter(referenceNode, newNode) {
var next = referenceNode.nextSibling
if (next) {
referenceNode.parentNode.insertBefore(newNode, next)
} else {
referenceNode.parentNode.appendChild(newNode)
}
}
module.exports = More