I'm learning javascript and I'm having trouble figuring out why my script is not working. I'm guessing its because the imageIn and imageOut functions don't have access to the counter variable. How would I go about fixing this? Both imageIn and imageOut have errors in my error console 'undefined'.
<style type="text/css">
ul {
list-style-type:none;
}
</style>
<body>
<div id="slideShow">
<ul>
<li>
<img src="stockboat.png" alt="Steam Boat" id="boat" />
</li>
</ul>
</div>
<script type="text/javascript" src="getElementsByClassName.js"></script>
<script type="text/javascript">
var image = document.getElementsByTagName('img');
for (i = 0, ii = image.length; i < ii; i++) {
image[i].style.opacity = "0.5";
image[i].addEventListener('mouseover', imageIn, 'false');
image[i].addEventListener('mouseout', imageOut, 'false');
}
function imageIn() {
image[i].style.opacity = "1";
}
function imageOut() {
image[i].style.opacity = "0.5";
}
</script>
</body>
</html>
I think you're right about it not recognizing your iteration variable, you'll have to do:
Use reference object:
function imageIn() {
this.style.opacity = "1"; // use "this" instead of image array
}
function imageOut() {
this.style.opacity = "0.5"; // use "this" instead of image array
}
-or-
Closure Approach:
image[i].addEventListener('mouseover'
, (function(obj){return function(){imageIn(obj)};})(image[i])
, 'false');
image[i].addEventListener('mouseout'
, (function(obj){return function(){imageOut(obj)};})(image[i])
, 'false');
Need to change function definition:
function imageIn(obj) { // added parameters "obj"
obj.style.opacity = "1";
}
This method allows you to reference the loop variable, which is nice to have as an example for when using setTimeOut in a loop - so you can reuse code later :)
You may try jsfiddle and put the 2 functions imagineIn and imageOut before the code that use them.
You need to wait for the dom to finish loading before accessing any elements.
Wrap your code in with the following:
window.addEventListener('load', function () {
. . . // Your code
});
Additionally, your i variable is wrapped in the closure of both imageIn and imageOut. This means that whenever any image is receives a mouseover or mouseout event, the opacity will always change for the last image in your list of images.
To fix this, you can bind a scope to the functions:
image[i].addEventListener('mouseover', imageIn.bind(image[i]), false);
Then in your imageIn function you would do:
this.style.opacity = "1";
One last point: you are passing the string 'false' as the third argument to addEventListener. In JavaScript, any non-empty string will evaluate to true, so you should pass the boolean value false instead to prevent event bubbling.
I find jQuery incredibly time-saving and intuitive. You just have to get used to throwaway functions. Check it out! http://jsfiddle.net/wgxZu/1/
<style type="text/css">
ul {
list-style-type:none;
}
</style>
<body>
<div id="slideShow">
<ul>
<li>
<img src="http://placekitten.com/100/100" alt="Steam Boat" id="boat" />
</li>
<li>
<img src="http://placekitten.com/200/100" alt="Steam Boat" id="boat" />
</li>
<li>
<img src="http://placekitten.com/300/60" alt="Steam Boat" id="boat" />
</li>
</ul>
</div>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
var image = document.getElementsByTagName('img');
for (i = 0, ii = image.length; i < ii; i++) {
image[i].style.opacity = "0.5";
$(image[i]).hover(function(){$(this).css({"opacity":"1.0"})},
function(){$(this).css({"opacity":"0.5"})});
}
</script>
</body>
</html>
There could be errors in your <script type="text/javascript" src="getElementsByClassName.js"></script> which is causing the rest of your script to stop executing.
In addition to the answers mentioned here I would offer some other advice:
Define your counter variables: var i = 0, ii = image.length. Otherwise you might end up using some global i and ii variables that are already set....
Use an inspector like Chrome Developer Tools to find issues in your JS code.
Add and remove CSS classes rather than changing the elements styles. This will allow you to make multiple style changes with little effort.
Learn to make use of Event Delegation in your code, it will help you in the long run especially when you want to start making use of dynamic content.
Good luck with your learning.
Also, as far as getting the code to work you can take a look at this jsFiddle which uses your code with a few modifications: http://jsfiddle.net/b9Fua/
Related
I have an AgentClass with the method this.move. It's working with static objects but when I create new HTML Objects via .append(), I can't use them with my this.move method.
All the new objects have an ID and I want to animate them with the move method.
I often read "live, on, ..." but they all need an event... I don't have such an event on them. They move directly. I tried something like that:
$('.agents').on("load", Agent.move());
But that isn't working... Any ideas?
Codesinppet:
var Agent = function(agentType, xTarget, yTarget) {
...
this.move = function() {
var id = this.agentId;
$('.agent#'+id).animate({
left:"200px"
}, 1000);
}
}
And I append them after this like this:
for (deployed = 0; deployed <= agents; deployed++) {
$('.agents').append('<div class="agent" id="'+deployed+'"></div>');
}
It would be awesome if someone could help me!?
You can use .clone(true)
A Boolean indicating whether event handlers and data should be copied along with the elements. The default value is false.
var agents = 6;
for (deployed = 0; deployed <= agents; deployed++) {
$element = $('<div class="agent" id="'+deployed+'"></div>').clone(true);
$('.agents').append($element);
}
.agent {
height:50px;
width:50px;
background-color:yellow;
margin-bottom:10px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Agent</title>
</head>
<body>
<div class="agents">
</div>
</body>
</html>
But for maximum optimization event is better to use an event handler "on" to monitor the items that will be added after reloading the DOM .
This allocates less memory
Firstly - i'm not even sure if the syntax is correct, but what i'm trying to do is, i have a div showing an animated image sequence which picks a position using a variable.
I will eventually use JSON to feed the value being changed, but for now i'm just trying to understand how to use JQuery to change the variable. Here's the code:
<div id="noiseAnimDiv" style="float: center; background-color: #ffffff; ">
<script type="text/javascript" src="./animatedpng.js">
</script>
<script type="text/javascript">
var stoptheClock = 3;
noiseAnim = new AnimatedPNG('noise', './noise/noise0.png', 8, 50);
noiseAnim.draw(false);
noiseAnim.setFrameDelay(stoptheClock, 1000); //spin yet stay on value 3
</script>
</div>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.2.js"></script>
<script>
$(document).ready(
function() {
$("#stoptheClock").val(6); //
}
);
</script>
Any help much appreciated
code is live btw at so you can at least see the animation seq
http://ashleyjamesbrown.com/fgbp/noise.htm
The AnimatedPNG library you are using only checks the variable's value once - when initialized. in your code, you are changing the value after initializing it.
$(document).ready(
function() {
$("#stoptheClock").val(6); //
}
);
Should be
function() {
stoptheClock = 6;
noiseAnim.draw(false);
noiseAnim.setFrameDelay(stoptheClock,1000);
}
You are not using JQuery for any useful cause in your code, therefore I have removed all of the Jquery parts.
I tried asking this before, but I guess I wasn't specific enough. Suppose I have HTML code that looks like this. How do I ONLY target the tags within the the horizontalNAV using pure JavaScript? Okay I know I could do this using jQuery like this...
<script type="text/javascript">
$(document).ready(function(){
$('#horizontalNAV li a').click(function(){
//jQuery code here...
});
});
</script>
However I do NOT want a jQuery answer, because I want to know how you target ('#horizontalNAV li a') using pure javaScript.
or you can tell me how to do it for the verticalNav portion, either way I'll get it, if I see an example or if its explained to me. If I'm not mistaken you would have to use the document.querySelectorAll method, if so, how does that work in the above example.
<div id="wrapper">
<div id="horizontalNav">
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
</div>
<div class="sideBar">
<div class="verticalNav">
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
</div>
</div>
</div>
Without jQuery it would look like this
<script type="text/javascript">
document.addEventListener("DOMContentLoaded", function(event) {
var elems = document.querySelectorAll('#horizontalNav li a');
for (var i = elems.length; i--;)
elems[i].addEventListener("click", handler, false);
}, false);
function handler(event) {
//javascript code here...
this.style.color = 'red';
}
</script>
FIDDLE
If #horizontalNAV is a UL or OL element, then it can only have LI element children so you can skip that part of the selector. The following doesn't use querySelectorAll so will work in browsers, that don't support it:
<script>
window.onload = function() {
var list = document.getElementById('#horizontalNAV');
var links = list && list.getElementsByTagName(‘a’);
if (links) {
for (var i=0, iLen=links.length; i<iLen; i++) {
links[i].onclick = listener;
}
}
}
function listener() {
// do stuff
}
</script>
If you want to include more than one listener for an event, you’ll need to use addEventListener or some other strategy instead of assigning the function directly to the element, but in most cases only one listener is required per event type and keeping things simple has its benefits.
The listener function is declared outside the function doing the assignment to avoid a closure and circular reference, so it should have less chance of creating a memory leak.
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>
I would like to add a click event in plain JavaScript (without using jQuery) to an element like this, so I don't have an id but a class:
Yummy
If you don't have an id and don't have any selector library and you want it to work in older browsers, then it takes a bit more work. If you can put an id on it, it's quite simple. If not, it takes more code:
var links = document.getElementsByClassName("MyClass");
links[0].onclick = function() {
// put your click handling code here
// return(false) if you don't want default click behavior for the link
}
Since getElementsByClassName is not universally available in older browsers, you would need a shim to implement it when not present. Or, you could get all the links in your document with:
var links = document.getElementsByTagName("a");
and then cycle through that list until you find the one you want (perhaps checking the class name).
If you can put an ID on the link:
<a href="http://braza.com/share" id="specialLink" class="MyClass" >Yummy</a>
Then, it just takes this code:
document.getElementById("specialLink").onclick = function() {
// add code here
}
If you're going to do this regularly, the adding an event listener is a little more extensible than using the onclick property, but if you don't have any framework, then you need a function for adding an event listener that handles older versions of IE.
There can be several ways of doing this.
One is you add the click event right in the anchor
as: <a href='' onclick='yourFunct()'> Yummy </a>
The other way can be using document.getElementsByTagName('a') you can get reference to all the href's as array then you can chose that particular href and add click event to it.
like: document.getElementsByTagName('a')[0].click = function(){ }
here 0 is just symbolic if u know the exact place in array you can give that index.
The third way can be you can write a custom. document.getElementsByClassName function in javascript and use it similiarly. You can find a number of implementations of getElementsByClassName by searching google.
look at http://robertnyman.com/2005/11/07/the-ultimate-getelementsbyclassname/ one of the implementation.
You simple use like below
<a href="http://braza.com/share" class="MyClass" onclick='return somefunction()'>Yummy</a>
<script>
function somefunction()
{
// do your stuff.
// return true, if you want to open the link, or false to cancel
return true;
}
</script>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<title>Untitled</title>
<style type="text/css">
td { border: 1px solid #ccc; }
.findMe { color: gold; }
.youFoundMe { color: green; }
</style>
<script type="text/javascript"><!--
var aryClassElements = new Array();
function doSomething() {
aryClassElements.length = 0;
getElementsByClassName( 'findMe', document.body );
for ( var i = 0; i < aryClassElements.length; i++ ) {
aryClassElements[i].className = 'youFoundMe';
}
}
function getElementsByClassName( strClassName, obj ) {
if ( obj.className == strClassName ) {
aryClassElements[aryClassElements.length] = obj;
}
for ( var i = 0; i < obj.childNodes.length; i++ )
getElementsByClassName( strClassName, obj.childNodes[i] );
}
//--></script>
</head>
<body onload="doSomething();">
<h1>Heading 1</h1>
<div>
This code is inside my div.
<span>This code is inside a span inside the div. Link inside the span inside the div.</span>
Link inside the div.
</div>
<p>
<h2 class="findMe">My Paragraph's Heading 2</h2>
<table>
<tr>
<td class="findMe">My first cell.</td>
<td>My second cell. Link inside the cell inside the row inside the table.</td>
</tr>
</table>
</p>
</body>
</html>`