jQuery: Finding link best matching to current URL
I have the following code which tries to add a class of selected to a link that matches the url:
var pathname = window.location.pathname;
$(document).ready(function ()
{
$('ul#ui-ajax-tabs li a').each(function()
{
if (pathname.indexOf($(this).attr('href')) == 0)
{
$(this).parents('li').addClass('selected');
}
});
});
1.) So for example if I have a url like /Organisations/Journal
and /Organisations/Journal/Edit
a link with Organisations and Journal will show as being selected. This is fine!
2.) However sometimes I have urls like: /Organisations
and /Organisations/Archived
and if I have a link to the Archived then both will be selected BUT I don't want this to happen because the Organisations like doesn't have the second part of the url so shouldn't match.
Can anyone help with getting this working for the second types Without breaking the first type? Also none of this can be hardcoded regex looking for keywords as the urls have lots of different parameters!
Cheers
EXAMPLES:
If the url is /Organisations/
Or /Organisations
then a link with /Organisations
should be selected. If the URL is /Organisations/Journal/New
then a link with /Organisations/Journal
or /Organisations/Journal/New
would be selected.
BUT if I have a url with /Organisations/Recent
and have two links: /Organisations
and /Organisations/Recent
then only the seco开发者_开发知识库nd should be selected! So the thing to note here is that it must have a third parameter before it should look for bits of the URL more loosly rather than an exact match.
Remember it might not always be Organisations so it can't be hardcoded into the JS!
Edit: My previous solution was quite over-complicated. Updated answer and fiddle.
var pathname = window.location.pathname;
$(document).ready(function ()
{
var best_distance = 999; // var to hold best distance so far
var best_match = false; // var to hold best match object
$('ul#ui-ajax-tabs li a').each(function()
{
if (pathname.indexOf($(this).attr('href')) == 0)
{
// we know that the link is part of our path name.
// the next line calculates how many characters the path name is longer than our link
overlap_penalty = pathname.replace($(this).attr('href'), '').length;
if (overlap_penalty < best_distance) { // if we found a link that has less difference in length that all previous ones ...
best_distance = overlap_penalty; // remember the length difference
best_match = this; // remember the link
}
}
});
if (best_match !== false)
{
$(best_match).closest('li').addClass('selected');
}
});
The best match is calculated like so:
Assume our pathname is "/foo/bar/baz/x". We have two links in question:
- /foo/bar/
- /foo/bar/baz
This is what happens:
/foo/bar/baz/x (the first link's url is deleted from the path namepathname.replace($(this).attr('href'), '')
)- "baz/x" is what remains.
- The character count (
length
) of this remainder is 5. this is our "penalty" for the link. - We compare 5 to our previous best distance (
if (overlap_penalty < best_distance)
). 5 is lower (=better) than 999. - We save
this
(being the<a href="/foo/bar/">
DOM object) for possible later use. - The second link is handled in the same manner:
/foo/bar/baz/x (the second link's url is deleted from the path name)- "/x" is what remains.
- The character count of this remainder is 2.
- We compare 2 to our previous best distance (being 5). 2 is lower than 5.
- We save
this
(being the<a href="/foo/bar/baz">
DOM object) for possible later use.
In the end, we just check if we found any matching link and, if so, apply addClass('selected')
to its closest <li>
parent.
Why dont u use
if($(this).attr('href') == pathname )
instead of
if (pathname.indexOf($(this).attr('href')) == 0)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
var windowLocationPathname = "/HTMLPage14.htm"; // For testing purpose.
//Or
//var windowLocationPathname = window.location.pathname;
$('ul.ui-ajax-tab').find('a[href^="' + windowLocationPathname + '"]').addClass('currentPage');
});
</script>
<style type="text/css">
.ui-ajax-tab
{
list-style: none;
}
a.currentPage
{
color: Red;
background-color: Yellow;
}
</style>
</head>
<body>
<ul class="ui-ajax-tab">
<li><a href="/HTMLPage14.htm">Test 1 (/HTMLPage14.htm)</a></li>
<li><a href="/HTMLPage15.htm">Test 2 (/HTMLPage15.htm)</a></li>
<li><a href="/HTMLPage16.htm">Test 3 (/HTMLPage16.htm)</a></li>
<li><a href="/HTMLPage17.htm">Test 4 (/HTMLPage17.htm)</a></li>
</ul>
</body>
</html>
精彩评论