Subversion Repositories Applications.papyrus

Rev

Blame | Last modification | View Log | RSS feed

if(!dojo._hasResource["dijit._base.place"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dijit._base.place"] = true;
dojo.provide("dijit._base.place");

// ported from dojo.html.util

dijit.getViewport = function(){
        //      summary
        //      Returns the dimensions and scroll position of the viewable area of a browser window

        var _window = dojo.global;
        var _document = dojo.doc;

        // get viewport size
        var w = 0, h = 0;
        if(dojo.isMozilla){
                // mozilla
                // _window.innerHeight includes the height taken by the scroll bar
                // clientHeight is ideal but has DTD issues:
                // #4539: FF reverses the roles of body.clientHeight/Width and documentElement.clientHeight/Width based on the DTD!
                // check DTD to see whether body or documentElement returns the viewport dimensions using this algorithm:
                var minw, minh, maxw, maxh;
                if(_document.body.clientWidth>_document.documentElement.clientWidth){
                        minw = _document.documentElement.clientWidth;
                        maxw = _document.body.clientWidth;
                }else{
                        maxw = _document.documentElement.clientWidth;
                        minw = _document.body.clientWidth;
                }
                if(_document.body.clientHeight>_document.documentElement.clientHeight){
                        minh = _document.documentElement.clientHeight;
                        maxh = _document.body.clientHeight;
                }else{
                        maxh = _document.documentElement.clientHeight;
                        minh = _document.body.clientHeight;
                }
                w = (maxw > _window.innerWidth) ? minw : maxw;
                h = (maxh > _window.innerHeight) ? minh : maxh;
        }else if(!dojo.isOpera && _window.innerWidth){
                //in opera9, dojo.body().clientWidth should be used, instead
                //of window.innerWidth/document.documentElement.clientWidth
                //so we have to check whether it is opera
                w = _window.innerWidth;
                h = _window.innerHeight;
        }else if(dojo.isIE && _document.documentElement && _document.documentElement.clientHeight){
                w = _document.documentElement.clientWidth;
                h = _document.documentElement.clientHeight;
        }else if(dojo.body().clientWidth){
                // IE5, Opera
                w = dojo.body().clientWidth;
                h = dojo.body().clientHeight;
        }

        // get scroll position
        var scroll = dojo._docScroll();

        return { w: w, h: h, l: scroll.x, t: scroll.y };        //      object
};

dijit.placeOnScreen = function(
        /* DomNode */   node,
        /* Object */            pos,
        /* Object */            corners,
        /* boolean? */          tryOnly){
        //      summary:
        //              Keeps 'node' in the visible area of the screen while trying to
        //              place closest to pos.x, pos.y. The input coordinates are
        //              expected to be the desired document position.
        //
        //              Set which corner(s) you want to bind to, such as
        //              
        //                      placeOnScreen(node, {x: 10, y: 20}, ["TR", "BL"])
        //              
        //              The desired x/y will be treated as the topleft(TL)/topright(TR) or
        //              BottomLeft(BL)/BottomRight(BR) corner of the node. Each corner is tested
        //              and if a perfect match is found, it will be used. Otherwise, it goes through
        //              all of the specified corners, and choose the most appropriate one.
        //              
        //              NOTE: node is assumed to be absolutely or relatively positioned.

        var choices = dojo.map(corners, function(corner){ return { corner: corner, pos: pos }; });

        return dijit._place(node, choices);
}

dijit._place = function(/*DomNode*/ node, /* Array */ choices, /* Function */ layoutNode){
        // summary:
        //              Given a list of spots to put node, put it at the first spot where it fits,
        //              of if it doesn't fit anywhere then the place with the least overflow
        // choices: Array
        //              Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} }
        //              Above example says to put the top-left corner of the node at (10,20)
        //      layoutNode: Function(node, orient)
        //              for things like tooltip, they are displayed differently (and have different dimensions)
        //              based on their orientation relative to the parent.   This adjusts the popup based on orientation.

        // get {x: 10, y: 10, w: 100, h:100} type obj representing position of
        // viewport over document
        var view = dijit.getViewport();

        // This won't work if the node is inside a <div style="position: relative">,
        // so reattach it to document.body.   (Otherwise, the positioning will be wrong
        // and also it might get cutoff)
        if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){
                dojo.body().appendChild(node);
        }

        var best=null;
        for(var i=0; i<choices.length; i++){
                var corner = choices[i].corner;
                var pos = choices[i].pos;

                // configure node to be displayed in given position relative to button
                // (need to do this in order to get an accurate size for the node, because
                // a tooltips size changes based on position, due to triangle)
                if(layoutNode){
                        layoutNode(corner);
                }

                // get node's size
                var oldDisplay = node.style.display;
                var oldVis = node.style.visibility;
                node.style.visibility = "hidden";
                node.style.display = "";
                var mb = dojo.marginBox(node);
                node.style.display = oldDisplay;
                node.style.visibility = oldVis;

                // coordinates and size of node with specified corner placed at pos,
                // and clipped by viewport
                var startX = (corner.charAt(1)=='L' ? pos.x : Math.max(view.l, pos.x - mb.w)),
                        startY = (corner.charAt(0)=='T' ? pos.y : Math.max(view.t, pos.y -  mb.h)),
                        endX = (corner.charAt(1)=='L' ? Math.min(view.l+view.w, startX+mb.w) : pos.x),
                        endY = (corner.charAt(0)=='T' ? Math.min(view.t+view.h, startY+mb.h) : pos.y),
                        width = endX-startX,
                        height = endY-startY,
                        overflow = (mb.w-width) + (mb.h-height);

                if(best==null || overflow<best.overflow){
                        best = {
                                corner: corner,
                                aroundCorner: choices[i].aroundCorner,
                                x: startX,
                                y: startY,
                                w: width,
                                h: height,
                                overflow: overflow
                        };
                }
                if(overflow==0){
                        break;
                }
        }

        node.style.left = best.x + "px";
        node.style.top = best.y + "px";
        return best;
}

dijit.placeOnScreenAroundElement = function(
        /* DomNode */           node,
        /* DomNode */           aroundNode,
        /* Object */            aroundCorners,
        /* Function */          layoutNode){

        //      summary
        //      Like placeOnScreen, except it accepts aroundNode instead of x,y
        //      and attempts to place node around it.  Uses margin box dimensions.
        //
        //      aroundCorners
        //              specify Which corner of aroundNode should be
        //              used to place the node => which corner(s) of node to use (see the
        //              corners parameter in dijit.placeOnScreen)
        //              e.g. {'TL': 'BL', 'BL': 'TL'}
        //
        //      layoutNode: Function(node, orient)
        //              for things like tooltip, they are displayed differently (and have different dimensions)
        //              based on their orientation relative to the parent.   This adjusts the popup based on orientation.


        // get coordinates of aroundNode
        aroundNode = dojo.byId(aroundNode);
        var oldDisplay = aroundNode.style.display;
        aroundNode.style.display="";
        // #3172: use the slightly tighter border box instead of marginBox
        var aroundNodeW = aroundNode.offsetWidth; //mb.w;
        var aroundNodeH = aroundNode.offsetHeight; //mb.h;
        var aroundNodePos = dojo.coords(aroundNode, true);
        aroundNode.style.display=oldDisplay;

        // Generate list of possible positions for node
        var choices = [];
        for(var nodeCorner in aroundCorners){
                choices.push( {
                        aroundCorner: nodeCorner,
                        corner: aroundCorners[nodeCorner],
                        pos: {
                                x: aroundNodePos.x + (nodeCorner.charAt(1)=='L' ? 0 : aroundNodeW),
                                y: aroundNodePos.y + (nodeCorner.charAt(0)=='T' ? 0 : aroundNodeH)
                        }
                });
        }

        return dijit._place(node, choices, layoutNode);
}

}