Suppose I have some divs which I want to allow users to switch between. I would write functions like this:
show_A = function () {$('.a').show(); $('.b').hide(); $('.c').hide();}
show_B = function () {$('.a').hide(); $('.b').show(); $('.c').hide();}
show_C = function () {$('.a').hide(); $('.b').hide(); $('.c').show();}
Then attach these functions to links or whatever. What's the best practice for abstracting out this sort of behavior? The total amount of code grows at N^2 with the number of divs, which is no good.
Give all those divs that you want to hide a common class name and then show one of those. like:
html:
<div class="a toggle">a div</div>
<div class="b toggle">b div</div>
<div class="c toggle">c div</div>
Now the js:
show_A = function () {$('.toggle').hide(); $('.a').show();}
show_B = function () {$('.toggle').hide(); $('.b').show();}
show_C = function () {$('.toggle').hide(); $('.c').show();}
The way I've handled this is before was just to hide them all then show the one (or ones) that you want visible.
Something like...
var showSingleDiv = function(klass) {
$('.container > div').hide();
$(klass).show();
};
Granted you don't want to hide every div so you'll need to setup whatever .container is with your own markup.
For each click, you could hide all the divs and then show only the one you need.
You could use a class to tag the divs involved...
<div id="a" class="collapse">...</div>
<div id="b" class="collapse">...</div>
<div id="c" class="collapse">...</div>
And use:
$(".collapse").hide();
You can do something like, by adding a common class to all those elements:
<div class="toggle">a</div>
<div class="toggle">b</div>
<div class="toggle">c</div>
$('.toggle').click(function(){
$('.toggle:visible').hide(); //Hide all visible 'toggle' div's
$(this).show(); //Show the clicked div
});
You can use the :not() selector.
show_A = function () {$('.a').show(); $('div:not(.a)').hide();}
Maybe I'm not understanding the question, but it seems like what he's wanting is something along these lines:
$('div').each().click( function(){
var cls = $(this).attr('class');
if( $("div[class*='"+cls+"']").is(':visible')){ $("div[class*='"+cls+"']").hide();}//
else{ $("div[class*='"+cls+"']").show(); }
}
);
//Disclaimer - I did not check to see if the concatenated selector works, but adapted it from a reputable blog.
Related
I have a project In which i want to select all the elements that have following classes: .GB1, .GB2, .GB3, .GB4, .GB5 and this will continue until .GB400.I also have other elements which contain the following types of classes .GB, .GBholder, .GB_color, .GB-size and I don't want to select this elements. I don't have any other element classes which starts with .GB and after .GB it have number like .GB1 or GB20. So I have a idea. But I don't know how to do this with jquery or javascript.The idea is "I Will tell the browser that, select all the elements that started with .GB and after .GB It have one or many numbers." Is it possible? How can I do it via js or jquery?
Here is the code I am trying now:
$('.color').on('click', function() {
$('*[class^="GB"]').css("background-color","red");
})
I have already wrote all the html and some long css by this classes. So It will take too many time change this class names.
You can use filter() and isNaN() method like following.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="GB1">GB1</div>
<div class="GB2">GB2</div>
<div class="GB3">GB2</div>
<div class="GBholder">GB holder</div>
<div class="GB_color">GB color</div>
<input type="button" value="Click" class="color"/>
<script>
$('.color').on('click', function () {
$('[class^="GB"]').filter(function () {
return isNaN($(this).attr('class').slice(2)) == false;
//if your elements has more than one class then add GB first and try this
//var cl = $(this).attr('class').split(' ')[0];
//return isNaN(cl.slice(2)) == false;
}).css("background-color", "red");
})
</script>
I've seen a few articles about this dotted around but I cant seem to get their solutions to work for me.
What I have are two buttons which control the show() and hide() states of different div's. On page load both of the div's are set to .hide() as the user doesn't need to see them until clicked.
So, I have two buttons a and b which currently work perfectly however you can show() both div's at the same time which I don't want to happen. The current code resembles
$('#a-div).hide();
$('#b-div).hide();
$('#a').click(function(){
$('#a-div).toggle(500);
});
$('#b').click(function(){
$('#b-div).toggle(500);
});
So how can I re-write this so that if #a-div is visible (already tried the .is(':visible') method) and #b is clicked nothing happens until #a-div is hidden again and vis versa?
Try this
$('#a-div').hide();
$('#b-div').hide();
$('#a').click(function(){
$('#a-div').toggle(500);
if($('#b-div').is(":visible"))
$('#b-div').hide();
});
$('#b').click(function(){
$('#b-div').toggle(500);
if($('#a-div').is(":visible"))
$('#a-div').hide();
});
probably you need to apply concept like this
$('#a-div).hide();
$('#b-div).hide();
$('#a').click(function(){
if ($('#b').isVisible)[you can check via css property as well]
{
$('#b-div).toggle(500); [or set css property visiblity:hidden]
$('#a-div).toggle(500);
}
else {$('#a-div).toggle(500);}
});
$('#b').click(function(){
if ($('#a').isVisible)[you can check via css property as well]
{
$('#a-div).toggle(500); [or set css property visiblity:hidden]
$('#b-div).toggle(500);
}
else {$('#b-div).toggle(500);}
});
What I ended up doing is this
$('#a-div').hide();
$('#b-div').hide();
$('#a').click(function(){
$('#a-div').toggle();
$('#b-div').hide();
});
$('#b').click(function(){
$('#b-div').toggle();
$('#a-div').hide();
});
For anyone who is interested. Prior to this I was making this much more complex than it needed to be.
Another solution is to create a universal function and pass the parameters of the shown and hidden objects. This way you can use the same method for future elements:
function toggleDivs($show, $hide) {
$show.toggle();
$hide.hide();
}
$("#b").on("click", function() { toggleDivs($("#b-div"), $("#a-div")); });
$("#a").on("click", function() { toggleDivs($("#a-div"), $("#b-div")); });
The only item missing is to initially hide the div objects, but I would add a css class to the objects to hide them.
HTML
<button id="a">Show A</button>
<button id="b">Show B</button>
<div id="a-div" class="hideDiv">A</div>
<div id="b-div" class="hideDiv">B</div>
CSS
.hideDiv { display:none; }
var $aDiv = $('#a-div');
var $bDiv = $('#b-div');
var $aBtn = $('#a');
var $bBtn = $('#b');
$aDiv.hide();
$bDiv.hide();
$aBtn.click(function(){
$aDiv.toggle(500, function(){
if($aDiv.is(":visible"))
$bBtn.prop("disabled",true);
else
$bBtn.prop("disabled",false);
});
});
$bBtn.click(function(){
$bDiv.toggle(500, function(){
if($bDiv.is(":visible"))
$aBtn.prop("disabled",true);
else
$aBtn.prop("disabled",false);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="a-div">div a</div>
<div id="b-div">div b</div>
<button id="a">btn a</button>
<button id="b">btn b</button>
I have some divs that need to be hidden (class named .hideable), and some divs that need to be shown (class named .toggleable. I have it working so far, which is great, but I`m having difficulties with the following; The hidden divs (.hideable) need to come back after the toggleable divs are hidden again.
here is what I have:
jQuery(document).ready(function($) {
var topContainer = $(".toggleable");
var topButton = $(".orsp a");
topButton.click(function() {
topContainer.slideToggle('slow');
$(".hideable").hide();
});
});
all help is welcome!
thanks,
J.
Use jQuery.toggle()
$(".hideable").toggle();
instead of jQuery.hide()
I think you wnat try like this
HTML
<div style='display:none' class='hideable' >Hidden Div</div>
<div class='toggleable'>Toggleable div</div>
<input class='topButton' type='button' value='toggle'>
JS
$('.topButton').click(function() {
$('.toggleable').slideToggle('slow', function() { $(".hideable").slideToggle(); });
});
Fiddle Here
If you don't want to use toggle to hide the .hideable div you can hide it using CSS and whenever you toggle .toggleable div you can check with Jquery whether it is hidden and if it is you can change it back to be shown. However Jakub's answer is the simplest solution.
jQuery(document).ready(function($) {
var topContainer = $(".toggleable");
var topButton = $(".orsp a");
topButton.toggle(function() {
topContainer.slideToggle('slow');
$(".hideable").hide();
},function () {
topContainer.slideToggle('slow');
$(".toggleable").hide();
});
});
Simplest choose toggle or toggle class
Fiddle
<http://jsfiddle.net/gcsHg/>?
I have a redundant process for making div's visible / hidden and I believe the way to make it more efficient is to use a loop.
Currently I have numerous div's through the document but there are 6 in particular that I want to deal with. I have a series of buttons that correspond to the six div's. When person clicks button A I want to show (make visible) div A and hide Div's B,C,D,E,F. My javascript is something like this:
<a href="#" onclick="ShowMe('A'); return false" />
<a href="#" onclick="ShowMe('B'); return false" />
<a href......etc />
<div id="A">blah...blah</div>
<div id="B">blah...blah</div>
<script type="java....">
function ShowHideDiv(DivName)
{
if(DivName == 'A')
{
var diva = document.getElementById('A');
div.style.visibility = 'visible';
var divb = document.getElementById('B');
div.style.visibility = 'hidden';
etc....
}
else if (DivName == 'B')
{
var diva = document.getElementById('A');
div.style.visibility = 'hidden';
var divb = document.getElementById('B');
div.style.visibility = 'visible';
etc...............
}
}
</script>
So as mentioned a prime candidate for loop but my question is how to contain the loop. For example if my loop went through the entire document object then I would have divs that I want visible being hidden so how do I avoid this?
I had two thought but was if others had additional thoughts, ideas, techniques etc.
Give my divs a really oddball prefix to their name like ShowHide_A then my loop can go through all the divs in the document object, parse it's name, if it doesn't have the prefix then move to the next one. This of course would be very inefficient if we had a large document and the script was getting every object and parsing then checking the name.
Wrap the div's in question in a parent container such as:
Then my javascript could be contained to looping through just the DivParent tree. But what if my div's are at different places in the document model? Do I keep them in the ParentDiv and position then where they belong with with css position properties?
Any other ideas would be greatly appreciated
JB
Let me suggest a better approach.
If you can use jQuery, you can do the following:
Assign a class (e.g. box) to all of your divs. Then your button needs to call this function:
function toggleDiv (divID) {
$(".box").hide();
$("#"+divID).show();
}
What you can also do is assign e.g. data-div attribute to your button which contains the ID of the div to hide/show, and then you can transform the above to the following (assuming your buttons have the button class):
$(".button").click(function () {
var divID = $(this).attr("data-div");
$(".box").hide();
$("#"+divID).show();
});
The above covers everything, assigning events to the buttons and hiding/showing divs.
see suppose you have markup like this
<div id="A" class="marked" >A</div>
<div id="B" class="marked" >B</div>
<div id="C" class="marked" >C</div>
<div id="D" class="marked" >D</div>
<div id="E" class="marked" >E</div>
<input type="button" value="Show A" data-target-div="A" />
<input type="button" value="Show B" data-target-div="B" />
then add a script like this:
$('input[type=button]').click(function(){
$('.marked').hide(200);
$('#'+$(this).data('target-div')).show();
});
it should work.
see this fiddle
so, you are not iterating through all the dom elements, you are picking exactly the ones you need to deal with. upon click, you hide all of them, and show the one which is target i.e. data-target-div
jQuery based solution:
Add a class to your div's that allow hiding/showing and then do
function ShowHideDiv(DivName)
{
$(".ShowHide").not("#" + DivName).hide();
$("#" + DivName).show();
}
Add class='switchable' (or whatever) to each such DIV then using prototype.js you could do something like this
function showMe( elem ) {
$$( '.switchable' ).each( function( switchable ) {
if ( switchable.id == $(elem).id )
switchable.show();
else
switchable.hide();
} );
}
I just created script that shows/hides (toggles) block of HTML. There are four buttons that each can toggle its HTML block. When any HTML block is opened, but user has been clicked on other button than that HTML block's associated button... it hides that HTML block and shows new one.
Here is what I have at the moment:
$('.btn_add_event').click( function() {
$('.block_link, .block_photos, .block_videos').hide();
$('.block_event').toggle();
});
$('.btn_add_link').click( function() {
$('.block_event, .block_photos, .block_videos').hide();
$('.block_link').toggle();
});
$('.btn_add_photos').click( function() {
$('.block_event, .block_link, .block_videos').hide();
$('.block_photos').toggle();
});
$('.btn_add_videos').click( function() {
$('.block_event, .block_link, .block_photos').hide();
$('.block_videos').toggle();
});
Any ideas how to reduce code size? Also, this script isn't very flexible. Imagine to add two new buttons and blocks.
like Sam said, I would use a class that all the blocks share, so you never have to alter that code. Secondly, you can try 'traversing' to the closest block, therefore avoiding it's name. That approach is better than hard coding each specific block, but if the html dom tree changes you will need to refactor. Last, but best, you can pass in the class name desired block as a variable to the function. Below is something you can copy paste that is close to what you started with.
$('.myAddButtonClass').click( function() {
$('.mySharedBlockClass').filter(':visible').hide();
//find a good way to 'traverse' to your desired block, or name it specifically for now.
//$(this).closest(".mySharedBlockClass").show() complete guess
$('.specificBlockClass').show();
});
I kept reading this "When any HTML block is opened, but user has been clicked on other button than that HTML block's associated button" thinking that my eyes were failing me when Its just bad English.
If you want to make it more dynamic, what you can do is add a common class keyword. Then
when the click event is raise. You can have it loop though all the classes that have the
keyword and have it hide them all (except the current one that was clicked) and then show the current one by using the 'this' keyword.
you can refer below link,
http://chandreshmaheshwari.wordpress.com/2011/05/24/show-hide-div-content-using-jquery/
call function showSlidingDiv() onclick event and pass your button class dynamically.
This may be useful.
Thanks.
try this
$('input[type=button]').click( function() {
$('div[class^=block]').hide(); // I resumed html block is div
$(this).toggle();
});
Unfortunatly I couldn't test it, but if I can remember right following should work:
function toogleFunc(clickObject, toogleTarget, hideTarget)
{
$(clickObject).click(function()
{
$(hideTarget).hide();
$(toogleTarget).toggle();
});
}
And the call:
toogleFunc(
".btn_add_videos",
".block_videos",
".block_event, .block_link, .block_photos"
);
and so far
Assuming the buttons will only have one class each, something like this ought to work.
var classNames = [ 'btn_add_event', 'block_link', 'block_photos', 'block_videos' ];
var all = '.' + classNames.join(', .'); // generate a jquery format string for selection
$(all).click( function() {
var j = classNames.length;
while(j--){
if( this.className === classNames[j] ){
var others = classNames.splice(j, 1); // should leave all classes but the one on this button
$('.' + others.join(', .')).hide();
$('.' + classNames[j]).toggle();
}
}
}
All the buttons have the same handler. When the handler fires, it checks the sender for one of the classes in the list. If a class is found, it generates a jquery selection string from the remaining classes and hides them, and toggles the one found. You may have to do some checking to make sure the strings are generating correctly.
It depends by how your HTML is structured.
Supposing you've something like this
<div class="area">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>
...
<div class="sender">
<a class="one"></a>
<a class="two"></a>
<a class="three"></a>
</div>
You have a class shared by the sender and the target.
Your js would be like this:
$('.sender > a').click(function() {
var target = $(this).attr('class');
$('.area > .' + target).show().siblings().hide();
});
You show your real target and hide its siblings, which aren't needed.
If you put the class postfixes in an array, you can easily make this code more dynamic. This code assumed that it doesn't matter in which order toggle or hide are called. If it does matter, you can just remember the right classname inside the (inner) loop, and toggle that class after the loop.
The advantage to this approach is that you can extend the array with an exta class without needing to modifying the rest of the code.
var classes = new Array('videos', 'event', 'link', 'photos');
for (var i = 0; i < classes.length; ++i)
{
$('.btn_add_' + classes[i]).click(
function()
{
for (var j = 0; j < classes.length; ++j)
{
if (this.hasClass('btn_add_' + classes[j]))
{
$('.block_' + classes[j]).toggle();
}
else
{
$('.block_' + classes[j]).hide();
}
}
});
}
You could make this code more elegant by not assigning those elements classes like btn_add_event, but give them two classes: btn_add and event, or even resort to giving them id's. My solution is based on your description of your current html.
Here is what I think is a nice flexible and performant function. It assumes you can contain your links and html blocks in a parent, but otherwise it uses closures to precalculate the elements involved, so a click is super-fast.
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js" ></script>
<script type="text/javascript">
// Enables show/hide functionality on click.
// The elements within 'container' matching the selector 'blocks' are hidden
// When elements within 'container' matching the selector 'clicker' are clicked
// their attribute with the name 'clickerAttr' is appended to the selector
// 'subject' to identify a target, usually one of the 'blocks'. All blocks
// except the target are hidden. The target is shown.
//
// Change clickerAttr from 'linkTarget' to 'id' if you want XHTML compliance
//
// container: grouping of related elements for which to enable this functionality
// clicker: selector to element type that when clicked triggers the show/hide functionality
// clickerAttr: name of the DOM attribute that will be used to adapt the 'subject' selector
// blocks: selector to the html blocks that will be shown or hidden when the clicker is clicked
// subject: root of the selector to be used to identify the one html block to be shown
//
function initToggle(container,clicker,clickerAttr,blocks,subject) {
$(container).each(
function(idx,instance) {
var containerElement = $(instance);
var containedBlocks = containerElement.find(blocks);
containerElement.find(clicker).each(function(idxC, instanceClicker) {
var tgtE = containerElement.find(subject+instanceClicker.getAttribute(clickerAttr));
var clickerBlocks = containedBlocks.not(tgtE);
$(instanceClicker).click(function(event) {
clickerBlocks.hide();
tgtE.toggle();
});
});
// initially cleared
containedBlocks.hide();
}
);
}
$(function() {
initToggle('.toggle','a.link','linkTarget','div.block','div.');
});
</script>
</head>
<body>
Example HTML block toggle:
<div class="toggle">
a <br />
b <br />
c <br />
<div class="A block"> A </div>
<div class="B block"> B </div>
<div class="C block"> C </div>
</div> <!-- toggle -->
This next one is not enabled, to show scoping.
<div class="toggle2">
a <br />
<div class="A block">A</div>
</div> <!-- toggle2 -->
This next one is enabled, to show use in multiple positions on a page, such as in a portlet library.
<div class="toggle">
a <br />
<div class="A block">A</div>
</div> <!-- toggle (2) -->
</body>
</html>