/* Siesta 5.1.0 Copyright(c) 2009-2018 Bryntum AB https://bryntum.com/contact https://bryntum.com/products/siesta/license */ Role('Siesta.Util.Role.Dom', { does : [ Siesta.Util.Role.CanCalculatePageScroll ], has : { doesNotIncludeMarginInBodyOffset : false }, methods : { isCrossOriginWindow : function (win) { try { var doc = win.document; } catch (e) { return true } // Safari doesn't throw exception when trying to access x-domain frames return !doc }, closest : function (elem, selector, maxLevels) { maxLevels = maxLevels || Number.MAX_VALUE; var docEl = elem.ownerDocument.documentElement; // Get closest match for (var i = 0; i < maxLevels && elem && elem !== docEl; elem = elem.parentNode) { if (Siesta.Sizzle.matchesSelector(elem, selector)) { return elem; } i++; } return false; }, contains : function (parentEl, childEl) { if (!parentEl) return false if (parentEl.contains) return parentEl.contains(childEl) // SVG elements in IE does not have "contains" method if (parentEl.compareDocumentPosition) return parentEl === childEl || Boolean(parentEl.compareDocumentPosition(childEl) & 16) throw new Error("Can't determine `contains` status") }, matches : function (node, selector) { return Siesta.Sizzle.matchesSelector(node, selector); }, // returns { left : Number, top : Number } object in page coordinates offset : function (elem) { if (!elem) return null var doc = elem.ownerDocument if (!doc) return null if (elem === doc.body) return this.bodyOffset(elem); var box = this.getBoundingClientRect(elem) var win = doc.defaultView || doc.parentWindow return box ? { left : this.viewportXtoPageX(Math.floor(box.left), win), top : this.viewportYtoPageY(Math.floor(box.top), win) } : { left : 0, top : 0 } }, bodyOffset: function (body) { var top = body.offsetTop, left = body.offsetLeft; this.initializeOffset(); if (this.doesNotIncludeMarginInBodyOffset) { var style = getComputedStyle(body); top += parseFloat(style.marginTop) || 0; left += parseFloat(style.marginLeft) || 0; } return { top: top, left: left }; }, initializeOffset: function () { var body = document.body, container = document.createElement("div"), bodyMarginTop = parseFloat(getComputedStyle(body).marginTop) || 0, html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>"; var styles = { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" }; for (var o in styles) { container.style[ o ] = styles[ o ]; } container.innerHTML = html; body.insertBefore(container, body.firstChild); var innerDiv = container.firstChild; var checkDiv = innerDiv.firstChild; var td = innerDiv.nextSibling.firstChild.firstChild; checkDiv.style.position = "fixed"; checkDiv.style.top = "20px"; checkDiv.style.position = checkDiv.style.top = ""; innerDiv.style.overflow = "hidden"; innerDiv.style.position = "relative"; this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop); body.removeChild(container); this.initializeOffset = function () {}; }, getElementWidth : function (el) { return this.getBoundingClientRect(el).width; }, getElementHeight : function (el) { return this.getBoundingClientRect(el).height; }, getWindowSize : function (win) { var doc = win.document return { width : win.innerWidth || doc.documentElement.clientWidth || doc.body.clientWidth, height : win.innerHeight || doc.documentElement.clientHeight || doc.body.clientHeight } }, isPointWithinElement : function (x, y, el) { var rect = this.getBoundingClientRect(el); return x >= rect.left && x <= rect.right && y >= rect.top && y <= rect.bottom; }, isElementReachableAt : function (el, pageX, pageY, allowChild) { allowChild = allowChild !== false var doc = el.ownerDocument var win = doc.defaultView || doc.parentWindow var foundEl = doc.elementFromPoint(this.pageXtoViewportX(pageX, win), this.pageYtoViewportY(pageY, win)) return foundEl && (foundEl === el || allowChild && this.contains(el, foundEl)) }, isElementReachableAtCenter : function (el, allowChild) { allowChild = allowChild !== false var offsets = this.offset(el); return this.isElementReachableAt( el, offsets.left + (this.getElementWidth(el) / 2), offsets.top + (this.getElementHeight(el) / 2), allowChild ); }, // patched version to support SVG in IE11/Edge getBoundingClientRect : function (el) { var svgEl = el.ownerSVGElement; if (svgEl && (bowser.msie || bowser.msedge)) { var elBox = el.getBBox(), svgRect = svgEl.getBoundingClientRect(), left = svgRect.left + elBox.x, top = svgRect.top + elBox.y, right = left + elBox.width, bottom = top + elBox.height; return { x : left, y : top, left : left, top : top, bottom : bottom, height : elBox.height, width : elBox.width }; } else { return el.getBoundingClientRect(); } }, nodeIsUnloaded : function (el) { try { // throws if accessed when element belonged to an iframe that's no longer in DOM el && el.tagName var doc = el.ownerDocument var win = doc && (doc.defaultView || doc.parentWindow) return !Boolean(win) } catch (e) { // exception here probably means the "lastOverEl" is from freed context (unloaded page) // access to such elements throws exceptions in IE el = null return true } }, nodeIsOrphan : function (el) { var doc = el.ownerDocument return !doc || !doc.body || !el.parentNode || !(el === doc.body || $.contains(doc.body, el)); }, getNodeParents : function (node) { var doc = node.ownerDocument; var nodes = []; for (; node && node.parentNode; node = node.parentNode) { nodes.unshift(node); } return nodes; }, getCommonAncestor : function (node1, node2) { var parents1 = this.getNodeParents(node1); var parents2 = this.getNodeParents(node2); // Make sure both nodes are part of same DOM tree if (parents1[ 0 ] != parents2[ 0 ]) return null; for (var i = 0; i < parents1.length; i++) { if (parents1[ i ] !== parents2[ i ]) { return parents1[ i - 1 ]; } } } } })