|
I had this issue as well and after a few hours of pounding my head I found a solution.
The problem exists in the GetNetImageUrl function
Specifically the following line:
return files[n].Replace(AppDomain.CurrentDomain.BaseDirectory, string.Empty);
You see files contains a complete path to the files in your image directory. This listing is using windows pathing. Ex: C:\whatever\images\whatever.jpg
We are finding everything up to the images directory with this line and removing it from the string leaving images\whatever.jpg and passing it to the browser. Now anyone that is paying attention here will notice that \ isn't a valid directory signifier on the web. / is! IE is happily translating your mistake for you Firefox isn't that forgiving nor is any other browser I'm aware of...
Change it to:
return "images/" + files[n].Replace(AppDomain.CurrentDomain.BaseDirectory + "images\\", string.Empty);
that will return a proper image path and allow firefox to find the images so they can load. However, you still have to disable the transitions for firefox to cooperate.
So to make this work with Firefox you need to:
C# Changes:
1.) Look in GetNextImageUrl() and change
return files[n].Replace(AppDomain.CurrentDomain.BaseDirectory, string.Empty);
to
return "images/" + files[n].Replace(AppDomain.CurrentDomain.BaseDirectory + "images\\", string.Empty);
2.) Look in GetCallBackResult() and change
return GetNextImageUrl() +";" + GetNextTransition();
to
return GetNextImageUrl();
JavaScript Changes:
1.) Replace ReveiveServerData(rValue) with this new function
function ReceiveServerData(rValue)
{
var img = new Image();
img.onload = function(){ imageLoaded(this); }
img.onerror = function(){ imageError(this); }
img.onabort = function(){ imageError(this); }
img.src = rValue;
}
2.) Look in imageLoaded and comment out or remove the two lines that deal with filters.
After that it runs a simple slide show on both browsers for me! The transitions are nice but I needed something more universal.
I hope this helps someone not lose any more hair. Many thanks to Lang Deng for the original!
|
|
|
|
|
It run well on both browser but not support any effect. Can u fix this?
QuynhTD
|
|
|
|
|
Sadly not to my knowledge. The effects are performed by direct x filters that only work in IE. I was going to try to make some animated gif files that I could put over the picture but the effect wasn't nearly as nice. The only thing I can think of would be to build this in Flash but I'm no flash guy.
|
|
|
|
|
I can not seem to get it to work when the files located inside a directory rather than in the root of my web directory. It looks for the images folder in the web root directory for some reason. if i modify the "images" line and add my directory like "/slideshow/images" then it finds the file names but the path has two "/slideshow" in it so the image still doesn't show up.
www.seedandgarden.com
|
|
|
|
|
Thank you for your interest in my article. Actually the image files can be in anywhere under the root or a virtual directory of your web site, as long as they can be read by browsers, i.e. http://your_web_url/your_virtual_dir/your_image.jpg. What you need to do is to return these image URLs in the function GetNextImageUrl(). In my examples, it search files in the folder “images” under the directory of the application or the directory you deploy your web page.
string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + "images", "*.jpg");
Then it makes up the URL for one of these files randomly.
files[n].Replace(AppDomain.CurrentDomain.BaseDirectory, string.Empty
The returned string of the function GetNextImageUrl() will look like “images\your_image.jpg”. This is a relative path to your virtual directory of your Slideshow page. You don’t need to put any strings, such as http:// in front of it, since the client’s browsers will automatically make up the absolute URL to load your image, i.e. http://your_web_site/your_slideshow_directory/images/your_image.jpg. Of course you can return an absolute URL in GetNextImageUrl(). So the image file can be anywhere in your web site. A relative path can be only under your application (or Slideshow) virtual directory.
One thing you need to know is running a website project in VS2005 is a bit different from the deployment. In a project, it always uses the root directory with a port other than 80. In the web site deployment, you need to create a web folder or virtual directory, i.e. “Slideshow”. Then you can just copy your project into that folder. So users can access to your web with the URL as http://your_web_site/Slideshow/default.aspx.
Hope these help you understand my example.
|
|
|
|
|
Hi there first of all thanks a lot for sharing your code, its' just great!!
I had the same issue as the first user: I think this is the scenario he was in, as it was the same I am in too.
The slideshow.aspx is in a folder ie. www.mysite.com/myfolder/slideshow.aspx
the images are into a subfolder ie. ie. www.mysite.com/myfolder/img
What happens with your code is if I add "myfolder/img" to GetNextImageUrl() the result will be that the code will be looking images into: www.mysite.com/myfolder/myfolder/img
The point is if I don't add "myfolder", the code will look for images into www.mysite.com/img which does not exist
I guess this is because AppDomain.CurrentDomain.BaseDirectory in some way will look at www.mysite.com and not at www.mysite.com/myfolder.
I haven't been able to figure out how to fix this scenario other than moving slideshow.aspx up to the root. Any idea on other ways to fix it??
Thanks!!
Antonio
|
|
|
|
|
Great job Lang. Clean and very easy to integrate.
I did have the same problem moving the files into a sub folder (SlideShow). I fixed it by making these small changes in GetNextImageUrl();
private string GetNextImageUrl()
{
//Randomly pick a image file in the server.
string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + "SlideShow/images", "*.jpg");
=========
if (files.Length == 0)
return string.Empty;
while (true)
{
int n = (int)((files.Length - 1) * (new Random()).NextDouble());
//Do not want to repeat the last image
if (files[n].IndexOf(m_lastFileName) < 0)
{
return files[n]; //.Replace
==
(AppDomain.CurrentDomain.BaseDirectory, string.Empty);
}
}
}
Dan Satria
Principal Consultant
Graha Logica, Inc.
|
|
|
|
|
where to call this function?? i mean which part of the code actually invoke this function
|
|
|
|
|
Hi,
If you look at the HTML source view of the Default.aspx, you will see a javascript timer that fires every 5 seconds.
window.setTimeout("getNextImage()", c_interval);
The timer event will call the function getNextImage().
function getNextImage()
{
CallServer(document.getElementById("photo").src, "");
}
The function getNextImage() will call another function CallServer(...). The CallServer() then sends a request to server with an an argument of last image's url. When the web server receives the request, it will call the method RaiseCallbackEvent(...) and then GetCallbackResult() in Default.aspx.cs in the server . And the method GetCallbackResult() then calls GetNextImageUrl(). When GetCallbackResult() is done, it returns a string back to the client browser and calls the function ReceiveServerData(...). These all happen in the background and the browser will nerver refresh itself. Actually the function GetNextImageUrl() is just a helper. The important thing is the returned string of the function GetCallbackResult(). The string is something like "http://www.myserver.com/myimage.jpg;blendTrans(duration=2)". The first part is the next image url and the second part is the transition effect command separated by a semicolumn ';'. This is what the javascript running in client browsers expects to receive. You can design your own returned string and modify the javascript to parse the string.
Note you do not see the implementation of CallServer() in the project source. But you can see it in the browser by selecting the "View Source" menu item. It is taken care of by the ASP.NET framework 2.0 in run time.
Hope this will help.
Lang Deng
|
|
|
|
|
Thx a lot this really help. i think i am too blur. i only look at the VB file. didnt know need the C sharp too. anyway i run into another problem. sigh
my project is store at this network drive Z:/ under another folder(projects). Eg: Z:/Projects/Slide.aspx and the image folder is store at Z:/. when i use the
string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + "image", "*.jpg");
it will show that the file they load is Z:/Projects/image. but the image folder is actually @ Z:/ . is there anyway to troubleshoot this error?
Thanks a lot
|
|
|
|
|
This is the problem confuses most of the people. In the WWW world, it doesn't use drive such as C: or D:. It always uses "http://www.servername.com/...". So you cannot pass a string contains physical path in your computer. It should be a virtual directory or an url, which can be accessed from other computers on the internet or intranet using http protocol. So the image file you set here should be on a virtual directory created in your web server. But if you run the source code in VS2005, there is no other virtual directory created in the build-in web serevr. The only virtual directory is the project's root directory, or in your case, the Z:\Projects. And any files under this virtual directory can be accessed from other computers on the network. But it has to be expressed as an url. For example, the url for an image file Z:\Projects\image1.jpg is "http://hostname:port/image1.jpg", but you better use the relative url, image1.jpg, if you don't know your hostname or port. And the url for an file Z:\Prijects\Album\photo1.jpg should be "Album/photo1.jpg", and so on. If you publish your project to you real web server, you still can use the relative urls. And you can also use the full urls like "http://www.abc.com/myalbum/hello.jpg", just the way you look at the images on the internet with your browser.
Hope this can help.
Lang Deng
|
|
|
|
|
thx! you are really my saviour. However, can i be a irritating jerk because i got a few more questions to ask u.
First question
Is it possible to actually display the picture in proper arrangement. as in the picture being display are not random but is from A.jpg, b.JPG, c.JPG ... to Z.jpg.
Second question
Is it possible to stop the timer so that i can actually scroll the pictures manually by clicking button And start the timer when i want it to be autoscroll by clicking the button autoscroll
Thanks a lot and sorry to trouble you.
|
|
|
|
|
You are welcome to ask questions. I am happy to help people as long as I have time.
Your two questions are sure to be able to resolve. The first one is easy to change. Please look at the function GetNextImageUrl()
private string GetNextImageUrl()
{
//Randomly pick a image file in the server.
string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + "images", "*.jpg");
if (files.Length == 0)
return string.Empty;
while (true)
{
int n = (int)((files.Length - 1) * (new Random()).NextDouble());
//Do not want to repeat the last image
if (files[n].IndexOf(m_lastFileName) < 0)
{
return files[n].Replace(AppDomain.CurrentDomain.BaseDirectory, string.Empty);
}
}
}
It assumes your image files are stored in the folder “images” under your project’s base directory. That folder can be changed as long as it is one of the virtual directory of your web server. It searches all JPG files in that folder and then randomly picks one and return its relative URL. If you want to display the images sequentially, you can use a session varible to save the index of the file in the folder, i.e. Session[“index”]. Then every time the GetNextImage() is called, you increase the index by 1. So you can design your display order patterns by modifying the function GetNextImageUrl().
As for your second question, it is not difficult but need to put more juice in the page. I can only show you how. You need a button to toggle the slide show’s play and pause. In the page’s HTML view, you need to implement the button’s onclick() event function in javascript. So in the function, if you want to stop the timer, you need to call
window.clearTimeout(timerId);
If you want to enable the timer to continue to play the show, you need to call
timeId = window.setTimeout(5000);
I think these are the things you need to implement it. Enjoy!
Lang Deng
|
|
|
|
|
>.< oh dear it seems that the timer cant work.
*removed => onclick
var c_interval = 5000;
window.setTimeout("getNextImage()", c_interval);
function startTime(){
timerId = window.setTimeout("getNextImage()",5000);}
function getNextImage(){
CallServer(document.getElementById("photo").src, "");}
function ReceiveServerData(rValue){
var wds = rValue.split(";");
document.getElementById("photo").style.filter = wds[1];
var img = new Image();
img.onload = function(){ imageLoaded(this); }
img.onerror = function(){ imageError(this); }
img.onabort = function(){ imageError(this); }
img.src = wds[0];}
function imageError(img){
window.setTimeout("getNextImage()", 1000);}
function StopTime()
{window.clearTimeout(timerId); }
function imageLoaded(img)
{var photo = document.getElementById("photo");
photo.filters[0].apply();
photo.filters[0].play();
photo.src = img.src;
window.setTimeout("getNextImage()", c_interval);}
Why the timer cant work. is it because there is no timerId being declare?
hmmm as for the displaying the file in sequential order thing, do i simply add an array or ? i am realy still lost about that. sorry.
i try to modify my code until like that
private string GetNextImageUrl()
{
//Randomly pick a image file in the server.
string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + "MOTStaffPhotos", "*.jpg");
if (files.Length == 0)
return string.Empty;
while (true)
{
for (int i = files.Length-1; i < files.Length; i--)
{
int n = (int)((files.Length-1)-i);
if (files[n].IndexOf(m_lastFileName) < 0)
{
return files[n].Replace(AppDomain.CurrentDomain.BaseDirectory, string.Empty);
}
}
}
}
only 2 images are diaplayed.one after another. what happened?
-- modified at 22:46 Wednesday 11th October, 2006
|
|
|
|
|
Yes, you need to declare a variable to store timer id, just like the variable c_interval.
var c_interval = 5000;
var timerId;
Are you sure your buttons have "removed" event? I think they should be "onclick".
You should not return a string array in GetNextImageUrl(). The code should look as following,
private string GetNextImageUrl()
{
string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + "MOTStaffPhotos", "*.jpg");
if (files.Length == 0)
return string.Empty;
if(Session["index"] == null)
Session["index"] = -1;
int index = (int)Session["index"] + 1;
if(index >= files.length)
index = 0;
Session["index"] = index;
return files[index].Replace(AppDomain.CurrentDomain.BaseDirectory, string.Empty);
}
The Session["index"] is like a global variable stored in your web server. So when the next time GetNextImageUrl() is called, it is used to move to the next image file.
Hope this help.
Lang Deng
|
|
|
|
|
hmmm what can i say. it work and i really owe u a lot. just that i wondered y the timer cant work.
function StopTime()
{
window.clearTimeout(timerId);
}
declare timerId and i set the button to trigger this function onclick. just wonder y it cantwork.
i decided to decrease the session index when i click previous button and increase the session index when i click next button. do i simply just
Session["index"] = Session["index"] +1;
and throw this into a function?
thanks a lot.
|
|
|
|
|
I think the reason that clearTimeout() doesn't work may comes from other functions call setTimeout() after clearTimeout() is called, i.e. the imageLoaded() and imageError() also call setTimeout(). So you may also use another variable for the states of play and pause. If it is in pause state, do not call setTimeout() in functions imageLoaded() and imageError().
Yes, you can use your ways to control the Session["index"]. But remember the Session[] variables can only be accessed in server code, which is the code in Default.aspx.cs. They cannot be accessed from the javascript running in browsers. And the button's event is also fired in different places, too.
|
|
|
|
|
oh dear. guess i cant do the scrolling of the images le. nvm thx a lot. you have been a great help. i appreciate your nice gesture.
|
|
|
|
|
hmm i manage to fix the timer problem. now i was wondering how to manually navigate the image. i manage to scroll to the next image manually. but i have problem with scrolling to previous image. is it just change the logic?
private string GetPrevImageUrl()
{
string[] files = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory + "MOTStaffPhotos", "*.jpg");
if (files.Length == 0)
return string.Empty;
if (Session["index"] == null)
Session["index"] = files.Length;
int index = (int)Session["index"] - 1;
if (index < 0)
index = files.Length-1;
Session["index"] = index;
return files[index].Replace(AppDomain.CurrentDomain.BaseDirectory, string.Empty);
}
However, how can i make sure that this method is being invoke when i press the previous button. oh dear. because the getNextimageurl is invoke in the pageload method.
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
return;
photo.Src = GetNextImageUrl(); <--------
//Register Ajax client script to client's browsers. This has to be hard coded.
string cbReference = Page.ClientScript.GetCallbackEventReference(this, "arg", "ReceiveServerData", "context");
string callbackScript = "function CallServer(arg, context)" + "{ " + cbReference + "} ;";
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "CallServer", callbackScript, true);
}
|
|
|
|
|
I have this exact same problem and, although the path to the images can be corrected, this does not seem to work when the .aspx is not the root folder, for some reason. Any idea how to fix this?
|
|
|
|
|
Ok, I fixed this myself. I did this:
- For clarity purpose, I replaced the line that gives the path to files by this; this gives a clear way of referencing where your images are from the root of your site: string[] files = Directory.GetFiles(Server.MapPath("~/my full path/my image folder"), "*.jpg");
- And I replaced the line that truncates the file name to make it relative to the current URL by this; this makes it work no matter where your .aspx is and is a lot clearer too: return files[n].Replace(Request.Url.AbsolutePath, string.Empty);
Now the only thing I can't get to work is running this in Firefox or Opera; both seem to get stuck before even displaying the first image, even when I use this to remove the transition effects:
if(navigator.appName == "Microsoft Internet Explorer")
{
photo.filters[0].apply(); //Apply the transition effect
photo.filters[0].play(); //Play the effect and display the new image
}
Any idea anybody!?
|
|
|
|
|
Seems like my second change does not quite work . It should be replaced by either:
- return files[n].Replace(new FileInfo(Request.PhysicalPath).DirectoryName + "/", string.Empty);, which is a valid correction of the initial intent
- or return files[n].Replace(Server.MapPath("~/path to the .aspx/"), string.Empty);, which is dependent on the path of the current url but is maybe easier to handle.
Sorry about that confusion...
|
|
|
|
|
The problem is that the "SlideShow" virtual directory isn't an application. You can either edit the GetNextImageUrl function, or make SlideShow an application in IIS.
- Jerome
|
|
|
|
|
1. slow to load, in general
2. before the image loads the image description shows up and then as the image loads this is pushed to the bottom of the page : this creates an effect of an animation which is disturbing.
3. some of the first pictures : if you mouse-click on them you move ahead to another picture, but this is not true of later pictures.
best, Bill Woodruff
"The greater the social and cultural distances between people, the more magical the light that can spring from their contact." Milan Kundera in Testaments Trahis
|
|
|
|
|
Thanks for the comments. At this stage I put my focus mainly on the functionality of the AJAX and transition effects. I will work on the performance later on, especially to test the web site on slow link speed clients.
The purpose of pushing pictures to the bottom is to let people have a chance to click on them and look at the details if they are interested in a picture.
If a client does not have the Windows Media Player 7 installed, the server will direct it to another slide-show page (slideshow2.aspx), which may show you a different picture's details if you click on it.
Best regards,
Lang Deng
|
|
|
|