Beginner here. I made some simple code that added a class to certain images when I click a button. When I click an image with that class, I want to remove the class from all elements that have it. However, I can't seem to remove the class. Here's all the relevant HTML/CSS:
.us{
border-style:solid;
border-color:#ff0000;
}
...
<button id="us_select"> select American films </button><br>
<!--When I click this button, all images of American films will have red borders by
adding the "us" class-->
<img id="sutter" src="sutter.png" alt="sutter">
<img id="theo" src="her.png" alt="theo">
<img id="holly" src="holly.png" alt="holly">
<img id="matsu" src="matsu.png" alt="matsu">
<img id="jesse" src="jesse.png" alt="jesse">
And javascript
$(document).ready(function(){
$("#us_select").click(function(){
$("#sutter,#theo,#holly,#jesse").addClass("us");
//adds "us" class to the four images.
});
$(".us").click(function(){
$(this).removeClass("us");
//removes "us" class from images and thus removing red borders.
});
});
I think $(".us").click(function() is the source of my problem. I believe the $(".us").click(function() is saying that when I click a html element with the class us, all elements with the class us are selected and have the us class removed. But when I click an image with the us class, nothing happens. Any ideas why?
I noticed this code works and is kind of what I'm looking for.
$("img").click(function(){
$(.us).removeClass("us");
});
But this code removes the us class when I click any image instead of just images with the class us.
This code runs once:
$(".us").click(function(){
//...
});
and only once, when the page loads. At that time, that selector finds no elements which match that class. So no click handlers are assigned.
Since the nature of the elements changes dynamically, add the click handler to a higher-level common parent element (or just the document itself) and filter by the selector dynamically when clicked. Something like this:
$(document).on("click", ".us", function(){
//...
});
This still adds the click handler once when the page loads, but it adds it to document. Which doesn't change. Any time document handles a click event, the (optional) second selector in the argument list is evaluated at that time to filter the source of the event before invoking the handler function.
You have to use event delegation as the us class is not present on load:
$(document).on('click', 'img.us', function() {
$('.us').removeClass('us');
})
In this way, you delegate the click event to an element that is present on load (document)
Assign the elements another class like .off and then target that class instead.
SNIPPET
$(document).ready(function() {
$("#us_select").click(function() {
$(".off").addClass("us");
});
$(".off").click(function() {
$(this).removeClass("us");
});
});
.us {
border-style: solid;
border-color: #ff0000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img src='http://placehold.it/50x50/000/fff?text=1' class='off'>
<img src='http://placehold.it/50x50/00f/eee?text=2' class='off'>
<img src='http://placehold.it/50x50/0e0/111?text=3' class='off'>
<img src='http://placehold.it/50x50/f00/fff?text=4' class='off'>
<img src='http://placehold.it/50x50/fc0/000?text=5' class='off'>
<img src='http://placehold.it/50x50/fff/000?text=6' class='off'>
<button id="us_select">select American films
</button>
Related
I need your support in selecting a logic. My script pulls few rows from DB and displays on screen. I want to give a feedback form for each data. These feedback forms must be hidden and should be visible on click of a text (Like reply to this) - Pls refer the picture.
I have tried with the help of java script and CSS
<script>
function hideElement()
{
document.getElementById("target").style.display="none";
}
function showElement()
{
document.getElementById("target").style.display="block";
}
</script>
// Data-1 fetched from DB goes here
<a href='#target'>Reply to this post</a>
<span id='target' style='display:none'>
// Feedback form for Data 1 here
</span>
// Data-2 fetched from DB goes here
<a href='#target'>Reply to this post</a>
<span id='target' style='display:none'>
// Feedback form for Data 2 here
</span>
But it works only for the first record, - Javascript finds the first object with the name "target" and sets display property 'none' or 'block'
What logic can I use to generate dynamic ID assigned to each record and make java sript to run for that. Are there any other better logics to do this? (I'm sure ther are)
Element IDs must be unique, but any time you find yourself generating unique IDs for repeating elements there's probably a simpler, more generic way to implement whatever you're doing.
For this type of function you don't need IDs at all, you can use classes and DOM navigation to get from the clicked item to the related span, using a single delegated event handler as follows:
// bind click handler to the document
document.addEventListener("click", function(e) {
// test if the actual clicked item has the class "reply"
if (e.target.className.match(/\breply\b/)) {
e.preventDefault();
// find the related target span
var target = e.target.parentNode.querySelector(".target");
// update its visibility
target.style.display = target.style.display === "none" ? "block" : "none";
}
});
<div> <!-- note added wrapper div -->
Reply to this post
<span class='target' style='display:none'>
Feedback form for Data 1 here
</span>
</div>
<div> <!-- note added wrapper div -->
Reply to this post
<span class='target' style='display:none'>
Feedback form for Data 2 here
</span>
</div>
I've put some comments within the above JS to explain what it's doing, but the important line is this one:
var target = e.target.parentNode.querySelector(".target");
Within the event listener, the e argument is the event object which holds various bits of information about the event being handled. e.target tells which element was clicked. Having already tested that element's class to see if it was one of the "reply" anchors, we then use the .parentNode property to get a reference to the wrapper div that I added to your markup, then from there .querySelector(".target") finds a descendant of the div that has the class target.
As you can see I've modified your html to support the above as follows:
Change the span ids to be classes
Given the anchors class="reply"
Added wrapper div elements for each group, to make the DOM navigation simple and reliable. You could navigate from the anchor to the span using e.target.nextSibling, except then you'd have to add extra code to skip over any text nodes. I find a wrapper element easier to work with. Of course, if your elements are already in some kind of wrappers for other purposes then you can just use the existing wrappers.
Note: it would be good to remove the inline styles, and to show and hide the spans by adding and removing classes rather than directly updating their styles, but that's not really the main issue here so I'll leave that as an exercise for the reader.
http://codepen.io/sheriffderek/pen/BzmAwg
Step 1: ditch those IDs
markup
<ul class="item-list">
<li>
<p>default stuff</p>
<div class="hidden-thing">
hidden stuff
</div>
</li>
<li>
<p>default stuff</p>
<div class="hidden-thing">
hidden stuff
</div>
</li>
<li>
<p>default stuff</p>
<div class="hidden-thing">
hidden stuff
</div>
</li>
</ul>
Step 2: hide the hidden stuff in CSS and not inline
styles
(this is stylus syntax.. but same point)
.item-list
list-style: none
margin: 0
padding: 0
li
background: gray
padding: .5rem
margin-bottom: 1rem
cursor: pointer
.hidden-thing
display: none // hide it
Step 3: get the thing you want to click with jquery or with vanilla JavaScript - attach event handler - use this to note what element the event happens on - with that element... traverse down the DOM and find the thing you want - then use the show method, whichs sets display: block... or fadeIn() or animate() or whatever you like.
JavaScript
$('.item-list li').on('click', function() {
$(this).find('.hidden-thing').show();
});
// or...
$('.item-list li').on('click', function() {
$('.item-list li').find('.hidden-thing').hide();
$(this).find('.hidden-thing').show();
});
If you want only one hidden thing open at a time, you can hide all the items each time first - which is kinda janky, but usual.
BUT... there is a better way to do this, where you add an active class to the whole item. This lets you style things inside it and just generally gives you a larger scope to work with. Here is an example of that. : ) It uses .closest - and passes the event into the click handler to stop the outer click action from bubbling up: http://codepen.io/sheriffderek/pen/oLoqEy
I'm having troubles in coming up with a conditional to load a script.
I need a conditional that will recognize if this element is the first one in the whole document that has a certain class.
The thing is that I've done a BBCode for a phpBB forum, and I want to put all the scripts there instead of put some in the templates, but if I do that and if the BBCode is used multiple times in the same page, the scripts mess up.
For example, this is a structure:
<div>
<div>
<div class="some-other-stuff"></div>
</div>
</div>
<div>
<div>
<div class="youtube"></div>
</div>
</div>
<div>
<div>
<div class="youtube"></div>
</div>
</div>
I want it so the script loads for the first div with the "youtube" class. I haven't managed to try anything (yep, that clueless).
This is the script I want to use the conditional for:
<script>
$(document).ready(function() {
$(".youtubebbcode_button").click(function() {
$(this).siblings('.youtubevideo').stop(true, true).slideToggle("medium");
});
});
</script>
If the problem is that you are loading the same script block for each instance you could remove the click handler before adding it using off()
$(document).ready(function() {
$(".youtubebbcode_button").off('click').click(function() {
$(this).siblings('.youtubevideo').stop(true, true).slideToggle("medium");
});
});
then only the last instance would activate the click handler
You can test if a given element is the first one in the document with a given class like this:
if ($(".someClass").eq(0) === element) {
// element is the first one in the document with .someClass
}
Or, if you just want to apply an event handler only to the first element in the document with a given class name at a specific point in time, you can just use .first() or .eq(0) directly:
// apply click handler only to first element with a a class
$(".someClass").first().click(function(e) {
// click handler only for first element
});
Or, if you your situation is dynamic (e.g. items are being added to the page all the time and you only want the click handler to act if the element is currently the first one in the page), then you can use delegated event handling:
$(document.body).on("click", ".someClass", function(e) {
if ($(".someClass").eq(0) === this) {
// element clicked is the first one in the document with .someClass
}
});
You could use :eq jQuery Selector, for example:
$('.test:eq(0)').css('color', 'red');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="test">Test 1</div>
<div class="test">Test 2</div>
<div class="test">Test 3</div>
I am trying to implement a function which changes style of element on click and remove it when unfocus. For ex: When element2 is clicked, it should remove class of other elements, and add class to the clicked element only.
<div class="dope" id="element777"></div>
<div class="dope" id="element2"></div>
<div class="dope" id="element11"></div>
<div class="dope" id="element245"></div>
<div class="dope" id="element60"></div>
.....(More are created automatically, numbers are not estimatable)
I couldnt know the element ids that are created. The only remains same is class.
I have tried this, but its an unprofessional approach.
$('#element1').click(function(){
$("#element1").addClass(dope2);
$("#element2").removeClass(dope);
$("#element3").removeClass(dope);
$("#element4").removeClass(dope);
});
$("#element1").blur(function(){
$("#element1").removeClass(dope);
});
$('#element2').click(function(){
$("#element2").addClass(dope2);
$("#element1").removeClass(dope);
$("#element3").removeClass(dope);
$("#element4").removeClass(dope);
});
$("#element2").blur(function(){
$("#element2").removeClass(dope);
});
What is the best approach for automating this function, instead of adding click and blur (unfocus) function to ALL of elements ?
You can listen for click events on any div with an id containing the word "element', then target its siblings elements (those that are not clicked, without referring to them by id). This might do it:
$("div[id*='element']").click(function(){
$(this).addClass('dope').siblings('.dope').removeClass('dope');
});
Your jQuery could be vastly simpler if you leverage this and siblings:
Instead of:
$("#element1").addClass(dope2);
$("#element2").removeClass(dope);
$("#element3").removeClass(dope);
$("#element4").removeClass(dope);
It could be:
$('.dope').click(
function() {
$(this).addClass(dope2).siblings().removeClass(dope);
}
);
NOTE:
Do you have a variable called dope with the class name, or is dope the class name? If it's the classname, you need to put it in quotes: $(this).addClass('dope2'), etc.
If you are removing the class dope, then will want to add a class you can always use to select these elements (so that when you remove dope, it continues to work).
Button part:
$("div").click(function(){
if($(this).hasClass("dope") || $(this).hasClass("dope2")){
$(this).addClass("dope2");
$(".dope").not($(this)).removeClass("dope");
}
})
Blur part:
$("div").blur(function(){
if($(this).hasClass("dope") || $(this).hasClass("dope2")){
$(this).removeClass("dope");
}
}
I would recommend using the :focus css selector rather than using javascript to do what you are doing... Read more here. Instead of having a click listener, the focus selector will take care of that for you and automatically remove the styling when the element is out of focus.
I am facing a little issue with some jquery code. I have some divs (look bellow)
<div class="add" id="1">Follow</div>
<div class="added" id="1">Following</div>
<div class="add" id="2">Follow</div>
<div class="added" id="2">Following</div>
I am trying when user clicks in each div with class add to fadeout the specific div and fade in the next div with class added.
Check my Code:
<script type="text/javascript">
$(document).ready(function($){
$('.add').click(function () {
$(this).find('.add').hide("fast");
$(this).find('.added').fadeIn("slow");
});
});
</script>
ID's must be unique and it should not be a number. You have to set different ids for your divs. Additionally you have to hide the div with class .added initially to achieve your need.
Because fadeIn wont work on elements which are already visible.
Try,
<script type="text/javascript">
$(document).ready(function($){
$('.added').hide();
$('.add').click(function () {
$(this).hide("fast");
$(this).next('.added').fadeIn("slow");
});
});
</script>
DEMO
You need to use $(this) to hide current element and use next to hide .added, also use unique ids to make your html valid.
The next element is already visible you probably need fadeOut() to hide it.
Live Demo
$('.add').click(function () {
$(this).hide("fast");
$(this).next('.added').fadeOut("slow");
});
You can't have same id on multiple elements. Instead use a class
$('.add').on('click', function(){ $(this).fadeOut().next('.added').fadeIn(); });
Couple of points:
Ids should be unique. In case, you need same selector on group of elements, use class.
this reference contains the target on which event listener is added, So your this context contains the element with add class. jquery.find() tries to match the selector on the children. That's why your code is not working.
Just try this Jsbin Demo
HTML
<div class="wrapper">
<div class="add" id="1">Follow</div>
<div class="added" id="1">Following</div>
</div>
JS
$('.wrapper').click(function () {
$(this).find('.add').hide("fast");
$(this).find('.added').fadeIn("slow");
});
Idea: Bind event listener on parent.
i have a website in which products are listed.There are around 30 products.Now there are links to go to details of each product.I want to put them all on one page and through javascript,change the content of a particular div on click.
What i know is that i can create 30 functions to change the display of 1 div to none..and displaying the other one....
how to achieve this..I am doing something like this
function changeImg2()
{
$('#change_content').stop(true, true).fadeOut({ duration: slideDuration, queue: false }).css('display', 'none');
$('#change_content2').stop(true, true).fadeIn({ duration: slideDuration, queue: false });
}
here is the type of div's that i have
<div id="change_content1">
<div class="viewport">
<a id="btn" href="http://www.flickr.com/photos/matt_bango/3479048548/">
<span class="dark-background">Northern Saw-whet Owl <em>Photo by Matt Bango</em></span>
<img src="images/HAND HELD POWER CUTTERS.jpg" alt="Northern Saw-Whet Owl" />
</a>
</div>
<div class="viewport no-margin">
<a href="http://www.flickr.com/photos/matt_bango/3478879694/">
<span class="dark-background">Red-shouldered Hawk <em>Photo by Matt Bango</em></span>
<img src="images/LIGHTING TOWERS.jpg" alt="Red-shouldered Hawk" />
</a>
</div>
<div class="viewport">
<a href="http://www.flickr.com/photos/matt_bango/3478189088/">
<span class="light-background">Blue-headed Vireo <em>Photo by Matt Bango</em></span>
<img src="images/MAGNETIC STAND DRILLS.jpg" alt="Blue-headed Vireo" />
</a>
</div>
<div><input name="back" value="back" id="back_btn1" type="button"></div>
</div>
But this code is not ok...because i'll have to repeat it for 30 div's.Is there a cleaner way to achieve this.
Use something like this:
$('.myDiv').click(function() {
$('.myDiv').hide(); //Or whatever function you like
$(this).show(); //or whatever function you like
});
The idea is it hides all divs with the same class and then $(this) is used to manipulate the individual div that was clicked on.
You can either target all the divs by giving them a similar class, or if they are all within a parent wrapper use something like $('.parent-wrapper > div')
ANSWER to Comment:
$(this) when used within an event such as a click function relates to the element which the event was triggered on. In this instance it would be a click event on a single div, which means you can use it to manipulate that div without targeting the others.
As mentioned above using a similar class or selector will allow you to target all divs so you can manipulate them as a group. Note that the target div will likely be included, so manipulate the group BEFORE the target div.
Alternatively you can use $(this).siblings() to manipulate all the other divs, if they are on the same level as the div that was clicked, i.e. they are siblings.
You can add a class to all your div, then do something like this. This way you won't have to write 30 functions
function changeImg(id) {
$('.your-divs').stop(true, true).fadeOut({ duration: slideDuration, queue: false });
$('#change_content'+id).stop(true, true).fadeIn({ duration: slideDuration, queue: false });
}
Looks like you need on() function.
This may be implemented like:
jQuery.yourCallback = function () {
//this here is object, on which triggered event
//your code may be below
jQuery(".currentactivediv").removeClass(".currentdiv").hide();
jQuery(this).addClass(".currentdiv").show();
}
jQuery(".yourdivs").on("click",jQuery.yourCallback);
If you want it work with links, you need to locate needed div at DOM where you use jQuery(this).
How it works: when div is showing - script assigns calss .currentactivediv to this div.
When other div is showing - script closes current div, removes .currentactivediv class from it and assigns this class to new div, what is showing.