Skip to content

Commit e213d1c

Browse files
committed
converted to the Viewport object
1 parent d3e25c3 commit e213d1c

File tree

1 file changed

+45
-81
lines changed

1 file changed

+45
-81
lines changed

src/ui-scroll.coffee

Lines changed: 45 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -125,43 +125,46 @@ angular.module('ui.scroll', [])
125125
div = table.find('div')
126126
result = table.find('tr')
127127
else
128-
result = angular.element('<' + repeaterType + '></' + repeaterType + '>')
128+
result = angular.element('<' + tagName + '></' + tagName + '>')
129129
result
130130

131131

132132

133133
Viewport = (element, controllers) ->
134134

135-
self = this
136-
137135
viewport = if controllers[0] and controllers[0].viewport then controllers[0].viewport else angular.element(window)
138136
viewport.css({'overflow-y': 'auto', 'display': 'block'})
139137

140138
topPadding = null
141139

142140
bottomPadding = null
143141

144-
self.createPaddingElements = (template) ->
142+
viewport.createPaddingElements = (template) ->
145143

146144
topPadding = new Padding template.localName
147145
element.before topPadding
148-
self.topPadding = topPadding.height
146+
viewport.topPadding = -> topPadding.height arguments
149147

150148
bottomPadding = new Padding template.localName
151149
element.after bottomPadding
152-
self.bottomPadding = bottomPadding.height
150+
viewport.bottomPadding = -> bottomPadding.height arguments
151+
152+
viewport.bottomDataPos = ->
153+
(viewport[0].scrollHeight ? viewport[0].document.documentElement.scrollHeight) - bottomPadding.height()
153154

154-
self.bottomDataPos = ->
155-
(viewport.scrollHeight ? viewport.document.documentElement.scrollHeight) - bottomPadding.height()
155+
viewport.topDataPos = -> topPadding.height()
156156

157-
self.topDataPos = -> topPadding.height()
157+
viewport.bottomVisiblePos = ->
158+
viewport.scrollTop() + viewport.outerHeight()
158159

159-
self.insertElement = (e, sibling) -> insertElement(e, sibling || topPadding)
160+
viewport.topVisiblePos = ->
161+
viewport.scrollTop()
160162

161-
self.insertElementAnimated = (e, sibling) -> insertElementAnimated(e, sibling || topPadding)
163+
viewport.insertElement = (e, sibling) -> insertElement(e, sibling || topPadding)
162164

163-
return
165+
viewport.insertElementAnimated = (e, sibling) -> insertElementAnimated(e, sibling || topPadding)
164166

167+
viewport
165168

166169

167170
require: ['?^uiScrollViewport']
@@ -192,8 +195,6 @@ angular.module('ui.scroll', [])
192195

193196
bufferSize = Math.max(3, +$attr.bufferSize || 10)
194197
bufferPadding = -> viewport.outerHeight() * Math.max(0.1, +$attr.padding || 0.1) # some extra space to initiate preload
195-
scrollHeight = (elem) -> elem[0].scrollHeight ? elem[0].document.documentElement.scrollHeight
196-
197198

198199
# initial settings
199200

@@ -206,53 +207,22 @@ angular.module('ui.scroll', [])
206207
eof = false
207208
bof = false
208209

210+
viewport = new Viewport element, controllers
211+
209212
# Padding element builder
210213
#
211214
# Calling linker is the only way I found to get access to the tag name of the template
212215
# to prevent the directive scope from pollution a new scope is created and destroyed
213216
# right after the builder creation is completed
214217
linker $scope.$new(), (template, scope) ->
215-
# Destroy template's scope to remove any watchers on it.
216-
scope.$destroy()
217-
218-
repeaterType = template[0].localName
219-
if repeaterType in ['dl']
220-
throw new Error 'ui-scroll directive does not support <' + template[0].localName + '> as a repeating tag: ' + template[0].outerHTML
221-
repeaterType = 'div' if repeaterType not in ['li', 'tr']
222-
223-
viewport = if controllers[0] and controllers[0].viewport then controllers[0].viewport else angular.element(window)
224-
viewport.css({'overflow-y': 'auto', 'display': 'block'})
225-
226-
padding = (repeaterType)->
227-
switch repeaterType
228-
when 'tr'
229-
table = angular.element('<table><tr><td><div></div></td></tr></table>')
230-
div = table.find('div')
231-
result = table.find('tr')
232-
result.paddingHeight = -> div.height.apply(div, arguments)
233-
else
234-
result = angular.element('<' + repeaterType + '></' + repeaterType + '>')
235-
result.paddingHeight = result.height
236-
result
237-
238-
topPadding = padding(repeaterType)
239-
element.before topPadding
240218

241-
bottomPadding = padding(repeaterType)
242-
element.after bottomPadding
219+
viewport.createPaddingElements(template[0])
243220

221+
# Destroy template's scope to remove any watchers on it.
222+
scope.$destroy()
223+
# also remove the template when the directive scope is destroyed
244224
$scope.$on '$destroy', -> template.remove()
245225

246-
builder =
247-
viewport: viewport
248-
topPadding: -> topPadding.paddingHeight.apply(topPadding, arguments)
249-
bottomPadding: -> bottomPadding.paddingHeight.apply(bottomPadding, arguments)
250-
bottomDataPos: -> scrollHeight(viewport) - bottomPadding.paddingHeight()
251-
topDataPos: -> topPadding.paddingHeight()
252-
insertElement: (e, sibling) -> insertElement(e, sibling || topPadding)
253-
insertElementAnimated: (e, sibling) -> insertElementAnimated(e, sibling || topPadding)
254-
255-
viewport = builder.viewport
256226
viewportScope = viewport.scope() || $rootScope
257227

258228
#v = new Viewport element, controllers
@@ -280,25 +250,19 @@ angular.module('ui.scroll', [])
280250
first = 1
281251
next = 1
282252
buffer.clear()
283-
builder.topPadding(0)
284-
builder.bottomPadding(0)
253+
viewport.topPadding(0)
254+
viewport.bottomPadding(0)
285255
eof = false
286256
bof = false
287257
adjustBuffer ridActual
288258

289-
bottomVisiblePos = ->
290-
viewport.scrollTop() + viewport.outerHeight()
291-
292-
topVisiblePos = ->
293-
viewport.scrollTop()
294-
295259
shouldLoadBottom = ->
296-
#log "bottom pos #{builder.bottomDataPos()} < bottom visible #{bottomVisiblePos()} + padding #{bufferPadding()} "
297-
!eof && builder.bottomDataPos() < bottomVisiblePos() + bufferPadding()
260+
#log "bottom pos #{viewport.bottomDataPos()} < bottom visible #{bottomVisiblePos()} + padding #{bufferPadding()} "
261+
!eof && viewport.bottomDataPos() < viewport.bottomVisiblePos() + bufferPadding()
298262

299263
clipBottom = ->
300264
# clip the invisible items off the bottom
301-
bottomHeight = 0 #builder.bottomPadding()
265+
bottomHeight = 0
302266
overage = 0
303267

304268
for i in [buffer.length-1..0]
@@ -307,7 +271,7 @@ angular.module('ui.scroll', [])
307271
newRow = rowTop isnt itemTop
308272
rowTop = itemTop
309273
itemHeight = item.element.outerHeight(true) if newRow
310-
if (builder.bottomDataPos() - bottomHeight - itemHeight > bottomVisiblePos() + bufferPadding())
274+
if (viewport.bottomDataPos() - bottomHeight - itemHeight > viewport.bottomVisiblePos() + bufferPadding())
311275
bottomHeight += itemHeight if newRow
312276
overage++
313277
eof = false
@@ -316,14 +280,14 @@ angular.module('ui.scroll', [])
316280
overage++
317281

318282
if overage > 0
319-
builder.bottomPadding(builder.bottomPadding() + bottomHeight)
283+
viewport.bottomPadding(viewport.bottomPadding() + bottomHeight)
320284
buffer.remove(buffer.length - overage, buffer.length)
321285
next -= overage
322-
#log 'clipped off bottom ' + overage + ' bottom padding ' + builder.bottomPadding()
286+
#log 'clipped off bottom ' + overage + ' bottom padding ' + viewport.bottomPadding()
323287

324288
shouldLoadTop = ->
325-
#log "top pos #{builder.topDataPos()} > top visible #{topVisiblePos()} - padding #{bufferPadding()}"
326-
!bof && (builder.topDataPos() > topVisiblePos() - bufferPadding())
289+
#log "top pos #{viewport.topDataPos()} > top visible #{topVisiblePos()} - padding #{bufferPadding()}"
290+
!bof && (viewport.topDataPos() > viewport.topVisiblePos() - bufferPadding())
327291

328292
clipTop = ->
329293
# clip the invisible items off the top
@@ -334,15 +298,15 @@ angular.module('ui.scroll', [])
334298
newRow = rowTop isnt itemTop
335299
rowTop = itemTop
336300
itemHeight = item.element.outerHeight(true) if newRow
337-
if (builder.topDataPos() + topHeight + itemHeight < topVisiblePos() - bufferPadding())
301+
if (viewport.topDataPos() + topHeight + itemHeight < viewport.topVisiblePos() - bufferPadding())
338302
topHeight += itemHeight if newRow
339303
overage++
340304
bof = false
341305
else
342306
break if newRow
343307
overage++
344308
if overage > 0
345-
builder.topPadding(builder.topPadding() + topHeight)
309+
viewport.topPadding(viewport.topPadding() + topHeight)
346310
buffer.remove(0, overage)
347311
first += overage
348312
#log 'clipped off top ' + overage + ' top padding ' + builder.topPadding()
@@ -364,7 +328,7 @@ angular.module('ui.scroll', [])
364328
adjustBuffer()
365329

366330
insertWrapperContent = (wrapper, sibling) ->
367-
builder.insertElement wrapper.element, sibling
331+
viewport.insertElement wrapper.element, sibling
368332
return true if isElementVisible(wrapper)
369333
wrapper.unregisterVisibilityWatcher = wrapper.scope.$watch () -> visibilityWatcher(wrapper)
370334
false
@@ -374,7 +338,7 @@ angular.module('ui.scroll', [])
374338
toBePrepended = []
375339
toBeRemoved = []
376340

377-
bottomPos = builder.bottomDataPos()
341+
bottomPos = viewport.bottomDataPos()
378342
for wrapper, i in buffer
379343
switch wrapper.op
380344
when 'prepend' then toBePrepended.unshift wrapper
@@ -386,30 +350,30 @@ angular.module('ui.scroll', [])
386350
wrapper.op = 'none'
387351
when 'insert'
388352
if (i == 0)
389-
promises = promises.concat (builder.insertElementAnimated wrapper.element)
353+
promises = promises.concat (viewport.insertElementAnimated wrapper.element)
390354
else
391-
promises = promises.concat (builder.insertElementAnimated wrapper.element, buffer[i-1].element)
355+
promises = promises.concat (viewport.insertElementAnimated wrapper.element, buffer[i-1].element)
392356
wrapper.op = 'none'
393357
when 'remove' then toBeRemoved.push wrapper
394358

395359
for wrapper in toBeRemoved
396360
promises = promises.concat (buffer.remove wrapper)
397361

398362
# for anything other than prepend adjust the bottomPadding height
399-
builder.bottomPadding(Math.max(0,builder.bottomPadding() - (builder.bottomDataPos() - bottomPos)))
363+
viewport.bottomPadding(Math.max(0,viewport.bottomPadding() - (viewport.bottomDataPos() - bottomPos)))
400364

401365
if toBePrepended.length
402-
bottomPos = builder.bottomDataPos()
366+
bottomPos = viewport.bottomDataPos()
403367
for wrapper in toBePrepended
404368
keepFetching = insertWrapperContent(wrapper) || keepFetching
405369
wrapper.op = 'none'
406370

407-
heightIncrement = builder.bottomDataPos() - bottomPos
371+
heightIncrement = viewport.bottomDataPos() - bottomPos
408372

409373
# adjust padding to prevent it from visually pushing everything down
410-
if builder.topPadding() >= heightIncrement
374+
if viewport.topPadding() >= heightIncrement
411375
# if possible, reduce topPadding
412-
builder.topPadding(builder.topPadding() - heightIncrement)
376+
viewport.topPadding(viewport.topPadding() - heightIncrement)
413377
else
414378
# if not, increment scrollTop
415379
viewport.scrollTop(viewport.scrollTop() + heightIncrement)
@@ -432,7 +396,7 @@ angular.module('ui.scroll', [])
432396
newRow = rowTop isnt itemTop
433397
rowTop = itemTop
434398
itemHeight = item.element.outerHeight(true) if newRow
435-
if newRow and (builder.topDataPos() + topHeight + itemHeight < topVisiblePos())
399+
if newRow and (viewport.topDataPos() + topHeight + itemHeight < viewport.topVisiblePos())
436400
topHeight += itemHeight
437401
else
438402
topVisible(item) if newRow
@@ -489,7 +453,7 @@ angular.module('ui.scroll', [])
489453
return if (rid and rid isnt ridActual) or $scope.$$destroyed
490454
if result.length < bufferSize
491455
eof = true
492-
builder.bottomPadding(0)
456+
viewport.bottomPadding(0)
493457
#log 'eof is reached'
494458
if result.length > 0
495459
clipTop()
@@ -508,7 +472,7 @@ angular.module('ui.scroll', [])
508472
return if (rid and rid isnt ridActual) or $scope.$$destroyed
509473
if result.length < bufferSize
510474
bof = true
511-
builder.topPadding(0)
475+
viewport.topPadding(0)
512476
#log 'bof is reached'
513477
if result.length > 0
514478
clipBottom() if buffer.length

0 commit comments

Comments
 (0)