HTML, Javascript: button doesn't call function - javascript

I make a button in HTML, and I want it to call function in javascript:
index.html
<body onLoad="setGameAreaBounds()" onResize="setGameAreaBounds()">
<div id="scoreLabel">Score: 0 </div>
<!--div Group-->
<div>
<p id="pageTitle">Button Chaser</p>
<input type="button" id="startButton" onClick="start()" value="Start"/>
</div>
<!--The following: gameArea and dot is grouped together-->
<div id="gameArea">
<button id="dot" onClick="detectHit()"></button>
</div>
</body>
buttonChaser.js
function detectHit() {
//Increase the var score
}
function setGameAreaBounds() {
//Setting the size of GameBoard/Window
}
function moveDot() {
//randomly move the button(id: dot) within the GameBoard/window
}
function start() {
alert("sometext");
moveDot();
}
The code runs fine if I put moveDot(); function inside setGameAreaBounds();
However, it seems like the button(id: startButton) never connects to function start();
What did I do wrong?

Try moving your functions inside your onLoad function and link them back up to the global scope:
var score = 0;
var aWidth;
var aHeight;
var timer;
var that = this;
function setGameAreaBounds() {
//Setting the size of GameBoard/Window
that.moveDot = function () {
//randomly move the button(id: dot) within the GameBoard/window
}
that.detectHit = function() {
//Increase the var score
}
that.start = _start; // link desired name to reference to existing function
}
function() _start {
alert("sometext");
moveDot();
}
Basically, your html functions are accessing functions defined in the global scope after the dom elements were created. So no reference to the function exists when the dom is created. The setGameAreaBounds function gets called after the dom is ready - onLoad. JavaScript functions each have their own scope so you need to pass this from the parent using an unique reference. Then you can assign the names you want to the functions.
A better approach would be to define all scripts after
Many programs use an onReady function that waits until the dom is loaded before defining any javascript functions. This is a good approach.

Related

Is there a way to use this.onClick event and still be able to use "this" in function it calls?

project with these needs.
(10 points) When a button is clicked, the appropriate points are added to the total score.
(10 points) You are Not allowed to make any change to the HTML code provided above. In other words, you need to write unobtrusive JavaScript code, attaching event handlers in JavaScript rather than in HTML.
(10 points) The window.onload event handler should be an anonymous function.
(10 points) You should use the same event handler to handle the onclick event occurred on all of the four buttons on the webpage. In other words, you need to avoid code redundancy by using the this keyword.
I would like if someone could tell me a way I can use "this" in both of my functions so it doesn't have to be repetative like it is now in the first function, something like what I commented out. Or a way to simplify the code so it works as it does now.
<script>
window.onload = pageLoad();
function pageLoad() {
//this.onclick = okClick;
document.getElementById("6pt").onclick = okClick;
document.getElementById("3pt").onclick = okClick;
document.getElementById("2pt").onclick = okClick;
document.getElementById("1pt").onclick = okClick;
}
function okClick() {
var num1 = document.getElementById("score").value;
num1 = parseInt(num1);
var num2 = num1 + parseInt(this.id[0]);
document.getElementById("score").value = num2;
}
</script>
<body>
<div>
<input id="score" type="text" value="0" />
</div>
<div>
<button id="6pt">6 points (touchdown)</button>
<button id="3pt">3 points (field goal)</button>
<button id="2pt">2 points (safety/2-point conversion)</button>
<button id="1pt">1 point (extra point)</button>
</div>
</body>
Why don't you give all those elements a class, and then use
var myLinks = document.querySelectorAll('.myClass');
for(var i=0;i<myLinks.length;i++)
myLinks[i].onclick = okClick;
Inside okClick, the clicked element will be available via this (and also event.target).
Event handlers, like onclick are called in the context of the target object, thus you can safely use this within any event handler function. This also applies to jQuery attached events.
The above is valid for the 'okClick' function. You asked about "both of my functions", so if you're referring to pageLoad, that function is not executed in the context of an object, so you can't use this. But why would you need it? It won't help you much.
You can use the bind function which will give a given context to your function:
var context = window;
context.something = 5;
var myFunc = function () {
console.log(this.something); //5
}.bind(context);
If all you want to do is attach the same okClick() to each button then you should try and use a more general selector than ID. You can only have one ID per element so, like you've noticed, you must individually hook into each one.
Instead, try a more general selector, like document.getElementsByClassName("className");, which would be a bit more general:
<body>
<div>
<input id="score" type="text" value="0" />
</div>
<div>
<button id="6pt" class="score-button">6 points (touchdown)</button>
<button id="3pt" class="score-button">3 points (field goal)</button>
<button id="2pt" class="score-button">2 points (safety/2-point conversion)</button>
<button id="1pt" class="score-button">1 point (extra point)</button>
</div>
<script>
(function(){
// Same as yours
function okClick() { ... }
var buttons = document.getElementsByClassName("score-button");
for(var i = 0, len = buttons.length; i < len; i++)
{
buttons[i].onClick = okClick;
}
}).call(this);
</script>
</body>
There's fancier selectors available in either jQuery or more modern javascript implementations which will save you having to use a class selector, you'll have to read into that though - or see Sidd's answer, which is doing exactly that (it's cleaner).

create multiple divs with the same class javascript

I am new to JavaScript and would like to know how I can create multiple divs dynamically with the same class name. I have the following code but it only creates one instance of the div.
<div id="wrapper">
<div id="container">
<div id="board">
<script>
var board = document.createElement('div');
board.className = "blah";
for(x=0; x<9;x++) {
document.getElementById('board').appendChild(board);
}
</script>
</div>
</div>
</div>
Right now, you're creating the element outside the loop, and appending that element to the DOM...again and again.
What you want to do is create a new element during every iteration of the loop. To do that, move the part where you create the new div inside the loop:
for(x=0; x<9;x++) {
var board = document.createElement('div');
board.className = "blah";
document.getElementById('board').appendChild(board);
}
Now, every time the loop runs, you'll create a new element, and append that element to the element with ID #board.
It's worth pointing out that the variable you created (board) now only has scope within this loop. That means that once the loop is done, you'll need to find a different way to access the new elements, if you need to modify them.
Only a single element is created.
<script>
var board = document.createElement('div');
board.className = "blah";
for(x=0; x<9;x++) {
document.getElementById('board').appendChild(board);
}
</script>
Should be written as:
<script>
for(x=0; x<9;x++) {
var board = document.createElement('div');
board.className = "blah";
document.getElementById('board').appendChild(board);
}
</script>
Others did answer the question in a nutshell; here is one approach which addresses some issues that are present in the your and proposed code snippets, and maybe gives your some insight for further exploration. I hope it helps :)
To extend a script a little bit, this solution creates every element by using function createDiv, and references to individual divs are stored in an array, so you can modify the content of each div by modifying array elements, which are referring to DOM elements. (in this example, I modify 6th div for demonstration sake)
Notes:
All of your code is thrown in a global object, it's good
practice to encapsulate your code, here in immediately invoked
anonymous function.
x would be thrown in a global object even if encapsulated, you need
always to declare your variables with a var keyword. Here I declare
all vars needed upfront in one statement, which is also a good
practice;
It is convention to use "i" for loop iterator variable.
Avoid "magic numbers" (9), rather create a variable that will
describe what you do in your code. It is good if the code describes what
it does.
Also in this example, we avoid declaring "board" on each loop
iteration (the element where your divs get appended.)
Test your code in JSLint - great tool to validate your scripts.
(this will pass the test, given that you set indentation to 2.
"use strict" - read here.
/*jslint browser:true */
(function () {
"use strict";
function createDiv() {
var boardDiv = document.createElement("div");
boardDiv.className = "new-div";
boardDiv.innerText = "I am new DIV";
return boardDiv;
}
function createAndModifyDivs() {
var board = document.getElementById("board"),
myDivs = [],
i = 0,
numOfDivs = 9;
for (i; i < numOfDivs; i += 1) {
myDivs.push(createDiv());
board.appendChild(myDivs[i]);
}
myDivs[5].className = "modified-div";
myDivs[5].innerText = "I'm modified DIV";
}
createAndModifyDivs();
}());
.new-div {
color: gray;
}
.modified-div {
color: red;
}
<!DOCTYPE html>
<html>
<head>
<title>Inserting Divs</title>
</head>
<body>
<div id="wrapper">
<div id="container">
<div id="board">
</div>
</div>
</div>
</body>
</html>

Javascript : Assign a function and pass parameter at the same time

I have html buttons "classA","classB" and "classC" to which I assign the onclick handler function as follows..
var classA = document.getElementById('classA');
classA.onclick = filterByClassA;
var classB = document.getElementById('classB');
classB.onclick = filterByClassB;
var classC = document.getElementById('classC');
classC.onclick = filterByClassC;
These 3 functions do the same thing, only difference being the class.
So, can I have a single function assigned to these buttons, called with different parameters for each button. Something like below
var classA = document.getElementById('classA');
classA.onclick = filterByClass('classA');
var classB = document.getElementById('classB');
classB.onclick = filterByClass('classB');
var classC = document.getElementById('classC');
classC.onclick = filterByClass('classC');
I know this is a function call and not assignment and this is wrong but is there a way I can achieve this i.e. assign a function and pass parameter at the same time but not call it?
function filterByClass(className)
{
return function()
{
// Do something with className
console.log(className);
}
}
Bind can help you out here: Its called partial application.
Bind Syntax
fun.bind(thisArg[, arg1[, arg2[, ...]]])
1st param is scope of the function when it is called.
From 2nd you can pass any number of agruments. See the below code to know how it works.
Code:
var classA = document.getElementById('classA');
classA.onclick = filterByClass.bind(classA, 'classA');
var classB = document.getElementById('classB');
classB.onclick = filterByClass.bind(classB, 'classB');
var classC = document.getElementById('classC');
classC.onclick = filterByClass.bind(classC, 'classC');
function filterByClass(className, eventObject) {
console.log(this, className, eventObject);
}
Update:
Check out the Compatibility section in the above MDN link. You may need to use it, if you are going to use bind in non modern browsers.
i always try to keep the code as short as possible
so if your buttons are inside a container you can do that.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>atest</title>
<script>
window.onload=function(){
var c=document.getElementsByTagName('div')[0].childNodes,
l=c.length,
filterByClass=function(){
console.log(this.id);//this.id is the classA or whatever
};
while(l--){
c[l].onclick=filterByClass;
}
}
</script>
</head>
<body>
<div>
<button id="classA">A</button>
<button id="classB">B</button>
<button id="classC">C</button>
</div>
</body>
</html>
in this case
document.getElementsByTagName('div')[0]
returns the first div in the document
childNodes
give u the list of the buttons inside that div
the while function adds the onclick event with your function 'filterByClass'
inside filterByClass u can access the element by this and so return it's id with this.id

Find div ID and use to call associated Javascript variable with jQuery

I have several fish images, within links, which are listed like so...
<img src="img/fish1.png" id="fish1"/>
<img src="img/fish2.png" id="fish2"/>
I want to take id 'fish1', 'fish2', ect. (based on which is clicked), and use a variable to replace some text.
The name of the variables are...
var fish1Hunger
var fish2Hunger
And the function I want to call with a variable is...
$(function() {
$('a.trigger').click(function() {
$('#popUp h3').html(REPLACE WITH VARIABLE ASSOCIATED WITH THE FISH);
});
});
How can I call the variable associated with the IMG id?
window[e.srcElement.id+"Hunger"];
Put that inside your click event with e being the event (function (e){...) and it should access the variable as long as it is in the global scope.
jsBin demo
var fish1Hunger = "Fish 1 is hunger!! Feed him!"
var fish2Hunger = "Fish 2 is hunger!! Feed him!"
$('a.trigger').click(function (e) {
e.preventDefault();
var ImLookingFor = $(this).find('img').attr('id')+'Hunger';
$('#popUp h3').html(eval(ImLookingFor));
});

JS: Prototyping - access the right instance property

I'm a little confused about prototyping in JS. I've prepared a fiddle for this:
http://jsfiddle.net/GBCav/7/
Markup:
<div class="container1">
<p>Container 1</p>
<button>Turn me (container1) red</button>
</div>
<div class="container2">
<p>Container 2</p>
<button>Turn me (container2) red</button>
</div>
JS:
// Constructor Function
function Box( container ) {
this.container = $(container);
}
// Prototype method
Box.prototype = {
init : function() {
// Assign buttons to object variable
this.button = this.container.find('button');
$this = this; // Set 'this' to Slider object
this.button.on('click', function() {
// It is getting the wrong container here, but why
$this.container.css('background-color','red');
});
}
};
Here's how I call the constructor function:
// Create two instances of box
(function() {
var container1 = new Box( $('div.container1') );
container1.init();
var container2 = new Box( $('div.container2') );
container2.init();
})();
I have two Box-objects created by a constructor function. When I click on a button inside of a box, the background of the CONTAINING box should change the color.
The change of color is handled in the init prototype function of the Box.
However, the wrong box is getting colored with the code above. How do I address the right container?
What am I missing here?
You're missing a var statement:
$this = this;
should be:
var $this = this;
Add in var and it works as expected: http://jsfiddle.net/GBCav/8/
Explanation: When you omit the var keyword, you're assigning $this to a global variable, rather than one limited to the scope of the .init() method. The assignment happens when you call .init(), so calling this method on the second instance re-assigns $this to the second instance, affecting the value of $this in the first instance's event handler as well.

Categories