place.js #1

  • //
  • guest/
  • perforce_software/
  • chronicle/
  • main/
  • application/
  • ui/
  • resources/
  • dojo/
  • ui/
  • place.js
  • View
  • Commits
  • Open Download .zip Download (5 KB)
dojo.provide("p4cms.ui.place");

// Override dijit._place to deal with fixed position nodes
// @todo update with dojo, last updated dojo 1.6.1
dijit._place = function(node, choices, layoutNode, aroundNodeCoords) {
    // get {x: 10, y: 10, w: 100, h:100} type obj representing position of
    // viewport over document
    var view = dojo.window.getBox();

    // if node position is fixed, reset view to pos 0
    if (dojo.style(node, 'position') === 'fixed') {
        view.t = 0;
        view.l = 0;
    }

    // This won't work if the node is inside a <div style="position: relative">,
    // so reattach it to dojo.doc.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;
    dojo.some(choices, function(choice) {
        var corner      = choice.corner,
            pos         = choice.pos,
            overflow    = 0;

        // calculate amount of space available given specified position of node
        var spaceAvailable = {
            w: corner.charAt(1) === 'L' ? (view.l + view.w) - pos.x : pos.x - view.l,
            h: corner.charAt(1) === 'T' ? (view.t + view.h) - pos.y : pos.y - view.t
        };

        // 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 tooltip's size changes based on position, due to triangle)
        if (layoutNode) {
            var res = layoutNode(node, choice.aroundCorner, corner, spaceAvailable, aroundNodeCoords);
            overflow = typeof res === "undefined" ? 0 : res;
        }

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

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

        overflow += (mb.w - width) + (mb.h - height);

        if (!best|| overflow < best.overflow) {
            best = {
                corner:         corner,
                aroundCorner:   choice.aroundCorner,
                x:              startX,
                y:              startY,
                w:              width,
                h:              height,
                overflow:       overflow,
                spaceAvailable: spaceAvailable
            };
        }

        return !overflow;
    });

    // In case the best position is not the last one we checked, need to call
    // layoutNode() again.
    if (best.overflow && layoutNode) {
        layoutNode(node, best.aroundCorner, best.corner, best.spaceAvailable, aroundNodeCoords);
    }

    // And then position the node.   Do this last, after the layoutNode() above
    // has sized the node, due to browser quirks when the viewport is scrolled
    // (specifically that a Tooltip will shrink to fit as though the window was
    // scrolled to the left).
    //
    // In RTL mode, set style.right rather than style.left so in the common case,
    // window resizes move the popup along with the aroundNode.
    var l = dojo._isBodyLtr(),
        s = node.style;
    s.top = best.y + "px";

    s[l ? "left" : "right"] = (l ? best.x : view.w - best.x - best.w) + "px";

    return best;
};

// Override placeOnScreenAround node to use fixed position if node is fixed
// @todo update when dojo is udpated, last updated dojo 1.6.1
dijit.placeOnScreenAroundNode = function(node, aroundNode, aroundCorners, layoutNode) {
    // get coordinates of aroundNode
    aroundNode          = dojo.byId(aroundNode);
    var isFixed         = dojo.style(node, 'position') === 'fixed',
        aroundNodePos   = dojo.position(aroundNode, !isFixed);

    // place the node around the calculated rectangle
    return dijit._placeOnScreenAroundRect(node,
        aroundNodePos.x, aroundNodePos.y, aroundNodePos.w, aroundNodePos.h,     // rectangle
        aroundCorners, layoutNode);
};

// @todo update when dojo is udpated, last updated dojo 1.6.1
dijit.placementRegistry.unregister("node");
dijit.placementRegistry.register("node",
    function(n, x) {
        return typeof x === "object" &&
            typeof x.offsetWidth !== "undefined" && typeof x.offsetHeight !== "undefined";
    },
    dijit.placeOnScreenAroundNode
);
# Change User Description Committed
#1 16170 perforce_software Move Chronicle files to follow new path scheme for branching.
//guest/perforce_software/chronicle/application/ui/resources/dojo/ui/place.js
#1 8972 Matt Attaway Initial add of the Chronicle source code