I am doing a uni assignment so please excuse the coplete lack of knowledge here. I have been tasked with creating a web based app for a "client" that requires me to open an invoice after they have completed all the details, so far I have the form working fine, i can save to localstorage without an issue and can even retrieve the information in the format that I want.
The issue is that if i have multiple "orders' than i can only retrieve the first string saved to localstorage and i cannot figure out how to make it display the newest/last one.
The key is an almost randomly generated number derived from the date as we had to assume a large quantity of orders. I have attached the code below so if anyone can help i would appreciate it. Also I cannot use Jquery or JSON or anything like that. We have been told we are not able to use these. Also i cannot use a server (php etc).
Thanks
Steve
<script>
var i = 0;
var itemKey = localStorage.key(i);
var values = localStorage.getItem(itemKey);
values = values.split(";");
var name = values[0];
var company = values[1];
var contactnumber = values[2];
var email = values[3];
var address1 = values[4];
var address2 = values[5];
var suburb = values[6]
var postcode = values[7];
var comments = values[8];
var bags = values[9];
var distance = values[10];
var hdelivery_fee = values[11];
var hprice = values[12];
var htotal_notax = values[13];
var hgst = values[14];
var htotal_tax = values[15];
var hordernumber = values[16];
document.write('Name: ' + name + '<br />');
document.write('Company: ' + company + '<br />');
document.write('Contact: ' + contactnumber + '<br />');
document.write('Email; ' + email + '<br />');
document.write('Address; ' + address1 + '<br />');
document.write('Address; ' + address2 + '<br />');
document.write('Suburb; ' + suburb + '<br />');
document.write('Postcode; ' + postcode + '<br />');
document.write('Comments; ' + comments + '<br />');
document.write('Number of Bags; ' + bags + '<br />');
document.write('Distance; ' + distance + '<br />');
document.write('Delivery Fee; $' + hdelivery_fee + '<br />');
document.write('Price of Bags; $' + hprice + '<br />');
document.write('Total Ex-GST; $' + htotal_notax + '<br />');
document.write('GST; $' + hgst + '<br />');
document.write('Total Inc GST; $' + htotal_tax + '<br />');
document.write('hordernumber; ' + hordernumber + '<br />');
</script>
To display the last value of an array you should use values[values.length-1].
This will guarantee you get the absolute last one.
simple put
var itemKey = localStorage.key(i);
var values = localStorage.getItem(itemKey); in a loop and increement i each time.
You can try something like this
var localStorageKeys = Object.keys(localStorage);
getOrder(localStoragesKeys[localStoragesKeys.length-1]);
function getOrder(itemKey) {
var values = localStorage.getItem(itemKey);
values = values.split(";");
var name = values[0];
var company = values[1];
var contactnumber = values[2];
var email = values[3];
var address1 = values[4];
var address2 = values[5];
var suburb = values[6]
var postcode = values[7];
var comments = values[8];
var bags = values[9];
var distance = values[10];
var hdelivery_fee = values[11];
var hprice = values[12];
var htotal_notax = values[13];
var hgst = values[14];
var htotal_tax = values[15];
var hordernumber = values[16];
document.write('Name: ' + name + '<br />');
document.write('Company: ' + company + '<br />');
document.write('Contact: ' + contactnumber + '<br />');
document.write('Email; ' + email + '<br />');
document.write('Address; ' + address1 + '<br />');
document.write('Address; ' + address2 + '<br />');
document.write('Suburb; ' + suburb + '<br />');
document.write('Postcode; ' + postcode + '<br />');
document.write('Comments; ' + comments + '<br />');
document.write('Number of Bags; ' + bags + '<br />');
document.write('Distance; ' + distance + '<br />');
document.write('Delivery Fee; $' + hdelivery_fee + '<br />');
document.write('Price of Bags; $' + hprice + '<br />');
document.write('Total Ex-GST; $' + htotal_notax + '<br />');
document.write('GST; $' + hgst + '<br />');
document.write('Total Inc GST; $' + htotal_tax + '<br />');
document.write('hordernumber; ' + hordernumber + '<br />');
}
If you must use localStorage and cannot use any client side database then I would save each entry with a key like new Date().getTime() with a known string in front of it, so that you have key-1368910344400.
When you need to retrieve the last entry then you could do:
var keys = Object.keys(localStorage);
keys = keys.map(function(key) {
// check if the current key matches match "key-"
// if that's the case create a new Date object with the ms obtained by a split
// return the Date
});
// sort keys and take the most recent
This is usually a bad choice but as I understand it you're limited with choices, so you have to stretch things a bit.
If you could use a browser that supports html5 and webdb then just throw localStorage away and go for that :D, here is an example: http://www.html5rocks.com/en/tutorials/webdatabase/todo/
Related
I have six static html questions and then 3-4 questions being generated by JSON dynamically based upon a form choice made on a page before. What I'm trying to do is generate the questions, then create a progress bar based on the final number of questions created. Where I'm having trouble is using the jQuery when done method after my each loop. It is firing after the first iteration instead of the last. I have tried populating an array "Qs" and passing the array, after reading some other posts, but what I have hasn't worked. I would really like to segment my code and clean it up as much as possible, so I'm trying to stay away from nesting it.
var Qs = [];
var generateQs = function (){
var $dept = sessionStorage.getItem("sFGeneralDepartment1");
var $qWrapper = $("#assessmentTool");
$.getJSON("js/dept-questions.json", function(data) {
var key = $dept;
var vals = [];
switch(key) {
case 'Information technology':
vals = data.IT;
break;
case 'Finance':
vals = data.FIN;
break;
case 'Human resources':
vals = data.HR;
break;
case 'Marketing':
vals = data.MKT;
break;
default:
vals = data.OT;
break;
}
$.each(vals, function(index, value) {
var $cleanID = (value.qID).replace(/q/g, '');
$qWrapper.append('<div class="question-container rangeIcon disabled" id="' + value.qID + '"><p>Question ' + $cleanID +'</p> <h4>' + value.questionText + '</h4><ul class="answer-container"></ul></div>');
$.each(value.answers, function(i, answer) {
var $aID = answer.aID;
var $radioBtn = '<div class="radioBtn"><span class="radioBtnInner"></span></div>';
$('.question-container#' + value.qID + ' .answer-container').append('<li class="survey-item"><div class="icon-holder" id="' + $aID + '"><img src="img/' + answer.iconFileName + '" width="' + answer.iconWidth +'" height="'+ answer.iconHeight + '"/></div><input type="radio" id="'+ $aID + '" value="' + answer.pointValue + '"><label for="' + $aID + '" class="radio" data-popover="'+ answer.popoverText + '">' + $radioBtn + '<span class="labelTopText">' + answer.labelTopText + '<span class="divider">/</span></span><span class="labelBottomText">' + answer.labelBottomText + '</span></label></li>');
});
Qs.push($cleanID);
});
console.log('done');
console.log(Qs);
});
};
$.when(generateQs($,Qs)).done(function() {
//create progress bar
console.log('starting');
var qCount = ($('.question-container').length + 1);
var qList = $('#progressBar');
for (var i = 0; i < qCount; i++){
qList.append('<li class="progress-bar-steps" data-item="q' + (i+1) + '">' + '<span class="step-text">' + (i+1) + '</span>' + '</li>');
$('.question-container').each(function (i, value){
var qId = $(this).attr('id');
if ($(this).hasClass("active")) {
$(this).css('opacity','1.0');
$('#progressBar').find("[data-item='" + qId + "']").addClass('active').html('<span class="step-text">' + (i+1) + '</span>');
$('.progress-bar-steps.active').next('.progress-bar-steps').addClass('next disabled-next').html('<span class="step-text">' + (i+2) + '</span>');
} else {
$(this).addClass('disabled');
}
});
}
});
I am making an AJAX call to the Tumblr API, and the code works fine on my desktop browser here, but it seems to fail on my iPhone. I can't seem to replicate the bug if I toggle the device through the Chrome developer tools. Anybody know what issue I might be having?
function loadPosts() {
var key = "api_key=USV2JcShmHgoYysSrXKL1OyzmouVcG3PxCtAJ0OT8rGkSkuGNR";
var api = "https://api.tumblr.com/v2/blog/c4ministry.tumblr.com/";
var retrieve_more = function(offset) {
$.getJSON(api + "posts/text?callback=?&filter=text&offset=" + offset + "&" + key,function(data) {
$.each(data.response.posts, function(i, item) {
moment.tz.add('America/Los_Angeles|PST PDT|80 70|0101|1Lzm0 1zb0 Op0');
var date = new Date(item.date).toISOString();
var momentDate = moment(date).tz('America/Los_Angeles').format('MMMM Do, YYYY');
var postUrl = item.post_url;
var title = item.title;
var body = item.body;
$("#tumblr").append('<li>' +
'<h3>' + title + '</h3>' +
'<p class="title">' + 'Pastor DP - ' + '<em>' + momentDate + '</em></p>' +
'<p class="body">' + body.substring(0,500) + '...' + '</p>' +
'<p><a class="btn btn-info" href="' + postUrl + '" target="blank">' + 'Read More' + '</a></p>' +
'</li>')
});
});
};
retrieve_more(0);
}
Annoyingly, the FlickrAPI provides the title and description of a photo in two separate methods. I'm having trouble getting the description of an image from Flickr and was wondering if you could highlight the error in my script.
for (var i = 0; i < photos.photo.length; i++) {
var descPhoto = "https://api.flickr.com/services/rest/?method=flickr.photos.getInfo&api_key="+API_KEY+"&photo_id="+photos.photo[i].id+"&format=json&nojsoncallback=1";
var descArr = [];
$.getJSON(descPhoto, function(data) {
var value = data.photo.description._content;
descArr.push(value);
});
link = 'https://farm' + photos.photo[i].farm + '.static.flickr.com/' + photos.photo[i].server + '/' + photos.photo[i].id + '_' + photos.photo[i].secret + '_';
title = this._htmlEscape( photos.photo[i].title );
var lightbox = "lightbox";
listItems +=
'<li ' + 'class="' + liClassNoDots + '">' +
'<a href="' + link + self.options.imageSize + '.jpg" title="' + title + '" class="' + aClassNoDots + '" target="_blank" data-lightbox="' + lightbox + '">' +
<img alt="' + title + '" src="' + link + self.options.thumbnailSize +'.jpg"/>' +
'<div class="hover-box">' +
'<p>' + descArr[i] + '</p>' +
'<button class="box-button view">View larger</button>' +
'<button class="box-button request">Request</button>' +
'</div>';
'</a>' +
'</li>';
}
Getting the title is fine and I've checked by API string calls and they work in the address bar of my browser.
I've used console.log() and the array is printed out correctly and I'm getting the descriptions. However, in each <p> tag the script is returning undefined in each instance.
However, if I run the script through the debugger the parapgraph tags are populated with the descriptions. Can somebody help?!
i think the problem is in following code::
..
$.getJSON(description, function(desc) {
value = desc.photo[ i ].description._content;
});
the service url returns photo object whereas you are using photo array, change to:
..
$.getJSON(description, function(desc) {
value = desc.photo.description._content;
console.log( value );
});
I have a script that calls data from a database. For every result a new div is output. However when the button that calls the function search() is clicked, I only get one result. I guess the question is: how do I create a new div for every result, not just set it to the first row found?
function search() {
var xhr2 = new XMLHttpRequest();
xhr2.addEventListener ("load", view);
var reg = document.getElementById("type").value;
xhr2.open("GET", "getresults.php?type=" + reg);
xhr2.send();
}
function view(e, resulthtml) {
var array = JSON.parse(e.target.responseText);
for (var count=0; count<array.length; count++)
{
var id = array[count].id;
var username = array[count].username;
var srcpath = array[count].srcpath;
var title = array[count].title;
var type = array[count].type;
var postcode = array[count]. postcode;
var description = array[count]. description;
var price = array[count].price;
var phone = array[count].phone;
var lat = array[count].lat;
var lon = array[count].lon;
resulthtml = "<div class='col-md-4'>"
+ "<div class='thumbnail'>"
+ "<img id='a' class='a' alt='300x200' src='" + srcpath + "'>"
+ "<div class='caption'>"
+ "<h3>"
+ description
+ "</h3>"
+ "<p>"
+ "£" + price + ""
+ "</p>"
+ "<p>"
+ "Contact number:"
+ "</p>"
+ "<p>"
+ "<input type='submit' value='Contact seller' onclick='search()'/>"
+ "</p>"
+ "</div>"
+ "</div>"
+ "</div>"
}
document.getElementById("row").innerHTML = resulthtml;
}
</script>
You're overwriting resulthtml on every iteration of the loop. Initialize it as an empty string outside the loop and then add to it.
edit: You're also doing quite a lot of work in the loop that could be hoisted outside of it, mainly all that string concatenation. This would be easier on the browser:
var item, id, username, srcpath, title, type, postcode, description, price, phone, lat, lon,
resulthtml = '',
pre = "<div class='col-md-4'><div class='thumbnail'><img id='a' class='a' alt='300x200' src='",
inner1 = "'><div class='caption'><h3>",
inner2 = "</h3><p>£",
post = "</p><p>Contact number:</p><p><input type='submit' value='Contact seller' onclick='search()'/></p></div></div></div>";
for (var count=0; count<array.length; count++)
{
item = array[count];
id = item.id;
username = item.username;
srcpath = item.srcpath;
title = item.title;
type = item.type;
postcode = item. postcode;
description = item. description;
price = item.price;
phone = item.phone;
lat = item.lat;
lon = item.lon;
resulthtml += pre + srcpath + inner1 + description + inner2 + price + post;
}
You can't do
document.getElementById("row").innerHTML = resulthtml;
Because that overwrites the old innerHTML of the #row. Instead, you can do:
document.getElementById("row").innerHTML += resulthtml;
That adds resulthtml to the innerHTML string returned, or use the method:
document.getElementById("row").appendChild(resulthtml);
That does the exactly same thing. It's really a matter of personal choice which one you'll use.
Cheers. Thought it was something small!
<script type="text/javascript">
function search() {
var xhr2 = new XMLHttpRequest();
xhr2.addEventListener ("load", view);
var reg = document.getElementById("type").value;
xhr2.open("GET", "getresults.php?type=" + reg);
xhr2.send();
}
function view(e, resulthtml) {
resulthtml = "";
var array = JSON.parse(e.target.responseText);
for (var count=0; count<array.length; count++)
{
var id = array[count].id;
var username = array[count].username;
var srcpath = array[count].srcpath;
var title = array[count].title;
var type = array[count].type;
var postcode = array[count]. postcode;
var description = array[count]. description;
var price = array[count].price;
var phone = array[count].phone;
var lat = array[count].lat;
var lon = array[count].lon;
resulthtml = resulthtml + "<div class='col-md-4'>"
+ "<div class='thumbnail'>"
+ "<img id='a' class='a' alt='300x200' src='" + srcpath + "'>"
+ "<div class='caption'>"
+ "<h3>"
+ description
+ "</h3>"
+ "<p>"
+ "£" + price + ""
+ "</p>"
+ "<p>"
+ "Contact number:"
+ "</p>"
+ "<p>"
+ "<input type='submit' value='Contact seller' onclick='search()'/>"
+ "</p>"
+ "</div>"
+ "</div>"
+ "</div>"
}
document.getElementById("row").innerHTML = resulthtml;
}
</script>
I am working on preparing some dynamic html with jquery and json object. but the problem is that when my json object has around 1500 rows it takes ages to load.
is there a way to load the thing faster.
Some code.
$(jQuery.each(jsonObject.AvailableColumns, function (i, l) {
if (type == "manual") {
innerList1 += '<li newText="" valueFormat="' + l.ValueFormat + '" scaleID="' + l.ScaleID + '" scaleType="' + l.ScaleType + '" hasWeights="' + l.HasWeights + '" customColumnType="' + l.CustomColumnType + '" class="" id="li_' + controlId + '"><span id="span_' + controlId + '" title = "' + l.QuestionText + '">' + getDisplayString(l.QuestionText) + '</span><a class="actionLeft"></a></li>';
}
else if (type = "exportall") {
innerList2 += CreateLiWithSpans('li_' + controlId, l.QuestionText, true, false, l.ScaleID, l.ScaleType, l.HasWeights, l.CustomColumnType, l.ValueFormat);
}
controlId++;
}));
$("#itemList").html(innerlist1);
EDIT : createliwithspan method
function CreateLiWithSpans(id, html, isLeft, isAddAll, scaleID, scaleType, hasWeights, customColumnType, valueFormat, newText) {
var ancClass = isLeft ? 'actionRight' : 'actionLeft';
var liObject = "";
if (newText == null) {
newText = "";
}
if (isLeft) {
liObject = '<li newtext="' + newText + '" valueFormat="' + valueFormat + '" scaleID="' + scaleID + '" scaleType="' + scaleType + '" hasWeights="' + hasWeights + '" customColumnType="' + customColumnType + '" class="" id="' + id + '"><span id="span_' + id + '" title = "' + html + '">' + getDisplayString(html) + '</span><span style="margin:0 10px 0 20px;pagging:0"><input title = "' + (newText == "" ? html : newText) + '" type="text" id="' + id + 'displayText" value="' + (newText == "" ? html : newText) + '" /><span style="color:Red; width:100%;" id="' + id + 'displayTextError"></span></span><span style="float:left">' + CreateDropDown('ddl_' + id, valueFormat, hasWeights) + '</span><a class="' + ancClass + '"></a></li>';
}
else {
liObject = '<li newtext="' + newText + '" valueFormat="' + valueFormat + '" scaleID="' + scaleID + '" scaleType="' + scaleType + '" hasWeights="' + hasWeights + '" customColumnType="' + customColumnType + '" class="" id="' + id + '"><span id="span_' + id + '" title = "' + html + '">' + getDisplayString(html) + '</span><a class="' + ancClass + '"></a></li>';
}
return liObject;
}
You can use for loop instead of jQuery.each, that will be faster. Store the itemCount before the loop, and use that:
itemCount = jsonData.items.length;
for(var i = 0; i < itemCount; i++ ) {
...
You can also use use an array instead of string concatenation, like so:
var innerList = [];
... // inside the loop
innerList.push(CreateLiWithSpans('li_' + controlId, l.QuestionText, true, false, l.ScaleID, l.ScaleType, l.HasWeights, l.CustomColumnType, l.ValueFormat));
... // after the loop
$("#itemList").html(innerList.join(''));
This will be faster in IE, I'm not sure about other js engines.
These two methods will not make a significant difference, so you should try implementing a client side pagination from json. (Not by hiding and showing divs, by rendering only visible page into the DOM).
Instead of waiting for the loop to end to append your data, why not actively append the data as you process it. This will allow the user to get immediate feedback instead of waiting for the whole thing to process. Other than this, I'd stick with my original comment to page the data.
$(jQuery.each(jsonObject.AvailableColumns, function (i, l) {
if (type == "manual") {
$("#itemList").append( '<li newText="" valueFormat="' + l.ValueFormat + '" scaleID="' + l.ScaleID + '" scaleType="' + l.ScaleType + '" hasWeights="' + l.HasWeights + '" customColumnType="' + l.CustomColumnType + '" class="" id="li_' + controlId + '"><span id="span_' + controlId + '" title = "' + l.QuestionText + '">' + getDisplayString(l.QuestionText) + '</span><a class="actionLeft"></a></li>');
}
else if (type = "exportall") {
$("#itemList2").append(CreateLiWithSpans('li_' + controlId, l.QuestionText, true, false, l.ScaleID, l.ScaleType, l.HasWeights, l.CustomColumnType, l.ValueFormat));
}
controlId++;
}));
Try replacing jQuery.each with a plain old for...in loop. Using jQuery.each adds overhead that you don't need.
Don't concatenate strings inside your loop. Instead, .push them onto an array variable and use .join('') to build the string all at once at the end.
You may need to eliminate CreateLiWithSpans as a separate function in order to fully implement (2).
Changing from using jQuery.each to a standard javascript for loop should speed it up a bit. Make sure that you save the length to a variable like this though:
for(var i = 0, len = jsonObject.AvailableColumns.length; i < len; i++){
var l = jsonObject.AvailableColumns[i];
// Continue with rest of code
}
Probably won't be a huge increase but every little helps.
Also try lowering the number of function calls you make as these have added overhead (not usually an issue, but in a large loop it can help). Unless the code is shared between functions try doing it inline and see how much that speeds it up.