This implementation is very naive. There are many browser quirks that make it extremely difficult to get accurate element coordinates in all situations
966278
function(el) {
                    var x = 0, y = 0, offsetEl = el, width = el.offsetWidth, height = el.offsetHeight;
                    while (offsetEl) {
                        x += offsetEl.offsetLeft;
                        y += offsetEl.offsetTop;
                        offsetEl = offsetEl.offsetParent;
                    }

                    return adjustClientRect(new Rect(y, x + width, y + height, x), dom.getDocument(el));
                }
871338
function getElementPos(pos) {
    var l = 0
    for (var i = 0; i < pos - 1; i++) { l += elements[i] }
    return l
  }
612652
function reComputeElementsPosition()
        {
            var baseOffset = 0;

            for (var idx = notificationList.length -1; idx >= 0; idx--)
            {
                notificationList[idx].height = getElementHeight(notificationList[idx].elem[0]);
                notificationList[idx].margin = baseOffset;

                notificationList[idx].elem.css('marginBottom', notificationList[idx].margin + 'px');

                baseOffset += notificationList[idx].height + 24;
            }
        }
1218072
function boundingBoxImpl(ele, options) {
  var cy = ele._private.cy;
  var styleEnabled = cy.styleEnabled();
  var headless = cy.headless();
  var bounds = makeBoundingBox();
  var _p = ele._private;
  var display = styleEnabled ? ele.pstyle('display').value : 'element';
  var isNode = ele.isNode();
  var isEdge = ele.isEdge();
  var ex1, ex2, ey1, ey2; // extrema of body / lines

  var x, y; // node pos

  var displayed = display !== 'none';
  var rstyle = _p.rstyle;
  var manualExpansion = isNode && styleEnabled ? ele.pstyle('bounds-expansion').pfValue : 0;

  if (displayed) {
    var overlayOpacity = 0;
    var overlayPadding = 0;

    if (styleEnabled && options.includeOverlays) {
      overlayOpacity = ele.pstyle('overlay-opacity').value;

      if (overlayOpacity !== 0) {
        overlayPadding = ele.pstyle('overlay-padding').value;
      }
    }

    var w = 0;
    var wHalf = 0;

    if (styleEnabled) {
      w = ele.pstyle('width').pfValue;
      wHalf = w / 2;
    }

    if (isNode && options.includeNodes) {
      var pos = ele.position();
      x = pos.x;
      y = pos.y;

      var _w = ele.outerWidth();

      var halfW = _w / 2;
      var h = ele.outerHeight();
      var halfH = h / 2; // handle node dimensions
      /////////////////////////

      ex1 = x - halfW;
      ex2 = x + halfW;
      ey1 = y - halfH;
      ey2 = y + halfH;
      updateBounds(bounds, ex1, ey1, ex2, ey2);
    } else if (isEdge && options.includeEdges) {
      // handle edge dimensions (rough box estimate)
      //////////////////////////////////////////////
      if (styleEnabled && !headless) {
        ex1 = Math.min(rstyle.srcX, rstyle.midX, rstyle.tgtX);
        ex2 = Math.max(rstyle.srcX, rstyle.midX, rstyle.tgtX);
        ey1 = Math.min(rstyle.srcY, rstyle.midY, rstyle.tgtY);
        ey2 = Math.max(rstyle.srcY, rstyle.midY, rstyle.tgtY); // take into account edge width

        ex1 -= wHalf;
        ex2 += wHalf;
        ey1 -= wHalf;
        ey2 += wHalf;
        updateBounds(bounds, ex1, ey1, ex2, ey2);
      } // precise haystacks
      ////////////////////


      if (styleEnabled && !headless && ele.pstyle('curve-style').strValue === 'haystack') {
        var hpts = rstyle.haystackPts || [];
        ex1 = hpts[0].x;
        ey1 = hpts[0].y;
        ex2 = hpts[1].x;
        ey2 = hpts[1].y;

        if (ex1 > ex2) {
          var temp = ex1;
          ex1 = ex2;
          ex2 = temp;
        }

        if (ey1 > ey2) {
          var _temp = ey1;
          ey1 = ey2;
          ey2 = _temp;
        }

        updateBounds(bounds, ex1 - wHalf, ey1 - wHalf, ex2 + wHalf, ey2 + wHalf); // handle points along edge
        ///////////////////////////
      } else {
        var pts = rstyle.bezierPts || rstyle.linePts || [];

        for (var j = 0; j < pts.length; j++) {
          var pt = pts[j];
          ex1 = pt.x - wHalf;
          ex2 = pt.x + wHalf;
          ey1 = pt.y - wHalf;
          ey2 = pt.y + wHalf;
          updateBounds(bounds, ex1, ey1, ex2, ey2);
        } // fallback on source and target positions
        //////////////////////////////////////////


        if (pts.length === 0) {
          var n1 = ele.source();
          var n1pos = n1.position();
          var n2 = ele.target();
          var n2pos = n2.position();
          ex1 = n1pos.x;
          ex2 = n2pos.x;
          ey1 = n1pos.y;
          ey2 = n2pos.y;

          if (ex1 > ex2) {
            var _temp2 = ex1;
            ex1 = ex2;
            ex2 = _temp2;
          }

          if (ey1 > ey2) {
            var _temp3 = ey1;
            ey1 = ey2;
            ey2 = _temp3;
          } // take into account edge width


          ex1 -= wHalf;
          ex2 += wHalf;
          ey1 -= wHalf;
          ey2 += wHalf;
          updateBounds(bounds, ex1, ey1, ex2, ey2);
        }
      }
    } // edges
    // handle edge arrow size
    /////////////////////////


    if (styleEnabled && options.includeEdges && isEdge) {
      updateBoundsFromArrow(bounds, ele, 'mid-source', options);
      updateBoundsFromArrow(bounds, ele, 'mid-target', options);
      updateBoundsFromArrow(bounds, ele, 'source', options);
      updateBoundsFromArrow(bounds, ele, 'target', options);
    } // ghost
    ////////


    if (styleEnabled) {
      var ghost = ele.pstyle('ghost').value === 'yes';

      if (ghost) {
        var gx = ele.pstyle('ghost-offset-x').pfValue;
        var gy = ele.pstyle('ghost-offset-y').pfValue;
        updateBounds(bounds, bounds.x1 + gx, bounds.y1 + gy, bounds.x2 + gx, bounds.y2 + gy);
      }
    } // always store the body bounds separately from the labels


    var bbBody = _p.bodyBounds = _p.bodyBounds || {};
    assignBoundingBox(bbBody, bounds);
    expandBoundingBox(bbBody, manualExpansion);
    expandBoundingBox(bbBody, 1); // expand to work around browser dimension inaccuracies
    // overlay
    //////////

    if (styleEnabled) {
      ex1 = bounds.x1;
      ex2 = bounds.x2;
      ey1 = bounds.y1;
      ey2 = bounds.y2;
      updateBounds(bounds, ex1 - overlayPadding, ey1 - overlayPadding, ex2 + overlayPadding, ey2 + overlayPadding);
    } // always store the body bounds separately from the labels


    var bbOverlay = _p.overlayBounds = _p.overlayBounds || {};
    assignBoundingBox(bbOverlay, bounds);
    expandBoundingBox(bbOverlay, manualExpansion);
    expandBoundingBox(bbOverlay, 1); // expand to work around browser dimension inaccuracies
    // handle label dimensions
    //////////////////////////

    var bbLabels = _p.labelBounds = _p.labelBounds || {};

    if (bbLabels.all != null) {
      clearBoundingBox(bbLabels.all);
    } else {
      bbLabels.all = makeBoundingBox();
    }

    if (styleEnabled && options.includeLabels) {
      updateBoundsFromLabel(bounds, ele, null, options);

      if (isEdge) {
        updateBoundsFromLabel(bounds, ele, 'source', options);
        updateBoundsFromLabel(bounds, ele, 'target', options);
      }
    } // style enabled for labels

  } // if displayed


  bounds.x1 = noninf(bounds.x1);
  bounds.y1 = noninf(bounds.y1);
  bounds.x2 = noninf(bounds.x2);
  bounds.y2 = noninf(bounds.y2);
  bounds.w = noninf(bounds.x2 - bounds.x1);
  bounds.h = noninf(bounds.y2 - bounds.y1);

  if (bounds.w > 0 && bounds.h > 0 && displayed) {
    expandBoundingBox(bounds, manualExpansion); // expand bounds by 1 because antialiasing can increase the visual/effective size by 1 on all sides

    expandBoundingBox(bounds, 1);
  }

  return bounds;
}
766929
function checkInside(event, element) {
  let c = pointerPosition(event);
  let current = document.elementFromPoint(c.x, c.y);
  return isOneOf(element._el, current, current.parentNode, current.parentNode.parentNode);
}
767598
function(elem) {

		try {
			// TODO: Fix issue with rotated groups. Currently they work
			// fine in FF, but not in other browsers (same problem mentioned
			// in Issue 339 comment #2).

			var bb = svgedit.utilities.getBBox(elem);
			var angle = svgedit.utilities.getRotationAngle(elem);

			if ((angle && angle % 90) ||
				svgedit.math.hasMatrixTransform(svgedit.transformlist.getTransformList(elem))) {
				// Accurate way to get BBox of rotated element in Firefox:
				// Put element in group and get its BBox
				var good_bb = false;
				// Get the BBox from the raw path for these elements
				var elemNames = ['ellipse', 'path', 'line', 'polyline', 'polygon'];
				if (elemNames.indexOf(elem.tagName) >= 0) {
					bb = good_bb = canvas.convertToPath(elem, true);
				} else if (elem.tagName == 'rect') {
					// Look for radius
					var rx = elem.getAttribute('rx');
					var ry = elem.getAttribute('ry');
					if (rx || ry) {
						bb = good_bb = canvas.convertToPath(elem, true);
					}
				}

				if (!good_bb) {
					// Must use clone else FF freaks out
					var clone = elem.cloneNode(true);
					var g = document.createElementNS(NS.SVG, "g");
					var parent = elem.parentNode;
					parent.appendChild(g);
					g.appendChild(clone);
					bb = svgedit.utilities.bboxToObj(g.getBBox());
					parent.removeChild(g);
				}

				// Old method: Works by giving the rotated BBox,
				// this is (unfortunately) what Opera and Safari do
				// natively when getting the BBox of the parent group
//						var angle = angle * Math.PI / 180.0;
//						var rminx = Number.MAX_VALUE, rminy = Number.MAX_VALUE, 
//							rmaxx = Number.MIN_VALUE, rmaxy = Number.MIN_VALUE;
//						var cx = round(bb.x + bb.width/2),
//							cy = round(bb.y + bb.height/2);
//						var pts = [ [bb.x - cx, bb.y - cy], 
//									[bb.x + bb.width - cx, bb.y - cy],
//									[bb.x + bb.width - cx, bb.y + bb.height - cy],
//									[bb.x - cx, bb.y + bb.height - cy] ];
//						var j = 4;
//						while (j--) {
//							var x = pts[j][0],
//								y = pts[j][1],
//								r = Math.sqrt( x*x + y*y );
//							var theta = Math.atan2(y,x) + angle;
//							x = round(r * Math.cos(theta) + cx);
//							y = round(r * Math.sin(theta) + cy);
//		
//							// now set the bbox for the shape after it's been rotated
//							if (x < rminx) rminx = x;
//							if (y < rminy) rminy = y;
//							if (x > rmaxx) rmaxx = x;
//							if (y > rmaxy) rmaxy = y;
//						}
//						
//						bb.x = rminx;
//						bb.y = rminy;
//						bb.width = rmaxx - rminx;
//						bb.height = rmaxy - rminy;
			}
			return bb;
		} catch(e) {
			console.log(elem, e);
			return null;
		}
	}
4321
function(el) {
    var pos = {
      left: 0,
      top: 0,
      width: 0,
      height: 0
    };
    if (el.getBoundingClientRect) {
      var elRect = el.getBoundingClientRect();
      var pageXOffset = _window.pageXOffset;
      var pageYOffset = _window.pageYOffset;
      var leftBorderWidth = _document.documentElement.clientLeft || 0;
      var topBorderWidth = _document.documentElement.clientTop || 0;
      var leftBodyOffset = 0;
      var topBodyOffset = 0;
      if (_getStyle(_document.body, "position") === "relative") {
        var bodyRect = _document.body.getBoundingClientRect();
        var htmlRect = _document.documentElement.getBoundingClientRect();
        leftBodyOffset = bodyRect.left - htmlRect.left || 0;
        topBodyOffset = bodyRect.top - htmlRect.top || 0;
      }
      pos.left = elRect.left + pageXOffset - leftBorderWidth - leftBodyOffset;
      pos.top = elRect.top + pageYOffset - topBorderWidth - topBodyOffset;
      pos.width = "width" in elRect ? elRect.width : elRect.right - elRect.left;
      pos.height = "height" in elRect ? elRect.height : elRect.bottom - elRect.top;
    }
    return pos;
  }
558729
function(element) {
    var r = { x: element.offsetLeft, y: element.offsetTop };
    if (element.offsetParent) {
      var tmp = getAbsolutePosition(element.offsetParent);
      r.x += tmp.x;
      r.y += tmp.y;
    }
    return r;
  }
260687
function getElementCoords (element, coords) {
  coords = coords || element.node().getBBox()
  const ctm = element.node().getCTM()
  const xn = ctm.e + coords.x * ctm.a
  const yn = ctm.f + coords.y * ctm.d
  return {
    left: xn,
    top: yn,
    width: coords.width,
    height: coords.height
  }
}
257911
function getPos(el) {
  var rect = el.getBoundingClientRect(),
    scrollY = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;

  return {
    top: rect.top + scrollY,
    bottom: rect.top + rect.height + scrollY,
    height: rect.height
  };
}
472880
function() {

        var crect = this.viewport.getBoundingClientRect();

        // Using Screen CTM was the only way to get the real viewport bounding box working in both
        // Google Chrome and Firefox.
        var clientCTM = this.clientMatrix();

        // for non-default origin we need to take the viewport translation into account
        var currentTranslate = this.translate();

        return new g.Rect({
            x: crect.left - clientCTM.e + currentTranslate.tx,
            y: crect.top - clientCTM.f + currentTranslate.ty,
            width: crect.width,
            height: crect.height
        });
    }
1325520
function () {
        var bbox = this.boundingBox;
        if (!bbox) {
            bbox = this.boundingBox = new BoundingBox();
        }
        var posArr = this.attributes.position.value;
        if (posArr && posArr.length) {
            var min = bbox.min;
            var max = bbox.max;
            var minArr = min.array;
            var maxArr = max.array;
            vec3.set(minArr, posArr[0], posArr[1], posArr[2]);
            vec3.set(maxArr, posArr[0], posArr[1], posArr[2]);
            for (var i = 3; i < posArr.length;) {
                var x = posArr[i++];
                var y = posArr[i++];
                var z = posArr[i++];
                if (x < minArr[0]) { minArr[0] = x; }
                if (y < minArr[1]) { minArr[1] = y; }
                if (z < minArr[2]) { minArr[2] = z; }

                if (x > maxArr[0]) { maxArr[0] = x; }
                if (y > maxArr[1]) { maxArr[1] = y; }
                if (z > maxArr[2]) { maxArr[2] = z; }
            }
            min._dirty = true;
            max._dirty = true;
        }
    }
1154425
function offset(el) {
  const rect = el.getBoundingClientRect();
  const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
  const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;

  return {
    top: rect.top + scrollTop,
    left: rect.left + scrollLeft
  };
}
815290
function getCoords(ev) {
    var x, y, w, h, el;

    // ignore browsers without pageX for now
    if (ev.pageX == null) return;

    x = ev.pageX;
    y = ev.pageY;
    el = self.element;

    // should probably check offsetParent
    // but this is more portable
    while (el && el !== self.document.documentElement) {
      x -= el.offsetLeft;
      y -= el.offsetTop;
      el = 'offsetParent' in el
        ? el.offsetParent
        : el.parentNode;
    }

    // convert to cols/rows
    w = self.element.clientWidth;
    h = self.element.clientHeight;
    x = Math.round((x / w) * self.cols);
    y = Math.round((y / h) * self.rows);

    // be sure to avoid sending
    // bad positions to the program
    if (x < 0) x = 0;
    if (x > self.cols) x = self.cols;
    if (y < 0) y = 0;
    if (y > self.rows) y = self.rows;

    // xterm sends raw bytes and
    // starts at 32 (SP) for each.
    x += 32;
    y += 32;

    return {
      x: x,
      y: y,
      type: ev.type === wheelEvent
        ? 'mousewheel'
        : ev.type
    };
  }
451786
function () {

            var nViewportOffset = Overlay.VIEWPORT_OFFSET,
                elementWidth = this.element.offsetWidth,
                elementHeight = this.element.offsetHeight,
                viewPortWidth = Dom.getViewportWidth(),
                viewPortHeight = Dom.getViewportHeight(),
                x,
                y;

            if (elementWidth < viewPortWidth) {
                x = (viewPortWidth / 2) - (elementWidth / 2) + Dom.getDocumentScrollLeft();
            } else {
                x = nViewportOffset + Dom.getDocumentScrollLeft();
            }

            if (elementHeight < viewPortHeight) {
                y = (viewPortHeight / 2) - (elementHeight / 2) + Dom.getDocumentScrollTop();
            } else {
                y = nViewportOffset + Dom.getDocumentScrollTop();
            }

            this.cfg.setProperty("xy", [parseInt(x, 10), parseInt(y, 10)]);
            this.cfg.refireEvent("iframe");

            if (UA.webkit) {
                this.forceContainerRedraw();
            }
        }
56934
function getSentinelPosition(stickyElement, sentinel, className) {
  const stickyStyle = window.getComputedStyle(stickyElement);
  const parentStyle = window.getComputedStyle(stickyElement.parentElement);

  switch (className) {
    case ClassName.SENTINEL_TOP:
      return {
        top: `calc(${stickyStyle.getPropertyValue('top')} * -1)`,
        height: 0,
      };

    case ClassName.SENTINEL_BOTTOM:
      const parentPadding = parseInt(parentStyle.paddingTop);

      return {
        bottom: stickyStyle.top,
        height: `${stickyElement.getBoundingClientRect().height + parentPadding}px`,
      };
  }
}
939213
function (align) {
        function getOffset(elm, rootElm) {
          var x, y, parent = elm;

          x = y = 0;
          while (parent && parent != rootElm && parent.nodeType) {
            x += parent.offsetLeft || 0;
            y += parent.offsetTop || 0;
            parent = parent.offsetParent;
          }

          return { x: x, y: y };
        }

        var elm = this.getEl(), parentElm = elm.parentNode;
        var x, y, width, height, parentWidth, parentHeight;
        var pos = getOffset(elm, parentElm);

        x = pos.x;
        y = pos.y;
        width = elm.offsetWidth;
        height = elm.offsetHeight;
        parentWidth = parentElm.clientWidth;
        parentHeight = parentElm.clientHeight;

        if (align == "end") {
          x -= parentWidth - width;
          y -= parentHeight - height;
        } else if (align == "center") {
          x -= (parentWidth / 2) - (width / 2);
          y -= (parentHeight / 2) - (height / 2);
        }

        parentElm.scrollLeft = x;
        parentElm.scrollTop = y;

        return this;
      }