dojo/window.js

Maintainability

50.23

Lines of code

238

Created with Raphaël 2.1.002550751002015-1-52014-12-42014-12-3

2015-5-18
Maintainability: 50.23

Created with Raphaël 2.1.00751502253002015-1-52014-12-42014-12-3

2015-5-18
Lines of Code: 238

Difficulty

67.24

Estimated Errors

2.80

Function weight

By Complexity

Created with Raphaël 2.1.0scrollIntoView50

By SLOC

Created with Raphaël 2.1.0<anonymous>237
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="&nbsp;";
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;
Column: 40 "Use '!==' to compare with '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
Column: 29 "Bad line breaking before '?'."
150
                            : (has("position-fixed-support") && (style.get(el, 'position').toLowerCase() == "fixed"));
151
                    },
152
                    self = this,
153
                    scrollElementBy = function(el, x, y){
154
                        if(el.tagName == "BODY" || el.tagName == "HTML"){
155
                            self.get(el.ownerDocument).scrollBy(x, y);
156
                        }else{
157
                            x && (el.scrollLeft += x);
Column: 53 "Expected an assignment or function call and instead saw an expression."
158
                            y && (el.scrollTop += y);
Column: 52 "Expected an assignment or function call and instead saw an expression."
159
                        }
160
                    };
161
                if(isFixed(node)){ return; } // nothing to do
162
                while(el){
163
                    if(el == body){ el = scrollRoot; }
164
                    var elPos = geom.position(el),
165
                        fixedPos = isFixed(el),
166
                        rtl = style.getComputedStyle(el).direction.toLowerCase() == "rtl";
167
 
168
                    if(el == scrollRoot){
169
                        elPos.w = rootWidth; elPos.h = rootHeight;
170
                        if(scrollRoot == html && (isIE || has("trident")) && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x
171
                        if(elPos.x < 0 || !isIE || isIE >= 9 || has("trident")){ elPos.x = 0; } // older IE can have values > 0
172
                        if(elPos.y < 0 || !isIE || isIE >= 9 || has("trident")){ elPos.y = 0; }
173
                    }else{
174
                        var pb = geom.getPadBorderExtents(el);
175
                        elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t;
176
                        var clientSize = el.clientWidth,
177
                            scrollBarSize = elPos.w - clientSize;
178
                        if(clientSize > 0 && scrollBarSize > 0){
179
                            if(rtl && has("rtl-adjust-position-for-verticalScrollBar")){
180
                                elPos.x += scrollBarSize;
181
                            }
182
                            elPos.w = clientSize;
183
                        }
184
                        clientSize = el.clientHeight;
185
                        scrollBarSize = elPos.h - clientSize;
186
                        if(clientSize > 0 && scrollBarSize > 0){
187
                            elPos.h = clientSize;
188
                        }
189
                    }
190
                    if(fixedPos){ // bounded by viewport, not parents
191
                        if(elPos.y < 0){
192
                            elPos.h += elPos.y; elPos.y = 0;
193
                        }
194
                        if(elPos.x < 0){
195
                            elPos.w += elPos.x; elPos.x = 0;
196
                        }
197
                        if(elPos.y + elPos.h > rootHeight){
198
                            elPos.h = rootHeight - elPos.y;
199
                        }
200
                        if(elPos.x + elPos.w > rootWidth){
201
                            elPos.w = rootWidth - elPos.x;
202
                        }
203
                    }
204
                    // calculate overflow in all 4 directions
205
                    var l = nodePos.x - elPos.x, // beyond left: < 0
206
//                      t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0
207
                        t = nodePos.y - elPos.y, // beyond top: < 0
208
                        r = l + nodePos.w - elPos.w, // beyond right: > 0
209
                        bot = t + nodePos.h - elPos.h; // beyond bottom: > 0
210
                    var s, old;
211
                    if(r * l > 0 && (!!el.scrollLeft || el == scrollRoot || el.scrollWidth > el.offsetHeight)){
212
                        s = Math[l < 0? "max" : "min"](l, r);
213
                        if(rtl && ((isIE == 8 && !backCompat) || isIE >= 9 || has("trident"))){ s = -s; }
214
                        old = el.scrollLeft;
215
                        scrollElementBy(el, s, 0);
216
                        s = el.scrollLeft - old;
217
                        nodePos.x -= s;
218
                    }
219
                    if(bot * t > 0 && (!!el.scrollTop || el == scrollRoot || el.scrollHeight > el.offsetHeight)){
220
                        s = Math.ceil(Math[t < 0? "max" : "min"](t, bot));
221
                        old = el.scrollTop;
222
                        scrollElementBy(el, 0, s);
223
                        s = el.scrollTop - old;
224
                        nodePos.y -= s;
225
                    }
226
                    el = (el != scrollRoot) && !fixedPos && el.parentNode;
227
                }
228
            }catch(error){
229
                console.error('scrollIntoView: ' + error);
230
                node.scrollIntoView(false);
231
            }
232
        }
233
    };
234
 
235
    has("extend-dojo") && lang.setObject("dojo.window", window);
Column: 63 "Expected an assignment or function call and instead saw an expression."
236
 
237
    return window;
238
});