| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- /**
- * DevExtreme (animation/position.js)
- * Version: 19.1.16
- * Build date: Tue Oct 18 2022
- *
- * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
- * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
- */
- "use strict";
- var $ = require("../core/renderer");
- var commonUtils = require("../core/utils/common");
- var each = require("../core/utils/iterator").each;
- var windowUtils = require("../core/utils/window");
- var window = windowUtils.getWindow();
- var domAdapter = require("../core/dom_adapter");
- var isWindow = require("../core/utils/type").isWindow;
- var extend = require("../core/utils/extend").extend;
- var browser = require("../core/utils/browser");
- var translator = require("./translator");
- var support = require("../core/utils/support");
- var horzRe = /left|right/;
- var vertRe = /top|bottom/;
- var collisionRe = /fit|flip|none/;
- var IS_SAFARI = browser.safari;
- var normalizeAlign = function(raw) {
- var result = {
- h: "center",
- v: "center"
- };
- var pair = commonUtils.splitPair(raw);
- if (pair) {
- each(pair, function() {
- var w = String(this).toLowerCase();
- if (horzRe.test(w)) {
- result.h = w
- } else {
- if (vertRe.test(w)) {
- result.v = w
- }
- }
- })
- }
- return result
- };
- var normalizeOffset = function(raw) {
- return commonUtils.pairToObject(raw)
- };
- var normalizeCollision = function(raw) {
- var pair = commonUtils.splitPair(raw);
- var h = String(pair && pair[0]).toLowerCase();
- var v = String(pair && pair[1]).toLowerCase();
- if (!collisionRe.test(h)) {
- h = "none"
- }
- if (!collisionRe.test(v)) {
- v = h
- }
- return {
- h: h,
- v: v
- }
- };
- var getAlignFactor = function(align) {
- switch (align) {
- case "center":
- return .5;
- case "right":
- case "bottom":
- return 1;
- default:
- return 0
- }
- };
- var inverseAlign = function(align) {
- switch (align) {
- case "left":
- return "right";
- case "right":
- return "left";
- case "top":
- return "bottom";
- case "bottom":
- return "top";
- default:
- return align
- }
- };
- var calculateOversize = function(data, bounds) {
- var oversize = 0;
- if (data.myLocation < bounds.min) {
- oversize += bounds.min - data.myLocation
- }
- if (data.myLocation > bounds.max) {
- oversize += data.myLocation - bounds.max
- }
- return oversize
- };
- var collisionSide = function(direction, data, bounds) {
- if (data.myLocation < bounds.min) {
- return "h" === direction ? "left" : "top"
- }
- if (data.myLocation > bounds.max) {
- return "h" === direction ? "right" : "bottom"
- }
- return "none"
- };
- var initMyLocation = function(data) {
- data.myLocation = data.atLocation + getAlignFactor(data.atAlign) * data.atSize - getAlignFactor(data.myAlign) * data.mySize + data.offset
- };
- var collisionResolvers = {
- fit: function(data, bounds) {
- var result = false;
- if (data.myLocation > bounds.max) {
- data.myLocation = bounds.max;
- result = true
- }
- if (data.myLocation < bounds.min) {
- data.myLocation = bounds.min;
- result = true
- }
- data.fit = result
- },
- flip: function(data, bounds) {
- data.flip = false;
- if ("center" === data.myAlign && "center" === data.atAlign) {
- return
- }
- if (data.myLocation < bounds.min || data.myLocation > bounds.max) {
- var inverseData = extend({}, data, {
- myAlign: inverseAlign(data.myAlign),
- atAlign: inverseAlign(data.atAlign),
- offset: -data.offset
- });
- initMyLocation(inverseData);
- inverseData.oversize = calculateOversize(inverseData, bounds);
- if (inverseData.myLocation >= bounds.min && inverseData.myLocation <= bounds.max || data.oversize > inverseData.oversize) {
- data.myLocation = inverseData.myLocation;
- data.oversize = inverseData.oversize;
- data.flip = true
- }
- }
- },
- flipfit: function(data, bounds) {
- this.flip(data, bounds);
- this.fit(data, bounds)
- },
- none: function(data) {
- data.oversize = 0
- }
- };
- var scrollbarWidth;
- var calculateScrollbarWidth = function() {
- var $scrollDiv = $("<div>").css({
- width: 100,
- height: 100,
- overflow: "scroll",
- position: "absolute",
- top: -9999
- }).appendTo($("body"));
- var result = $scrollDiv.get(0).offsetWidth - $scrollDiv.get(0).clientWidth;
- $scrollDiv.remove();
- scrollbarWidth = result
- };
- var defaultPositionResult = {
- h: {
- location: 0,
- flip: false,
- fit: false,
- oversize: 0
- },
- v: {
- location: 0,
- flip: false,
- fit: false,
- oversize: 0
- }
- };
- var calculatePosition = function(what, options) {
- var $what = $(what);
- var currentOffset = $what.offset();
- var result = extend(true, {}, defaultPositionResult, {
- h: {
- location: currentOffset.left
- },
- v: {
- location: currentOffset.top
- }
- });
- if (!options) {
- return result
- }
- var my = normalizeAlign(options.my);
- var at = normalizeAlign(options.at);
- var of = $(options.of).length && options.of || window;
- var offset = normalizeOffset(options.offset);
- var collision = normalizeCollision(options.collision);
- var boundary = options.boundary;
- var boundaryOffset = normalizeOffset(options.boundaryOffset);
- var h = {
- mySize: $what.outerWidth(),
- myAlign: my.h,
- atAlign: at.h,
- offset: offset.h,
- collision: collision.h,
- boundaryOffset: boundaryOffset.h
- };
- var v = {
- mySize: $what.outerHeight(),
- myAlign: my.v,
- atAlign: at.v,
- offset: offset.v,
- collision: collision.v,
- boundaryOffset: boundaryOffset.v
- };
- if (of.preventDefault) {
- h.atLocation = of.pageX;
- v.atLocation = of.pageY;
- h.atSize = 0;
- v.atSize = 0
- } else {
- of = $(of);
- if (isWindow(of [0])) {
- h.atLocation = of.scrollLeft();
- v.atLocation = of.scrollTop();
- h.atSize = of [0].innerWidth >= of [0].outerWidth ? of [0].innerWidth : of.width();
- v.atSize = of [0].innerHeight >= of [0].outerHeight || IS_SAFARI ? of [0].innerHeight : of.height()
- } else {
- if (9 === of [0].nodeType) {
- h.atLocation = 0;
- v.atLocation = 0;
- h.atSize = of.width();
- v.atSize = of.height()
- } else {
- var o = of.offset();
- h.atLocation = o.left;
- v.atLocation = o.top;
- h.atSize = of.outerWidth();
- v.atSize = of.outerHeight()
- }
- }
- }
- initMyLocation(h);
- initMyLocation(v);
- var bounds = function() {
- var win = $(window);
- var windowWidth = win.width();
- var windowHeight = win.height();
- var left = win.scrollLeft();
- var top = win.scrollTop();
- var documentElement = domAdapter.getDocumentElement();
- var hZoomLevel = support.touch ? documentElement.clientWidth / windowWidth : 1;
- var vZoomLevel = support.touch ? documentElement.clientHeight / windowHeight : 1;
- if (void 0 === scrollbarWidth) {
- calculateScrollbarWidth()
- }
- var boundaryWidth = windowWidth;
- var boundaryHeight = windowHeight;
- if (boundary) {
- var $boundary = $(boundary);
- var boundaryPosition = $boundary.offset();
- left = boundaryPosition.left;
- top = boundaryPosition.top;
- boundaryWidth = $boundary.width();
- boundaryHeight = $boundary.height()
- }
- return {
- h: {
- min: left + h.boundaryOffset,
- max: left + boundaryWidth / hZoomLevel - h.mySize - h.boundaryOffset
- },
- v: {
- min: top + v.boundaryOffset,
- max: top + boundaryHeight / vZoomLevel - v.mySize - v.boundaryOffset
- }
- }
- }();
- h.oversize = calculateOversize(h, bounds.h);
- v.oversize = calculateOversize(v, bounds.v);
- h.collisionSide = collisionSide("h", h, bounds.h);
- v.collisionSide = collisionSide("v", v, bounds.v);
- if (collisionResolvers[h.collision]) {
- collisionResolvers[h.collision](h, bounds.h)
- }
- if (collisionResolvers[v.collision]) {
- collisionResolvers[v.collision](v, bounds.v)
- }
- var preciser = function(number) {
- return options.precise ? number : Math.round(number)
- };
- extend(true, result, {
- h: {
- location: preciser(h.myLocation),
- oversize: preciser(h.oversize),
- fit: h.fit,
- flip: h.flip,
- collisionSide: h.collisionSide
- },
- v: {
- location: preciser(v.myLocation),
- oversize: preciser(v.oversize),
- fit: v.fit,
- flip: v.flip,
- collisionSide: v.collisionSide
- },
- precise: options.precise
- });
- return result
- };
- var position = function(what, options) {
- var $what = $(what);
- if (!options) {
- return $what.offset()
- }
- translator.resetPosition($what, true);
- var offset = $what.offset();
- var targetPosition = options.h && options.v ? options : calculatePosition($what, options);
- var preciser = function(number) {
- return options.precise ? number : Math.round(number)
- };
- translator.move($what, {
- left: targetPosition.h.location - preciser(offset.left),
- top: targetPosition.v.location - preciser(offset.top)
- });
- return targetPosition
- };
- var offset = function(element) {
- element = $(element).get(0);
- if (isWindow(element)) {
- return null
- } else {
- if (element && "pageY" in element && "pageX" in element) {
- return {
- top: element.pageY,
- left: element.pageX
- }
- }
- }
- return $(element).offset()
- };
- if (!position.inverseAlign) {
- position.inverseAlign = inverseAlign
- }
- if (!position.normalizeAlign) {
- position.normalizeAlign = normalizeAlign
- }
- module.exports = {
- calculateScrollbarWidth: calculateScrollbarWidth,
- calculate: calculatePosition,
- setup: position,
- offset: offset
- };
|