Changeset 13710

Show
Ignore:
Timestamp:
05/12/08 17:50:50 (2 months ago)
Author:
doughays
Message:

Fixes #6409 !strict. Redesigned dijit.scrollIntoView to handle horizontal scrolling, right-to-left, and nested scrollbars. Called scrollIntoView automatically onfocus of a widget. Added automated test.

Location:
dijit/trunk
Files:
1 added
2 modified

Legend:

Unmodified
Added
Removed
  • dijit/trunk/_base/scroll.js

    r13320 r13710  
    1515        // node.scrollIntoView hides part of the parent's scrollbar, 
    1616        // so just manage the parent scrollbar ourselves 
     17 
     18        // all the V/H object members below are to reuse code for both directions 
     19        function addPseudoAttrs(element){ 
     20                // use border box for node since margin visibility is least important 
     21                // use content box for parents since we don't care about parent border and padding 
     22                // use HTML size instead of BODY size since that's where the scrollbars are defined 
     23                var parent = element.parentNode; 
     24                var nodeBox = dojo._getBorderBox(element); 
     25                if(element.tagName=="BODY"){ 
     26                        htmlBox = dojo._getBorderBox(parent); 
     27                        // this varies depending on browser and DOCTYPE 
     28                        if(htmlBox.w < nodeBox.w){ nodeBox.w = htmlBox.w; } 
     29                        if(htmlBox.h < nodeBox.h){ nodeBox.h = htmlBox.h; } 
     30                } 
     31                size = { H: nodeBox.w, V: nodeBox.h }; 
     32                var start = { H:element.offsetLeft, V:element.offsetTop }; 
     33                // check if this node and its parent share the same offsetParent 
     34                element._startIsRelative = !(parent && parent.tagName && parent.offsetParent == element.offsetParent); 
     35                var bp = dojo._getBorderExtents(element); 
     36                if(element != node){ // parent = skip border 
     37                        start.H += bp.l; 
     38                        start.V += bp.t; 
     39                }else{ // original node = add border to size 
     40                        size.H += bp.w; 
     41                        size.V += bp.h; 
     42                } 
     43                // FIXME: _getBorderBox/FF2 workaround 
     44                var fudgeStart = { H:0, V:0 }; 
     45                if(dojo.isFF == 2){ 
     46                        var parent = element.parentNode; 
     47                        if(parent && parent.tagName){ 
     48                                var bp = dojo._getBorderExtents(parent); 
     49                                fudgeStart.H += bp.l; 
     50                                fudgeStart.V += bp.t; 
     51                        } 
     52                } 
     53                element._size = size; 
     54                element._start = start; 
     55                element._fudgeStart = fudgeStart; 
     56        } 
     57 
     58        var r2l = !dojo._isBodyLtr(); 
     59        node = dojo.byId(node); 
    1760        var parent = node.parentNode; 
    18         var parentBottom = parent.scrollTop + dojo.marginBox(parent).h; //PORT was getBorderBox 
    19         var nodeBottom = node.offsetTop + dojo.marginBox(node).h; 
    20         if(parentBottom < nodeBottom){ 
    21                 parent.scrollTop += (nodeBottom - parentBottom); 
    22         }else if(parent.scrollTop > node.offsetTop){ 
    23                 parent.scrollTop -= (parent.scrollTop - node.offsetTop); 
     61        addPseudoAttrs(node); 
     62        var xy = { V: null, H: null }; 
     63        while(parent && parent.tagName){ // tagName check needed for IE since HTML node has a tag-less parent 
     64                addPseudoAttrs(parent); 
     65                // for both x and y directions 
     66                for (var dir in xy){ 
     67                        var scrollAttr = (dir=="H")? "scrollLeft" : "scrollTop"; 
     68                        var oldScroll = parent[scrollAttr]; 
     69                        nodeRelativeOffset = node._start[dir] + node._fudgeStart[dir] - (node._startIsRelative? 0 : parent._start[dir]) - oldScroll; 
     70                        if(parent._size[dir] < node._size[dir]){ // see if the node will be clipped 
     71                                node._size[dir] = parent._size[dir]; // simplify calculations 
     72                        } 
     73                        var overflow = nodeRelativeOffset + node._size[dir] - parent._size[dir]; 
     74                        var underflow = nodeRelativeOffset; 
     75                        var scrollAmount; 
     76                        // see if we should scroll forward or backward 
     77                        if(underflow <= 0){ 
     78                                scrollAmount = underflow; 
     79                        }else if(overflow <= 0){ 
     80                                scrollAmount = 0; 
     81                        }else if(underflow < overflow){ 
     82                                scrollAmount = underflow; 
     83                        }else{ 
     84                                scrollAmount = overflow; 
     85                        } 
     86                        var newScroll = scrollAmount + oldScroll; 
     87                        if(newScroll < 0 && r2l && dir=="H"){ // safari and IE need an adjustment since inline nodes return the wrong offsetLeft in right-to-left mode 
     88                                newScroll += parent.scrollWidth - parent.clientWidth; 
     89                        } 
     90                        parent[scrollAttr] = newScroll; // actually perform the scroll 
     91                        nodeRelativeOffset -= parent[scrollAttr] - oldScroll; 
     92                        parent._size[dir] = node._size[dir]; // now we only want to show this portion of the parent 
     93                        parent._start[dir] += nodeRelativeOffset; // the new visible portion of the parent may have tweaked coordinates 
     94                } 
     95                node = parent; // now see if the parent needs to be scrolled as well 
     96                parent = parent.parentNode; 
    2497        } 
    2598}; 
  • dijit/trunk/_Widget.js

    r13683 r13710  
    298298 
    299299        _onFocus: function(e){ 
     300                dijit.scrollIntoView(this.domNode); 
    300301                this.onFocus(); 
    301302        },