Skip to content
This repository has been archived by the owner on Mar 13, 2018. It is now read-only.

Commit

Permalink
refactoring for better extending positioning.
Browse files Browse the repository at this point in the history
  • Loading branch information
sorvell authored and Yvonne Yip committed Sep 16, 2014
1 parent 051babf commit 4587cae
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 58 deletions.
124 changes: 66 additions & 58 deletions core-overlay.html
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ <h2>Dialog</h2>
-->
<!--
Fired when the `core-overlay` needs to position itself. Optionally, implement
in order to position an overlay dynamically.
in order to position an overlay via code. If the overlay was not otherwise
positioned, it's important to indicate how the overlay has been positioned by
setting the `dimensions.position` object. For example, if the overlay has been
positioned via setting `right` and `top`, set dimensions.position to an
object like this: `{v: 'top', h: 'right'}`.
@event core-overlay-position
@param {Object} detail
Expand Down Expand Up @@ -373,10 +377,9 @@ <h2>Dialog</h2>
if (this.opened) {
// force layout so SD Polyfill renders
this.target.offsetHeight;
// TODO(sorvell): bc
this._shouldPosition = {left: true, top: true};
// if we are showing, then take care when measuring
this.prepareMeasure();
this.measure();
this.updateTargetDimensions();
this.finishMeasure();
if (this.layered) {
Expand Down Expand Up @@ -453,6 +456,40 @@ <h2>Dialog</h2>
this.target.style.display = '';
},

measure: function() {
if (this.dimensions) {
return;
}
var target = getComputedStyle(this.target);
var sizer = getComputedStyle(this.sizingTarget);
this.dimensions = {
position: {
v: target.top !== 'auto' ? 'top' : (target.bottom !== 'auto' ?
'bottom' : null),
h: target.left !== 'auto' ? 'left' : (target.right !== 'auto' ?
'right' : null),
css: target.position
},
size: {
v: sizer.maxHeight !== 'none',
h: sizer.maxWidth !== 'none'
},
margin: {
top: parseInt(target.marginTop) || 0,
right: parseInt(target.marginRight) || 0,
bottom: parseInt(target.marginBottom) || 0,
left: parseInt(target.marginLeft) || 0
}
};
// size at top/left if unset
if (!this.dimensions.position.v) {
this.target.style.top = '0px';
}
if (!this.dimensions.position.h) {
this.target.style.left = '0px';
}
},

finishMeasure: function(target) {
this.target.style.display = 'none';
this.target.style.transform = this.target.style.webkitTransform = '';
Expand Down Expand Up @@ -485,103 +522,74 @@ <h2>Dialog</h2>
}
},

updateTargetDimensions: function() {
this.positionTarget();
this.discoverDimensions();
this.sizeTarget();
this.applyDefaultPositioning();
},

positionTarget: function() {
// fire positioning event
this.fire('core-overlay-position', {target: this.target,
sizingTarget: this.sizingTarget, opened: this.opened});
},

discoverDimensions: function() {
if (this._dims) {
return;
}
var pos = this.target.style.position;
// this.target.style.position = 'absolute !important';
var target = getComputedStyle(this.target);
var sizer = getComputedStyle(this.sizingTarget);
this._dims = {
position: {
v: target.top !== 'auto' ? 'top' : (target.bottom !== 'auto' ?
'bottom' : null),
h: target.left !== 'auto' ? 'left' : (target.right !== 'auto' ?
'right' : null),
css: target.position
},
size: {
v: sizer.maxHeight !== 'none',
h: sizer.maxWidth !== 'none'
},
margin: {
top: parseInt(target.marginTop) || 0,
right: parseInt(target.marginRight) || 0,
bottom: parseInt(target.marginBottom) || 0,
left: parseInt(target.marginLeft) || 0
}
};
// size at top/left if unset
if (!this._dims.position.v) {
if (!this.dimensions.position.v) {
this.target.style.top = '0px';
}
if (!this._dims.position.h) {
if (!this.dimensions.position.h) {
this.target.style.left = '0px';
}
this.target.style.position = pos || '';
},

updateTargetDimensions: function() {
this.sizeTarget();
this.repositionTarget();
},

sizeTarget: function() {
this.sizingTarget.style.boxSizing = 'border-box';
var dims = this.dimensions;
var rect = this.target.getBoundingClientRect();
if (!this._dims.size.v) {
this.sizeDimension(rect, this._dims.position.v, 'top', 'bottom', 'Height');
if (!dims.size.v) {
this.sizeDimension(rect, dims.position.v, 'top', 'bottom', 'Height');
}
if (!this._dims.size.h) {
this.sizeDimension(rect, this._dims.position.h, 'left', 'right', 'Width');
if (!dims.size.h) {
this.sizeDimension(rect, dims.position.h, 'left', 'right', 'Width');
}
},

sizeDimension: function(rect, positionedBy, start, end, extent) {
var dims = this.dimensions;
var flip = (positionedBy === end);
var m = flip ? start : end;
var ws = window['inner' + extent];
var o = this._dims.margin[m] + (flip ? ws - rect[end] :
var o = dims.margin[m] + (flip ? ws - rect[end] :
rect[start]);
this.sizingTarget.style['max' + extent] = (ws - o) + 'px';
var offset = 'offset' + extent;
var o2 = this.target[offset] - this.sizingTarget[offset];
this.sizingTarget.style['max' + extent] = (ws - o - o2) + 'px';
},

// vertically and horizontally center if not positioned
applyDefaultPositioning: function() {
repositionTarget: function() {
// only center if position fixed.
if (this._dims.position.css !== 'fixed') {
if (this.dimensions.position.css !== 'fixed') {
return;
}
if (!this._dims.position.v) {
if (!this.dimensions.position.v) {
var t = (window.innerHeight - this.target.offsetHeight) / 2;
t -= this._dims.margin.top;
t -= this.dimensions.margin.top;
this.target.style.top = t + 'px';
}

if (!this._dims.position.h) {
if (!this.dimensions.position.h) {
var l = (window.innerWidth - this.target.offsetWidth) / 2;
l -= this._dims.margin.left;
l -= this.dimensions.margin.left;
this.target.style.left = l + 'px';
}
},

resetTargetDimensions: function() {
if (!this._dims.size.v) {
if (!this.dimensions.size.v) {
this.sizingTarget.style.maxHeight = '';
}
if (!this._dims.size.h) {
if (!this.dimensions.size.h) {
this.sizingTarget.style.maxWidth = '';
}
this._dims = null;
this.dimensions = null;
},

tapHandler: function(e) {
Expand Down
Loading

0 comments on commit 4587cae

Please sign in to comment.