I know this is awfully simple, but I'm new to this and I just need to be shown it once. So when I'm using jQuery/javascript I find myself writing repetitive code again and again to target different elements with the same function, for example:
$(function() {
$('.icon1').click(function() {
$('.info1').toggle().addClass('animated fadeInDown');
$('.info2, .info3, .info4').hide();
});
});
$(function() {
$('.icon2').click(function() {
$('.info2').toggle().addClass('animated fadeInLeft');
$('.info1, .info3, .info4').hide();
});
});
and this repeats again for icon3 and icon4. I'm selecting a different element, showing another, hiding another three, and adding different classes in each function, and I don't know what would be the best way not to repeat the whole thing for each element. I would be very glad to be shown any ideas to refactor this, and wouldn't mind seeing how that is done in vanilla js also.
(For illustration the code here is a snippet from the code on the experience section of my portfolio where clicking on an icon reveals an info panel about it, and hides any previously shown info panels.)
Use a common class, use this, and not to remove it from the collection
$(function() {
$('.commonClass').click(function() {
$(this).toggle().addClass('animated fadeInDown');
$('.commonClass').not(this).hide();
});
});
You should be able to separate those selectors with commas.
$('.icon1,.icon2').click(function()
Or assign each a single class they share that behavior? ".icon-btn" where you use ".icon-btn" as the selector for any you wish to have that behavior.
It would be better if you can plan your html better with data attribute
for eg:
<div class="icon" data-info = "1"> <div>
<div class="icon" data-info = "2"> <div>
<div class="info-1 info"> <div>
<div class="info-2 info"> <div>
$('.icon').click(function() {
var className = '.info-' + $(this).data('info');
$('.info').hide();
$(className).toggle().addClass('animated fadeInDown');
});
you can also remove .info1,.info2 from js code by adding some common class in html as info to them.
for eg
I'm making some assumptions about your actual HTML, but you could probably leverage the siblings() method in this case.
$(document).on('click', '.icon', function() {
$(this).toggle().addClass('animated fadeIn')
.siblings().hide();
});
Related
On a web page we have a list of profiles. On the right hand side of the profile is some text, followed by an arrow img#arrow.
When img#arrow is clicked, we have the following jQuery we hope to run:
However, the corresponding .bottom-sec is not toggling.
jQuery('#arrow').click(function(){
var $parent = $(this).parent();
$($parent).addClass('active');
jQuery($parent +' .bottom-sec').toggle();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="profile-right">
<h2>Bob Brown</h2>
<h3>Non-Executive Chairman</h3>
<p>Intially showing text.</p>
<div class="bottom-sec" style="display: none;">
<p>Initially hidden text.</p>
</div>
<img id="arrow" src="/wp-content/themes/wtc/images/icons/down-arrow-circle-hi.png">
</div>
Problem
The problem with your code is exactly what the comment on your question is saying, but he didn't explain anything:
You're combining two different ways of selecting elements. One is with selectors, the other is traversing. You're using them in a way which isn't possible (the $parent + ' .bottom-sec' part). The comment linked to a jQuery page about traversing which you should definitely read! It tells you a lot about how to use traversing functions, which you could use!
Solution
There are multiple solutions to this, but I'll write down the one I think is the best:
First of all, change the HTML a bit. I've removed the element style of .bottom-sec and changed the id of the image to a class, because you have multiple images with the same id on the page, which is not a recommended thing to do. Classes can occur more than once, id's cannot.
<div class="profile-right">
<h2>Bob Brown</h2>
<h3>Non-Executive Chairman</h3>
<p>Intially showing text.</p>
<div class="bottom-sec">
<p>Initially hidden text.</p>
</div>
<img class="arrow" src="/wp-content/themes/wtc/images/icons/down-arrow-circle-hi.png">
</div>
I've reduced the JavaScript to the following. Note that is just reduced to one line, where a click on the .arrow element goes searching for the closest .profile-right parent. If, for whatever reason, you decide to change the HTML and the .arrow element is no longer a child of the .profile-right, this code still works. The only thing it does is toggle an active class on the .profile-right.
jQuery(document).on('ready', function() {
jQuery('.arrow').on('click', function(){
jQuery(this).closest('.profile-right').toggleClass('active');
});
});
The document ready listener was added because of OP's comment.
With CSS, we can use the new .active class to show or hide the element.
.profile-right .bottom-sec {
display: none
}
.profile-right.active .bottom-sec {
display: block
}
Original Code Fix
If for some reason you wanted to use your original code, this is how it should be:
// Nothing wrong about this part.
// Your only worry should be that there could be
// multiple elements with the same ID, which is something really bad.
jQuery('#arrow').click(function(){
// This part is correct, no worries
var $parent = $(this).parent();
// Removed the $(...), because $parent is already a jQuery object
$parent.addClass('active');
// Changed the selector to a find function
$parent.find('.bottom-sec').toggle();
});
You could also combine all of the code inside the listener function to just one line:
jQuery('#arrow').click(function(){
$(this).parent().addClass('active').find('.bottom-sec').toggle();
});
Change your js code like below.
jQuery('#arrow').click(function(){
var $parent = $(this).parent();
$($parent).addClass('active');
jQuery($parent).find('.bottom-sec').toggle();
});
In your event listener you can catch the element (the down arrow) that triggered the event. It will be referred as this.
Then you can go through the DOM tree using .next() and .parent() to access the <div> to toggle.
Note: you may need more functions than the one I explained above.
Note 2: without code or more detailed information, we can't help you further, I will edit this answer if you add details.
I have three article tags that each have 1 section which I need to animate to appear i.e height from 0px to whatever px. Each article has an ID what is the most efficient way to have an on click event for each one without writing a separate function for each individual id i.e is there a 'get clicked article's id' type method?
Thanks
This is what I would do,
jQuery:
$('.art h1').on('click', function() {
$(this).parent().find('p').stop(true).slideToggle();
});
html:
<div class="art">
<h1>Some article stuff</h1>
<p>text goes here</p>
</div>
fiddle: JSFIDDLE
If you want it to slide up and have only one open at a time then you can make a minor edit like so,
jQuery:
$('.art h1').on('click', function() {
$('.art p').slideUp();
$(this).parent().find('p').stop(true).slideToggle();
});
fiddle: Only one active JSFIDDLE
You can combine multiple selectors with a comma:
$('#id1,#id2,#id3').click(function() {
$(this).animate(...);
});
...or you could add class="something" to each element and just select that:
$('.something').click(function() { ... });
Use a class for the click event, instead of ids .. you can then use the id or some other attribute to identify which article to expand.
$('.someClass').click(function() {
thisId = $(this).attr('id');
$('#whereTheSectionsAre').find('.active').removeClass('active').next().slideUp(400);
$(thisId+'article').toggleClass('active').next().slideDown(400);
return false;
});
You can check some examples here, mainly if the id's are dynamic:
http://jsbin.com/uzEkiQa/3/
The first approach is the one already suggested, but with dynamic id's:
$('div[id^="id_"]').text("Changed by regexep");
The second one if your matching is a bit more hardcore uses filter:
var reg = new RegExp(/id_\d+/);
$('div[id^="id_"]')
.filter(function(index, item) {
return reg.test(item.id);
})
.text("Changed by filter and regexp");
After the selection you can apply the behaviours you want. Check the JSBin to play around.
I'm trying to change the CSS class of a couple DIVs, Linked below is my jFiddle
The only change is that the -selected class actually has a background image which seems to have the background color of the -non-selected class.
The other problem is after selecting another div, you can't select the first one again. What exactly is jQuery doing with the classes? When I add the -non-selected class to it, it should become select-able again, right?
http://jsfiddle.net/9FZcz/
jQuery
$(".selector-box").click(function () {
$(".selector-box-selected").removeClass("selector-box-selected").addClass("selector-box");
$(this).removeClass("selector-box").addClass("selector-box-selected");
});
HTML
<div class="selector-box-selected"></div>
<div class="selector-box"></div>
<div class="selector-box"></div>
<div class="selector-box"></div>
CSS
.selector-box{
margin-bottom:2px;
width:328px;
height:46px;
background-color:rgba(255,255,255,.25);
}
.selector-box-selected{
margin-bottom:2px;
width:351px;
height:46px;
background-image:url(../images/layout/SelectedArrow.png);
}
You should try another way to adding and removing classes, try this one :
$(".selector-box").click(function () {
$('.selector-box').removeClass("selected");
$(this).addClass("selected");
});
Updated JsFiddle
The problem with not being able to select the first one again is that the click event is not being linked to it, since you only apply it to the <div> elements with the class .selector-box. Apart from that, CSS seems fine, check the fiddle: http://jsfiddle.net/9FZcz/2/
I change your code abit
<div name="ss" class="selector-box-selected"></div>
<div name="ss" class="selector-box"></div>
<div name="ss" class="selector-box"></div>
<div name="ss" class="selector-box"></div>
$("div[name=ss]").click(function () {
$("div[name=ss]").removeClass("selector-box-selected").addClass("selector-box");
$(this).removeClass("selector-box").addClass("selector-box-selected");
});
don't mind a name SS, change it to what you want :D
There are already answers posted that suggests solutions that requires some refactoring, like adding a selected class to selected elements rather than having seperate selector-box-selected and selector-box classes.
While I think you should perform the refactoring since it makes the overall design better and leads to less CSS code duplication, here's a solution without refactoring the code.
I kept track of the last selected element to avoid looping over all of boxes to remove the selected class.
DEMO
var selectedBox = $('.selector-box-selected').get();
$('.selector-box').add(selectedBox).click(function () {
if (selectedBox === this) return;
selectedBox = $([this, selectedBox])
.toggleClass('selector-box-selected')
.toggleClass('selector-box')
.get(0);
});
I have created an expanding div that hides on load and expands when clicked using javascript and jQuery. My problem is that I need to use this feature multiple times on each page (10-30x). Is there a way to call the function to work with multiple Div ids using an array or something of that nature (I am a newbie, my apologies), e.g. a few of my div ids would be eb1, eb2, eb3, eb4. and here is my script that currently works on one id:
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery('#eb1').hide();
//hides box at the begining
jQuery("#hide").click(function() {
jQuery('#eb1').fadeOut(300);
//jQuery('#the_box').hide();
});
jQuery("#show").click(function() {
jQuery('#eb1').fadeIn(300);
//jQuery('#the_box').show();
});
});
</script>
Any help would be appreciated, even a link to an explanation.
Thanks,
Travis
Further to John Conde's answer this is also possible using attribute-starts-with:
jQuery('div[id^="eb"]').hide();
JS Fiddle demo.
It is, of course, easier to just use a particular class-name, and the selector then becomes:
jQuery('.className').hide();
JS Fiddle demo.
References:
Attribute-starts-with ([attribute^="value"]) selector.
You should be able to do this by separating the ids with a comma:
jQuery('#eb1','#eb2','#eb3').hide();
just type "jquery multiple div show hide" into google:
the first link gives this:
Show/Hide Multiple Divs with Jquery
:)
Maybe it is cleaner to add a css class to all the div (or whatever tag you use) elements that should behave like that, then use that class in the selector ?
jQuery('div.hidable').hide();
//hides all 'hidable' boxes
jQuery("#hide").click(function() {
jQuery('div.hidable').fadeOut(300);
});
etc...
You could create a function to do that.
let me explain
function ToogleDiv(container){
// simple toogle
$(container).toggle();
// a toogle with some effect
$(container).toggle('slow', function() {
// add some action }); }
here's is a Jquery example Toogle Jquery Example
Hope this helps.
You can use Attribute Starts With Selector [name^="value"]
var divs = $('div[id^="eb"]');
$(divs).hide();
$('#show').click(function(){
$(divs).show();
});
$('#hide').click(function(){
$(divs).hide();
});
Live example on JSFiddle
function show(var id){
jQuery(id).fadeIn(300);
}
function hide(var id){
jQuery(id).fadeOut(300);
}
and then, in your divs:
<a id="hide" onClick="hide('eb1')">hide</a>
<a id="show" onClick="show('eb1')">show</a>
<div id="eb1"></div>
I have a dropdown function that I need to work only on the div clicked, not all (I have 14+ of the same classes on the page that need to be displayed when a certain one is clicked)
At the moment my jQuery is as follows.
$('.qacollapsed').hide();
$('.qa').click(function () {
$('.qacollapsed').slideToggle();
$(this).toggleClass('active');
});
Of course, that is toggling all qacollapsed classes when there is 14 on the page (Q&A)
Is there a way for it to only drop down the one that is clicked?
the HTML
<div class="qa">
<h4 class="question"> </h4>
</div>
<div class="qacollapsed">
<p> </p>
</div>
It would be helpful to provide a snippet of HTML here, but I'll take a guess at the structure of your markup for now..
Instead of referencing all .qacollapsed elements, you need find elements that are close to the .qa that was clicked, e.g.:
$('.qa').click(function () {
$(this) // start with the clicked element
.find('.qacollapsed') // find child .qacollapsed elements only
.slideToggle();
$(this).toggleClass('active');
});
This will work if .qacollapsed is inside .qa - if not, you might need to use next (for siblings), or one of the other jQuery tree traversal methods.
Yo could find() it or use this as a context in the selector to choose only a descendent of the clicked object
$('.qa').click(function () {
$('.qacollapsed', this).slideToggle();
//You could do $(this).find('.qacollapsed').slideToggle();
$(this).toggleClass('active');
});
Check out the jQuery selectors and why not just use $(this)?
$('.qacollapsed').hide();
$('.qa').click(function () {
$(this).toggleClass('active').next().slideToggle();
});
Personally, I'd give all the divs IDs, the clickable bit being the ID of the question in the database for example, and the answer just being id='ID_answer' or something, then use jquery to slide in the div with the id corresponding to the link clicked, ie
Var showIt = $(this).attr('id') + '_answer'
$('.qacollapsed').not('#'+showIt).hide();
$('#'+showIt).slideToggle;
That will hide all the divs without that ID and show the required one.
Dexter's use of .next above looks simpler though, I've not tried that as being relatively new to jquery too.