UNPKG

dojo

Version:

Dojo core is a powerful, lightweight library that makes common tasks quicker and easier. Animate elements, manipulate the DOM, and query with easy CSS syntax, all without sacrificing performance.

242 lines (224 loc) 9.29 kB
define(["./_base/lang", "./sniff", "./_base/window", "./dom", "./dom-geometry", "./dom-style", "./dom-construct"], function(lang, has, baseWindow, dom, geom, style, domConstruct){ // feature detection /* not needed but included here for future reference has.add("rtl-innerVerticalScrollBar-on-left", function(win, doc){ var body = baseWindow.body(doc), scrollable = domConstruct.create('div', { style: {overflow:'scroll', overflowX:'hidden', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', width:'64px', height:'64px'} }, body, "last"), center = domConstruct.create('center', { style: {overflow:'hidden', direction:'ltr'} }, scrollable, "last"), inner = domConstruct.create('div', { style: {overflow:'visible', display:'inline' } }, center, "last"); inner.innerHTML="&nbsp;"; var midPoint = Math.max(inner.offsetLeft, geom.position(inner).x); var ret = midPoint >= 32; center.removeChild(inner); scrollable.removeChild(center); body.removeChild(scrollable); return ret; }); */ has.add("rtl-adjust-position-for-verticalScrollBar", function(win, doc){ var body = baseWindow.body(doc), scrollable = domConstruct.create('div', { style: {overflow:'scroll', overflowX:'visible', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', top:'0', width:'64px', height:'64px'} }, body, "last"), div = domConstruct.create('div', { style: {overflow:'hidden', direction:'ltr'} }, scrollable, "last"), ret = geom.position(div).x != 0; scrollable.removeChild(div); body.removeChild(scrollable); return ret; }); has.add("position-fixed-support", function(win, doc){ // IE6, IE7+quirks, and some older mobile browsers don't support position:fixed var body = baseWindow.body(doc), outer = domConstruct.create('span', { style: {visibility:'hidden', position:'fixed', left:'1px', top:'1px'} }, body, "last"), inner = domConstruct.create('span', { style: {position:'fixed', left:'0', top:'0'} }, outer, "last"), ret = geom.position(inner).x != geom.position(outer).x; outer.removeChild(inner); body.removeChild(outer); return ret; }); // module: // dojo/window var window = { // summary: // TODOC getBox: function(/*Document?*/ doc){ // summary: // Returns the dimensions and scroll position of the viewable area of a browser window doc = doc || baseWindow.doc; var scrollRoot = (doc.compatMode == 'BackCompat') ? baseWindow.body(doc) : doc.documentElement, // get scroll position scroll = geom.docScroll(doc), // scrollRoot.scrollTop/Left should work w, h; if(has("touch")){ // if(scrollbars not supported) var uiWindow = window.get(doc); // use UI window, not dojo.global window // on mobile, scrollRoot.clientHeight <= uiWindow.innerHeight <= scrollRoot.offsetHeight, return uiWindow.innerHeight w = uiWindow.innerWidth || scrollRoot.clientWidth; // || scrollRoot.clientXXX probably never evaluated h = uiWindow.innerHeight || scrollRoot.clientHeight; }else{ // on desktops, scrollRoot.clientHeight <= scrollRoot.offsetHeight <= uiWindow.innerHeight, return scrollRoot.clientHeight // uiWindow.innerWidth/Height includes the scrollbar and cannot be used w = scrollRoot.clientWidth; h = scrollRoot.clientHeight; } return { l: scroll.x, t: scroll.y, w: w, h: h }; }, get: function(/*Document*/ doc){ // summary: // Get window object associated with document doc. // doc: // The document to get the associated window for. // In some IE versions (at least 6.0), document.parentWindow does not return a // reference to the real window object (maybe a copy), so we must fix it as well // We use IE specific execScript to attach the real window reference to // document._parentWindow for later use if(has("ie") && window !== document.parentWindow){ /* In IE 6, only the variable "window" can be used to connect events (others may be only copies). */ doc.parentWindow.execScript("document._parentWindow = window;", "Javascript"); //to prevent memory leak, unset it after use //another possibility is to add an onUnload handler which seems overkill to me (liucougar) var win = doc._parentWindow; doc._parentWindow = null; return win; // Window } return doc.parentWindow || doc.defaultView; // Window }, scrollIntoView: function(/*DomNode*/ node, /*Object?*/ pos){ // summary: // Scroll the passed node into view using minimal movement, if it is not already. // Don't rely on node.scrollIntoView working just because the function is there since // it forces the node to the page's bottom or top (and left or right in IE) without consideration for the minimal movement. // WebKit's node.scrollIntoViewIfNeeded doesn't work either for inner scrollbars in right-to-left mode // and when there's a fixed position scrollable element try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method node = dom.byId(node); var doc = node.ownerDocument || baseWindow.doc, // TODO: why baseWindow.doc? Isn't node.ownerDocument always defined? body = baseWindow.body(doc), html = doc.documentElement || body.parentNode, isIE = has("ie") || has("trident"), isWK = has("webkit"); // if an untested browser, then use the native method if(node == body || node == html){ return; } if(!(has("mozilla") || isIE || isWK || has("opera") || has("trident") || has("edge")) && ("scrollIntoView" in node)){ node.scrollIntoView(false); // short-circuit to native if possible return; } var backCompat = doc.compatMode == 'BackCompat', rootWidth = Math.min(body.clientWidth || html.clientWidth, html.clientWidth || body.clientWidth), rootHeight = Math.min(body.clientHeight || html.clientHeight, html.clientHeight || body.clientHeight), scrollRoot = (isWK || backCompat) ? body : html, nodePos = pos || geom.position(node), el = node.parentNode, isFixed = function(el){ return (isIE <= 6 || (isIE == 7 && backCompat)) ? false : (has("position-fixed-support") && (style.get(el, 'position').toLowerCase() == "fixed")); }, self = this, scrollElementBy = function(el, x, y){ if(el.tagName == "BODY" || el.tagName == "HTML"){ self.get(el.ownerDocument).scrollBy(x, y); }else{ x && (el.scrollLeft += x); y && (el.scrollTop += y); } }; if(isFixed(node)){ return; } // nothing to do while(el){ if(el == body){ el = scrollRoot; } var elPos = geom.position(el), fixedPos = isFixed(el), rtl = style.getComputedStyle(el).direction.toLowerCase() == "rtl"; if(el == scrollRoot){ elPos.w = rootWidth; elPos.h = rootHeight; if(scrollRoot == html && (isIE || has("trident")) && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w;// IE workaround where scrollbar causes negative x } elPos.x = 0; elPos.y = 0; }else{ var pb = geom.getPadBorderExtents(el); elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t; var clientSize = el.clientWidth, scrollBarSize = elPos.w - clientSize; if(clientSize > 0 && scrollBarSize > 0){ if(rtl && has("rtl-adjust-position-for-verticalScrollBar")){ elPos.x += scrollBarSize; } elPos.w = clientSize; } clientSize = el.clientHeight; scrollBarSize = elPos.h - clientSize; if(clientSize > 0 && scrollBarSize > 0){ elPos.h = clientSize; } } if(fixedPos){ // bounded by viewport, not parents if(elPos.y < 0){ elPos.h += elPos.y; elPos.y = 0; } if(elPos.x < 0){ elPos.w += elPos.x; elPos.x = 0; } if(elPos.y + elPos.h > rootHeight){ elPos.h = rootHeight - elPos.y; } if(elPos.x + elPos.w > rootWidth){ elPos.w = rootWidth - elPos.x; } } // calculate overflow in all 4 directions var l = nodePos.x - elPos.x, // beyond left: < 0 // t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0 t = nodePos.y - elPos.y, // beyond top: < 0 r = l + nodePos.w - elPos.w, // beyond right: > 0 bot = t + nodePos.h - elPos.h; // beyond bottom: > 0 var s, old; if(r * l > 0 && (!!el.scrollLeft || el == scrollRoot || el.scrollWidth > el.offsetHeight)){ s = Math[l < 0? "max" : "min"](l, r); if(rtl && ((isIE == 8 && !backCompat) || has("trident") >= 5)){ s = -s; } old = el.scrollLeft; scrollElementBy(el, s, 0); s = el.scrollLeft - old; nodePos.x -= s; } if(bot * t > 0 && (!!el.scrollTop || el == scrollRoot || el.scrollHeight > el.offsetHeight)){ s = Math.ceil(Math[t < 0? "max" : "min"](t, bot)); old = el.scrollTop; scrollElementBy(el, 0, s); s = el.scrollTop - old; nodePos.y -= s; } el = (el != scrollRoot) && !fixedPos && el.parentNode; } }catch(error){ console.error('scrollIntoView: ' + error); node.scrollIntoView(false); } } }; has("extend-dojo") && lang.setObject("dojo.window", window); return window; });