Skip to content

Commit

Permalink
Merge pull request #27 from rlems/scrollbody-update
Browse files Browse the repository at this point in the history
fix for issue #8
  • Loading branch information
keithnlarsen committed Apr 19, 2016
2 parents d998321 + 5aafc1c commit a2049ea
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 54 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Then add the directive to the element that you with to stick to the top of the p
```html
<table ng-app="MyHappyModule" id="testtable">
<thead>
<tr fsm-sticky-header scroll-body="'#testtable'" scroll-stop='50'>
<tr fsm-sticky-header scroll-body="#testtable" scroll-stop='50'>
<th>Column One Header</th>
<th>Column Two Header</th>
</tr>
Expand Down
6 changes: 3 additions & 3 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@

<div id="area1" class="section text-area">

<h2 fsm-sticky-header scroll-body="'#area1'" scroll-stop="50">Just a block of text</h2>
<h2 fsm-sticky-header scroll-body="#area1" scroll-stop="50">Just a block of text</h2>
<div class="text-content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus at commodo neque, in pellentesque massa. Quisque nibh nisi, eleifend at finibus quis, euismod in metus. Vestibulum sit amet ultricies enim. Nullam odio elit, sollicitudin non varius sit amet, pretium eu metus. Mauris lacinia feugiat odio, et bibendum ligula consectetur et. Proin aliquet eros vel pulvinar mattis. Cras a rutrum lorem, ut luctus dolor. Sed vel eros ut orci sagittis euismod. Curabitur gravida elit sit amet mi rhoncus malesuada.
Expand All @@ -73,7 +73,7 @@ <h2 fsm-sticky-header scroll-body="'#area1'" scroll-stop="50">Just a block of te

<div id="area2" class="section text-area">

<h2 fsm-sticky-header scroll-body="'#area2'" scroll-stop="50">Another block of text</h2>
<h2 fsm-sticky-header scroll-body="#area2" scroll-stop="50">Another block of text</h2>
<div class="text-content">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus at commodo neque, in pellentesque massa. Quisque nibh nisi, eleifend at finibus quis, euismod in metus. Vestibulum sit amet ultricies enim. Nullam odio elit, sollicitudin non varius sit amet, pretium eu metus. Mauris lacinia feugiat odio, et bibendum ligula consectetur et. Proin aliquet eros vel pulvinar mattis. Cras a rutrum lorem, ut luctus dolor. Sed vel eros ut orci sagittis euismod. Curabitur gravida elit sit amet mi rhoncus malesuada.
Expand All @@ -94,7 +94,7 @@ <h2 fsm-sticky-header scroll-body="'#area2'" scroll-stop="50">Another block of t
</div>

<table id="testtable" fsm-big-data="dataPage of test.data take 50">
<thead fsm-sticky-header scroll-body="'#testtable'" scroll-stop="50">
<thead fsm-sticky-header scroll-body="#testtable" scroll-stop="50">
<tr>
<th colspan="2">Total records: {{::test.data.length | number: 0}}</th>
<th style="text-align: right" colspan="2">Displayed records: {{dataPage.length | number: 0}}</th>
Expand Down
108 changes: 58 additions & 50 deletions src/fsm-sticky-header.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,31 @@

(function(angular){
var fsm = angular.module('fsm', []);

fsm.directive('fsmStickyHeader', [function(){
return {
restrict: 'EA',
replace: false,
scope: {
scrollBody: '=',
scope: {
scrollBody: '@',
scrollStop: '=',
scrollableContainer: '=',
contentOffset: '=',
fsmZIndex: '='
},
link: function(scope, element, attributes, control){
var header = $(element, this);
var clonedHeader = null;
var content = $(scope.scrollBody);
var scrollableContainer = $(scope.scrollableContainer);
var contentOffset = scope.contentOffset || 0;

var content,
header = $(element, this),
clonedHeader = null,
scrollableContainer = $(scope.scrollableContainer),
contentOffset = scope.contentOffset || 0;

var unbindScrollBodyWatcher = scope.$watch('scrollBody', function(newValue, oldValue) {
content = $(scope.scrollBody);
init();
unbindScrollBodyWatcher();
});

if (scrollableContainer.length === 0){
scrollableContainer = $(window);
}
Expand All @@ -45,10 +51,10 @@

if ( (scrollTop > contentTop) && (scrollTop < contentBottom) ) {
if (!clonedHeader){
createClone();
createClone();
clonedHeader.css({ "visibility": "visible"});
}

if ( scrollTop < contentBottom && scrollTop > contentBottom - clonedHeader.outerHeight(false) ){
var top = contentBottom - scrollTop + scope.scrollStop - clonedHeader.outerHeight(false);
clonedHeader.css('top', top + 'px');
Expand Down Expand Up @@ -76,17 +82,17 @@
}
}
};

function calculateSize() {
clonedHeader.css({
top: scope.scrollStop,
width: header.outerWidth(),
left: header.offset().left
});

setColumnHeaderSizes();
};

function createClone(){
/*
* switch place with cloned element, to keep binding intact
Expand All @@ -99,20 +105,22 @@
position: 'fixed',
'z-index': scope.fsmZIndex || 10000,
visibility: 'hidden'
});
});
calculateSize();
};

scrollableContainer.on('scroll.fsmStickyHeader', determineVisibility).trigger("scroll");
scrollableContainer.on('resize.fsmStickyHeader', determineVisibility);
};

scope.$on('$destroy', function() {
scrollableContainer.off('.fsmStickyHeader');
});
function init() {
scrollableContainer.on('scroll.fsmStickyHeader', determineVisibility).trigger("scroll");
scrollableContainer.on('resize.fsmStickyHeader', determineVisibility);

scope.$on('$destroy', function () {
scrollableContainer.off('.fsmStickyHeader');
});
}
}
};
}]);

fsm.directive('fsmMenu', ['$location', function ($location) {
return {
restrict: 'A',
Expand Down Expand Up @@ -299,13 +307,13 @@

scope.$on('$destroy', function() {
menuButton.off('.fsmMenuButton');
});
});
}
}
});

fsm.directive('fsmBigData', ['$filter', function ($filter) {

return {
restrict: 'AE',
scope: {},
Expand All @@ -318,57 +326,57 @@
var rightHandExpression = attrs.fsmBigData.split(' of ')[1];
var pageSize = parseInt(rightHandExpression.split(' take ')[1], 10);
var sourceData = rightHandExpression.split(' take ')[0];

// Interesting things can be done here with the source object...
// var displayGetter = $parse(sourceData);
// var displaySetter = displayGetter.assign;
// var results = orderBy(displayGetter(scope.$parent), sortColumns);
// displaySetter(scope.$parent, results)

var rawData = [];
var sortedData = [];
var pagedData = [];
var page = $(window);
var sortTypes = [ 'None', 'Ascending', 'Descending' ];
var sortColumns = [];

transclude(function (clone, transcludedScope) {

transcludedScope.sortTypes = sortTypes;

element.append(clone);
transcludedScope[pagedDataName] = pagedData;

function nextPage() {
var dataSlice = sortedData.slice(pageSize * currentPage, (pageSize * (currentPage + 1)));
if (dataSlice.length > 0) {
pagedData.push.apply(pagedData, dataSlice);
currentPage++;
}
}

function renderData() {
if (sortColumns.length){
sortedData = orderBy(rawData, sortColumns);
}
else {
sortedData = rawData;
}

pagedData.length = 0;
currentPage = 0;
nextPage();
}

function addSortColumn(columnName, sortType) {

// If this column is currently in the sort stack, remove it.
for (var i = 0; i < sortColumns.length; i ++){
if (sortColumns[i].indexOf(columnName) > -1) {
sortColumns.splice(i, 1);
}
}

// Push this sort on the top of the stack (aka. array)
if (sortType > 0) {
var direction = '';
Expand All @@ -377,31 +385,31 @@
}
sortColumns.unshift(direction + columnName);
}

renderData();
}

function onPageScroll() {
var s = $(window).scrollTop();
var d = $(document).height();
var c = $(window).height();
var scrollPercent = (s / (d-c));

if (scrollPercent > 0.98) {
// We use scope.apply here to tell angular about these changes because
// they happen outside of angularjs context... we're using jquery here
// to figure out when we need to load another page of data.
transcludedScope.$apply(nextPage);
}
}

transcludedScope.$parent.$watchCollection(sourceData, function (newData) {
if (newData){
rawData = newData;
renderData();
}
});

transcludedScope.addSortColumn = addSortColumn;

page.on('scroll.fsmBigData', onPageScroll).trigger('scroll');
Expand All @@ -413,10 +421,10 @@
}
};
}]);

fsm.directive('fsmSort', [function () {
var sortIconTemplate = '<i class="fa fa-sort"></i>';

return {
restrict: 'AE',
replace: false,
Expand All @@ -428,18 +436,18 @@
columnHeader.append('&nbsp;');
columnHeader.append(sortIcon);
var currentSortType = 0;

function swapIcons(){
sortIcon.removeClass('fa-sort-desc fa-sort-asc fa-sort');

var classToAdd = 'fa-sort';

if (scope.$parent.sortTypes[currentSortType] === 'Ascending'){
classToAdd = 'fa-sort-asc';
} else if(scope.$parent.sortTypes[currentSortType] === 'Descending') {
classToAdd = 'fa-sort-desc';
}

sortIcon.addClass(classToAdd);
};

Expand All @@ -449,14 +457,14 @@
if (currentSortType == scope.$parent.sortTypes.length ){
currentSortType = 0;
}

scope.$apply( scope.$parent.addSortColumn(columnName, currentSortType) );

swapIcons();
};

columnHeader.css({ cursor: 'pointer' });

columnHeader.on('click.fsmSort', applySort);

columnHeader.on('keydown.fsmSort', function(e) {
Expand Down

0 comments on commit a2049ea

Please sign in to comment.