Background
Modern browsers do away with the classic status bar and instead draw a small tooltip at the bottom of their windows that displays the link target on hover/focus.
An example of this (undesirable, in my case) behavior is illustrated in the following screenshot:
Questions
Is there a portable way to disable these tooltips?
Am I missing any obvious drawbacks to doing this in my particular situation?
Is my attempt (see below) a reasonable way of accomplishing this?
Reasoning
I am working on an intranet web application and would like to disable this behavior for some application-specific actions because quite frankly, https://server/# everywhere looks like an eye-sore and is obtrusive since in some instances my application draws its own status bar in that location.
My Attempt
I'm not a web-developer by trade, so my knowledge is still rather limited in this domain.
Anyway, here's my attempt with jQuery:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Target Tooltip Test</title>
<style>
a, span.a {
color: #F00;
cursor: pointer;
text-decoration: none;
}
a:hover, span.a:hover {
color: #00F;
}
a:focus, span.a:focus {
color: #00F;
outline: 1px dotted;
}
</style>
<script src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script>
$(document).ready(function() {
patch();
});
function patch() {
$('a').each(function() {
var $this = $(this).prop('tabindex', 0);
if($this.prop('href').indexOf('#') == -1 || $this.prop('rel').toLowerCase() == 'external') {
return;
}
var $span = $('<span class="a" tabindex="0"></span>');
$span.prop('data-href', $this.prop('href'));
$span.text($this.text());
$this.replaceWith($span);
});
$('a[rel="external"]').click(function() {
window.open($(this).prop('data-href'));
return false;
});
$('span.a').click(function() {
location.href = $(this).prop('data-href');
}).keypress(function(event) {
if(event.keyCode == 13) {
location.href = $(event.target).prop('data-href');
}
}).focus(function() {
window.status = ''; // IE9 fix.
});
}
</script>
</head>
<body>
<ol>
<li>External Link</li>
<li>Action Foo</li>
<li>Action Bar</li>
<li>Action Baz</li>
<li>Email Support</li>
</ol>
</body>
</html>
patch() replaces all links containing # (i.e., application-specific actions in my case) with a span element, makes all "external" links open in a new tab/window and doesn't seem to break custom protocol handling.
Is there a portable way to disable these tooltips?
Nope, other than workarounds like your example above.
Am I missing any obvious drawbacks to doing this in my particular situation?
You seem to be missing the fact that the whole situation is awkward. Why have links at all if you're going to make them look like buttons? Just use buttons. For that matter, why bother with links if you end up switching them out with spans anyway? Just use spans.
Is my attempt (see below) a reasonable way of accomplishing this?
It's not really reasonable as a general approach, because you're removing those anchor elements from the document, so any attached event listeners, expandos, etc. will be lost. It may work for your specific situation, but a more sane approach would be to not use links in the first place (see above).
If you're still determined to do something like this, at least don't replace the a element. Just get rid of its href attribute and set up an event listener as you did in your example. Now it's no longer a link, so it won't show up in the status bar (but it's still the same element, at least).
<button onclick="window.open('yoururlhere.html','_self')">your link text here</button>
Note that this treats ctrl-clicks as ordinary clicks and disables right-clicking. I don't know about middle clicks.
You could also use "a" and merely replace the href with the onclick as in the code above, but when I tried that my "a:hover" styling stopped working. Apparently an "a" without an href is considered unhoverable, at least in Firefox. So I switched to "button" and "button:hover" styling and all was well.
I understand this solution will be considered bad practice, but in some situations, eg the site I'm making made up mainly of full screen photos, aesthetics trumps principles.
The tooltip provides an indication to the user where a link will take them if clicked. It's part of the standard browser user experience and will be expected by users of your site. Changing this expectation because you don't think it looks nice will probably lead to a poor user experience. Any content shown in that area will be visible as soon as the user stops hovering over a link tag.
I know that any link that doesn't tell me where it is going looks pretty suspicious to me.
try this
$(this).removeAttr("href");
$(this).click(function(){}).mouseover(function(){.........}).etc
This is what I do with jQuery:
//remove status bar notification...
$('a[href]').each(function(){
u = $(this).attr('href');
$(this).removeAttr('href').data('href',u).click(function(){
self.location.href=$(this).data('href');
});
});
Related
For our website, we use Internet Browser before and it was totally fine with no errors but starting from yesterday we migrated to modern browsers and when we click, we get error message Uncaught TypeError: document.hwinv.datatyp.options.focus is not a function in the developer tool. Error is causing in document.hwin.datatyp.options.focus(); line. Before using in Edge, it was totally fine and right now, it is causing that error. May I know how can I fix it? Added JS Fiddle link to check. Also, I saw adding setTimeout but I don't know how that works.
JsFiddle link, U can see the the bottom of the web, there is 2 button and If i click those buttons, causing the error for .focus()
function gonext()
{
var myIndex = document.hwinv.datatyp.options.selectedIndex;
var chkvalue=document.hwinv.datatyp.options[myIndex].value;
if(!(chkvalue))
{
document.hwinv.datatyp.options.focus();
alert("Please select Hardware Type!");
}
else
{
document.hwinv.step.value='11';
document.hwinv.submit();
}
}
<body style="margin=0px;" alink="#0000ff" vlink="#0000ff" bgcolor="#ffffff" window.focus="document.hwinv.datatyp.options.focus();">
<form name="hwinv" method="post" action="inventory.php" target="bottomview">
Welcome to StackOverflow!
Oh boy. If this is the sort of HTML that your site has, then migrating it to use more "modern" HTML, CSS and JS is going to be quite a long process. But it has to be done, now that IE is officially dead.
Alternative: Use "Internet Explorer Mode" in Edge
You may not be aware that there is a way to switch Edge into running a site almost identically to how IE would have done it. Which might be enough to get your site working again. I found some decent instructions for how to do that.
However, I wouldn't rely on that as a long-term solution. At some point, you are going to need to migrate this site to use HTML5, CSS3, and modern JS. But it might help you out in a pinch.
Fixing your code
To start with, the specific answer to your question about the exception is that the focus() method doesn't exist on the .options property of select inputs. Rather, it exists on the select input object itself.
But we also want to deal with the other antiquated markup in the snippet you posted.
window.focus="..." is not a thing. There are on____ attributes on elements - such as onfocus in your case, but it is considered bad practice to use it, typically. Instead, register an event handler in the JS code like I do below.
style="margin=0px" is wrong. Within inline style attributes, the syntax is property: value, not property=value.
alink, vlink and bgcolor attributes should be replaced with the appropriate CSS, as I have done below. alink corresponds to body a, vlink corresponds to body a:visited and bgcolor corresponds to body { background-color: white; }.
function gonext() {
var myIndex = document.hwinv.datatyp.options.selectedIndex;
var chkvalue = document.hwinv.datatyp.options[myIndex].value;
if (!(chkvalue)) {
document.hwinv.datatyp.focus();
alert("Please select Hardware Type!");
} else {
document.hwinv.step.value = '11';
document.hwinv.submit();
}
}
document.addEventListener('DOMContentLoaded', function () {
document.hwinv.datatyp.focus();
});
body {
margin: 0;
background-color: white;
}
body a {
color: blue;
}
body a:visited {
color: blue;
}
<body>
<form name="hwinv" method="post" action="inventory.php" target="bottomview">
<select name="datatyp">
<option>Hammer</option>
<option>Spanner</option>
<option>Other</option>
</select>
</form>
</body>
I've been trying out the excellent Medium Editor. The problem that I've been having is that I can't seem to get links to "work".
At the simplest, here's some HTML/JS to use to demonstrate the problem:
HTML:
<html>
<head>
<script src="//cdn.jsdelivr.net/medium-editor/latest/js/medium-editor.min.js"></script>
<link rel="stylesheet" href="//cdn.jsdelivr.net/medium-editor/latest/css/medium-editor.min.css" type="text/css" media="screen" charset="utf-8">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/medium-editor/latest/css/themes/beagle.min.css" type="text/css">
</head>
<body>
<div class='editable'>
Hello world. link
</div>
</body>
</html>
Javascript:
var editor = new MediumEditor('.editable');
This fiddle demonstrates the problem (using the code above).
If you hover on the link, a popup appears.
If you click the link, nothing happens.
If you click the popup, a form appears where you can edit the link.
It seems to me that clicking the link should take me wherever the link's href is targeting. The only way to use the link is to right click and either open in a new tab or new window -- which I don't want to ask my users to do.
I feel like I must be missing something simple in the configuration (either the Anchor Preview Options or the Anchor Form Options). Unfortunately, I'm not seeing it.
In my actual application, I'm not using jQuery, but I am using angularjs. If a strictly Medium Editor answer doesn't exist, I can fall back to using basic JS or anything that angularjs provides.
I've found how to bind event.
Here is full event list https://github.com/yabwe/medium-editor/blob/master/CUSTOM-EVENTS.md
Try to change your code to
var editor = new MediumEditor('.editable')
.subscribe("editableClick", function(e){if (e.target.href) {window.open(e.target.href)}})
https://jsfiddle.net/fhr18gm1/
So medium-editor is built on top of the built-in browser support for contenteditable elements. When you instantiate medium-editor, it will add the contenteditable=true attribute to whatever element(s) you provided it.
By default, since the text is now editable (the contenteditable attribute makes the browser treat it as WYSIWYG text) the browser no longer supports clicking on the links to navigate. So, medium-editor is not blocking these link clicks from happening, the browsers do it inherently as part of making the text editable.
medium-editor has built in extensions for interacting with links:
anchor extension
allows for adding/removing links
anchor-preview extension
shows a tooltip when hovering a link
when the tooltip is clicked, allows for editing the href of the link via the anchor extension
I think the underlying goal of the editor is the misunderstanding here. The editor allows for editing text, and in order to add/remove/update links, you need to be able to click into it without automatically navigating away. This is what I think of as 'edit' mode.
However, the html produced as a result of editing is valid html, and if you take that html and put it inside an element that does NOT have the contenteditable=true attribute, everything will work as expected. I think of this as 'publish mode'
I look at editors like word or google docs, and you see a similar kind of behavior where when you edit the document, the links don't just navigate away when you click on them, you have to actually choose to navigate them through a separate action after you click the link. However, on a 'published' version of the document, clicking the link will actually open a browser window and navigate there.
I think this does make for a good suggestion as an enhancement to the existing anchor-preview extension. Perhaps the tooltip that appears when hovering a link could have multiple options in it (ie Edit Link | Remove Link | Navigate to URL).
tldr;
Links are not navigable on click when 'editing' text in a browser via the built-in WYSIWYG support (contenteditable). When not in 'edit' mode, the links will work as expected.
This could make for a nice enhancement to the medium-editor anchor-preview extension.
Working off some ideas from #Valijon in the comments, I was able to get it to work using the following code:
var iElement = angular.element(mediumEditorElement);
iElement.on('click', function(event) {
if (
event.target && event.target.tagName == 'A' &&
event.target.href && !event.defaultPrevented) {
$window.open(event.target.href, '_blank');
}
});
I think the key is that apparently the editor lets the event propogate to the ancestor elements, so I was able to just listen for the click on the top level editor element.
Here, $window is angular's $window service -- If you're not using angularjs, window would do the trick and I used angular.element to ease the event listener registry, but you could do it the old-fashioned way (or using the JS framework of your choice).
What I really wanted when I asked the question was behavior similar to Google Docs when in "edit" mode (as described by Nate Mielnik). I opened an issue on the Medium Editor tracker and they decided not to implement it as part of the core medium editor, but they noted that they would be happy to have someone add that functionality as an extension.
So, I decided to implement that functionality as an extension as suggested. It can be found as part of MediumTools1. The project is still in very early stages (e.g. I haven't done anything to make the styling look better, or to use better minifying practices, etc. but we'll happily accept Pull Requests for that).
The guts of the code look like this:
var ClassName = {
INNER: 'medium-editor-toolbar-anchor-preview-inner',
INNER_CHANGE: 'medium-editor-toolbar-anchor-preview-inner-change',
INNER_REMOVE: 'medium-editor-toolbar-anchor-preview-inner-remove'
}
var AnchorPreview = MediumEditor.extensions.anchorPreview;
GdocMediumAnchorPreview = MediumEditor.Extension.extend.call(
AnchorPreview, {
/** #override */
getTemplate: function () {
return '<div class="medium-editor-toolbar-anchor-preview">' +
' <a class="' + ClassName.INNER + '"></a>' +
' -' +
' <a class="' + ClassName.INNER_CHANGE + '">Change</a>' +
' |' +
' <a class="' + ClassName.INNER_REMOVE + '">Remove</a>' +
'</div>';
},
/** #override */
createPreview: function () {
var el = this.document.createElement('div');
el.id = 'medium-editor-anchor-preview-' + this.getEditorId();
el.className = 'medium-editor-anchor-preview';
el.innerHTML = this.getTemplate();
var targetBlank =
this.getEditorOption('targetBlank') ||
this.getEditorOption('gdocAnchorTargetBlank');
if (targetBlank) {
el.querySelector('.' + ClassName.INNER).target = '_blank';
}
var changeEl = el.querySelector('.' + ClassName.INNER_CHANGE);
this.on(changeEl, 'click', this.handleClick.bind(this));
var unlinkEl = el.querySelector('.' + ClassName.INNER_REMOVE);
this.on(unlinkEl, 'click', this.handleUnlink.bind(this));
return el;
},
/** Unlink the currently active anchor. */
handleUnlink: function() {
var activeAnchor = this.activeAnchor;
if (activeAnchor) {
this.activeAnchor.outerHTML = this.activeAnchor.innerHTML;
this.hidePreview();
}
}
});
As an explanation, I just use medium's flavor of prototypical inheritance to "subclass" the original/builtin AnchorPreview extension. I override the getTemplate method to add the additional links into the markup. Then I borrowed a lot from the base implementation of getPreview, but I bound new actions to each of the links as appropriate. Finally, I needed to have an action for "unlinking" the link when "Remove" is clicked, so I added a method for that. The unlink method could probably be done a little better using contenteditable magic (to make sure that it is part of the browser's undo stack), but I didn't spend the time to figure that out (though it would make a good Pull Request for anyone interested :-).
1Currently, it's the only part, but I hope that'll change at some point. . .
I need to change the mouse pointer to the wait cursor. I tried
document.body.style.cursor = 'wait';
In my fiddle, my mouse cursor does not change (nor does it change in my main app). I tried a couple methods, but nothing seems to work (IE7 and FF7 tested). How do I change the cursor? I am open to using CSS instead of JavaScript if that works better.
For what it is worth...In the final program, I need to change the pointer at the start of an AJAX call and then change it back to the default in the callback. But, this is a simplified example and still does not work.
I'd create a CSS class:
.busy {
cursor: wait !important;
}
and then assign this class to body or whatever element you want to mark as busy:
$('body').addClass('busy');
// or, if you do not use jQuery:
document.body.className += ' busy';
http://jsfiddle.net/ThiefMaster/S7wza/
If you need it on the whole page, see Wait cursor over entire html page for a solution
Since there is no text you don't really have a body (in terms of "it has no height").
Try adding some content and then hovering the text: http://jsfiddle.net/kX4Es/4/. You can just use CSS.
Or, add it to the <html> element to bypass this <body> constraint: http://jsfiddle.net/kX4Es/3/.
html {
cursor: wait;
}
Like this:
$('html').css('cursor', 'wait');
Or as a CSS class as said above by ThiefMaster
I only tried this in chrome and firefox so it may not work everywhere.
But if you want to do this with javascript and turn it on and off try this.
//add
document.styleSheets[1].insertRule('html {cursor:wait;}',document.styleSheets[1].cssRules.length);
//for firefox I had to tell it to fill the screen with the html element
//document.styleSheets[1].insertRule('html {height:100%;width:100%;cursor:wait;}',0);
//remove
document.styleSheets[1].deleteRule(document.styleSheets[1].cssRules.length-1);
http://www.quirksmode.org/dom/w3c_css.html#access seems to be a good reference on messing around with the actual stylesheets. I was hoping for a better way to edit the html elements style but this was all I could find...
are you declaring it as a function ?
function cursor_wait() {
document.body.style.cursor = 'wait';
}
then call
cursor_wait();
in your script ?
How Do I disable the copy paste feature in my webpage. To be precise, I don't want my users to copy any information from my website and use them for personal purposes. The previous question on the same topic doesn't give enough explanation. The onselect and ondrag aren't working. Please help.
I don't want my users to copy any
information from my website and use
them for personal purposes
There is no way to do this. If someone really wants your information, they can get it.
You might be able to give them a litte bit of trouble with disabling certain functions using javascript or whatever...but you'll only give the people who don't know much about technology that trouble. And usually those people aren't even trying to copy your data. The one's who are, will figure out a way.
If you publish information online, you should clearly indicate your copyright claim on the page (or indicate the type of license you issue the content under). Please find and read the copyright law of your territory to understand what this does and doesn't allow - for example, in the UK there are provisions for making personal copies of copyrighted material and for using parts of copyrighted work for critical review or parody.
You can't stop people from copying the content on your page. You can make it more difficult for them to do - but this will have a negative impact on your page. Techniques such as preventing the left-click of the mouse, intercepting keyboard events or converting your entire article into images just make your website less usable.
If you have textual information on your website, I can re-type it even if you've stopped every other method of me copying the image. If you have an image and you've managed to lock out everything else, I can still do a screen-grab (not to mention the fact that my browser caches all the images in a temporary folder on my machine).
Your content-paranoia affects many people who set up a website - but the idea behind the Internet is that it is used for sharing information.
Just add the following code to the HEAD tag of your web page:
<script type="text/JavaScript">
//courtesy of BoogieJack.com
function killCopy(e){
return false
}
function reEnable(){
return true
}
document.onselectstart=new Function ("return false")
if (window.sidebar){
document.onmousedown=killCopy
document.onclick=reEnable
}
</script>
By default, Chrome and Firefox block disabling the right click menu. You have to manually edit an entry in about:config in Firefox to prevent it being blocked, which is not something you can force your visitors to do.
Regarding IE, you can modify your BODY tag like so:
<body onContextMenu="return false">
Which will prevent the right click context menu.
Other than that, the next best step is to create an image of your text, place it in a .swf (flash) document, and point the page to load the .swf as the page. This will cause all browsers to display the flash context menu on right click, and will prevent simple copy/paste efforts.
I do agree with previous replies, regardless of method used, any user can simply use their Print Screen key, paste the image in Paint (or other program), save it, and use OCR to grab your text.
You need to rethink your strategy if you're resorting to these measures on the front end. What you are trying to do is inherently wrong.
As a visitor to your web page, pulling something like this is just going to annoy me - I will eventually figure out what you've done and get around it. That said, I've recently found this particular method can be quite effective if you're aiming to restrict impatient or non-technical users. Proceed with caution...
<div class="text">
<p>Hello, world! Sadly, I won't work.</p>
<img alt="I can't be dragged or saved either :(" src="tree.png">
<div class="preventSelect"></div>
</div>
...and the CSS:
.text {
position: relative;
width: auto; /* can be fixed as well (ie 400px) */
width: auto; /* can be fixed as well (ie 400px) */
z-index: 0;
}
.preventSelect {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1;
}
The obvious drawback for this method is that the user cannot interact with anything inside the div we're preventSelecting. That includes links, buttons, images etc.
Please don't use this unless you absolutely have to. Frankly, it's a pain in the ass for everyone.
To be honest, if you don't want people to use any information on your site, then you can't put it up there. If you stop them from being able to copy and paste the information, they'll still be able to take a screenshot of it, type it out and save the data that way. I know it's not the answer you're looking for, but that's just something to think about.
(I did this because i can't comment yet).
Forget it. It is not possible to block these functions in a browser. The "best" you can do is to present your data in an image or Flash movie - inconceivable, slow, impractical, horrible to implement and also circumventable using OCR software.
If all else fails, users will simply make screen shots or key in the data manually.
If you present data to your users, you will have to live with the possibility that they can copy it. End of story.
Use legal threats to prevent your contents, not technical means.
You can't ever disable it.. users can view the source of your page so the text is always available. If you put click handlers to disable right-click, they can turn javascript off..
The best you can try to do is make it inconvenient for people to deter them, but never can you prevent them.
It is impossible to secure a website against copying. There are some technices to make it more difficult, but as soon as the user has the information on his screen its already too late. He could for example take a picture with a camera if the screenshot function could be disabled somehow.
Disabling of javascript functionality (f.e. shortcuts) is not working in all browsers and the user may disable javascript.
Using programs like curl all the information on the webpage can be grabbed.
Best thing you could do is to put all the information you present into an image.
What the developers of lyrics.com have done is attach events to document.body.oncontextmenu, document.onselectstart, and document.body.onkeydown to disable the actions browsers would take.
It can be done as simply as
<body oncontextmenu="return false" onselectstart="return false"
onkeydown="if ((arguments[0] || window.event).ctrlKey) return false">
You'd need all three; oncontextmenu basically governs right clicks, onselectstart covers drag-selecting with the mouse, and onkeydown Ctrl-key events (like someone who'd hit Ctrl+A, Ctrl+C to copy the whole page).
But I highly recommend that you NOT DO THIS. It kills usability and frustrates even legitimate users (for example people that have certain key mappings set up, or the ones who use "back" and "reload" from the context menu), and the ones you'd have to worry about would not be hindered even the slightest bit. And frankly, your content is not as special as you think it is, or you wouldn't be serving it up to any loser with a web browser. Information that valuable is not put online.
As has been noted before, all that return false stuff is not enforceable. And because i found the page particularly infuriating, that prompted me to pop up a console and dissect what they did, and detach event handlers so i could copy whatever i like and they don't even get their precious click-tracking data. Really, though, all anyone has to do is disable JavaScript.
The only way to keep people from copying text from the internet, is to keep it off the internet. Any other way is doomed to fail, as you yourself are handing them a copy as part of the very act of serving it to them.
You can stop from copy paste using below code
<body ondragstart="return false" onselectstart="return false">
<script type="text/javascript">
function md(e)
{
try { if (event.button==2||event.button==3) return false; }
catch (e) { if (e.which == 3) return false; }
}
document.oncontextmenu = function() { return false; }
document.ondragstart = function() { return false; }
document.onmousedown = md;
</script>
<br />
Try adding this css:
#content {
pointer-events: none;
}
This will deactivate mouse actions, thus copy-paste too.
Disable cut, copy, and paste options.
<script language="text/javascript">
// disable portal cut copy and paste options.
$('body').bind('cut copy paste', function (e) {
e.preventDefault();
});
</script>
But I prefer to enable this option on localhost.
<script language="text/javascript">
// disable portal cut copy and paste options.
$('body').bind('cut copy paste', function (e) {
// enable only localhost
if (location.hostname === "localhost" || location.hostname === "127.0.0.1")
{
return;
}
e.preventDefault();
});
</script>
please try this one its working for me...
$('body').bind('cut copy paste',function(e) {
e.preventDefault(); return false;
});
With Javascript you can disable copy/cut/drag for average users who don't know how to use inspect element feature, for that just add this simple javascript code:
document.addEventListener("copy", disable);
document.addEventListener("cut", disable);
document.addEventListener("drag", disable);
document.addEventListener("dragstart", disable);
document.addEventListener("dragover", disable);
document.addEventListener("dragend", disable);
document.addEventListener("drop", disable);
function disable(e) {
if (e) e.preventDefault();
return false;
}
If the user however tries to access the source code then you can't stop him, the best is to wrap each sentence in its own span to make it difficult for him to copy.
<script type="text/JavaScript">
function killCopy(e){
return false
}
function reEnable(){
return true
}
document.onselectstart=new Function ("return false")
if (window.sidebar){
document.onmousedown=killCopy
document.onclick=reEnable
}
</script>
I would suggest disabling right click.
<script language="text/javascript">
var message = "Not allowed.";
function rtclickcheck(keyp){
if (navigator.appName == "Netscape" && keyp.which == 3){
alert(message); return false;
}
if (navigator.appVersion.indexOf("MSIE") != -1 && event.button == 2) {
alert(message);
return false;
}
}
document.onmousedown = rtclickcheck;
</script>
After clicking a link with a common href (local page or web-site)
and the href is successfully loaded, both FF2 and IE7 will display
the link with a:visited styling.
For links with href="javascript:anyfunc()", IE7 works as above
while FF2 does not display a:visited styling. No change with any
DOCTYPE.
Q: Is either behaviour with JS links and :visited considered correct?
Q: Does FF2 leave anchor state unchanged after clicking a JS link?
Q: Without having to attach an onClick handler or modify classes/style
with JS, is there a concise way to tell FF2 to use :visted
styling independent of whether href is another page or a JS link?
Example follows:
<html>
<head>
<style>
div.links { font-size: 18px; }
div.links a { color: black; text-decoration: none; }
div.links a:visited { background-color: purple; color: yellow; }
div.links a:hover { background-color: yellow; color: black; }
</style>
<script>
function tfunc(info) { alert("tfunc: info = " + info) }
</script>
</head>
<body>
<div class="links">
JS Link 1<br>
JS Link 2<br>
Common href, google
</div>
</body>
</html>
It would be difficult to style these sorts of links... whilst they may have the same href, they could potentially do anything through JS (which may make it seem that visiting it would not).
Is there a way to link to something such as a HTML page and attach event handlers to the link (and return false to stop the link clicking through)? And if the links are in fact JS hooks, I would use an element such as a <button> and style it accordingly... remember to add cursor: pointer so the end user knows it is clickable.
Using inline javascript:function(something) in a href is bad practice. Try unobtrusive event handlers.
a:hover MUST come after a:link and a:visited in the CSS definition in order to be effective!
Here's my take:
Q: Is either behaviour with JS links and :visited considered correct?
The purpose of a link is to retrieve a resource. If your link doesn't go anywhere, what are you "visiting"? The behavior is correct from this perspective in my opinion.
Q: Does FF2 leave anchor state unchanged after clicking a JS link?
It seems as though it doesn't change the state of the link to :visited unless it points to an element in the page (which means the link points to the current page which is implicitly visited) or to another resource which as already been accessed.
Q: Without having to attach an onClick handler or modify classes/style with JS, is there a concise way to tell FF2 to use :visted styling independent of whether href is another page or a JS link?
I don't think so. You can probably get the visited effect if you point the href of the link to "#" and use the onclick handler for your JavaScript needs.
I have encountered the issue I believe this question is asking. Consider this simple example:
style sheet:
#homebox { display: none;}
#contactbox { display: none; }
html:
<a id="#home"></a>
Show Home
<div id="homebox">Your home</div>
<a id="#contact onclick="return showHideDiv(this);"></a>
<div id="contactbox">Contact Info</div>
script:
function showHideDiv(elem) {
if( elem.style.display && elem.style.display == "none"; ) elem.style.display = "block";
else if( elem.style.display && elem.style.display == "block"; ) elem.style.display = "none";
return true;
}
Although not the most beautiful code, it points out some issues which can develop when using javascript onlick within a href. The reason you might want to do something like this, is to create dynamic content changes without reload which show a visited style. The a links would be handier than buttons, so the visited status of the links is maintained, even though internal. However, I have noticed some issues with browsers triggering visited status on internal links, let alone internal links with javascript onclick event handlers. A button would require coding a function to control visited styles.
I agree with Alex, a link should be a link to something, not a JS trigger - a button would much more effective here.
If you do want to attach some JS function to a link, you should definitely use some unobtrusive JS to attach that function to the click event.
EG using jQuery:
$("#myLinkID").click(function () {
//function stuff
});