reptile7's JavaScript blog
Wednesday, December 26, 2012
Not on the Menu
Blog Entry #274

We return now to our discussion of Lissa Explains It All's up.html demo page. In the demo source the marquee code is followed by a center element bearing a request for the demo's visitors:

<center>Do not remove the graphics from this page please, I made them for this page only =)</center>

In the hope of preventing the user from downloading the mfish1.gif/mfish2.gif images by right-clicking them, popping up a context menu, and saving them (presumably this also applies to the bubble images, but you have to be pretty fast to right-click those guys)
A context menu with a highlighted 'Save Image As...' command
Lissa places the script below in the document head:

/* No right-click script v.2.5; © 1998 barts1000;
Provided free at - don't delete this header! */

// Message for the alert( ) box
var message = "Sorry, that function is disabled.\n\nContents & Graphics Copyright ©Lissa\nMy work is not Public Domain, and should NOT be taken from this site.";

// Don't edit below!
function click(e) {
    if (document.all) {
        if (event.button == 2) {
            return false; } }
    if (document.layers) {
        if (e.which == 3) {
            return false; } } }

if (document.layers) document.captureEvents(Event.MOUSEDOWN);
document.onmousedown = click;

The preceding script was authored by "barts1000" and at a time (1998) when the current versions of Internet Explorer and Netscape were IE 4.x and Netscape 4.x, respectively. A document.onmousedown = click; statement causes the click( ) function to listen for mousedown events that occur anywhere in the document content area. Right-clicking a demo image calls the click( ) function, which displays a "don't take my stuff" message on an alert( ) box and returns false so as to end the event handling for the triggering mousedown event and thereby prevent a context menu from popping up. With most browsers, context menus are generated by mousedown events and not by click events and would therefore not be suppressed by a document.onclick = click; click( ) trigger.

Browser differences:
• IE 4.x goes through the document.all gate and then checks the value of the then-proprietary, now-standard event.button property, which returns 2 for a right-click.
• Netscape 4.x goes through the document.layers gate and then checks the value of the now cross-browser but still not standard e.which property, which returns 3 for a right-click.
• For both IE 4.x and Netscape 4.x, mousedowning on an image dispatches the mousedown event to the underlying img element. Netscape 4.x does not support the onmousedown event handler for the client-side Image object and does not support event bubbling, so it must capture mousedown events at the level of the window or document object in order to bind an image mousedown to the click( ) function.

FYI: If you're going to put a non-ASCII character - in this case a copyright symbol - in a string literal, then the safe and reliable way to do so is to encode the character as a Unicode escape sequence, i.e., ©Lissa should be formulated as \u00A9Lissa.

Although not labeled "Windows only", the barts1000 script as originally written does not work on the Mac platform. Back in the day Apple's mice had only one button, and the Classic Mac browsers on my iMac accordingly do not recognize right-button mouse events qua right-button mouse events, e.g., a right-click is interpreted as an ordinary (left-)click. However, control-clicking a rendered element does display a context menu with Classic Mac browsers. I find that IE 4.5 and Netscape 4.61 do not interpret control-clicks as right-clicks but Netscape 6.2.3 and Netscape 7.02 do: with the latter two browsers the barts1000 script works as advertised upon changing the document.layers gate to a document.getElementById && !document.all gate, i.e., the alert( ) message pops up and a context menu doesn't.

As for the OS X GUI browsers on my computer, they all recognize right-button mouse events and they all display a context menu upon control-clicking a rendered element. The two oldest of these browsers, IE 5.2.3 and Opera 7.50*, disable JavaScript for control-click and right-click events - this is not so odd given that they predate the Mighty Mouse**, the first Apple mouse with a right-button capability - they won't even call the click( ) function, let alone go through the document.all gate, with a control-click or right-click. The rest of the OS X gang go through a document.getElementById && !document.all gate and generally display the alert( ) message but the return false; statement does not prevent a context menu from popping up (with one exception - the script does suppress right-click-generated context menus when using Camino - but in all other cases I get a context menu).

*Turning on Opera 7.50's
Allow script to receive right clicks
Preferences option has no effect on my computer.

**I myself use a Mighty Mouse; its 'right button' is enabled via the Keyboard & Mouse pane of the System Preferences application:
Enabling the Mighty Mouse's 'right button'
A newer script

The barts1000 script is offered as a standalone unit of code by the How do I disable the right click? subsection of Section 6 of the JavaScript subsector of Lissa Explains It All; the subsection also provides a second, slightly newer 'no right-click' script that takes us in the direction we want to go:

if (window.Event) document.captureEvents(Event.MOUSEUP);

function nocontextmenu( ) {
    event.cancelBubble = true;
    event.returnValue = false;
    return false; }

function norightclick(e) {
    if (window.Event) {
        if (e.which == 2 || e.which == 3) return false; }
    else if (event.button == 2 || event.button == 3) {
        event.cancelBubble = true;
        event.returnValue = false;
        return false; } }

if (document.layers) document.captureEvents(Event.MOUSEDOWN);
document.oncontextmenu = nocontextmenu;
document.onmousedown = norightclick;
document.onmouseup = norightclick;

Lissa does not specify the second script's author; admittedly, tracking down script authors can often be difficult. She also doesn't give a date for the script, although the script's combination of features indicates that it was written in either 1999 or 2000.

The second script's all-important feature is the oncontextmenu event handler, which was first implemented by Microsoft in IE 5 for Windows (IE 5 for Mac doesn't support it), was subsequently picked up by Netscape for Netscape 6, and now has cross-browser support, and is being brought into HTML5 (nope, it didn't make the cut - the WHATWG guys are currently working on it). The display of a context menu constitutes a contextmenu event, which can be tied to the execution of JavaScript code by the oncontextmenu event handler. Like most mouse-related events, the contextmenu event can be canceled, and the script's nocontextmenu( ) function aims to do just that.

The nocontextmenu( ) function is meant for IE 5+ for Windows - note its use of the event keyword for referencing the event object. I can't tell you if the cancelBubble and returnValue assignments*** are necessary with IE, but what I can tell you is that the return false; statement by itself successfully suppresses the display of context menus with Firefox, Google Chrome, Safari, Opera 12, Camino, and Netscape 6/7/9 on my computer, as would be expected from the first Example on Mozilla's "GlobalEventHandlers.oncontextmenu" page.

***Microsoft's own oncontextmenu examples don't use this code and I am thus not inclined to discuss it, but let me make two quick comments thereon:
(1) If we're going to register the nocontextmenu( ) listener on the document object, then we shouldn't be setting event.cancelBubble to true, i.e., we will want the contextmenu event to bubble up from the img target to the document object.
(2) Setting event.returnValue to false can be done in place of the return false; operation (there's no need for both statements to be there) for non-Mozilla browsers. Leaving Firefox/Camino users out in the cold would not be cool, so we should keep the return false; statement and lose the returnValue assignment.

The accompanying norightclick( ) function was written for Netscape 4.x and IE 4.x; interestingly, it targets both the middle button and the right button for a three-button mouse. After going through a window.Event gate, Netscape 4.x checks the e.which value and then returns false if the value is either 2 or 3. For its part, IE 4.x tests if event.button is 2 or 3 - these values should be 1 or 2, respectively - and then runs through the same set of statements that makes up the nocontextmenu( ) function body.

Leaving aside the issue of what a middle-click might do on your computer (on my computer, a middle-click launches the Dashboard application by default), there is no point in holding onto the norightclick( ) function as no one should be using those browsers without oncontextmenu support. Indeed, we should be able to reduce the second script to a single line of code:

document.oncontextmenu = function ( ) { return false; }

Mozilla notes that the Events DOM's Event interface has a preventDefault( ) method that can also be pressed into service in this regard:

document.oncontextmenu = function (e) { e.preventDefault( ); }

Alternatively, we can equip each up.html img element with an oncontextmenu="return false;" attribute - see the first Example on the aforelinked Microsoft oncontextmenu page.

<img id="fish0" width="75" height="50" src="mfish1.gif" alt="fish" oncontextmenu="return false;">

Try it out on the image below - nothing should happen when you right-click it.


Relatedly, giving the body element an onmousedown="return false;" attribute will (for newer browsers, at least) throw up a roadblock preventing the user from mousically selecting text on a Web page. Try to select the text in the sentence below:

The quick brown fox jumps over the lazy dog.

Regarding the right-click-disabling scripts, Lissa concedes:
[These scripts are] not foolproof. If someone really wants something from your page they can find ways around it, but at least it's a warning to people who want to take your graphics.
All a user has to do is turn off the browser's JavaScript engine via the Preferences pane and - *poof* - there goes the script. (In my case, I didn't even do that - I just went to the up.html/image URL locations and then downloaded the files via the File menu's Save command.)

We have one last falling snow script to cover: the How do I make snow fall on my Web site? subsection of Section 1 of the JavaScript subsector offers a "cross-browser snowflake script" that we'll take on in the next post.

Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)