-
-
Save Poordeveloper/e6a1714ea399f95c779f to your computer and use it in GitHub Desktop.
m.directive('ionSticky', ['$ionicPosition', '$compile', '$timeout', function ($ionicPosition, $compile, $timeout) { | |
return { | |
restrict: 'A', | |
require: '^$ionicScroll', | |
link: function ($scope, $element, $attr, $ionicScroll) { | |
var scroll = angular.element($ionicScroll.element); | |
var clone; | |
// creates the sticky clone and adds it to DOM | |
var createStickyClone = function ($element) { | |
clone = $element.clone().css({ | |
position: 'absolute', | |
top: $ionicPosition.position(scroll).top + "px", | |
left: 0, | |
right: 0 | |
}); | |
clone[0].className += " assertive"; | |
clone.removeAttr('ng-repeat-start'); | |
clone.removeAttr('ng-if'); | |
scroll.parent().append(clone); | |
// compile the clone so that anything in it is in Angular lifecycle. | |
$compile(clone)($scope); | |
}; | |
var removeStickyClone = function () { | |
if (clone) | |
clone.remove(); | |
clone = null; | |
}; | |
$scope.$on("$destroy", function () { | |
// remove the clone, unbind the scroll listener | |
removeStickyClone(); | |
angular.element($ionicScroll.element).off('scroll'); | |
}); | |
var lastActive; | |
var updateSticky = ionic.throttle(function() { | |
var active = null; | |
var dividers = []; | |
var tmp = $element[0].getElementsByClassName("item-divider"); | |
for (var i = 0; i < tmp.length; ++i) dividers.push(angular.element(tmp[i])); | |
if (dividers.length == 0) return; | |
if (!clone) createStickyClone(angular.element(dividers[0][0])) | |
dividers.sort(function(a, b) { return $ionicPosition.offset(a).top - $ionicPosition.offset(b).top; }); | |
var sctop = $ionicPosition.offset(scroll).top; | |
if ($ionicPosition.offset(dividers[0]).top - sctop - dividers[0].prop('offsetHeight') > 0) { | |
var letter = dividers[0][0].innerHTML.trim(); | |
var i = $scope.letters.indexOf(letter); | |
if (i == 0) return; | |
active = $scope.letters[i-1]; | |
} else for (var i = 0; i < dividers.length; ++i) { // can be changed to binary search | |
if ($ionicPosition.offset(dividers[i]).top - sctop - dividers[i].prop('offsetHeight') < 0) { // this equals to jquery outerHeight | |
if (i === dividers.length-1 || $ionicPosition.offset(dividers[i+1]).top - sctop - | |
(dividers[i].prop('offsetHeight') + dividers[i+1].prop('offsetHeight')) > 0) { | |
active = dividers[i][0].innerHTML.trim(); | |
break; | |
} | |
} | |
} | |
if (lastActive != active) { | |
if (active) clone[0].innerHTML = active; | |
if (lastActive) { | |
var e = scroll.parent()[0].getElementsByClassName(lastActive); | |
if (e && e[0]) e[0].className = e[0].className.replace(/assertive/g,''); | |
} | |
if (active) { | |
var e = scroll.parent()[0].getElementsByClassName(active); | |
if (e && e[0]) e[0].className += " assertive"; | |
} | |
lastActive = active; | |
} | |
}, 200); | |
scroll.on('scroll', function (event) { | |
updateSticky(); | |
}); | |
} | |
} | |
}]); |
Is there a solution to this bug or is it near impossible to sort for collection-repeat?
Think I have a fix for this. Divider elements can sometimes be in the DOM but not actually be positioned in the list. You can see this because they have a transform: translate3d(-9999px, -9999px, 0px)
applied to the parent. If you exclude these elements from the dividers list, you'll only consider dividers that are actually visible.
Replace line 44:
for (var i = 0; i < tmp.length; ++i) dividers.push(angular.element(tmp[i]));
With:
for (var i = 0; i < tmp.length; ++i){
// Get the parent's transform value.
var elt = angular.element(tmp[i]);
var parentTransform = elt.parent().css('transform');
// Exclude dividers positioned out of the DOM
if (!parentTransform || parentTransform.indexOf("-9999") == -1){
dividers.push(elt);
}
}
i used element with ng-repeat its working, but it loops ng-repeat 8 times
That doesnt always work. collection-repeat has the capacity to add or remove elements to the dom as it scrolls up and gets 'too old'
My version: https://gist.github.com/bdirito/e25b8fafe7363a0662e17d3b96a61ffa
It assumes that if something got removed from the dom thats simply an artifact of collection-repeat and not a removal from the underlying repeat object (valid in my case). It has several other modifications for things that I was personally interested in. Its also in coffeescript with ngInject, requirejs(amd) and jquery dependencies. However it should get people an idea.
hi, the plugin works just great out of the box with collection-repeat with cache disabled, but when the view is cached it doesn't do the job anymore, i.e when i select an item in the list and then press the back button to return to the list, it is not effective.
Any suggestion about this ?
@egamer106, I did get this bug too.