localStorage clearing when I use split() - javascript

I want to create an array of names based on localStorage variable called "names". I use the String.split() to detect a new line which seems to work well, but not if I refresh the page more than once.
var names = localStorage.names;
if (!names) {
textArea.style.display = "block";
mybutton.style.display = "block";
} else {
textSplit = localStorage.names.split(/\n/);
copyInput1.innerHTML = textSplit[0];
copyInput2.innerHTML = textSplit[1];
copyInput3.innerHTML = textSplit[2];
}
document.getElementById("textArea").focus();
var showText = function() {
var text = textArea.value;
localStorage.names = text;
textSplit = localStorage.names.split(/\n/);
copyInput1.innerHTML = textSplit[0];
copyInput2.innerHTML = textSplit[1];
copyInput3.innerHTML = textSplit[2];
}
mybutton.onclick = showText;
clearbutton.onclick = localStorage.clear();
Any help appreciated.

You are executing clear() on localStorage which explains why it clears:
clearbutton.onclick = localStorage.clear();
Change this to:
clearbutton.onclick = localStorage.clear;
This way you're referencing the function instead.

Related

How to use localStorage to cache button result?

I have a button that I am making completely out of JS.
I want to save whether it was in a true or false state so that if a user leaves the page the button will be in the same state when they return. I'd like to use localStorage but I'm relatively new to JS so they may be a better solution.
Current Code:
var btn;
var btn = document.createElement("BUTTON");
btn.onclick = function() {myFunction()};
btn.style.height = "100%";
btn.style.width = "98%";
btn.style.border = "0px";
btn.innerHTML = "CLICK ME";
btn.id = "toggle";
document.getElementById("button").appendChild(btn);
function myFunction() {
document.getElementById('notepad').classList.toggle('hide'); return false
}
Edit Code:
window.onload = function initBt(){
var buttonState = localStorage.getItem('mybutton');
if ( null !== buttonState )
{
buttonState && document.getElementById('notepad').classList.add('hide');
}
}
var btn;
var btn = document.createElement("BUTTON");
btn.onclick = function() {myFunction()};
btn.style.height = "100%";
btn.style.width = "98%";
btn.style.border = "0px";
btn.innerHTML = "CLICK ME";
btn.id = "toggle";
document.getElementById("button").appendChild(btn);
function myFunction() {
var bt = document.getElementById('notepad');
bt.classList.toggle('hide');
localStorage.setItem('mybutton', bt.classList.contains('hide'))
return false;
}
you can use following functions in youir code to store and retrieve the button state:
localStorage documentation
function store(key, data)
{
localStorage.setItem(key, JSON.stringify(data));
}
function retrieve(key)
{
var data = localStorage.getItem(key);
return data ? JSON.parse(data) : null;
}
function remove(key)
{
localStorage.removeItem(key);
}
usage examples:
store('mybutton', buttonState);
var buttonState = retrieve('mybutton');
if ( buttonState !== null )
{
/* set button State*/
}
else
{
/* state has not been saved before, initialise */
}
NOTE since localStorage can handle ONLY string values, we use JSON.stringify when saving to make a string out of data and JSON.parse when retrieving in order to store and retrieve arbitrary data (that are of course JSON valid structures)
For your updated question try the following (it would be more helpfull if the whole html structure was added since some elements are missing, but anyway):
// include the needed localStorage manipulation methods
function store(key, data)
{
localStorage.setItem(key, JSON.stringify(data));
}
function retrieve(key)
{
var data = localStorage.getItem(key);
return data ? JSON.parse(data) : null;
}
function remove(key)
{
localStorage.removeItem(key);
}
// create and initialise the button
var btn = document.createElement("BUTTON");
btn.onclick = function() {myFunction()};
btn.style.height = "100%";
btn.style.width = "98%";
btn.style.border = "0px";
btn.innerHTML = "CLICK ME";
btn.id = "toggle";
document.getElementById("button").appendChild(btn);
var buttonState = retrieve('mybutton');
// make sure at this point element with id="notepad" exists on page
if ( null !== buttonState )
{
buttonState && document.getElementById('notepad').classList.add('hide');
}
function myFunction() {
var bt = document.getElementById('notepad');
bt.classList.toggle('hide');
store('mybutton', bt.classList.contains('hide'));
return false;
}
For a flexible caching library for web/browser that can support a variety of storage mechanisms (and also support for server-side php and node.js) check Unicache (ps. I am the author)
There are of course other libraries as well (eg localForage)

Firebase: Using callback function to decide whether data is in the database

I am creating search bar, which shows results from database dynamically on keypress, when they match the string that is in the search bar. Also when the string doesn't match anything in my database, I want to show message to user, that nothing matches his input. Problem is that I don't know how to do this in javaScript. I tried using callback function, but my implementation doesn't work. It is my first time using callback function, so I guess something is not right. Can anybody help me?
Here is simplified code:
var bars = firebase.database().ref("bars").orderByChild("rating");
var types = firebase.database().ref("types");
var searcher = document.getElementById("searcher");
var results = document.getElementById("searchResults");
function search(){
var value = searcher.value.toUpperCase();
clearTimeout(timeout);
timeout = setTimeout(function () {
if(value == null || value == ""){
results.style.display = "none";
} else{
results.innerHTML = "";
//callback function here
function findResults(callback) {
types.once("value").then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var type = childSnapshot.key;
if(type.toUpperCase().startsWith(value)){
results.style.display = "block";
var typeItem = createDiv("result-item");
typeItem.innerHTML = type;
results.append(typeItem);
}
callback(true);
});
});
bars.once("value").then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var bar = childSnapshot.key;
if(bar.toUpperCase().startsWith(value)){
results.style.display = "block";
var barItem = createDiv("result-item");
barItem.innerHTML = type;
results.append(barItem);
}
callback(true);
});
});
}
//This needs to work, when callback didn't return true
findResults(function(callback){
if(!callback){
var empty = createDiv("emptyResult");
empty.innerHTML = "No matching results";
results.appendChild(empty);
results.style.display = "block";
}
});
}
}, 400);
}
function createDiv(name){
var div = document.createElement("div");
div.className = name;
return div;
1.Let me start by pointing out that querying the Firebase Database on Keypress can be very expensive, since you'll be downloading data more frequently and Firebase has a price on data downloaded. I recommend querying the database when the user presses Enter or a Search Button.
2.I don't see why you need a callback function for this. You can use plain functions to achieve that. Like this:
function search(){
var value = searcher.value.toUpperCase();
clearTimeout(timeout);
timeout = setTimeout(function () {
if(value == null || value == ""){
results.style.display = "none";
} else{
results.innerHTML = "";
types.once("value").then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var type = childSnapshot.key;
var foundUnderTypes = false;
if(type.toUpperCase().startsWith(value)){
results.style.display = "block";
var typeItem = createDiv("result-item");
typeItem.innerHTML = type;
results.append(typeItem);
foundUnderTypes = true;
}
bars.once("value").then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var bar = childSnapshot.key;
if(bar.toUpperCase().startsWith(value)){
results.style.display = "block";
var barItem = createDiv("result-item");
barItem.innerHTML = type;
results.append(barItem);
}
else{
if(!foundUnderTypes)
emptyResult();
}
});
});
});
});
}
}, 400);
}
function emptyResult(){
var empty = createDiv("emptyResult");
empty.innerHTML = "No matching results";
results.appendChild(empty);
results.style.display = "block";
}

Set innerHTML of box to element of one of multiple arrays

I'm trying to create a website (for fun) that will be an Ultimate Frisbee strategy tutorial (unimportant, but if you were curious, that's what it'll be).
I want the user to be able to select a topic, and then I will be using jQuery to create a moving diagram of a field, but for now, I am trying to have multiple JavaScript arrays, and when the user hits the button "Next", a < p > tag's innerHTML will change to an element of that array.
However, I want to be able to use only one function in order to cycle through any possible array of instructions. If this made any sense, I'm impressed. If you do know what I mean and have any ideas, please tell me. Here's the code below. It all works except for currentNumber, or much more likely currentArray.
var basicManGuide = new Array();
basicManGuide[0] = "First, we will look at the handlers. The handlers are the two people who will typically have the disc.";
basicManGuide[1] = "Volvo";
basicManGuide[2] = "BMW";
var currentNum = 0;
document.getElementById("basicMan").onclick = function() {
var currentArray = basicManGuide.slice();
document.getElementById("menuStuff").style.display = "none";
document.getElementById("buttons").style.display = "block";
document.getElementById("players").style.display = "block";
document.getElementById("description").innerHTML = currentArray[currentNum];
++currentNum;
}
document.getElementById("cancel").onclick = function() {
document.getElementById("menuStuff").style.display = "inline";
document.getElementById("buttons").style.display = "none";
document.getElementById("players").style.display = "none";
}
document.getElementById("next").onclick = function() {
document.getElementById("description").innerHTML = currentArray[currentNum];
++currentNum;
}
currentArray is only in the click handler for basicMan (local scoped). Move that variable outside of the click handler for it to be available to the other events as a global variable.
Obviously, there other areas that need to be addressed, but this should answer your question. (E.g., why slice the array when you are not passing in indices to slice?)
var basicManGuide = new Array();
basicManGuide[0] = "First, we will look at the handlers. The handlers are the two people who will typically have the disc.";
basicManGuide[1] = "Volvo";
basicManGuide[2] = "BMW";
var currentNum = 0;
var currentArray = basicManGuide.slice(); // <-- this was moved.
document.getElementById("basicMan").onclick = function() {
document.getElementById("menuStuff").style.display = "none";
document.getElementById("buttons").style.display = "block";
document.getElementById("players").style.display = "block";
document.getElementById("description").innerHTML = currentArray[currentNum];
++currentNum;
}
document.getElementById("cancel").onclick = function() {
document.getElementById("menuStuff").style.display = "inline";
document.getElementById("buttons").style.display = "none";
document.getElementById("players").style.display = "none";
}
document.getElementById("next").onclick = function() {
document.getElementById("description").innerHTML = currentArray[currentNum];
++currentNum;
}

Need help passing a single array value to an attached function on a dynamically created element

I'm having trouble putting an array's value into the function call of an added event on a dynamically created element.
So here's the hard-coded version that works just fine:
var parent_item = document.getElementById("developers_container");
var part = document.createElement('div');
part.id = "developer_A";
part.name = "developer_A";
part.className = "developer_block_un";
part.onmouseover = function() { hilight_dev('A',true)};
part.onmouseout = function() { hilight_dev('A',false)};
parent_item.appendChild(part);
var parent_item = document.getElementById("developer_A");
var part = document.createElement('span');
part.id = "developer_title_A";
part.name = "developer_title_A";
part.className = "developer_un";
part.innerHTML = "John Doe";
part.onclick = function() { select_dev('A')};
parent_item.appendChild(part);
Basically what this does is create a listing of users for selecting. Each user's listing has mouseover, mouseoff and onclick events. The meat of the above code is currently being duplicated for every user.
I want to replace the duplication with an array-based function:
var dev_id = new Array();
var dev_fn = new Array();
var dev_ln = new Array();
document.getElementById("developers_container").innerHTML = "";
dev_id[0] = "A";
dev_fn[0] = "John";
dev_ln[0] = "Doe";
dev_id[1] = "B";
dev_fn[1] = "John";
dev_ln[1] = "Smith";
dev_id[2] = "C";
dev_fn[2] = "John";
dev_ln[2] = "Jones";
dev_id[3] = "D";
dev_fn[3] = "John";
dev_ln[3] = "Yougetthepoint";
document.getElementById("developers_container").innerHTML = "";
for(var i = 0; i < dev_id.length; i++)
{
var parent_item = document.getElementById("developers_container");
var part = document.createElement('div');
part.id = "developer_"+dev_id[i];
part.name = "developer_"+dev_id[i];
part.className = "developer_block_un";
part.onmouseover = function() { hilight_dev(dev_id[i],true)};
part.onmouseout = function() { hilight_dev(dev_id[i],false)};
parent_item.appendChild(part);
var parent_item = document.getElementById("developer_"+dev_id[i]);
var part = document.createElement('span');
part.id = "developer_title_"+dev_id[i];
part.name = "developer_title_"+dev_id[i];
part.className = "developer_un";
part.innerHTML = dev_fn[i]+"<BR>"+dev_ln[i];
part.onclick = function() { select_dev(dev_id[i])};
parent_item.appendChild(part);
}
Every bit of that is working just fine, save for the added events. Where "dev_id[i]" is being used within the function code (as in "part.onmouseover = function() { hilight_dev(dev_id[i],true)};"), it doesn't seem to be doing anything. The event fires off and the function is called, but the variable that's being passed is coming through as "undefined" instead of that user's id like it should be.
I'm hoping someone here knows how to get this to work. Googling was not very helpful, and this is one of those silly little issues that's cost me half a day trying to figure out. Any and all help is greatly appreciated.
Thanks
part.onmouseover = function(i) {
return function() { hilight_dev(dev_id[i],true) }
}(i)
The variable i that you have in the loop is undefined at the time the function is invoked, you need to form a closure over it in order to keep it's value. Please refer to "JavaScript, the Good Parts" by Douglas Crockford for a detailed explanation on this
Err.. after Neil's comment.. yes.. i is not undefined.. it will always be the length of dev_id.. in any case, it's not what the op wants :)

Javascript event doesn't seem to get added to a dynamically generated textbox

I added onkeyup javascript for a dynamically added textbox in javascript... But it doesnt seem to work....
var cell4 = row.insertCell(3);
cell4.setAttribute('align','center')
var e3 = document.createElement('input');
e3.type = 'text';
e3.name = 'txtqt' + iteration;
e3.id = 'txtqt' + iteration;
e3.onkeyup = totalAmount(event,this,'tblsample');//Adding this lines doesnt work
e3.size = 10;
cell4.appendChild(e3);
But when i used
e3.onkeyup = totalAmount;
It worked... Here is my javascript function,
function totalAmount(e,obj,tblid)
{
var tbl = document.getElementById(tblid);
//alert(tbl);
var tblRows = tbl.rows.length;
//alert(tblRows);
var result =0;
var str1;
if (obj != null) {
str1 = obj.id;
} else {
str1 = this.id;
}
var lastChar = str1.substring(5,str1.length);
//alert(lastChar);
if(str1=='txtqt'+lastChar)
{
var str2 = 'txtup'+lastChar;
var str3 = 'txtAmount'+lastChar;
var txtDeduct = document.getElementById(str1).value;
var txtAmt = document.getElementById(str2).value;
var txtTotal = document.getElementById(str3);
var totRes = txtAmt*txtDeduct;
//var res = formatNumber(totRes,2)
txtTotal.value = totRes.toFixed(2)
document.getElementById('txttotAmount').value = totRes.toFixed(2);
for(i=1;i<=tblRows;i++)
{
//alert(tblRows);
txtTotID = 'txtAmount'+i;
if(document.getElementById(txtTotID).value!='')
{
result =parseFloat(result) + parseFloat(document.getElementById(txtTotID).value);
//var res= formatNumber(result,2)
document.getElementById('txtTotalAmount').value = result.toFixed(2);
document.getElementById('txttotAmount').value = result.toFixed(2);
//document.getElementById('txtTotalAmount').value = result;
}
}
}
}
You need to wrap your function call in an anonymous function:
e3.onkeyup = function(event){ totalAmount(event,this,'tblsample'); }
But an even better way to do it, to allow for cross browser compatibility would be to use an addEvent function:
function addEvent(obj,type,fn){
if (obj.addEventListener){
obj.addEventListener(type,fn,false);
} else if(obj.attachEvent){
obj["e"+type+fn]=fn;
obj[type+fn]=function(){
obj["e"+type+fn](window.event);
};
obj.attachEvent("on"+type,obj[type+fn]);
};
};
And then add the event using that function:
addEvent(e3,'keyup',function(event){ totalAmount(event,this,'tblsample'); });
Just a much better way to handle events. I would recommend you switch to this method.
onkeyup is a function. If you pass it the return value of totalAmount(event,this,'tblsample'); it won't work (unless it returns a function).
e3.onkeyup = totalAmount; is probably enough.
then inside totalAmount..
function totalAmount(event) {
alert(this); // this is the e3 object
}
So if you need the this and the 'tblsample' arguments, I suggest you add them to the e3 object so that you can access them through the this keyword inside the totalAmount function:
e3.otherScope = this;
e3.tblid = 'tblsample;
e3.onkeyup = totalAmount;
and..
function totalAmount(event) {
alert(this); // this is the e3 object
alert(this.otherScope); // the `this` object in the other scope
alert(this.tblid); // 'tblsample'
}
Or you can simply just do
var otherScope = this;
e3.onkeyup = function(event) {
totalAmount(event, otherSope, 'tblsample');
};

Categories