Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

angular-sticky-table-header

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

angular-sticky-table-header - npm Package Compare versions

Comparing version 0.1.3 to 0.2.0

4

bower.json
{
"name": "angular-sticky-table-header",
"version": "0.1.3",
"version": "0.2.0",
"description": "Sticky headers for tables",

@@ -14,3 +14,3 @@ "main": "dist/angular-sticky-table-header.js",

"jquery": "^1.11",
"watch-dom": "^0.0"
"watch-dom": "~0.0"
},

@@ -17,0 +17,0 @@ "keywords": [

@@ -20,3 +20,3 @@ angular.module('watchDom', []).constant('watchDomOptions', {

mutationObserver.observe(element, angular.extend({}, watchDomOptions, options));
return mutationObserver.disconnect;
return mutationObserver.disconnect.bind(mutationObserver);
};

@@ -46,5 +46,11 @@ }

restrict: 'A',
link: function (scope, element, attrs) {
scope: {
disabled: '=',
rows: '='
},
template: '<div ng-transclude></div>',
transclude: true,
link: function (scope, element) {
angular.extend(scope, {
isStuck: false,
stuck: false,
mutationObserver: null,

@@ -63,3 +69,3 @@ offset: {},

removeClones: function () {
scope.isStuck = false;
scope.stuck = false;
element.find('.' + options.cloneClassName).remove();

@@ -80,7 +86,7 @@ },

setOffset: function () {
scope.offset = scope.tr.getBoundingClientRect();
scope.offset = angular.element(scope.tr).offset();
},
setStuck: function (bool) {
scope.$apply(function () {
scope.isStuck = !!bool;
scope.stuck = !!bool;
});

@@ -98,6 +104,6 @@ },

var scroll = $window.scrollY;
if (!scope.isStuck && scroll >= scope.offset.top) {
if (!scope.stuck && scroll >= scope.offset.top) {
scope.setClonedCellWidths();
scope.setStuck(true);
} else if (scope.isStuck && scroll < scope.offset.top) {
} else if (scope.stuck && scroll < scope.offset.top) {
scope.setStuck(false);

@@ -114,24 +120,43 @@ }

});
},
on: function () {
scope.observeTr();
scope.addEvents();
},
off: function () {
scope.mutationObserver();
scope.removeEvents();
scope.removeClones();
},
addEvents: function () {
angular.element($window).on({
'resize.angularStickyTableHeader': _.debounce(scope.setClonedCellWidths.bind(scope), options.interval),
'scroll.angularStickyTableHeader': _.debounce(scope.checkScroll.bind(scope), options.interval)
});
},
removeEvents: function () {
angular.element($window).off('.angularStickyTableHeader');
},
changeDisabled: function (disabled, old) {
if (disabled === old) {
return;
}
if (disabled) {
scope.off();
} else {
scope.on();
scope.resetClone();
}
}
});
// enable/disable api
scope.$watch('disabled', scope.changeDisabled);
// watch rows, and re-measure column widths when they change
if (attrs.rows) {
scope.$watch(function () {
return scope[attrs.rows];
}, scope.rowsChanged);
}
scope.$watch('rows', scope.rowsChanged);
// fired when stuck state changes
scope.$watch('isStuck', scope.toggleClone);
// start observing header for DOM changes
scope.observeTr();
// listen on window resize event
angular.element($window).on({
'resize.angularStickyTableHeader': _.debounce(scope.setClonedCellWidths.bind(scope), options.interval),
'scroll.angularStickyTableHeader': _.debounce(scope.checkScroll.bind(scope), options.interval)
});
scope.$watch('stuck', scope.toggleClone);
// teardown
scope.$on('$destroy', function () {
angular.element($window).off('.angularStickyTableHeader');
scope.mutationObserver();
});
scope.$on('$destroy', scope.off);
// init
scope.on();
// helpers

@@ -138,0 +163,0 @@ function ifClone(fn) {

{
"name": "angular-sticky-table-header",
"version": "0.1.3",
"version": "0.2.0",
"description": "Sticky headers for tables",

@@ -5,0 +5,0 @@ "main": "dist/angular-sticky-table-header.js",

@@ -23,3 +23,7 @@ angular-sticky-table-header [![Build Status](https://travis-ci.org/turn/angular-sticky-table-header.svg?branch=master)](https://travis-ci.org/turn/angular-sticky-table-header)

<div ng-controller="fooCtrl">
<div sticky-table-header rows="rowCollection">
<div
sticky-table-header
rows="rowCollection"
disabled="expression"
>
<table>

@@ -46,2 +50,4 @@ ...

$scope.expression = false;
});

@@ -48,0 +54,0 @@ ```

@@ -25,3 +25,9 @@ angular

restrict: 'A',
link: function (scope, element, attrs) {
scope: {
disabled: '=',
rows: '='
},
template: '<div ng-transclude></div>',
transclude: true,
link: function (scope, element) {

@@ -31,3 +37,3 @@ angular.extend(scope, {

// show the cloned <tr>?
isStuck: false,
stuck: false,

@@ -66,3 +72,3 @@ // MutationObserver bound to the original <tr>

scope.isStuck = false;
scope.stuck = false;

@@ -96,3 +102,3 @@ element

scope.offset = scope.tr.getBoundingClientRect();
scope.offset = angular.element(scope.tr).offset();

@@ -104,3 +110,3 @@ },

scope.$apply(function(){
scope.isStuck = !!bool;
scope.stuck = !!bool;
});

@@ -128,6 +134,6 @@

if (!scope.isStuck && scroll >= scope.offset.top) {
if (!scope.stuck && scroll >= scope.offset.top) {
scope.setClonedCellWidths();
scope.setStuck(true);
} else if (scope.isStuck && scroll < scope.offset.top) {
} else if (scope.stuck && scroll < scope.offset.top) {
scope.setStuck(false);

@@ -155,34 +161,67 @@ }

},
on: function () {
scope.observeTr();
scope.addEvents();
},
off: function () {
scope.mutationObserver();
scope.removeEvents();
scope.removeClones();
},
addEvents: function () {
angular.element($window).on({
'resize.angularStickyTableHeader': _.debounce(scope.setClonedCellWidths.bind(scope), options.interval),
'scroll.angularStickyTableHeader': _.debounce(scope.checkScroll.bind(scope), options.interval)
});
},
removeEvents: function () {
angular.element($window).off('.angularStickyTableHeader');
},
changeDisabled: function (disabled, old) {
if (disabled === old) {
return;
}
if (disabled) {
scope.off();
} else {
scope.on();
scope.resetClone();
}
}
});
// enable/disable api
scope.$watch('disabled', scope.changeDisabled);
// watch rows, and re-measure column widths when they change
if (attrs.rows) {
scope.$watch(function(){
return scope[attrs.rows];
}, scope.rowsChanged);
}
scope.$watch('rows', scope.rowsChanged);
// fired when stuck state changes
scope.$watch('isStuck', scope.toggleClone);
scope.$watch('stuck', scope.toggleClone);
// start observing header for DOM changes
scope.observeTr();
// listen on window resize event
angular.element($window).on({
'resize.angularStickyTableHeader': _.debounce(scope.setClonedCellWidths.bind(scope), options.interval),
'scroll.angularStickyTableHeader': _.debounce(scope.checkScroll.bind(scope), options.interval)
});
// teardown
scope.$on('$destroy', function() {
angular.element($window).off('.angularStickyTableHeader');
scope.mutationObserver();
});
scope.$on('$destroy', scope.off);
// init
scope.on();
// helpers
function ifClone (fn) {

@@ -189,0 +228,0 @@ return util.guard(fn, cloneExists);

@@ -40,2 +40,3 @@ // Generated by CoffeeScript 1.7.1

_this.scope.$digest();
_this.scope = _this.element.scope();
return $window = {

@@ -57,3 +58,3 @@ scrollY: 0,

this.scope.createClone();
return expect(($((this.element.find('thead tr'))[1]).find('th')).length).toBe(this.scope.columnCollection.length);
return expect(($((this.element.find('thead tr'))[1]).find('th')).length).toBe(this.scope.$parent.columnCollection.length);
});

@@ -103,6 +104,6 @@ it('should clone the <tr>\'s events', function() {

describe('#removeClones', function() {
it('should set scope.isStuck to false', function() {
it('should set scope.stuck to false', function() {
this.scope.createClone();
this.scope.removeClones();
return expect(this.scope.isStuck).toBe(false);
return expect(this.scope.stuck).toBe(false);
});

@@ -133,10 +134,10 @@ return it('should remove all <tr> clones', function() {

describe('#setOffset', function() {
it('should call getBoundingClientRect on the first <tr>', function() {
spyOn((this.element.find('tr'))[0], 'getBoundingClientRect');
it('should call getOffset on the first <tr>', function() {
spyOn(($()).__proto__, 'offset');
this.scope.setOffset();
return expect((this.element.find('tr'))[0].getBoundingClientRect).toHaveBeenCalled();
return expect(($()).__proto__.offset).toHaveBeenCalled();
});
return it('should set scope.offset equal to the value returned by getBoundingClientRect', function() {
this.scope.offset = null;
spyOn((this.element.find('tr'))[0], 'getBoundingClientRect').andReturn('foo');
spyOn(($()).__proto__, 'offset').andReturn('foo');
this.scope.setOffset();

@@ -147,20 +148,20 @@ return expect(this.scope.offset).toEqual('foo');

describe('#setStuck', function() {
it('should set scope.isStuck equal to the boolean passed into it', function() {
this.scope.isStuck = null;
it('should set scope.stuck equal to the boolean passed into it', function() {
this.scope.stuck = null;
this.scope.setStuck(true);
return expect(this.scope.isStuck).toBe(true);
return expect(this.scope.stuck).toBe(true);
});
return it('should coerce non-boolean values into booleans', function() {
this.scope.setStuck(true);
expect(this.scope.isStuck).toBe(true);
expect(this.scope.stuck).toBe(true);
this.scope.setStuck('foo');
expect(this.scope.isStuck).toBe(true);
expect(this.scope.stuck).toBe(true);
this.scope.setStuck(42);
expect(this.scope.isStuck).toBe(true);
expect(this.scope.stuck).toBe(true);
this.scope.setStuck(null);
expect(this.scope.isStuck).toBe(false);
expect(this.scope.stuck).toBe(false);
this.scope.setStuck(0);
expect(this.scope.isStuck).toBe(false);
expect(this.scope.stuck).toBe(false);
this.scope.setStuck(false);
return expect(this.scope.isStuck).toBe(false);
return expect(this.scope.stuck).toBe(false);
});

@@ -214,5 +215,5 @@ });

});
it('should call #setStuck with true and #setClonedCellWidths with no arguments when scope.isStuck is false and scrollY is >= offset.top', function() {
it('should call #setStuck with true and #setClonedCellWidths with no arguments when scope.stuck is false and scrollY is >= offset.top', function() {
this.scope.clone = true;
this.scope.isStuck = false;
this.scope.stuck = false;
this.scope.offset = {

@@ -226,5 +227,5 @@ top: 0

});
it('should call #setStuck with false when scope.isStuck is true and scrollY is < offset.top', function() {
it('should call #setStuck with false when scope.stuck is true and scrollY is < offset.top', function() {
this.scope.clone = true;
this.scope.isStuck = true;
this.scope.stuck = true;
this.scope.offset = {

@@ -239,3 +240,3 @@ top: 1

this.scope.clone = true;
this.scope.isStuck = true;
this.scope.stuck = true;
this.scope.offset = {

@@ -246,3 +247,3 @@ top: 0

this.scope.checkScroll();
this.scope.isStuck = false;
this.scope.stuck = false;
this.scope.offset = {

@@ -266,10 +267,80 @@ top: 1

});
return describe('$destroy', function() {
return it('should remove the mutation observer', function() {
describe('#on', function() {
return it('should call #observeTr and #addEvents with no arguments', function() {
spyOn(this.scope, 'observeTr');
spyOn(this.scope, 'addEvents');
this.scope.on();
expect(this.scope.observeTr).toHaveBeenCalledWith;
return expect(this.scope.addEvents).toHaveBeenCalledWith;
});
});
describe('#off', function() {
return it('should call #mutationObserver, #removeEvents, and #removeClones with no arguments', function() {
this.scope.mutationObserver = function() {};
spyOn(this.scope, 'mutationObserver');
spyOn(this.scope, 'removeEvents');
spyOn(this.scope, 'removeClones');
this.scope.off();
expect(this.scope.mutationObserver).toHaveBeenCalledWith;
expect(this.scope.removeEvents).toHaveBeenCalledWith;
return expect(this.scope.removeClones).toHaveBeenCalledWith;
});
});
describe('#changeDisabled', function() {
it('shouldn\'t call anything if the 1st argument is identical to the 2nd argument', function() {
spyOn(this.scope, 'on');
spyOn(this.scope, 'off');
spyOn(this.scope, 'resetClone');
this.scope.changeDisabled(true, true);
expect(this.scope.on).not.toHaveBeenCalled();
expect(this.scope.off).not.toHaveBeenCalled();
return expect(this.scope.resetClone).not.toHaveBeenCalled();
});
it('should call #off with no arguments if the 1st argument is truthy', function() {
spyOn(this.scope, 'off');
this.scope.changeDisabled(true);
return expect(this.scope.off).toHaveBeenCalledWith;
});
return it('should call #on and #resetClone with no arguments if the 1st argument is truthy', function() {
spyOn(this.scope, 'on');
spyOn(this.scope, 'resetClone');
this.scope.changeDisabled(false);
expect(this.scope.on).toHaveBeenCalledWith;
return expect(this.scope.resetClone).toHaveBeenCalledWith;
});
});
describe('$destroy', function() {
return it('should call #off with no arguments', function() {
this.scope.mutationObserver = function() {};
spyOn(this.scope, 'off');
this.scope.$destroy();
return expect(this.scope.mutationObserver).toHaveBeenCalled();
return expect(this.scope.off).toHaveBeenCalledWith;
});
});
return describe('$watches', function() {
it('should call #changeDisabled when scope.disabled changes', inject(function($timeout) {
spyOn(this.scope, 'changeDisabled');
this.element.attr('disabled', 'foo');
this.scope.$apply();
return $timeout(function() {
return expect(this.scope.changeDisabled).toHaveBeenCalled();
});
}));
it('should call #rowsChanged when scope.rows changes', inject(function($timeout) {
spyOn(this.scope, 'rowsChanged');
this.element.attr('rows', 'foo');
this.scope.$apply();
return $timeout(function() {
return expect(this.scope.rowsChanged).toHaveBeenCalled();
});
}));
return it('should call #toggleClone when scope.stuck changes', inject(function($timeout) {
spyOn(this.scope, 'toggleClone');
this.element.attr('stuck', 'foo');
this.scope.$apply();
return $timeout(function() {
return expect(this.scope.toggleClone).toHaveBeenCalled();
});
}));
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc