Hover effects in for loops - javascript

Here is the HTML:
<div class=column1of4>
<a rel="Appendix" href="images/watermarks/watermark_pic1.jpg"
title="Bottle in the mirror">
<img src="images/250-width/pic1.jpg"
alt="" width="250px" height="250px"
id="Bottleinthemirrorpic">
</a>
<a rel="Appendix" href="images/watermarks/watermark_pic1.jpg"
title="Bottle in the mirror">
<div id="Bottleinthemirror" class="spanlink">
<p>Bottle in the mirror</p>
</div>
</a>
</div>
and here is the Javascript:
var texts = ['#Bottleinthemirror'];
var picture = ['#Bottleinthemirrorpic'];
for ( var i = 0; i < 1; ++i ) {
$.each(texts, function(i) {
$(this).hide();
$([this, picture[i]]).hover(function() {
$(this).show();
}, function() {
$(this).hide();
});
});
Basically, when I hover over #Bottleinthemirrorpic, I want #Bottleinthemirror to show up and I want #Bottleinthemirror to go away when I hover off of both of them.
I want the for loop because I am going to add more elements to texts and picture, I'm just wondering why the Javascript doesn't work? It doesn't seem to hide #Bottleinthemirror.
This code works but I want to be able to loop through the elements inside texts and picture which is why I am not using this code:
$('#Bottleinthemirror').hide();
$('#Bottleinthemirrorpic, #Bottleinthemirror').hover(function() {
// in
$('#Bottleinthemirror').show();
}, function() {
// out
$('#Bottleinthemirror').hide();
});

Nested loops are unnecessary, where the arrays are one-dimensional. You can try something like:
var texts = ['#Bottleinthemirror'],
pictures = ['#Bottleinthemirrorpic'],
i, j, curText, curPicture, generateHandlers;
generateHandlers = function (text, picture) {
$(text).hide();
$(text + "," + picture).hover(function () {
//in
$(text).show();
},function () {
//out
$(text).hide();
});
};
for (i = 0, j = texts.length; i < j; i++) {
curText = texts[i];
curPicture = pictures[i];
generateHandlers(curText, curPicture);
}
DEMO: http://jsfiddle.net/hQ8xt/
The immediate problem with binding events in a loop is that the event is triggered later, when the loop has finished. So by that time, the iterator (in this case, i) has reached the last value (in this case, j). You need to create a new scope to capture the values in the arrays, which is what I've done by calling the generatedHandlers function and passing the array values.
One thing I'd suggest is to combine the texts and pictures arrays into an object, like:
var textPics = {
'#Bottleinthemirror': '#Bottleinthemirrorpic'
};
And loop over that like:
var curText, curPicture;
for (curText in textPics) {
curPicture = textPics[curText];
generateHandlers(curText, curPicture);
}

Related

How do I create a <p> tag dynamically and assign it to a var when I click it?

How do I create a <p> tag dynamically and assign it to a var when I click it, it should go to a function goTo and know in what <p> I clicked, in order to access the index of the array lastGoals.
And I have other problem, it is 30 in "30s" I do this function to update and when I click it call the function many times I updated with this function.
I know the i is not in the scope of $(document).on(); there is other problem because if I put inside the for it will be addind the click in a bad way I think.
var isFirstTime = true;
var text = '<p class="boxLastGoals">test</p>';
var size = lastGoals.length;
for (var i = 0; i < size; i++) {
if (isFirstTime) {
$('#listLastGoals').html(text);
isFirstTime = false;
} else {
$('#listLastGoals').append(text);
}
}
$(document).on('click', 'p.boxLastGoals', goTo(event, i));
Assuming you are happy using JQuery you can use JQuery to create the <p> element for you inside the loop and attach the click handler dynamically in there. You can also attach the data to the element using the .prop('value', 'test'); method so it can be accessed inside the click handler like $(this).prop('value');.
I've updated my example to include a loop and access a variable to match your scenario
Example
HTML
<div id="content">
</div>
JavaScript
$(document).ready(function() {
var list = ['goal 1', 'goal 2', 'goal 3', 'goal 4', 'goal 5'];
for (var i = 0; i < list.length; i++) {
var text = list[i];
var pEl = $('<p></p>', {
text: text
});
pEl.prop('arrayIndex', i);
pEl.on('click', function(e) {
goToGoal(e, $(this).prop('arrayIndex'));
});
$('#content').append(pEl);
}
});
function goToGoal(e, i) {
alert('go to goal: ' + i);
}
JSFiddle to demonstrate

Iterating through an array of divs

Im still new at javascript ive been learning the concepts for several months and this is my first time taking a crack at it.
Im trying to create a carousel using css3 and Javascript (no Jquery)
the console keeps throwing an error.
Uncaught TypeError: Cannot read property display of undefined
The following is my html and javascript code
var slideShow = document.querySelectorAll('.inside');
for (var i = 0; i < slideShow.length; i++) {
setTimeout(function() {
slideShow[i].display.style = 'inline-block';
}, 2000)
}
<div class="inside">
<div class="inner1">
<h1>This is Inner div 1</h1>
</div>
<div class="inner2">
<h1>This is Inner div2</h1>
</div>
<div class="inner3">
<h1>This is Inner div3</h1>
</div>
<div class="inner4">
<h1>This is Inner div4</h1>
</div>
</div>
Aside from display and style being in the wrong order, the problem is that by the time the setTimeout callback function is executed, the for loop has already ended, and i is equal to the length of the nodeList (and since the last element's index is one less than the length of the nodeList, an error is thrown).
You could capture the value of i in an IIFE:
Example Here
var slideShow = document.querySelectorAll('.inside');
for (var i = 0; i < slideShow.length; i++) {
(function (i) {
setTimeout(function () {
slideShow[i].style.display = 'inline-block';
}, 2000 * (i + 1));
})(i);
}
or you could use the .forEach() method:
Example Here
var slideShow = document.querySelectorAll('.inside');
Array.prototype.forEach.call(slideShow, function (el, i) {
setTimeout(function () {
el.style.display = 'inline-block';
}, 2000 * (i + 1));
});
Alternatively, you could just use setInterval:
Example Here
var slideShow = document.querySelectorAll('.inside');
var i = 0;
var interval = setInterval(function () {
if (i < slideShow.length) {
slideShow[i].style.display = 'inline-block';
i++;
} else {
clearInterval(interval);
}
}, 2000);
You have display and style in the wrong order.
It should be slideShow[i].style.display='inline-block';
Additionally, slideShow is only an array-like object of length 1: it contains the div .inner but not its children. If you want to iterate through the child elements, use
var slideShow = document.querySelector('.inside').children;
Edit: As Josh pointed out in a separate answer, you have another problem as well in using setTimeout within a for loop. By the time the function inside the timeout executes, i will be 4, which will give you an undefined value.
If you insist on using a for loop, you can also do this using the forEach method. However, slideShow is not technically an array, but rather an "array-like object", so it does not have its own forEach method. Instead, you must invoke the Array.prototype method as such:
[].forEach.call(slideShow, function(item) {
setTimeout(function() {
item.style.display = 'inline-block';
}, 2000);
});
problem is you are only selecting div.inside and it is not returning div.inner
Try this if you want to select all .inner
change class="inside" to id="inside" and copy this js
var slideShow=document.getElementById("inside").querySelectorAll('div');
slideShow[1].style.backgroundColor = "red";
for (var i=0; i<slideShow.length; i++){
setTimeout(myFun(i), 2000)
}
function myFun(i ){slideShow[i].style.display = "inline-block";}

Trouble with finding class element names in Javascript

I'm trying to grab the Names of some Class Elements in a document (there are several of them) and rotate through them.
The HTML code of the site looks like this:
<div class="parent">
<div class="item">
<a class="item-name" href="http://somerandomurl.com">Relevant Item</a>
If I wanted to grab the URL I know the solution already:
function searchItem(itemname) {
listings = $(".item-name");
for(var i = 0; i < links.length; i++) {
element = listing[i];
if(element.href.indexOf(itemname) !== -1) {
return true;
}
}
}
In this case however, I don't want to compare the URL against another URL, I need to grab the Title off the "item-name" class as String and compare it to other Strings.
How can I manage to do this? I have tried a few things already, like listings = $(".market-name market-link").text();.
First, yo are looping through the wrong variable.
You should loop through listing instead of links
Then compare it to the element HTML:
function searchItem(itemname) {
listings = $(".item-name");
for(var i = 0; i < listing.length; i++) {
element = listing[i];
if(element.html().indexOf(itemname) !== -1) {
return true;
}
}
}
function searchItem(itemname) {
if($('a.item-name:contains("' + itemname + '")').length) {
//console.log("true");
return true;
}
}
jsfiddle

Passing the JavaScript variable into HTML

My JavaScript code is:
<script type="text/javascript">
var current = 0;
var cars = new Array(5);
cars[0] = "Audi";
cars[1] = "Bentley";
cars[2] = "Mercedes";
cars[3] = "Mini";
cars[4] = "BMW";
document.getElementById("addCarBtn").onclick = function () {
if (!(current > cars.length - 1)) {
document.getElementById("carsDiv").innerHTML += cars[current] + "<br />";
current++;
}
}
</script>
I want to display the value of each array item one by one on button click the div.
But when i click the button, the array[0] i.e "Audi" is displayed but just for fraction of seconds. then it disappears and only the button is visible.
You can use a loop like:-
for(var i=0; i< cars.length;i++)
{
alert(cars[i]);
}
//It will show alert 5 times. You'll need to click through ok to traverse all array elements.
//I think it is what you're thinking, or have I interpreted it wrong.
// I'm assuming you're completely new to javascript then on your button write onclick="yourFuncName();"
function YourfuncName()
{
//Initailze your array here, like you have done or like kamituel has done
// then just print each array element one by one
for(var i=0; i< cars.length;i++)
{
alert(cars[i]);
}
}
How about the every method?
cars.every( function(c) {
alert("car: " + c);
});
You're almost there. Since the JS code was located before the HTML, the button element still doesn't exist. Best just wrap the code with window.onload and it should work:
window.onload = function() {
document.getElementById("addCarBtn").onclick = function() {
if (!(current > cars.length - 1)) {
document.getElementById("carsDiv").innerHTML += cars[current] + "<br />";
current++;
}
}
};
Live test case.
Edit: just noticed your button doesn't have type. This means that some browsers might make it a submit button by default, which will cause a page reload. To avoid it, make it a plain button:
<button id="addCarBtn" type="button">

Jquery Problem Sort of Auto Slideshow

I'm having some problems, I'd like to have a sort of slideshow where users have 4 buttons, and when they click one div appears and the others disappear. The div's are all in the same place with the same size. I'd also like to put this automatic
var Idx = 1;
var IntervalKey = setInterval = (auto, 5000);
var auto = function() {
$("#MainImage").eq(Idx).fadeIn(1000);
while(Idx <3) {
Idx++;
$("#MainImage").eq(Idx).hide();
}
Idx++;
if(Idx>3) {
Idx = 0;
}
};
$(".botao-imagem").click(function(){
Idx = $(".botao-imagem").index(this);
auto();
});
Your main issue is repeated IDs, IDs must be unique, so $("#ID").eq() doesn't every have a purpose really, since it should be 1 or 0 results. First give the elements a class instead:
<div class="MainImage"><p>111111</p></div>
<div class="MainImage"><p>222222</p></div>
<div class="MainImage"><p>333333</p></div>
<div class="MainImage"><p>444444</p></div>​
and use a class selector, like this:
$(".MainImage")
Also auto needs to be declared before using it or define it as a function directly, overall like this:
var Idx = 0;
var IntervalKey = setInterval(auto, 5000);
function auto() {
$(".MainImage").hide().eq(Idx).fadeIn(1000);
Idx++;
if(Idx>3) Idx = 0;
};
$(".botao-imagem").click(function(){
Idx = $(".botao-imagem").index(this);
auto();
});
You can test the updated/working version with the above code here.

Categories