220 lines
7.1 KiB
JavaScript
220 lines
7.1 KiB
JavaScript
/**
|
|
* angular-strap
|
|
* @version v2.2.1 - 2015-03-10
|
|
* @link http://mgcrea.github.io/angular-strap
|
|
* @author Olivier Louvignes (olivier@mg-crea.com)
|
|
* @license MIT License, http://www.opensource.org/licenses/MIT
|
|
*/
|
|
'use strict';
|
|
|
|
angular.module('mgcrea.ngStrap.helpers.dimensions', [])
|
|
|
|
.factory('dimensions', ["$document", "$window", function($document, $window) {
|
|
|
|
var jqLite = angular.element;
|
|
var fn = {};
|
|
|
|
/**
|
|
* Test the element nodeName
|
|
* @param element
|
|
* @param name
|
|
*/
|
|
var nodeName = fn.nodeName = function(element, name) {
|
|
return element.nodeName && element.nodeName.toLowerCase() === name.toLowerCase();
|
|
};
|
|
|
|
/**
|
|
* Returns the element computed style
|
|
* @param element
|
|
* @param prop
|
|
* @param extra
|
|
*/
|
|
fn.css = function(element, prop, extra) {
|
|
var value;
|
|
if (element.currentStyle) { //IE
|
|
value = element.currentStyle[prop];
|
|
} else if (window.getComputedStyle) {
|
|
value = window.getComputedStyle(element)[prop];
|
|
} else {
|
|
value = element.style[prop];
|
|
}
|
|
return extra === true ? parseFloat(value) || 0 : value;
|
|
};
|
|
|
|
/**
|
|
* Provides read-only equivalent of jQuery's offset function:
|
|
* @required-by bootstrap-tooltip, bootstrap-affix
|
|
* @url http://api.jquery.com/offset/
|
|
* @param element
|
|
*/
|
|
fn.offset = function(element) {
|
|
var boxRect = element.getBoundingClientRect();
|
|
var docElement = element.ownerDocument;
|
|
return {
|
|
width: boxRect.width || element.offsetWidth,
|
|
height: boxRect.height || element.offsetHeight,
|
|
top: boxRect.top + (window.pageYOffset || docElement.documentElement.scrollTop) - (docElement.documentElement.clientTop || 0),
|
|
left: boxRect.left + (window.pageXOffset || docElement.documentElement.scrollLeft) - (docElement.documentElement.clientLeft || 0)
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Provides set equivalent of jQuery's offset function:
|
|
* @required-by bootstrap-tooltip
|
|
* @url http://api.jquery.com/offset/
|
|
* @param element
|
|
* @param options
|
|
* @param i
|
|
*/
|
|
fn.setOffset = function (element, options, i) {
|
|
var curPosition,
|
|
curLeft,
|
|
curCSSTop,
|
|
curTop,
|
|
curOffset,
|
|
curCSSLeft,
|
|
calculatePosition,
|
|
position = fn.css(element, 'position'),
|
|
curElem = angular.element(element),
|
|
props = {};
|
|
|
|
// Set position first, in-case top/left are set even on static elem
|
|
if (position === 'static') {
|
|
element.style.position = 'relative';
|
|
}
|
|
|
|
curOffset = fn.offset(element);
|
|
curCSSTop = fn.css(element, 'top');
|
|
curCSSLeft = fn.css(element, 'left');
|
|
calculatePosition = (position === 'absolute' || position === 'fixed') &&
|
|
(curCSSTop + curCSSLeft).indexOf('auto') > -1;
|
|
|
|
// Need to be able to calculate position if either
|
|
// top or left is auto and position is either absolute or fixed
|
|
if (calculatePosition) {
|
|
curPosition = fn.position(element);
|
|
curTop = curPosition.top;
|
|
curLeft = curPosition.left;
|
|
} else {
|
|
curTop = parseFloat(curCSSTop) || 0;
|
|
curLeft = parseFloat(curCSSLeft) || 0;
|
|
}
|
|
|
|
if (angular.isFunction(options)) {
|
|
options = options.call(element, i, curOffset);
|
|
}
|
|
|
|
if (options.top !== null ) {
|
|
props.top = (options.top - curOffset.top) + curTop;
|
|
}
|
|
if ( options.left !== null ) {
|
|
props.left = (options.left - curOffset.left) + curLeft;
|
|
}
|
|
|
|
if ('using' in options) {
|
|
options.using.call(curElem, props);
|
|
} else {
|
|
curElem.css({
|
|
top: props.top + 'px',
|
|
left: props.left + 'px'
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Provides read-only equivalent of jQuery's position function
|
|
* @required-by bootstrap-tooltip, bootstrap-affix
|
|
* @url http://api.jquery.com/offset/
|
|
* @param element
|
|
*/
|
|
fn.position = function(element) {
|
|
|
|
var offsetParentRect = {top: 0, left: 0},
|
|
offsetParentElement,
|
|
offset;
|
|
|
|
// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
|
|
if (fn.css(element, 'position') === 'fixed') {
|
|
|
|
// We assume that getBoundingClientRect is available when computed position is fixed
|
|
offset = element.getBoundingClientRect();
|
|
|
|
} else {
|
|
|
|
// Get *real* offsetParentElement
|
|
offsetParentElement = offsetParent(element);
|
|
|
|
// Get correct offsets
|
|
offset = fn.offset(element);
|
|
if (!nodeName(offsetParentElement, 'html')) {
|
|
offsetParentRect = fn.offset(offsetParentElement);
|
|
}
|
|
|
|
// Add offsetParent borders
|
|
offsetParentRect.top += fn.css(offsetParentElement, 'borderTopWidth', true);
|
|
offsetParentRect.left += fn.css(offsetParentElement, 'borderLeftWidth', true);
|
|
}
|
|
|
|
// Subtract parent offsets and element margins
|
|
return {
|
|
width: element.offsetWidth,
|
|
height: element.offsetHeight,
|
|
top: offset.top - offsetParentRect.top - fn.css(element, 'marginTop', true),
|
|
left: offset.left - offsetParentRect.left - fn.css(element, 'marginLeft', true)
|
|
};
|
|
|
|
};
|
|
|
|
/**
|
|
* Returns the closest, non-statically positioned offsetParent of a given element
|
|
* @required-by fn.position
|
|
* @param element
|
|
*/
|
|
var offsetParent = function offsetParentElement(element) {
|
|
var docElement = element.ownerDocument;
|
|
var offsetParent = element.offsetParent || docElement;
|
|
if(nodeName(offsetParent, '#document')) return docElement.documentElement;
|
|
while(offsetParent && !nodeName(offsetParent, 'html') && fn.css(offsetParent, 'position') === 'static') {
|
|
offsetParent = offsetParent.offsetParent;
|
|
}
|
|
return offsetParent || docElement.documentElement;
|
|
};
|
|
|
|
/**
|
|
* Provides equivalent of jQuery's height function
|
|
* @required-by bootstrap-affix
|
|
* @url http://api.jquery.com/height/
|
|
* @param element
|
|
* @param outer
|
|
*/
|
|
fn.height = function(element, outer) {
|
|
var value = element.offsetHeight;
|
|
if(outer) {
|
|
value += fn.css(element, 'marginTop', true) + fn.css(element, 'marginBottom', true);
|
|
} else {
|
|
value -= fn.css(element, 'paddingTop', true) + fn.css(element, 'paddingBottom', true) + fn.css(element, 'borderTopWidth', true) + fn.css(element, 'borderBottomWidth', true);
|
|
}
|
|
return value;
|
|
};
|
|
|
|
/**
|
|
* Provides equivalent of jQuery's width function
|
|
* @required-by bootstrap-affix
|
|
* @url http://api.jquery.com/width/
|
|
* @param element
|
|
* @param outer
|
|
*/
|
|
fn.width = function(element, outer) {
|
|
var value = element.offsetWidth;
|
|
if(outer) {
|
|
value += fn.css(element, 'marginLeft', true) + fn.css(element, 'marginRight', true);
|
|
} else {
|
|
value -= fn.css(element, 'paddingLeft', true) + fn.css(element, 'paddingRight', true) + fn.css(element, 'borderLeftWidth', true) + fn.css(element, 'borderRightWidth', true);
|
|
}
|
|
return value;
|
|
};
|
|
|
|
return fn;
|
|
|
|
}]);
|