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

Commit b094eaa

Browse files
committed
Add remainder when parent container size is odd
Remainder from rounding down of autoSize value is added to the last container of a layout. - Tests adjusted to account for the new container sizing - Few style fixes as suggested during PR review
1 parent b4eb6c2 commit b094eaa

File tree

3 files changed

+83
-33
lines changed

3 files changed

+83
-33
lines changed

src/ui-layout.js

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -268,15 +268,15 @@ angular.module('ui.layout', [])
268268
opts.minSizes[i] = optionValue(c.minSize);
269269
opts.maxSizes[i] = optionValue(c.maxSize);
270270

271-
if(opts.sizes[i] != 'auto') {
271+
if(opts.sizes[i] !== 'auto') {
272272
if(ctrl.isPercent(opts.sizes[i])) {
273273
opts.sizes[i] = ctrl.convertToPixels(opts.sizes[i], originalSize);
274274
} else {
275275
opts.sizes[i] = parseInt(opts.sizes[i]);
276276
}
277277
}
278278

279-
if(opts.minSizes[i] != null) {
279+
if(opts.minSizes[i] !== null) {
280280
if(ctrl.isPercent(opts.minSizes[i])) {
281281
opts.minSizes[i] = ctrl.convertToPixels(opts.minSizes[i], originalSize);
282282
} else {
@@ -287,7 +287,7 @@ angular.module('ui.layout', [])
287287
if(!c.collapsed && opts.sizes[i] < opts.minSizes[i]) opts.sizes[i] = opts.minSizes[i];
288288
}
289289

290-
if(opts.maxSizes[i] != null) {
290+
if(opts.maxSizes[i] !== null) {
291291
if(ctrl.isPercent(opts.maxSizes[i])) {
292292
opts.maxSizes[i] = ctrl.convertToPixels(opts.maxSizes[i], originalSize);
293293
} else {
@@ -306,8 +306,14 @@ angular.module('ui.layout', [])
306306
}
307307
}
308308

309+
// FIXME: autoSize if frequently Infinity, since numOfAutoContainers is frequently 0, no need to calculate that
309310
// set the sizing for the ctrl.containers
310-
var autoSize = Math.floor(availableSize / numOfAutoContainers);
311+
/*
312+
* When the parent size is odd, rounding down the `autoSize` leaves a remainder.
313+
* This remainder is added to the last auto-sized container in a layout.
314+
*/
315+
var autoSize = Math.floor(availableSize / numOfAutoContainers),
316+
remainder = availableSize - autoSize * numOfAutoContainers;
311317
for(i=0; i < ctrl.containers.length; i++) {
312318
c = ctrl.containers[i];
313319
c[ctrl.sizeProperties.flowProperty] = usedSpace;
@@ -317,7 +323,16 @@ angular.module('ui.layout', [])
317323
//TODO: adjust size if autosize is greater than the maxSize
318324

319325
if(!LayoutContainer.isSplitbar(c)) {
320-
var newSize = (opts.sizes[i] === 'auto') ? autoSize : opts.sizes[i];
326+
var newSize;
327+
if(opts.sizes[i] === 'auto') {
328+
newSize = autoSize;
329+
// add the rounding down remainder to the last auto-sized container in the layout
330+
if (remainder > 0 && i === ctrl.containers.length - 1) {
331+
newSize += remainder;
332+
}
333+
} else {
334+
newSize = opts.sizes[i];
335+
}
321336

322337
c.size = (newSize !== null) ? newSize : autoSize;
323338
} else {
@@ -500,8 +515,12 @@ angular.module('ui.layout', [])
500515
// to offset the lost space when converting from percents to pixels
501516
endDiff = (isLastContainer) ? ctrl.bounds[sizeProperty] - c[flowProperty] - c.uncollapsedSize : 0;
502517

503-
if(prevSplitbar) prevSplitbar[flowProperty] += (c.uncollapsedSize + endDiff);
504-
if(prevContainer) prevContainer.size += (c.uncollapsedSize + endDiff);
518+
if(prevSplitbar) {
519+
prevSplitbar[flowProperty] += (c.uncollapsedSize + endDiff);
520+
}
521+
if(prevContainer) {
522+
prevContainer.size += (c.uncollapsedSize + endDiff);
523+
}
505524

506525
} else {
507526
c.size = c.uncollapsedSize;
@@ -510,8 +529,12 @@ angular.module('ui.layout', [])
510529
// to offset the additional space added when collapsing
511530
endDiff = (isLastContainer) ? ctrl.bounds[sizeProperty] - c[flowProperty] - c.uncollapsedSize : 0;
512531

513-
if(prevSplitbar) prevSplitbar[flowProperty] -= (c.uncollapsedSize + endDiff);
514-
if(prevContainer) prevContainer.size -= (c.uncollapsedSize + endDiff);
532+
if(prevSplitbar) {
533+
prevSplitbar[flowProperty] -= (c.uncollapsedSize + endDiff);
534+
}
535+
if(prevContainer) {
536+
prevContainer.size -= (c.uncollapsedSize + endDiff);
537+
}
515538
}
516539
});
517540
$scope.$broadcast('ui.layout.toggle', c);

test/layout-scenar.spec.js

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ splitMoveTests('mouse', 'mousedown', 'mousemove', 'mouseup');
88
// Wrapper to abstract over using touch events or mouse events.
99
function splitMoveTests(description, startEvent, moveEvent, endEvent) {
1010
return describe('Directive: uiLayout with ' + description + ' events', function () {
11-
var element, scope, compile,
11+
var element, scope, compile, $timeout,
1212
validTemplate = '<div ui-layout><header ui-layout-container></header><footer ui-layout-container></footer></div>',
1313
defaultDividerSize = 10;
1414

@@ -29,9 +29,10 @@ function splitMoveTests(description, startEvent, moveEvent, endEvent) {
2929

3030
module('ui.layout');
3131

32-
inject(function ($rootScope, $compile) {
32+
inject(function ($rootScope, $compile, _$timeout_) {
3333
scope = $rootScope.$new();
3434
compile = $compile;
35+
$timeout = _$timeout_;
3536
});
3637
});
3738

@@ -110,7 +111,7 @@ function splitMoveTests(description, startEvent, moveEvent, endEvent) {
110111

111112
it('should not follow the ' + description + ' before ' + startEvent, function () {
112113
var expectedPos = Math.floor((element_bb.height - defaultDividerSize) / 2);
113-
expect(Math.ceil(parseFloat($splitbar[0].style.top))).toEqual(expectedPos); // Obvious...
114+
expect(Math.ceil(parseFloat($splitbar[0].style.top))).toEqual(expectedPos);
114115

115116
// Move without clicking on it
116117
browserTrigger($splitbar, moveEvent, { y: Math.random() * element_bb.width });
@@ -149,11 +150,12 @@ function splitMoveTests(description, startEvent, moveEvent, endEvent) {
149150
});
150151

151152
it('should toggle before', function() {
152-
var expectedSize = Math.floor((element_bb.height - defaultDividerSize) / 2);
153+
var expectedAutosized = Math.floor((element_bb.height - defaultDividerSize) / 2);
154+
153155
var $header = element.children().eq(0)[0];
154156

155-
expect(parseInt($splitbar[0].style.top)).toEqual(expectedSize);
156-
expect($header.getBoundingClientRect().height).toEqual(expectedSize);
157+
expect(parseInt($splitbar[0].style.top)).toEqual(expectedAutosized);
158+
expect($header.getBoundingClientRect().height).toEqual(expectedAutosized);
157159

158160
browserTrigger(toggleBeforeButton, 'click');
159161

@@ -163,28 +165,33 @@ function splitMoveTests(description, startEvent, moveEvent, endEvent) {
163165

164166
browserTrigger(toggleBeforeButton, 'click');
165167

166-
expect(parseInt($splitbar[0].style.top)).toEqual(expectedSize);
167-
expect($header.getBoundingClientRect().height).toEqual(expectedSize);
168+
expect(parseInt($splitbar[0].style.top)).toEqual(expectedAutosized);
169+
expect($header.getBoundingClientRect().height).toEqual(expectedAutosized);
168170
expect(toggleAfterButton.style.display).toBe('inline');
169171
});
170172

171173
it('should toggle after', function() {
172-
var expectedSize = Math.floor((element_bb.height - defaultDividerSize) / 2);
173-
var $footer = element.children().eq(2)[0];
174174

175-
expect(parseInt($splitbar[0].style.top)).toEqual(expectedSize);
176-
expect($footer.getBoundingClientRect().height).toEqual(expectedSize);
175+
var roundedHalf = Math.floor((element_bb.height - defaultDividerSize) / 2),
176+
expectedAutosized = roundedHalf,
177+
expectedLastAutosized = roundedHalf;
177178

178-
browserTrigger(toggleAfterButton, 'click');
179+
// add remainder to the last element when parent size is odd
180+
if (element_bb.height % 2 === 1) {
181+
expectedLastAutosized += 1;
182+
}
183+
var $footer = element.children().eq(2)[0];
184+
expect(parseInt($splitbar[0].style.top)).toEqual(expectedAutosized);
185+
expect($footer.getBoundingClientRect().height).toEqual(expectedLastAutosized);
179186

187+
browserTrigger(toggleAfterButton, 'click');
180188
expect(parseInt($splitbar[0].style.top)).toEqual(element_bb.height - defaultDividerSize);
181189
expect($footer.getBoundingClientRect().height).toEqual(0);
182190
expect(toggleBeforeButton.style.display).toBe('none');
183191

184192
browserTrigger(toggleAfterButton, 'click');
185-
186-
expect(parseInt($splitbar[0].style.top)).toEqual(expectedSize);
187-
expect($footer.getBoundingClientRect().height).toEqual(expectedSize);
193+
expect(parseInt($splitbar[0].style.top)).toEqual(expectedAutosized);
194+
expect($footer.getBoundingClientRect().height).toEqual(expectedLastAutosized);
188195
expect(toggleBeforeButton.style.display).toBe('inline');
189196
});
190197
});

test/layout.spec.js

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,18 @@ describe('Directive: uiLayout', function () {
361361
});
362362

363363
it('should initialise with equal width', function () {
364-
var expectedWidth = Math.floor((layoutBounds.width - defaultDividerSize) / 2);
364+
var expectedHeaderWidth = Math.floor((layoutBounds.width - defaultDividerSize) / 2),
365+
expectedFooterWidth = expectedHeaderWidth;
366+
367+
if (layoutBounds.width % 2 === 1) {
368+
expectedFooterWidth += 1; // "dangling pixel" added to the last autosized container in a layout
369+
}
370+
371+
365372
expect($header.style.left).toEqual('0px');
366-
expect($header.style.width).toEqual(expectedWidth + 'px');
367-
expect($footer.style.left).toEqual((expectedWidth + defaultDividerSize) + 'px');
368-
expect($footer.style.width).toEqual(expectedWidth + 'px');
373+
expect($header.style.width).toEqual(expectedHeaderWidth + 'px');
374+
expect($footer.style.left).toEqual((expectedHeaderWidth + defaultDividerSize) + 'px');
375+
expect($footer.style.width).toEqual(expectedFooterWidth + 'px');
369376
});
370377

371378
it('should have a split bar at the middle', function () {
@@ -405,14 +412,27 @@ describe('Directive: uiLayout', function () {
405412
expect(element).toHaveClass('ui-layout-row');
406413
});
407414

408-
it('should initialise with equal height', function () {
409-
var firstElemHeight = element.children()[0].getBoundingClientRect().height;
410-
for (var i = 0; i < element.children().length; i += 2) {
411-
expect(element.children()[i].getBoundingClientRect().height, 'tagName').toEqual(firstElemHeight);
415+
it('should initialise with equal height when parent container height has an even value', function () {
416+
var parentHeightEven = element[0].getBoundingClientRect().height % 2 === 0;
417+
if (parentHeightEven) {
418+
var firstElemHeight = element.children()[0].getBoundingClientRect().height;
419+
for (var i = 0; i < element.children().length; i += 2) {
420+
expect(element.children()[i].getBoundingClientRect().height, 'tagName').toEqual(firstElemHeight);
421+
}
422+
}
423+
});
424+
425+
it('should initialise with last container height larger by 1px when parent container height has an odd value', function () {
426+
var parentHeightOdd = element[0].getBoundingClientRect().height % 2 !== 0;
427+
if (parentHeightOdd) {
428+
var firstElemHeight = element.children()[0].getBoundingClientRect().height;
429+
var lastElementHeight = element.children()[2].getBoundingClientRect().height;
430+
expect(lastElementHeight).toEqual(firstElemHeight + 1);
412431
}
413432
});
414433

415434
it('should have a split bar at the middle', function () {
435+
// not an absolute middle. In case of odd height, last container is larger by 1px (remainder of the rounding down)
416436
var expectedMiddle = Math.floor((layoutBounds.height - defaultDividerSize) / 2);
417437
expect($sidebar.style.top).toEqual(expectedMiddle + 'px');
418438
});

0 commit comments

Comments
 (0)