JQuery toggle between different divs - javascript

I need a some sort of a practical solution for toggle between different divs, when i click on a anchor tag.
I have done a JSfiddle that is kind of the solution i want.
the problem there is when i first click on "show 1" and then "show 2" the two first placeholders content disappear, but nothing new shows up.
I want it this way:
When i click "show 1", Two Placeholders appear(PlaceHolder 1 and 2).
When clicking "show 2" WITHOUT closing Placeholder 1 and 2. The PlaceHolder 1 and 2 should close AND PlaceHolder 3 should appear.
Jsfiddle: http://jsfiddle.net/CY3tj/2/
HTML:
<a id="1" class="show">show 1</a>
<br/ ><br/ >
<a id="2" class="show">show 2</a>
<div class="content-wrapper">
<div id="item-1">
<div>
<h2>Placeholder1</h2>
<p>Placeholder1</p>
</div>
<div>
<h2>PLaceHolder2</h2>
<p>Placeholder2</p>
</div>
</div>
<div id="item-2">
<div>
<h2>Placeholder3</h2>
<p>Placeholder3</p>
</div>
</div>
</div>
JQuery:
$(document).ready(function () {
$(".content-wrapper").hide();
});
$(document.body).on("click", "a.show", function () {
var id = $(this).attr("id");
$(".content-wrapper > div").each(function () {
if ($(this).attr("id") == "item-" + id) {
$(this).show();
} else {
$(this).hide();
}
});
$(".content-wrapper").toggle();
});

You can simplify this to:
$(function(){
var $allItems = $(".content-wrapper > div"); //Cache the collection here.
$(document).on("click", "a.show", function () {
var id = this.id, itemId = "#item-" + id; //get the id and itemId
$allItems.not($(itemId).toggle()).hide(); //Hide all items but not the one which is the target for which you will do a toggle
});
});
Demo
Instead of hiding the wrapper via JS, you can just add a rule to hide its contents.
.content-wrapper >div{
display:none;
}

Your main problem is your using $(.content-wrapper).toggle() You only want to hide the content wrapper initially and then after one click you want it to show up. By toggling your content wrapper you were making it dissapear every other click which was why you had to click twice to see it.
$(document.body).on("click", "a.show", function () {
var id = $(this).attr("id");
$(".content-wrapper > div").each(function () {
if ($(this).attr("id") == "item-" + id) {
$(this).show();
} else {
$(this).hide();
}
});
$(".content-wrapper").show();
});
If you are looking to keep the toggle functionality (to hide a div that is already showing) here is a solution for that.
$(document.body).on("click", "a.show", function () {
var id = $(this).attr("id");
if($(".content-wrapper #item-"+id).is(':visible'))
$(".content-wrapper").hide();
else{
$(".content-wrapper").children("div").hide();
$(".content-wrapper #item-"+id).show();
$(".content-wrapper").show();
}
});

You would gain more flexibility and performance by selecting the ids of the anchor tags. You should also hide the specific divs that you want to be hidden rather than hiding the overall container. That way, you can easily target which div you want to show and which one to hide.
$(document).ready(function () {
$(".content-wrapper > div").hide();
});
$("#1").click(function(){
$("#item-2").hide();
$("#item-1").show();
});
$("#2").click(function(){
$("#item-1").hide();
$("#item-2").show();
});
However, if you're looking to add an unknown number of these items, then you will want to select (for readability) just the element and class, rather than having to go through the document, which is just redundant.
$(document).ready(function () {
$(".content-wrapper > div").hide();
});
$("a.show").click(function(){
$(".content-wrapper > div").hide();
$("#item-" + $(this).attr("id").show();
});

Related

How to hide multiple jQuery toggle() when I click outside of the menu?

I have multiple toggle elements on my page. I am trying to get them closed when clicking on the outside of the div element. the script i have now works veyr well with multiple elements but it also closes the div when clicking on inside of the div
<ul>
<li class="menuContainer">
<a class="top" href="#">Menu</a>
<div class="sub">
<a class="top" href="google.com">item in dropdown menu with valid url when clicked here div.sub should stay close</a>
</div>
</li>
<li class="menuContainer">
<a class="top" href="#">Menu</a>
<div class="sub">
<a class="top" href="#">item in dropdown menu when clicked here div.sub should stay open</a>
</div>
</li>
$(document).ready(function(){
$('li.menuContainer').each(function() {
var $dropdown = $(this);
$("a.top", $dropdown).click(function(e) {
e.preventDefault();
$div = $("div.sub", $dropdown);
$div.toggle();
$("li.menuContainer div.sub").not($div).hide();
$( "#effect" ).hide();
return false;
});
$("li.menuContainer div.sub").on("click", function (event) {
event.stopPropagation();
});
});
$(document).on("click", function (){
$("li.menuContainer div.sub").hide();
});
});
what i want to do is to stop closing div when clicked inside of it. Any help please?
I think you are looking for e.stopPropagation();. Use it in an event on the child items.
This will stop the event from propagating to the parent div.
In your code the problem is inside the following function, now corrected:
$('html').click(function(event){
var ele = event.target.tagName + '.' + event.target.className;
if (ele != 'DIV.sub') {
$("li.menuContainer div.sub").hide();
}
});
Like you can see now when you click on whatever html element a check is done to prevent the undesired action.
use this code
$("li.menuContainer > a.top").click(function(e) {
e.preventDefault();
$div = $(this).next("div.sub");
$("li.menuContainer div.sub").not($div).slideUp();
$div.slideDown();
});
instead of
$('li.menuContainer').each(function() {
var $dropdown = $(this);
$("a.top", $dropdown).click(function(e) {
e.preventDefault();
$div = $("div.sub", $dropdown);
$div.toggle();
$("li.menuContainer div.sub").not($div).hide();
return false;
});
});
and about
$('html').click(function(){
$("li.menuContainer div.sub").hide();
});
you can use
$(window).on('click',function(e){
if (!$("li.menuContainer").is(e.target) // if the target of the click isn't the container...
&& $("li.menuContainer").has(e.target).length === 0) // ... nor a descendant of the container
{
$("li.menuContainer div.sub").slideUp();
}
});
Working Demo
Update:
$("div.sub > a.top").on('click',function(e) {
e.preventDefault(); // prevent page from reloading
e.stopPropagation(); // prevent parent click
alert('Here We Are :)');
});
Working Demo

Remove from inside div using jQuery

I have written a script that is supposed to render text (later a partial view) inside a div on click. I detect if div is visible or not and if not, I add text on click and make the div visible. This part works perfectly. When clicked and the div is visible I want to remove what has been added so that it wont multiply if I click it multiple times.
I get both alert - so detection of div visibility works but the text is not removed and it multiplies if I click it many times.
Here is my code - can you tell me what i am doing wrong?
<script language="javascript">
$(document).ready(function () {
$(".content").hide();
$(".heading").click(function () {
var id = $(this).attr("id");
var content = $(this).next(".content");
if (content.is(":hidden")) {
content.append("<p id='render-object'>Testing rendering on click</p>");
alert('Content is opening');
}
else if (content.is(":visible")) {
content.next("#render-object").remove();
alert('Content is closing');
}
content.slideToggle(100);
});
});
</script>
You probably want to use .find() instead of .next() when removing.
Use .html() instead of .append()
<script language="javascript">
$(document).ready(function () {
$(".content").hide();
$(".heading").click(function () {
var id = $(this).attr("id");
var content = $(this).next(".content");
if (content.is(":hidden")) {
content.html("<p id='render-object'>Testing rendering on click</p>");
alert('Content is opening');
}
else if (content.is(":visible")) {
content.find("#render-object").remove();
alert('Content is closing');
}
content.slideToggle(100);
});
});
</script>
Edit : - use .find() instead of .next() as render-object is child of content and not sibling
use .find instead of .next and use .html instead of .append
<script language="javascript">
$(document).ready(function () {
$(".content").hide();
$(".heading").click(function () {
var id = $(this).attr("id");
var content = $(".content");
if (content.is(":hidden")) {
content.html("<p id='render-object'>Testing rendering on click</p>");
alert('Content is opening');
}
else if (content.is(":visible")) {
content.find("#render-object").remove();
alert('Content is closing');
}
content.slideToggle(100);
});
});
</script>

.addClass to element adds a styling then removes, how do I fix

I have a code
var prev;
function addClass( classname, element ) {
prev = cn;
var cn = document.getElementById(element);
$(cn).addClass("selected");
}
The element in the dom look like this:
<div class="arrowgreen">
<ul>
<li>Manager</li>
<li>Planner</li>
<li>Administrator</li>
</ul>
</div>
For 'arrowgreen' I have a styling which changes the li styling on rollover and click.
When an element is clicked on, I want to apply the 'selected' classname to the element.
It does this for a split second and then reverts back.
The css looks like
.arrowgreen li a.selected{
color: #26370A;
background-position: 100% -64px;
}
Working jsFiddle Demo
In usage of $ in your code, I see that you are using jQuery.
There is no need to set onclick internally.
Let's jQuery handle it for you:
// wait for dom ready
$(function () {
// when user clicks on elements
$('.arrowgreen li a').on('click', function (e) {
// prevent default the behaviour of link
e.preventDefault();
// remove old `selected` classes from elements
$('.arrowgreen li a').removeClass('selected');
// add class `selected` to current element
$(this).addClass('selected');
});
});
Working JSFiddle
There was an error in your HTML, a " that opened a new string after onclick.
var prev;
function addClass(classname, element) {
var cn = document.getElementById(element);
prev = cn; //does nothing useful really
$(cn).addClass("selected");
}
<div class="arrowgreen">
<ul>
<li>Manager
</li>
<li>Planner
</li>
<li>Administrator
</li>
</ul>
</div>
Remember to include jQuery in your page!
There is a way to do this without jQuery anyway:
function addClass(classname, element) {
var cn = document.getElementById(element);
prev = cn; //does nothing useful really
cn.className += " " + classname;
}
Similar way to do it:
(function ($) {
$('.arrowgreen > ul > li > a').on('click', function (e) {
e.preventDefault();
$(this).addClass('selected').siblings().removeClass('selected');
});
}(jQuery));

a second click to close a toggle div

Iā€™m using the following jQuery for hiding and showing content (toggle), as a tree navigation menu in my website. I found this code extremely useful because by clicking, it displays only one div at a time.
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script type="text/javascript">
function show_region(chosen_region) {
$('.city_div').each(function(index) {
if ($(this).attr("id") == chosen_region) {
$(this).slideDown(200);
}
else {
$(this).slideUp(600);
}
});
}
</script>
<style type="text/css">
.city_div {display: none;}
</style>
North<br>
<div class="city_div" id="box01">Div #01</div>
Centre<br>
<div class="city_div" id="box02">Div #02</div>
South<br>
<div class="city_div" id="box03">Div #03</div>
The problem is that I can close a div only by opening another div.
How to close the div by a second click on it?
You can use slideToggle, change from slideDown to slideToggle:
function show_region(chosen_region) {
$('.city_div').each(function(index) {
if ($(this).attr("id") == chosen_region) {
$(this).slideToggle(200); // instead of slideDown
}
else {
$(this).slideUp(600);
}
});
}
First of all, don't use inline event handlers.
<script type="text/javascript">
$(document).ready(function() {
var boxes = $('.city_div');
$('.city-toggle').click(function(e) {
var box = $(this).next();
var isHidden = box.is(':hidden');
boxes.slideUp(600);
if(isHidden) {
box.slideDown(200);
}
e.preventDefault();
});
});
</script>
<style type="text/css">
.city_div {display: none;}
</style>
North
<div class="city_div" id="box01">Div #01</div>
Centre
<div class="city_div" id="box02">Div #02</div>
South
<div class="city_div" id="box03">Div #03</div>
Also, if your links don't go anywhere meaningful, use # as the href and make sure the boxes are visible by default. (Hide them using boxes.hide(); right at the start.)
Also also, <br> isn't what you should use there. <div>s are already block-level elements. If you want more padding, give them a top margin.
try this:
$(document).ready(function(){
$('.city_div').click(function(){
$(this).hide(); //or whatever code you want to hide it
});
});
that way when you click on a div, it will hide it.
Since you are using jQuery you could try using the jQuery.toggle function.
function show_region(chosen_region) {
$('#' + chosen_region).toggle('slide');
return false;
}
Keep track of the div you have clicked last:
var globalLastClickedButtonId;
$("div.city_div").click(function() {
if (globalLastClickedButtonId == $(this).attr("id")) {
$(this).hide();
} else {
var box = $(this).next().next();
var clickedId = $(this).attr("id");
$("div.city_div").each(function() {
if ($(this).attr("id") == clickedId)
box.slideDown(200);
else
box.slideUp(600);
}
}
globalLastClickedButtonId = $(this).attr("id");
});
First, why are you using such an old version of jQuery?
Second, your JavaScript can be simplified. jQuery works on sets; you don't need the .each, or loops.
Here is a working example: http://jsfiddle.net/gibble/25P9z/
Simplified HTML:
North<br>
<div class="city_div" id="box01">Div #01</div>
Centre<br>
<div class="city_div" id="box02">Div #02</div>
South<br>
<div class="city_div" id="box03">Div #03</div>ā€‹
New JavaScript:
function show_region(e) {
var $target = $(e.target);
var chosen_region = $target.attr('data-contentDiv');
var openDiv = $('#' + chosen_region);
openDiv.slideDown(200);
$('.city_div').not(openDiv).slideUp(600);
}
Last, attach events, don't inline them in your HTML.
$('a[data-contentDiv]').click(show_region);ā€‹
Because you are using an animation it is best to keep track of the div that is currently shown. If you don't, then you will start to see multiple divs showing if you click links in quick succession.
You can use this:
$(function() {
$("a").click(function(e) {
e.preventDefault();
var selectedDiv = $("#" + $(this).attr("href"));
var hide = selectedDiv.data("shown");
$(".city_div").slideUp(600);
$(".city_div").data("shown", false);
if (hide) {
selectedDiv.data("shown", false);
}
else {
selectedDiv.data("shown", true);
selectedDiv.slideDown(200);
}
});
});ā€‹
Here is a working example
You should keep a variable with your old chosen region name
<script type="text/javascript">
var old_chosen_region="";
function show_region(chosen_region) {
$('.city_div').each(function(index) {
if (($(this).attr("id") == chosen_region)&&(chosen_region!=old_chosen_region)) {
$(this).slideDown(200);
old_chosen_region=chosen_region;
} else {
$(this).slideUp(600);
}
}
old_chosen_region='';
});
</script>
This allows you to 'remember' which region you chose last and, if the chosen one equals the last you close it.
You should set old_chosen_region='' in the end to let the tab reopen.

JQuery Fading Problem

I have a menu which has 8 pictures and I want to write a fade effect for them. I want to show the name of the menu when the mouse goes over it, and hide it when mouse goes out. Here is my code for two of my menu items:
$(".menu_account").mouseover(function(){
$("#menu_name").html('first');
$("#menu_name").fadeIn('slow', function(){
$(".menu_account").mouseout(function(){
$("#menu_name").fadeOut('slow', function(){});
})
});
});
$(".menu_myposts").mouseover(function(){
$("#menu_name").html('second');
$("#menu_name").fadeIn('slow', function(){
$(".menu_myposts").mouseout(function(){
$("#menu_name").fadeOut('slow', function(){});
})
});
});
My problem is when I am on the first item and the name has been appeared, when I move the cursor to the second item before the first fades out, the name's innerHTML changes and it gets ugly. I want to wait for fading out to be completed and start again. I really appreciate any help.
thanx.
Here is my full code:
HTML :
<div id="menu">
<a class="menu_account"></a>
<a class="menu_myposts"></a>
<a class="menu_allposts"></a>
<a class="menu_favorites"></a>
<a class="menu_follow"></a>
<a class="menu_logout"></a>
<a class="menu_help"></a>
<a class="menu_contact"></a>
</div>
<div style="height:20px;width:200px;margin:0 auto;text-align:center;">
<div id="menu_name" style="font-size:30px;color:#A1A1A1;display:none;"></div>
</div>
JS :
$("#menu").ready(function(){
$(".menu_myposts").hover(
function () {
$("#menu_name").html('first');
$("#menu_name").fadeIn('slow', function(){});
},
function () {
$("#menu_name").fadeOut('slow', function(){});
}
);
$(".menu_myposts").hover(
function () {
$("#menu_name").html('second');
$("#menu_name").fadeIn('slow', function(){});
},
function () {
$("#menu_name").fadeOut('slow', function(){});
}
);
});
Correct JS:
$(".menu_item").hover(
function() {
$("#menu_name").html($('#' + this.id + '_name').html());
$("#menu_name").stop(true, true).fadeIn();
},
function() {
$("#menu_name").stop(true, true).fadeOut();
}
);
I guess the mouseout event should be defined outside like this:-
$(".menu_account").mouseover(function(){
$("#menu_name").html('first');
$("#menu_name").fadeIn('slow', function(){
});
});
$(".menu_account").mouseout(function(){
$("#menu_name").fadeOut('slow', function(){});
})
That's why the fadeout happens immediately.
You could reuse the code like this :-
var menuClasses = {'menu_account' : 'first', 'menu_classes' :'second'};
$.each(menuClasses function(index, value) {
$("."+value).hover(dothisOnMouseover(value), dothisOnMouseout())
});
$("td").hover(
function () {
$(this).addClass("hover");
},
function () {
$(this).removeClass("hover");
}
);
function dothisOnMouseover(value)
{
$("#menu_name").html(value);
$("#menu_name").fadeIn('slow', function(){});
}
function dothisOnMouseout()
{
$("#menu_name").html('');
$("#menu_name").fadeOut('slow', function(){});
}
Updates
The solution is to somehow check inside dothisOnMouseout() if the fadeIn() has completed already. But I don't know how to do that. So, I have this other trick to enable mouseover only if fadeOut() is complete -
function dothisOnMouseover(value)
{
//Remove the `onmouseover="dothisOnMouseover()" binding of all other menus here - or may be all menus - check it.
$("#menu_name").html(value);
$("#menu_name").fadeIn('slow', function(){
//On completion of this fade in attach back the `onmouseover="dothisOnMouseover"` event binding all other menus here - Note - do not call `dothisOnMouseout()` here
});
}
Doing so, if you hover on any menu before the fadeOut() completes, nothing will happen. try it out.
I've created a Fiddle that might be interesting. It is similar to the one in this post with the difference that the names of the menu items are created on the fly.
The code from the fiddle:
$("#menu li").hover(
function() {
if (!$(this).data("name")) {
$(this).data("name",
$('<div class="name"></div>')
.text($(this).text())
.hide()
.appendTo("#nameWrapper"));
}
$(this).data("name")
.stop(true, true)
.fadeIn();
},
function() {
$(this).data("name")
.stop(true, true)
.fadeOut();
}
);
The idea is to have a name element for every menu item so you get a nice fade effect when the old name fades out and new one fades in at the same time.
The first part of the first hover function creates a name element if there isn't one. The element is connected with the menu item using the data() function.
The second part of the first hover function just fades in the name element. The second function fades it out.
The trick here is to use stop(true, true) to stop all animation on the element.
EDIT:
You start with a html structure like this one:
<ul id="menu">
<li>First</li>
<li>Second</li>
</ul>
<div id="nameWrapper"></div>
And after a couple of mouseover's over the menu items the nameWrapper div gets filled like so:
<div id="nameWrapper">
<div class="name">First</div>
<div class="name">Second</div>
</div>
The div.name elements is what actually gets shown when you hover over the menu items. The div.name elements are created when you hover over the menu item for the first time, in the folowing code section:
$(this).data("name", // associate the <div class="name"> element with the menu item that is currently hovered - $(this)
$('<div class="name"></div>') // create a div element
.text($(this).text()) // set text inside div to text of the menu item
.hide() // hide the div (it gets faded in later)
.appendTo("#nameWrapper")); // append the element to the element with id nameWrapper
Edit: See this jsFiddle code
I would bind all your menu items at once with a class name with an id attached to each one, like (I'm just guessing your HTML structure here):
<ul id="menu">
<li class="menu-item" id="account">Account</li>
<li class="menu-item" id="myposts">My Posts</li>
</ul>
And your javascript might be something like the below. Keep in mind that it's untested though, and I'm not sure what effect it would have on performance.
bindMouseOver();
$('.menu-item').mouseout(function(){
$('.menu-item').unbind('mouseover'); //disable all mouseovers while fadeOut is happening
$("#menu_name").fadeOut('slow', function(){
bindMouseOver(); //rebind the mouseover event after the fadeOut is completed
});
});
var bindMouseOver = function(){
$('.menu-item').mouseover(function(){
$("#menu_name").html($(this).html()); //use the menu item's innerHTML text, or something else if you prefer
$("#menu_name").fadeIn('slow');
});
};
Here is a JSFiddle I made that kind of simplifies all the JS into one hover listener: Example here
[EDIT] updated to auto load the menu title container...
Code to example:
CSS
#menu_name div{
position:absolute;
display:none;
}
.menu_link{
cursor:pointer;
}
HTML
<div id="menu_name"></div>
<br/>
<div id="menu_account" class="menu_link">link 1</div>
<div id="menu_myposts" class="menu_link">link 2</div>
JavaScript
(function() {
//auto-load the menu title container...
$(".menu_link").each(function(index, item) {
$('#menu_name').append('<div id="' + item.id + '-title">' + item.innerHTML + '</div>');
});
$(".menu_link").hover(
function() {
$('#' + this.id + '-title').fadeIn('medium');
}, function() {
$('#' + this.id + '-title').fadeOut('medium');
});
})();

Categories