Reports are blank in Safari and Chrome
Asked Answered
B

10

85

I migrated our reporting services from version 2008 to another server version 2008 R2. In version 2008 the reports work fine on Safari. The new version 2008 R2 the reports do not show up at all. All I see is the parameter section and then the report is blank. Same in Chrome. According to Microsoft Safari IS supported if in a limited fashion. The reports are not complex. In fact I created a report that only had a line on it to see if it would show up in Safari but no, that report is completely blank as well. Did anyone make SSRS reports viewable on Safari? Do I have to mess with some kind of a configuration setting?

Brittle answered 11/5, 2011 at 17:16 Comment(1)
duplicate: #5428517Equivalence
P
110

Ultimate solution (works in SSRS 2012 too!)

Append the following script to the following file (on the SSRS Server)
C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportManager\js\ReportingServices.js

function pageLoad() {    
    var element = document.getElementById("ctl31_ctl10");
    if (element) 
    {
        element.style.overflow = "visible"; 
    }
}

Note: As azzlak noted, the div's name isn't always ctl31_ctl10. For SQL 2012 tryctl32_ctl09 and for 2008 R2 try ctl31_ctl09. If this solution doesn't work, look at the HTML from your browser to see if the script has worked properly changing the overflow:auto property to overflow:visible.


Solution for ReportViewer control

Insert into .aspx page (or into a linked .css file, if available) this style line

#reportViewer_ctl09 {
  overflow:visible !important;
 }

Reason

Chrome and Safari render overflow:auto in different way respect to IE.

SSRS HTML is QuirksMode HTML and depends on IE 5.5 bugs. Non-IE browsers don't have the IE quirksmode and therefore render the HTML correctly

The HTML page produced by SSRS 2008 R2 reports contain a div which has overflow:auto style, and it turns report into an invisible report.

<div id="ctl31_ctl10" style="height:100%;width:100%;overflow:auto;position:relative;">

I can see reports on Chrome by manually changing overflow:auto to overflow:visible in the produced webpage using Chrome's Dev Tools (F12).


I love Tim's solution, it's easy and working.

But there is still a problem: any time the user change parameters (my reports use parameters!) AJAX refreshes the div, the overflow:auto tag is rewritten, and no script changes it.

This technote detail explains what is the problem:

This happens because in a page built with AJAX panels, only the AJAX panels change their state, without refreshing the whole page. Consequently, the OnLoad events you applied on the <body> tag are only fired once: the first time your page loads. After that, changing any of the AJAX panels will not trigger these events anymore.

User einarq suggested this solution:

Another option is to rename your function to pageLoad. Any functions with this name will be called automatically by asp.net ajax if it exists on the page, also after each partial update. If you do this you can also remove the onload attribute from the body tag

So wrote the improved script that is shown in the solution.

Payload answered 29/8, 2011 at 10:42 Comment(7)
I altered function page_load to pageLoad in order to trigger the script. Otherwise, it seems to solve rendering issues in Chrome 13. Unfortunately basic auth in SSRS does not seem to work with Safari 5.1, so I can't verify there.Collection
The reason is WRONG. The real reason is, SSRS HTML is QuirksMode HTML and depends on IE 5.5 bugs. Non-IE browsers don't have the IE quirksmode and therefore render the HTML correctly. For browsers that don't emulate IE 5.5 bugs in their QuirksMode, it lacks setting the table width... This also applies to IE 10 by the way, as it has a new default-quirksmode mode.Compromise
Works perfectly. But for SQL Server 2012, the offending div id is ctl32_ctl09.Kimikokimitri
Another reason I have found is that there is a non-nullable (required) parameter defined in the report but it is not supplied, as mentioned in project page (see Key points section)Fitzpatrick
This is a great solution - however in chrome the left hand div showing the report document map only extends down as far as the height of the report on the right hand side. In IE native functionality is that this div would fill the height of the screen - any thoughts how to achieve this?Bedeck
rather than searching for id ctl32_ctl09 or whatever is generated, try: document.querySelector("[id^=VisibleReportContent]").parentNode;Shanghai
@JustinMangum - the use of querySelector will fail in IE in Compatibility View, which is almost certainly enabled for intranet SSRS sites. The symptom is that the Loading dialog will never close, so users will be unable to view any report.Costly
T
27

Just include SizeToReportContent="true" as shown below

<rsweb:ReportViewer ID="ReportViewer1" runat="server" SizeToReportContent="True"...
Tomato answered 23/11, 2012 at 5:50 Comment(7)
I don't know why this is not the accepted solution as a) it works fine, and b) it seems to be the built in solution. Not a hack to make reportviewer work properly. Not that there is anything wrong with hacking ReportViewer to make it work. Seems like the whole reportviewer is on big hack.Lauzon
Doesn't this solution only apply to embedding the ReportViewer control in an application? If this applies to Report Manager and reports run from the ReportServer URL, then please specify where you would need to include this edit.Sexagesima
Are you referring to the following line in \SQL\MSRS11.MSSQLSERVER\Reporting Services\ReportServer\Pages\ReportViewer.aspx: <RS:ReportViewerHost ID="ReportViewerControl" runat="server"/>Sexagesima
It may work fine, but if you have a lot of images (indicators/Sparklines) on a report it will blow the rendering time out atrociously.Heligoland
This doesn't work when modifying ReportViewer.aspx in SSRS 2012.Bistoury
So simple, but works so well. This NEEDS to be the accepted answer.Revolutionist
This answer needs more explanation on how to apply it. Where do I put this code?Briquette
M
23

I am using Chrome version 21 with SQL 2008 R2 SP1 and none of the above fixes worked for me. Below is the code that did work, as with the other answers I added this bit of code to Append to "C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportManager\js\ReportingServices.js" (on the SSRS Server) :

//Fix to allow Chrome to display SSRS Reports
function pageLoad() { 
    var element = document.getElementById("ctl31_ctl09");
    if (element) 
    {
        element.style.overflow = "visible";         
    } 
}
Milagro answered 22/8, 2012 at 19:36 Comment(1)
This solution is working very well in our environment. Thanks MikeDorsal
E
14

This is a known issue. The problem is that a div tag has the style "overflow: auto" which apparently is not implemented well with WebKit which is used by Safari and Chrome (see Emanuele Greco's answer). I did not know how to take advantage of Emanuele's suggestion to use the RS:ReportViewerHost element, but I solved it using JavaScript.

Problem

enter image description here

Solution

Since "overflow: auto" is specified in the style attribute of the div element with id "ctl31_ctl10", we can't override it in a stylesheet file so I resorted to JavaScript. I appended the following code to "C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportManager\js\ReportingServices.js"

function FixSafari()
{    
    var element = document.getElementById("ctl31_ctl10");
    if (element) 
    {
        element.style.overflow = "visible";  //default overflow value
    }
}

// Code from https://mcmap.net/q/244093/-add-multiple-window-onload-events
if (window.addEventListener) // W3C standard
{
    window.addEventListener('load', FixSafari, false); // NB **not** 'onload'
} 
else if (window.attachEvent) // Microsoft
{
    window.attachEvent('onload', FixSafari);
}

Note

There appears to be a solution for SSRS 2005 that I have not tried but I don't think it is applicable to SSRS 2008 because I can't find the "DocMapAndReportFrame" class.

Equivalence answered 12/8, 2011 at 16:39 Comment(1)
There is one thing I do not understand. if you apply the code function FixSari in \ReportingServices.js, and then you execute the code to display the report in SSRS, where do you apply the function to execute the source method code for FixSafari? If I understand correctly, the original code for ReportingServices.js is generated and in the end you execute FixSafari code?Transsonic
S
12

My solution based on the ideas above.

function pageLoad() {
    var element = document.querySelector('table[id*=_fixedTable] > tbody > tr:last-child > td:last-child > div');
    if (element) {
        element.style.overflow = "visible";
    } 
}

It's not limited to a certain id plus you don't need to include any other library such as jQuery.

Syck answered 17/1, 2015 at 19:51 Comment(2)
But the elements everyone else is targeting, like ctl31_ctl10 and its variants, don't necessarily have _fixedTable in them. Am I missing something?Knowle
@Knowle - The above solution uses the Child Selector to find the correct div. It starts based on an item higher up the chain with a more static id attribute, then walks the children down the tree to the desired div. I would prefer it used a more descriptive, less overloaded name for the variable, but this is an otherwise excellent solution. Suggested name: reportPayloadElement.Prejudicial
B
11

Here is the solution I used for Report Server 2008 R2

It should work regardless of what the Report Server will output for use for in its "id" attribute of the table. I don't think you can always assume it will be "ctl31_fixedTable"

I used a mix of the suggestion above and some ways to dynamically load jquery libraries into a page from javascript file found here

On the server go to the directory: C:\Program Files\Microsoft SQL Server\MSRS10_50.MSSQLSERVER\Reporting Services\ReportManager\js

Copy the jquery library jquery-1.6.2.min.js into the directory

Create a backup copy of the file ReportingServices.js Edit the file. And append this to the bottom of it:

var jQueryScriptOutputted = false;
function initJQuery() {

    //if the jQuery object isn't available
    if (typeof(jQuery) == 'undefined') {


        if (! jQueryScriptOutputted) {
            //only output the script once..
            jQueryScriptOutputted = true;

            //output the script 
            document.write("<scr" + "ipt type=\"text/javascript\" src=\"../js/jquery-1.6.2.min.js\"></scr" + "ipt>");
         }
        setTimeout("initJQuery()", 50);
    } else {

        $(function() {     

        // Bug-fix on Chrome and Safari etc (webkit)
        if ($.browser.webkit) {

            // Start timer to make sure overflow is set to visible
             setInterval(function () {
                var div = $('table[id*=_fixedTable] > tbody > tr:last > td:last > div')

                div.css('overflow', 'visible');
            }, 1000);
        }

        });
    }        
}

initJQuery();
Basically answered 19/9, 2012 at 19:7 Comment(1)
One question though, if there is more than one report table on the page, won't this cause multiple loads of the controls? If so then the very first line could be changed to : var jQueryScriptOutputted = ((typeof(jQueryScriptOutputted) == 'undefined') ? false : true);Argentine
O
4

You can fix this easily with jQuery - and a little ugly hack :-)

I have a asp.net page with a ReportViewer user control.

 <rsweb:ReportViewer ID="ReportViewer1" runat="server"...

In the document ready event I then start a timer and look for the element which needs the overflow fix (as previous posts):

 <script type="text/javascript">
    $(function () {
        // Bug-fix on Chrome and Safari etc (webkit)
        if ($.browser.webkit) {
            // Start timer to make sure overflow is set to visible
             setInterval(function () {
                var div = $('#<%=ReportViewer1.ClientID %>_fixedTable > tbody > tr:last > td:last > div')
                div.css('overflow', 'visible');
            }, 1000);
        }
    });
</script>

Better than assuming it has a certain id. You can adjust the timer to whatever you like. I set it to 1000 ms here.

Opportunist answered 8/9, 2011 at 7:0 Comment(0)
P
3

FYI - none of the above worked for me in 2012 SP1...simple solution was to embed credentials in the shared data source and then tell Safari to trust the SSRS server site. Then it worked great! Took days chasing down supposed solutions like above only to find out integrated security won't work reliably on Safari - you have to mess with the keychain on the mac and then still wouldn't work reliably.

Prosciutto answered 11/3, 2014 at 23:21 Comment(0)
B
2

The solution provided by Emanuele worked for me. I could see the report when I accessed it directly from the server but when I used a ReportViewer control on my aspx page, I was unable to see the report. Upon inspecting the rendered HTML, I found a div by the id "ReportViewerGeneral_ctl09" (ReportViewerGeneral is the server id of the report viewer control) which had it's overflow property set to auto.

<div id="ReportViewerGeneral_ctl09" style="height: 100%; width: 100%; overflow: auto; position: relative; ">...</div>

I used the procedure explained by Emanuele to change this to visible as follows:

function pageLoad() {
    var element = document.getElementById("ReportViewerGeneral_ctl09");

    if (element) {
        element.style.overflow = "visible";
    }
}
Bewitch answered 3/10, 2012 at 6:55 Comment(0)
B
2

I've used this. Add a script reference to jquery on the Report.aspx page. Use the following to link up JQuery to the microsoft events. Used a little bit of Eric's suggestion for setting the overflow.

$(document).ready(function () {
    if (navigator.userAgent.toLowerCase().indexOf("webkit") >= 0) {        
        Sys.Application.add_init(function () {
            var prm = Sys.WebForms.PageRequestManager.getInstance();
            if (!prm.get_isInAsyncPostBack()) {
                prm.add_endRequest(function () {
                    var divs = $('table[id*=_fixedTable] > tbody > tr:last > td:last > div')
                    divs.each(function (idx, element) {
                        $(element).css('overflow', 'visible');
                    });
                });
            }
        });
    }
});
Bonney answered 8/4, 2013 at 14:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.