Call By Reference error in javascript(edited) - javascript

just try to run this code in two ways:
1) run this code below;
2) enable for loop then run it
<html>
<head>
<script>
function toggle(){
//console.log('hi');
var samplediv = document.getElementById('samplediv');
samplediv.innerHTML = '';
var i = 1;
//for(var i = 0; i < 3; ++i){
samplediv.innerHTML +=
"<div id=\'jh"+ i + "\'>Hi This is "+i+"</div>" +
"<div id=\'edit" + i + "\' style=\'display:none\'>Edit "+i+"</div>" ;
document.getElementById('jh'+i).addEventListener("click", function(){document.getElementById('edit'+i).style.display="block";});
/*
(function(i){
//console.clear();
var key = i;
i += "";
document.getElementById('jh0').addEventListener("click", function(){document.getElementById('edit0').style.display="block";});
//document.getElementById('jh'+key).addEventListener("click", function(){document.getElementById('edit'+key).style.display="none";}, true);
//console.log(i, key);
}(i));
*/
//}
}
</script>
</head>
<body>
<div id="samplediv" >over here</div>
<script>toggle();</script>
</body>
</html>
I'm trying to add addEventLister on every divs using for. I'm sure this is kind of call by reference error. I know there are ways to add events such as on attribute method. Also adding a number of similar listeners is inefficient but I have to make them as you can see.
I've made a IIFE to make key be a value but failed. Do you have any idea to solve this problem?(No jQuery please)

JSFiddle
You will change method which You use to adding new elements.
I replaced innerHTML += to document.createElement for each new item.
var jh = document.createElement('div');
jh.id = 'jh'+i;
jh.innerText = 'Hi This is '+i;
var edit = document.createElement('div');
edit.id = 'edit'+i;
edit.style.display = 'none';
edit.innerText = 'Edit '+i;
samplediv.appendChild(jh).appendChild(edit);
Variable i on click event is visible with last value, so You must get index from other source (from id for example).
document.getElementById('jh'+i).addEventListener("click", function(){
var jhIndex = this.id.split('jh')[1];
document.getElementById('edit'+jhIndex).style.display= 'block';
});

Related

How do I get the id of a element in a form?

I need to get the id of an element within a form so I can tag the element as "false" or "true". Or, alternately, I need a way to associate a name with an element that can I pull in javascipt so I can change the associated value.
var form = document.getElementById("myForm");
form.elements[i].value
Those lines of code is what I tried but it doesn't seem to work.
Edit:
function initial(){
if (localStorage.getItem("run") === null) {
var form = document.getElementById("myForm").elements;
for(var i = 0; i < 1 ; i++){
var id = form.elements[i].id;
sessionStorage.setItem(id,"false");
}
localStorage.setItem("run", true);
}
}
So basically when I run the page, I want a localStorage item attached to all the buttons on the screen. I want this to run once so I can set all the items to false. Problem is I don't know how to get the ids so I have a value to attach to the button. Any idea of how to accomplish a task like this.
Edit2:
function initial(){
if (localStorage.getItem("run") === null) {
var form = document.getElementById("myForm");
var tot = document.getElementById("myForm").length;
for(var i = 0; i < tot ; i++){
sessionStorage.setItem(form.elements[i].id,"false");
}
localStorage.setItem("run", true);
}
}
This is the new code. It mostly seems to work but for some reason only the first value is getting set to false. Or maybe it has to do with this function, I'm not sure.
function loader(){
var form = document.getElementById("myForm");
var tot = 5;
for(var i = 0; i < 5 ; i++){
if(sessionStorage.getItem(form.elements[i].id) === "true"){
document.getElementById(form.elements[i].id).style.backgroundColor = "green";
return ;
}else{
document.getElementById(form.elements[i].id).style.backgroundColor = "red";
return false;
}
}
}
Anyways, I'm running both of these at the same time when the page is executed so they are all set to false and turn red. But when a button is properly completed, the color of the button turns green.
It's available via the id property on the element:
var id = form.elements[i].id;
More on MDN and in the spec.
Live Example:
var form = document.getElementById("myForm");
console.log("The id is: " + form.elements[0].id);
<form id="myForm">
<input type="text" id="theText">
</form>
You're already storing all the elements in the form so it must be :
var form = document.getElementById("myForm").elements;
var id = form[i].id;
Or remove the elements part from the form variable like :
var form = document.getElementById("myForm");
var id = form.elements[i].id;

Remove all HTML <button> elements with regex

I'm trying to build a program to run a function every time I press a button, and output the returned value. To do this, I use the following HTML:
<h2>Test Results:</h2>
<strong><span id='runs'>0</span> tests</strong><br>
<div id='testResults'>
<button id='test' onClick='this.parentNode.innerHTML = initiatePlanB()'>Begin</button>
</div>
Here's the javascript:
var tests = document.getElementById('runs');
var inner = document.getElementById('testResults').innerHTML;
//Here's the part I can't figure out
var wo = inner.replace(??????, '');
var out = wo + '<br><strong>Test #' + String(Number(tests.innerText) + 1) + '</strong><br>';
tests.innerText = Number(tests.innerText) + 1;
//More stuff here
return out;
Basically, I need either a regex expression, or some other function that can remove any html tag and it's contents.
Why not just find all buttons using getElementsByTagName('button')
and then remove them all?
var testCount = 0;
var tests = document.getElementById('runs');
var inner = document.getElementById('testResults')
function initiatePlanB() {
var buttons = inner.getElementsByTagName('button');
if (buttons) {
for (var i = 0; i < buttons.length; i++) {
buttons[i].remove();
}
}
testCount++;
inner.insertAdjacentHTML('beforeend', '<br><strong>Test #' + testCount + '</strong><br>');
tests.innerText = testCount;
//More stuff here
}
<h2>Test Results:</h2>
<strong><span id='runs'>0</span> tests</strong><br>
<div id='testResults'>
<button id='test' onClick='initiatePlanB()'>Begin</button>
</div>
Though you should probably just hide the buttons, or disable them.

Passing array -- scope

I want to pass an array from one external .js file to another.
Each of these files works fine by themselves, but I am having a problem passing the array from pickClass.js to displayStudent.js, and getting the names and "remaining" value to display in the html file. I know it has something to do with how the arrays are declared, but I can't seem to get it to work properly.
The first file declares the array choice:
(masterStudentList.js):
var class1 = ['Brown, Abe','Drifter, Charlie','Freed, Eve'];
var class2 = ['Vole, Ug','Xylo, William','Zyzzyx, Yakob'];
The second picks which array to use based on the radio buttons (pickClass.js):
var classPicked = array(1);
function randomize(){
return (Math.round(Math.random())-0.5); }
function radioResult(){
var chooseClass = document.getElementsByName("chooseClass");
for (i = 0; i < chooseClass.length; i++){currentButton = chooseClass[i];
if (currentButton.checked){
var selectedButton = currentButton.value;
} // end if
} // end for
var output = document.getElementById("output");
var response = "You chose ";
response += selectedButton + "\n";
output.innerHTML = response;
chosenClass = new Array();
if (selectedButton == "class1")
{chosenClass = class1;}
else
{chosenClass = class2;}
var text = "";
var nametext = "";
var i;
for (i = 0; i < chosenClass.length; i++) {
text += chosenClass[i]+ ' / ';
}
var showText = "";
l = chosenClass.length;
classPicked = Array(l);
for (var i = 0; i < l; ++i) {
classPicked[i] = chosenClass[i].split(', ').reverse().join(' ');
showText += classPicked[i]+ '<br>';
}
//return = classPicked;
document.getElementById("classList").innerHTML = classPicked;
} // end function
This works properly.
I then want to pass "classPicked" to another .js file (displayStudent.js) which will randomize the student list, loop and display the students for a few seconds, and then end with one student name.
basket = classPicked; //This is where the array should be passed
function randOrd(){
return (Math.round(Math.random())-0.5); }
function showBasket(){
mixedBasket = basket.sort( randOrd ); //randomize the array
var i = 0; // the index of the current item to show
document.getElementById("remaining").innerHTML = basket.length;
fruitDisplay = setInterval(function() {
document.getElementById('showStud')
.innerHTML = mixedBasket[i++]; // get the item and increment
if (i == mixedBasket.length) i = 0; // reset to first element if you've reached the end
}, 100); //speed to display items
var endFruitDisplay = setTimeout(function()
{ clearInterval(fruitDisplay);
var index = mixedBasket.indexOf(document.getElementById('showStud').innerHTML);
mixedBasket.splice(index,1);
}, 3500); //stop display after x milliseconds
}
Here is the html (master.html). It's just rough -- I'll be working on the layout later:
<html>
<head>
<script src="masterStudentList.js" type="text/javascript"></script>
<script src="pickClass.js" type="text/javascript"></script>
<script src="displayStudent.js" type="text/javascript"></script>
</head>
<body>
<h2>Choose Class</h2>
<form action = "">
<fieldset>
<input type = "radio"
name = "chooseClass"
id = "radSpoon"
value = "class1"
checked = "checked" />
<label for = "radSpoon">Class 1</label>
<input type = "radio"
name = "chooseClass"
id = "radFlower"
value = "class2" />
<label for = "radFlower">Class 2</label>
<button type = "button"
onclick = "radioResult()"> Choose Class
</button>
<div id = "output">
</fieldset>
</form>
</div>
<center>
<h1> <span id="chooseStud"></span><p></h1>
<script> var fruitSound = new Audio();
fruitSound.src = "boardfill.mp3";
function showFruitwithSound()
{
fruitSound.play(); // Play button sound now
showBasket()
}
</script>
Remaining: <span id = "remaining" ></span>
<p>
<button onclick="showFruitwithSound()">Choose Student</button>
</center>
pickedClassList = <p id = classList> </p>
</body>
</html>
You shouldn't use global variable like this (I encourage you to read more on this theme) and I'm not sure I understand what you're trying to do... but the solution of your issue should be to move the basket = classPicked; line into your showBasket method :
basket = classPicked; //This is where the array should be passed
function randOrd(){
return (Math.round(Math.random())-0.5);
}
function showBasket(){
// whatever
}
should be :
function randOrd(){
return (Math.round(Math.random())-0.5);
}
function showBasket(){
basket = classPicked; //This is where the array should be passed
// whatever
}
This way, each time you call showBasket, this method will use the last value of classPicked.
Otherwise, basket will always keep the reference on the first value of classPicked.
Why ? because each time you assign a new Array to the basket variable (classPicked = Array(l);) instead of changing directly it's content by :
emptying it : while (classPicked.length > 0) { classPicked.pop(); }
and then adding new data : classPicked.concat(chosenClass)
You can't pass things to files; you could call a function defined in displayStudent.js, pass it classPicked, and have it assign it to basket.
I noticed this at the end of your second chunk of code ...
} // end function
This could indicate the classPicked is declared inside a function (I don't see one on the code). Because it is inside function scope, your set of code that is trying to use it cannot.
Push the declaraction of classPicked outside of the function.
var classPicked = Array(1);
function thisusesclasspicked() {
...
Also, please start indenting your code properly, it will become much easier to maintain and read.
UPDATE FROM COMMENTS:
I see the declaration now ...
classPicked = Array(l);
for (var i = 0; i < l; ++i) {
classPicked[i] = chosenClass[i].split(', ').reverse().join(' ');
showText += classPicked[i]+ '<br>';
}
... however, you are re-assigning the array with an element of one just before you attempt to make modifications to it ... You are emptying it there: classPicked = Array(l);

Javascript Arrays and variable click functions

So I have set up two javascript arrays to pull information from some php. One array gets the name of the category to be clicked on, while the other array stores the class and id tag for the category. The class and id tags are the same other than there css type, but the array needs to output them into document elements and then, when clicked, affect the relevant areas of the document. I also need to remove duplicates from the arrays, which doesn't seem to work under my current code:
<script type="text/javascript">
var BookSeries = [];
var BookClass = [];
var i=0;
</script>
then variables for the array are pulled from php and output this way:
<script type="text/javascript">
var uniqueSeries = BookSeries.filter(function(elem, pos) {
return BookSeries.indexOf(elem) == pos;
});
var uniqueClass = BookClass.filter(function(elem, pos) {
return BookClass.indexOf(elem) == pos;
});
while (uniqueSeries[i]) {
document.write( "<span id='"+uniqueClass[i]+"'>"+uniqueSeries[i]+"</span>" );
i++;
}
for(var i = 0; i < uniqueClass.length; i++) {
$np("#"+uniqueClass[i]).click(function(){
$np(".postitem").fadeOut(200);
$np("."+uniqueClass[i]).fadeIn(200);
});
}
</script>
You are using jquery so you can do the following for appending the elements to the DOM:
var htmlString = "";
for (var i = 0; i < uniqueSeries.length; i++) {
htmlString += "<span id='"+uniqueClass[i]+"'>"+uniqueSeries[i]+"</span>";
}
$("#myContainer").html(htmlString);
Not sure what is $np so I'll assume you meant jquery's $.
for(var i = 0; i < uniqueClass.length; i++) {
var uClass = uniqueClass[i];
$("#" + uClass).click(function(){
$(".postitem").fadeOut(200);
$("." + uClass).fadeIn(200);
});
}
Edit:
"#myContainer" refers to the id of the dom element you want to append the html to. if you just want to append it to document you can do:
$(document).appendTo(htmlString);
Also see I updated the code above to reflect your comments about the uniqueClass array.

How to get child element by ID in JavaScript?

I have following html:
<div id="note">
<textarea id="textid" class="textclass">Text</textarea>
</div>
How can I get textarea element? I can't use document.getElementById("textid") for it
I'm doing it like this now:
var note = document.getElementById("note");
var notetext = note.querySelector('#textid');
but it doesn't work in IE(8)
How else I can do it? jQuery is ok
Thanks
If jQuery is okay, you can use find(). It's basically equivalent to the way you are doing it right now.
$('#note').find('#textid');
You can also use jQuery selectors to basically achieve the same thing:
$('#note #textid');
Using these methods to get something that already has an ID is kind of strange, but I'm supplying these assuming it's not really how you plan on using it.
On a side note, you should know ID's should be unique in your webpage. If you plan on having multiple elements with the same "ID" consider using a specific class name.
Update 2020.03.10
It's a breeze to use native JS for this:
document.querySelector('#note #textid');
If you want to first find #note then #textid you have to check the first querySelector result. If it fails to match, chaining is no longer possible :(
var parent = document.querySelector('#note');
var child = parent ? parent.querySelector('#textid') : null;
Here is a pure JavaScript solution (without jQuery)
var _Utils = function ()
{
this.findChildById = function (element, childID, isSearchInnerDescendant) // isSearchInnerDescendant <= true for search in inner childern
{
var retElement = null;
var lstChildren = isSearchInnerDescendant ? Utils.getAllDescendant(element) : element.childNodes;
for (var i = 0; i < lstChildren.length; i++)
{
if (lstChildren[i].id == childID)
{
retElement = lstChildren[i];
break;
}
}
return retElement;
}
this.getAllDescendant = function (element, lstChildrenNodes)
{
lstChildrenNodes = lstChildrenNodes ? lstChildrenNodes : [];
var lstChildren = element.childNodes;
for (var i = 0; i < lstChildren.length; i++)
{
if (lstChildren[i].nodeType == 1) // 1 is 'ELEMENT_NODE'
{
lstChildrenNodes.push(lstChildren[i]);
lstChildrenNodes = Utils.getAllDescendant(lstChildren[i], lstChildrenNodes);
}
}
return lstChildrenNodes;
}
}
var Utils = new _Utils;
Example of use:
var myDiv = document.createElement("div");
myDiv.innerHTML = "<table id='tableToolbar'>" +
"<tr>" +
"<td>" +
"<div id='divIdToSearch'>" +
"</div>" +
"</td>" +
"</tr>" +
"</table>";
var divToSearch = Utils.findChildById(myDiv, "divIdToSearch", true);
(Dwell in atom)
<div id="note">
<textarea id="textid" class="textclass">Text</textarea>
</div>
<script type="text/javascript">
var note = document.getElementById('textid').value;
alert(note);
</script>
Using jQuery
$('#note textarea');
or just
$('#textid');
$(selectedDOM).find();
function looking for all dom objects inside the selected DOM.
i.e.
<div id="mainDiv">
<p>Paragraph 1</p>
<p>Paragraph 2</p>
<div id="innerDiv">
link
<p>Paragraph 3</p>
</div>
</div>
here if you write;
$("#mainDiv").find("p");
you will get tree p elements together. On the other side,
$("#mainDiv").children("p");
Function searching in the just children DOMs of the selected DOM object. So, by this code you will get just paragraph 1 and paragraph 2. It is so beneficial to prevent browser doing unnecessary progress.

Categories

Resources