How to use dynamic div ID - javascript

I've been looking at so many answers here that are so close but because my jQuery knowledge is so patchy, I can't make them relevant. So I'll just go ahead and ask. I hope you all don't mind!
So, here's the script:
$("#button1").mouseenter(function(){
$("#a1").fadeIn('100', function() { });
$("#button1").mouseleave(function(){
$("#a1").fadeOut('100', function() {});
});
});
I have multiple buttons which, on mouseenter, I want to activate the corresponding arrow.
Rather than repeat the script for each pair - #button2 to #arrow2 etc - how can I just put in some neat variable in the $() bit and have it work? Sounds simple, I'm sure there's a way that my denseness cannot find.
This is the HTML (for those who requested it):
<div id="buttons">
<p><img src="images/1.png" name="button1" id="button1" /></p>
<p><img src="images/2.png" name="button2" id="button2" /></p>
<p><img src="images/3.png" name="button3" id="button3" /></p>
<p><img src="images/4.png" name="button4" id="button4" /></p>
<p><img src="images/5.png" name="button5" id="button5" /></p>
</div>
<div class="arrow" id="a1"><img src="images/arrow.png" width="747" height="75" /></div>
<div class="arrow" id="a2"><img src="images/arrow.png" width="747" height="75" /></div>
<div class="arrow" id="a3"><img src="images/arrow.png" width="747" height="75" /></div>
<div class="arrow" id="a4"><img src="images/arrow.png" width="747" height="75" /></div>
<div class="arrow" id="a5"><img src="images/arrow.png" width="747" height="75" /></div>
<div class="arrow" id="a6"><img src="images/arrow.png" width="747" height="75" /></div>

Your solution doesn't scale.
You are assigning eventhandlers for each element in the dom.
This is one of the beefs I have with jQuery. It makes it very easy to do these things wrong and shoot yourself in the foot along the way.
What you need is event delegation.
Essentially the concept is that you have an event handler much higher up in the dom tree that listens to events that bubble up. So you might be handling your mouse events on a list, not on the list items themselves, but on the document, in a single event handler.
Take a look at http://api.jquery.com/on/
Your code should be something like this:
$('body').on('mouseenter', '#buttons img', function (e) {
$('#a' + $(this).attr('id').slice(-1)).fadeIn(300);
});
$('body').on('mouseleave', '#buttons img', function (e) {
$('#a' + $(this).attr('id').slice(-1)).fadeOut(300);
});
Notice that I'm actually only using the id to get a link between the buttons and the arrows. You might consider skipping the id's all together and just go by what index the element has in its parent element.
Working example can be found here: http://jsfiddle.net/GNs44/1/

$(".buttonClass").mouseenter(function(){
$(this).siblings('.aClass').fadeIn('100', function() { });
$(".buttonClass").mouseleave(function(){
$(this).siblings('.aClass').fadeOut('100', function() {});
});
});
You can use this (or similar, instead of siblings use a proper selector) and add the mentioned classes (aClass and buttonClass) to your components).
An example where this works:
<div>
<button class="buttonClass">Description</button>
<a class="aClass">Description</a>
</div>
Note that it's important to "group" them inside a div tag, because otherwiese ALL <a> tags will fade in/out when you hover a button.

Rather than using the ID, give the button a class.
HTML:
<button id="button1" class="hoverbutton" />
<button id="button2" class="hoverbutton" />
jQuery:
$(".hoverbutton").mouseenter(function () {
$(".arrowclass").fadeIn('100', function () { });
});
$(".hoverbutton").mouseleave(function () {
$(".arrowclass").fadeOut('100', function () { });
});

Something like this might get you started:
$("[id*=button]").mouseenter(function(){
var t = $(this),
idnum = t.slice(-1);
$("[id=a" + idnum + "]").fadeIn('100', function() {
});
}).mouseleave(function(){
var t = $(this),
idnum = t.slice(-1);
$("[id=a" + idnum + "]").fadeOut('100', function() {
});
});

Related

How to check if file was selected with Jquery?

I can't seem to find out why this won't work.
photoVal always equals nothing. So the background I have never disappears. When I select a file shouldn't the value change?
Jquery
$(document).ready(function() {
$('.browsebutton').bind("click" , function () {
$('#uploadphoto').click();
});
var photoVal = $('#uploadphoto').val();
$('#uploadphoto').change(function(){
alert(photoVal);
});
if (photoVal !== ''){
$('#photo').css('background', 'none');
}
});
HTML
<div id="photo">
<img id="preview" src="#" alt="Image Preview" />
</div>
<br>
<div id="browse">
<button type="button" class="browsebutton">Add Photo</button>
</div>
<input type="file" id="uploadphoto" name="uploadphoto" style="display: none;"/>
This question seems like a duplicate.
Try this :
$(function() {
$("#uploadphoto").change(function (){
var file_name = $(this).val();
});
});

Can I optimize this jQuery 'toggle' image source function?

I have this functionality witch i am not sure is the best. It is actually working. I'm asking because i couldn't find any 'copy-paste' solution over the net so i wrote this. There no need to suggest other CSS solutions, i am stuck with the <a href><img>text</a> structure and i am UNABLE to write .css (all this because of back-end coding restrictions/ ' they are overwhelmed : lol ' )
javascript (an easy way to let the client build his own icon set [stuck with .png]) :
$(".list-habiliy").on({
mouseenter: function(){
$('img.icone', this).attr("src",$('img.icone', this).attr("src").replace('.png', '-o.png'));
},
mouseleave: function(){
$('img.icone', this).attr("src",$('img.icone', this).attr("src").replace('-o.png', '.png'));
}
},"a");
html (the list of <a> can come up to 30 elements) :
<div class="list-habiliy">
<img class="icone" src="/path/to/default/icons/icon-24px-icon-name1.png" alt="" width="24" height="24" />Some text1
<img class="icone" src="/path/to/default/icons/icon-24px-icon-name2.png" alt="" width="24" height="24" />Some tex2t
<img class="icone" src="/path/to/default/icons/icon-24px-icon-name3.png" alt="" width="24" height="24" />Some text3
<img class="icone" src="/path/to/default/icons/icon-24px-icon-name4.png" alt="" width="24" height="24" />Some text4
</div>
The goal of the function is to replace the icon <img> from within an <a> by adding/removing '-o' text from image source. I'm wondering, should i use the .each(), the hover() for performance reason ?
jsFiddle :
http://jsfiddle.net/5dpaA/
Is this the best way to do it ?
Thanks for all your advices.
[Finaly]:
Explained by user #Xotic750 [accepted answer] (Instead of wrapping this in jquery we use the event attribute and directly access the elements using javascript, we also don't perform any further jquery searches..)
This was somehow the only optimisation i could make.
thanks to user #codelio [i can't accept 2 answers] for is shortened code writing :
$(".list-habiliy a").on({
mouseenter: function (e) {
var elm=e.delegateTarget.firstChild;
elm.src=elm.src.replace('.png','-o.png');
},
mouseleave: function (e) {
var elm=e.delegateTarget.firstChild;
elm.src=elm.src.replace('-o.png','.png');
}
});
Here is another solution, uses jquery event delegation, so only 1 event handler (well 2, one for mounseenter and one for mouseleave) attached to list-habiliy, if you had multiple such structures then you could attach it to document,body and change the selectors to list-habiliy a,img. Instead of wrapping this in jquery we use the event attribute and directly access the elements using javascript, we also don't perform any further jquery searches as we are now assuming that your html pattern does not deviate from that which you have stated. Still, would be pretty difficult to measure it's improvement as it is a user fired event, but it should be faster than your jquery only methods.
HTML
<div class="list-habiliy">
<img class="icone" src="http://placehold.it/64x64/&text=.png1" alt="" width="64" height="64" />Some text1
<img class="icone" src="http://placehold.it/64x64/&text=.png2" alt="" width="64" height="64" />Some tex2t
<img class="icone" src="http://placehold.it/64x64/&text=.png3" alt="" width="64" height="64" />Some text3
<img class="icone" src="http://placehold.it/64x64/&text=.png4" alt="" width="64" height="64" />Some text4
</div>
Javascript
$(".list-habiliy").on("mouseenter", "a,img", function (evt) {
var target = evt.target;
if (target.nodeName === "IMG") {
target.src = target.src.replace('.png', '-o.png');
} else {
target.firstChild.src = target.firstChild.src.replace('.png', '-o.png');
}
}).on("mouseleave", "a,img", function (evt) {
var target = evt.target;
if (target.nodeName === "IMG") {
target.src = target.src.replace('-o.png', '.png');
} else {
target.firstChild.src = target.firstChild.src.replace('-o.png', '.png');
}
})
On jsfiddle
this will allways find the hovered child which is your img, and it's fast!
$(".list-habiliy a").on({
mouseenter: function (e) {
//faster is not possible!
var elm=e.delegateTarget.firstChild, src=elm.src.replace('.png','-o.png');
elm.src=src;
},
mouseleave: function (e) {
//same a bit jQuery stylish
var elm=e.delegateTarget.firstChild, src=elm.src;
$(elm).attr('src',src.replace('-o.png','.png'));
}
});
sorry there is a shorter one. :)
$(".list-habiliy a").on({
mouseenter: function (e) {
var elm=e.delegateTarget.firstChild;
elm.src=elm.src.replace('.png','-o.png');
},
mouseleave: function (e) {
var elm=e.delegateTarget.firstChild;
elm.src=elm.src.replace('-o.png','.png');
}
});
The way you have it works perfectly, and I couldn't say using .hover() will have any performance benefits and .each() is unnecessary. In fact:
Calling $(selector).hover(handlerInOut) is shorthand for:
$(selector).on("mouseenter mouseleave", handlerInOut);
I would probably store the $('img.icone', this) query in a variable so that it's not doing two queries inside each of the mouseenter / mouseleave functions.
It also increases readability and reduces potential problems should this be cut/pasted onto other areas:
$(".list-habiliy").on({
mouseenter: function () {
var imgIcon = $('img.icone', this);
imgIcon.attr("src", imgIcon.attr("src").replace('.png', '-o.png'));
},
mouseleave: function () {
var imgIcon = $('img.icone', this);
imgIcon.attr("src", imgIcon.attr("src").replace('-o.png', '.png'));
}
}, "a");
JS Fiddle demo: http://jsfiddle.net/5dpaA/3/
Hover is implemented like this (as seen here):
hover: function( fnOver, fnOut ) {
return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
}
So no performance here. Avoiding delegation would create a lot of handlers instead.
What you can actually do is add something like this at the end of your html:
<div id="hidden-img">
<img class="icone" src="http://placehold.it/64x64/&text=-o.png1" alt="" width="64" height="64" />
<img class="icone" src="http://placehold.it/64x64/&text=-o.png2" alt="" width="64" height="64" />
<img class="icone" src="http://placehold.it/64x64/&text=-o.png3" alt="" width="64" height="64" />
<img class="icone" src="http://placehold.it/64x64/&text=-o.png4" alt="" width="64" height="64" />
</div>
And add some CSS:
#hidden-img {
margin-left: -9999px;
}
I think it's Opera that won't load images if they're hidden.

Access all items under specific div in javascript

Hi i want to access all images under some specific div in javascript.My code is :
<div id="image-container" style="background-image:url(loading.gif)">
<div class="fade-box" id="image-1"><img src="2bscene-logo.gif" alt="" width="330" height="108" border="0" /></div>
<div class="fade-box" id="image-2" style="display: none;"><img src="streetgallery-logo.gif" alt="" width="330" height="108" border="0" /></div>
<div class="fade-box" id="image-3" style="display: none;"><img src="g4m-logo.gif" alt="" width="330" height="108" border="0" /></div>
</div>
While my js code is :
var image_slide = new Array('image-1', 'image-2', 'image-3');
I want to get all DIVs based on id dynamically, not having a predefined array. How can I do that?
By pure javascript, you can try:
var arr = document.querySelectorAll('#image-container img');
for(var i=0;i<arr.length;i++){
console.log(arr[i].getAttribute('src'))
}
On browsers that support querySelectorAll. (IE8 and up, modern versions of others, not IE7 and down.) - As mentioned in the comment by T.J. Crowder
With JavaScript, you can do this easily with the DOM:
var container = document.getElementById("image-container");
var child;
var image_slide = [];
for (child = container.firstChild; child; child = child.nextSibling) {
if (child.id && child.nodeName === "DIV") {
image_slide.push(child.id);
}
}
Live Example | Source
Note that the code above must be run after the elements are already in the DOM. The best way to ensure that is to put the script tag below them in the page (just before the closing </body> element is good).

click handler in capty plugin

I am trying this JS code in jquery capty plugin . However the plugin needs an image to works, like:
<img id="default1" src="img/1.jpg" name="#content-target1" width="208" height="143" class="latest_img" />
Well, when i add this image the JS below didn't works. Basically what i want is just click in span and show an alert message with the content.
$('.tag_content').live('click', function(event){
var span_val = $(this).parent().children("span").html();
alert(span_val);
});
html code
<div class="images">
<img id="default1" src="img/1.jpg" name="#content-target1" width="208" height="143" class="latest_img" />
<div id="content-target1">
<span class="tag_content">Design</span>
</div>
</div>
Any idea ? thanks
The following code seems to work for me. You can try it out on jsFiddle: http://jsfiddle.net/fZSGt/4/
$('#default1').capty();
$('.tag_content').click(function() {
//var span_val = $(this).parent().children("span").html();
var span_val = $(this).html();
alert(span_val);
});
I also changed $(this).parent().children("span").html() to $(this).html() because it seems to be unnecessary for your code.

jQuery code refactoring help needed

An update to before, here's what I'm dealing with:
<body>
<div class="header"> <img class="imgLogo" src="img/vegtablelogo.jpg"> </div>
<div id="thumbsContainer">
<div class="thumb" id="carrotThumb"> <img id="showCarrot" class="imgThumb" src="img/carot.jpg" onClick=setupVeg("showCarrot", "carrotBig") /> </div>
<div class="hidden" id="carrotBig"> <img class="imgBig" src="img/carot.jpg" /> </div>
<div class="thumb" id="brocThumb"> <img id="showBroc" class="imgThumb" src="img/brocoli.jpg" onClick=setupVeg("showBroc", "brocBig") /> </div>
<div class="hidden" id="brocBig"> <img class="imgBig" src="img/brocoli.jpg" /> </div>
</div>
<!-- end thumbs container -->
<script>
var active = "";
function setupVeg(thumbVeg, hiddenVeg) {
$("#" + thumbVeg).click(function() {
if (active != hiddenVeg) {
$("div.hidden").hide("fast");
$("#" + hiddenVeg).show("fast", function() {});
active = hiddenVeg;
}
else {
$("div.hidden").hide("fast");
active="";
}
});
}
$("div.hidden").click(function () {
$("div.hidden").hide("fast");
isAnyBig=false;
});
</script>
</body>
This code is not working unfortunately. I have borrowed from suggested solution below.
Would be nice if it did work!
Any suggestions, most welcome.
I don't think you need any of the flags or the if conditions really. I think your logic is:
toggle carrotBig whenever showCarrot
is clicked.
hide div.hidden whenever showCarrot is clicked.
So all you need is:
$("#showCarrot").click(function () {
$("#carrotBig").toggle("fast");
$("#div.hidden").hide();
});
.toggle will handle one of your flags (isCarrotBig) and .hide() won't do anything if div.hidden is already hidden, so that takes care of your isAnyBig flag.
Now.. let's make that work with broc as well...
function setupVegetable(showId, toggleId) {
$("#" + showId).click(function () {
$("#" + toggleId).toggle("fast");
$("#div.hidden").hide();
});
}
setupVegetable("showCarrot", "carrotBig");
setupVegetable("showBroc", "brocBig");
If you're interested, you can refactor it FURTHER so you don't need to supply the IDs for each of the vegetables. I'll need to see your HTML markup though.
Ok I'll post a new answer in response to the edit.
Points worth noting:
Removed divs surrounding the imgs - they are unnecessary and complicate the relationship between the thumnnails and the large images.
Removed onclick attribute from within HTML - you will be attaching the event handlers in the JS so this is not needed.
Since the relationship between the thumbnails and the large images is quite obvious (the large images is just the next element) you don't need IDs to identify ANY of them. All you need is a class on the thumbnails.
Since we're not using IDs, only classes, you can add as many vegetables as you want without touching the JS
Your code modified:
<body>
<div class="header"> <img class="imgLogo" src="img/vegtablelogo.jpg"> </div>
<div id="thumbsContainer">
<img class="imgThumb" src="img/carot.jpg" />
<img class="imgBig hidden" src="img/carot.jpg" />
<img class="imgThumb" src="img/brocoli.jpg" />
<img class="imgBig hidden" src="img/brocoli.jpg" />
</div>
<!-- end thumbs container -->
<script>
$("#thumbsContainer .imgThumb").click(function () {
var thisImgBig = $(this).next();
// Hide all imgBigs, except for this one
$("#thumbsContainer .imgBig").not(thisImgBig[0]).hide();
// Toggle this imgBig
thisImgBig.toggle();
});
$("#thumbsContainer .imgBig").click(function () {
// Hide this imgBig
$(this).hide();
});
</script>
</body>
create a function and reuse it....something like:
/**
* document here....
*/
var toggleElements = function() {
// your code here
}
and then
$("#whatever").click(toggleElements);
Personally I would suggest creating a simple jQuery plugin. Something like so:
(function($){
$.fn.big = function(options) {
var defaults = {
target: '#carrotBig',
};
var options = $.extend(defaults, options);
return this.each(function() {
$(this).click(function () {
isBrocBig=false;
if (isCarrotBig == false && isAnyBig == false) {
$(options.target).show("fast", function() {});
isCarrotBig=true;
isAnyBig=true;
}
else if (isCarrotBig == true) {
$(options.target).hide("fast");
isCarrotBig=false;
isAnyBig=false;
}
else if (isCarrotBig == false && isAnyBig == true) {
$("div.hidden").hide("fast");
$(options.target).show("fast", function() {});
isCarrotBig=true;
}
else {
$("div.hidden").hide("fast");
isCarrotBig=false;
isAnyBig=false;
}
});
});
};
})(jQuery);
Then you just call it with something like so:
$("#showCarrot").big({target: '#carrotBig'})
Your next step should be to investigate whether you can get rid of the global variables or not.
Ok I have found a neat(ish) sollution, dependent on each hidden DIV being the .next() one. If it isn't it won't work but should be fine generally though. Hacked!
<div class="header"> <img class="imgLogo" src="img/vegtablelogo.jpg"> </div>
<div id="thumbsContainer">
<div class="thumb" id="carrotThumb"> <img id="showCarrot" class="imgThumb" src="img/carot.jpg" /> </div>
<div class="hidden" id="carrotBig"> <img class="imgBig" src="img/carot.jpg" /> </div>
<div class="thumb" id="brocThumb"> <img id="showBroc" class="imgThumb" src="img/brocoli.jpg" /> </div>
<div class="hidden" id="brocBig"> <img class="imgBig" src="img/brocoli.jpg" /> </div>
</div>
<!-- end thumbs container -->
<script>
var active = "";
$("div.thumb").click(function() {
var thumbVeg = $(this).attr("id");
var hiddenVeg = $(this).next().attr("id");
setupVeg(thumbVeg, hiddenVeg);
});
function setupVeg(thumbVeg, hiddenVeg) {
if (active != hiddenVeg) {
$("div.hidden").hide("fast");
$("#" + hiddenVeg).show("fast", function() {});
active = hiddenVeg;
}
else {
$("div.hidden").hide("fast");
active="";
}
}
$("div.hidden").click(function () {
$("div.hidden").hide("fast");
});
</script>

Categories

Resources