My previous post about using a simple javascript in Reporting Services 2008 got me thinking. Wouldn’t it be cool if you could do more with javascript in Reporting Services?! This would enable a lot of extra functionality in the webpage. It would be possible to change the innerHTML of div tags for instance. One thing that popped into my head was the use of advanced tooltips. It would be a cool feature if certain links could have nice looking tooltips.
But let’s face it: typing javascript in the Reporting Services expression window isn’t really that “developer friendly”. So it would be a lot easier if it was possible to use an external file where you could put your javascript. I started experimenting with injecting the javascript after the report was already loaded by using a link. And it actually worked! I have created a proof of concept that can inject javascript into a report.
The following code has to be added to a link in Reporting Services. But before we stuff it into an expression lets look at the code first.
eval
(
unescape
(‘
function addScript(scriptFile)
{
var head = document.getElementsByTagName(‘head’)[0];
var script = document.createElement(‘script’);
script.setAttribute(‘type’, ‘text/javascript’);
script.setAttribute(‘src’, scriptFile);
head.appendChild(script);
}
addScript(‘http://[SERVER_ADDRESS]/ReportsLibrary/script.js’);
‘)
)
It is really only one statement. Let’s work from the inside to the outside and focus on the function addScript first. This function takes the location of the script file as an argument. So the full path to the script file has to be used here. It looks for the head tag and adds a script tag to it with the appropriate attributes type and src. The src attribute gets the location of the provided scriptFile. After the function is declared it is called with the parameter http://[SERVER_ADDRESS]/ReportsLibrary/tooltip.js (Replace [SERVER_ADDRESS] by the address of the server the js script is on. You can replace it with localhost, but then it will only work on the server itself). This will cause the following script tag to be added to the head tag of the page.
<script type=“text/javascript” src=“http://localhost/ReportsLibrary/script.js”></script>
This function is passed as a string to the unescape function. This is necessary because Reporting Services URL encodes the strings that are passed. To convert this back to a regular string unescape is put to work. We now have a string that actually contains javascript code. To execute this code the eval function is used. This function can, obviously, execute a string as javascript code.
As you might have concluded in this case I am running Reporting Services in SharePoint integrated mode. And will upload the script.js file to my report library later.
Lets create the Reporting Services report first. I want to create a report with two links: one to enable the injection and another one to test that the injection has succeeded. This test will be a textbox (SPAN) changing its innerHTML. Therefore another textbox is created. So first create a href injection link with the following Value expression. (See my previous post for more details on how to do this)
=”<a href=””j avascript:eval
(
unescape
(‘
function addScript(scriptFile)
{
var head = document.getElementsByTagName(‘head’)[0];
var script = document.createElement(‘script’);
script.setAttribute(‘type’, ‘text/javascript’);
script.setAttribute(‘src’, scriptFile);
head.appendChild(script);
}
addScript(‘http://[SERVER_ADDRESS]/ReportsLibrary/script.js’);
‘)
)
“”>inject</a>”
Remove the space after the j of javascript. I incorporated this because otherwise it gets blocked by the blog engine
Make sure that there is no space after the colon from javascript. If you want to be sure that it works it best to remove all the newline and space characters.
Create another href link with the following Value expression
=”<a href=””j avascript:test()””>test</a>”
Remove the space after the j of javascript. I incorporated this because otherwise it gets blocked by the blog engine
(When adding the links do not forget to check the HTML radio button in the Placeholder properties!)
The test link will execute the function test() which we will create later.
As a last step create a textbox and add the text following text to it
=”<span>CHANGEME</span>”
The report should look something like this.
Deploy the report so we can use it later.
Next we will create the script.js file. So create a blank file and add the following code to it.
function test()
{
alert(“The CHANGEME textbox will actually change…”);
var doc = window.frames[1][1].document;
var el = doc.getElementsByTagName(‘span’);
for (var nr=0; nr<el.length; nr++)
{
if (el[nr].innerHTML == “CHANGEME”)
el[nr].innerHTML = “I FEEL LIKE A CHANGED TEXTBOX”;
}
}
Before we look at the code in more detail I first want to talk about how the Reporting Services report is displayed in the browser. It is not just one webpage we are looking at. But it are really a couple of pages encapsulated in iframes. The actual report is ‘hidden’ in frames[1][1]. This means that it is a iframe within an iframe.
The function test will loop through all the span elements in the report (frames[1][1]). If it finds the CHANGEME textbox/span it will change its innerHTML.
Upload the js file to the ReportsLibrary or the place that you have specified in the addScript call.
Now it is time to test! Open the report in the browser and click the inject link. It seems like nothing happened, but in reality we have injected our javascript into the report ready for use. Next click the test link. This executes the test function which is located in our external script.js file. If all went well an alert should appear and after clicking OK the text in the textbox CHANGEME should have been changed.
This was just a proof of concept on how to inject javascript into your Reporting Services report. It enables you to change behaviour of the report without modifying the report itself. And you can put the javascript in a seperate file which is a lot more clear than editing it in the expression windows of Reporting Services. It should be possible te create more advanced tooltips or other cool features this way. If anybody is up for it: you can find a cool lightweight tooltip script over here. Would be nice to see that in Reporting Services…
I have included the injection.rdl and scrip.js in the inject.zip file with this post.
17 comments
Thanks for the post. I am trying to find ways to inject some JS so that I can add a menu type effect when a person clicks on a cell. The frames are throwing me off in my own tinkering.
I downloaded your sample and tried to use it. I get the message box that indicates it is going to change the text, but then i get an object missing error on the window.frames[1][1].document. Could this vary based on how RS is deployed? I am in standalone mode.
Thanks,
Brian
Brian
Hi Brian,
My RS is also in standalone mode. So that should not be the problem.
Can you post the exact error message?
– Bas
bast
Bas,
Thank you for your reply. I am getting the following error:
“window.frames.1.1.document is null or not an object”
Thanks for your help!
Brian
Brian
Bas,
I should have tried this before I posted again. I changed the array to be [0][1] and it worked. Sorry for the bother and thanks again for your post. Not sure why the layout is different between my machine and yours.
Here is the line I changed:
var doc = window.frames[0][1].document;
Brian
Brian
Hi Brian,
Good to hear that you solved it! Just like you I have no direct answer to why your frame layout is different from mine. This will require extra investigation.
If the frame layout can be different per machine it would require some measures to locate the correct frame dynamically.
– Bas
bast
Hi, Bas !
Unfortunately there are no any frame in rendered report.
I added this line in script.js file
alert(window.frames.length);
and I received a 0 value.
Could you suggest something ?
Alex
Hi Alex,
Are you running Reporting Services 2008 in integrated or native mode? The example I have posted is native mode.
If you are running in native mode and you have the 2008 version, it seems that the display is different per installation type.
– Bas
bast
anyone can you send any code for add pop up menu to reporting service in visual studio 2008
Chinthaka
hi,nice post!! do we have to deploy before testing it…cant”t we test it on the visual studio preview option????need some help 🙂
charix
cant we try testing on the preview without deploying???
charix
Hi,
Great post! I was lossing my hope…. I have tried that but one drawback for me was that I had to press a button to make it work (and https didn’t like it). In my case fortunatenelly I was able to use this code with asp.net page and reportviewer control and implement proper javascript tooltip! (Finally!!) I generate HTML code using SQL and put into ‘tooltip’ property on report using the extra generated field; which is assigned to title attribute in HTML so I just loop throught all elements in reports viewer (area, td) and add onmouseover/out which fires javascript and value is taken from title attribute.
The file might get big but I presume AJAX might help with it.
Many thanks for that. Finally I have that working!!
Regards
Emil
Emil
Charix, sorry for my late response.
If I am not mistaken the render engine of the preview and of the final result differs. This means that it is advisable to develop it so it renders in IE. To tell you the truth I have not even tried it in the preview mode.
– Bas
bast
Thanks Emil!
I am pleased to hear that my post was of help. It would be great if you could share your code with us.
– Bas
bast
Hi Bas
Here is the early stage script (ReportViewer2010)
<script type=”text/javascript”>
function Test(doc) {
var el = doc.getElementsByTagName(‘AREA’);
var len = el.length;
for (j = 0; j < len; j++) {
var ToolTipText = “<table><tr><td>Milestone: </td><td>”+el[j].getAttribute(“TITLE”)+”</td></tr></table>”;
el[j]onmouseover = function () { tooltip.show(this.value,200); };
el[j].onmouseout = function () { tooltip.hide() };
el[j].setAttribute(“value”, ToolTipText);
}
}
</script>
Regards
Emil
Emil
Thanks Emil! I hope this can help others…
I had to change your variable i in the for loop to j. Because if you use [ i] in the comments, the blog engine replaces it with [i]. I don’t know how to get around this problem other then renaming or using spaces.
bast
how do you inject javascript into a SSRS 2005 report
Ben
It is in reality a nice and helpful piece of info. I?m satisfied that you simply shared this useful info with us. Please stay us up to date like this. Thank you for sharing.
WoW Adult