diff --git a/src/ui-layout.js b/src/ui-layout.js index 0a2a5a9..63b913d 100644 --- a/src/ui-layout.js +++ b/src/ui-layout.js @@ -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; @@ -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; @@ -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 //================================================================================ @@ -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; @@ -363,6 +392,9 @@ angular.module('ui.layout', []) container.index = index; ctrl.containers.splice(index, 0, container); + updateContainerStorageIds(); + loadContainerState(container); + ctrl.calculate(); }; @@ -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!"); @@ -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); diff --git a/test/layout-scenar.spec.js b/test/layout-scenar.spec.js index a545d67..8f33906 100644 --- a/test/layout-scenar.spec.js +++ b/test/layout-scenar.spec.js @@ -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 = '
', defaultDividerSize = 10; @@ -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 () { @@ -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(); @@ -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 () { @@ -95,7 +104,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 follow the ' + description, function () { @@ -103,8 +112,9 @@ function splitMoveTests(description, startEvent, moveEvent, endEvent) { 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); }); @@ -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 () { @@ -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() { diff --git a/test/uiLayoutContainer.spec.js b/test/uiLayoutContainer.spec.js index ade2406..5953bd0 100644 --- a/test/uiLayoutContainer.spec.js +++ b/test/uiLayoutContainer.spec.js @@ -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(); + }); }); \ No newline at end of file