Skip to content
This repository has been archived by the owner on Sep 8, 2020. It is now read-only.

Persistent State #164

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions src/ui-layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ angular.module('ui.layout', [])
var sizePattern = /\d+\s*(px|%)\s*$/i;

Layout.addLayout(ctrl);
if ($attrs.layoutId) {
ctrl.id = $attrs.layoutId;
}

ctrl.containers = [];
ctrl.movingSplitbar = null;
Expand Down Expand Up @@ -120,6 +123,12 @@ angular.module('ui.layout', [])
afterContainer.uncollapsedSize = afterContainer.size;
}

// store the current value in local storage to preserve size also when reloading the window
if($window.localStorage !== undefined) {
$window.localStorage.setItem(beforeContainer.storageId, beforeContainer.uncollapsedSize + 'px');
$window.localStorage.setItem(afterContainer.storageId, afterContainer.uncollapsedSize + 'px');
}

// move the splitbar
ctrl.movingSplitbar[position] = newPosition;

Expand Down Expand Up @@ -161,6 +170,26 @@ angular.module('ui.layout', [])
}
}

function loadContainerState(container) {
// load uncollapsedSize from local storage if available:
container.uncollapsedSize = null;
if($window.localStorage !== undefined) {
container.uncollapsedSize = $window.localStorage.getItem(container.storageId);
}
if(container.uncollapsedSize === null) {
container.uncollapsedSize = container.size;
}
}

/**
* Updates the storage ids of all containers according to the id of this controller and the index of the container.
*/
function updateContainerStorageIds() {
ctrl.containers.forEach(function(c, i) {
c.storageId = ctrl.id + ':' + i;
});
}

//================================================================================
// Public Controller Functions
//================================================================================
Expand Down Expand Up @@ -248,7 +277,7 @@ angular.module('ui.layout', [])
};

/**
* Sets the default size for each container.
* Sets the default size and position (left, top) for each container.
*/
ctrl.calculate = function() {
var c, i;
Expand Down Expand Up @@ -363,6 +392,9 @@ angular.module('ui.layout', [])
container.index = index;
ctrl.containers.splice(index, 0, container);

updateContainerStorageIds();
loadContainerState(container);

ctrl.calculate();
};

Expand Down Expand Up @@ -396,6 +428,7 @@ angular.module('ui.layout', [])
if(newIndex >= 0) {
ctrl.containers.splice(newIndex, 1);
}
updateContainerStorageIds();
ctrl.calculate();
} else {
console.error("removeContainer for container that did not exist!");
Expand Down Expand Up @@ -903,7 +936,6 @@ angular.module('ui.layout', [])
scope.container.resizable = scope.resizable;
}
scope.container.size = scope.size;
scope.container.uncollapsedSize = scope.size;
scope.container.minSize = scope.minSize;
scope.container.maxSize = scope.maxSize;
ctrl.addContainer(scope.container);
Expand Down
69 changes: 60 additions & 9 deletions test/layout-scenar.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ splitMoveTests('mouse', 'mousedown', 'mousemove', 'mouseup');

// Wrapper to abstract over using touch events or mouse events.
function splitMoveTests(description, startEvent, moveEvent, endEvent) {
return describe('Directive: uiLayout with ' + description + ' events', function () {
var element, scope, compile, $timeout,
return describe('Directive: uiLayout with ' + description + ' events', function() {
var element, scope, compile, $timeout, $window,
validTemplate = '<div ui-layout><header ui-layout-container></header><footer ui-layout-container></footer></div>',
defaultDividerSize = 10;

Expand All @@ -29,15 +29,23 @@ function splitMoveTests(description, startEvent, moveEvent, endEvent) {

module('ui.layout');

inject(function ($rootScope, $compile, _$timeout_) {
inject(function($rootScope, $compile, _$timeout_, _$window_) {
scope = $rootScope.$new();
compile = $compile;
$timeout = _$timeout_;
$window = _$window_;
});
});

beforeEach(function() {
// clear local storage:
if($window.localStorage !== undefined) {
$window.localStorage.clear();
}
});

afterEach(function () {
if (element) element.remove();
if(element) element.remove();
});

describe('require', function () {
Expand All @@ -62,12 +70,13 @@ function splitMoveTests(description, startEvent, moveEvent, endEvent) {

describe('the slider', function () {

var element_bb, $splitbar, splitbar_bb, splitbarLeftPos;
var element_bb, leftContainer, $splitbar, splitbar_bb, splitbarLeftPos;

beforeEach(function () {
element = createDirective();

element_bb = element[0].getBoundingClientRect();
leftContainer = angular.element(_jQuery(element[0]).find('header')[0]).isolateScope();
$splitbar = _jQuery(element[0]).find('.ui-splitbar');
splitbar_bb = $splitbar[0].getBoundingClientRect();

Expand All @@ -83,7 +92,7 @@ function splitMoveTests(description, startEvent, moveEvent, endEvent) {

expect(window.requestAnimationFrame).not.toHaveBeenCalled();
expect(Math.ceil(splitbar_bb.left)).toEqual(splitbarLeftPos);

expect($window.localStorage.getItem(leftContainer.container.storageId)).toBeNull();
});

it('should do nothing when moving around it', function () {
Expand All @@ -95,16 +104,17 @@ function splitMoveTests(description, startEvent, moveEvent, endEvent) {

expect(window.requestAnimationFrame).not.toHaveBeenCalled();
expect(Math.ceil(splitbar_bb.left)).toEqual(splitbarLeftPos);

expect($window.localStorage.getItem(leftContainer.container.storageId)).toBeNull();
});

it('should follow the ' + description, function () {
browserTrigger($splitbar, startEvent, { y: splitbarLeftPos });
browserTrigger($splitbar, moveEvent, { y: element_bb.height / 4});
expect(window.requestAnimationFrame).toHaveBeenCalled();

var expextedPos = Math.floor(element_bb.height / 4);
expect(Math.ceil(parseFloat($splitbar[0].style.top))).toEqual(expextedPos);
var expectedPos = Math.floor(element_bb.height / 4);
expect(Math.ceil(parseFloat($splitbar[0].style.top))).toEqual(expectedPos);
expect($window.localStorage.getItem(leftContainer.container.storageId)).toEqual(expectedPos + 'px');

browserTrigger(document.body, endEvent);
});
Expand All @@ -119,6 +129,7 @@ function splitMoveTests(description, startEvent, moveEvent, endEvent) {
expect(window.requestAnimationFrame).not.toHaveBeenCalled();

expect(Math.ceil(parseFloat($splitbar[0].style.top))).toEqual(expectedPos);
expect($window.localStorage.getItem(leftContainer.container.storageId)).toBeNull();
});

it('should not follow the ' + description + ' after ' + startEvent, function () {
Expand All @@ -134,6 +145,46 @@ function splitMoveTests(description, startEvent, moveEvent, endEvent) {
var expectedPos = Math.floor(element_bb.height / 4);
expect(window.requestAnimationFrame.calls.count()).toEqual(1);
expect(Math.ceil(parseFloat($splitbar[0].style.top))).toEqual(expectedPos);
expect($window.localStorage.getItem(leftContainer.container.storageId)).toEqual(expectedPos + 'px');
});

describe('persistent state', function() {

var leftContainerElement, rightContainerElement, $splitbar, splitbar_bb, splitbarLeftPos;

beforeEach(function() {
leftContainerElement = _jQuery(element[0]).find('header')[0];
rightContainerElement = _jQuery(element[0]).find('footer')[0];
$splitbar = _jQuery(element[0]).find('.ui-splitbar');
splitbar_bb = $splitbar[0].getBoundingClientRect();

splitbarLeftPos = Math.ceil(splitbar_bb.left);
});

it('should initially respect size from attributes', function() {
expect(leftContainerElement.style.width).toEqual('');
expect(rightContainerElement.style.width).toEqual('');
});

it('should save the saved splitbar position', function() {
browserTrigger($splitbar, 'mousedown', { y: splitbarLeftPos });
browserTrigger($splitbar, 'mousemove', { y: 150 });
expect(window.requestAnimationFrame).toHaveBeenCalled();

var expectedPos = Math.floor(150);
expect(Math.ceil(parseFloat($splitbar[0].style.top))).toEqual(expectedPos);
expect($window.localStorage.getItem(leftContainer.container.storageId)).toEqual(expectedPos + 'px');

browserTrigger(document.body, 'mouseup');

if(element) element.remove();
element = createDirective();

splitbar_bb = $splitbar[0].getBoundingClientRect();
splitbarLeftPos = Math.ceil(splitbar_bb.left);
expect(Math.ceil(parseFloat($splitbar[0].style.top))).toEqual(expectedPos);
});

});

describe('collapse buttons', function() {
Expand Down
3 changes: 3 additions & 0 deletions test/uiLayoutContainer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ describe('Directive: uiLayoutContainer', function () {
expect(acScope.container.minSize).toBeNull();
expect(acScope.container.maxSize).toBeNull();

// every container has a storageId:
expect(acScope.container.storageId).not.toBeNull();

});

});