123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- 'use strict';
- import { rtl as Rtl } from "./foundation.core.utils";
- var Box = {
- ImNotTouchingYou: ImNotTouchingYou,
- OverlapArea: OverlapArea,
- GetDimensions: GetDimensions,
- GetOffsets: GetOffsets,
- GetExplicitOffsets: GetExplicitOffsets
- }
- /**
- * Compares the dimensions of an element to a container and determines collision events with container.
- * @function
- * @param {jQuery} element - jQuery object to test for collisions.
- * @param {jQuery} parent - jQuery object to use as bounding container.
- * @param {Boolean} lrOnly - set to true to check left and right values only.
- * @param {Boolean} tbOnly - set to true to check top and bottom values only.
- * @default if no parent object passed, detects collisions with `window`.
- * @returns {Boolean} - true if collision free, false if a collision in any direction.
- */
- function ImNotTouchingYou(element, parent, lrOnly, tbOnly, ignoreBottom) {
- return OverlapArea(element, parent, lrOnly, tbOnly, ignoreBottom) === 0;
- };
- function OverlapArea(element, parent, lrOnly, tbOnly, ignoreBottom) {
- var eleDims = GetDimensions(element),
- topOver, bottomOver, leftOver, rightOver;
- if (parent) {
- var parDims = GetDimensions(parent);
- bottomOver = (parDims.height + parDims.offset.top) - (eleDims.offset.top + eleDims.height);
- topOver = eleDims.offset.top - parDims.offset.top;
- leftOver = eleDims.offset.left - parDims.offset.left;
- rightOver = (parDims.width + parDims.offset.left) - (eleDims.offset.left + eleDims.width);
- }
- else {
- bottomOver = (eleDims.windowDims.height + eleDims.windowDims.offset.top) - (eleDims.offset.top + eleDims.height);
- topOver = eleDims.offset.top - eleDims.windowDims.offset.top;
- leftOver = eleDims.offset.left - eleDims.windowDims.offset.left;
- rightOver = eleDims.windowDims.width - (eleDims.offset.left + eleDims.width);
- }
- bottomOver = ignoreBottom ? 0 : Math.min(bottomOver, 0);
- topOver = Math.min(topOver, 0);
- leftOver = Math.min(leftOver, 0);
- rightOver = Math.min(rightOver, 0);
- if (lrOnly) {
- return leftOver + rightOver;
- }
- if (tbOnly) {
- return topOver + bottomOver;
- }
- // use sum of squares b/c we care about overlap area.
- return Math.sqrt((topOver * topOver) + (bottomOver * bottomOver) + (leftOver * leftOver) + (rightOver * rightOver));
- }
- /**
- * Uses native methods to return an object of dimension values.
- * @function
- * @param {jQuery || HTML} element - jQuery object or DOM element for which to get the dimensions. Can be any element other that document or window.
- * @returns {Object} - nested object of integer pixel values
- * TODO - if element is window, return only those values.
- */
- function GetDimensions(elem){
- elem = elem.length ? elem[0] : elem;
- if (elem === window || elem === document) {
- throw new Error("I'm sorry, Dave. I'm afraid I can't do that.");
- }
- var rect = elem.getBoundingClientRect(),
- parRect = elem.parentNode.getBoundingClientRect(),
- winRect = document.body.getBoundingClientRect(),
- winY = window.pageYOffset,
- winX = window.pageXOffset;
- return {
- width: rect.width,
- height: rect.height,
- offset: {
- top: rect.top + winY,
- left: rect.left + winX
- },
- parentDims: {
- width: parRect.width,
- height: parRect.height,
- offset: {
- top: parRect.top + winY,
- left: parRect.left + winX
- }
- },
- windowDims: {
- width: winRect.width,
- height: winRect.height,
- offset: {
- top: winY,
- left: winX
- }
- }
- }
- }
- /**
- * Returns an object of top and left integer pixel values for dynamically rendered elements,
- * such as: Tooltip, Reveal, and Dropdown. Maintained for backwards compatibility, and where
- * you don't know alignment, but generally from
- * 6.4 forward you should use GetExplicitOffsets, as GetOffsets conflates position and alignment.
- * @function
- * @param {jQuery} element - jQuery object for the element being positioned.
- * @param {jQuery} anchor - jQuery object for the element's anchor point.
- * @param {String} position - a string relating to the desired position of the element, relative to it's anchor
- * @param {Number} vOffset - integer pixel value of desired vertical separation between anchor and element.
- * @param {Number} hOffset - integer pixel value of desired horizontal separation between anchor and element.
- * @param {Boolean} isOverflow - if a collision event is detected, sets to true to default the element to full width - any desired offset.
- * TODO alter/rewrite to work with `em` values as well/instead of pixels
- */
- function GetOffsets(element, anchor, position, vOffset, hOffset, isOverflow) {
- console.log("NOTE: GetOffsets is deprecated in favor of GetExplicitOffsets and will be removed in 6.5");
- switch (position) {
- case 'top':
- return Rtl() ?
- GetExplicitOffsets(element, anchor, 'top', 'left', vOffset, hOffset, isOverflow) :
- GetExplicitOffsets(element, anchor, 'top', 'right', vOffset, hOffset, isOverflow);
- case 'bottom':
- return Rtl() ?
- GetExplicitOffsets(element, anchor, 'bottom', 'left', vOffset, hOffset, isOverflow) :
- GetExplicitOffsets(element, anchor, 'bottom', 'right', vOffset, hOffset, isOverflow);
- case 'center top':
- return GetExplicitOffsets(element, anchor, 'top', 'center', vOffset, hOffset, isOverflow);
- case 'center bottom':
- return GetExplicitOffsets(element, anchor, 'bottom', 'center', vOffset, hOffset, isOverflow);
- case 'center left':
- return GetExplicitOffsets(element, anchor, 'left', 'center', vOffset, hOffset, isOverflow);
- case 'center right':
- return GetExplicitOffsets(element, anchor, 'right', 'center', vOffset, hOffset, isOverflow);
- case 'left bottom':
- return GetExplicitOffsets(element, anchor, 'bottom', 'left', vOffset, hOffset, isOverflow);
- case 'right bottom':
- return GetExplicitOffsets(element, anchor, 'bottom', 'right', vOffset, hOffset, isOverflow);
- // Backwards compatibility... this along with the reveal and reveal full
- // classes are the only ones that didn't reference anchor
- case 'center':
- return {
- left: ($eleDims.windowDims.offset.left + ($eleDims.windowDims.width / 2)) - ($eleDims.width / 2) + hOffset,
- top: ($eleDims.windowDims.offset.top + ($eleDims.windowDims.height / 2)) - ($eleDims.height / 2 + vOffset)
- }
- case 'reveal':
- return {
- left: ($eleDims.windowDims.width - $eleDims.width) / 2 + hOffset,
- top: $eleDims.windowDims.offset.top + vOffset
- }
- case 'reveal full':
- return {
- left: $eleDims.windowDims.offset.left,
- top: $eleDims.windowDims.offset.top
- }
- break;
- default:
- return {
- left: (Rtl() ? $anchorDims.offset.left - $eleDims.width + $anchorDims.width - hOffset: $anchorDims.offset.left + hOffset),
- top: $anchorDims.offset.top + $anchorDims.height + vOffset
- }
- }
- }
- function GetExplicitOffsets(element, anchor, position, alignment, vOffset, hOffset, isOverflow) {
- var $eleDims = GetDimensions(element),
- $anchorDims = anchor ? GetDimensions(anchor) : null;
- var topVal, leftVal;
- // set position related attribute
- switch (position) {
- case 'top':
- topVal = $anchorDims.offset.top - ($eleDims.height + vOffset);
- break;
- case 'bottom':
- topVal = $anchorDims.offset.top + $anchorDims.height + vOffset;
- break;
- case 'left':
- leftVal = $anchorDims.offset.left - ($eleDims.width + hOffset);
- break;
- case 'right':
- leftVal = $anchorDims.offset.left + $anchorDims.width + hOffset;
- break;
- }
- // set alignment related attribute
- switch (position) {
- case 'top':
- case 'bottom':
- switch (alignment) {
- case 'left':
- leftVal = $anchorDims.offset.left + hOffset;
- break;
- case 'right':
- leftVal = $anchorDims.offset.left - $eleDims.width + $anchorDims.width - hOffset;
- break;
- case 'center':
- leftVal = isOverflow ? hOffset : (($anchorDims.offset.left + ($anchorDims.width / 2)) - ($eleDims.width / 2)) + hOffset;
- break;
- }
- break;
- case 'right':
- case 'left':
- switch (alignment) {
- case 'bottom':
- topVal = $anchorDims.offset.top - vOffset + $anchorDims.height - $eleDims.height;
- break;
- case 'top':
- topVal = $anchorDims.offset.top + vOffset
- break;
- case 'center':
- topVal = ($anchorDims.offset.top + vOffset + ($anchorDims.height / 2)) - ($eleDims.height / 2)
- break;
- }
- break;
- }
- return {top: topVal, left: leftVal};
- }
- export {Box};
|