views:

1456

answers:

6

Currently I have this line of code in a datalist in a usercontrol:

<asp:Image ID="Image1" runat="server" imageurl='<%# "~/Thumbnail.ashx?image=" + Utilities.ToURLEncoding("~\\Files" + DataBinder.Eval(Container.DataItem, "file_path")) %>' />

As you can see, it calls Thumbnail.ashx, which generates a thumbnail image given the original image location and returns it to the asp:Image object. This part works fine. Now what I want to do is preload the original image in the background. I can't use Javascript because this isn't an <img> object, but rather an ASP one. How would I go about doing this?

A: 

Depending how your preloader works, you could still render the asp part --

<%# "~/Thumbnail.ashx?image=" + Utilities.ToURLEncoding("~\\Files" + DataBinder.Eval(Container.DataItem, "file_path")) %>

-- as a string value passed to a javascript function. it is really not very different from a regular img.

EDIT

To elaborate, continuing from post below; no, that was not quite what I meant, more something like this:

<script type="text/javascript" language="javascript">
function preloadImage(path)
{
    // preload image by adding a hidden image to the document
    var img = document.createElement('img');
    img.src = path;
    img.style.display = 'none';
    document.body.appendChild(img);
}

// invoke the above function
preloadImage('<%# "~/Thumbnail.ashx?image=" + OceanitData.ToURLEncoding("~\\Files" + DataBinder.Eval(Container.DataItem, "file_path")) + "&height=206" %>');
</script>

I don't quite know what you want from your script more than that. But if you've got an asp:image control, you could still access it as any other image:

<asp:Image id="img1" runat="server" />
<script type="text/javascript">
document.getElementById('<%=img1.ClientID%>').src = '<%# "~/Thumbnail.ashx?image=" + OceanitData.ToURLEncoding("~\\Files" + DataBinder.Eval(Container.DataItem, "file_path")) + "&height=206" %>';
</script>
David Hedlund
By the way, there's no way to post code in a comment, right?
Daniel T.
i'm only a few days old here, but no, it seems we can't even do line breaks in the comments. but we can edit one another's posts ;)
David Hedlund
A: 

You mean like this?

<script type="text/javascript" language="javascript">
    function preloadImage(image, path)
    {
        image.src = path;
    }
</script>

<asp:Image ID="Image1" runat="server" imageurl='<%# "~/Thumbnail.ashx?image="
+ OceanitData.ToURLEncoding("~\\Files" + DataBinder.Eval(Container.DataItem,
"file_path")) + "&height=206" %>' OnLoad='<%# "preloadImage(this," +
OceanitData.ToURLEncoding("~\\Files" + DataBinder.Eval(Container.DataItem,
"file_path")) %>' />

I tried it, but I don't think it's working. asp:Image doesn't have a src control.

Daniel T.
to be honest, i don't know what you're trying to achieve there. you have a function that sets the source of the image to what it already was? asp:image renders as an img-tag, so javascript can't tell it from other regular img tags. that means that once you process it with javascript, it definitely has an 'src' attribute. i doubt, however, that the asp:image control has a 'onload' attribute, so your javascript function is never actually called there. see my edit to my own answers for some working examples
David Hedlund
A: 

In your example you are confusing client-side code and server-side code.

Client side code is code that is being executed in the client browser and it comprises of such things as the scripting language (generally JavaScript), and HTML controls.

Server-side code is code that is executed on the server, and it comprises (in the case of ASP.NET) of server controls and a programming language either C# or VB (mind you, there are .Net methods that generate client-side code as well). Server controls are the controls that have the runat="server" attribute.

So in your example, if you are using the <asp:Image ...> control, that is a server side control, so it will be generated on the server, and then, because it needs to be displayed in the user's browser it will be rendered into an HTML control (<img> object). The server-side code cannot run the client side code.

To achieve preloading you have to load the image on the client-side in the <head> section of you HTML. You can do that in the aspx page if you add the runat="server" to the <head> tag. Something like this:

<head runat="server">
   <script type="text/javascript">
      var img1 = new Image();
      img1.src = '<%# "~/Thumbnail.ashx?image=" + Utilities.ToURLEncoding("~\\Files" + DataBinder.Eval(Container.DataItem, "file_path")) %>';
   </script>
</head>

Or you can generate that using the ScriptManager.RegisterClientScriptBlock method.

Use any of these in addition to using your <asp:Image> control. How it will go down on the client side is that the image will be loaded before the page is displayed, and when your asp:image controls will need to render it, it will already be available from the cache of the browser

Mircea Grelus
A: 

Sorry for the quick and dirty explanation in the beginning, let me elaborate some more. I have a user control (gallery.ascx) with a datalist in it, so it looks something like this:

<asp:DataList ID="DataList1" runat="server" OnItemDataBound="DataList1_ItemDataBound">
<ItemTemplate>
    <asp:HyperLink ID="HyperLink1" runat="server" Target="_blank">
    <asp:Image ID="Image1" runat="server"
    imageurl='<%# "~/Thumbnail.ashx?image=" + OceanitData.ToURLEncoding("~\\Files"
    + DataBinder.Eval(Container.DataItem, "file_path")) + "&height=206" %>'
    OnLoad='<%# "preloadImage (~\\Files" + Eval("file_path") + ")" %>' />
    </asp:HyperLink>
</ItemTemplate>
</asp:DataList>

Basically, there's a folder with a bunch of images in it. The DataList gets bound to the SQL table that has the paths to all the files in that particular folder. The imageurl for the <asp:Image> is set to run the custom handler Thumbnail.ashx, which generates a thumbnail and returns the response to <asp:Image> so that the client gets a thumbnail instead of the full image. However, what I want to do is also have the original image download in the background so when the user clicks on the thumbnail, the large image is already downloaded to the cache and displays instantly.

The problem I have is that I don't know the path to the files until the DataList is bound to the SQL table, so I have to run the Javascript function inside the DataList. However, based on the code I just provided above, this is the HTML output I get (simplified):

<a href="pic.jpg" target="_blank"><img OnLoad="preloadImage(pic.jpg)"
src="Thumbnail.ashx?image=pic.jpg&amp;height=206" /></a>

Internet Explorer tells me "Error on page." so it's not running preloadImage(). I hope this helps.

Oh, by the way, I changed the Javascript function to this:

<script type="text/javascript">
    function preloadImage(path)
    {
        loadImage = new Image();
        loadImage.src = path;
    }
</script>

This function is put into the main page (not my user control), under the <head runat="server"> tag.

Daniel T.
A: 

You can't run a Javascript function inside any server code. Javascript is client-side code and will only be executed on the client computer after you have generated the entire page.

The idea is simple. You just have to add all your images into the head section of the HTML. How can you do that? First create a generic Javascript function that which accepts a variable number of arguments and create an image for each one. Add that to you head tag:

<head id="myHeadTag" runat="server">
    <script type="text/javascript">
    function PreloadMyImages() 
    {
      var lenArg = arguments.length;
      if (lenArg > 0) 
      {
        var imgArr = new Array();
        for (var i = 0; i < lenArg; i++) 
        {
       imgArr[i] = new Image();
       imgArr[i].src = arguments[i];
        }
      }
    }
</script>
</head>

So this function needs to be called on the client side by something like:

PreloadMyImages('/Images/img1.gif',
    '/Images/img2.gif', '/Images/img3.gif');

So, you have to collect the URLs on the serverside when the DataList is bound and keep them in a variable. The DataList.ItemDataBound event fires when each item is added to the DataList. So in that event you can collect the URLs for your photo. Add them to an array or just concatenate the URLs in a string like: aStringVariable += "'" + url + "'" + ","; Then, when you've finished collecting all the URLs on the server-side remove you last "," and register the Javascript in the <head> tag to be run on the client machine when the pages is opened in the user's browser. You can do that by adding the following code in the PreRender event:

HtmlGenericControl x = new HtmlGenericControl("script");
 x.InnerText = "PreloadMyImages(" + aStringVariable  + ");";
 Page.Header.Controls.Add(x);

That will basically generate a script tag like that will call the PreloadMyImages Javascript function when the users is displayed the page.

Mircea Grelus
A: 

I finally figured out the solution! ...And I'm banging my head on the table for it. It turns out all I needed to do was change this:

<asp:Image runat="server" imageurl='<%# "~/Thumbnail.ashx?image=" +
OceanitData.ToURLEncoding("~\\Files" + DataBinder.Eval(Container.DataItem,
"file_path")) + "&height=206" %>' onload='<%# "preloadImage(" +
OceanitData.ToURLEncoding("~\\Files" + Eval("file_path")) + ")"%>' />

to this:

<asp:Image runat="server" imageurl='<%# "~/Thumbnail.ashx?image=" +
OceanitData.ToURLEncoding("~\\Files" + DataBinder.Eval(Container.DataItem,
"file_path")) + "&height=206" %>' onload='<%# "preloadImage(" +
OceanitData.ToURLEncoding("\"~\\Files" + Eval("file_path")) + "\")"%>' />

All that needed to be done was add quotes around the string passed to preloadImage(). This changes the HTML source from this:

<img onload="preloadImage(image.jpg)" src="Thumbnail.ashx?image=image.jpg&amp;height=206" />

to this:

<img onload="preloadImage(&quot;image.jpg&quot;)" src="Thumbnail.ashx?image=image.jpg&amp;height=206" />

Which means the Javascript function is being called as preloadImage("image.jpg") instead of preloadImage(image.jpg). That was it! bangs head on table some more

Daniel T.
I can see why that would work, but it is not good practice. You've basically added an invalid attribute ("onload") to your server control which is ignored because it is unknown, and it apparently is rendered in the HTML <img> tag. The HTML <img> tag has an "onload" attribute and that's why it works. The ASP control <asp:Image> has an "onLoad" (notice capital L) attribute which refers to a server-side function.
Mircea Grelus
So I should convert my `<asp:Image>` tag to `<img>` then? I don't need any of the special methods that `<asp:Image>` provides.
Daniel T.