Reporting Services javascript injection
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.