Skip to content

Instantly share code, notes, and snippets.

@bdirito
Created June 8, 2016 16:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bdirito/e25b8fafe7363a0662e17d3b96a61ffa to your computer and use it in GitHub Desktop.
Save bdirito/e25b8fafe7363a0662e17d3b96a61ffa to your computer and use it in GitHub Desktop.
# based on ion-sticky
# this is heavily modified however as ion-sticky does not work with
# collection-repeat. To make this work we make the assumption that
# if an element is removed from the 'top' of the list it does NOT
# cease to be there. (collection-repeat prunes the top as it goes out of
# scroll)
define ['ionic'], ->
angular.module 'bl-ion-sticky', ['ionic']
.directive 'blIonSticky', ($ionicPosition) ->
'ngInject'
restrict: 'A'
require: '^$ionicScroll'
link: ($scope, $element, $attr, $ionicScroll) ->
scroll = angular.element $ionicScroll.element
clone = null
createStickyClone = (element) ->
clone = angular.copy element
.css
position: 'absolute'
top: "#{$ionicPosition.position(scroll).top}px"
left: 0
right: 0
.addClass $attr.blIonStickyClass ? 'assertive'
.removeAttr 'ng-repeat-start'
.removeAttr 'ng-if'
scroll.parent().append clone
# compile the clone to put in angular .. really?
# we dont need - so removing
# $compile(clone) $scope
return clone
removeStickyClone = ->
if clone
clone.remove()
clone = null
lastActive = null
return
$scope.$on 'destroy', ->
removeStickyClone()
angular.element $ionicScroll.element
.off 'scroll'
return
updateSticky = ionic.throttle ->
active = null
itemDividers = $ $element
.find '.item-divider'
dividers = []
# get a listing of all the dividers
for d in itemDividers
d = $ d
parentXform = d.parent().css 'style'
if not parentXform or ~parentXform.indexOf '-9999'
dividers.push d
# find out if there is any elements above the threshold of viewability - if so get the last one
for d, i in dividers
d = $ d
next = $ dividers[i + 1]
if $ionicPosition.offset(d).top - d.outerHeight() < 0 # the current item is not above the top
if i == dividers.length - 1 or ($ionicPosition.offset(next).top - next.outerHeight() > 0) # and the next one is not above the top
active = d
break
# see if we should *change* the clone in the dom; and do it ifso
# TODO: the .find(.collection-repeat-container) is fragile - but we are not actually garunteed any .item-dividers, so keep it for now
if $ionicPosition.offset($element).top < $ionicPosition.offset($element.find('.collection-repeat-container')).top
removeStickyClone()
else if active and active != lastActive
removeStickyClone()
lastActive = active
createStickyClone active
# push the clone up when a new one comes in from below
if clone and next and ($ionicPosition.offset(next).top < $ionicPosition.offset(clone).top + clone.outerHeight())
cloneTop = Number.parseInt clone.css 'top'
clone.css 'top', cloneTop + $ionicPosition.offset(next).top - ($ionicPosition.offset(clone).top + clone.outerHeight())
, 50 # note i reduced a 200 ms orig rate down to 50ms so the 'pushing' behaviour would look smoother
scroll.on 'scroll', (event) ->
updateSticky()
@bdirito
Copy link
Author

bdirito commented Jun 9, 2016

just as a warning - this is intended as an example not production code. Ill not be updating this gist if/when I find & fix bugs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment