Onclick action: two functions; only first working. Quite desperate - javascript

This is my html code:
<td width="15%" align="center"><input name="submit" type="submit" class="button"
value="Basic" tabindex="13"
onclick="return submit_Click('bxbas','bxsht');" /></td>
And this is my javascript code:
<script type="text/javascript">
function submit_Click(aclass,bclass) {
var elementsa = document.getElementsByClassName(aclass);
for(i in elementsa)
{
elementsa[i].style.display = "block";
}
var elementsb = document.getElementsByClassName(bclass);
for(j in elementsb)
{
elementsb[j].style.display = "none";
}
}
</script>
Unfortunately this is not working. Apparently, only the first part of the function is working, the one that makes the first class (aclass) to be shown. The second one remains visible.
Thank you

Don't use For.. In in this case. If you Console.Log your elementsa you'll see that the last element is a not a number, so it breaks your elementsa[i]. Using "for" solves the problem:
function submit_Click(aclass, bclass) {
var elementsa = document.getElementsByClassName(aclass);
for (i=0; i < elementsa.length; i++) {
elementsa[i].style.display = "block";
}
var elementsb = document.getElementsByClassName(bclass);
for (j=0; j < elementsb.length; j++) {
elementsb[j].style.display = "none";
}
}

Related

JavaScript - while loop

I am having trouble displaying images using a while loop using a function showCards(7) to output the HTML to display the images. I believe my problem lies somewhere within the JS function but I can't seem to be able to figure it out.
This assignment is to create a black jack game although this first part should only display 7 cards.
Below is the HTML and JS:
<table border=0 style='margin:auto'>
<tr>
<td>
<form>
<input type="BUTTON" onClick="Javascript:alert('Dummy Link')" value="Deal > > >">
</form>
</td>
<script type="text/javascript">showCards(7)</script>
<td>
<form>
<input type="BUTTON" onClick="Javascript:alert('Dummy Link')" value="< < < Hit Me">
</form>
</td>
</tr>
</table>
function showCards(7) {
while (true) {
document.writeln("< IMG src='http://www.college1.com/images/cards/gbCard52.gif' width=30 height=30 >")
count = count + 1
}
}
The problem is with your truthy in the while() loop. You should modify it to use a for() loop as follows:
function showCards( arg )
{
for(var i = 0; i < arg; i++)
{
document.writeln("< IMG src='http://www.college1.com/images/cards/gbCard52.gif' width=30 height=30 >");
}
}
Notice that the showCards() function now accepts an argument, which should be the number of cards to be added.
You have made an infinite loop, so the code will just keep writing out image tags until the browser stops the script for taking too long to run.
Lets start with the function declaration. You have used the number 7 where you would use a parameter name:
function showCards(cardCount) {
You use a counter inside the loop, which is good, but you should initialise the counter before the loop:
var count = 0;
You should make the loop run as long as there are more images to write out:
while (count < cardCount) {
So:
function showCards(cardCount) {
var count = 0;
while (count < cardCount) {
document.writeln("< IMG src='http://www.college1.com/images/cards/gbCard52.gif' width=30 height=30 >");
count = count + 1;
}
}
You can also use a for loop to do the same thing:
function showCards(cardCount) {
for (var count = 0; count < cardCount; count++) {
document.writeln("< IMG src='http://www.college1.com/images/cards/gbCard52.gif' width=30 height=30 >");
}
}

Run function on every table entry

I got a table that has an entry that looks like this:
<tr>
<td><input type="checkbox" name="ids[]"/><a style="cursor: pointer;" onclick="addtopath('parameter1', 'parameter2')" class="btn_addpath"> Add</a></td>
</tr>
As you can see every table entry countains the function "addtopath('parameter1', 'paramter2');"
The parameters are generated via php; so each item is different. Also, every entry has a checkbox. This is where the trouble occurs.
I want to create a function that runs the "addtopath" function for every table item, that is checked, as if the user clicked the "Add" button.
Hope it makes sense.
Modern browsers...
function runChecked() {
var links = mytable.querySelectorAll("input[name='ids[]']:checked + a.btn_addpath");
[].forEach.call(links, function(link) {
link.onclick();
});
}
IE8+...
function runChecked() {
var inputs = mytable.querySelectorAll("input[name='ids[]']");
for (var i = 0; i < inputs.length; i++) {
if (inputs[i].checked)
inputs[i].nextSibling.onclick();
}
}
IE6+...
function runChecked() {
var inputs = mytable.getElementsByTagName("input");
for (var i = 0, len = inputs.length; i < len; i++) {
if (inputs[i].name === "ids[]" && inputs[i].checked)
inputs[i].nextSibling.onclick();
}
}
I would add the parameters to data attributes in case you want to move to jQuery at some point. It's also good practice.
<td><input type="checkbox" data-one="one" data-two="two" class="btn_addpath"/>Add</td>
<td><input type="checkbox" data-one="three" data-two="four" class="btn_addpath"/>Add</td>
<td><input type="checkbox" data-one="five" data-two="six" class="btn_addpath"/>Add</td>
<td><input type="checkbox" data-one="seven" data-two="eight" class="btn_addpath"/>Add</td>
function addToPath(p1, p2) {
console.log(p1, p2);
}
var checkboxes = document.getElementsByClassName('btn_addpath');
var checkboxArr = [].slice.call(checkboxes);
checkboxArr.forEach(function (el) {
var p1 = el.getAttribute('data-one');
var p2 = el.getAttribute('data-two');
el.onchange = function () {
if (this.checked) { addToPath(p1, p2); }
};
});
If you use jQuery you can use the following code:
$("input[type=checkbox]:checked").siblings('a').click();
Test it at http://jsfiddle.net/tMe46/
This should emulate onClick event at all links in checked boxes
$("input[type=checkbox]:checked + a").click();

Load parts of page on demand without jquery

I am completely new to web design and I am experimenting with few things.
Lets assume that I can't use jquety and I can't upload any file to the page, instead I can use simple javascript.
What I have now is a table with few tags, and a javascript function to show based on checkboxes.
Script
<script language="javascript">
function toggleTR(trId) {
var trArray = document.getElementsByTagName("tr");
for(i = 0; i < trArray.length; i++){
if(trArray[i].id == trId){
if(trArray[i].style.display == 'none'){
trArray[i].style.display = '';
}else{
trArray[i].style.display = 'none';
}
}
}
}
</script>
Checkbox
<input type="checkbox" onClick="toggleTR('TR1');"/> TR1
And simple table
<table>
<tr id="TR1" style="display: none;">
<td>content</td>
</tr>
</table>
It works as intended, however as the page gets bigger the load time is horrible.
Is there a way for those tags to be loaded on demand when display attribute is changed? I've read about lazy load, but could not get it to work with this.
Please try to explain it as easy as it could be, as I am totally inexperienced :-)
There can't be lazy load.
Your loop will keep on running till the end. Give a break statement if the id is found., so that the rest of th loop doesn't run.
<script language="javascript">
function toggleTR(trId) {
var trArray = document.getElementsByTagName("tr");
for(i = 0; i < trArray.length; i++){
if(trArray[i].id == trId){
if(trArray[i].style.display == 'none'){
trArray[i].style.display = '';
}else{
trArray[i].style.display = 'none';
}
break;
}
}
}
</script>
OR
You can find the particular element by id and toggle as desired. This would be recommended though.
var trobj = document.getElementById(trId);
if (var != null)
{
// toggle code here
}
As ID should be unique, this should be more optimised
function toggleTR(trId) {
var tr= document.getElementById(trId);
if(tr != null){
if(tr.style.display == 'none'){
tr.style.display = '';
}else{
tr.style.display = 'none';
}
}
}
And if you don't want to hide/show unique element, then you can use classes.
<table>
<tr class="TR1" style="display: none;">
<td>content</td>
</tr>
</table>
and
function toggleTR(trClass) {
var tr= document.querySelectorAll('.'+trClass);
if(tr != null){
for(var i = 0, l = tr.length; i < l ; i++){
if(tr[i].style.display == 'none'){
tr[i].style.display = '';
}else{
tr[i].style.display = 'none';
}
}
}
}

Javascript increment variable to update table cells onclick

I have a page where the user inputs a color and I call the onClick method to change the color of the individual cells of the table. However, when I click any cell, only the last cell (cell3 in this case) will change color. What am I doing wrong?
I get the error:
Message: 'document.getElementById(...)' is null or not an object
Line: 24
Char: 4
Code: 0
My code is:
<html>
<body>
<input type='text' id='userInput' value='yellow' />
<table border="1">
<tr>
<td id="1">cell1
</td>
</tr>
<tr>
<td id="2">cell2
</td>
</tr>
<tr>
<td id="3">cell3
</td>
</tr>
</table>
<script type="text/javascript">
for(var i = 1; i <= 3; i++){
document.getElementById(i).onclick = function(){
var newColor = document.getElementById('userInput').value;
document.getElementById(i).style.backgroundColor = newColor;
}
}
</script>
</body>
</html>
Change your HTML to this: An ID must start with an an alpha character. It is not valid to start with a number.
<table border="1">
<tr>
<td id="td1">cell1
</td>
</tr>
<tr>
<td id="td2">cell2
</td>
</tr>
<tr>
<td id="td3">cell3
</td>
</tr>
</table>
This is a very common Javascript issue: All the code shares the value of i which is 3 at the end of the loop. You can solve it by using another helper function like this:
function changeIt(i) {
// This inner function now has its own private copy of 'i'
return function() {
var newColor = document.getElementById('userInput').value;
document.getElementById("td" + i).style.backgroundColor = newColor;
}
}
for(var i = 1; i <= 3; i++){
document.getElementById(i).onclick = changeIt(i);
}
It can also be written using an anonymous function, but those are harder to read.
First of all, your for loop is wrong. Try:
for(var i = 1; i <= 3; i++) {
//code
}
Second, instead of retrieving the element each time in your loop, you could use this:
this.style.backgroundColor = document.getElementById('userInput').value;
Jeremy's answer is close but there is still a problem in that changeIt is not being called until the element is clicked, by which time the value of i is still three. Using Jeremy's update to the HTML the correct script can be written as...
function createChangeColorHandler(n) {
return function() {
var newColor = document.getElementById('userInput').value;
document.getElementById("td" + n).style.backgroundColor = newColor;
}
}
for(var i = 1; i <= 3; i++) {
// We pass i to the function createChangeColorHandler by value
// at the time of this pass of the loop rather than referencing
// the variable directly after the loop has finished
document.getElementById(i).onclick = createChangeColorHandler(i);
}
As an anonymous function...
for(var i = 1; i <= 3; i++) {
// We pass i to the function createChangeColorHandler by value
// at the time of this pass of the loop rather than referencing
// the variable directly after the loop has finished
document.getElementById(i).onclick = (function(n) {
return function() {
var newColor = document.getElementById('userInput').value;
document.getElementById("td" + n).style.backgroundColor = newColor;
}
})(i);
}
EDIT Jeremy's answer is now correct

Why would a script differ in evaluating 'element.checked' in the same script, acting on different table-rows with the same structure?

I wrote an answer to this question: Fetch content of next td on checkbox click, the answer was accepted (as of writing this question).
The intent was to find the text-value of the table-cell following the current cell that contained the input checkbox; for the second row this works (in Chrome 18/WinXP), but in the first row the evaluation console.log(that.checked); evaluates to false (regardless, so far as I can see, of it being checked or not).
The supplied HTML:
<table>
<tr>
<td>
<input type=checkbox name=t>
</td>
<td width=25%>
FOOBAR
</td>
<td width=73%>
BAZ
</td>
</tr>
<tr>
<td>
<input type=checkbox name=t>
</td>
<td width=25%>
FOO
</td>
<td width=73%>
BAR
</td>
</tr>
</table>
And my JavaScript:
var c = [];
c = window.document.getElementsByTagName('input');
for (var i = 0; i < c.length; i++) {
var that = c[i];
if (that.type == 'checkbox') {
that.onchange = function() {
console.log(that.checked);
if (that.checked){
console.log(that.parentNode.nextElementSibling.firstChild.nodeValue.trim());
}
};
}
}​
JS Fiddle demo.
Note that it seems to work reliably for the second row (and logs FOO to the console), but in the first row the console logs only false. Is there an obvious mistake I'm making?
You're actually running into an issue unrelated to checked. Your that variable is outside the scope of the event handler, and so it is always resolving to c[1]. You need to either wrap the thing in a closure (aka function () { ... }(); or just change that to this inside your event handler, like in this: http://jsfiddle.net/z88HH/3/
for (var i = 0; i < c.length; i++) {
var that = c[i];
if (that.type == 'checkbox') {
that.onchange = function() {
console.log(this.checked);
if (this.checked){
console.log(this.parentNode.nextElementSibling.firstChild.nodeValue.trim());
}
};
}
}​
Isn't that always the last row e.g. try console.log(that, that.checked) , wrap it in a closure see your edited jsFiddle
for (var i = 0; i < c.length; i++) {
if (c[i].type == 'checkbox') {
c[i].onchange = function(){
var that = c[i];
return function() {
console.log(that, that.checked);
if (that.checked){
console.log(that.parentNode.nextElementSibling.firstChild.nodeValue.trim());
}
}}();
}
}​

Categories

Resources