]>
Commit | Line | Data |
---|---|---|
f0cfe83e AD |
1 | define("dojo/window", ["./_base/lang", "./sniff", "./_base/window", "./dom", "./dom-geometry", "./dom-style"], |
2 | function(lang, has, baseWindow, dom, geom, style){ | |
3 | ||
4 | // module: | |
5 | // dojo/window | |
6 | ||
7 | var window = { | |
8 | // summary: | |
9 | // TODOC | |
10 | ||
11 | getBox: function(/*Document?*/ doc){ | |
12 | // summary: | |
13 | // Returns the dimensions and scroll position of the viewable area of a browser window | |
14 | ||
15 | doc = doc || baseWindow.doc; | |
16 | ||
17 | var | |
18 | scrollRoot = (doc.compatMode == 'BackCompat') ? baseWindow.body(doc) : doc.documentElement, | |
19 | // get scroll position | |
20 | scroll = geom.docScroll(doc), // scrollRoot.scrollTop/Left should work | |
21 | w, h; | |
22 | ||
23 | if(has("touch")){ // if(scrollbars not supported) | |
24 | var uiWindow = window.get(doc); // use UI window, not dojo.global window | |
25 | // on mobile, scrollRoot.clientHeight <= uiWindow.innerHeight <= scrollRoot.offsetHeight, return uiWindow.innerHeight | |
26 | w = uiWindow.innerWidth || scrollRoot.clientWidth; // || scrollRoot.clientXXX probably never evaluated | |
27 | h = uiWindow.innerHeight || scrollRoot.clientHeight; | |
28 | }else{ | |
29 | // on desktops, scrollRoot.clientHeight <= scrollRoot.offsetHeight <= uiWindow.innerHeight, return scrollRoot.clientHeight | |
30 | // uiWindow.innerWidth/Height includes the scrollbar and cannot be used | |
31 | w = scrollRoot.clientWidth; | |
32 | h = scrollRoot.clientHeight; | |
33 | } | |
34 | return { | |
35 | l: scroll.x, | |
36 | t: scroll.y, | |
37 | w: w, | |
38 | h: h | |
39 | }; | |
40 | }, | |
41 | ||
42 | get: function(/*Document*/ doc){ | |
43 | // summary: | |
44 | // Get window object associated with document doc. | |
45 | // doc: | |
46 | // The document to get the associated window for. | |
47 | ||
48 | // In some IE versions (at least 6.0), document.parentWindow does not return a | |
49 | // reference to the real window object (maybe a copy), so we must fix it as well | |
50 | // We use IE specific execScript to attach the real window reference to | |
51 | // document._parentWindow for later use | |
52 | if(has("ie") && window !== document.parentWindow){ | |
53 | /* | |
54 | In IE 6, only the variable "window" can be used to connect events (others | |
55 | may be only copies). | |
56 | */ | |
57 | doc.parentWindow.execScript("document._parentWindow = window;", "Javascript"); | |
58 | //to prevent memory leak, unset it after use | |
59 | //another possibility is to add an onUnload handler which seems overkill to me (liucougar) | |
60 | var win = doc._parentWindow; | |
61 | doc._parentWindow = null; | |
62 | return win; // Window | |
63 | } | |
64 | ||
65 | return doc.parentWindow || doc.defaultView; // Window | |
66 | }, | |
67 | ||
68 | scrollIntoView: function(/*DomNode*/ node, /*Object?*/ pos){ | |
69 | // summary: | |
70 | // Scroll the passed node into view, if it is not already. | |
71 | ||
72 | // don't rely on node.scrollIntoView working just because the function is there | |
73 | ||
74 | try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method | |
75 | node = dom.byId(node); | |
76 | var doc = node.ownerDocument || baseWindow.doc, // TODO: why baseWindow.doc? Isn't node.ownerDocument always defined? | |
77 | body = baseWindow.body(doc), | |
78 | html = doc.documentElement || body.parentNode, | |
79 | isIE = has("ie"), isWK = has("webkit"); | |
80 | // if an untested browser, then use the native method | |
81 | if((!(has("mozilla") || isIE || isWK || has("opera")) || node == body || node == html) && (typeof node.scrollIntoView != "undefined")){ | |
82 | node.scrollIntoView(false); // short-circuit to native if possible | |
83 | return; | |
84 | } | |
85 | var backCompat = doc.compatMode == 'BackCompat', | |
86 | clientAreaRoot = (isIE >= 9 && "frameElement" in node.ownerDocument.parentWindow) | |
87 | ? ((html.clientHeight > 0 && html.clientWidth > 0 && (body.clientHeight == 0 || body.clientWidth == 0 || body.clientHeight > html.clientHeight || body.clientWidth > html.clientWidth)) ? html : body) | |
88 | : (backCompat ? body : html), | |
89 | scrollRoot = isWK ? body : clientAreaRoot, | |
90 | rootWidth = clientAreaRoot.clientWidth, | |
91 | rootHeight = clientAreaRoot.clientHeight, | |
92 | rtl = !geom.isBodyLtr(doc), | |
93 | nodePos = pos || geom.position(node), | |
94 | el = node.parentNode, | |
95 | isFixed = function(el){ | |
96 | return ((isIE <= 6 || (isIE && backCompat))? false : (style.get(el, 'position').toLowerCase() == "fixed")); | |
97 | }; | |
98 | if(isFixed(node)){ return; } // nothing to do | |
99 | ||
100 | while(el){ | |
101 | if(el == body){ el = scrollRoot; } | |
102 | var elPos = geom.position(el), | |
103 | fixedPos = isFixed(el); | |
104 | ||
105 | if(el == scrollRoot){ | |
106 | elPos.w = rootWidth; elPos.h = rootHeight; | |
107 | if(scrollRoot == html && isIE && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x | |
108 | if(elPos.x < 0 || !isIE){ elPos.x = 0; } // IE can have values > 0 | |
109 | if(elPos.y < 0 || !isIE){ elPos.y = 0; } | |
110 | }else{ | |
111 | var pb = geom.getPadBorderExtents(el); | |
112 | elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t; | |
113 | var clientSize = el.clientWidth, | |
114 | scrollBarSize = elPos.w - clientSize; | |
115 | if(clientSize > 0 && scrollBarSize > 0){ | |
116 | elPos.w = clientSize; | |
117 | elPos.x += (rtl && (isIE || el.clientLeft > pb.l/*Chrome*/)) ? scrollBarSize : 0; | |
118 | } | |
119 | clientSize = el.clientHeight; | |
120 | scrollBarSize = elPos.h - clientSize; | |
121 | if(clientSize > 0 && scrollBarSize > 0){ | |
122 | elPos.h = clientSize; | |
123 | } | |
124 | } | |
125 | if(fixedPos){ // bounded by viewport, not parents | |
126 | if(elPos.y < 0){ | |
127 | elPos.h += elPos.y; elPos.y = 0; | |
128 | } | |
129 | if(elPos.x < 0){ | |
130 | elPos.w += elPos.x; elPos.x = 0; | |
131 | } | |
132 | if(elPos.y + elPos.h > rootHeight){ | |
133 | elPos.h = rootHeight - elPos.y; | |
134 | } | |
135 | if(elPos.x + elPos.w > rootWidth){ | |
136 | elPos.w = rootWidth - elPos.x; | |
137 | } | |
138 | } | |
139 | // calculate overflow in all 4 directions | |
140 | var l = nodePos.x - elPos.x, // beyond left: < 0 | |
141 | t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0 | |
142 | r = l + nodePos.w - elPos.w, // beyond right: > 0 | |
143 | bot = t + nodePos.h - elPos.h; // beyond bottom: > 0 | |
144 | if(r * l > 0){ | |
145 | var s = Math[l < 0? "max" : "min"](l, r); | |
146 | if(rtl && ((isIE == 8 && !backCompat) || isIE >= 9)){ s = -s; } | |
147 | nodePos.x += el.scrollLeft; | |
148 | el.scrollLeft += s; | |
149 | nodePos.x -= el.scrollLeft; | |
150 | } | |
151 | if(bot * t > 0){ | |
152 | nodePos.y += el.scrollTop; | |
153 | el.scrollTop += Math[t < 0? "max" : "min"](t, bot); | |
154 | nodePos.y -= el.scrollTop; | |
155 | } | |
156 | el = (el != scrollRoot) && !fixedPos && el.parentNode; | |
157 | } | |
158 | }catch(error){ | |
159 | console.error('scrollIntoView: ' + error); | |
160 | node.scrollIntoView(false); | |
161 | } | |
162 | } | |
163 | }; | |
164 | ||
165 | 1 && lang.setObject("dojo.window", window); | |
166 | ||
167 | return window; | |
168 | }); |