In my web site, I have three pages: Home, About, and Contact. I want the current page's link to give some visual indication that clicking the corresponding link would be senseless as the user is already on that page. Is this task better handled by CSS or jQuery, and in either case, what is the most elegant solution that will also automatically apply to any pages which may be added in the future?
Here's my HTML diesbezueglich:
<nav>
<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
UPDATE
I wonder why this didn't work; I added to Site.css this:
nav ul li a.current {
color: blue;
}
And the relevant HTML is:
<nav>
<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
Yet the links remain the same (as Led Zeppelin predicted).
UPDATE 2
I tried this to test out kind of an amalgam of the various ideas proposed here:
In Site.css:
.current {
color: blue;
}
In _SiteLayout.cshtml:
<ul id="menu">
<li id="home" name="home">Home</li>
<li>About</li>
<li>Contact</li>
</ul>
In Default.cshtml:
<script type="text/javascript">
$(document).ready(function () {
$("#tabs").tabs();
$(".fancybox").fancybox();
$("home").addClass('current');
});
</script>
...but no go; the "Home" link is as homely as ever (no pun intended).
I also tried giving all of the links an id of "location" and adding this to Default.cshtml's "ready" function:
if ($(#location).attr('href').indexOf('home') != -1) $('home').addClass('currentPage');
else if ($(#location).attr('href').indexOf('about') != -1) $('about').addClass('currentPage');
else if ($(#location).attr('href').indexOf('contact') != -1) $('contact').addClass('currentPage');
(where "currentPage" is the css class that sets the color to blue, and each nav link has an id of "location"); I reckon I would also have to add a "removeClass" for the two links with an index of -1 in each if/else block.
My beer is getting saltier by the nanosecond.
UPDATE 3
I tried this:
Added the IDs to the elements in _SiteLayout.cshtml:
<nav>
<ul id="menu">
<li id="home">Home</li>
<li id="about">About</li>
<li id="contact">Contact</li>
</ul>
</nav>
And added this to Site.css:
#home {color: orange;}
#home.current {color: blue;}
#about {color: orange;}
#about.current {color: blue;}
#contact {color: orange;}
#contact.current {color: blue;}
...but it did nothing - all the links are still gray no matter where I navigate.
UPDATE 4
Also tried this to no avail:
if ($('#home').attr('href').indexOf('Home') != -1) $('#home').addClass('currentPage');
UPDATE 5
I wonder if there's a way to use the _PageStart.cshtml to handle this? IOW, could I do something like:
#{
Layout = "~/_Layout.cshtml";
//pseudocode follows
var currentPage = CurrentPage.Id;
}
//and then some jQuery (also pseudocode):
if #currentPage == Default {
#home.display = none;
else if #currentPage == About {
#about.display = none;
else if #currentPage == Contact {
#contact.display = none;
} // perhaps set them all visible from the git-go
UPDATE 6
Another possibility that "jQuery for ASP.NET Developers" has inspired is something like the following inside the "ready" function (pseudocode; if this would work, I welcome the specific jQuery I would need to flesh this out):
// first set all of the nav ul li to their default color, right? (not shown)
// now, color the current one chartreuse:
$("nav ul li").each(function() {
switch ($(this.name)) {
case 'home':
$(#home).css("color", "chartreuse");
break;
case 'about':
$(#about).css("color", "chartreuse");
break;
case 'contact':
$(#contact).css("color", "chartreuse");
break;
}
});
UPDATE 7
Well, I'm sure this is nobody's idea of elegant, but I did figure out a way to accomplish it by using a click event for each li. Elegantizations welcome to the jsfiddle here: http://jsfiddle.net/vV4h5/1/
As to the elegantization of the jsfiddle above, there must be a way to do something like this instead:
jQuery(function () {
$("nav ul li").css("color", "black");
var currentLI = theOneClicked; //??? how to get this???
$(currentLI).css("color", "blue");
});
UPDATE 8
It works in jsfiddle, but not in my project; Having this in _SiteLayout.cshtml:
<nav>
<ul id="menu">
<li id="home">Home</li>
<li id="about">About</li>
<li id="contact">Contact</li>
</ul>
</nav>
. . .
jQuery(function () {
$("#home").click(function (event) {
$("#home").css("color", "blue");
$("#about").css("color", "black");
$("#contact").css("color", "black");
});
});
jQuery(function () {
$("#about").click(function (event) {
$("#home").css("color", "black");
$("#about").css("color", "blue");
$("#contact").css("color", "black");
});
});
jQuery(function () {
$("#contact").click(function (event) {
$("#home").css("color", "black");
$("#about").css("color", "black");
$("#contact").css("color", "blue");
});
});
...does not work. Neither does moving just the first function to Default.cshtml, so that it looks like this:
$(document).ready(function () {
$("#tabs").tabs();
$(".fancybox").fancybox();
$("#home").click(function (event) {
$("#home").css("color", "blue");
$("#about").css("color", "black");
$("#contact").css("color", "black");
});
});
I think this is pretty close to what you are looking for here:
http://jsfiddle.net/qmHeF/1/
JS:
$("#menu a").each(
function(index)
{
if(window.location.href==this.href)
{
$(this).parent().remove();
}
}
);
I remove it from the DOM here (my personal preference) but you can just add a class or custom CSS if you like.
http://jsfiddle.net/qmHeF/2/
Updated: Changed it to add a class instead of remove it.
$("#menu a").each(
function(index)
{
if(window.location.href==this.href)
{
$(this).addClass("current");
}
}
);
using window.location.href instead of the jquery href will give you the full URL instead of the relative url. That way you don't need to parse either url and you can just compare the two.
You have to create a CSS class for this active state, like suggested in the comment, I use current in this example.
.current {
text-decoration: none;
/* here you style the seemingly disabled link as you please */
}
As for the HTML, the active menu page would look like this:
If you are in the About page
<nav>
<ul id="menu">
<li>Home</li>
<li><a class="current" href="~/About">About</a></li>
<li>Contact</li>
</ul>
</nav>
If you want the link to be disabled, using only html, here goes the code. Fiddle was updated to show this code. An elegant solution using Javascript was provided below in the comments.
<nav>
<ul id="menu">
<li>Home</li>
<li><span class="current" >About</span></li>
<li>Contact</li>
</ul>
</nav>
I made a quick example here so you can see if this is what you're looking for:
Example in jsFiddle.net
Best wishes
UPDATED
On second thought, your problem is that when you click the link to a new page, you are refreshing the javascript...so the click event fires but then is immediately replaced by the original DOM elements for whatever page you browse to.
Use this instead:
HTML/Razor
<nav>
<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
jQuery
$(document).ready(function () {
$("#menu a").each(function(){
//set all menu items to 'black
$(this).css("color","black");
var linkPath=$(this).attr("href");
var relativePath=window.location.pathname.replace('http://'+window.location.hostname,'');
//set the <a> with the same path as the current address to blue
if(linkPath==relativePath)
$(this).css("color","blue");
});
});
You can either check with some server-side language (e.g. PHP) to see if the current page is Home, About, or Contact, and apply a "current" class accordingly. Or, if you'd prefer, you can do this with JavaScript. I'm not sure how your absolute URLs look, but I would do something like this:
$(document).ready(function() {
$('a[href="' + window.location.pathname + '"]').addClass('current');
});
You may have to add some forward slashes in there, depending upon how your URLs look.
There are three sets of solutions to this universal development task: 1) server-side scripting alters menu/links for you, 2) CSS styling using something like a "current" class, or 3) javascript/css hybrid solutions.
It really all depends on your system and scope of development. For large dynamic sites, obviously one might as well use server-side code if it's already being used anyway. But for most projects where one isn't already using such scripting, one can manually add in a 'current' class to links and style them as you please with CSS or even more the anchor wrapping the text entirely (depending on your style of link/menus).
For a more robust javascript solution, you might try this: automatic link hightler/styling
function extractPageName(hrefString)
{
var arr = hrefString.split('/');
return (arr.length < 2) ? hrefString : arr[arr.length-2].toLowerCase() + arr[arr.length-1].toLowerCase();
}
function setActiveMenu(arr, crtPage)
{
for (var i=0; i < arr.length; i++)
{
if(extractPageName(arr[i].href) == crtPage)
{
if (arr[i].parentNode.tagName != "DIV")
{
arr[i].className = "current";
arr[i].parentNode.className = "current";
}
}
}
}
function setPage()
{
hrefString = document.location.href ? document.location.href : document.location;
if (document.getElementById("nav") !=null )
setActiveMenu(document.getElementById("nav").getElementsByTagName("a"), extractPageName(hrefString));
}
Then run setPage onload, such as with:
window.onload=function()
{
setPage();
}
As far as usability goes, it's generally accepted that just styling a nav link to look less interesting, lower contrast, grayer, not underlined, etc, is sufficient to help people know here they are. The cost of clicking a link where you already are is pretty low, but it's a nice design touch for most sites anyway.
to programmatically change my links, based on current url, i would prefer jquery:
<style type="text/css">
.current {
color: #cccccc;
}
</style>
...
<nav>
<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
...
<script type="text/javascript">
$(document).ready(function() {
var href = $("#menu li a").prop("href");
$("a[href$='"+href.substr( href.lastIndexOf("/") )+"']").addClass("current");
});
</script>
..the jquery code adds the "current" class to any a link that has its href property set to last part of address (after last /). Thats not perfect anyway if your links are somewhat like /Contact/More..
Your "Update 2" version is close to working - you just need to add the class to #home, not home
Something like:
.current {
color: blue;
}
.current a {
text-decoration: none;
}
with:
// ...
$("#home").addClass('current');
// ...
How about something like this?
What we are doing here is that we call updateMenu with a string contained in the href attribute of a menu anchor. If the string and the anchor.href match, then we hide the anchor and copy it's text content to a new text node which we then append to the li element.
If we don't have a match then we unhide the menu anchor and check to see if the li element's (the parentNode in this case) last child is a text node, if it is we remove it because it was added by us.
You requested:
I want the current page's link to give some visual indication that
clicking the corresponding link would be senseless as the user is
already on that page.
This solution does that and also renders the link unclickable.
Of course it doesn't have to be exactly this formulation, but can be some other variant, and of course you can achieve this using jquery rather than vanilla javascript if you prefer.
HTML
<nav>
<ul id="menu">
<li>Home</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
Javascript
(function () {
var updateMenu = (function () {
var anchors = document.getElementById("menu").getElementsByTagName("a");
return function (page) {
Array.prototype.forEach.call(anchors, function (anchor) {
var last;
if (anchor.pathname === page) {
anchor.style.display = "none";
anchor.parentNode.appendChild(document.createTextNode(anchor.textContent));
} else {
last = anchor.parentNode.lastChild;
anchor.style.display = "block";
if (last.nodeType === 3) {
anchor.parentNode.removeChild(last);
}
}
});
}
}());
setTimeout(function () {
updateMenu("/");
setTimeout(function () {
updateMenu("/About");
setTimeout(function () {
updateMenu("/Contact");
setTimeout(function () {
updateMenu("");
}, 5000);
}, 5000);
}, 5000);
}, 5000);
}());
On jsfiddle
I you want to use hrefs like in your example i.e. "~/About", then you will need to formulate your string to be passed to updateMenu, like so for my example;
HTML
About
Javascript
console.log(document.getElementsByTagName("a")[0].pathname);
console.log(window.location.pathname + "~/About");
Outputs
/Xotic750/G5YuV/show/~/About
/Xotic750/G5YuV/show/~/About
On jsfiddle
See window.location for it's other properties
Returns a location object with information about the current location
of the document.
For a purely css solution to this you could try pointer-events, here is a jsfiddle showing it in use.
Warning: The use of pointer-events in CSS for non-SVG elements is
experimental. The feature used to be part of the CSS3 UI draft
specification but, due to many open issues, has been postponed to
CSS4.
CSS
.current {
pointer-events: none;
cursor: default;
text-decoration: none;
color: black;
}
HTML
<nav>
<ul id="menu">
<li>Home</li>
<li><a class="current" href="/About">About</a></li>
<li>Contact</li>
</ul>
</nav>
Your update #2 should work, but you forgot to put "#" ($('#home').addClass...).
But if again it's not working, pay a particular attention to your CSS
If you have, for example, a css like
#home{color : blue;}
.current{color : orange;}
The text will be blue since #home is "stronger"
If we put values to selector:
id=10
class=5
node selector (div) = 1
so #home = 10 and is higher than .current wich equal 5, #homestyles will override.
you could use li.current but again, 5+1=6 wich is lower than an id.
But #home.current will equal 15! Wich will overide #home styles!
But if your color style is on the node itself with the attribute style="" you have to remove it with jquery or use !important :
.current{
color: blue !important;
}
It will override EVERY css but it is not recommended.
Your update #3 was close.
give your body an ID whatever name you want the page to be and give your links ids like so
<body id="about">
<nav>
<ul id="menu">
<li class="home">Home</li>
<li class="about">About</li>
<li class="contact">Contact</li>
</ul>
</nav>
</body
Then your CSS can look somewhat like your update #3 example:
li a {color:blue}
#home .home{color:red !important}
#about .about{color:red !important}
#contact .contact{color:red !important}
This should ignore any classes that are not being used and only color the selected one red.
I hate to point out that the reason your css color is not being applied to your link is because css colors for links must be set on the anchor tag (an anchor tag will not inherit a color from a wrapping LI element). Try
.current a {color:#123456;}
or leave your css as is, but change your markup so the "current" class is applied to the < a > tag instead of the < li >.
EDIT: The reason your jsfiddle works when attempting to change colors (while your production code doesn't) is because the fiddle text is not inside of an A tag.
If you wish to automatically detect which page you are currently on, simply compare the HREF value of each link to the document.URL string:
$('nav').find('a').each(function(){
if ( document.URL.indexOf( $(this).attr('href') ) !== -1 ){
$(this).parent().addClass('current');
}
});
Detailed description & test available here: -> http://jsfiddle.net/vV4h5/26/
EDIT #2: One more thing... your asp.net links are going to mess with this a bit as the document.URL will not contain the ~ character... simply remove the first character from your href value as follows:
var href = $(this).attr('href').split(1); //
if ( document.URL.indexOf( href[1] ) !== -1 ){
...
I'd just remove the linkyness from the one you are currently on. You can control the styling by targeting li and li a differently in your CSS. The only slightly tricky thing is to get the actual href value right for the links you are using, but that shouldn't be too hard. And it's not a lot of code.
$(function(){
var href = window.location.pathname.replace(/.*\//, "/"),
$active = $("nav ul#menu a[href='"+href+"']");
$active.replaceWith($active.text());
});
I use these on my website. It doesn't use JavaScript but it does pretty much what you are asking.
<style>
.header-nav a:target {
pointer-events: none;
color: #000;
font-weight: bold;
text-decoration: underline;
}
</style>
<p class="header-nav">
<a id="headerabout" href="/about.html#headerabout">about</a>
|
<a id="headertags" href="/tags.html#headertags">tags</a>
|
<a id="headershit" href="/shit.html#headershit">Shit I say</a>
</p>
It adds id to anchor and its target URL. If the anchor is :target-ed, they will be disabled completely. Also, adding an # to href attribute will cause an anchor to not refreshing when clicked if the current page match the anchor target page.
Related
I have the following jQuery code to add a class to a anchor tag when its clicked, the objective is to give the anchor tag a border bottom:
$(".breadcrumbs > li > a").click(function(){
$(this).addClass('hoveractive');
});
on Ios this class is never added and so the styles are not applied, Rest of the code is below:
.breadcrumbs > li > a.hoveractive {
border-bottom : 1px solid #f05034;
}
HTML::-
<ul class="breadcrumbs">
<li>Home</li>
<li>About Desunin<sup>®</sup> </li>
<li>Interesting links</li>
</ul>
basically i just want the class to be added for a fraction of a secound before the page refreshes and goes to the next link, but this does't seem to be happening.
If i change my code to the below,
$(".breadcrumbs > li > a").click(function(){
$(this).addClass('hoveractive');
return false;
});
I.E. include a return false statement , then the class is added in ios, but that's ofcourse not what i want to be doing , so to summerise my question why is my addClass not working in ios ?
Try to bind the click event from document and see if that helps,
$(document).on('click', '.breadcrumbs > li > a', function(){
$(this).addClass('hoveractive');
});
I have a 3 groups of content in a page that can be navigated through tabs. There's a default visible tab when I enter the page and then I can click the tabs to hide the current content and show the other.
example.html
Example // default
About
...
...
<div class="example visible" id="example">...</div> // default visible content
<div class="about" id="about">...</div>
<div class="contact" id="contact">...</div>
Now, I added a footer where there are links connecting to the 3 tabs. So, if I am in a different part of the site, I can click a link, say, About Me, that would navigate to example.html and straight to the section About Me.
footer.html
<ul>
<li>Example</li>
<li>Example About</li>
<li>Example Contact</li>
</ul>
The above works perfectly fine. But here's the problem, when I click on the footer links while I am on example.html, it jumps to the position of the content but it cannot be seen because the current tab is still active. Is there a way to check the url whenever it changes so I can parse it and change the active tab based on it?
JS
$(document).ready(function() {
// find which footer link was clicked; doesn't work when navigating on the same page
var hash = window.location.href.slice(window.location.href.indexOf('#') + 1);
if(hash === "foundation") {
$("a[name='foundation']").addClass("active").siblings().removeClass("
active");
$(".foundation").addClass("visible").siblings().removeClass("visible");
}
else if(hash === "credits") {...}
...
// click event for tabs
$("a").on("click", function(event) {
event.preventDefault();
$(this).addClass("active").siblings().removeClass("active");
var currentAttrVal = $(this).attr("href");
$("." + currentAttrVal).addClass("visible").siblings().removeClass("visible");
});
});
I know the script is too repetitive, but I'll refactor everything once I sort this out!
the location object has its own property for the current hash
window.location.hash
this includes the hash sign too so you need
window.location.hash.slice(1)
For listening to the change of the hash you will have to use the onhashchange event
You can use one of the following techniques
window.onhashchange = funcRef;
or
window.addEventListener("hashchange", funcRef, false);
This way is used in frameworks like angular when they use the #! way of defining routes for browsers that do not support the History API
You can read more about it to MDN
Here the concept which i think may help you: (jsfiddle version)
footer.html
<ul>
<li>
<input type="button" class="navigateButton" value="example" onclick="navigate(value)">
</li>
<li>
<input type="button" class="navigateButton" value="About" onclick="navigate(value)">
</li>
<li>
<input type="button" class="navigateButton" value="Contact" onclick="navigate(value)">
</li>
</ul>
CSS
.navigateButton {
background: none!important;
border: none;
padding: 0!important;
font: inherit;
/*border is optional*/
border-bottom: 1px solid #444;
cursor: pointer;
}
JS
var navigate = function (value) {
switch (value) {
case "example":
//select appropriate tab here
window.location.replace('/example');
break;
case "About":
//select appropriate tab here
window.location.replace('/example#About');
break;
case "Contact":
//select appropriate tab here
window.location.replace('/example#Contact');
break;
default:
alert('Unknown type');
}
}
So i have 2 <ul> 's with 3 <li>'s on each. I want to change the color of a specified <li> on the second <ul> when I hover over a specified <li> on the first <ul>. And when I do not hover the element, I want the format to change back to normal. Here is my code:
<ul class="a">
<li class="a1"></li>
<li class="a2"></li>
<li class="a3"></li>
</ul>
<ul class="b">
<li class="b1"></li>
<li class="b2"></li>
<li class="b3"></li>
</ul>
<script>
$(document.ready(function() {
$(".a1").mouseover(function(){
$(".b1").css({"color":"red","font-size":"19px"});
});
$(".a1").mouseout(function(){
$(".b1").css({"color":"#045491","font-size":"16px"});
});
$(".a2").mouseover(function(){
$(".b2").css({"color":"red","font-size":"19px"});
});
$(".a2").mouseout(function(){
$(".b2").css({"color":"#045491","font-size":"16px"});
});
$(".a3").mouseover(function(){
$(".b1").css({"color":"red","font-size":"19px"});
});
$(".a3").mouseout(function(){
$(".b1").css({"color":"#045491","font-size":"16px"});
});
});
</script>
So my question is, how can I perform the above with less code? Ive tried some toggle/add,remove methods but I could not get it to work. The code above does work, but I feel like it can be performed with less lines of code. Thank you.
You could use .index since your class names are all the same besides the number and add/remove a class:
JS
$(".a").find("li").hover(function(){
var index = $(this).index()+1;
$(".b"+index).addClass("active")
}, function(){
$(".b").find("li").removeClass("active")
});
CSS
.active{
color: red;
font-size: 19px;
}
FIDDLE
UPDATE
I saw your comment about the class names just being an example, I adjusted my code still using .index() this way the class name of li is irrelevant and it will highlight the corresponding li in the same position of ul.b UPDATE I switched to James Gaunt's suggestion of eq() AND StevenL's to use .toggleCLass. I like both of those better than using nth-of-type() and a hover out function:
$(".a").find("li").hover(function(){
var index = $(this).index();
$(".b").find("li").eq(index).toggleClass("active");
});
NEW FIDDLE
at lease, you can 'extract code' for css and 'make the chain call' for js:
origin js
$(".a1").mouseover(function(){
$(".b1").css({"color":"red","font-size":"19px"});
});
$(".a1").mouseout(function(){
$(".b1").css({"color":"#045491","font-size":"16px"});
});
to new js:
$(".a1").mouseover(..).mouseout(...);
change your origin css code:
mouse_over_style = {"color":"red","font-size":"19px"}
mouse_out_style = {"color":"#045491","font-size":"16px"}
then change your js to:
$('.b1').mouseover(mouse_over_style).mouseout(mouse_out_style)
i have a Nav wherein i'm attempting to use jQuery's addClass method to set the link color of the last clicked link. problem is then i have to use removeClass on all other links in the Nav. that's what i'm having trouble with.
I have written the code in a naive way, but know this is not good programming. below is the code with style sheet ref.
jQuery('#shop-nav').click(function(){
jQuery("#shop-nav").addClass("clicked");
jQuery("#art-nav").removeClass("clicked");
jQuery("#obj-nav").removeClass("clicked");
jQuery("#acc-nav").removeClass("clicked");
});
jQuery('#art-nav').click(function(){
jQuery("#art-nav").addClass("clicked");
jQuery("#shop-nav").removeClass("clicked");
jQuery("#obj-nav").removeClass("clicked");
jQuery("#acc-nav").removeClass("clicked");
});
etc. etc!
the HTML is
<div id="nav-cell-1" class="grid f-cell nav-cell">
<ul id="main-nav" class="nav clearfix">
<li>Shop
<ul id="shop-cats">
<li>Art</li>
<li>•</li>
<li>Objects</li>
<li>•</li>
<li>Accessories</li>
</ul>
</li>
</ul>
</div>
CSS:
a:link, a:visited {color:#cfb199;text-decoration:none} /* official this color:#9d9fa1; work color: #222*/
a:active, a:hover {color:#9d9fa1;text-decoration:none} /* old color:#9d9fa1; */ /* official color:#cfb199; work color: #f00*/
a:link.clicked, a:visited.clicked {color:green;text-decoration:underline}
a demo site is here:
http://www.tomcarden.net/birdycitynav/partial-nav-demo.html
I did solve part of the problem by using the this reference, but this do not include the .removeClass part.
jQuery('#shop-cats>li>a').click(function(){
jQuery(this).addClass("clicked");
});
Or this one works more like your site:
$('.nav a').click(function(){
$('.nav a').removeClass('clicked');
$(this).toggleClass('clicked');
});
test it here:
http://www.jsfiddle.net/mjYq3/18/
Try this to toggle the class:
var navs = jQuery('#shop-nav,#art-nav, #obj-nav, #acc-nav');
navs.click(function(){
navs.removeClass("clicked");
$(this).addClass("clicked");
});
Untested
jQuery('#shop-cats>li>a').click(function(){
$this = jQuery(this);
$this.parent().children('a').removeClass('clicked');
$this.addClass("clicked");
});
You can first remove all the clicked classes then add it back to just the one that was clicked.
jQuery('#shop-cats>li>a').click(function(){
jQuery('#shop-cats>li>a').removeClass("clicked")
jQuery(this).addClass("clicked");
});
This should work:
$('#main-nav a').click(function() {
$('#main-nav a').not(this).removeClass('clicked');
$(this).addClass('clicked');
});
On the basis that you apparently want to do this for all links that are descendents of #main-nav, and not just those that are in the inner <ul> list.
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?