I have a pure html+JavaScript slideshow I am making. The slideshow is in a sidebar of the website that is loaded with php for each page that has the slideshow sidebar. The only page without the sidebar is the main page.
The slide show is working fine. However, understandably, each time I go to a new page with the sidebar, the slideshow starts over. Makes sense since the javascript reloads with each new page.
I would like to find some way to have the slideshow remember its place so that when I go to a new page the slide show just continues where it left off on the previous page. I can only think of two solutions, one seem brute force, and one I don't know how to do:
Write the current image number to a file and read it each time the
slideshow loads.
Somehow use ajax, but I haven't learned to use ajax
yet (would it work?).
Any suggestions? Oh, and please I'm learning javascript, jQuery and ajax are next, but...
Here is my code:
simpleslideshow.html:
<html>
initializeSlideShow();
<table width="100">
<tr>
<td align="left"> <div id="previous"> Previous</div></td>
<td align="right"> <div id="next">Next</div></td>
<td align="right"> <div id="auto">auto</div></td>
<td align="right"> <div id="stop">stop</div></td>
</tr>
</table>
<img src="" id="slideshow-image" width="400px" height="auto" style="display:block;"/>
simpleslideshow.js:
var inaterval_ID = 0;
var image_number = 0;
var num_images = images_with_captions.length;
function change_image(increment){
image_number = image_number + increment;
image_number = (image_number + num_images) % num_images;
var string = images_with_captions[image_number].source;
document.getElementById("slideshow-image").src = string;
}
function initializeSlideShow() {
//var string = images_with_captions[0].source;
//document.getElementById("slideshow-image").src = string;
auto();
}
function auto() {
interval_ID = setInterval("change_image(1)", 1000);
}
function stop() {
clearInterval(interval_ID);
}
image_caption_list.js:
var images_with_captions = new Array(
{
source: "http://www.picgifs.com/clip-art/flowers-and-plants/flowers/clip-art-flowers-435833.jpg",
caption: "flower 1"
},
{
source: "http://www.picgifs.com/clip-art/flowers-and-plants/flowers/clip-art-flowers-511058.jpg",
caption: "flower 2"
},
{
source: "http://www.picgifs.com/clip-art/flowers-and-plants/flowers/clip-art-flowers-380016.jpg",
caption: "flower 3"
}
);
Edit: I can't get a jsfiddle to work. But here is a live version that may or may not be up for a while:
You can save the current slide value to either a cookie or localStorage each time you change to a new slide and then when you start up the slideshow on a new page, you can read the previous slide value and start from that slide number.
Here's reading the previous slide number:
function initializeSlideShow() {
// get prior slideshow num
var lastSlideNum = +readCookie("lastSlideNum");
// if there was a prior slideshow num, set that as the last one we used
if (lastSlideNum) {
image_number = lastSlideNum;
}
auto();
}
Here's saving the slideshow number each time it changes:
function change_image(increment){
image_number = (image_number + increment) % num_images;
// remember what slide we're on for subsequent page loads
createCookie("lastSlideNum", image_number);
var string = images_with_captions[image_number].source;
document.getElementById("slideshow-image").src = string;
}
And, here's a simple cookie library:
// createCookie()
// name and value are strings
// days is the number of days until cookie expiration
// path is optional and should start with a leading "/"
// and can limit which pages on your site can
// read the cookie.
// By default, all pages on the site can read
// the cookie if path is not specified
function createCookie(name, value, days, path) {
var date, expires = "";
path = path || "/";
if (days) {
date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
expires = "; expires=" + date.toGMTString();
}
document.cookie = name + "=" + value + expires + "; path=" + path;
}
function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
function eraseCookie(name) {
createCookie(name, "", -1);
}
A localStorage implementation (which would not remember the slide in IE versions before IE8) would look like this:
function initializeSlideShow() {
// get prior slideshow num
var lastSlideNum;
// localStorage requires IE8 or newer
// if no localStorage, then we just don't remember the previous slide number
if (window.localStorage) {
lastSlideNum = +localStorage["lastSlideNum"];
// if there was a prior slideshow num, set that as the last one we used
if (lastSlideNum) {
image_number = lastSlideNum;
}
auto();
}
Here's saving the slideshow number each time it changes:
function change_image(increment){
image_number = (image_number + increment) % num_images;
// remember what slide we're on for subsequent page loads
if (window.localStorage) {
localStorage["lastSlideNum"] = image_number;
}
var string = images_with_captions[image_number].source;
document.getElementById("slideshow-image").src = string;
}
Related
I've been trying to display a different logo on my website depending on the date (to add a christmas logo that will automatically be displayed in december).
Here's what I've got for now:
<img class="logo" id="global_logo" style="height:56%; margin-top:12px;" src="">
<script>
function initLogo(){
var GlobalDate = date.getMonth()+1;
var GlobalLogo = document.getElementById("global_logo");
if (GlobalDate == 12) {
GlobalLogo.src = "xmas_mgmods-animated.gif"
}else{
GlobalLogo.src = "logo1.png"
}
/**/
alert('Script working');
}
initLogo();
</script>
I've got two problems: first, the logo is not showing up at all (no logo is)
Second: I want to know if I can set the script to also change the style applied for each logo (the style="height:56%; margin-top:12px;"is only needed for the gif, and not for the png).
I've tried to add a line instead of changing the source depending of the ID:
function initLogo(){
var GlobalDate = date.getMonth()+1;
var content = document.getElementById("global_logo");
var GlobalIcon = "";
if (GlobalDate == 12) {
html += "<img class='logo' src='logo1.png'>";
}else{
html += "<img class='logo' style='height:56%; margin-top:12px;' src='xmas_mgmods-animated.gif'>";
}
content.innerHTML += GlobalIcon;
alert('Script working');
}
It doesn't work...
You were using date without having it defined anywhere, assuming you copied it from somewhere else; it was supposed to be an instance of Date.
function initLogo(){
const date = new Date();
var GlobalDate = date.getMonth()+1;
var GlobalLogo = document.getElementById("global_logo");
if(GlobalDate == 12) {
GlobalLogo.innerHTML = `<img class="logo" src="xmas_mgmods-animated.gif" style="height:56%; margin-top:12px;">`;
}
else {
GlobalLogo.innerHTML = `<img class="logo" src="logo1.png">`;
}
}
initLogo();
<div id="global_logo"></div>
This has to be super easy, just couldn't find the solution for the past three hours:
I want to display a number (100) on my website that will be increased by the days past, problem is that the number goes back to the 100 when I reload the website, how do I make that number stay increased over time?
Here's the code:
<script>
var smyle = 11406;
var happyclients = 1006;
var hours = 4220;
window.setInterval(
function () {
smyle = smyle + 2;
document.getElementById("smiles").innerHTML = smyle;
}, 2880);
window.setInterval(
function () {
happyclients = happyclients + 4;
document.getElementById("happy").innerHTML = happyclients;
}, 28800000);
window.setInterval(
function () {
hours = hours + 8
document.getElementById("hoursspent").innerHTML = hours;
}, 86400000);
</script>
The HTML
<div class="col-md-3 col-sm-6 animate-box" data-animate-effect="fadeInLeft">
<div class="feature-center">
<span class="icon">
<i class="ti-music"></i>
</span>
<span class="counter js-counter" data-from="0" data-to="" data-speed="4000" data-refresh-interval="50" id="smiles"></span>
<span class="counter-label">Smiles Created</span>
</div>
</div>
I am new to JS, previously tried with PHP but couldn't find the answer either, this is the closest I got.
So far I've gotten to this with your help, the idea of storing the data on the local database is quite clean and efficient, but I'm not being able to make it work yet (see changes at the bottom of the code)
I've read plenty of documentation about this and I think that the order is correct, but is it?
<script>
var smyle = 11000;
var happyclients = 1006;
var hours = 4220;
window.setInterval(
function () {
smyle = smyle + 2;
document.getElementById("smiles").innerHTML = smyle;
}, 288);
window.setInterval(
function () {
happyclients = happyclients + 4;
document.getElementById("happy").innerHTML = happyclients;
}, 288);
window.setInterval(
function () {
hours = hours + 8
document.getElementById("hoursspent").innerHTML = hours;
}, 864);
if (typeof(Storage) !== "undefined") {
// Store
localStorage.setItem("smyle");
//Retrieve
document.querySelector("smiles").innerHTML = localStorage.getItem("smyle");
} else {
document.write(11404);
}
</script>
I didn't change anything in the HTML part yet, so the id is still id="smiles"
You may wish to store this somewhere, which could be a cookie or more easily just store it in a database. You can say for each user how long they have spent, by updating your database every few seconds or minutes. Then all you would need to do is pull for that data and check where the data is.
Currently, your method requires the user to have the page open continuously, which will in fact restart it every time as the JavaScript will have no sense of previous time spent.
you can save it in localStorage on client side.
here is the reference
if you want the same result for everyone you should do this on your server.
Saving the data in localStorage will definitely help:
localStorage.setItem(//takes an object);
For retrieval:
document.querySelector("...").innerHTML = localStorage.getItem(//takes object key);
I have a small web calculator which calculates time. My mobile browser gets rid of all data when I've minimised/closed the mobile broswer for a few minutes or on a page refresh so I've made a button which can reload all previous data and displays as text.
I want to get rid of the "Get old data" button and just have the page reload with all the values displayed in the input box as they were before the page refresh.
I've been thinking an onload event in the input box would work but as i understand this is not possible.
HTML
<body onload="getreload()">
<p>Please enter minutes</p>
<input type="text" id="etime">
<br>
<p>Please enter time in 24 hour format (eg. 15:00)</p>
<input type="text" id="stime">
<br>
<br>
<button onclick="myFunction()">Calculate</button>
<p id="finishtime">
<br>
<br>
<button onclick="getreload()">Get old data</button>
<p id="finishtime2">
<p id="mintime2">
</body>
Javascript
function myFunction() {
function converToMinutes(s) {
var c = s.split(':');
return parseInt(c[0]) * 60 + parseInt(c[1]);
}
function parseTime(s) {
var seconds = parseInt(s) % 60;
return Math.floor(parseInt(s) / 60) + ":" + ((seconds < 10)?"0"+seconds:seconds);
}
var endTime = document.getElementById("etime").value;
var startTime = converToMinutes(document.getElementById("stime").value);
var converted = parseTime(startTime - endTime);
document.getElementById('finishtime').innerHTML = "You will finish your break at " + converted;
if (typeof(Storage) !== "undefined") {
localStorage.setItem("convertedTime", converted);
localStorage.setItem("endTimeReload", endTime);
} else {
// Sorry! No Web Storage support
}
}
function getreload() {
var convertedTime = localStorage.getItem("convertedTime");
document.getElementById('finishtime2').innerHTML = "End of break time: " + convertedTime;
var endTimeReload = localStorage.getItem("endTimeReload");
document.getElementById('mintime2').innerHTML = "Minutes till next client: " + endTimeReload;
}
You are mostly there, but you are not restoring correctly and not saving the startTime.
Here is a fiddle with everything you need:
https://jsfiddle.net/22ej8scw/
Restore like this. (I also changed how it is saved)
function getreload() {
var startTime = localStorage.getItem("startTime");
document.getElementById("stime").value = startTime;
var endTimeReload = localStorage.getItem("endTimeReload");
document.getElementById("etime").value = endTimeReload;
if (startTime && endTimeReload)
myFunction();
}
So after you've calculated a time, you want those values to be there if you refresh the page?
When you calculate, save all the values in localstorage, then when the page loads (body element's 'onload') set the input boxes values to the corresponding localstorage ones (checking to make sure those values exist first)
This is likely an easy fix (easy +200 reputation), for someone who has javascript skills.
Demo of problem: http://shoppingcart-bthub.blogspot.com/ Just add all the items to the cart and click refresh to see the problem with the cookies.
Everything works correctly, except the part of the code that handles cookies for the items that get added to the shopping cart. For some reason, it only holds 2 -5 items, depending on the broswer:
Google Chrome - only holds 2 items (all other items in shopping cart disappear after page reload)
Firefox - 4 items total
Safari - 4
Internet Exploer - 5
The javascript in the demo:
http://shopppingcart.googlecode.com/files/simplecart.js
The part of the javascript link above that is coded to handle cookies:
/*** data storage and retrival ****/
/* load cart from cookie */
me.load = function () {
var me = this;
/* initialize variables and items array */
me.items = {};
me.total = 0.00;
me.quantity = 0;
/* retrieve item data from cookie */
if( readCookie('simpleCart') ){
var data = unescape(readCookie('simpleCart')).split('++');
for(var x=0, xlen=data.length;x<xlen;x++){
var info = data[x].split('||');
var newItem = new CartItem();
if( newItem.parseValuesFromArray( info ) ){
newItem.checkQuantityAndPrice();
/* store the new item in the cart */
me.items[newItem.id] = newItem;
}
}
}
me.isLoaded = true;
};
/* save cart to cookie */
me.save = function () {
var dataString = "";
for( var item in this.items ){
dataString = dataString + "++" + this.items[item].print();
}
createCookie('simpleCart', dataString.substring( 2 ), 30 );
};
To test the full live code:
For the complete live template with all the codes, open a free blog at blogger.com and download the XML template here to upload into blogger: http://www.bloggermint.com/2011/05/shopping-cart-blogger-template/ The free download is in the left-hand sidebar. Also follow the intructions on that page to get it woking in blogger.com
In my opinion the problem is related to the 4K cookie size limit.
Your shopppingcart code is trying to store all the items data in a simpleCart cookie, but when such data gets bigger than 4K the items are not stored into the cookie, even if they're showed in the cart, therefore when the page is reloaded those items disappear.
Consider for example the site http://shoppingcart-bthub.blogspot.in/, and specifically the HTML markup for the "Sony VAIO laptop" item:
<table border="1" style="width: 660px;">
<tbody>
<tr>
<th class="item_thumb" id="thumb" width="45%"><img border="0" src="http://3.bp.blogspot.com/-LcQD--Bb_YE/TeDI44AmUsI/AAAAAAAACBw/K4IJZE2CpMY/s1600/sony+vaio.JPG"></th>
<td>
<input class="item_add" type="button" value="Add to Cart" id="s1">
</td>
</tr>
<tr>
<th><b>Item Name</b></th>
<td class="item_name">Sony VPCEE42FX 15.5" 2.30GHz 500GB VAIO Laptop</td>
</tr>
<tr>
<th><b>Price</b></th>
<td class="item_price">$610.00</td>
</tr>
<tr>
<th><b>Description</b></th>
<td class="item_Description">
The VPCEE42FX is big enough to be useful, but small
enough to be portable. With 500GB of hard drive space, youll have to work hard
to fill up the memory. The 15.5 HD resolution screen and AMD Mobility Radeon HD
graphics card ensure that youll see crisp, fast action, even when youre watching
DVDs on the DVD drive. And at under six pounds, the laptop is easy to pack up
and haul with you.
</td>
</tr>
<tr>
<th><b>Available Stock</b></th>
<td>2 more available</td>
</tr>
</tbody>
</table>
When this product is added to the cart, the simpleCart cookie will contain the following string:
id=c10||thumb=%3Cimg%20border%3D%220%22%20src%3D%22http%3A//3.bp.blogspot.com/-LcQD--Bb_YE/TeDI44AmUsI/AAAAAAAACBw/K4IJZE2CpMY/s1600/sony+vaio.JPG%22%3E%0A||name=Sony%20VPCEE42FX%2015.5%22%202.30GHz%20500GB%20VAIO%20Laptop||price=610||description=The%20VPCEE42FX%20is%20big%20enough%20to%20be%20useful%2C%20but%20small%20enough%20to%20be%20%0Aportable.%20With%20500GB%20of%20hard%20drive%20space%2C%20youll%20have%20to%20work%20hard%20to%20%0Afill%20up%20the%20memory.%20The%2015.5%20HD%20resolution%20screen%20and%20AMD%20Mobility%20%0ARadeon%20HD%20graphics%20card%20ensure%20that%20youll%20see%20crisp%2C%20fast%20action%2C%20even%20%0Awhen%20youre%20watching%20DVDs%20on%20the%20DVD%20drive.%20And%20at%20under%20six%20pounds%2C%20the%20%0Alaptop%20is%20easy%20to%20pack%20up%20and%20haul%20with%20you.||quantity=1
As you can see, it seems that all the <td> elements with a class name starting with item_ are stored in the cookie.
Chrome Developer's Tools shows a size of 828 bytes for this cookie.
Therefore the number of the items that can be added to the cart is variable and depends by the length of each item data (name, description, etc.).
So, what can you do to avoid this problem?
Reduce the item HTML markup to the minimum, for example by removing the item_thumb and item_Description elements.
Modify the addToCart method in the simplecart.js code to reduce the lenght of the cookie by storing less information (see below for details).
Modify the createCookie, readCookie and eraseCookie functions in the simplecart.js code to use local storage instead of a cookie to store item data (have a look at this page for a code sample, or below for another example).
For example, to avoid the storing of the "thumb" and "Description" item fields in the cookie, you could modify the addToCart method as follows:
ShelfItem.prototype.addToCart = function () {
var outStrings = [],valueString;
for( var field in this ){
if( typeof( this[field] ) != "function" && field != "id" ){
valueString = "";
//console.log(field);
switch(field){
case "price":
if( this[field].value ){
valueString = this[field].value;
} else if( this[field].innerHTML ) {
valueString = this[field].innerHTML;
}
/* remove all characters from price except digits and a period */
valueString = valueString.replace( /[^(\d|\.)]*/gi , "" );
valueString = valueString.replace( /,*/ , "" );
break;
case "image":
valueString = this[field].src;
break;
case "thumb":
case "Description":
case "description":
/* don't store "thumb" and "description" in the cookie */
break;
default:
if( this[field].value ){
valueString = this[field].value;
} else if( this[field].innerHTML ) {
valueString = this[field].innerHTML;
} else if( this[field].src ){
valueString = this[field].src;
} else {
valueString = this[field];
}
break;
}
outStrings.push( field + "=" + valueString );
}
}
}
A much better approach would be to use localStorage if the browser supports it, otherwise use cookies as a fallback:
function supports_html5_storage() {
try {
return 'localStorage' in window && window['localStorage'] !== null;
} catch (e) {
return false;
}
}
function createCookie(name,value,days) {
if (supports_html5_storage()) {
if (value == '') {
eraseCookie(name);
} else {
window.localStorage.setItem(name, JSON.stringify(value));
}
} else {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else var expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}
}
function readCookie(name) {
if (supports_html5_storage()) {
return window.localStorage.getItem(name);
} else {
var ca = document.cookie.split(';');
var nameEQ = name + "=";
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
}
function eraseCookie(name) {
if (supports_html5_storage()) {
window.localStorage.removeItem(name);
} else {
createCookie(name,"",-1);
}
}
When using localStorage we can also store the thumb and description fields without problems (since we have 5 Mb of space), therefore we can further modify the ShelfItem.prototype.addToCart function this way:
...
case "thumb":
case "Description":
case "description":
if (!supports_html5_storage()) break;
...
It seems you are catching black cat in a dark room and cat isn't there.
So what I've done:
Get http://shopppingcart.googlecode.com/files/simplecart.js
Get html from http://wojodesign.com/simpleCart/
Replace simplecart.js with yours.
What I've found:
When you open html page from filesystem then you have what you have
If you put it on a server (in my case local instance of apache) then everything works fine
2 Episode.
You trying to put to much information in cookie.
Simple way modify print function like this
CartItem.prototype.print = function () {
var returnString = '';
for( var field in this ) {
if( typeof( this[field] ) != "function" && field !="description") {
returnString+= escape(field) + "=" + escape(this[field]) + "||";
}
}
return returnString.substring(0,returnString.length-2);
};
Do you really need all item fields in cookie?
Users select checkboxes and hit select, the results are displayed, but then checkboxes lose their checked state and that will make users confused what they checked. I am trying to presist the checkboxes state after the page refresh. I am not able to acheive this yet, but I am hopeful its doable. Can someone help me in the right direction?
Emergency Centers<input name="LocType" type="checkbox" value="Emergency"/>
Out-Patient Centers<input name="LocType" type="checkbox" value="Out-Patient"/>
Facilities<input name="LocType" type="checkbox" value="Facility"/>
<div class="searchBtnHolder"><a class="searchButton" href="#" type="submit"><span>Search</span></a></div>
$(document).ready(function() {
var url = "http://mysite/sites/dev/contact-us/Pages/LocationSearchTestPage.aspx?s=bcs_locations";
$('a.searchButton').click(function(){
var checkboxValues = $("input[name=LocType]:checked").map(function() {
return "\"" + $(this).val() + "\"";}).get().join(" OR ");
//Now use url variable which has all the checked LocType checkboxes values and jump to url
window.location = url+'&k='+checkboxValues;
});
//Keep the selected checked on page redirect
var value = window.location.href.match(/[?&]k=([^&#]+)/) || [];
if (value.length == 2) {
$('input[name="LocType"][value="' + value[1] + '"]').prop('checked', true);
}
});
not sure if you're still interested in this, but I had the same problem a little while ago, and found this generic piece of JS that persist checkbox states:
// This function reads the cookie and checks/unchecks all elements
// that have been stored inside. It will NOT mess with checkboxes
// whose state has not yet been recorded at all.
function restorePersistedCheckBoxes() {
var aStatus = getPersistedCheckStatus();
for(var i = 0; i < aStatus.length; i++) {
var aPair = aStatus[i].split(':');
var el = document.getElementById(aPair[0]);
if(el) {
el.checked = aPair[1] == '1';
}
}
}
// This function takes as input an input type="checkbox" element and
// stores its check state in the persistence cookie. It is smart
// enough to add or replace the state as appropriate, and not affect
// the stored state of other checkboxes.
function persistCheckBox(el) {
var found = false;
var currentStateFragment = el.id + ':' + (el.checked ? '1' : '0');
var aStatus = getPersistedCheckStatus();
for(var i = 0; i < aStatus.length; i++) {
var aPair = aStatus[i].split(':');
if(aPair[0] == el.id) {
// State for this checkbox was already present; replace it
aStatus[i] = currentStateFragment;
found = true;
break;
}
}
if(!found) {
// State for this checkbox wasn't present; add it
aStatus.push(currentStateFragment);
}
// Now that the array has our info stored, persist it
setPersistedCheckStatus(aStatus);
}
// This function simply returns the checkbox persistence status as
// an array of strings. "Hides" the fact that the data is stored
// in a cookie.
function getPersistedCheckStatus() {
var stored = getPersistenceCookie();
return stored.split(',');
}
// This function stores an array of strings that represents the
// checkbox persistence status. "Hides" the fact that the data is stored
// in a cookie.
function setPersistedCheckStatus(aStatus) {
setPersistenceCookie(aStatus.join(','));
}
// Retrieve the value of the persistence cookie.
function getPersistenceCookie()
{
// cookies are separated by semicolons
var aCookie = document.cookie.split('; ');
for (var i=0; i < aCookie.length; i++)
{
// a name/value pair (a crumb) is separated by an equal sign
var aCrumb = aCookie[i].split('=');
if ('JS_PERSISTENCE_COOKIE' == aCrumb[0])
return unescape(aCrumb[1]);
}
return ''; // cookie does not exist
}
// Sets the value of the persistence cookie.
// Does not affect other cookies that may be present.
function setPersistenceCookie(sValue) {
document.cookie = 'JS_PERSISTENCE_COOKIE=' + escape(sValue);
}
// Removes the persistence cookie.
function clearPersistenceCookie() {
document.cookie = 'JS_PERSISTENCE_COOKIE=' +
';expires=Fri, 31 Dec 1999 23:59:59 GMT;';
}
Just make sure your checkboxes have an onChange= persistCheckBox(this); attached to them
eg.
<label for= "LocType">User Preference</label>
<input name= "LocType" type= "checkbox" onChange= persistCheckBox(this);"/>
And also an onLoad in your opening body tag:
<body onload="restorePersistedCheckBoxes();">
I would be more inclined to go with HTML5 web storage (faster and more secure) but cookies would also do the job. Here is a link to some samples using HTML5 http://www.w3schools.com/html5/html5_webstorage.asp