I think this may be because these elements didn't originally have the DOM element. I have tried using events and then a propagation tool, but it's still not working :(
I want it so that when you click one of the items, it removes the underline from all items, and then adds it to the item that you just clicked, but in this case it keeps it underlined. To test just use the fiddle link and click on the first "A", and then the second bigger "A"
(JSFiddle)
$(document).ready(function() {
$("li.big").on("click", function(e) {
$("li>a.underline").removeClass("underline");
$("li.big").addClass("underline");
e.stopPropagation();
});
$("li.default").on("click", function(e) {
$("li>a.underline").removeClass("underline");
$("li.default").addClass("underline");
e.stopPropagation();
});
});
a {
text-decoration: none;
}
.underline {
text-decoration: underline;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="nav navbar-nav">
<li>
<div class="raisetext">Raise Text:</div>
</li>
<li class="default">A
</li>
<li class="big">A
</li>
<li class="bigger">A
</li>
</ul>
To add to Sushils answer, it sounded like the anchors were appended. So, just in case the anchor tags were dynamically appended to the page:
$(document).ready(function() {
$("li").on("click","a", function() {
$("li > a").removeClass("underline");
$(this).addClass("underline");
});
});
you can simply use $('a').on('click', function(){ instead of the li.big and li.default since they're all links.
try this
$(document).ready(function() {
$('a').on('click', function(){
$('a').removeClass('underline');
$(this).addClass('underline');
});
});
here's a working JSFIDDLE
note: this will apply to all the links on the page. if you don't wan't it to apply to all the links, then you can use a class.
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.
Actually I am trying to do jquery tabs. I have written a code that needs rework and probably better ways to implement. I think I could use function arguments to achieve this, but I am not sure. Can somebody tell me how to achieve this in a better way. Though my code works but I think it is rudimentary. I would also like only one tab to display a background color if this is active.
http://jsfiddle.net/5nB4P/
HTML:
<div id="nav">
<ul>
<li>First Tab</li>
<li>Second Tab</li>
<li>Third Tab</li>
</ul>
</div>
<div id="content">
<div class="tabs first">First Div content</div>
<div class="tabs">Second Div content</div>
<div class="tabs">Third Div content</div>
</div>
Script:
$(function() {
$("li :eq(0)").click(function() {
$("li").css("background","none");
$(this).css("background","red");
$(".tabs:gt(0)").hide();
$(".tabs:eq(0)").show();
})
$("li :eq(1)").click(function() {
$("li").css("background","none");
$(this).css("background","red");
$(this).css("background","red")
$(".tabs:gt(1), .tabs:lt(1)").hide();
$(".tabs:eq(1)").show();
})
$("li :eq(2)").click(function() {
$("li").css("background","none");
$(this).css("background","red");
$(".tabs:lt(2)").hide();
$(".tabs:eq(2)").show();
})
})
There is a much better way to achieve this. Here you go
$(function() {
$("li").click(function() {
$(this).css("background","red").siblings().css("background","none");
$(".tabs").hide().eq($(this).index()).show();
return false;
});
})
Working Demo
As #Niels mentioned for setting the background style you can have a dedicated class(active) and add/remove this class instead of setting the inline sytle.
FYI..In the above code $(this).index() gives the position of the first element within the jQuery object relative to its sibling elements
CSS:
.active {
background-color:red;
}
JQuery:
$('li').click(function(){
$this = $(this);
$this.addClass('active').siblings().removeClass('active');
$('.tabs:eq(' + $this.index() + ')').show().siblings().hide();
});
Here is a demo: http://jsfiddle.net/5nB4P/6/
Here is the way that I updated this to make it smaller and I believe to be more effective and easier to use:
http://jsfiddle.net/5nB4P/7/
Code:
$("#nav ul li").click(function(){
var id = $(this).attr("rel");
$("#nav ul li").each(function(){
$(this).removeClass("active");
});
$(this).addClass("active");
$("#content div").each(function(){
$(this).hide();
});
$("#"+id).show();
});
Do you mean this? http://jsfiddle.net/tsukasa1989/5nB4P/1/
$(function() {
$("#nav li").click(function(){
// Handle active status
$(this).addClass("active").siblings().removeClass("active");
// Show the tab at the index of the LI
$(".tabs").hide().eq($(this).index()).show();
})
// Don't forget to set first tab as active one at start
.eq(0).addClass("active");
})
If you want to style the active tab use
#nav li.active{}
My approach doesn't use arguments, but HTML class and id references to shorten things: http://jsfiddle.net/ZScGF/1/
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.