I am using JS to show/hide divs via clicking on the side nav with jquery functions fadeIn() and fadeOut(). The problem I run into is as one div fades out, the next is fading in simultaneously. Also, if I click the link for the div that is already shown, it fades out and fades in again. I'm not sure if an IF statement would be the best approach to do two fixes:
1. Let shown div fully fadeOut before next starts to fadeIn.
2. Currently shown div will not fadeOut/In if same link is clicked.
Here is what I have thus far (without my broken attempt at an IF statement):
http://jsfiddle.net/k55Cw/1/
HTML:
<div class="container">
<header>
<ul class="sidenav">
<li><h2><a data-region="nav-1" href="#">About</a></h2></li>
<li><h2><a data-region="nav-2" href="#">Services</a></h2></li>
<li><h2><a data-region="nav-3" href="#">Team</a></h2></li>
<li><h2><a data-region="nav-4" href="#">News</a></h2></li>
<li><h2><a data-region="nav-5" href="#">Contact</a></h2></li>
</ul>
</header>
<div id="nav-1" class="infozone"><p>Hello I'm box 1.</p></div>
<div id="nav-2" class="infozone"><p>Hello I'm box 2.</p></div>
<div id="nav-3" class="infozone"><p>Hello I'm box 3.</p></div>
<div id="nav-4" class="infozone"><p>Hello I'm box 4.</p></div>
<div id="nav-5" class="infozone"><p>Hello I'm box 5.</p></div>
</div>
CSS:
.infozone{
float:left;
height:400px;
width:800px;
background-color: #000;
display:none;
}
JS:
$(document).ready(function() {
$('.sidenav a').click(function(){
$('.infozone').fadeOut(850);
var region = $(this).attr('data-region');
$('#' + region).fadeIn(850);
});
});
to chain the animations put the fadeIn inside the callback for fadeOut, and to cancel the function if it's currently shown, check if the div is already visible.
I've also had to add a check to see if the current .infozone div is visible - or else the fadeOut applies to hidden elements too, and the callback fires multiple times:
$(document).ready(function() {
$('.sidenav a').click(function(){
var region = $(this).attr('data-region');
var $region = $('#' + region);
if ($region.is(':visible')) return;
var $infozone = $('.infozone:visible');
if ($infozone.length === 0) {
$region.fadeIn(850);
} else {
$infozone.fadeOut(850, function() {
$region.fadeIn(850);
});
}
});
});
You could something like that:
html
This make you page works when javascript is disabled:
<header>
<ul class="sidenav">
<li><h2>About</h2></li>
<li><h2>Services</h2></li>
<li><h2>Team</h2></li>
<li><h2>News</h2></li>
<li><h2>Contact</h2></li>
</ul>
</header>
note that the href point to the id you want to show. This will works also for screen reader if you want to make your page accessible.
javascript. I have not tested it, you might have to fix few things, but the idea is there
$(document).ready(function() {
$('.sidenav a').click(function(e){
var href = $(this).attr('href');
// prevent default
e.preventDefault();
// prevent clicked twice
if(!$(this).hasClass('active'){
$('.sidenav a').removeClass('active');
$(this).addClass('active'){
$('.infozone').fadeOut(850);
$(href.substring(1)).fadeIn(850);
}
});
You should also consider adding some ARIA attributes and roles attributes.
Related
I want to display a <div> block when mouse enters an element
My code so far:
<div class="dropdown">
MEN
<div class="dropdowncontent" id="ddmen" style="margin-left:100px;">
TOPWEAR <br/>
BOTTOMWEAR </br>
FOOTWEAR
</div>
</div>
JavaScript Code:
var ddm=document.getElementById("ddmen")
function ddmenin()
{
ddm.style.display="block";
}
function ddmenout()
{
ddm.style.display="none";
}
But when i hover over <a href="#men"> I cannot click on the links in the <div> with class="dropdowncontent" as the block disappears when i leave the <a href="#men">
I don't understand why this is happening since i have used onmouseover, which is valid even for child elements.
I have tried doing it using css but for some reason the following does not work (Style.css is used in above html)
STYLE.CSS
.dropdowncontent{
display:none;
}
.dropdown:hover .dropdowncontent{display:block;}
Can someone please correct my code to satisfy my needs or has any other simple alternative?
Well, your div link container is not part of a link, so when you move cursor to dropdown menu you leave the link and onmouseout listener does its job.
What you want is to hide the menu when it's not needed anymore. E.g. you clicked on the menu item or you left the menu and didn't return for some time.
To achieve this you can do the following:
Add hiding the menu to click listener on menu items
Add a function that starts some timer as soon as you leave the dropdown button or the menu (so that makes two onmouseout listeners). If you return there, you can reset the timer in onmouseover. When timer is done you can hide the menu.
It can look like this:
const $ = document.querySelector;
let menuTimeoutId;
const menu = $('#ddmen');
function stopMenuTimeoutAndShowMenu() {
if (menuTimeoutId) {
clearTimeout(menuTimeoutId);
menuTimeoutId = null;
}
menu.style.display = 'block';
}
function startMenuTimeout() {
window.menuTimeoutId = setTimeout(() => {
menu.style.display = 'none';
}, 2000); // possible timeout value
}
$('#men, #ddmen').addEventListener('onmouseover', stopMenuTimeoutAndShowMenu);
$('#men, #ddmen').addEventListener('onmouseout', startMenuTimeout);
I think you should use the onmouseover and onmouseout in your <div class="dropdown"> instead. Because, when you go to the div.dropdowncontent you probably invokes the onmouseout event. So the code will be like this:
<div class="dropdown" onmouseover="ddmenin()" onmouseout="ddmenout()">
MEN
<div class="dropdowncontent" id="ddmen" style="margin-left:100px;">
TOPWEAR <br/>
BOTTOMWEAR </br>
FOOTWEAR
</div>
</div>
See if it works ;D
You can try simple CSS changes, that can even help you :
In your Style.css file:
.dropdown .dropdowncontent {
visibility: hidden;
}
.dropdown:hover .dropdowncontent {
visibility: visible;
}
I'm stuck with a jQuery issue that I don't manage to solve.
I've created a menu with sub menu elements. I would like to toggle the height of content by clicking in menu items. The thing is when I click on other item, the content collapse. Kind of tricky to explain, I've put two websites doing the job
http://www.polerstuff.com/ -> When you click on 'shop' and then on 'info', the sub menu stays open. The same trick was seen here http://topodesigns.com/
I guess these two websites are using Shopify.
$(document).ready(function() {
$(".button").on("click", function() {
if($(".content").height() == 0) {
$(".content").animate({height: "300px"});
}
else if($(".content").height() == 300) {
$(".content").animate({height: "0px"});
}
});
});
Here is my jsfiddle
-> Thank a lot in advance.
Here's version of your fiddle that uses the data attribute to target divs with desired content, and another data tag containing desired heights to animate (but there are many other ways).
Clicking on the same button toggles it shut, this is achieved by adding an indicative class.
The 'hiding' divs may contain further divs with classes and layout as required.
$(document).ready(function (){
$(".b").on("click", function (){
var $this = $(this),
target = $this.data('target'),
tall = $this.data('tall'),
content = $(".content");
target = $('.'+target).html(); // get the html content of target divs
content.html(target); // insert said content
if (!$this.hasClass('on')) { // if it hasn't been clicked yet..
$(".b").removeClass('on'); // say that none have been clicked
$this.addClass('on'); // say that just this one has been clicked
content.animate({height: tall}, 200); // animate to the height specified in this buttons data attribute
} else {
content.animate({height: "0px"});
$this.removeClass('on');
}
});
});
.content {
background: coral;
width: 100%;
height: 0px;
overflow:hidden;
}
.hiding{
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<button class="b" data-target="alpha" data-tall="4em">Button</button>
<button class="b" data-target="bravo" data-tall="7em">Button</button>
<button class="b" data-target="charlie" data-tall="5em">Button</button>
<div class="content">Le contenu</div>
<div class="hiding alpha"> some stuff </div>
<div class="hiding bravo"> other things </div>
<div class="hiding charlie"> bits and pieces </div>
I am using a JavaScript function and some jQuery to perform two actions on a page. The first is a simple JS function to hide/show divs and change the active state of a tab:
This is the JS that show/hides divs and changes the active state on some tabs:
var ids=new Array('section1','section2','section3');
function switchid(id, el){
hideallids();
showdiv(id);
var li = el.parentNode.parentNode.childNodes[0];
while (li) {
if (!li.tagName || li.tagName.toLowerCase() != "li")
li = li.nextSibling; // skip the text node
if (li) {
li.className = "";
li = li.nextSibling;
}
}
el.parentNode.className = "active";
}
function hideallids(){
//loop through the array and hide each element by id
for (var i=0;i<ids.length;i++){
hidediv(ids[i]);
}
}
function hidediv(id) {
//safe function to hide an element with a specified id
document.getElementById(id).style.display = 'none';
}
function showdiv(id) {
//safe function to show an element with a specified id
document.getElementById(id).style.display = 'block';
}
The html:
<ul>
<li class="active"><a onclick="switchid('section1', this);return false;">ONE</a></li>
<li><a onclick="switchid('section2', this);return false;">TWO</a></li>
<li><a onclick="switchid('section3', this);return false;">THREE</a></li>
</ul>
<div id="section1" style="display:block;">TEST</div>
<div id="section2" style="display:none;">TEST 2</div>
<div id="section3" style="display:none;">TEST 3</div>
Now the problem....
I've added the jQuery image gallery called galleria to one of the tabs. The gallery works great when it resides in the div that is intially set to display:block. However, when it is in one of the divs that is set to display: none; part of the gallery doesn't work when the div is toggled to be visible. Specifically, the following css ceases to be written (this is created by galleria jQuery):
element.style {
display:block;
height:50px;
margin-left:-17px;
width:auto;
}
For the life of me, I can't figure out why the gallery fails when it's div is set to display: none. Since this declaration is overwritten when a tab is clicked (via the Javascript functions above), why would this cause a problem? As I mentioned, it works perfectly when it lives the in display: block; div.
Any ideas? I don't expect anybody to be familiar with the jQuery galleria image gallery... but perhaps an idea of how one might repair this problem?
Thanks!
If you are including jQuery then you can shorten your javascript to this:
$(function() {
var sections = $('#section1, #section2, #section3');
function switchid(id, el){
sections.hide();
$('#'+id).show();
$(this).addClass('active').closest('ul').find('li').removeClass('active');
}
});
I would also remove the inline styles that set display:none. Then you can in your javascript you can initialize galleria then hide your sections.
Something like:
$(function() {
$('#section2, #section3').hide();
$('#section2 .images').galleria();
var sections = $('#section1, #section2, #section3');
function switchid(id, el){
sections.hide();
$('#'+id).show();
$(this).addClass('active').closest('ul').find('li').removeClass('active');
}
});
I would even go further and change your html to be something like this:
<ul class="sectionlinks">
<li class="active">ONE</li>
<li>TWO</li>
<li>THREE</li>
</ul>
<div id="section1" class="section">TEST</div>
<div id="section2" class="section">TEST 2</div>
<div id="section3" class="section">TEST 3</div>
Then you javascript could just be:
$(function() {
$('#section2 .images').galleria();
$('#section2, #section3').hide();
var sections = $('.section');
$('.sectionlinks a').click(function(e){
e.preventDefault();
sections.hide();
$($(this).attr('href')).show();
$(this).closest('ul').find('li').removeClass('active');
$(this).closest('li').addClass('active');
});
});
Working example: http://jsfiddle.net/cdaRu/2/
Set them all to 'block' by default, initialize the galleria image gallery, and afterwards hide the divs you want hidden and see if that fixes it. Or try initializing the gallery again after every switchid.
My first recommendation would be to re-write your original Javascript function to use jQuery. It already has built-in visibility toggle functions ... using the same system will minimize conflicts and make for smoother code.
This is just "off the cuff" but perhaps the box model is incomplete: "The element will generate no box at all" with display: none;
Perhaps change that back to "block" and set visibility: hidden; would be better?
I have a number of dropdowns and divs that are hidden when the page loads and can be toggled with a click or mouseover, but some of them flash b/c the JavaScript does not run in time. I have their display initially set to block and then I use JavaScript/prototype to find the element and hide it. I have tried loading these "hider" functions using dom:loaded but there is still flashing. This is an example of a dropdown prototype initialization function. From
http://www.makesites.cc/programming/by-makis/simple-drop-down-menu-with-prototype/:
var DropDownMenu = Class.create();
DropDownMenu.prototype = {
initialize: function(menuElement) {
menuElement.childElements().each(function(node){
// if there is a submenu
var submenu = $A(node.getElementsByTagName("ul")).first();
if(submenu != null){
// make sub-menu invisible
Element.extend(submenu).setStyle({display: 'none'});
// toggle the visibility of the submenu
node.onmouseover = node.onmouseout = function(){
Element.toggle(submenu);
}
}
});
}
};
Is there a better way to hide div's or dropdowns to avoid this flashing?
You always run the risk of flicker when you try to hide elements after page load.
I suggest you give the elements in question an inline style like display:none; or a css class with the same setting.
From the class creation syntax used, I take it that you are using something like Prototype version 1.5.x. Here's my take on how I'd do it with that version (it would be nicer to step up to the latest version, of course):
<script type="text/javascript">
var DropDownMenu = Class.create();
DropDownMenu.prototype = {
initialize: function(menuElement) {
// Instead of using 2 listeners for every menu, listen for
// mouse-ing on the menu-container itself.
// Then, find the actual menu to toggle when handling the event.
$(menuElement).observe('mouseout', DropDownMenu.menuToggle);
$(menuElement).observe('mouseover', DropDownMenu.menuToggle);
}
};
DropDownMenu.menuToggle = function (event) {
var menu = DropDownMenu._findMenuElement(event);
if (menu) {Element.toggle(menu);}
};
DropDownMenu._findMenuElement = function (event) {
var element = Event.element(event);
return Element.down(element, 'ul');
}
var toggler = new DropDownMenu('menus');
</script>
And here is some markup to test it with (it may not match yours perfectly, but I think it is similar enough):
<html>
<head>
<title>menu stuff</title>
<style type="text/css ">
/* minimal css */
#menus ul, .menu-type {float: left;width: 10em;}
</style>
</head>
<body>
<h1>Menus</h1>
<div id="menus">
<div class="menu-type">
Numeric
<ul style="display: none;">
<li>1</li><li>2</li><li>3</li><li>4</li>
</ul>
</div>
<div class="menu-type">
Alpha
<ul style="display: none;">
<li>a</li><li>b</li><li>c</li><li>d</li>
</ul>
</div>
<div class="menu-type">
Roman
<ul style="display: none;">
<li>I</li><li>II</li><li>III</li><li>IV</li>
</ul>
</div>
</div>
</body>
</html>
Yoda voice: "Include the prototype.js, I forgot."
Should you want to get rid of inline styling (like I do), give the uls a class like
.hidden {display:none;}
instead, and make the DropDownMenu.menuToggle function do this
if (menu) {Element.toggleClassName(menu, 'hidden');}
instead of toggling the display property directly.
Hope this helps.
Set the display initially to none, then show them as needed. That will get rid of the flashing.
I'm creating a page with an image at the top, and a menu below. When the user clicks on on of the 3 menu buttons, the image slideUp and the page scrolls down so the menu is at the top of the page, then the right .content div fades in. The slideUp should only happen the first time the user clicks on of the buttons.
What the absolute best way to do this with jQuery? (no plugins)
I also need to know how I can't prevent it to fade in the page that is already visible if i click the same button twice?
I'm using rel instead of href, since the href made the page jump, even with return false.
This is what I have so far:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript">
$(function(){
imgVisible = true;
$('#mainmenu a').click(function(){
var $activeTab = $(this).attr('rel');
if(!imgVisible){
$('html:not(:animated),body:not(:animated)').animate({scrollTop:$('#mainmenu').offset().top-20},500);
$('.content').hide();
$($activeTab).fadeIn();
} else{
$('#imgholder').slideUp(500,function(){
imgVisible = false;
$('#mainmenu a[rel="'+$activeTab+'"]').click();
});
}
return false;
});
});
</script>
<div id="imgholder"><img src="image.jpg" /></div>
<div id="mainmenu">
<ul>
<li><a rel="#tab1"></a></li>
<li><a rel="#tab2"></a></li>
<li><a rel="#tab3"></a></li>
</ul>
</div>
<div id="container">
<div class="content" id="tab1">
content
</div>
<div class="content" id="tab2">
content
</div>
<div class="content" id="tab3">
content
</div>
</div>
The following code accomplishes what you need:
$('#mainmenu a').click(function(){
var myrel=$(this).attr('rel');
$('.content:not([id='+myrel+'])').hide();
$('#imgholder').slideUp(500,function(){
$('#'+myrel).fadeIn();
});
});
....
<li><a href='#' rel='tab0'></a></li>
I have removed the '#' sign from your rel='' piece ;-)
I am not sure why you would want to scroll the page. When a user clicks on the menu, he/she already has it focused (so it is visible inside the current viewport). But do you have a very large top image? If that is the case, let me know and I will modify the snippet. (Still, it depends on the amount of content below the menu visible when the page first loads.)
Also, for SEO reasons you might want to use the href instead of the rel attribute and create separate content holding pages. The following snippet would remove the navigation action.
$('#mainmenu a').each(function(){
var myhref = $(this).attr('href');
$(this).attr('href','#').attr('rel',myhref);
}).click(function(){
var myrel=$(this).attr('rel');
$('.content:not([id='+myrel+'])').hide();
//....etc
I think this is a great example of what your looking for: Organic Tabs
var imgVisible = true;
var $activeTab, $lastTab;
var $mainmenu = $('#mainmenu');
var offset = $mainmenu.offset().top - 20;
$mainmenu.find('a').click(function() {
$activeTab = $($(this).attr('rel'));
if (!imgVisible) {
// dont fire any events if already open
if ($lastTab.attr('id') == $activeTab.attr('id')) return false;
$lastTab.fadeOut('normal', function() {
$activeTab.fadeIn(500, function() {
$lastTab = $activeTab;
});
});
} else {
$('#imgholder').slideUp(500, function() {
imgVisible = false;
window.scrollTo(0, offset);
$activeTab.fadeIn(500, function() {
$lastTab = $activeTab;
});
});
}
return false;
});
I highly suggest adding <a href="#"> as this will not make the page jump when done properly and will ensure validation on your anchor links. Someone let me know if I missed something, it can be resolved quickly (or you can do it for me if you have an optimization or improvement).