Search code examples
salesforcevisualforce

How to fix Visualforce navbar overflow issue caused by embedding analytics:reportCharts


Sorry for the long title. I posted this question on the official Salesforce developer forum about a week ago and still haven't gotten any responses, so I thought I'd ask about it here to see if I have any better luck.

I have a visualforce page. It worked well until I added a embedded piecharts in the top right corner. After I added these, I noticed that the navbar began spilling out of it's container (it is normally supposed to convert itself to a drop down for additional menu items)

navbar overflowing out of its containing element

Here is my VF code:

<apex:page controller="SalesGoalsController" sidebar="false">
    <apex:stylesheet value="{!$Resource.MapStyles}" />
    <apex:includeScript value="{!$Resource.MapSettings}"/>
    <apex:includeScript value="{!$Resource.MapTabs}" loadonReady="true"/>

    <script type="text/javascript">
          // some javascript stuff that initializes some things here
          window.onload = function() {
               // a bunch of Visualforce.remoting.Manager.invokeAction()
               // calls that do not manipulate any elements on the page
               // whatsoever and i would never have any reason to suspect
               // that this would be what is causing this issue because
               // literally all these calls do is populate some arrays
          };
    </script>

    <div class="pagelabel">Maps</div>

    <div id="tabsContainer">
        <ul class="tabs">
            <li class="tab"><a href="#tab1">tab1</a></li>
            <li class="tab"><a href="#tab2">tab2</a></li>
        </ul>        
    </div>

    <div id="tab1" class="tabcontent">
        <div class="topleft">
            <div id="tab1Logo">
                <apex:image url="{!$Resource.tab1LogoSmall}"/>
            </div>
        </div>  

        <div class="topright">
            <div id="piechart-world" class="piechart">
                <analytics:reportChart reportId="areportIDgoeshere" size="tiny" showRefreshButton="false">
                </analytics:reportChart>
            </div>
            <div id="piechart-us" class="piechart">
                <analytics:reportChart reportId="areportIDgoeshere" size="tiny" showRefreshButton="false">
                </analytics:reportChart>
            </div>
            <div id="piechart-ca" class="piechart">
                <analytics:reportChart reportId="areportIDgoeshere" size="tiny" showRefreshButton="false">
                </analytics:reportChart>
            </div>
        </div>  

        <div class="ChartsContainer" >
            <font size="3" color="blue">  
                <p>Opportunities sold this year</p>
                <select id="tab1ChartView" onchange="setView(this)">
                    <option value="world">World</option>
                    <option value="usa">USA</option>
                    <option value="canada">Canada</option>
                </select>
            </font>
            <div id="tab1SalesChart" class="saleschart">
            </div> 
            <font size="3" color="blue">
                <p>RFQ received this year</p>
            </font>
            <div id="RFQChart" class="saleschart"></div>
        </div>
    </div>

    <div id="tab2" class="tabcontent">
        <div class="topleft">
            <div id="tab2Logo">
                <apex:image url="{!$Resource.tab2LogoSmall}"/>
            </div>
        </div> 

        <div class="topright">
            <div id="piechart-world" class="piechart">
                <analytics:reportChart reportId="aReportIDgoeshere" size="tiny" showRefreshButton="false">
                </analytics:reportChart>
            </div>
            <div id="piechart-us" class="piechart">
                <analytics:reportChart reportId="aReportIDgoeshere" size="tiny" showRefreshButton="false">
                </analytics:reportChart>
            </div>
            <div id="piechart-ca" class="piechart">
                <analytics:reportChart reportId="aReportIDgoeshere" size="tiny" showRefreshButton="false">
                </analytics:reportChart>
            </div>
        </div>

        <div class="ChartsContainer" >
            <font size="3" color="blue">  
                <p>Opportunities sold this year</p>
                <select id="tab2ChartView" onchange="setView(this)">
                    <option value="world">World</option>
                    <option value="usa">USA</option>
                    <option value="canada">Canada</option>
                </select>
            </font>
            <div id="tab2SalesChart" class="saleschart">
            </div> 
        </div>
    </div>
</apex:page>

Here is my CSS:

ul.tabs {
    overflow: hidden;
    border-top: none;
    border-left: none;
    border-right: none;
    border-bottom: 3px solid;
    border-color: #1797C0;
    padding: 0px;
    margin: 0px;
    margin-bottom: 10px;
}

li.tab {
    list-style-type: none;
    float: left;
    display; inline;
    background-color: inherit;
    border: none;
    outline: none;
    cursor: pointer;
    padding: 0px;
    margin: 0px;
    transition: 0.3s;
}

.tabs a {
    padding: 5px 10px;
    font-weight: bold;
    display: inline-block;
    background: #fff;
    color: #000;
    text-decoration: none;
}

.tabs a:hover {
    text-decoration: none;
    color: #1797C0;
}

.tabs a.active {
    background: #1797C0;
    color: #fff;
    text-decoration: none;
}

.topleft {
    float: left;
    position: relative;
    width: 100%;
    margin-bottom: 10px;
}

.topright {
    float: right;
    position:absolute;
    right:10px;
    z-index: 11;
}

.piechart {
    display: none;
}

.pagelabel {
    position: relative;
    font-size: 1.5em;
    color: #222;
    margin: 10px;
}

.saleschart {
    width: 90vw;
    height: 90vh;
    padding-top: 15px;
}

.logo {
    display: inline;
    float: left;
}

.chartheader {
    color: #0000ff;
    font-size: 1.3em;
}

.maptotal {
    font-size: 1.5em;
    color: #222;
    display: inline;
    float: right;
    width: 60%;
}

I have a javascript function that basically sets all except one of the piecharts to display:none (the one that is displayed is display:block) depending on what tab the user is on. I know this is pretty hacky but I couldn't really figure out a better way to do it.

function showPiechart(piechart_name) {
    var elem_id = "piechart-" + piechart_name;
    for (var i=0, elem; elem = piechart_divs[i]; i++) {
        if (elem.id == elem_id) {
            elem.style.display = "block";
        } else {
            elem.style.display = "none";
        };
    };
};

Solution

  • So, for whatever dumb reason, if you have some Visualforce.remoting.manager.invokeAction(); calls being made inside of a window.onload = function() { ... } block, it's going to break your navbar. In fact, for all I know, this might happen even if you're not making Visualforce.remoting.manager.invokeAction(); calls. It might even happen if all that block is doing is calling some console.log("hello world"); statements. So, to work around this infuriatingly stupid bug, you have to use something like window.onready instead. Hope this helps anyone else who encounters a similar issue so that they don't end up spending 6 days pulling their hair out trying to figure it out like I did!

    Update: looks like someone has already explained why doing anything with window.onload in a Visualforce page is no bueno. You can read up on that here: https://salesforce.stackexchange.com/questions/184589/window-onload-function-disables-inline-edit-capabilities-on-custom-vf-page

    The skinny is that Salesforce already hooks window.onload to its own crap, which includes whatever function they have to collapse the navbar. If you hook it yourself in your VF page, that overwrites what they did, and so their crap never executes. The more you know...