jquery toggle with a master switch - javascript

I am trying to use jquery toggling to show and hide features of a specific product. I have it working, however it's not perfect and wondered if anyone could help please?
Basically what I'm having problems with is that when you use the master open all and then close all of the individual items on their own, I need the master switch to revert back to show all text.
In addition I want to have a + and - icon on each of the items but can't figure out how to only replace the clicked image and not all of them in the list!
Any help would be greatly appreciated, thanks.
Script
$(document).ready(function() {
$('.toggle').hide();
$('.toggler').click(function() {
var target = this.id + '_content';
var imgtarget = this.id + '_expand';
$('#' + target).slideToggle();
$('.toggleall').text('Hide all');
$('<img src="images/collapse.gif">').prependTo('.toggleall');
});
$('.toggleall').click(function() {
if ($('.toggle').is(':visible')) {
$('.toggle').slideUp();
$('.toggleall').text('Show all');
$('<img src="images/expand.gif">').prependTo('.toggleall');
} else {
$('.toggle').slideDown();
$('.toggleall').text('Hide all');
$('<img src="images/collapse.gif">').prependTo('.toggleall');
}
});
});
Html
<div class="toggleall"><img src="images/expand.gif">Show all</div>
<br><br>
<div class="toggler" id="toggle1"><img src="images/expand.gif" class="toggle1_expand">Toggle 1</div>
<div class="toggle" id="toggle1_content">only toggle1</div>
<div class="toggler" id="toggle2"><img src="images/expand.gif" class="toggle2_expand">Toggle 2</div>
<div class="toggle" id="toggle2_content">only toggle2</div>
<div class="toggler" id="toggle3"><img src="images/expand.gif" class="toggle3_expand">Toggle 3</div>
<div class="toggle" id="toggle3_content">only toggle3</div>
Here is the jfiddle of the code (thanks François Wahl): jsfiddle.net/GUYfG

Here is the working version in a proper format :-
$(document).ready(function() {
$('.toggle').hide();
$('.toggler').click( function() {
var target = this.id + '_content';
var imgtarget = this.id + '_expand';
$('#' + target).slideToggle(function(){
if( $('.toggle').is(':visible') ) {
$('.toggleall').text('Hide all');
$('<img src="images/collapse.gif">').prependTo('.toggleall');
} else {
$('.toggleall').text('Show all');
$('<img src="images/expand.gif">').prependTo('.toggleall');
}
});
if( $('.toggle').is(':visible') ) {
$('.toggleall').text('Hide all');
}
});
$('.toggleall').click(function() {
if ($('.toggle').is(':visible')) {
$('.toggle').slideUp();
$('.toggleall').text('Show all');
$('<img src="images/expand.gif">').prependTo('.toggleall');
} else {
$('.toggle').slideDown();
$('.toggleall').text('Hide all');
$('<img src="images/collapse.gif">').prependTo('.toggleall');
}
});
});
EDIT:
Here is the fiddle
I have edited the code check now. Also check the fiddle.

To expand-collapse you can toggle a class with different background images inside a DIV, or use unordered lists (UL / LI).

Related

jquery click to close current div using attr id

I have one problem with jquery secon click to close opened div.
I have created this DEMO from codepen.io
In this demo you can see there are two button div with blue color.So before clicked first button after click second button the first <div class="emoWrap" id="ac1"> is not closing.
I tryed the following js code:
$(document).ready(function() {
$("body").on("click", ".button", function(e) {
e.stopPropagation();
var ID = $(this).attr("id");
$("#ac" + ID).toggleClass("emoWrap-active");
/*var $current = $(this).find('.emoWrap').toggleClass("emoWrap-active");
$('.emoWrap').not($current).removeClass('emoWrap-active');*/
});
$("body").click(function(){
$(".emoWrap").removeClass("emoWrap-active");
});
});
HTML
<div class="container">
<div class="button" id="1">1</div>
<div class="emoWrap" id="ac1">
<div class="Emojis">For 1</div>
</div>
</div>
<div class="container">
<div class="button" id="2">2</div>
<div class="emoWrap" id="ac2">
<div class="Emojis">For 2</div>
</div>
</div>
Try this codepen example, I edited it so that all other emoWraps will turn off when a different one is clicked. This also means that it is exapandable, just change the IDAmount to the number of emoWraps you have.
This is the edited JavaScript code:
var IDAmount = 2;
$(document).ready(function() {
$(".button").on("click", function(e) {
e.stopPropagation();
var ID = $(this).attr("id");
$("#ac" + ID).toggleClass("emoWrap-active");
for(var i = IDAmount; i >= 1; i--){
if(i != ID){
$("#ac" + i).removeClass("emoWrap-active");
}
}
});
});
Just add a bit more logic to your first function. This isn't how I'd do it, but building on your code would be something like:
$(".button").on("click", function(e) {
e.stopPropagation();
var ID = $(this).attr("id");
if($("#ac" + ID).hasClass('emoWrap-active')) {
$(".emoWrap").removeClass("emoWrap-active");
} else {
$(".emoWrap").removeClass("emoWrap-active");
$("#ac" + ID).toggleClass("emoWrap-active");
}
});
Like so: http://codepen.io/anon/pen/wMqZqY
Sorry, didn't test. Although you do not need both clicks. You can remove from all the classes then just add the one you want:
e.stopPropagation();
var ID = $(this).attr("id");
$(".emoWrap").removeClass("emoWrap-active"); // Add this
$("#ac" + ID).addClass("emoWrap-active");

Hide div with jquery but can't work out the logic to target correct div

At the moment I'm trying to add a mouse click event listener on a h3 tag, when this tag is clicked it will slidetoggle a div.
Here is my HTML
<div class="gallery-wrapper">
<h3 class="visible-toogle"> >> Hide gallery</h3>
<div class="galleria">
<img src="../Images/spherefactor_001.png" data-title="Sphere factor image 1" data-description="Sphere factor">
<img src="../Images/spherefactor_002.png" data-title="Sphere factor image 2" data-description="Sphere factor">
<img src="../Images/spherefactor_003.png" data-title="Sphere factor image 3" data-description="Sphere factor">
</div>
</div>
and here is my javascript
$( document ).ready(function() {
$(".visible-toogle").click(function ()
{
var result = $(this).text();
if(result == " >> Show gallery")
{
$(this).text(" >> Hide gallery");
}
else
{
$(this).text(" >> Show gallery");
}
$(this).closest(".galleria").slideToggle( "slow", function()
{
});
});
});
What am I doing wrong?
Using next in jQuery might help you
$(this).next("div").slideToggle("slow", function () { });
Closest must be a parent. You need to use siblings there.
Use "first instead of closest:
$(this).first(".galleria").slideToggle("slow", function () {
jsfiddle
$(document).ready(function () {
$(".visible-toogle").click(function () {
var result = $(this).text();
var hText = result.indexOf("Hide") > -1 ? ">> Show gallery" : ">> Hide gallery";
$(this).text(hText);
//slide toggle.
$('.gallery-wrapper').find(".galleria").slideToggle(500, function () {
});
});
});
Fiddle Demo

Apply a loop in JS between X and XX

So I have been trying to think of how to explain this in a way that makes sense, but I will show you below, as it makes more sense.
I have this code that works fine but I want to shorten it down into a for each loop or something.
$('.holder1').on({
click: function(){
$('.box1').css({display: 'none'});
$('.text1').css({display: 'block'});
}
});
$('.holder2').on({
click: function(){
$('.box2').css({display: 'none'});
$('.text2').css({display: 'block'});
}
});
$('.holder3').on({
click: function(){
$('.box3').css({display: 'none'});
$('.text3').css({display: 'block'});
}
});
I have this going on up to 40+, and obviously this code is horrific.
You can refactor the HTML code to use a common class and data attributes. Something like this:
<div class="holder" data-box="box1" data-text="text1"></div>
<div class="holder" data-box="box2" data-text="text2"></div>
<div class="holder" data-box="box3" data-text="text3"></div>
Then you can have a single click handler for all classes:
$('.holder').on({
click: function(){
$('.' + $(this).data('box')).css({ display: 'none' });
$('.' + $(this).data('text')).css({ display: 'block' });
}
});
This avoids the needs for ugly loops to add multiple handlers and iterative id attributes, which always turns in to a maintenance nightmare.
To solve this problem it is possible to iterate over holder elements using jQuery Attribute Starts With selector (API docs):
$.each('[class^="holder"]', function(index, item) {
$(item).on('click', function() {
$('.box' + index).css({display: 'none'});
$('.text' + index).css({display: 'block'});
});
});
I would prefer using some common class, though, as Rory McCrossan pointed out in his answer.
for (var i = 0; i< 40; i++) {
$('.holder' + i ).on({
click: function(){
$('.box' + i).css({display: 'none'});
$('.text' + i).css({display: 'block'});
}
});
}
or just add a common class and use it.
try this:
use class .box and .text instead
var holder = $(".holder1");
for (var i = 2; i<= 40; i++) {
holder.add($(".holder"+i));
}
$(holder).on(
'click', function(){
$('.box').css({display: 'none'});
$('.text').css({display: 'block'});
}
});
Assuming holders and boxes sit in their respective containers, like
<div>
<div class="holder">a</div>
<div class="holder">b</div>
<div class="holder">c</div>
<div class="holder">d</div>
</div>
<div>
<div class="box">a</div>
<div class="box">b</div>
<div class="box">c</div>
<div class="box">d</div>
</div>
you can get rid of box/text numbers altogether:
$(".holder").click(function() {
var n = $(this).index();
$(".box").eq(n).show();
});
This way it will be much easier to add new elements or change their order.
Use:
$("*[class^='holder']").on({
click: function(){
var id = $(this).attr("class").replace("holder","");
$('.box'+id).css({display: 'none'});
$('.text'+id).css({display: 'block'});
}
});

Unable to set the click event for 2 images in jQuery

I have two images with the title "Show Options" it looks like this:
<a class="io-content-pane-header-button-right" style="right: 41px;"><img class="io-content-pane-header-button" src="/document/c947bf0e-0144-4fc8-8a33-ce0d0d698384/latest" title="Show Options"></a>
I have the following jQuery to display another div called "recordViewPopover" when this image is clicked.
$('img[title*=\"Show\"]').live('click', function(e) {
console.log('RECORD VIEW OPTION SELECTED!');
e.stopImmediatePropagation();
var position = $(this).parent().offset();
$('#recordViewPopover').css('top', (position.top + $(this).height()) - 50);
console.log(position);
$('#recordViewPopover').fadeToggle('fast');
if ($('img[title*=\"Show\"]').hasClass('active')) {
$(this).removeClass('active');
} else {
$('img[title*=\"Show\"]').addClass('active');
}
});
The problem is, I want to be able to show another DIV called "objectViewPopover" when the 2nd image is clicked. Right now, when I click on the 2nd image, only "recordViewPopover" is shown.
How can I solve this?
UPDATE:
here is a simpler scenario, I am just going through each of the images:
$('img[title*=\"Show\"]').each(function(index, value){
if(index === 0){
console.log('object');
$(this).live('click', function(e) {
console.log('OBJECT VIEW OPTION SELECTED!');
});
}
else
console.log('record');
});
Why doesn't the click bind to the first match?
If the positioning of the images in the DOM is consistent you could do something like
if($(this).is(':last-child'))...
Or you could give the images a unique class:
<a class="io-content-pane-header-button-right recordView" style="right: 41px;"><img class="io-content-pane-header-button" src="/some/src" title="Show Options"></a>
<a class="io-content-pane-header-button-right objectView" style="right: 41px;"><img class="io-content-pane-header-button" src="/some/other/src" title="Show Options"></a>
and do
if($(this).hasClass('objectView'))...
img1=$('img[title*=\"Show\"]')[0];
img2=$('img[title*=\"Show\"]')[1];
$(img1).live('click', function(e) {
console.log('RECORD VIEW OPTION SELECTED!');
e.stopImmediatePropagation();
var position = $(this).parent().offset();
$('#recordViewPopover').css('top', (position.top + $(this).height()) - 50);
console.log(position);
$('#recordViewPopover').fadeToggle('fast');
if ($(img1).hasClass('active')) {
$(this).removeClass('active');
} else {
$(img1).addClass('active');
}
});
$(img2).live('click', function(e) {
console.log('OBJECT VIEW OPTION SELECTED!');
e.stopImmediatePropagation();
var position = $(this).parent().offset();
$('objectViewPopover').css('top', (position.top + $(this).height()) - 50);
console.log(position);
$('objectViewPopover').fadeToggle('fast');
if ($(img2).hasClass('active')) {
$(this).removeClass('active');
} else {
$(img2).addClass('active');
}
});
I'm not great with jQuery, but try that.
In the images add data attribute, something like this
First Image: <img class="io-content-pane-header-button" data-divid="recordViewPopover"...>
Second Image: <img class="io-content-pane-header-button" data-divid="objectViewPopover"...>
and change
$('#recordViewPopover')
to
$('#' + $(this).data("divid"))
and change
$('img[title*=\"Show\"]')
to
$(this)
in your code.
Demo

javascript/jquery shorthand code and active function

I have this code i would like to know if there is a shorter way of writing it?
also which code do i need to make an active tab stay active when on the relevant div
thanks
$(document).ready(function () {
$(".overveiw").click(function () {
$(".div1").show();
$(".div2").hide();
$(".div3").hide();
$(".div4").hide();
$(".div5").hide();
});
$(".tour").click(function () {
$(".div2").show();
$(".div1").hide();
$(".div3").hide();
$(".div4").hide();
$(".div5").hide();
});
$(".websites").click(function () {
$(".div3").show();
$(".div1").hide();
$(".div2").hide();
$(".div4").hide();
$(".div5").hide();
});
$(".faq").click(function () {
$(".div4").show();
$(".div1").hide();
$(".div3").hide();
$(".div2").hide();
$(".div5").hide();
});
$(".support").click(function () {
$(".div5").show();
$(".div1").hide();
$(".div3").hide();
$(".div4").hide();
$(".div2").hide();
});
});
It looks like what you're trying to do is show one div and hide a bunch of others when other elements are clicked — e.g., a tabbed interface.
The easy way is to use something someone's already built for you, like jQuery UI's tabs.
But you can also easily relate the divs to show/hide (the panels) and the divs that you click on (the tabs) by giving them some information in common. For instance, if you put an attribute on the panels that identifies the tab they belong to, this gets a lot shorter:
$(".overview, .tour, .websites, .faq").click(function() {
var thisTab = $(this).attr("data-panel");
var container = $("#container");
container.find("div").hide();
container.find("div[data-panel=" + thisTab + "]").show();
});
...works if you put a data-panel attribute on both the tab and panel that agrees. Live example
But if you run that live example without JavaScript, notice how it doesn't degrade well. That's why you normally see this done with lists and anchors for navigation, e.g., like this:
<ul id='tabs'>
<li class="overview">Overview</li>
<li class="tour">Tour</li>
<li class="websites">Websites</li>
<li class="faq">FAQ</li>
</div>
<div id='container'>
<div id="overview">The overview panel</div>
<div id="tour">The tour panel</div>
<div id="websites">The websites panel</div>
<div id="faq">The FAQ panel</div>
</div>
With this code:
$("#container div:not(#overview)").hide();
$("#tabs > li > a").click(function() {
var thisTab = this.href;
var index = thisTab.indexOf("#");
if (index >= 0) {
thisTab = thisTab.substring(index + 1);
}
$("#container div").hide();
$("#" + thisTab).show();
return false;
});
Live example
Give each of those divs another class:
<div class="div1 new_class"></div>
Then:
$(".overveiw").click(function () {
$(".new_class").hide();
$(".div1").show();
});

Categories

Resources