1 | define(["./_base/lang", "./sniff", "./_base/window", "./dom", "./dom-geometry", "./dom-style", "./dom-construct"], |
---|
2 | function(lang, has, baseWindow, dom, geom, style, domConstruct){ |
---|
3 | |
---|
4 | // feature detection |
---|
5 | /* not needed but included here for future reference |
---|
6 | has.add("rtl-innerVerticalScrollBar-on-left", function(win, doc){ |
---|
7 | var body = baseWindow.body(doc), |
---|
8 | scrollable = domConstruct.create('div', { |
---|
9 | style: {overflow:'scroll', overflowX:'hidden', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', width:'64px', height:'64px'} |
---|
10 | }, body, "last"), |
---|
11 | center = domConstruct.create('center', { |
---|
12 | style: {overflow:'hidden', direction:'ltr'} |
---|
13 | }, scrollable, "last"), |
---|
14 | inner = domConstruct.create('div', { |
---|
15 | style: {overflow:'visible', display:'inline' } |
---|
16 | }, center, "last"); |
---|
17 | inner.innerHTML=" "; |
---|
18 | var midPoint = Math.max(inner.offsetLeft, geom.position(inner).x); |
---|
19 | var ret = midPoint >= 32; |
---|
20 | center.removeChild(inner); |
---|
21 | scrollable.removeChild(center); |
---|
22 | body.removeChild(scrollable); |
---|
23 | return ret; |
---|
24 | }); |
---|
25 | */ |
---|
26 | has.add("rtl-adjust-position-for-verticalScrollBar", function(win, doc){ |
---|
27 | var body = baseWindow.body(doc), |
---|
28 | scrollable = domConstruct.create('div', { |
---|
29 | style: {overflow:'scroll', overflowX:'visible', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', top:'0', width:'64px', height:'64px'} |
---|
30 | }, body, "last"), |
---|
31 | div = domConstruct.create('div', { |
---|
32 | style: {overflow:'hidden', direction:'ltr'} |
---|
33 | }, scrollable, "last"), |
---|
34 | ret = geom.position(div).x != 0; |
---|
35 | scrollable.removeChild(div); |
---|
36 | body.removeChild(scrollable); |
---|
37 | return ret; |
---|
38 | }); |
---|
39 | |
---|
40 | has.add("position-fixed-support", function(win, doc){ |
---|
41 | // IE6, IE7+quirks, and some older mobile browsers don't support position:fixed |
---|
42 | var body = baseWindow.body(doc), |
---|
43 | outer = domConstruct.create('span', { |
---|
44 | style: {visibility:'hidden', position:'fixed', left:'1px', top:'1px'} |
---|
45 | }, body, "last"), |
---|
46 | inner = domConstruct.create('span', { |
---|
47 | style: {position:'fixed', left:'0', top:'0'} |
---|
48 | }, outer, "last"), |
---|
49 | ret = geom.position(inner).x != geom.position(outer).x; |
---|
50 | outer.removeChild(inner); |
---|
51 | body.removeChild(outer); |
---|
52 | return ret; |
---|
53 | }); |
---|
54 | |
---|
55 | // module: |
---|
56 | // dojo/window |
---|
57 | |
---|
58 | var window = { |
---|
59 | // summary: |
---|
60 | // TODOC |
---|
61 | |
---|
62 | getBox: function(/*Document?*/ doc){ |
---|
63 | // summary: |
---|
64 | // Returns the dimensions and scroll position of the viewable area of a browser window |
---|
65 | |
---|
66 | doc = doc || baseWindow.doc; |
---|
67 | |
---|
68 | var |
---|
69 | scrollRoot = (doc.compatMode == 'BackCompat') ? baseWindow.body(doc) : doc.documentElement, |
---|
70 | // get scroll position |
---|
71 | scroll = geom.docScroll(doc), // scrollRoot.scrollTop/Left should work |
---|
72 | w, h; |
---|
73 | |
---|
74 | if(has("touch")){ // if(scrollbars not supported) |
---|
75 | var uiWindow = window.get(doc); // use UI window, not dojo.global window |
---|
76 | // on mobile, scrollRoot.clientHeight <= uiWindow.innerHeight <= scrollRoot.offsetHeight, return uiWindow.innerHeight |
---|
77 | w = uiWindow.innerWidth || scrollRoot.clientWidth; // || scrollRoot.clientXXX probably never evaluated |
---|
78 | h = uiWindow.innerHeight || scrollRoot.clientHeight; |
---|
79 | }else{ |
---|
80 | // on desktops, scrollRoot.clientHeight <= scrollRoot.offsetHeight <= uiWindow.innerHeight, return scrollRoot.clientHeight |
---|
81 | // uiWindow.innerWidth/Height includes the scrollbar and cannot be used |
---|
82 | w = scrollRoot.clientWidth; |
---|
83 | h = scrollRoot.clientHeight; |
---|
84 | } |
---|
85 | return { |
---|
86 | l: scroll.x, |
---|
87 | t: scroll.y, |
---|
88 | w: w, |
---|
89 | h: h |
---|
90 | }; |
---|
91 | }, |
---|
92 | |
---|
93 | get: function(/*Document*/ doc){ |
---|
94 | // summary: |
---|
95 | // Get window object associated with document doc. |
---|
96 | // doc: |
---|
97 | // The document to get the associated window for. |
---|
98 | |
---|
99 | // In some IE versions (at least 6.0), document.parentWindow does not return a |
---|
100 | // reference to the real window object (maybe a copy), so we must fix it as well |
---|
101 | // We use IE specific execScript to attach the real window reference to |
---|
102 | // document._parentWindow for later use |
---|
103 | if(has("ie") && window !== document.parentWindow){ |
---|
104 | /* |
---|
105 | In IE 6, only the variable "window" can be used to connect events (others |
---|
106 | may be only copies). |
---|
107 | */ |
---|
108 | doc.parentWindow.execScript("document._parentWindow = window;", "Javascript"); |
---|
109 | //to prevent memory leak, unset it after use |
---|
110 | //another possibility is to add an onUnload handler which seems overkill to me (liucougar) |
---|
111 | var win = doc._parentWindow; |
---|
112 | doc._parentWindow = null; |
---|
113 | return win; // Window |
---|
114 | } |
---|
115 | |
---|
116 | return doc.parentWindow || doc.defaultView; // Window |
---|
117 | }, |
---|
118 | |
---|
119 | scrollIntoView: function(/*DomNode*/ node, /*Object?*/ pos){ |
---|
120 | // summary: |
---|
121 | // Scroll the passed node into view using minimal movement, if it is not already. |
---|
122 | |
---|
123 | // Don't rely on node.scrollIntoView working just because the function is there since |
---|
124 | // it forces the node to the page's bottom or top (and left or right in IE) without consideration for the minimal movement. |
---|
125 | // WebKit's node.scrollIntoViewIfNeeded doesn't work either for inner scrollbars in right-to-left mode |
---|
126 | // and when there's a fixed position scrollable element |
---|
127 | |
---|
128 | try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method |
---|
129 | node = dom.byId(node); |
---|
130 | var doc = node.ownerDocument || baseWindow.doc, // TODO: why baseWindow.doc? Isn't node.ownerDocument always defined? |
---|
131 | body = baseWindow.body(doc), |
---|
132 | html = doc.documentElement || body.parentNode, |
---|
133 | isIE = has("ie"), |
---|
134 | isWK = has("webkit"); |
---|
135 | // if an untested browser, then use the native method |
---|
136 | if(node == body || node == html){ return; } |
---|
137 | if(!(has("mozilla") || isIE || isWK || has("opera") || has("trident")) && ("scrollIntoView" in node)){ |
---|
138 | node.scrollIntoView(false); // short-circuit to native if possible |
---|
139 | return; |
---|
140 | } |
---|
141 | var backCompat = doc.compatMode == 'BackCompat', |
---|
142 | rootWidth = Math.min(body.clientWidth || html.clientWidth, html.clientWidth || body.clientWidth), |
---|
143 | rootHeight = Math.min(body.clientHeight || html.clientHeight, html.clientHeight || body.clientHeight), |
---|
144 | scrollRoot = (isWK || backCompat) ? body : html, |
---|
145 | nodePos = pos || geom.position(node), |
---|
146 | el = node.parentNode, |
---|
147 | isFixed = function(el){ |
---|
148 | return (isIE <= 6 || (isIE == 7 && backCompat)) |
---|
149 | ? false |
---|
150 | : (has("position-fixed-support") && (style.get(el, 'position').toLowerCase() == "fixed")); |
---|
151 | }; |
---|
152 | if(isFixed(node)){ return; } // nothing to do |
---|
153 | while(el){ |
---|
154 | if(el == body){ el = scrollRoot; } |
---|
155 | var elPos = geom.position(el), |
---|
156 | fixedPos = isFixed(el), |
---|
157 | rtl = style.getComputedStyle(el).direction.toLowerCase() == "rtl"; |
---|
158 | |
---|
159 | if(el == scrollRoot){ |
---|
160 | elPos.w = rootWidth; elPos.h = rootHeight; |
---|
161 | if(scrollRoot == html && isIE && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x |
---|
162 | if(elPos.x < 0 || !isIE || isIE >= 9){ elPos.x = 0; } // older IE can have values > 0 |
---|
163 | if(elPos.y < 0 || !isIE || isIE >= 9){ elPos.y = 0; } |
---|
164 | }else{ |
---|
165 | var pb = geom.getPadBorderExtents(el); |
---|
166 | elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t; |
---|
167 | var clientSize = el.clientWidth, |
---|
168 | scrollBarSize = elPos.w - clientSize; |
---|
169 | if(clientSize > 0 && scrollBarSize > 0){ |
---|
170 | if(rtl && has("rtl-adjust-position-for-verticalScrollBar")){ |
---|
171 | elPos.x += scrollBarSize; |
---|
172 | } |
---|
173 | elPos.w = clientSize; |
---|
174 | } |
---|
175 | clientSize = el.clientHeight; |
---|
176 | scrollBarSize = elPos.h - clientSize; |
---|
177 | if(clientSize > 0 && scrollBarSize > 0){ |
---|
178 | elPos.h = clientSize; |
---|
179 | } |
---|
180 | } |
---|
181 | if(fixedPos){ // bounded by viewport, not parents |
---|
182 | if(elPos.y < 0){ |
---|
183 | elPos.h += elPos.y; elPos.y = 0; |
---|
184 | } |
---|
185 | if(elPos.x < 0){ |
---|
186 | elPos.w += elPos.x; elPos.x = 0; |
---|
187 | } |
---|
188 | if(elPos.y + elPos.h > rootHeight){ |
---|
189 | elPos.h = rootHeight - elPos.y; |
---|
190 | } |
---|
191 | if(elPos.x + elPos.w > rootWidth){ |
---|
192 | elPos.w = rootWidth - elPos.x; |
---|
193 | } |
---|
194 | } |
---|
195 | // calculate overflow in all 4 directions |
---|
196 | var l = nodePos.x - elPos.x, // beyond left: < 0 |
---|
197 | // t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0 |
---|
198 | t = nodePos.y - elPos.y, // beyond top: < 0 |
---|
199 | r = l + nodePos.w - elPos.w, // beyond right: > 0 |
---|
200 | bot = t + nodePos.h - elPos.h; // beyond bottom: > 0 |
---|
201 | var s, old; |
---|
202 | if(r * l > 0 && (!!el.scrollLeft || el == scrollRoot || el.scrollWidth > el.offsetHeight)){ |
---|
203 | s = Math[l < 0? "max" : "min"](l, r); |
---|
204 | if(rtl && ((isIE == 8 && !backCompat) || isIE >= 9)){ s = -s; } |
---|
205 | old = el.scrollLeft; |
---|
206 | el.scrollLeft += s; |
---|
207 | s = el.scrollLeft - old; |
---|
208 | nodePos.x -= s; |
---|
209 | } |
---|
210 | if(bot * t > 0 && (!!el.scrollTop || el == scrollRoot || el.scrollHeight > el.offsetHeight)){ |
---|
211 | s = Math.ceil(Math[t < 0? "max" : "min"](t, bot)); |
---|
212 | old = el.scrollTop; |
---|
213 | el.scrollTop += s; |
---|
214 | s = el.scrollTop - old; |
---|
215 | nodePos.y -= s; |
---|
216 | } |
---|
217 | el = (el != scrollRoot) && !fixedPos && el.parentNode; |
---|
218 | } |
---|
219 | }catch(error){ |
---|
220 | console.error('scrollIntoView: ' + error); |
---|
221 | node.scrollIntoView(false); |
---|
222 | } |
---|
223 | } |
---|
224 | }; |
---|
225 | |
---|
226 | has("extend-dojo") && lang.setObject("dojo.window", window); |
---|
227 | |
---|
228 | return window; |
---|
229 | }); |
---|