Jquery click event if statement - javascript

I'm adding trivia as a main component to my webpage. I'm trying to the class of "correct" when it's right, and "wrong" when it's wrong. I have no idea what I'm doing. lol. Any help would be greatly appreciated.
<ul>
<li id="a">A) Lucy</li>
<li id="b">B) Bonnie</li>
<li id="c">C) Sheila</li>
<li id="d">D) Kai</li>
</ul>
JQuery
I tried to make the correct one a variable in Jquery
var right = $( "ul li#a" ).on(click, function() {});
if (click === right){
$("ul li#a").addClass("correct");
} else {
$("li").addClass("wrong");
}

If I'm understanding your end goal, you want to do something to indicate that an answer is the "right" answer or not, then you want to assign class .correct or .wrong if they get the "right" answer or not.
I would assign data-right="right" to the "right" answer. Then when someone clicks on an li, look for that attribute and assign .correct if they chose the "right" answer, and assign .wrong if not.
$('li').on('click',function() {
var right = $(this).data('right');
$(this).siblings().removeClass('correct wrong');
if (right == "right") {
$(this).addClass('correct');
} else {
$(this).addClass('wrong');
}
})
.correct {
color: green;
}
.correct:after {
content: '\2713';
}
.wrong {
color: red;
}
.wrong:after {
content: '\2613';
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="a" data-right="right">A) Lucy</li>
<li id="b">B) Bonnie</li>
<li id="c">C) Sheila</li>
<li id="d">D) Kai</li>
</ul>

This solution relies on giving the right answers a class called "correctAnswer", then binding a click event handler that sets the class of the clicked li based on whether or not it has that class. I think that does what you're looking for:
<ul>
<li id="a" class="correctAnswer">A) Lucy</li>
<li id="b">B) Bonnie</li>
<li id="c">C) Sheila</li>
<li id="d">D) Kai</li>
</ul>
$('li').on('click', function () {
var classToAdd = $(this).is('.correctAnswer') ? 'correct' : 'wrong';
$(this).addClass(classToAdd);
});

Here is a complete example:
$( document ).ready(function() {
var correctAnser = 'a'; // you need to set this to what you need the answer to be
$('ul li').on('click', function () {
$('ul li').removeClass('correct').removeClass('wrong'); // remove both classes on list elements
var classToAdd = $(this).attr('id') == correctAnser ? 'correct' : 'wrong';
$(this).addClass(classToAdd);
});
});
.correct {
background:#2bb539;
color:#ffffff;
}
.wrong {
background:#c00;
color:#ffffff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="a">A) Lucy</li>
<li id="b">B) Bonnie</li>
<li id="c">C) Sheila</li>
<li id="d">D) Kai</li>
</ul>

Related

Switch between numbers and run function on scroll

How could I toggle class between these numbers both on click and on scroll..? So, basically I want to switch between these when rotating mouse wheel, and fire some sort of a callback after that...
EDIT: So, I would like to be able to move mouse wheel anywhere in the window, and that would in return toggle class .active in the li's. Also, when for example li#runOne is selected, it should run a callback function let's say runFunctionOne. When li#runTwo is selected/scrolled to - it would run for example runFunctionTwo...
$("#runTwo").on('click', function() {
$("#runTwo").toggleClass("active", function() {
// Run some callback
console.log("Two");
});
});
$(window).scroll(function() {
// Switch between numbers on scroll
});
ul {
margin: 50px auto;
width: 300px;
}
.active {
background-color: lightblue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li id="runOne" class="runOne active">Run 1</li>
<li id="runTwo" class="runTwo">Run 2</li>
<li id="runThree" class="runThree">Run 3</li>
</ul>
You can toggle class using click and mousewheel like this
https://codepen.io/creativedev/pen/rKOBEq
$('.rr').on('click, mousewheel', function() {
$('.rr').removeClass('active');
$(this).addClass('active');
console.log("Two");
});
HTML code:
<ul>
<li id="runOne" class="runOne active list">Run 1</li>
<li id="runTwo" class="runTwo list">Run 2</li>
<li id="runThree" class="runThree list">Run 3</li>
</ul>
jQuery code:
$('.list').click(function(e){
$('.list.active').removeClass('active');
$(this).addClass('active').trigger('activeEvent');
});
$(document).on('mousewheel',function(e){
var currentScrollAmt=$(window).scrollTop();
var activeLi=$('.list.active');
$('.list.active').removeClass('active');
if(e.originalEvent.wheelDelta /120 > 0) {
//Scrolling Up
if(!activeLi.is(':first-child'))
activeLi.prev('li').addClass('active').trigger('activeEvent');
}
else{
//Scrolling Down
if(!activeLi.is(':last-child'))
activeLi.next('li').addClass('active').trigger('activeEvent');
}
});
$('li').on('activeEvent',function(e){
runCallback(e.target.id);
});
function runCallback(id)
{
if(!id)
return false;
switch(id)
{
case 'runOne':
alert('runOne Callback Code');
break;
case 'runTwo':
alert('runTwo Callback Code');
break;
case 'runThree':
alert('runThree Callback Code');
break;
}
}

How can I select a specific tag in two different HTML structure?

I have two different HTML structure and I cannot change them. Now I need to write a jQuery code to get the href attribute of one specific <a> in them. Here is my code:
$(document).on('click', '.myclass', function(e){
e.preventDefault(e);
var url = $(this).attr('href');
console.log(url);
$(this).closest('li').css('background-color','#f1f1f1');
})
li{
border: 1px solid gray;
}
a{
display:block;
}
.myclass{
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
HTML1:
<ul>
<li>
sth
<span>something</span>
<a class="myclass" href="./my/path">link</a>
</li>
</ul>
<hr />
HTML2:
<ul>
<li class="myclass">
<a href="./my/path">
<span>something</span>
</a>
<div>sth</div>
</li>
</ul>
Ok, let me explain. I want two things happen when the user clicks on .myclass element: (as you see, .myclass element is different in two HTML structures)
Setting a pale gray color to the background of li.
Printing the href value of the link in the console.
My current code works correctly for the first HTML structure (but not for the second one).
Note: For the second one, jQuery code should look like this:
$(document).on('click', '.myclass', function(e){
e.preventDefault(e);
var url = $(this).find('a').attr('href');
console.log(url);
$(this).css('background-color','#f1f1f1');
})
See? I've added find('a') (there is always one <a> in the second kind of HTML) and removed closest('li').
Anyway, how can I write one jQuery code instead of both above?
You can use .is() to test where current element is anchor and keep using .closest() to target LI element.
Check the current matched set of elements against a selector, element, or jQuery object and return true if at least one of these elements matches the given arguments.
$(document).on('click', '.myclass', function(e) {
e.preventDefault(e);
var url;
if ($(this).is('a')) {
url = $(this).attr('href');
} else {
url = $(this).find('a').attr('href');
}
console.log(url);
$(this).closest('li').css('background-color', '#f1f1f1');
});
$(document).on('click', '.myclass', function(e) {
e.preventDefault(e);
var url;
if ($(this).is('a')) {
url = $(this).attr('href');
} else {
url = $(this).find('a').attr('href');
}
console.log(url);
$(this).closest('li').css('background-color', '#f1f1f1');
})
li {
border: 1px solid gray;
}
a {
display: block;
}
.myclass {
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
HTML1:
<ul>
<li>
sth
<span>something</span>
<a class="myclass" href="./my/path">link</a>
</li>
</ul>
<hr /> HTML2:
<ul>
<li class="myclass">
<a href="./my/path">
<span>something</span>
</a>
<div>sth</div>
</li>
</ul>
However It would be cleaner to use separate event handler
$(document).on('click', 'a.myclass', function(e){
var url = $(this).attr('href');
})
$(document).on('click', 'li.myclass', function(e){
var url = $(this).find('a').attr('href');
})
This would be cleaner using a css rule for the background
$(document).on('click', '.myclass', function(e){
e.preventDefault(e);
var $el = $(this),
//if this is <a> tag use it for href, otherwise find it
$link = $el.is('a') ? $el : $el.find('a:first'),
url = $link.attr('href');
$el.closest('li').toggleClass('active');
console.log(url);
})
li{
border: 1px solid gray;
}
a{
display:block;
}
.myclass{
cursor: pointer;
}
li.active, .myclass.active{
background-color:#f1f1f1
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
HTML1:
<ul>
<li>
sth
<span>something</span>
<a class="myclass" href="./my/path">link</a>
</li>
</ul>
<hr />
HTML2:
<ul>
<li class="myclass">
<a href="./my/path">
<span>something</span>
</a>
<div>sth</div>
</li>
</ul>
This could be done in a number of ways ranging from checking what type of tag it is, all the way to applying data attributes and then checking them against that what we have on the clicked class.
For this example, we're checking if it has a 'href' tag.
I have left the separate background colour setters in each if() in case you wish to change them to different values at some point.
Here's my take on it:
$(document).ready(function() {
$('.myclass').click(function(e) {
e.preventDefault();
var url;
if($(this).attr("href")) { //WE check if the "href" attribute exists
//Found, it must be an link
url = $(this).attr('href');
console.log(url);
$(this).closest('li').css('background-color','#f1f1f1');
} else {
//Not found
url = $(this).find('a').attr('href');
console.log(url);
$(this).css('background-color','#f1f1f1');
}
});
});
I am not very clear about the problem at hand, but tried this
$(document).on('click', '.myclass', function(e){
{
e.stopPropagation();
var x='';
if(evt.target.tagName=="LI")
{
x = $(this).find('a.myclass').attr('href');
$(this).css('background-color', '#f1f1f1');
}
else if(evt.target.tagName=="A")
{
x = $(this).attr('href');
$(this).parent("li").css('background-color', '#f1f1f1');
}
console.log(x);
});

Filtering a tree view made of nested <ul> <li> along with child nodes

Sorry for not entering the code I have worked on. I am explaining my doubt clearly this time. I have a tree made of nested ul and li tags. the tree node names are obtained from database. I need to filter the tree based on the name I enter in a text box. While showing the filtered tree item, if it the filtered item is a parent node, child nodes should also be listed(eventhough they don't match the text entered in texbox.)
I have refered this link: Filter multiple <ul> lists with jQuery
This link helped me to filter out a tree node by entering its name in textbox.
But its childnodes are not visible.Please help me. Please find my code below:
function func(){
alert("Onclick function parent node...");}
function func1(){
alert("Onclick function child node...");}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script>
$(document).ready(function() {
$('input[type="text"]').keyup(function(){
var filter = jQuery(this).val();
jQuery("ul li").each(function () {
if (jQuery(this).text().search(new RegExp(filter, "i")) < 0) {
jQuery(this).hide();
} else {
jQuery(this).show();
jQuery(this).children().show();
}
});
});
});
</script>
</head>
<body>
<input type="text" />
<ul class="mainlayer" id="category1">
<li class="layer1">item1
<ul>
<li class="layer2">hju11</li>
<li class="layer2"><a>kiu12</a></li>
</ul>
</li>
<li class="layer1"><a>item2</a></li>
<li class="layer1"><a> item3</a></li>
</ul>
</body>
</html>
Thanks in advance.
Try something like this:
function func(){
alert("Onclick function parent node...");}
function func1(){
alert("Onclick function child node...");}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<style>
.hide{
display:none;
}
</style>
<script>
$(document).ready(function() {
$('input[type="text"]').keyup(function(){
var filter = jQuery(this).val();
jQuery(".menu ul > li").removeClass("hide");
jQuery(".menu ul > li").removeClass("show");
jQuery(".menu ul > li").each(function () {
if (jQuery(this).text().search(new RegExp(filter, "i")) < 0 && !jQuery(this).hasClass('show')) {
jQuery(this).addClass('hide');
} else {
jQuery(this).addClass('show');
jQuery(this).find(' ul > li').addClass('show');
}
});
});
});
</script>
</head>
<body>
<input type="text" />
<div class="menu">
<ul class="mainlayer" id="category1">
<li class="layer1">item1
<ul>
<li class="layer2">hju11</li>
<li class="layer2"><a>kiu12</a></li>
</ul>
</li>
<li class="layer1"><a>item2</a></li>
<li class="layer1"><a> item3</a></li>
</ul>
</div>
</body>
</html>
UPDATE
updated snippet, where you can change .menu class for whatever you need
You can use following jQuery
$(document).ready(function()
{
$('input[type="text"]').keyup(function()
{
var filter = jQuery(this).val();
jQuery("ul li.layer1").each(function()
{
if (jQuery(this).text().search(new RegExp(filter, "i")) < 0)
{
jQuery(this).hide();
}
else
{
jQuery(this).show();
jQuery(this).children().show();
var found = false;
jQuery(this).find("li.layer2").each(function(i,obj)
{
if ($(obj).text().search(new RegExp(filter, "i")) < 0)
{
$(obj).hide();
jQuery(obj).closest('.layer1').show();
}
else
{
$(obj).show();
found = true;
}
});
if(found==false)
{
jQuery(this).find("li.layer2").show();
}
}
});
});
});
Well I have got a lot of help from so many developers.. Thank you all for the support and useful answers.. Please find the one among them which I felt much easier...
Instead of checking it like this,
jQuery("ul li").each(function () {}
Check it as:
jQuery(".mainlayer>li").each(function () {}
So that child nodes are visible and associated functions shall work...
Once again Thank you all for the useful answers.. Happy coding!

Carousel - How to loop through elements?

I'm trying to figure out how to loop through each list element one at a time and apply a function to them when they run, I've tried several methods and some hints would help!
HTML structure
<div class="custom-item">
<ul>
<li id="first-slide" class="slide active"><h1>Test</h1></li>
<li id="second-slide" class="slide"><h1>Test</h1></li>
<li id="third-slide" class="slide"><h1>Test</h1></li>
</ul>
</div>
I've worked out an each function that if i understand correctly will handle the changing of classes, this is where I'm failing to loop through each element.
$(document).ready(function() {
$( ".slide" ).each(function( i ) {
if ( this.className !== "active" ) {
this.addClass("active");
} else {
this.removeClass("active");
}
});
});
You need to use $(this).hasClass to check for "active" class.
JSFiddle
http://jsfiddle.net/39o0bagv/
JavaScript
$(document).ready(function() {
$( ".slide" ).each(function( i ) {
if ( $(this).hasClass("active") ) {
$(this).removeClass('active');
$(this).addClass("changed");
} else {
$(this).addClass("active");
}
});
});
CSS
.active {
color: red;
}
.changed {
color: blue;
}
The loop will check if the element has 'active' class and replace it with 'changed'. And vise versa.
I've added a css class so that you can see the active class being toggled. Your methods for checking, adding, and removing the class weren't write, so it was failing with a script error. See what I've done below, using the classList property. However, judging from your post title, I'm not sure if maybe you're wanting to pause on each one and then continue. In that case the javascript setInterval method might be the tool you want. http://www.w3schools.com/jsref/met_win_setinterval.asp
$(document).ready(function() {
$(".custom-item").find('.slide').each(function(){
if (!this.classList.contains("active")) {
this.classList.add("active");
} else {
this.classList.remove("active");
}
});
});
.active{
background-color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="custom-item">
<ul>
<li id="first-slide" class="slide active"><h1>Test</h1></li>
<li id="second-slide" class="slide"><h1>Test</h1></li>
<li id="third-slide" class="slide"><h1>Test</h1></li>
</ul>
</div>
Fiddle
Fix: fiddle
$(document).ready(function() {
$('.slide').each(function(i) {
if ( !$(this).hasClass("active")) {
$(this).addClass("active");
} else {
$(this).removeClass("active");
}
});
});

How can I give the current page's link a disabled look?

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.

Categories