My navigation menu on header looks like this:
<ul id="nav">
<li id="home">
<a class="mainmenu" href="#">Link1</a>
</li>
<li>
<a class="mainmenu" href="#">Link2</a>
</li>
</ul>
and the same markup is used for the footer section and it's not working.
I have also a file called jscript.js which contains all the javascript for the website,
and I found this variable:
var navTarget = "ul#nav li a" //menu link to target
Also, if I remove for example the markup in the header sections the footer will work.
I've tried also to use .nav instead of #nav and I have the same problem.
The navigation menu is controlled by javascript, I don't post the code here because it's huge, for better understanding of how the navigation menu works look here
I've found this in the javascript:
//SET MENU ITEM IDs
$(navTarget).each(function(i){
i++
this.id = this.id +"_" +i ;
});
//MENU CLICK FUNCTION
$(navTarget).click(function() {
//ensure link isnt clickable when active
if ($(this).hasClass('active')) return false;
//get id of clicked item
activeNavItem = $(this).attr('id');
//call the page switch function
switchContent();
});
//CONTENT SWTICH FUNCTION
var switchContent = function (){
//set previous and next link & page ids
var PrevLink = $(navTarget+'.active')
$(PrevLink).removeClass('active');
var PrevId = $(PrevLink).attr('id');
//alert(PrevId)
var NextLink = $('#'+activeNavItem).addClass('active');
var NextId = activeNavItem
//alert(NextId);
From the looks of it, the JS code is using some CSS selector (like jquery's $ or dojo's dojo.query) that pulls in the DOM element target based on the value of navTarget, and then does something with it: turns it into a menu.
But its only doing it once.
You need to look at the JS and see where navTarget is used. Then it should be fairly easy to make it do the menu creation on all the results of $(navTarget) instead of just the first hit.
Also, you should only have on instance of an ID in your dom.
You can change this to a class instead:
var navTarget = "ul.nav li a"
And in the markup:
<div class='nav'>
But you will still have to look at the JS and make sure it functions against a set of targets returned by the CSS selector. That code is probably expecting just a single result and using just it: results[0].
You can only have one element of a given id on the page. So based on your description, it sounds like you have 2.
I don't know exactly how this script works, but you can try using classes instead.
<ul class="nav">
var navTarget = "ul.nav li a";
You would have to change your HTML and the JS navTarget selector string.
But there is also a good chance that your script may not support creating multiple menus at all. And if thats the case, you may need to fix that script or find a better one.
If the code for the footer really is identical to the header, that's the problem. An id should only be used for a single element in a page, and jQuery's selectors will only return the first. Meaning code like "ul#nav li a" only works on the header.
Easiest solution is to change the id's to classes, e.g.:
<ul class="nav">
... and change your jQuery to match that, e.g.:
var navTarget = "ul.nav li a";
Update: And (ignoring that this may end up turning into three duplicate posts), that fix is probably not enough at all, since other parts of the script may only work with a single menu.
Related
I am trying to overwrite an old link that is written into some code via a CMS, therefore I cannot access the base code easily.
I am trying to add a script that will overwrite the current link with a new one.
Here is my code:
script:
function linkChange() {
var links = document.getElementById("titlecontent");
links.getElementsByTagName("a").href = "http://www.cnn.com/";
}
or
function linkChange() {
document.getElementById("titlecontent").getElementsByTagName("a").href = "http://www.cnn.com/";
}
html:
<ul id="titlecontent"><li>link</li></ul>
The main issue is I cannot go in and add an id or class to the <a> tag, so I need to target it starting with the <ul> which has the id "titlecontent".
This works :
document.getElementById("titlecontent").getElementsByTagName("a")[0].href = "http://www.cnn.com/";
<ul id="titlecontent"><li>link</li></ul>
The problem was that you needed to select a specific element in getElementsByTagName, because it returns a list of elements, not just one.
I am trying to clone an li element but without the tags.
I am have tried many different ways but I can make it seem to work.
When I take a look at the html of the li element it still selects the span tags.
Below is the code I am using. Any help would be really appreciated. Thanks!
<ul class="todo_list_items" data-category_id="44">
<li class="tasks" data-task_id="30">
<!-- Don't want to select this span class -->
<span class="modify_tasks">
<a href='#' class='delete_task_name'>Delete</a>
<a href='#' class='edit_task_name'>Edit Task</a>
</span>
Test
</li>
</ul>
<script>
$(document).on("click", ".edit_task_name", function () {
var task_id = $(this).data("task_id");
var previous = $(".tasks[data-task_id=30]").not(".tasks[data-task_id=30] > span").clone();
console.log(previous.html());
});
</script>
Just clone it and then empty it:
var previous = $(".tasks[data-task_id=30]").clone().empty();
EDIT: If you only want to remove the span and not other content, then just remove the span from the clone:
var previous = $(".tasks[data-task_id=30]").clone();
previous.children("span").remove();
not() will check against elements in the set, in your case the set consists of only $(".tasks[data-task_id=30]"). not() is testing the span inside it to see if it matches its own parent, so not wont be adjusting your jQuery object for cloning there. An alternative way to achieve what you want might be code similar to this:
var $tasks = $(".tasks[data-task_id=30]"),
$modifyTasks = $tasks.children('span').detach(),
$cloneOfTasks = $tasks.clone();
$modifyTasks.prependTo($tasks);
$cloneOfTasks.appendTo($tasks.parent());
.detach() removes the span without losing events and data so you can put it back in when your done making your clone.
Alternatively this code might be easier to interpret and use:
var $tasks = $(".tasks[data-task_id=30]");
$('ul.todo_list_items').append($tasks.contents().not('span').clone().wrap('<li class="tasks" data-task_id="30">').closest('li'));
This uses .contents() to grab whats inside the task so you can run not against it. The closest('li') part is needed to ensure the li wrapped around the new element is returned for appending to the ul.
I'm trying to append a class to an LI automatically if the filename matches the href (e.g; if the anchor has the href attribute set to about.php and the filename of the current page is about.php then it would append the class.) however, along the way I've hit some complications and I've been getting myself confused with the syntax a little...
So far I have this...
var filename = location.pathname.substring(1)
$(document).ready(function(){
$('a').each(function() {
if (this.href === filename) {
$(this).parent('li').addClass('current_page_item');
}
});
});
My navigation is constructed as shown here and as you can see, it works and everything but only when the class is set manually... so I'm trying to get it to be automatic from the actual filename.
I hope this make some sense to someone, as I'm really confused on how to get this working now!
Thank-you to anyone who contributes, it's of great help and will help me understand the jquery syntax further, actually selecting something specific and writing a logical statement in jquery really confuses me as it's very different to PHP, which is what I'm used to.
My markup looks like this, since I didn't include it before and just assumed people would look at the source code to understand what I was meaning (though, I should have put it here)
<nav>
<div class="container">
<ul class="group" id="effects">
<li>News</li>
<li>About</li>
<li>Races</li>
<li>Tools</li>
<li>FAQ</li>
<li>Contact Us</li>
</ul>
</div>
</nav>
Thanks.
I think you can do it as simple as this:
$(function(){
$('a').filter(function() {
return (this.href == location.href);
}).parent('li').addClass('current_page_item');
});
​Filter the anchor tags by their href attribute. Seems to work on this JSFiddle. For some reason, you have to hit run for it to work.
I assume that li tag is parent of anchor tag than you can try this-
$(this).parent().addClass('current_page_item');
instead:
$(this).parent('li').addClass('current_page_item');
Based on what little information you've provided in your question, I'd suggest (though this is untested):
var file = document.location.href.split('/').pop();
$('li a').filter(function(){
return this.href.indexOf(file) !== -1;
}).parent().addClass('current_page_item');
This gets the contents of the current page's URL and splits it by the / character and then assigns the last element of the array to the variable file, for example:
'http://example.com/directory/page.html'
is converted into an array:
["http:", "", "example.com", "directory", "page.html"]
And the last element of that array is assigned to the variable, so file becomes equal to:
'page.html'
The jQuery iterates over every a element within an li element and then, if it finds the string page.html within the href attribute it returns that a element, and adds the class-name to its parent element.
You could, instead, use the full document.location.href, of course; which would give:
var page = document.location.href;
$('li a').filter(function(){
return this.href == page;
}).parent().addClass('current_page_item');
This works much the same way, but instead of looking to see if the filename can be found within the URL, it checks that the href of the element is exactly equal to the current document.location.href.
References:
JavaScript:
Array.pop().
String.indexOf().
String.split().
*jQuery:
filter().
I have a list of links, one has the class active.
On my next button click id like to remove the class from the current element and add it to the next only I cant seem to get it to add?
Ive made a fiddle to hopefully explain my problem, any help would be great, thanks
http://jsfiddle.net/h6D4k/
$('.next').click(function(){
$('ul.pagination').find('a.active').removeClass('active');
$('ul.pagination').find('a.active').next('a').addClass('active');
return false;
});
One of the jQuery most usable conveniencies is that its methods are (usually) chainable - in other words, they return the very object they are called from. So you can simply write this:
$('ul.pagination').find('a.active').removeClass('active').closest('li')
.next('li').find('a').addClass('active');
... as it's <li> elements that should be 'nexted', not <a> ones. But in fact, you shouldn't probably discard 'active' altogether if it's the last element in question:
var $a = $('ul.pagination').find('a.active'),
$li = $a.closest('li'),
$nextLi = $li.next('li');
if ($nextLi.length) {
$a.removeClass('active');
$nextLi.find('a').addClass('active');
}
This is actually what you want based on your html structure in you fiddle. http://jsfiddle.net/h6D4k/1/
$('ul.pagination').find('a.active').removeClass('active').parent()
.next().find('a').addClass('active');
Because once you've done this...
$('ul.pagination').find('a.active').removeClass('active');
There is no more a.active - the active classname has been removed from that element. So repeating the same selector...
$('ul.pagination').find('a.active')//...
... will select nothing.
Chain it all together instead.
$('ul.pagination').find('a.active').removeClass('active').next('a').addClass('active');
You have a second problem. According to the jQuery API for next(), it will:
Get the immediately following sibling of each element in the set of matched elements. If a selector is provided, it retrieves the next sibling only if it matches that selector.
You're not trying to get the following sibling:
<ul class="pagination">
<li><a class="one active" href="#">X</a></li>
<li><a class="two" href="#">X</a></li>
<li><a class="three" href="#">X</a></li>
</ul>
Next
Prev
You're trying to get the next <a> in the whole document. That's more challenging - and I'm not sure how to do it.
I would write it this way, preventing the action from doing anything on the last li as well.
http://jsfiddle.net/h6D4k/6/
$('.next').click(function(e){
e.preventDefault();
if ($("ul.pagination a.active").parent().is(":last-child")) return;
$('ul.pagination a.active').removeClass('active').parent().next().find("a").addClass('active');
});
You have two errors in your code:
Once removed, the active class can't be found anymore
your a tags are nested in li tags so next() doesn't work as you expect
To simplify things, you could attach the active class to the li tags.
Live demo: http://jsfiddle.net/h6D4k/7/
Code:
$('.next').click(function(){
$('ul.pagination').find('li.active').removeClass('active')
.next().addClass('active');
return false;
});
I have the following code:
<div id="nav">
<ul>
<li id="tabOne" class="first current">Page One</li>
<li id="tabTwo">Page Two</li>
<li id="tabThree"><a href="./CS3.html" target="SheetView">Page Three</li>
<li id="tabFour">Page Four</li>
<li id="tabFive">Page Five</li>
<li id="tabSix">Page Six</li>
</ul>
This loads the selected page into an iframe named "SheetView." What I need to do is use JavaScript to alter the class when an option that isn't the currently selected on is clicked. I should say that I have the current class already setup in my CSS. I just have no way to trigger it.
I thought adding an onlick event to the <UL> up there and calling onclick="Javascript:changeCurrent();" but there is the problem (four actually):
Is <ul onclick="JavaScript:changeCurrent();> where I need to have the event?
What is the resulting JavaScript to make the change happen?
How can I cause the first option to be set as current by default?
Is there a way to keep the currently selected option from being an active link?
I found a few different examples but I couldn't tailor them to work for me. Any help would be most appreciated.
Since you specified that you wanted a non-jQuery response, here's a function that will toggle appropriately:
function toggleNavSelected(el){
var list = document.getElementById('nav').children[0];
for(var i=0; i<list.children.length; i++){
var cur = list.children[i];
if(el==cur){
cur.classList.add("current");
cur.firstChild.onclick = (function(){
toggleNavSelected(this.parentElement);
return false;
});
} else {
if(cur.classList.contains("current")){
cur.classList.remove("current");
}
cur.firstChild.onclick = (function(){
toggleNavSelected(this.parentElement);
});
}
}
}
Either add an onclick handler to each LI (onclick="toggleNavSelected(this);") or execute the following after the menu has loaded:
var list = document.getElementById('nav').children[0];
for(var i=0; i<list.children.length; i++){
var el = list.children[i];
el.firstChild.onclick = (function(){
toggleNavSelected(this.parentElement);
});
}
Demo: http://jsfiddle.net/bWY7P/2/
(note: The JSFiddle script has a small difference; it adds a return false; to the onclick function so that you can play with it without the links actually following the HREF attribute. Do not use that line in your live code)
Explanation:
The function looks at each LI element within the #nav element.
If that element is the element passed to the function, then it adds the class .current.
Otherwise, it removes the class .current (if present).
The second part binds a function to the onclick event of each a element that calls the toggleNavSelected() function and passes its parent element (the li) as the argument.
1) if you want to change the currently selected class when you click an item, put the onclick into the li item
2) using jquery would be very easy here, all you have to do is import the jquery file with the <script> tag and you're ready! For example, you could do onclick="changeClass(this);" on the <li> tag and in a normal JavaScript file or in a script tag:
function changeClass(this){
$('#nav li').attr("class","");
$(this).attr("class","current");
}
Replace the 'current' with the class name you want to use
3) it should already be set as current
4) use the :visited CSS selector to change what colour followed links look like eg:
a:visited{
color: #000000;
}
First of all you should set the event handler from a separate script, not from an onclick attribute. You don't repeat your code that way and have anything in one place. The HTML is also much cleaner.
Using jQuery it would be as easy as:
var menuLinks = jQuery( '#nav a' );
menuLinks.on( 'click' function() {
menuLinks.removeClass( 'active' );
$( this ).addClass( 'active' );
} );
You could also do that in plain JS, but using some library keeps you out of the trouble of browser incompatibilities.