Disabling the Browser Context Menu

You can disable the browser context menu for an element in your DOM with the following JavaScript recipe:

function disableContextMenu(element) {
    element.oncontextmenu = function() {
        return false;
    }
}

For example, to disable the context menu over a photo on your page, you could use:

disableContextMenu(document.getElementById("photo"));

Browsers like Firefox do not always allow web pages to disable the context menu (this option is a setting in Firefox), so this recipe will not work 100% of the time in all browsers.

See the example

Comments

Not reliable at all you mean. This stuff is going to work flawlessly ONLY with IE6, dont need to bother trying with any other browser, you will always have a new issue. Dont touch the context menu, let people use the context menu if the want to. Worst, even if i was allowing scripts to cancel contextMenu, this is not preventing the special key i have on my keyboard to call this famous contextual menu, and this "code" is not preventing me to call it.

So nope, dont do it, ever.
I've used this code on a recent project where I needed to replace the context menu with my own options. Very effective, however. It was on an IE based Intranet.
I completely agree with Richard.
Truly, it is annoying when someone "disables" your context menu so that you don't steal their content (yeah, right), but when building an AJAX web application, it really comes in handy - a requirement, if you want to acheive the complete look-and-feel of a standard non-web application.
I have tried it on a Mozilla FireFox and it functioned as implemented.
Asghar: it will only work in a subset of Firefox browsers. It is a security preference in Firefox 1.5+ -- check out the link I included in my post above for more information.
seems to work a lot better than some other scripts I've seen. In many scripts you can circumvent the functionality thus:

Press+Hold LeftButton
Press RightButton
Release LeftButton
Release RightButton

I don't think disabling the context menu is a great idea. There are situations where you want to replace the context menu with one you have made yourself, but you should at least allow the original context menu through some other combination, say ctrl-RightClick.

This was one of the first options I ticked when I started using firefox.
As you said by yourself this doesn´t work 100%. In fact there is
a) no way to prevent "theft" of images
b) no way to effectively prevent context menus due to different browsers, javascript options, userscripts, script blockers etc etc...

So please don´t even try to disable context menus. If you don´t want your content to be copied, then the only way is to not publish it at all.
You can keep most people from stealing your images by placing them as the background image file of a table, then place a transparent gif in the table over the background image. When a user right clicks and saves they are saving the transparent gif. Of course advanced users can print screen and paste the actual image, or if they are crafty enough view your source and link directly to the image. One way around this would be to store the image binary file in a database.

Kinda like the old saying you can fool some of the people some of the time but you can never fool all the people all the time.
WbDev4allvin: you must have bunch of experience. How could you otherwise say such a nonsense as having image in DB.

And how would you link the image in the DB? just from the clean air, or putting base64encoded mime string into the src attribute? You are not able to that and you don't have a clue what you are talking about, so don't comment in future on topic you don't understand.

The only way is to check the referer in the image script linked and if no referer is passed, stop the execution or display default place holder image. This still however won't be 100% defense against stealing of images, as anyone can even save image generated by script etc.

The main purpose of this debate is not to block user from saving the image, but to develop application that handles the right click in the way user is accustomed to.
Dusoft, the technique that wbDev4alivin mentions IS possible, and has been done before. I can't name any offhand, but I recall reading about a few pieces of free message board software that would do this to store file uploads, instead of actually storing them in a folder.
doh!
Ofcourse it's possible to upload images or any other binary data to ur database (i've done it on oracle and db2, haven't tried it on mysql yet), it all comes down to dbms. Oracle and it's plSQL (and oracle web agent) make it possible to retrieve the binary data (blob) and use it as a src within your html elements. Oracle and IBM both have predefined routines and rewrite rules that help you link to them. No need to reinvent hot water.
"so don't comment in future on topic you don't understand."

Ah ha ha ha!! Take your own advice buddy! Storing images in a database is easy.

One method is how Ap4rTheAd mentioned.

Another method is to create a php script that will retrive the image data, and output it on a page with the proper image headers.


Know it all douchebags like that give me a good chuckle from time to time. :)
Google online apps (like spreadsheet) disable context menu and enable their own EVEN if in mozilla the settings DONT allow to do it. Well.. actually... i'm shocked and trying to understand how the hell they did it.
@TheDoc - yes they do. So does MSN maps: http://maps.live.com/

Anyone know how they do it?

~d
@TheDoc and @delvinj:

The Prototype.js framework (http://en.wikipedia.org/wiki/Prototype_Javascript_Framework) will successfully suppress the context menu. Just include the prototype.js script, and add something like this onload:

Event.observe(document,'contextmenu',disableContextMenu,false);

function disableContextMenu(evt) {
alert("I won't allow the context menu!");
Event.stop(evt);
}
ertyertye
@phrygius
This does not work in every browser. EG in Konqueror it doesn't. But what does Google do to get this effect?
Google also stopped tha Drag&Drop Effect...
Click,

It seems that certain versions of Konqueror/Safari do not work with Prototype's Event.stop() method. Here is a short article describing the problem: http://particletree.com/notebook/eventstop/

Solution 3 apparently works for this guy, but I have no way of testing it out at the moment.
function hide(){ if(event.button==2){ return(false);} }
document.onmousedown = hide;
document.oncontextmenu = new Function("return false");


put this in your javascript file. it will block the context menu for IE. for firefox just use this CSS for your

body, html{
-moz-user-focus: ignore;
-moz-user-select: none;
}

the aim i think is not to stop people from getting yo code but to make the web application better simulate a real win32 one. lol
function hide(){ if(event.button==2){ return(false);} }
document.onmousedown = hide;
document.oncontextmenu = new Function("return false");


put this in your javascript file. it will block the context menu for IE. for firefox just use this CSS for your

body, html{
-moz-user-focus: ignore;
-moz-user-select: none;
}

the aim i think is not to stop people from getting yo code but to make the web application better simulate a real win32 one. lol
hoe to disable print option in an web browser and also save as option using java scripts
You've all missed dusoft's point. Yes, you can store an image in a database, or an encrypted filesystem on a USB stick, or place it on a wooden table with a digital camera rigged up to take a photo of it on every HTTP request. But it makes absolutely no difference to how easy or hard it is to steal - if it has a URL (and by definition, an image on the internet does have a URL) then a user can save it just the same.

But none of this is anything to do with disabling menus in Javascript, anyway - there are still other legitimate reasons for doing that.
This post was very entertaining, i dig the heat :)
@laurent...a very good reason you would want to control the context menu is if you are creating a javascript component that you would like to have it's own context menu.

Although this might not work in all browsers, it is a very important point, and something all good developers should be aware of.
The Yahoo UI handles this issue quite well:

YAHOO.util.Event.addListener(document.getElementById("myElement"), "contextmenu", doSomething);

function doSomething(event)
{
//insert your own context menu script here

YAHOO.util.Event.stopEvent(event);
}
true,the image data still has a url, and it can still be linked to over the net, but you can have conditions in your cgi to NOT allow requests without a matched sessionid and password, with such a script you could also check to see where the image is being linked from and require a password to be sent along with the request, if the password does not match the db with the with the check against the current sessionid, then it's likely that it's being hotlinked by someone without permission. this makes dusoft's point, and yours, moot.
I have to do the same work, hiding context menu. I fall upon a great deal when dealing with mozilla with successful code in IE.
For Firefox browsers (version 2.0 anyway) you can disable the context menu on the 'document' object with a return value of 'false';

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

I'll let you implement that how you will for your web 2.0 application projects...such as detecting what element you are over, stopping propagation, selecting the appropriate return value 'true|false'...

:-)
Here's a little more code to show this in context...

<html>
<head>
<script type="text/javascript">
window.onload = context_menu;

function context_menu () {
document.oncontextmenu = function ( event ) {
if ( typeof event == 'undefined' ) {
event = window.event;
}
if ( typeof event.target == 'undefined' ) {
event.target = event.srcElement;
}
var node = event.target;
do {
if ( typeof eval( node.getAttribute('rel') ) == 'function' ) {
eval( node.getAttribute('rel') )( node );
return false;
}
} while ( node = node.parentNode );
return true;
}
}

function menu1 ( node ) {
// do your custom menu 1 here //
alert( 'context menu one: ' + node.id );
}

function menu2 () {
// do your custom menu 2 here //
alert( 'context menu two' );
}
</script>
</head>
<body>
<div>
<ul>
<li rel="menu1" id="one"><a href="#">Some Nav One</a></li>
<li rel="menu1" id="two"><a href="#">Some Nav Two</a></li>
<li rel="menu1" id="three"><a href="#">Some Nav Three</a></li>
<li rel="menu1" id="four"><a href="#">Some Nav Four</a></li>
</ul>
</div>
<img rel="menu2" src="http://technology.beloblog.com/archives/Wootlogo.gif" />
</body>
</html>
A much simpler solution to this entire problem is to use a different method altogether. Macintosh users are familiar with the Ctrl+click, so why not use that? Instead of trying to override the default browser functionality, it is better practice to ADD to that functionality. When a user presses a key, append that key to an array. When the user releases a key, remove that key from the array of "down" keys. When the user clicks, check whether the Ctrl key is contained in the "down" array (it's keyCode is 17), and if it's there, create a context menu.

On another note, it is indeed possible to completely eliminate "hotlinking" and the forced download of images using PHP. To eliminate hotlinking, all you have to do is check the referrer when you retrieve an image from the database (if it's not your site, just output a "no hotlinking" image, or text). To disable users "right clicking" or "viewing source" in order to download, simply make each image unique using some manipulation of the current unix timestamp. Give each user a sessionID, then create a database that logs the time at which each and every page was loaded for each sessionID. If the user tries to access an image by entering it's url, it would be seen that the sessionID's last page load was NOT within the same ~10 seconds that the image was loaded. Depending on the speed of your web server, you can choose to reduce the time to something smaller - thus making it impossible to download an image that you choose to "protect".

But, as someone mentioned above, that's a lot of work just to find out that someone else's "image downloader" hack might just be a little quicker than your server.
Just a few notes for "Did my homework":

- You need to learn XHTML. Google it, use it.

-you should make sure to reserve the "window.onload" event for other scripts, so you don't break any pages:

window.myOnLoadOld = window.onload?window.onload:function(){};
window.onload = function() {
window.context_menu();
window.myOnLoadOld();
};

-When you define a function with the syntax you have used ( var = function(){}; ) you need to add a semicolon after the terminating brace bracket. You can see what I mean above ^
Hi Jason,

My interest in the context menu is to expand navigation options on certain elements on a web application I'm building.

About image protection, I know of no reliable way to disable the browser caching the image on the local machine. I have also written simple browser 'robots' that can download images and ignore Pragma rules.

It is also easy enough for someone to navigate to a page, then disable javascript in the browser, then use the context menu to download the image off the page.

There is NO sure way that I know of to protect images...if they are worth that much then put a watermark on them.

Cheers
The following link will show you an example implementation of "Ctrl+click" that seemed to please users:

http://www.engjazzband.com/gallery/
Ah - very true, the image would be cached whether it was a background or not.

Well, I guess we'll just have to let Apple work out DRM for web images (haha).
Jason, on your latest post above...I do know XHTML and do use it...this is meant to be a very simple example to illustrate a concept--no more. I'm not trying to create a full blown tutorial here.

However, to own up to all the things I still don't know, why is the purpose of the closing semi-colon for anonymous functions? I've seen it but never run into any issues with using or not using it. I guess if you consider the function the value of the variable then it makes perfect sense in a 'strict' sense. So never mind, I get it--thanks for the feedback.

Cheers
I also wanted to inform the author that this script fails in ALL *NIX browsers, including Firefox on Linux and Safari on Mac OS X.

To increase browser compatibility, you need to do more than "return false":

function preventMe(e) {
if(!e) e=window.event;
if(e.returnValue)
e.returnValue = false;
if(e.preventDefault)
e.preventDefault();
return false;
};

document.oncontextmenu = preventMe;
window.oncontextmenu = preventMe;
document.onmousedown = preventMe;
window.onmousedown = preventMe;


---
That will make the script work as intended on *a few* more browsers. I still think disabling the context menu is a waste of energy though.


Another thought on image protection - the browser would "uncache" an image if it's content-expiry was set very very low, right?
One more note; I don't use window.onload in my actual scripts...I have a function I use that handles the onload event with 'window.addEventListener', 'document.addEventListener', and 'window.attachEvent' branching for various browsers...but again...I didn't post my snippet above as a full blown JS tute.
Ah, then I can appreciate the simplicity of HTML 4.01 in that case.

The purpose of the semicolon after declaring an anonymous function is because it is actually a standard JavaScript variable. The "function" keyword does not define a variable in the traditional sense, thus no semicolon is required.

Only a few JavaScript engines will throw an exception if you don't include the semicolon, and they are all outdated (I believe old Netscape does this).

If you are interested in learning more about this kind of stuff, check out this forum:

http://www.jasonmillerdesign.com/forum/

Look at the Cellnotes.ca API.
Did my homework >

good, I was never one for the window.addEventListener route, it reminds me too much of Visual Basic.
As one person mentioned above, without using any mouse buttons you can always take a screen shot of the image directly on the html page.

Once the image is loaded by the browser it can no longer be protected.

If you want to protect an image you are trying to sell, then load a low-res thumbnail or a version with a watermark. Then people who pay to get the good one can have a download key sent to them or loaded on the page, and you can deliver the high-res image out of a database--or something on those lines.

I am in the process of creating a photo-sharing site that allows users to edit their images in realtime. The watermark approach will be just what I needed. All this "disabling" talk made me forget about that, heck I have a PHP script for that already coded!
I believe ImageMaick will allow you to add a watermark to images on the fly.

I was in the works on building an image editor using JavaScript and PHP so a person could scale (resize-constrained), resize, crop, and compress (jpeg) an image .

I thought this would be useful for uploading images to a site database but be able to edit them on the page in a simple fashion.

I put that script on hold for a while, while I'm working on an app for a friend.

Let me know if you want anyone to brainstorm with for your image sharing app. Sometimes a different perspective can be useful.

Cheers,
Kevin (kdouglas AT satarah DOT com)
Typo: PHP's ImageMagick
I have never used ImageMagick, only the GD Graphics Library - I try to stick to only functions that come with a relatively "stock" install of PHP. Any speed differences between GD and ImageMagick?
The functionality I have planned would be:
-draw lines, boxes, circles, and pencil on photos
-save an edited photo to the database
-Add text to a photo (imgString, I believe)
-overlay images on an existing photo

It's going to be VERY AJAX intensive, but I think it might appeal to a lot of people.
I've got to run out for a while...maybe I was using GD too, come to think--it all gets jumbled in my brain.

My personal issue with drawing tools is that the lines are always jaggedy unless they allow for vector curves between two points. If you can find a way to soften the pencil lines or allow for other brush types (air brush) application then it sounds like a cool idea.
I'm sure you have an JavaScript Ajax object class that you are using, but if not let me know since I just finished one for this app I'm working on.
Sorry, lost track of myself...we shouldn't be discussing this on this thread.

Email me (above address) if you want to talk some more.
I think your email was withheld by this site's comment system. Drop me a line at:
admin [at] jasonmillerdesign [dot] com

or post a message on my forum, at:
www.jasonmillerdesign.com/forum

As for a JavaScript AJAX object, I would be interested in what yours looks like. I started working with AJAX before I was doing ObjectOriented JavaScript design, so my AJAX library is likely getting outdated.
sorry, I found the address - I will send you an email so we don't overload Bret's server.
btw with GIMP's screenshot function
i can steal any image from any webpage :)
Am I the only one here that would like to BAN Laurent from Internet ??? Shut up you negative, pessimistic, stick in the mud! Thanks for the effort Bret your site has enlightened me.
The following is a working example of disallowing context menu on the body but allowing in the other elements.

<html>
<head>
<title> New Document </title>
<script type="text/javascript">

function preventMe(e) {
if(!e) e=window.event;
if(e.returnValue)
e.returnValue = false;
if(e.preventDefault)
e.preventDefault();
return false;
};

function enableMe(e) {
if(!e) e=window.event;
if(e.returnValue)
e.returnValue = true;
if(e.preventDefault)
e.preventDefault();
return true;
};

function handleMouseDownEvents(e) {
if (!e) var e = window.event;

if (e.srcElement.id == 'bodyArea')
{
document.oncontextmenu = preventMe;
}
else
{
document.oncontextmenu = enableMe;
}

return;
}


document.onmousedown = handleMouseDownEvents;
</script>
</head>
<body id="bodyArea">
testing...... <input name="box1" type="text"> <input name="box2" type="text">
</body>
</html>
Uh, excuse me... I'd like to interject.

I found this page while looking for a way to guarantee that my context menu on my web browser on *MY* computer is not overridden by some obnoxious web developer. Some code has been by passing my "do not allow disabling or replacing of the context menu" setting. (My next step is to kill the interpreter all together.)

The number one reason I use Firefox is because there is nothing I find more annoying when visiting a web page than not being able to right-click and open-link-in-new-tab. I used get VERY angry when this happened and just avoid the offending website all together.

So let me ask you control freaks masquerading as web developers a question...

What gives you the right to dictate what menus are allowed to pop up on *MY* computer? I read above where it's to protect your 'content'. (images) Well, I have an idea for you then: Do not place materials you do not want others to consume on a device called a 'server'. Because what a server does by it's very nature is distribute information. Not to mention the fact that the servers you guys use are on a public network.

All messing with the context menu does is really miff people like me off. Even if you disabled every menu in the browser there is still a key combination that will get your pictures: <ALT> + <PRINT/SC>

So, just like movie and music companies, all your attempts at introducing 'rights management' to your content does is anger legitimate users. So, do the world a favor and don't impose your OCD on other people...

Chad
Hey chad, u genious of a consumer... have you thaught about the idea that you can get a customized context menu on *YOUR* computer, that gives you the possibility to get the content in a much more context-driven way?
And if you want to show a customized context menu you have to disable the default one.
I don't think that banning the context menu is always for preventing others to steal the images,source code or something else,as a matter of fact,it's really absurd,however I do think there are a lot of senario that you will find contextmenu is nessesary,like google map ect...


Write a Comment