Concatenation of variable and String wrong - javascript

I would like to pass an argument to another page but it turns out that it's undefined.
getAccount() returns a list of json. Firstly, I display those json objects one by one on HTML and when the user clicks each, the accDetail[i].accNo is set as local storage and will be passed to next page.
var accDetail=getAccounts();
for(var i =0;i<accDetail.length;i++) {
document.getElementById("demo").innerHTML+=''+accDetail[i].accNo +''+' '+ accDetail[i].accType+' '+ accDetail[i].balance+'<br>';
}
This is the function to set the item as local storage.
function getAcc(item)
{
localStorage.setItem("accNo",item); }
It does not display the value I want, is the way I concatenate it wrong?

Your onclick handler is going to be literally getAcc(accDetail[i].accNo) (try viewing in Inspect Element), which won't work because accDetail is not defined in the event handler. You need to change your Javascript so that it writes getAcc(0), getAcc(1), etc where 0, 1 are the different accNo.
Here is a small example I wrote, hopefully you can extend it to solve your problem:
var accNo = [1, 2, 3, 4];
for(var i = 0;i < accNo.length; i++) {
var line = '' + accNo[i] + ' <br>';
console.log(line);
document.getElementById("demo").innerHTML += line;
}

First Make sure your function getting correct value
Try Using window object instead
function getAcc(item)
{
localStorage.setItem("accNo",item);
}
Replace with
function getAcc(item)
{
console.log(item); //Please check you get item correct not undefined
window.accNo = item;
}
And whereever you want just use window.accNo

Related

I am trying to stop my function from displaying the same object twice when clicking a button

I have for quite some time now been trying to figure out how I can stop my code to print the same quote twice.
Also, when every single object in the array has been printed out, I'd like for it to reset somehow. So that you can browse through the quotes once you've gone through all of them.
This is the essential parts of my code:
document.getElementById('loadQuote').addEventListener("click", printQuote, false);
The printQuote function simply contains information that's accessing information from my array:
var randomObjectNumber = getRandomQuote();
var html = "<p class='quote'>"
+ quotes[randomObjectNumber].quote +
"</p>";
document.getElementById('quote-box').innerHTML = html;
One random object is displayed each time you click the eventListener:
function getRandomQuote () {
var randomObjectNumber = Math.floor(Math.random() * quotes.length );
return randomObjectNumber;
}
I have some ideas on how to do this and I have tried them but without success. I tried giving each object a boolean property but I can't really seem to assign each property a boolean value without messing the printQuote function up.
I also tried assigning the object displayed to a different array but the same problem occurred there.
I feel like there is some concepts around the eventListener that I don't fully understand, because every time I try to manipulate a displayed object I just end up changing every single object.
This is what a typical object in the array looks like by the way:
{quote : "Darkness is merely the absence of light"}
(I also have other properties assigned to the object but i feel like presenting them would be redundant)
If someone could explain, or give me a hint, on how to solve this problem I've been struggling with for some time.
Some hints would be greatly appreciated!
Have a nice day.
Sebastian.
EDIT: All code: https://jsfiddle.net/fusqb7hz/
Basically what you need:
Create a separate array that will store all quotes that you've already used.
Remove quote from initial array.
Check if you still have quotes in initial array, if not, get them back from backup array.
The problem is that you call addEventListener twice:
//Let's developers create multiple eventListeners without being redundant.
function onClicking (printFunction) {
document.getElementById('loadQuote').addEventListener("click", printFunction, false);
}
onClicking(printColor);
onClicking(printQuote);
by calling onClicking twice you make the click happen twice, so addEventListener is added twice, meaning one click counts as two.
Change the above code for this:
//Let's developers create multiple eventListeners without being redundant.
document.getElementById('loadQuote').addEventListener("click", function(){
printColor();
printQuote();
});
Here is the jsfiddle:
https://jsfiddle.net/fusqb7hz/3/
I think the easiest approach is to shuffle your quote array and then go through them one by one. This gives you the next "random" as yet unseen quote. The only part I'm not keen on is this shuffler (a derivation of Fisher Yates) modifies the original quote array. You might not care about that though.
// --------------------------------
// A bunch of quotes
// --------------------------------
var quotes = [];
quotes.push({quote : "Darkness is merely the absence of light"});
quotes.push({quote : "quote 2"});
quotes.push({quote : "quote 3"});
quotes.push({quote : "quote 4"});
quotes.push({quote : "quote 5"});
// --------------------------------
// --------------------------------
// Your favorite array shuffle utility
// --------------------------------
var shuffle = function(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
};
// --------------------------------
// --------------------------------
// construct a function to get a random unseen quote until
// all quotes have been seen. Then reset...
// --------------------------------
var getQuote = (function(quotes, shuffle){
var current = 0;
var get = function(){
if ( !quotes || !quotes.length ) { return ""; }
if ( current >= quotes.length ){ current = 0; }
if ( current === 0 ){
console.log("randomizing quotes...");
shuffle(quotes);
}
return quotes[current++].quote;
};
return get;
})(quotes, shuffle);
// --------------------------------
var printQuote = function(){
document.getElementById('quote').innerText = getQuote();
};
document.getElementById('loadQuote').addEventListener("click", printQuote, false);
<div id="quote"></div>
<button id="loadQuote">get quote</button>

How do I add elements to a dynamic array and exclude exsisting elements

function addNumifnotThere(numer){
var numCent = [];
numCent.forEach(function(){
if(numer in numCent)
console.log("you logged that");
else
numCent.push(numer);
});
return numCent;
}
This is my current code, what its attempting to do is read an array and if there is already an element exits the loop and says "you already logged that", obviously if it cannot find a similar element then it pushes it to the array.
I want this to work dynamically so we cannot know the size of the array beforehand, so the first element passed as an argument should be put into the array, (addNum(1) should have the array print out [1], calling addNum(1) again should print "you already logged that")
However there are two problems with this
1) Trying to push to a new array without any entries means everything is undefined and therefore trying to traverse the array just causes the program to print [].
2) Adding some random elements to the array just to make it work, in this case numCent=[1,2,3] has other issues, mainly that adding a number above 3 causes the code to print incorrect information. In this case addNum(5) should print [1,2,3,5] but instead prints [1,2,3,5,5,5]
I know this has to be a simple mistake but I've been dragging myself too long to not ask for help.
EDIT: Thanks to the many outstanding answers here I have now leanred about the indexOf method, thank you guys so much.
For every non-match you are pushing the number. Use something like this
var numCent = [];
function addNumifnotThere(numer)
{
var index = numCent.indexOf(number);
if(index >=0)
{
console.log("you logged that");
}
else
{
numCent.push(number);
}
return numCent;
}
Use Array.prototype.indexOf
var numCent = [];
function addNum(numer){
if (numCent.indexOf(numer) > -1)
{
console.log("Number already in array");
}
else
{
numCent.push(numer);
}
}
//DEMO CODE, not part of solution
document.querySelector("button").addEventListener("click", function(){
if (document.querySelector("input").value.length > 0)
{
addNum(document.querySelector("input").value);
document.querySelector("div").innerHTML = numCent.join(", ");
}
}, false);
Output
<div id="output"></div>
<input />
<button>Add number</button>
indexOf tests if an element is inside the array and returns its index. If not found it will return -1. You can test for this. You can try it for your self in this snippet. It will only allow you to add a number (or any string, in this example) once.
I also was confused by the newCent array declaration inside the function. I think, based upon the content of your question, you meant this.
If you want the array held in the instance, you can do it like this.
function AddIf(arr){
if( arr || !this.arr ) {
this.arr = arr || [];
}
return function(number) {
if( this.arr.indexOf(number) >= 0 ) {
console.log("Already Present!");
} else {
this.arr.push(number);
}
return this.arr;
}.bind(this);
}
// Usage would be like this:
// var addIf = new AddIf([1, 2, 3]);
// addIf(10); // returns [1, 2, 3, 10]
// addIf(10); // logs "Already Present!", doesn't add 10 to array
This basically returns a function, with this bound to the function being called. If you pass in an initial array, it will use that array to compare to when adding it to the array.
You can catch the return function and call it as you would want to. If you don't call new when invoking however, it will share the same array instance (and have a funky way of being called, AddIf()(10)).
I used fn.bind() to ensure the function gets called in the correct context every time, if you were wondering why I called it like that.
Do do this cleanly, I'd consider prototyping the global Array object and adding a method to push values but only if they're unique to the array. Something like this:
Array.prototype.pushUnique = function (item) {
if (this.indexOf(item) != -1) {
console.log("Item with value of " + item + " already exists in the array."
}
else {
this.push(item);
}
}
If you're not comfortable prototypeing global types like Array, you can build the same thing in a procedural pattern:
function arrayPushUnique (arr, item) {
if (arr.indexOf(item) != -1) {
console.log("Item with value of " + item + " already exists in the array."
}
else {
arr.push(item);
}
}
Then to use it, simply create a new empty array and start pushing things to it.
var numCent = [];
// The Array.prototype method
numCent.pushUnique(number);
// The procedural method
arrayPushUnique(numCent, number);

How do I correctly use an iteration value in JavaScript?

I am creating a 'simple' javaScript function which basically displays new information on the page when a user clicks next or previous.
The information is taken from an array and I want to use either i++ or i-- to call an element of the array.
Heres my JavaScript:
var titles = ["Dundalk", "Navan", "Drogheda", "Dublin"];
var i = 0;
function next()
{
i++;
if (i == titles.length)
{
i = 0;
}
var object = document.getElementById('tname');
object.innerHTML = titles[i];
}
function prev()
{
if (i == 0)
{
i = titles.length;
}
i--;
var object = document.getElementById('tname');
object.innerHTML = titles[i];
}
The problem is, when I run this code in my HTML page, I get an 'UNDEFINED' result. The JavaScript is not recognizing that i has been initialized as 0 in the beginning.
If i change titles[i] to titles[2], for example, the correct text is displayed in HTML.
What am I forgetting or how can I overcome this?
Thanks
The fact that you're seeing undefined indicates that you're accessing an array index which hasn't been set. Your code looks fine at a glance, so I would guess that there's some more code you're not showing which also uses i as a loop variable and leaves it set to a value > titles.length after the code above has run.

javascript - coldfusion - working with a list

This is probably easy for someone.
I am returning a list of campaignIDs (12,45,66) via JSON to a javascript variable
var campaignList = res.DATA.CAMPAIGNS
Now, given a specified campaignID passed in the URL
var campaignId ='<cfoutput>#url.campaignID#</cfoutput>'
I want to check if the returned list contains this campaignID
Any help much appreciated.
Plenty of ways to do it, but I like nice data structures, so ...
Split the list on comma, then loop over list, looking for value:
function campaignExists(campaignList,campaignId) {
aCampaignList = campaignList.split(',');
for (i=0;i<aCampaignList.length;i++) {
if (aCampaignList[i]==campaignId)
return true;
}
return false;
}
Since Array.indexOf sadly isn't cross browser, you're looking at something like:
// assume there is no match
var match_found = false;
// iterate over the campaign list looking for a match,
// set "match_found" to true if we find one
for (var i = 0; i < campaignList.length; i += 1) {
if (parseInt(campaignList[i]) === parseInt(campaignId)) {
match_found = true;
break;
}
}
If you need to do this repeatedly, wrap it in a function
Here's a bit of a "out of the box" solution. You could create a struct for your property id's that you pass into the json searilizer have the key and the value the same. Then you can test the struct for hasOwnProperty. For example:
var campaignIDs = {12 : 12, 45 : 45, 66 : 66};
campaignIDs.hasOwnProperty("12"); //true
campaignIDs.hasOwnProperty("32"); //false
This way if the list is pretty long you wont have to loop through all of the potential properties to find a match. Here's a fiddle to see it in action:
http://jsfiddle.net/bittersweetryan/NeLfk/
I don't like Billy's answer to this, variables within the function have been declared in the global scope and it is somewhat over complicated. If you have a list of ids as a string in your js just search for the id you have from user input.
var patt = new RegExp("(^|,)" + campaignId + "(,|$)");
var foundCampaign = campaignList.search(patt) != -1;

Javascript reference by value/by reference problem

I'm creating a jQuery plugin to do paging and encountered the following problem.
When I click on a page link created by the plugin below, it will always give we the value of the last index passed into the value i at the last iterator of the code below. If there are 4 pages, I will always get 4 if I press link 1, 2, 3 or 4. It seems that the reference to the delegate onclick also keeps a reference to the value of i instead of just the value.
Any Ideas? It's the options.onclick(i) that's acting strange.
$.fn.pager = function(options) {
var defaults = {
resultSet: undefined,
onclick: function(page) { alert(page); return false; },
};
return this.each(function () {
var rnd = Math.floor(Math.random()*9999)
var result = '';
for(var i = 1; i <= options.resultSet.PageCount; i++)
{
if(i == options.resultSet.PageCount)
result += '' + i + '';
else
result += '' + i + '' + options.separator;
}
$(this).html(result);
for(var i = 1; i <= options.resultSet.PageCount; i++)
{
$('#' + rnd + '_pagerPage_' + i).click(function() { options.onclick(i) });
}
});
}
I reduced the above code to just the problem case. So some checks re missing ;)
It seems that the reference to the delegate onclick also keeps a reference to the value of i instead of just the value.
What you are experiencing is your first (unexpected) encounter with closures. It's not even a reference that is being passed, it's weirder than that. To understand what's going on (and it's critical that you do if you program in javascript, this is considered basic stuff these days) read my answers to the following related questions:
Please explain the use of JavaScript closures in loops
Hidden Features of JavaScript?
This is a classic problem: the value of i that gets used inside the option click event handler function is whatever value i has at the point at which the event fires (which will be 4, the final value it has in the loop), not the value it had at the point at which you assigned the event handler. The way round it is to create an extra function each time through the loop that has its own variable containing a copy of the value of i at the point it was called:
var createClickHandler = function(n) {
return function() { options.onclick(n); };
};
$('#' + rnd + '_pagerPage_' + i).click( createClickHandler(i) );

Categories