[SalesForce] Mini Page Layout CSS in Visualforce Page

I've a VF Page which uses a Apex StandardSetController() to display the list of a Standard Object Records(Case in my Page). The mini page layout which is a standard functionality from Salesforce has some CSS issues.

On Hover, the mini page layout appears as expected but the position is absolute. I've scroll-able view, so when I hover on records after scrolling(on those which were hidden previously), the mini page layout is shown at the absolute position and not at the current position.

I'm sure that it has nothing to do with the StandardSetController(). Is there a CSS patch for this situation. Will it be a proper way to alter the Standard CSS since the classes and the CSS might be changed from the Salesforce side in a newer releases?

Best Answer

I've run into this issue before as well. It seems to be a combination of Javascript and CSS. Looking at their Javascript, this is the function that appears to be called

function LookupHoverDetail(a, b) {
    this.id = a;
    this.width = LookupHoverDetail.STANDARD_BUBBLE_WIDTH;
    this.bubbleOffset = Sfdc.userAgent.isIE6 ? 5 : 14;
    this.height = LookupHoverDetail.STANDARD_BUBBLE_HEIGHT;
    this.hover = document.createElement("div");
    this.hover.id = a + "Hover";
    this.hover.className = "individualPalette lookupHoverDetail lookupHoverDetailLoading lookupHoverDetailOverridable";
    this.hover.innerHTML = '<div class="topLeft"><div class="bPageBlock"><div class="pbBody">' + LC.getLabel("Global", "loading") + '<div><div class="pbFooter"><div class="bg"><div></div></div><div>';
    document.body.appendChild(this.hover);
    var c = this;
    addEvent(this.hover, "mouseover", function () {
        c.show()
    }, true);
    addEvent(this.hover, "mouseout", function () {
        c.hide()
    }, true);
    this.hover = new iframeShim(this.hover);
    this.originalClass = "";
    this.fadingIn = this.fadingOut = null;
    this.loaderURL = b;
    this.loaded = false
}
LookupHoverDetail.STANDARD_BUBBLE_WIDTH = 302;
LookupHoverDetail.STANDARD_BUBBLE_HEIGHT = 262;
LookupHoverDetail.SHOW_DELAY = 800;
LookupHoverDetail.HIDE_DELAY = 250;
LookupHoverDetail.stopLoading = false;
LookupHoverDetail.hovers = {};
LookupHoverDetail.getHover = function (a, b) {
    var c = window.Shepherd;
    if (c && b) b = c.fixRetUrl(b);
    if (LookupHoverDetail.hovers[a]) return LookupHoverDetail.hovers[a];
    c = new LookupHoverDetail(a, b);
    return LookupHoverDetail.hovers[a] = c
};
LookupHoverDetail.hideAllHovers = function () {
    var a = LookupHoverDetail.hovers,
        b;
    for (b in a) a.hasOwnProperty(b) && a[b].hide()
};
LookupHoverDetail.prototype.show = function () {
    if (this.fadingOut) {
        clearTimeout(this.fadingOut);
        this.fadingOut = null
    } else {
        var a = this;
        if (!this.fadingIn) this.fadingIn = setTimeout(function () {
            a.showNow()
        }, LookupHoverDetail.SHOW_DELAY)
    }
};
LookupHoverDetail.prototype.showNow = function () {
    if (!this.loaded) if (this.loaderURL != null) {
        var a = this;
        Sfdc.Ajax.get(this.loaderURL, function (b) {
            a.load(b)
        }, {
            failure: function (b) {
                a.load(b)
            }
        })
    } else return;
    this.position();
    this.hover.setStyle("visibility", "visible");
    this.fadingIn = null
};
LookupHoverDetail.prototype.hide = function () {
    if (this.fadingIn) {
        clearTimeout(this.fadingIn);
        this.fadingIn = null
    } else {
        var a = this;
        this.fadingOut = setTimeout(function () {
            a.hideNow()
        }, LookupHoverDetail.HIDE_DELAY)
    }
};
LookupHoverDetail.prototype.hideNow = function () {
    this.hover.setStyle("visibility", "hidden");
    this.fadingOut = null
};
LookupHoverDetail.prototype.load = function (a) {
    this.hover.div.innerHTML = a;
    Util.evalScriptsUnderElement(this.hover.div);
    this.originalClass = this.hover.div.firstChild.className;
    this.height = this.hover.div.offsetHeight;
    delStyleClass(this.hover.div, "lookupHoverDetailLoading");
    this.position();
    this.loaded = true
};
LookupHoverDetail.prototype.position = function () {
    var a = getElementByIdCS(this.id),
        b = getObjX(a),
        c = getObjY(a),
        d = a.offsetWidth,
        e = a.offsetHeight,
        f = getScrollX(),
        g = getScrollY(),
        h = getWindowWidth(),
        i = getWindowHeight();
    a = this.originalClass + " ";
    if (c + e + this.height < g + i) {
        a += "top";
        c += e
    } else {
        a += "bottom";
        c -= this.height
    }
    if (b + d - this.bubbleOffset + this.width < f + h) {
        a += "Left";
        b = b + d / 2 - this.bubbleOffset
    } else {
        a += "Right";
        b = b + d / 2 - this.width
    }
    this.hover.setStyle("left", b + "px");
    this.hover.setStyle("top", c + "px");
    this.hover.div.firstChild.className = a;
    if (this.hover.div.firstChild) if (b = Util.hasStyleEndsWith(this.hover.div.firstChild, "Override")) {
        delStyleClass(this.hover.div, "lookupHoverDetailOverridable");
        delStyleClass(this.hover.div.firstChild, b);
        addStyleClass(this.hover.div, b)
    }
};

I would guess that Salesforce most likely uses the same ID for the same object referenced twice on a page (so if you have a lookup field to the same object twice on the page, they probably share the same ID), so when this LookupHoverDetail method is used, it looks for the first instance in the DOM which is at the top of the page.

To be completely honest with you, I am not sure how you can fix this. You will need to override Salesforce's included Javascript.

Related Topic