Unable to properly add value to a cell using GAS - javascript

I adopted the script below and I am having two issues.
The "Email Sent" value does not update in the correct row. Let's say I sent an email to the recipient in row 5, instead of appearing in column 10 of row 5 "Email Sent" appears in column 10 of row 21.
Sometimes "Email Sent" does not appear at all even though I know the email went out.
I've tried everything I can think of but I can't make it work.
//Send approval or non-approval of time off request
function sendLeaveRequestDecisions() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Form Responses 2");
var dataRange = sheet.getRange(2,1,sheet.getLastRow()-1,sheet.getLastColumn());
var data = dataRange.getValues();
for (i in data) {
var startRow = 2; //First row of data to process
var rowData = data [i];
var startdate = rowData [2];
var enddate = rowData [3];
var type = rowData [4];
var email = rowData [5];
var recipient = rowData [1];
var decision = rowData [7];
var comments = rowData [8];
var emailstatus = rowData [9]
var emailPattern = /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}|aero|asia|biz|com|coop|edu|gov|info|int|jobs|mil|mobi|name|museum|name|net|org|pro|tel|travel)\b/;
var validEmailAddress = emailPattern.test(email);
if (validEmailAddress == true && emailstatus != "Email Sent") {
var message = "<HTML><BODY>"
+ "<P>Dear " + recipient + ","
+ "<br /><br />"
+ "<P>The following request:"
+ "<br /><br />"
+ "<b>Type: </b>" + type + "<br />"
+ "<b>From: </b>" + startdate + "<br />"
+ "<b>To: </b>" + enddate + "<br />"
+ "<br /><br />"
+ "<b>is </b>" + decision + "<br />"
+ "<b>Comments </b>" + comments + "<br />"
+ "<br /><br />"
+ "Diane"
+ "<br /><br />"
+ "</HTML></BODY>";
MailApp.sendEmail(email, "Regarding your leave request", "", {htmlBody: message});
sheet.getRange(i + 2,10).setValue("Email Sent");
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}

Try this:
Mostly what was wrong was that you didn't escape the forward slashes contained in your regex expression. I'm surprised it ran at all. It runs okay for me. You might like to take a look at Utilities.formatString() for building your message. Just click on Help/API Reference. From there it's down at the bottom left where it says Script Service/Utilities.
Personally, I wouldn't put flush in a loop like that. I moved startRow and emailPattern out of the loop as well. They don't change. The less you put in a loop the faster it runs. I commented out the MailApp.sendmail because I didn't actually want to send email and I assume that you got that right.
function sendLeaveRequestDecisions() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Index Generation");
var dataRange = sheet.getRange(2,1,sheet.getLastRow()-1,sheet.getLastColumn());
var data = dataRange.getValues();
var startRow = 2; //First row of data to process
var emailPattern = /^[a-z0-9!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}|aero|asia|biz|com|coop|edu|gov|info|int|jobs|mil|mobi|name|museum|name|net|org|pro|tel|travel)\b/;
for (var i=0;i<data.length;i++){
var rowData = data [i];
var startdate = rowData[2];
var enddate = rowData[3];
var type = rowData[4];
var email = rowData[5];
var recipient = rowData[1];
var decision = rowData[7];
var comments = rowData[8];
var emailstatus = rowData[9];
var validEmailAddress = emailPattern.test(email);
if (validEmailAddress == true && emailstatus != "Email Sent") {
var message = "<HTML><BODY>" + "<P>Dear " + recipient + "," + "<br /><br />" + "<P>The following request:" + "<br /><br />" + "<b>Type: </b>" + type + "<br />" + "<b>From: </b>" + startdate + "<br />" + "<b>To: </b>" + enddate + "<br />" + "<br /><br />" + "<b>is </b>" + decision + "<br />" + "<b>Comments </b>" + comments + "<br />"+ "<br /><br />" + "Diane"+ "<br /><br />" + "</HTML></BODY>";
//MailApp.sendEmail(email, "Regarding your leave request", "", {htmlBody: message});
sheet.getRange(i + 2,10).setValue("Email Sent");
}
}
//SpreadsheetApp.flush();
}

I did something similar but quite differently and I've personally found this kind of response unhelpful in the past so do tell me to leave it alone if you feel like that.
If you would like me to try writing something though, which you and others could run, I will do that. My example of doing this is as personal - even more so - than yours.

Related

How can I loop into the objects of a DTO in Ajax?

I'm trying to GET all players from a list, but the whole GetMapping it's constructed around Player DTO. The data I want to loop is a list of "players" stored into a DTO like this:
{
PLAYERS: [
{ player0 {parameters...} },
{ player1 {parameters...} },
...
]
}
Here is my ajax code in JS:
//GET ALL PLAYERS
function getAllPlayers() {
document.getElementById("erase_repeated_results").innerHTML = ""; //to erase info I don't want to store
document.getElementById("fullInfo").innerHTML = "";
document.getElementById("data").innerHTML = "";
document.getElementById("sameRoles").innerHTML = "";
$.ajax({
type: "GET",
url: "http://localhost:8081/dices/players",
contentType: "application/json",
dataType: "json",
success: function (data) {
for (var j = 0; j < data.length; j++) {
document.getElementById("fullInfo").innerHTML += "Complete info of player " + (j+1) + ": " + "<br />" + "<br />" +
"The ID of this player is: " + data[j].id + "<br />" +
"The name of this player is: " + data[j].name + "<br />" +
"The register date of this player is: " + data[j].registerDate + "<br />" +
"The total amount of dice rolls of this player is: " + data[j].totalDiceRolls + "<br />" +
"The total amount of games won of this player is: " + data[j].gamesWon + "<br />" +
"The success rate of this player is: " + data[j].successRate + "<br />";
console.log(data[j]);
}
},
error: function () {
alert("Something went wrong! Maybe you are entering parameters not related to our Database!");
}
});
}
Below I attached a screenshot so you can see how it is working while I debug it, and you'll see in the scope section what I'm talking about.
How can I enter only in the array parameter of the DTO?
In your data structure, it's the PLAYERS property which is an array. data is an object containing a single property called PLAYERS. So looping through that makes no sense. Just loop through the players array instead:
for (var j = 0; j < data.PLAYERS.length; j++) {
document.getElementById("fullInfo").innerHTML += "Complete info of player " + (j+1) + ": " + "<br />" + "<br />" +
"The ID of this player is: " + data.PLAYERS[j].id + "<br />" +
"The name of this player is: " + data.PLAYERS[j].name + "<br />" +
"The register date of this player is: " + data.PLAYERS[j].registerDate + "<br />" +
"The total amount of dice rolls of this player is: " + data.PLAYERS[j].totalDiceRolls + "<br />" +
"The total amount of games won of this player is: " + data.PLAYERS[j].gamesWon + "<br />" +
"The success rate of this player is: " + data.PLAYERS[j].successRate + "<br />";
console.log(data.PLAYERS[j]);
}

Text input value is returning undefined without any error

I want to make alert message show the data of the form I input.But the text element's data doesn't work correctly.
<script type="text/javascript">
function showUserData(){
category = document.getElementById("category").value;
regicon = "";
var obj=document.getElementsByName("register");
for(idx in obj){
if(obj[idx].checked){
regicon += obj[idx].value;
}
}
title = document.getElementById("title").value;//here is the problem
author = document.getElementById("author").value;
email = document.getElementById("email").value;
content = document.getElementById("content").value;
password = document.getElementById("password").value;
coverdate = document.getElementById("coverdate").value;
contentimage = document.getElementById("contentimage").value;//
time_result = new Date();//기사등록일은 date()
window.alert("카테고리: "+category + "\n"
+ "등록상태: " + regicon + "\n"
+ "제목: " + title + "\n"
+ "이메일: " + email + "\n"
+ "기자: " + author + "\n"
+ "내용: " + content + "\n"
+ "취재일: " + coverdate + "\n"
+ "기사등록일: " + time_result + "\n");
}
</script>
When I run the code, the alert show 'undefined' at the title value.
I thought that the title value doesn't initialized so I tried
title = "";
It was not the solution.How can I make the function run correctly
Have you created a titlevariable? It seems to me you forgot to put "var" or "const" before the title variable.

Run 2 functions inside a master function

I'm a beginner, sorry if my code might look a bit messy.
I'm trying to write a function to send an email to a specific email address whenever a cell in a column is equal to send_email. The email body needs to include data from the row with the cell equal to send_email.
This is my code:
function warnStatusBeginDay() {
// This function imports house data, every day, between 0am and 1am, and sends an email if the time left to answer the 'acta de observacion' is 3 or 7 days from the deadline
//Check when to send email
var checkValues = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('service_1_2_main').getRange('V2:AQ').getValues();
for (var i in checkValues) {
if (checkValues[i][4] === 'send_email') {
//Send email notification
function sendMail_7() {
// Build email body
var email_head = "https://i.imgur.com/aaa.jpg";
var house_id = checkValues[i][10];
var project = checkValues[i][7];
var name = checkValues[i][14];
var address = checkValues[i][19];
var neigh = checkValues[i][21];
var municipality = checkValues[i][17];
var country = checkValues[i][18];
var acta_date = Utilities.formatDate(checkValues[i][13],"GMT-0500","d MMM yyyy");
var acta_date_limit = Utilities.formatDate(checkValues[i][12],"GMT-0500","EEE, d MMM yyyy");
var record_id = checkValues[i][11];
var lat = checkValues[i][8];
var lng = checkValues[i][9];
var imageURL = checkValues[i][20];
var mapURL = "http://maps.googleapis.com/maps/api/staticmap?center="+lat+","+lng+"&zoom=15&size=300x300&maptype=hybrid&markers=color:red%7C"+lat+","+lng+"&key=myKey";
var mapURL2 = "https://www.google.com/maps/search/?api=1&query="+lat+","+lng;
var body = "<p>" +
"<p><img src='" + email_head + "' width='269' height='70' alt='Build Change - Sistema de notificación'></p>" +
"<i>[Este es un mensaje automatizado, por favor no responda a este correo]</i>" + "<br>" + "<br>" +
"La vivienda a continuación recibió una acta de observación el " + acta_date + ". El plazo limite para responder al acta vence en <b>7 días</b> desde hoy." + "<br>" + "<br>" +
"<b>Código ID vivienda: </b>" + house_id + "<br>" +
"<b>Proyecto: </b>" + project + "<br>" +
"<b>Nombre y apellido propietario: </b>" + name + "<br>" +
"<b>Fecha vencimiento acta de observación: </b>" + acta_date_limit + "<br>" + "<br>" +
"<b>Código ID Fulcrum: </b>" + record_id + "<br>" +
"<b>Latitud y longitud: </b>" + lat + ", " + lng + "<br>" +
"<b>Barrio/Comuna/Localidad/Sector: </b>" + neigh + "<br>" +
"<b>Dirección: </b>" + address + "<br>" +
"<b>Municipalidad: </b>" + municipality + "<br>" +
"<b>País: </b>" + country + "<br>" +
"<p><a href='https://web.fulcrumapp.com/records/" + record_id + "' title='Open in Fulcrum'><img src='" + mapURL + "'></a>" + " " + "<img src='" + imageURL + "' height='300 alt='Imagén fachada vivienda'></p>" +
"</p>";
// Send email
MailApp.sendEmail({
to: "myemail.dev#gmail.com",
subject: house_id + " - Acta de observación en vencimiento (7 días restantes)",
htmlBody: body
});
}
sendMail_7();
}
else {
continue;
}
}
SpreadsheetApp.flush();
for (var j in checkValues) {
if (checkValues[j][6] === 'send_email') {
//Send email notification
function sendMail_3() {
// Build email body
var email_head = "https://i.imgur.com/aaa.jpg";
var house_id = checkValues[j][10];
var project = checkValues[j][7];
var name = checkValues[j][14];
var address = checkValues[j][19];
var neigh = checkValues[j][21];
var municipality = checkValues[j][17];
var country = checkValues[j][18];
var acta_date = Utilities.formatDate(checkValues[j][13],"GMT-0500","d MMM yyyy");
var acta_date_limit = Utilities.formatDate(checkValues[j][12],"GMT-0500","EEE, d MMM yyyy");
var record_id = checkValues[j][11];
var lat = checkValues[j][8];
var lng = checkValues[j][9];
var imageURL = checkValues[j][20];
var mapURL = "http://maps.googleapis.com/maps/api/staticmap?center="+lat+","+lng+"&zoom=15&size=300x300&maptype=hybrid&markers=color:red%7C"+lat+","+lng+"&key=myKey";
var mapURL2 = "https://www.google.com/maps/search/?api=1&query="+lat+","+lng;
var body = "<p>" +
"<p><img src='" + email_head + "' width='269' height='70' alt='Build Change - Sistema de notificación'></p>" +
"<i>[Este es un mensaje automatizado, por favor no responda a este correo]</i>" + "<br>" + "<br>" +
"La vivienda a continuación recibió una acta de observación el " + acta_date + ". El plazo limite para responder al acta vence en <b>3 días</b> desde hoy." + "<br>" + "<br>" +
"<b>Código ID vivienda: </b>" + house_id + "<br>" +
"<b>Proyecto: </b>" + project + "<br>" +
"<b>Nombre y apellido propietario: </b>" + name + "<br>" +
"<b>Fecha vencimiento acta de observación: </b>" + acta_date_limit + "<br>" + "<br>" +
"<b>Código ID Fulcrum: </b>" + record_id + "<br>" +
"<b>Latitud y longitud: </b>" + lat + ", " + lng + "<br>" +
"<b>Barrio/Comuna/Localidad/Sector: </b>" + neigh + "<br>" +
"<b>Dirección: </b>" + address + "<br>" +
"<b>Municipalidad: </b>" + municipality + "<br>" +
"<b>País: </b>" + country + "<br>" +
"<p><a href='https://web.fulcrumapp.com/records/" + record_id + "' title='Open in Fulcrum'><img src='" + mapURL + "'></a>" + " " + "<img src='" + imageURL + "' height='300 alt='Imagén fachada vivienda'></p>" +
"</p>";
// Send email
MailApp.sendEmail({
to: "myemail.dev#gmail.com",
subject: house_id + " - Acta de observación en vencimiento (3 días restantes)",
htmlBody: body
});
}
sendMail_3();
}
else {
return;
}
}
}
Basically, I'm building an array through get.Values and then checking:
which row of the fifth column in the array is equal to send_email (checkValues[i][4] === 'send_email') and then send as many emails as the number of cells equal to send_email in the fifth column of the array, thanks to the function sendMail_7.
which row of the sevent column in the array is equal to send_email (checkValues[j][6] === 'send_email') and then send as many emails as the number of cells equal to send_email in the seventh column of the array, thanks to the function sendMail_3.
The function sendMail_7 works perfectly but I can't understand way the second part of the script, starting from for (var j in checkValues) {... is not working.
Actually the last curly bracket of the script is highlighted in red, so I think something is wrong but I don't know what.
I also tried to place the 2 functions to send emails, sendMail_7 and sendMail_3, outside of the main function warnStatusBeginDay. In this case the last curly bracket of the main function warnStatusBeginDay is green but in this way the variables defined in the email body (i.e. var name = checkValues[i][14] or var municipality = checkValues[i][17]) are not working.
I'm not sure if my explanation was clear but it's my first time with Google App Scripts/javascripts in general I'm a beginner in coding.
Any suggestion?
Thanks a lot,
Stefano
If your first j does not fulfill equation in (checkValues[j][6] === 'send_email') then you go out from the loop because of else{ return; }

Issue appending newly changed variable and outputting with Javascript

I have an issue with the following code.
I am trying to change the content of a variable if a button is clicked and then output the corresponding content as part of a larger output. The output varies depending on if the inner button within the form is clicked.
Can anyone suggest a fix for this code or improvements?
In the output I should see a longer version as the extra block would be appended on to the newly created block and grab new id values generated. Any help would be great.
Here is my code:
<script>
$(document).ready(function() {
var currentID = 1;
$(':button#add').on('click',function() {
currentID++;
var clone = $('#content').clone();
clone.children('.content_title').attr('id', 'title_content-' + currentID);
clone.children('.content_more').attr('id', 'more_content-' + currentID);
clone.attr("id", "content_1");
clone.insertAfter('#content');
if(currentID >= 2) {
document.getElementById("add").style.display = "none";
}
});
});
</script>
</head>
<body>
<div>
<div>
<form action="" method="post">
<h1>Create Code</h1>
<fieldset>
<legend><span class="number"></span>Header</legend>
<label for="name">Title:</label>
<input type = "text" id = "title" />
</fieldset>
<fieldset id = "content">
<legend><span class="number"></span>Content</legend>
<label for="name">Title:</label>
<input class = "content_title" type = "text" id = "title_content" />
<label for="mail">Content:</label>
<input class = "content_more" type = "text" id = "more_content" />
</fieldset>
<input id = "add" type = "button" value = "Add" /> </form>
<button onClick="tryTest()">Code</button>
</div>
<div style = "float:left; width:48%; padding-left:10px;">
<p id="new_block"></p>
</div>
</div>
<script>
function tryTest() {
var quote = '"';
var start = "<pre><div class=" + quote + "newest" + quote + "></pre>";
var title = "title=" + quote + document.getElementById("title").value + quote;
var end = "<pre></div></pre>";
var start_1 = "{{widget type=" + quote + "new_version" + quote;
var title_1 = "title=" + quote + document.getElementById("title_content").value + quote;
var content_1 = "content=" + quote + document.getElementById("more_content").value + quote;
var end_1 = "template=" + quote + "other" + quote + "}}";
var title_2 = "title=" + quote + document.getElementById("title_content-2").value + quote;
var content_2 = "content=" + quote + document.getElementById("more_content-2").value + quote;
var widget = start_1 + "<br />" + title_1 + "<br />" + content_1 + "<br />" + end_1;
var widget_1 = start_1 + "<br />" + title_1 + "<br />" + content_1 + "<br />" + end_1 + start_1 + "<br />" + title_2 + "<br />" + content_2 + "<br />" + end_1;
if(add.clicked == false) {
document.getElementById("new_block").innerHTML = start + "<br />" + title + "<br />" + end + "<br /><br />" widget + "<br /><br />";
} else {
document.getElementById("new_block").innerHTML = start + "<br />" + title + "<br />" + end + "<br /><br />" widget_1 + "<br /><br />"";
}
</script>
This code is a strange mix of jQuery and vanilla JavaScript syntaxes...
But it would work if there was no parse error.
Those error were quite easy to find in a code editor like CodePen, by the way.
if(add.clicked == false) {
document.getElementById("new_block").innerHTML = start + "<br />" + title + "<br />" + end + "<br /><br />" + widget + "<br /><br />";
// Added a missing + sign ---> ---> ---> ---> here -------^
} else {
document.getElementById("new_block").innerHTML = start + "<br />" + title + "<br />" + end + "<br /><br />" + widget_1 + "<br /><br />";
// Added a missing + sign ---> ---> ---> ---> here -------^
}
} // Added this curly bracket to close the tryTest() function.
Just above this code block, is a condition to choose which string to append to new_block.
The if(add.clicked == false) { condition always evaluates to false, because add is not defined. So the property .clicked of undefined, obviously also is undefined...
Then "undefined" == false is false... And makes the else block to always execute.
This condition fixed will avoid the Cannot read property 'value' of null error on "Code" click if the "Add" has not been clicked.
There is a couple ways to determine if the "Add" button has been clicked.
Check if the element title_content-2 exist
Use a boolean "flag" turned to true on "add" click
Adding a class to the "Add" button on click
I will let you think about the solution you would prefer and try it.
Here is your code freed of the mentionned syntax errors in CodePen.

retrieving last key in javascript localstorage

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/

Categories

Resources