I have a menu inside a masterpage (in a ASP.NET Web site), and i want to highlight active page in masterpage menu and submenus.
HTML:
<ul id="nav" class="sf-menu">
<li class="current-menu-item">Home</li>
<li>menu-2
<ul>
<li>full</li>
<li>featurs</li>
<li>typography</li>
</ul>
</li>
</ul>
CSS:
#nav>li.current-menu-item>a,
#nav>li.current_page_item>a{
color: #fe8300;
}
thanks in advance.
finally i solved my problem with using jQuery:
var str=location.href.toLowerCase();
$("#nav li a").each(function() {
if (str.indexOf($(this).attr("href").toLowerCase()) > -1) {
$("li.current-menu-item").removeClass("current-menu-item");
$(this).parent().addClass("current-menu-item");
}
});
$("li.current-menu-item").parents().each(function(){
if ($(this).is("li")){
$(this).addClass("current-menu-item");
}
});
There are many ways to do this. There are some easy and some ugly hacky ones:
Solution 1:
Use a Menu Control. The standard .NET Menu Control has an easy solution to do this. This is the cleanest and fastest solution in my opinion. Have a look at this post. Maby it'll help you if you choose this solution.
Solution 2:
You coud use some sort of javascript to highlight the current item. jQuery would make that easier if you dont want to write everything by yourself. For this solution have a look at this page. It's outdated but still effective.
Solution 3:
This is kinda ugly solution and you can do that in many different ways: You could change the <a> elements to HyperLink controls and set some sort of session or cookie when you click on them. When set you could change the style based on the value the cookie has.
There are even more ways you could solve this but I think the first two solutions will help you.
check your url and get the html file name then compare it and set your css class in master page or make a menu UserControl seperate and then put it on master page.
You have to change your anchor tag to Hyperlinks
asp.net markup :
<li><asp:HyperLink runat="server" ID="lnk_full" NavigateUrl="page-full.html" Text="full" /></li>
<li><asp:HyperLink runat="server" ID="lnk_features" NavigateUrl="page-features.html" Text="features" /></li>
<li><asp:HyperLink runat="server" ID="lnk_typography" NavigateUrl="page-typography.html" Text="typography" /></li>
Codebehind :
protected void SelectMenu()
{
try
{
string page = Path.GetFileNameWithoutExtension(Request.AppRelativeCurrentExecutionFilePath);
string pageDirectory = Path.GetDirectoryName(Request.AppRelativeCurrentExecutionFilePath);
string category = Request.QueryString.Count>0 ? Request.QueryString[0] : string.Empty;
if (pageDirectory.Length > 3)
{
pageDirectory = pageDirectory.Substring(2, pageDirectory.Length - 2);
}
if (pageDirectory != null && pageDirectory.Length > 0 && page != null && page.Length > 0)
{
switch (pageDirectory)
{
case "Secure\\Clients":
switch (page)
{
case "page-full":
lnk_full.CssClass = "current-menu-item";
break;
case "page-features":
lnk_features.CssClass = "current-menu-item";
break;
case "page-typography":
lnk_typography.CssClass = "current-menu-item";
break;
}
break;
}
}
}
catch (Exception ex)
{
throw ex;
}
}
If your webpages are in root directory then don't switch for pageDirectory. and if you are using querystrings then you can switch for category. Hope this is helps you.
$(function () {
$(".navbarâbtn a").each(function () {
var hreff = this.href.trim().split("/").splice(3, 4);
if (hreff.length > 1)
hreff.splice(0, 1);
if (hreff[0] == window.location.pathname.split("/").splice(1, 1)[0])
$(this).parent().addClass("active");
});
})
This works fine for me during development and in local, but when I host it on IIS the active highlighting on the menu does not work. What am I missing here?
Masterpage code below
$(document).ready(function () {
//You can name this function anything you like
function activePage() {
//When user lands on your website location.pathname is equal to "/" and in
//that case it will add "active" class to all links
//Therefore we are going to remove first character "/" from the pathname
var currentPage = location.pathname;
var slicedCurrentPage = currentPage.slice(1);
//This will add active class to link for current page
$('.nav-link').removeClass('active');
$('a[href*="' + location.pathname + '"]').closest('li').addClass('active');
//This will add active class to link for index page when user lands on your website
if (location.pathname == "/") {
$('a[href*="index"]').closest('li').addClass('active');
}
}
//Invoke function
activePage();
});
jQuery(document).ready(function() {
var str = location.href.toLowerCase();
jQuery('#topnav li a[href=\'' + str + '\']').addClass('active');
});
Related
Situation: I want to remove the anchor tags ( #tag ) from the end of the URL
What I have tried: I have been following "https://www.finsweet.com/hacks/15/" and "https://stackoverflow.com/questions/34175285/removing-anchor-tags-from-url". Its not working out very well though.
Code:
My snippet from the top nav bar
<ul class="nav">
<li class="scroll-to-section">
Home
</li>
</ul>
My use of Id
<div class="main-banner header-text" id="top">
Maybe the way i approached the edits to the navigation bar is wrong.. but im not sure what i need to to do to achieve the goal. Or how I used the classes and IDs is possibly incorrect?
--- Edit 1 ---
this is the snipper of the script im attempting to use to remove the anchor tag from the URL bar of a brower.
$("#js-anchor").click(function (evt) {
evt.preventDefault();
var anchor = $(this).text();
$("html, body").animate(
{
scrollTop: $("#" + anchor).offset().top,
},
1500
);
});
And the html im looking at
<li class="scroll-to-section">
<a id="js-anchor" href="#testimonials" class="active"
>staff</a>
</li>
The experment on it is here:
https://the-md.studio/indexhash.html
EDIT2
My new attempt
<li class="scroll-to-section">
Home
</li>
JS
$(document).ready(function () {
// get the anchor link buttons
const menuBtn = $(".scroll-to");
// when each button is clicked
menuBtn.click(() => {
// set a short timeout before taking action
// so as to allow hash to be set
setTimeout(() => {
// call removeHash function after set timeout
removeHash();
}, 5); // 5 millisecond timeout in this case
});
// removeHash function
// uses HTML5 history API to manipulate the location bar
function removeHash() {
history.replaceState(
"",
document.title,
window.location.origin + window.location.pathname + window.location.search
);
}
});
Just saw this Q. I guess this is what you tried to ask:
// first: get the full url
var hash_url = window.location.href;
// second: simply do a split
// can't go wrong here, because url's that show content are always in correct format
hash_url = hash_url.split('#'); var clean_url = hash_url[0];
alert(clean_url);
There's your clean url!
I have a pivot element in my page, it's work but when I want to change text by icons, they become not clickable and we have to click in the grey part. Do you know how make them clickable ?
In green the clickable part and in red not clickable part.
Part of my code :
<li id="listPivotAccount" class="ms-Pivot-link is-selected " data-content="account" title="Mon compte" tabindex="1">
<i style="" class=" ms-Icon ms-Icon--Accounts" aria-hidden="true"></i>
</li>
You can check the code here
For the record, I have never used SharePoint, so there may be a more elegant solution.
You can fix this behaviour by adding this vanilla JavaScript after your current JavaScript:
// select all icons
var msIcons = document.querySelectorAll(".ms-Icon");
// loop all icons
for (var i = 0; i < msIcons.length; i++) {
// add a click event to the nearest element with class "ms-Pivot-link"
msIcons[i].closest(".ms-Pivot-link").addEventListener("click", function() {
this.click();
});
}
jQuery Example of the above code:
$(".ms-Icon").on("click", function() {
$(this).closest(".ms-Pivot-link").click();
});
var Dropdown = new Class({
initialize: function() {
var e = this;
document.addEvents({
"click:relay(.windowLabel, .dropdown a.dropdownTrigger)": function(t, n) {
t && (t.preventDefault(),
t.stopPropagation()), // issue is here
e.showPopover.call(e, n)
}
}),
document.body.addEventListener("click", function(t) {
e.hideOutside.call(e, t)
})
},
// ...
})
Problem is in preventing propagation of events, and as result all nested elements shouldn't emit what you need.
What is the solution?
You can try add the icon in different way (for example using :before, :after)
The simple way to fix it is to trigger the pivot with a click. So if you use JQuery :
$('.ms-Icon').click(function () {
var pivot = $(this).closest(".ms-Pivot-link");
pivot.click();
});
Short and compatible with IE > 9
So I have this:
clicking here
<a name="link">goes here</a>
Simple, but the problem is that my site has a fixed position header that stays at the top of the page, so when a user clicks on the link, the place I want them to go to is hidden by the header. So I guess where I really want them to end up a certain amount of pixels above what I actually want them to see. I've tried putting the destination link above where I want them to end up, but it's a block of text so it changes with different screen sizes and therefore isn't consistent.
I'm wondering if there is any way to solve this problem, perhaps something with css.
Thanks in advance.
I realise this is over a year old, but for the benefit of anyone else who comes across it:
A slightly simpler solution is to put padding at the top of the section you are targeting with the link.
HTML:
<section id="section_name">
...Your stuff here...
</section>
CSS:
#section_name {
padding-top: 40px;
}
You could use a jQuery method so that when a link with a # is clicked, it finds the position of the element it's meant to go to and then moves to a position X number of pixels above the target.
Something like this:
$(function(){
var positionOffset = 50;
$('a[href=*"#"]').click(function(){
var targetHash = this.hash;
if(targetHash.length > 0 && targetHash == window.location.hash){
var elementPosition;
if($(targetHash).length){
elementPosition = $(targetHash).offset();
} else {
var targetAnchor = targetHash.replace("#", "");
elementPosition = $('a[name="' + targetAnchor + '"]').position();
}
$(window).scrollTop(elementPosition.top - positionOffset);
return false;
} else {
return true;
}
});
});
When I use the HTML <base> tag to define a base URL for all relative links on a page, anchor links also refer directly to the base URL. Is there a way to set the base URL that would still allow anchor links to refer to the currently open page?
For example, if I have a page at http://example.com/foo/:
Current behaviour:
<base href="http://example.com/" />
bar <!-- Links to "http://example.com/bar/" -->
baz <!-- Links to "http://example.com/#baz" -->
Desired behaviour:
<base href="http://example.com/" />
bar <!-- Links to "http://example.com/bar/" -->
baz <!-- Links to "http://example.com/foo/#baz" -->
I found a solution on this site: using-base-href-with-anchors that doesn't require jQuery, and here is a working snippet:
<base href="https://example.com/">
/test
Anchor
Or without inline JavaScript, something like this:
document.addEventListener('DOMContentLoaded', function(){
var es = document.getElementsByTagName('a')
for(var i=0; i<es.length; i++){
es[i].addEventListener('click', function(e) {
e.preventDefault()
document.location.hash = e.target.getAttribute('href')
})
}
})
Building upon James Tomasino's answer, this one is slightly more efficient, solves a bug with double hashes in the URL and a syntax error.
$(document).ready(function() {
var pathname = window.location.href.split('#')[0];
$('a[href^="#"]').each(function() {
var $this = $(this),
link = $this.attr('href');
$this.attr('href', pathname + link);
});
});
A little bit of jQuery could probably help you with that. Although base href is working as desired, if you want your links beginning with an anchor (#) to be totally relative, you could hijack all links, check the href property for those starting with #, and rebuild them using the current URL.
$(document).ready(function () {
var pathname = window.location.href;
$('a').each(function () {
var link = $(this).attr('href');
if (link.substr(0,1) == "#") {
$(this).attr('href', pathname + link);
}
});
}
Here's an even shorter, jQuery based version I use in a production environment, and it works well for me.
$().ready(function() {
$("a[href^='\#']").each(function() {
this.href = location.href.split("#")[0] + '#' + this.href.substr(this.href.indexOf('#')+1);
});
});
You could also provide an absolute URL:
<base href="https://example.com/">
test
Rather than this
test
I'm afraid there is no way to solve this without any server-side or browser-side script. You can try the following plain JavaScript (without jQuery) implementation:
document.addEventListener("click", function(event) {
var element = event.target;
if (element.tagName.toLowerCase() == "a" &&
element.getAttribute("href").indexOf("#") === 0) {
element.href = location.href + element.getAttribute("href");
}
});
<base href="https://example.com/">
/test
#test
It also works (unlike the other answers) for dynamically generated (i.e. created with JavaScript) a elements.
If you use PHP, you can use following function to generate anchor links:
function generateAnchorLink($anchor) {
$currentURL = "//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}";
$escaped = htmlspecialchars($currentURL, ENT_QUOTES, 'UTF-8');
return $escaped . '#' . $anchor;
}
Use it in the code like that:
baz
To prevent multiple #s in a URL:
document.addEventListener("click", function(event) {
var element = event.target;
if (element.tagName.toLowerCase() == "a" &&
element.getAttribute("href").indexOf("#") === 0) {
my_href = location.href + element.getAttribute("href");
my_href = my_href.replace(/#+/g, '#');
element.href = my_href;
}
});
My approach is to search for all links to an anchor, and prefix them with the document URL.
This only requires JavaScript on the initial page load and preserves browser features like opening links in a new tab. It also and doesn't depend on jQuery, etc.
document.addEventListener('DOMContentLoaded', function() {
// Get the current URL, removing any fragment
var documentUrl = document.location.href.replace(/#.*$/, '')
// Iterate through all links
var linkEls = document.getElementsByTagName('A')
for (var linkIndex = 0; linkIndex < linkEls.length; linkIndex++) {
var linkEl = linkEls[linkIndex]
// Ignore links that don't begin with #
if (!linkEl.getAttribute('href').match(/^#/)) {
continue;
}
// Convert to an absolute URL
linkEl.setAttribute('href', documentUrl + linkEl.getAttribute('href'))
}
})
You can use some JavaScript code inside the tag that links.
<span onclick="javascript:var mytarget=((document.location.href.indexOf('#')==-1)? document.location.href + '#destination_anchor' : document.location.href);document.location.href=mytarget;return false;" style="display:inline-block;border:1px solid;border-radius:0.3rem"
>Text of link</span>
How does it work when the user clicks?
First it checks if the anchor (#) is already present in the URL. The condition is tested before the "?" sign. This is to avoid the anchor being added twice in the URL if the user clicks again the same link, since the redirection then wouldn't work.
If there is sharp sign (#) in the existing URL, the anchor is appended to it and the result is saved in the mytarget variable. Else, keep the page URL unchanged.
Lastly, go to the (modified or unchanged) URL stored by the mytarget variable.
Instead of <span>, you can also use <div> or even <a> tags.
I would suggest avoiding <a> in order to avoid any unwanted redirection if JavaScript is disabled or not working, and emulate the look of your <a> tag with some CSS styling.
If, despite this, you want to use the <a> tag, don't forget adding return false; at the end of the JavaScript code and set the href attribute like this <a onclick="here the JavaScript code;return false;" href="javascript:return false;">...</a>.
From the example given in the question. To achieve the desired behavior, I do not see the need of using a "base" tag at all.
The page is at http://example.com/foo/
The below code will give the desired behaviour:
bar <!-- Links to "http://example.com/bar/" -->
baz <!-- Links to "http://example.com/foo/#baz" -->
The trick is to use "/" at the beginning of string href="/bar/".
If you're using Angular 2 or later (and just targeting the web), you can do this:
File component.ts
document = document; // Make document available in template
File component.html
<a [href]="document.location.pathname + '#' + anchorName">Click Here</a>
I have a menu that I am using and it will change the background color when I hover using a:hover but I want to know how to change the class=line so that it sticks.
So from the home if they click contacts the home pages
from (a href="#" class="clr") to (a href="#")
and Contacts would change
from (a href="#") to (a href="#" class="clr")
any help?
JD
I believe you are wanting to highlight the navigational item that you're on. My answer here is fairly valid in this question as well, I believe:
It's a better semantic match and likely an easier variable to set to keep the navigation using the same classes or ids everywhere and only alter the body element's id to match:
<li id="homeNav">home</li>
<li id="blogNav">blog</li>
and then on each page...
<body id="home">
<body id="blog">
And in the css:
#home #homeNav {background-image:url(homeNav-on.jpg);}
#blog #blogNav {background-image:url(blogNav-on.jpg);}
The way to change class (I assume you're talking of the DOM), in javascript is:
document.getElementById("element").className='myClass';
Hope this helps.
The mechanism we use frequently is by having a few generic event listeners on the body and have all required events bubble up. Once caught, we check for a certain className (or className pattern) on the triggering element. If such a className is found, we consider it a state identifier, and we trigger behavior based on such states.
For instance, we have defined className pairs (such as "selected" and "unselected") with the default behavior of toggling. Or make them exclusive by giving the parent element the className "exclusive-selected".
A simple mechanism like that can be extended to your liking and can be very powerful.
Allow me to post a simple demonstration. Non-generic, but it is just to illustrate the inner workings of such a mechanism. For this example I consider the className pair "selected" and "unselected" to be exclusive.
<html>
<head>
<script>
document.onclick = function(evt) {
var el = window.event? event.srcElement : evt.target;
if (el && el.className == "unselected") {
el.className = "selected";
var siblings = el.parentNode.childNodes;
for (var i = 0, l = siblings.length; i < l; i++) {
var sib = siblings[i];
if (sib != el && sib.className == "selected")
sib.className = "unselected";
}
}
}
</script>
<style>
.selected { background: #f00; }
</style>
</head>
<body>
One
Two
Three
</body>
</html>
It ought to work on IE, Firefox and other browsers. Of course this mechanism can be made generic and have all kinds of className states and behaviors implemented.
This may not apply to you, but it may lead you down the right path. If you are using PHP, stick this in your head before the doctype declaration or the (x)html tag:
<?php
// Get current page file name
$url = Explode('/', $_SERVER["PHP_SELF"]);
$page = $parts[count($url) - 1];
?>
Then, in your menu item where you would like the class designation, place the following, but change "index.php" to the name of the page:
<?php if ($page == "index.php") echo ' class="current"' ?>
So ultimately your menu should look similar to this:
<div id="navigation">
<ul>
<li><a href="index.php"<?php if ($page == "index.php") echo ' class="current"' ?>>Home</a></li>
<li><a href="page1.php"<?php if ($page == "page1.php") echo ' class="current"' ?>>Resume</a></li>
<li><a href="page2.php"<?php if ($page == "page2.php") echo ' class="current"' ?>>Photography</a></li>
</ul>
</div>
Last step is adding the CSS:
#navigation ul li a.current {
background-color: #FFF;
}
Hope this helps.
You may want to check out jQuery (jquery.com).
Using jQuery, you would change the class (and stick it) like this:
$('#link-id').addClass('your-class');
You could bind the code to the links like this:
$('#link-id').mouseover(
function(){
$(this).addClass('your-class');
}
);
http://docs.jquery.com/Attributes