How to prevent a hyperlink from linking - asp.net

Is it possible to prevent an asp.net Hyperlink control from linking, i.e. so that it appears as a label, without actually having to replace the control with a label? Maybe using CSS or setting an attribute?
I know that marking it as disabled works but then it gets displayed differently (greyed out).
To clarify my point, I have a list of user names at the top of my page which are built dynamically using a user control. Most of the time these names are linkable to an email page. However if the user has been disabled the name is displayed in grey but currently still links to the email page. I want these disabled users to not link.
I know that really I should be replacing them with a label but this does not seem quite as elegant as just removing the linking ability usings CSS say (if thats possible). They are already displayed in a different colour so its obvious that they are disabled users. I just need to switch off the link.

This sounds like a job for JQuery. Just give a specific class name to all of the HyperLink controls that you want the URLs removed and then apply the following JQuery snippet to the bottom of your page:
$(document).ready(function() {
$('a.NoLink').removeAttr('href')
});
All of the HyperLink controls with the class name "NoLink" will automatically have all of their URLs removed and the link will appear to be nothing more than text.
A single line of JQuery can solve your problem.

I'm curious on what it is you which to accomplish with that. Why use a link at all?
Is it just for the formatting? In that case, just use a <span> in HTML and use stylesheets to make the format match the links.
Or you use the link and attach an onClick-Event where you "return false;" which will make the browser not do the navigation - if JS is enabled.
But: Isn't that terribly confusing for your users? Why create something that looks like a link but does nothing?
Can you provide more details? I have this feeling that you are trying to solve a bigger problem which has a way better solution than to cripple a link :-)

A Hyperlink control will render as a "a" "/a" tag no matter what settings you do. You can customize a CSS class to make the link look like a normal label.
Alternatively you can build a custom control that inherits from System.Web.UI.WebControls.HyperLink, and override the Render method
protected override void Render(HtmlTextWriter writer)
{
if (Enabled)
base.Render(writer);
else
{
writer.RenderBeginTag(HtmlTextWriterTag.Span);
writer.Write(Text);
writer.RenderEndTag(HtmlTextWriterTag.Span);
}
}
}
Could be a bit overkill, but it will work for your requirements.
Plus I find is usefull to have a base asp:CustomHyperlink asp:CustomButton classes in my project files. Makes it easier to define custom behaviour throughout the project.

If you merely want to modify the appearance of the link so as not to look like a link, you can set the CSS for your "a" tags to not have underlines:
a: link, visited, hover, active {
text-decoration: none;
}
Though I would advise against including "hover" here because there will be no other way to know that it's a link.
Anyway I agree with #pilif here, this looks like a usability disaster waiting to happen.

If you mean to stop the link from activating, the usual way is to link to "javascript:void(0);", i.e.:
foo

This should work:
onclick="return false;"
if not, you could change href to "#" also. Making it appear as a rest of text is css, e.g. displaying arrow instead of hand is:
a.dummy {
cursor:default;
}

Thanks for all the input, it looks like the short answer is 'No you can't (well not nicely anyway)', so I'll have to do it the hard way and add the conditional code.

If you are using databind in asp.net handle the databinding event and just don't set the NavigateUrl if that users is disabled.

Have you tried just not setting the NavigateUrl property? If this isn't set, it may just render as a span.

.fusion-link-wrapper { pointer-events: none; }

Another solution is apply this class on your hyperlink.
.avoid-clicks {
pointer-events: none;
}

CSS solution to make tags with no href (which is what asp:HyperLink will produce if NavigateURL is bound to null/empty string) visually indistinguishable from the surrounding text:
a:not([href]), a:not([href]):hover, a:not([href]):active, a:not([href]):visited {
text-decoration: inherit !important;
color: inherit !important;
cursor: inherit !important;
}
Unfortunately, this won't tell screen readers not to read it out as a link - though without an href, it's not clickable, so I'm hoping it already won't be identified as such. I haven't had the chance to test it though.
(If you also want to do the same to links with href="", as well as those missing an href, you would need to add pointer-events:none as well, since otherwise an empty href will reload the page. This definitely leaves screen readers still treating it as a link, though.)
In the OP's use case, if you still have the href being populated from the database but have a boolean value that indicates whether the link should be a 'real' link or not, you should use that to disable the link, and add a:disabled to the selector list above. Then disabled links will also look like plain text rather than a greyed-out link. (Disabling the link will also provide that information to screen readers, so that's better than just using pointer-events: none and a class.)
A note of caution - if you add these sorts of rules globally rather than for a specific page, remember to watch out for cases where an tag has no (valid) href, but you are providing a click handler - you still need those to look/act like links.

Related

update CSS class dynamically for a whole website

I have a reference site for a series of books, and I'd like to make it so that readers can avoid spoilers. The idea I had was to make a setup webpage where they click on a checkbox for each book from which they want to see info. I could then store that (somehow) as a cookie for each time that they visit the site, plus have it work for each page in the site. So, one page might have this:
<li class="teotw">Rand killed a Trolloc</li>
and another page might have
<li class="teotw">Nynaeve tugged her braid</li>
and that information would not show up on the page unless they had checked the box for the "teotw" book. My initial thoughts are to do something like toggling the CSS class value like this:
document.styleSheets[0]['cssRules'][0].class['teotw'] = 'display:none';
document.styleSheets[0]['cssRules'][0].class['teotw'] = 'display:inherit';
but I'm not sure if this is the best method. Firstly, it would only apply to the current document only so I'd need a way to re-apply it to each page they visit. I'm using YUI as well, if it matters.
Any ideas on the best way of doing this?
There are many ways to implement it. You can use the YUI Stylesheet module (read its User Guide for how to use it) which will do what you're considering with cross-browser support and it's much easier to use than using the DOM directly.
Another way would be to add classes to the body of the page. You can define styles like this:
.teotw {
display: none;
}
.teotw-visible .teotw {
display: block;
}
With the following JS code:
if (someCondition) {
// show the hidden content
Y.one('body').addClass('teotw-visible');
}
For the persistance of the visible state you can use cookies with the YUI Cookie utilty or local storage with CacheOffline. Code using cookies would look something like this:
var body = Y.one('body');
if (Y.Cookie.get('teotwVisible')) {
body.addClass('teotw-visible');
}
// change the cookie
Y.one('#teotw-toggle').on('click', function (e) {
var checked = this.get('checked');
Y.Cookie.set('teotwVisible', checked);
body.toggleClass('teotw-visible', checked);
});
You should probably store the different sections in a JS object and avoid hard-coding class names in every JS line. Or maybe use a convention between checkboxes IDs and section class names.

How to render checked checkboxes using CSS alone?

This is may be very noobish and a bit embarrassing but I am struggling to figure out how to make checkboxes 'checked' using CSS?
The case is that if a parent has a class setup (for example) I'd like to have all the checkboxes having setup as parent to be checked. I'm guessing this is not doable in pure CSS, correct? I don't mind using JS but am just very curious if I could toggle the state of the checkboxes along with that of their parent (by toggling the class).
Here's a fiddle to play around with.
A checkbox being "checked" is not a style. It's a state. CSS cannot control states. You can fake something by using background images of check marks and lists and what not, but that's not really what you're talking about.
The only way to change the state of a checkbox is serverside in the HTML or with Javascript.
EDIT
Here's a fiddle of that pseduo code. The things is, it's rather pointless.
It means you need to adding a CSS class to an element on the server that you want to jQuery to "check". If you're doing that, you might as well add the actually element attribute while you're at it.
http://jsfiddle.net/HnEgT/
So, it makes me wonder if I'm just miss-understanding what you're talking about. I'm starting to think that there's a client side script changing states and you're looking to monitor for that?
EDIT 2
Upon some reflection of the comments and some quick digging, if you want a JavaScript solution to checking a checkbox if there's some other JavaScript plugin that might change the an attribute value (something that doesn't have an event trigger), the only solution would be to do a simple "timeout" loop that continuously checks a group of elements for a given class and updates them.
All you'd have to do then is set how often you want this timeout to fire. In a sense, it's a form of "long polling" but without actually going out to the server for data updates. It's all client side. Which, I suppose, is what "timeout" is called. =P
Here's a tutorial I found on the subject:
http://darcyclarke.me/development/detect-attribute-changes-with-jquery/
I'll see if I can whip up a jQuery sample.
UPDATE
Here's a jsfiddle of a timeout listener to check for CSS classes being added to a checkbox and setting their state to "checked".
http://jsfiddle.net/HnEgT/5/
I added a second function to randomly add a "checked" class to a checkbox ever couple of seconds.
I hope that helps!
Not possible in pure css.
However, you could have a jQuery event which is attached to all elements of a class, thereby triggering the check or uncheck based on class assignments.
Perhaps like this:
function toggleCheck(className){
$("."+className).each( function() {
$(this).toggleClass("checkedOn");
});
$(".checkedOn").each( function() {
$(this).checked = "checked";
});
}

Change HTML/CSS from ASP(C# or VB) code

In my case, I have an HTML/CSS Menu in the site master.
So, when you hover your mouse over "Graphics", it highlights it (using CSS onHover).
Now what I need to do is that when you actually click on "Graphics" (and it takes you to the graphics page), it remains highlighted, if possible in a different colour.
I'm thinking of modifying the Site.Master style from C# or VB code.
Any ideas? Thanks.
An idea would be to check what page you are in, and apply a css class:
<li class="<%= this.Page.ToString().ToLower().EndsWith("graphics_aspx") ? "selected" : "normal"%>">
Graphics<li>
Hope it helps!
You can either use the CSS active state if the page you are on directly relates to the link, however if the menu points to sections (i.e. multiple pages) you may need to use a bit of server side code to your master page, that gets the requested URL and determines which link is active. Usual convention is to then add the class 'active' or similar to the outputted html.
You can convert the UL/LI with runat = "server" and finally add styles in the code behind
Example
Control.Style.Add("display", "none");

How do I access a DIV from javascript, if ASP.NET mangles its ID?

I have a web page that contains a "div" element. On the page, there is javascript to reference the div: document.getElementById('divId'). This was working fine until another developer redesigned the page to use an ASP master page.
Now, document.getElementById('divId') returns null. It appears that ASP.net prepends some characters to the names of elements within contents forms when you use a master page. How can I know what the id of the div is when the page loads?
Update Allow me to give a specific example to clarify the question: My page had a div with ID divNotice. After changing my page to use a master page, I see when I print the source to the page that renders that the div ID is ctl00_ContentPlaceHolder1_divNotice. My question is, how am I supposed to know what the div ID is going to be when the framework is done with it?
I think that this is what you looking for.
document.getElementById('<%=divNotice.ClientID%>')
to get the ID of your element as appears on the html page use .ClientID
Hope this help.
Dynamically create the javascript using Control.ClientID to determine the calculated ID of div.
document.getElementById('<%= DivControl.ClientID %>')
Or search for the element on the client side using the base ID as a search pattern. See here: A generic way to find ASP.NET ClientIDs with jQuery
I prefer the server side calculation, but if you don't do it often and/or your current design prohibits it, the client side way is a reasonable workaround.
you can check i the element exists by checking if it returns not null
if (document.getElementById('divId') != null) { /* do your stuff*/ }
in other words:
if (document.getElementById('divId')) { /* do your stuff*/ }
now you have edited you orginal question i got it.. i would do something like this:
var arrDivs = document.getElementsByTagName('div'),
strDivName = "divId";
for (i=0;i<=arrDivs.length;i++){
if( arrDivs[i].id.indexOf(strDivName) != -1) {
alert("this is it")
}
}
you can see a demo here:
http://jsfiddle.net/pnHSw/2/
i think you could do it better with a regex.
But this is a pure JS way i don't know ASP.net
edit: i think Aristos solution is much cleaner :P
maybe you can use a descendent selector un css
<div id="wrapperControler">
<controler id="controler"></controler>
</div>
wrapperControler controler{
dosomething;
}

How can I use a traditional HTML id attribute with an ASP.net runat='server' tag?

I am refactoring some CSS on a website. I have been working on, and noticed the absence of traditional HTML IDs in the code.
There is heavy use of CssClass='…', or sometimes just class='…', but I can't seem to find a way to say id='…' and not have it swapped out by the server.
Here is an example:
<span id='position_title' runat='server'>Manager</span>
When the response comes back from the server, I get:
<span id='$aspnet$crap$here$position_title'>Manager</span>
Any help here?
Use jQuery to select the element:
$("span[id$='position_title']")....
jQuery's flexible selectors, especially its 'begins with'/'ends with selectors' (the 'end with' selector is shown above, provide a great way around ASP.NET's dom id munge.
rp
The 'crap' placed in front of the id is related to the container(s) of the control and there is no way (as far as I know) to prevent this behavior, other than not putting it in any container.
If you need to refer to the id in script, you can use the ClientID of the control, like so:
<script type="text/javascript">
var theSpan = document.getElementById('<%= position_title.ClientID %>');
</script>
Most of the fixes suggested her are overkill for a very simple problem. Just have separate divs and spans that you target with CSS. Don't target the ASP.NET controls directly if you want to use IDs.
<span id="FooContainer">
<span runat="server" id="Foo" >
......
<span>
</span>
You can embed your CSS within the page, sprinkled with some server tags to overcome the problem. At runtime the code blocks will be replaced with the ASP.NET generated IDs.
For example:
[style type="text/css"]
#<%= AspNetId.ClientID %> {
... styles go here...
}
[/style]
[script type="text/javascript"]
document.getElementById("<%= AspNetId.ClientID %>");
[/script]
You could go a bit further and have some code files that generate CSS too, if you wanted to have your CSS contained within a separate file.
Also, I may be jumping the gun a bit here, but you could use the ASP.NET MVC stuff (not yet officially released as of this writing) which gets away from the Web Forms and gives you total control over the markup generated.
Ok, I guess the jury is out on this one.
#leddt, I already knew that the 'crap' was the containers surrounding it, but I thought maybe Microsoft would have left a backdoor to leave the ID alone. Regenerating CSS files on every use by including ClientIDs would be a horrible idea.
I'm either left with using classes everywhere, or some garbled looking IDs hardcoded in the css.
#Matt Dawdy: There are some great uses for IDs in CSS, primarily when you want to style an element that you know only appears once in either the website or a page, such as a logout button or masthead.
The best thing to do here is give it a unique class name.
You're likely going to have to remove the runat="server" from the span and then place a within the span so you can stylize the span and still have the dynamic internal content.
Not an elegant or easy solution (and it requires a recompile), but it works.
.Net will always replace your id values with some mangled (every so slightly predictable, but still don't count on it) value. Do you really NEED to have that id runat=server? If you don't put in runat=server, then it won't mangle it...
ADDED:
Like leddt said, you can reference the span (or any runat=server with an id) by using ClientID, but I don't think that works in CSS.
But I think that you have a larger problem if your CSS is using ID based selectors. You can't re-use an ID. You can't have multiple items on the same page with the same ID. .Net will complain about that.
So, with that in mind, is your job of refactoring the CSS getting to be a bit larger in scope?
I don't know of a way to stop .NET from mangling the ID, but I can think of a couple ways to work around it:
1 - Nest spans, one with runat="server", one without:
<style type="text/css">
#position_title { // Whatever
}
<span id="position_titleserver" runat="server"><span id="position_title">Manager</span></span>
2 - As Joel Coehoorn suggested, use a unique class name instead. Already using the class for something? Doesn't matter, you can use more than 1! This...
<style type="text/css">
.position_title { font-weight: bold; }
.foo { color: red; }
.bar { font-style: italic; }
</style>
<span id="thiswillbemangled" class="foo bar position_title" runat="server">Manager</span>
...will display this:
Manager
3 - Write a Javascript function to fix the IDs after the page loads
function fixIds()
{
var tagList = document.getElementsByTagName("*");
for(var i=0;i<tagList.length;i++)
{
if(tagList[i].id)
{
if(tagList[i].id.indexOf('$') > -1)
{
var tempArray = tagList[i].id.split("$");
tagList[i].id = tempArray[tempArray.length - 1];
}
}
}
}
If you're fearing classitus, try using an id on a parent or child selector that contains the element that you wish to style. This parent element should NOT have the runat server applied. Simply put, it's a good idea to plan your structural containers to not run code behind (ie. no runat), that way you can access major portions of your application/site using non-altered IDs. If it's too late to do so, add a wrapper div/span or use the class solution as mentioned.
Is there a particular reason that you want the controls to be runat="server"?
If so, I second the use of < asp : Literal > . . .
It should do the job for you as you will still be able to edit the data in code behind.
I usually make my own control that extends WebControl or HtmlGenericControl, and I override ClientID - returning the ID property instead of the generated ClientID. This will cause any transformation that .NET does to the ClientID because of naming containers to be reverted back to the original id that you specified in tag markup. This is great if you are using client side libraries like jQuery and need predictable unique ids, but tough if you rely on viewstate for anything server-side.
If you are accessing the span or whatever tag is giving you problems from the C# or VB code behind, then the runat="server" has to remain and you should use instead <span class="some_class" id="someID">. If you are not accessing the tag in the code behind, then remove the runat="server".

Resources