I have one asp.net application, in which i have to disable or make it as read only to the Paste option from the context menu. But i searched in internet. I didn't get one exact method. Please help me for resolve this issue. Thanks in advance
The short answer is that you can't do this.
The user's browser is their own, and as such they have the sovereign power to interact with your page however they want. You can catch right-click events to prevent the menu from coming up; you can catch keypress events to stop Ctrl-V (and Shift-Insert, which is often forgotten) from being registered. However, you can't remove the Edit -> Paste menu option, which works within the browser and subverts Javascript altogether.
Not to mention that the user could just disable Javascript temporarily, paste into the field, then reenable Javascript if they wanted.
Even if you're happy with the limitations, you cannot modify the actual context menu, only prevent the right click from registering at all.
I suppose isn't possible to disable a single item on context menu, so I think you should try to disable the whole context menu, e.g.
$(document).bind("contextmenu", function(e) {
e.preventDefault();
});
∎ Another way of solving this pesky problem,
using JavaScript's Object-Oriented characteristics
<div class="ro-editable">
<span.....</...
<pre....</...
</div>
<script>
function make_editable_readonly(element){
element.backup_innerHTML = element.innerHTML; /* backup before editable. */
element.contenteditable = "true"; /* editable. CTRL+A is usable (FUN!) */
element.onautocomplete /* what in the world could change the content? actually lot!.. */
= element.onchange
= element.oncontextmenu
= element.oncopy
= element.oncuechange
= element.oncut
= element.ondrag
= element.ondragend
= element.ondrop
= element.onemptied
= element.onkeyup
= element.onmouseup
= element.onpaste
= element.onreset = function restore(){
if (element.innerHTML !== element.backup_innerHTML)
element.innerHTML = element.backup_innerHTML;
};
}
make_editable_readonly(
document.querySelector('div.ro-editable')
);
</script>
∎ Easy! Right? (and with no 💩y key-event "filtering" ☺):
∎ And here is a JSFiddle to play⚽ with
∎ taken from iCompile - ContentEditable And "ReadOnly"? YES! ☕
Related
I got a warning by my ad system provider about click fraud. No further info, all they are recommending is "hide the ads for users who click on ads too quickly'". I wrote a piece of JS script that hides all DIVs with ads for N seconds (using cookie) when clicked on, but this solution does not work as the "inner" content (with ads) is generated by an JS script that calls and renders the content from external server (as you would expect from an ad system). So, when one takes the cross-domain security into account it is kinda Catch 22. How can I detect a click inside a DIV (locally defined) of which content is rendered by an external JS and in iframe?
Example:
<div class="ad-class"> <!-- locally defined div -->
<div id="my-id"> </div> <!-- identifies my ad in the provider's system -->
<script>
var foo = blah // declares the ad dimensions and stuff
// and renders the contextual ad in #my-id DIV
</script>
</div>
Were it all local, solution would be easy as the internal div would inherit the parent class ("ad-class"). In case of cross-domain, this is not valid. Any tips, dudes?
You cannot detect click events in cross-domain iframe.
That put, you might have one bad option:
One of the nearest things you can do is detect that the focus moved from your window to the iframe:
window.focus(); //force focus on the currenct window;
window.addEventListener('blur', function(e){
if(document.activeElement == document.querySelector('iframe'))
{
alert('Focus Left Current Window and Moved to Iframe / Possible click!');
}
});
http://jsfiddle.net/wk1yv6q3/
However it's not reliable, loose focus does not mean a click, it could be user moving across the website using TAB.
Another problem is that, you only detect the first time focus is moved to the iframe, you do not know what user does in there, he can click a million times and you will never know.
Luizgrs inspired me this solution :
var clickIframe = window.setInterval(checkFocus, 100);
var i = 0;
function checkFocus() {
if(document.activeElement == document.getElementById("ifr")) {
console.log("clicked "+(i++));
window.focus();
}
}
<!DOCTYPE html>
<h2>Onclick event on iframe</h2>
<iframe src="https://www.brokenbrowser.com/" id="ifr"></iframe>
The function detect if the iframe has the focus, if yes, the user clicked into the iframe. We then give back the focus to our main windows, which allow us to find if the user click another time.
This trick has been usefull to me for a POC on a 2 step iframe click-jacking. Getting to know when the user clicked for the first time on the iframe allowed me to reorganize my different layers to keep the illusion perfect.
The approach #Luizgrs pointed out is very accurate, however I managed to indeed detect the click event using a variation of the method:
var iframeMouseOver = false;
$("YOUR_CONTAINER_ID")
.off("mouseover.iframe").on("mouseover.iframe", function() {
iframeMouseOver = true;
})
.off("mouseout.iframe").on("mouseout.iframe", function() {
iframeMouseOver = false;
});
$(window).off("blur.iframe").on("blur.iframe", function() {
if(iframeMouseOver){
$j("#os_top").click();
}
});
The above code works like a charm on desktop if you want to add mobile support you just need to use touch events touchstartand touchendevents to simulate the mouseover on mobile.
Source
Well, a while ago I found this plugin for WordPress. Obviously it does what I need -- just wondering how this guy made it to work, it does count clicks on Adsense iframe. I must have a closer look though I am not a PHP programmer. I program mainly in Python and need some solution of this kind for Django. If anyone can read the code easily, I would appreciate any help.
The plugin is searching first for any iframe wrapped by a previous specified class name.
The iframe id´s will be collected in a array and for everyone of these id´s an mouseover event will be created which fires the script which hides the class 'cfmonitor'. As a result the iframe containing ad is not visible anymore.
// IFRAME ACTION
function iframeAction () {
jq.each(jq.cfmonitor.iframes, function(index,element) {
frameID = jq(element).attr('id') || false;
if (frameID) initiateIframe(frameID);
//alert (frameID);
});
}
// INIT IFRAME
function initiateIframe(elementID) {
var element = document.getElementById(elementID);
// MOUSE IN && OUT
if (element) {
element.onmouseover = processMouseOver;
element.onmouseout = processMouseOut;
//console.log("mouse on out");
}
// CLICKS
if (typeof window.attachEvent !== 'undefined') {
top.attachEvent('onblur', processIFrameClick);
}
else if (typeof window.addEventListener !== 'undefined') {
top.addEventListener('blur', processIFrameClick, false);
}
}
// IFRAME CLICKS
function processIFrameClick() {
// ADD A CLICK
if(isOverIFrame) {
//addClick();
// Some logic here to hide the class 'cfmonitor'
//console.log("Go");
top.focus();
}
}
Check this it might help. You can not detect the click event when its cross browser.
window.focus();
window.addEventListener('blur', function(e){
if(document.activeElement == document.getElementById('Your iframe id'))
{
console.log('iframe click!');
}
});
I'm making an extension for Chrome to be used on Youtube. The extension adds an overlay on top of the video with a text input. However, typing into the extension triggers Youtube's various keystroke listeners (e.g. space -> pause). event.stopPropagation() does nothing, neither does return false at the end of the Angular event callback.
My current (successfully prototyped but not yet implemented) solution is to wrap the input in an iframe, which will pass messages back to the parent window:
iframe.contentWindow.document.querySelector("#wrapped-input").addEventListener("input", function(){
result.innerHTML = this.value;
});
I feel that this solution is a bit of a hack, and I'm hoping to find something more elegant. As an aside, I am using AngularJS for the app, so if there are any Angular-specific workarounds, I'd love to know those too. Thoughts?
EDIT
Current solution:
<iframe id="wrapper-frame"></iframe>
...
link: {
var input = '<input id="inner-input" />';
var wrap = $window.document.querySelector('#wrapper-iframe').contentWindow.document;
$scope.commentInput = wrap.querySelector('#inner-input');
wrap.open();
wrap.write(input);
wrap.close();
$scope.commentInput.addEventListener('input', function(){
var val = this.value;
$scope.$applyAsync(function(){
$scope.inputContent = val;
});
});
}
It works, but still -- iframe. Bleh, hack. I will leave the question open in case if someone has a better idea.
I'm building a game as a webapp for the iPad. It incorporates a shake action to trigger an event for one of the screens, but, since it also has a information collection form, sometimes that shake action triggers the annoying "Shake to Undo" dialog. The form input the user has typed in don't even exist in the DOM anymore when the user reaches the shake action, so in my mind the Undo function shouldn't be triggered, but unfortunately it is. There is no way this can be wrapped in a native wrapper (PhoneGap or other), so I was wondering if anyone knows if it's at all possible to disable this functionality for a specific web page/app, through CSS or JavaScript?
Thanks.
For PhoneGap I just inserted this line:
[UIApplication sharedApplication].applicationSupportsShakeToEdit = NO;
in the webViewDidFinishLoad class and it worked wonders for me.
Just go to the MainViewController.m and change webViewDidFinishLoad to look like this:
- (void)webViewDidFinishLoad:(UIWebView*)theWebView
{
// Black base color for background matches the native apps
theWebView.backgroundColor = [UIColor blackColor];
[UIApplication sharedApplication].applicationSupportsShakeToEdit = NO;
return [super webViewDidFinishLoad:theWebView];
}
This blog describes a very simple shake detection using the DeviceMotionEvent listener:
http://www.jeffreyharrell.com/blog/2010/11/creating-a-shake-event-in-mobile-safari/
Try the following code to disable to undo event happening:
window.addEventListener('devicemotion', function (e) {
// This is where you put your code for dealing with the shake event here
// Stop the default behavior from triggering the undo dialog (hopefully)
e.preventDefault();
});
There is one other thing I can think of which would be to turn the text input into a readonly item after you are done with it. Presumably, a read only input field cannot make use of the undo function, though I haven't tested it. It's odd that the feature fires even after the input is no longer part of the DOM.
I'm not sure if preventing a shake action can be done through the -webkit- properties in CSS. Here is a list of webkit specific CSS properties (which may not contain 100% of the properties accessible).
http://qooxdoo.org/documentation/general/webkit_css_styles
I recently ran into this issue while developing a game where a user pairs devices using WebSockets. Unfortunately none of the solutions mentioned above work.
In short, the game involved a user subscribing to a channel via a form on their phone. Once subscribed they would shake the device and a scenario would play out on their desktop. The problem was that any time someone shook an iOS device the "undo typing" alert would pop up.
Here are the only two solutions that I've found for this issue.
Prevent your input from ever losing focus. This will require you to prevent form submission if the input is part of a form. You must also listen for "touchstart" instead of "click" on any anchors and prevent the touchstart event from propagating. This will prevent that anchor from gaining focus and your input from losing focus. This approach has some disadvantages for sure.
Add a "keydown" event handler to the window and prevent the event from propagating. This prevents any values from getting inserted into the input on iOS devices. I also had to create an object that mapped the keycodes to the proper character. This is the route I ended going because all I needed in my input was a 6 character code so I only needed numbers. If you need more than just numbers this may be a pain in the ass. On key down, snag that character via the keycode and set the value of the input. This tricks iOS into thinking that no value was ever inserted into the input via the keyboard so there is nothing for it to undo.
Keep in mind preventing the keydown event from propagating does not prevent input on the stock android browser, so it will just function normally. But that is OK since this is not an android issue. You can prevent duplicate values from getting inserted by listening for the input event on the input itself and removing the keydown listener if this event is received.
var codes = {
48: 0,
49: 1,
50: 2,
51: 3,
52: 4,
53: 5,
54: 6,
55: 7,
56: 8,
57: 9
},
myInput = document.getElementById("myInput");
var keydownHelper = function (e) {
e.preventDefault();
myInput.removeEventListener("input", inputHelper);
var val = myInput.value;
// Delete
if (e.keyCode === 8 && val.length) {
myInput.value = val.slice(0, val.length - 1);
return;
}
// If not a number, do nada
if (typeof codes[e.keyCode] === "undefined") { return; }
val += codes[e.keyCode];
myInput.value = val;
};
var inputHelper = function (e) {
e.preventDefault();
window.removeEventListener("keydown", keydownHelper);
};
myInput.addEventListener("input", inputHelper);
window.addEventListener("keydown", keydownHelper);
Objective-C
Just add the line of code inside "- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions"
[application setApplicationSupportsShakeToEdit:NO];
Swift 2.x
Add single line of code in appDelegate.swift didFinishLaunchingWithOptions method
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
application.applicationSupportsShakeToEdit = false
return true
}
Swift 3.x
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
application.applicationSupportsShakeToEdit = false
return true
}
Perhaps try event.preventDefault(); in your DeviceMotionEvent listener ?
Looking around Stack Overflow, I can see other people have had success disabling default "events" using CSS (oddly).
Prevent default Press but not default Drag in iOS MobileSafari?
See: How to stop the UITextField from responding to the shake gesture?
For phonegap, set this property within the webViewFinishLoad method in AppDelegate.m
First solution
The easiest way is to use this plugin:
https://github.com/nleclerc/cordova-plugin-ios-disableshaketoedit
Second solution
If you don't want to use the above plugin then you should do it manually by opening the MainViewController.m and change webViewDidFinishLoad to look like this:
- (void)webViewDidFinishLoad:(UIWebView*)theWebView
{
// Black base color for background matches the native apps
theWebView.backgroundColor = [UIColor blackColor];
[UIApplication sharedApplication].applicationSupportsShakeToEdit = NO;
return [super webViewDidFinishLoad:theWebView];
}
Third solution
it's another solution i designed to disable "Shake To Undo" which works on text inputs. note that users are not allowed to insert emojis.
<body>
<textarea cols="40" rows="8" name="textarea" id="textarea"></textarea>
<script>
textArea = document.getElementById("textarea");
textArea.onkeypress = function(event){
event.preventDefault();
var nationUnicode=event.which;
var utf8=encodeURIComponent(String.fromCharCode(parseInt(nationUnicode, 10)));
if (utf8.search("%EF") != 0) //value is not an Emoji
textArea.value= textArea.value + String.fromCharCode(nationUnicode);
}
textArea.onkeydown = function (event){
if (event.keyCode == 8){
event.preventDefault();
var txtval = textArea.value;
textArea.value = txtval.slice(0, - 1);
}
}
</script>
</body>
I found a workaround that works consistently: you can host the text input in a frame. When you're done with the input, remove the frame from the page. This seems to do the trick.
function resetIframe() {
// Remove the old frame
document.body.removeChild(frame);
// Create a new frame that has an input internally
frame = document.createElement('iframe');
frame.src = '/html-with-input.html';
frame.style = 'border: 0; height: 30px; width: 200px;'
document.body.appendChild(frame);
// When the frame is ready, grab a reference to the input
frame.addEventListener('load', () => {
const input = frame.contentDocument.body.querySelector('input');
console.log(frame, frame.contentDocument.body)
// When the input changes, grab the value
input.addEventListener('input', e => {
document.getElementById('output').innerText = e.target.value;
});
});
}
Here's a proof of concept: https://codepen.io/joshduck/full/RJMYRd/
Put the input into an iframe, reload the iframe when you don't need the input.
I am trying to do a little pacman game to train my JavaScript skills. To move pacman around, I use the onkeyup event function associated with a move function.
Still I am having a problem. Every time pacman dies (or game ends) I always use an alert box to alert the user of what happened. Still, after I press the OK button to make pacman move again I must click on the browser window to make it responsive to keyboard events.
Somehow I believe this is a windows focus problem, still, tried to use some focus around (after the alert box mainly) and doesn't seem to do the trick.
Can someone give me general pointers of what could be the solution for this?
PS: In the game construction I am using images created on the fly, having only 2 text tags on the page with id's.
EDIT: code associated in the onkeyup:
function muda_sentido(event)
{
//baixo
if(event.keyCode == 40)
{
pacman_status = status[2];
imagem_pacman.src = "Imagens/pacmanb.gif";
imagens[pacman_pos[0]][pacman_pos[1]].src = "Imagens/pacmanb.gif";
}
//direita
else if(event.keyCode == 39)
{
pacman_status = status[0];
imagem_pacman.src = "Imagens/pacmand.gif";
imagens[pacman_pos[0]][pacman_pos[1]].src = "Imagens/pacmand.gif";
}
//cima
else if(event.keyCode == 38)
{
pacman_status = status[3];
imagem_pacman.src = "Imagens/pacmanc.gif";
imagens[pacman_pos[0]][pacman_pos[1]].src = "Imagens/pacmanc.gif";
}
//esquerda
else if(event.keyCode == 37)
{
pacman_status = status[1];
imagem_pacman.src="Imagens/pacmane.gif"
imagens[pacman_pos[0]][pacman_pos[1]].src = "Imagens/pacmane.gif";
}
}
html body contents is a double h2 tag (cannot add it to code format cause it appears messed up on the previewer) with an ID each.
And around the program I have something like:
alert("Pacman died!")
And the problem is after this.
2 EDIT: Managed to grab the piece of code that lies the alert box (just changed it now to look for it in only one place):
function pacman_morreu()
{
alert("O pacman morreu!");
if(pacman_vidas==0)
{
alert("Game Over!");
reinicia_tabuleiro();
}
else
{
pacman_vidas--;
vidas.innerHTML = "Número de vidas: "+ pacman_vidas;
}
pintaEcra();
}
The functions listed inside the code will only do matrix manipulation operations (nothing special really).
EDIT 3: As requested, here goes:
function reinicia_tabuleiro()
{
pacman_vidas = 3;
vidas.innerHTML = "Número de vidas: 3";
pontuacao.innerHTML = "Pontuação: 0";
pontos = 0;
for(i=1;i<24;i++)
{
for(j=1;j<24;j++)
{
if(tabuleiro[i][j] == 0)
tabuleiro[i][j] = 2;
}
}
}
Sorry dude, I don't see anything that would be causing this. What browser are you using? I'm doing similar tests on IE and FF and am getting window focus after clicking 'Ok' in the alert box. Have you tried using Firebug? It is a great program for debugging javascript. I would highly recommend it for this pacman project you are doing. You might have an error somewhere in your code that is causing this that isn't very apparent in the code shown above.
Well right now, I don't have solution to this problem but I have a workaround.
Dont use alertbox, use lightbox(div with higher z-index value) and make the div show and hide based on condition in javascript.
I hope this will help.
I just went through a similar problem with keydown and Firefox 5.0. The window focuses when the page loads and all my $(window).keydown(...) events worked fine.
Then after I show an alert, none of the events fire. It ends up that the window does not focus itself after I dismiss the alert. I was able to solve it by forcing the window to refocus when it blurs. I'm using jQuery so here's what it looks like for me:
$(window).blur(function(){
setTimeout(function(){
$(window).focus();
}, 0);
});
The timeout is necessary since Firefox (& maybe other browsers) won't let you immediately focus during a blur event.
This may have unintended consequences since you're basically never letting the window blur. For example, clicking on the location bar won't even work because the window pulls focus back immediately. To dig a deeper hole, you might set a "refocus" flag for your callback so it knows whether to give up focus or not. Here's the basic idea:
var doRefocusWindow = false;
$(window).blur(function(){
if(!doRefocusWindow) return;
doRefocusWindow = false;
setTimeout(function(){
$(window).focus();
}, 0);
});
...
doRefocusWindow = true;
alert("Game Over");
I have a weird problem.
I try to write a GreaseMonkey script to be run in Firefox and Google Chrome.
With Chrome I tried 2 extensions : "TamperMonkey" and "Blank Canvas Script Handler", mainly because my script check regulary for a new version on an external site and this is considered as cross site scripting and not authorized in Chrome.
To show you my problem, I write a simple test case :
// ==UserScript==
// #name test
// #namespace http://fgs.ericc-dream.fr.nf
// #description test gm script
// #include http://gaia.fallengalaxy.eu/
// #author ericc
// #version 0.0.1
// ==/UserScript==
/* We attach an event listener to the body tag and trigger the function
* 'message' each time that an element is inserted in the page */
var el = document.body;
el.addEventListener('DOMNodeInserted', message, false);
var extraFlag = false;
function message(event) {
/* first we capture the id of the new inserted element
* (the one who created the event) */
var objId = event.target.id;
/* add an event listener on the map container */
if (objId == "extra") {
el = document.getElementById('extra');
el.addEventListener('DOMSubtreeModified',readTest,false);
GM_log(el.style.display);
}
}
function readTest() {
el = document.getElementById('extra');
GM_log(extraFlag);
GM_log(el.style.display);
if ((el.style.display != 'none') && (!extraFlag)) {
alert('extra');
extraFlag = true;
} else if ((el.style.display == 'none')) {
extraFlag = false;
}
}
the div element 'extra' is modified by the page. The problem is that Chrome is unable to read the value of el.style.display and thus extraFlag never become 'false' again.
I use this flag to avoid to run the code several time, the site is heavily JavaScript driven
This code work nicely in Firefox !
I tried to search with Google but can't find a correct answers. Seems easy to change the value of display, but it seems that I'm the only one who try to read it !!!
I write this code because "DOMAttrModified" isn't supported in Chrome :-(
Thanks in advance for your help
ericc
I'm having a hard time understanding exactly what your question is, but it looks like Chrome can read .style.display properties just fine. I just threw the following code into an HTML template and loaded it in Chrome 10:
<div id="div1">
</div>
<div id="div2" style="display: block;">
</div>
<div id="div3" style="display: inline;">
</div>
<div id="div4" style="display: none;">
</div>
<script type="text/javascript">
alert(document.getElementById("div1").style.display);
alert(document.getElementById("div2").style.display);
alert(document.getElementById("div3").style.display);
alert(document.getElementById("div4").style.display);
document.getElementById("div1").style.display = "none";
alert(document.getElementById("div1").style.display);
</script>
The code produced 5 'alert' boxes with the following output:
blockinlinenonenone
So it seems Chome reads this property just fine.
Maybe the issue is that the webpage on which you're running your greasemonkey script is behaving differently in Chrome than in Firefox? Could it be that the ID of the element is different, or the element is being removed from the DOM instead of just being hidden? What would happen if you modified your function with some more checks, kinda like this?
function readTest() {
el = document.getElementById('extra');
if(el)
{
GM_log(extraFlag);
GM_log(el.style.display);
if (el.style.display && (el.style.display != 'none') && (!extraFlag)) {
alert('extra');
extraFlag = true;
} else if ((el.style.display == 'none') || !el.style.display) {
extraFlag = false;
}
}
else
{
GM_log(extraFlag);
GM_log("element not present");
extraFlag = false;
}
}
Does that help? If not, is there any other reason you could think of why el.style.display wouldn't evaluate properly in Chrome?
It might help if we knew more about what you're trying to do with your script, and possibly what web page or code you're trying to run this on.
After several hours and a ton of test case, I finally find an acceptable explanation (but not yet a solution !)
Let's explain the scenario :
1°) the user click on an icon on the screen
2°) the div#extra, which is already present in the page, is made visible by removing its display property (.style.display="")
3°) the div#extra is filed by an AJAX function with some elements depending on which icon was clicked by the user (more than 200 elements in certain case)
4°) the user click on an other icon to close the div
5°) all elements from the div#extra are removed
6°) the div#extra is hidden by putting is display property to 'none' (.style.display="none")
At first, on Firefox, I used "DOMAttrModified" event on the div#extra to check when the display property was modified and react accordingly.
Problem, this event is not supported on Chrome !!
So I replace it by "DOMSubtreeModified" (attached to div#extra) which is supported by both browser .... but not exactly in the same way :-(
On Firefox, an event is fired for every modification in the subtree but also when the element itself is modified.
On Chrome, they are a little bit more strict and fired event only for modification in the subtree .... and this is my issue !
In Firefox,first event is fired at point 2 (in the scenario) and last at point 6 allowing my function to read when the div#extra is made hidden
In Chrome, first event is fired at point 3 and last at point 5 ... so when the the div#extra is hidden my function is not called and I can't modify the flag !!!! CQFD
Now, or I will add an event listener to the body of the page to intercept when the display property is modified, but it will generate a lot of call to my function, or the developer of TamperMonkey said yesterday that his extension now support "DOMAttrModified" (on Chrome) ....
Thanks anyway to take the time to understand my question and your proposed solution
ericc