Shopping cart: Cookies only holding 2 - 5 items - javascript

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?

Related

SCRIPT5007: Unable to get property 'toLowerCase' of undefined or null reference

I have a .aspx file working on SharePoint.
We are using IE11, jQuery 2.2.3, jQuery UI 1.11.4, Bootstrap 3.3.6
We had this system for around three years by a third party, which we stopped business. And not able to contact anymore.
It was working fine until a few weeks ago suddenly the page is loading forever and showing this error
SCRIPT5007: Unable to get property 'toLowerCase' of undefined or null reference
Loading page - capture
I have Googled and it seems like the script is waiting for ConfigurationCube.js to load. But since it's not loading, I think it's waiting forever.
/* handles the displaying of all outstanding items requiring approval*/
var TableCreated=0;
var app="";
var teamsArr = [];
var GlobalDivisionsArr = [];
$(document).ready(function(){
//check to see if the Configuration cube Obj Exists and wait until it does
var checkExist = setInterval(function() {
if (sessionStorage["ConfigurationCube"] != null) {
app = JSON.parse(sessionStorage.ConfigurationCube).AppURL;
/**CreateLookupSectionForEmployees("My Winners","Kaizen List","#ViewWinnersTable");**/
//Displayed using the configuration cube.js file
DisplayUserInformation();
popDD("kznSearchCategory",JSON.parse(sessionStorage.ConfigurationCube).ListOfCategories);
IntialPopulationOfApprovedKaizens("","Kaizen List","#kznSearchResultsTable");
//Initialize date range picker
/**$("#kznEditToDate").datepicker();*/
var CubeMin = (JSON.parse(sessionStorage.ConfigurationCube).SubmissionPeriod).split(" ")[0];
clearInterval(checkExist);
}
}, 500);
});
I also tried in IE8, 9, 10, Edge. All not working.
Our company does not allow Chrome or any other browser so we need to get it work in IE..
My current meta tag is like this. Also tried various ways, but did not work.
<meta http-equiv="x-ua-compatible" content="IE=edge; charset=UTF-8">
Does anyone have any similar problems?
Any kind of idea is appreciated..
When clicking on the error, it directs to ConfigutationCube.js
//Tools for other pages
function compareStrings(a, b) {
// Assuming you want case-insensitive comparison
a = a.toLowerCase();
b = b.toLowerCase();
return (a < b) ? -1 : (a > b) ? 1 : 0;
}
Script snip from SearchKaizen.js
function IntialPopulationOfApprovedKaizens(HeadingTitle,ListName,ElementToAppend){
//Get all current data from lists
var GetKaizenPromise = GetList( "Kaizen List",
"Id,Nominated_x0020_person, Status, Kaizen_x0020_Title,Division/Id, Team/Id,Division/Title, Team/Title, Name, Financial_x0020_Year, Kaizen_x0020_Category,Quarter",
"Division/Id, Team/Id,Division/Title, Team/Title",
"Status eq 'Approved'",
app);
$.when(GetKaizenPromise).done(function(KaizenSelectionData){
var EditButton = "";
var Results = KaizenSelectionData.d.results;
//Creates table structure and heading
var DataTableHtml = "";
var SetVotedBackground = "style='background-color:lightgreen;color:white;'";
var DivisionList = [];
var TeamList = [];
var YearList = [];
var DivisionCheck = [];
var TeamCheck = [];
if(Results.length > 0){
for(r=0;Results.length > r;r++){
TableCreated++;
var ResultsName = Results[r].Nominated_x0020_person;
var KaizenTitle = Results[r].Kaizen_x0020_Title;
var ResultsTeam = Results[r].Team.Title;
var ResultsDivision = Results[r].Division.Title;
var ResultsTeamId = Results[r].Team.Id;
var ResultsDivisionId = Results[r].Division.Id;
var ResultsCategory = Results[r].Kaizen_x0020_Category;
var ResultsStatus = Results[r].Status;
var ResultsQuarter = Results[r].Quarter;
var ResultsYear = Results[r].Financial_x0020_Year;
EditButton = "<p style='cursor:pointer;' class='edititem text-light-blue' data-itemid='"+Results[r].Id+"' data-listname='"+ListName+"'><i class='fa fa-edit'></i> View</p>";
DataTableHtml += "<tr>"+
"<td>"+ResultsName+"</td><td>"+ResultsDivision+"</td><td>"+ResultsTeam +"</td>"+
"<td>"+ResultsYear+"</td><td>"+ResultsQuarter+"</td><td>"+KaizenTitle +"</td>"+
"<td>"+ResultsCategory +"</td><td>"+EditButton+"</td>"
"</tr>";
//Create the drop down box info from all the results
if($.inArray(ResultsDivision , DivisionCheck ) == -1){
// Add to departments list
DivisionList.push({"FullName": ResultsDivision,"ID":ResultsDivisionId});
DivisionCheck.push(ResultsDivision);
//Keep duplicate of original divisions list
GlobalDivisionsArr.push({"FullName": ResultsDivision,"ID":ResultsDivisionId});
}
if($.inArray(ResultsTeam , TeamCheck) == -1){
// Add to Teams list
TeamList .push({"FullName": ResultsTeam,"ID":ResultsTeamId,"Division":ResultsDivisionId});
TeamCheck.push(ResultsTeam);
//Keep duplicates of original list
teamsArr.push({"FullName": ResultsTeam,"ID":ResultsTeamId,"Division":ResultsDivisionId});
}
if($.inArray(ResultsYear , YearList) == -1){
// Add to Year list
YearList.push(ResultsYear );
}
//next Item
}
}else{
//if there are no results
DataTableHtml = "<tr>"+
"<td colspan='8'>No results found</td>" +
"</tr>";
}
YearList.sort();
YearList.reverse();
TeamList.sort(function(a, b) {
return compareStrings(a.FullName, b.FullName);
});
DivisionList.sort(function(a, b) {
return compareStrings(a.FullName, b.FullName);
});
popDD("kznSearchYear",YearList);
popDDSearchWithDataAttr("kznSearchTeam",TeamList,TeamList);
DivisionList.unshift({"FullName": "All","ID":"All"}); //Add All option to division list
popDDVal("kznSearchDivision",DivisionList);
//adds items to DOM
$(ElementToAppend + " tbody").html(DataTableHtml);
//Create column match with returned results
if (Results.length>0){
$.fn.dataTable.ext.errMode = 'console';
$(ElementToAppend).DataTable({
"dom": 'ftipr',
"responsive": true
});
}
$("body").css("overflow","");
//removes overlayer and loading symbol
$("#OverlayFade").addClass("hidden");
$("#Timer").addClass("hidden");
});
}
This snip of the script has popDDVal, and it looks like 'DivisionList' 'TeamList' 'YearList' is returning null. Since this is null it can not break from the loading overlayer.
I was able to narrow it down to this part.
TeamList.sort(function(a, b) {
return compareStrings(a.FullName, b.FullName);
});
DivisionList.sort(function(a, b) {
return compareStrings(a.FullName, b.FullName);
});
Changed it to this, and it worked. But obviously the sorting is not sorted correctly, but least it works now...
TeamList.sort();
DivisionList.sort();
Instead of passing in an anonymous function pass the function name:
TeamList.sort(compareStrings);
or
DivisionList.sort(compareStrings);

"FORBIDDEN You don't have permission to access /greenfloyd/php/bm_edit_xml.php on this server."

I've been sweating over this the last three days, I am baffled!
The input html launches an xml scan of a web site to gather text, images and links which populate a form for the user to select what they want to save. (The output eventually becomes a bookmark stored at greenfloyd.org.) The problem began a month or so ago, the scan started crashing with a "Forbidden 403" error pointing to my php code file, on the gf server (dir/file permission at 0644). The problem revolves around the links (url and text) gathered and placed into a box , the url is put in the value, and the link text into the innerHTML. The default is that none of the links are selected, the user can then select one or more links from this box, or manually add a link via two fields that get put into the select box, and become part of the form.
<form id = "bmInputForm" onsubmit = "bmSub(); return false;" onreset = "bmInputFormReset();" action = "http://greenfloyd.org/greenfloyd/php/bm_input_xml.php" method = "post" enctype = "multipart/form-data" class = "readerBox">...
<code><input type = "url" id = "link1Url" class = "input_size" size = "40" maxlength = "250" value ="" onclick = "this.select();" title = "Enter a standard url for this related link.">
<input id = "link1Title" class = "input_size" size = "40" maxlength = "150" value = "" onclick = "this.select();" title = "Enter a short title for this related link.">
<button type = "button" onclick = "relatedAdd()" title = "Add to related links list.">[+]</button>
<hr style="width:25%;">
<select id = "relatedSelect" name = "related_select[]" multiple title = "To select/unselect hold down the Ctrl key and click an option." onchange = "relatedCheck();" style = "width:80%;"></select></code>
The scan is an ajax xml call and returns elements from the target url, including the following:
<code>//echo "<related url='".rawurlencode($valid_url)."' txt='".htmlspecialchars($related_text, ENT_QUOTES,'UTF-8')."'></related>";
err = false;
try { var relatedNode = ( xmlDoc.getElementsByTagName("related") ) ? xmlDoc.getElementsByTagName("related") : false; }
catch(err) { err = true; relatedNode = false; }
result += ( !relatedNode ) ? "<li>Scanner unable to retrieve relatedNode || "+err+"</li>" : "<li>Link scan found: "+relatedNode.length+" entries.</li>";
if( relatedNode.length > 0 )
{
clearCache("relatedSelect");
var selObj = document.getElementById("relatedSelect");
for(var i = 0; i < relatedNode.length; i++)
{
val = unescape(relatedNode[i].getAttribute("url"));
str = unescape(relatedNode[i].getAttribute("txt"));
opt = document.createElement("option");
opt.value = val;
opt.innerHTML= ( str.length > 50 ) ? str.substring(0,48)+"..." : str;
selObj.appendChild(opt);
}
}
</code>
All the above is working fine. But everything goes south at submit time when the urls, (the value), are external relative to greenfloyd.org. Then, I get the "Go away and don't come back message..." On the other hand, if the urls point to greenfloyd there's no problem and the bookmark is published, with links. It's almost like I were trying to call the local script from some other domain. The uls are not in any linkable context, they are treated as plain text in the value attribute of the option. Although I do combine the url with the text using a seperator (,) between them so that php can unpack the value to produce seperate url and text fields that are stored on msqli... it's hacky, but it works, or at least it use to and I've yet to find a better alternative. One other odd thing: when I gather the links in greenfloyd.org there are a couple external links and they are accepted!?
<code>
function bmSub()
{
...
var selObj = document.getElementById("relatedSelect");
var url, txt, val, sendCt=0;
for ( var i = 0; i < selObj.options.length; i++ )
{
if ( selObj.options[i].selected )
{
url = selObj.options[i].value.trim();
txt = selObj.options[i].innerHTML;
val = url+"*,*"+txt; // pack url and txt into the value attribute, php unpacks it into 2 db fields
selObj.options[i].value = val;
sendCt +=1;
}
}
resultDisplay("Link count: "+sendCt);
var formElement = document.getElementById("bmInputForm");
var formData = new FormData(formElement);
var urlX = encodeURI("http://greenfloyd.org/greenfloyd/php/bm_input_xml.php?sid="+Math.random());
xmlObj = GetXmlHttpObject();
xmlObj.open("POST", urlX, false);
xmlObj.send(formData);
// pause echo "<return err='$err' msg='$msg'></return>";
try
{
xmlDoc = xmlObj.responseXML;
var returnNode = xmlDoc.getElementsByTagName("return");
err = ( returnNode[0].getAttribute("err") == "1" ) ? true : false;
msg = unescape(returnNode[0].getAttribute("msg"));
}
catch(e)
{
msg = "bmSub status : "+e+"<br>xml: "+xmlObj.statusText+", "+xmlObj.status+", size: "+xmlObj.responseText.length;
err = true;
}
resultDisplay(msg);
if ( err ) return;
</code>

Microsoft Dynamics CRM 2011/2013

In my entity (A) has 50 option set. If the user select 10 optionsset value and not selected remaining one, and he/she click save button. In that situation i need to alert user "To fill all the option set". I don't want to get the Schema name for the optionset individually, i need to get all the option set schema name dynamically.
Is it possible? Help me.
I have not tested this function, but you can try this and make changes if needed.
function IsFormValidForSaving(){
var valid = true;
var message = "Following fields are required fields: \n";
Xrm.Page.data.entity.attributes.forEach(function (attribute, index) {
if (attribute.getRequiredLevel() == "required") {
if(attribute.getValue() == null){
var control = attribute.controls.get(0);
// Cheking if Control is an optionset and it is not hidden
if(control.getControlType() == "optionset" && control.getVisible() == true) {
message += control.getLabel() + "\n";
}
valid = false;
}
}
});
if(valid == false)
{
alert(message);
}
}
Ref: Microsoft Dynamics CRM 2011 Validate required form javascript
Required fields individual alert fire before the on save event. If you wish to prevent the single alert routine for all unfilled option sets you need to remove the requirement constraint and manage the constraint yourself, probably in your on save handler. I’m just writing the idea here (not tested).
// enter all optionsets ids
var OptionSets50 = ["new_optionset1","new_optionset2","new_optionset50"];
var dirtyOptions = [];
function MyOptionSet(id) {
var mos = this;
var Obj = Xrm.Page.getAttribute(id);
var Ctl = Xrm.Page.getControl(id);
Obj.addOnChange(
function () {
if (Obj.getValue() != null)
delete dirtyOptions[id];
else
dirtyOptions[id] = mos;
});
this.GetLabel = function() {
return Ctl.getLabel();
}
if (Obj.getValue() == null)
dirtyOptions[id] = mos;
}
function OnCrmPageLoad() {
for(var x in OptionSets50) {
OptionSets50 [x] = new MyOptionSet(OptionSets50 [x]);
}
Xrm.Page.data.entity.addOnSave(OnCrmPageSave);
}
//check for dirty options and alert
function OnCrmPageSave(execContext) {
var sMsg = "The following Optinsets Are Required: ";
var sLen = sMsg.length;
for(var os in dirtyOptions) {
sMsg += dirtyOptions[os].GetLabel() + "\n";
}
if (sMsg.length > sLen) {
execContext.getEventArgs().preventDefault();
alert(sMsg);
}
}

Remember image number in JavaScript slide show across pages

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;
}

Keeping clicked checkboxes state after page refresh

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

Categories

Resources