Handling text selection event in Firefox extension (preventing user from selecting text) - javascript

I was wondering if in chrome code we have some better way to detect when the user selects/highlights something in the current page than listening for keyup/mouseup and checking window.getSelection(). Any ideas?
edit: Actually, what I'm trying to do is simply preventing the user from selecting any text at all in the contentDocument. Something that accomplishes this will be fine as well. (The idea behind getting the selection event was just to preventDefault() or otherwise getSelection().removeAllRanges())
edit2: Please note that I need not just to prevent the highlighting from showing up, but rather the selection from happening.
edit3: I don't need to prevent copying but rather selecting the elements.

If you put the following scipt in you body, selection will be disabled in Firefox:
<script type="text/javascript">
document.body.style.MozUserSelect = "none";
document.body.style.cursor = "default";
</script>
It does not only disable the highlight, it also disables the selection itself. If you try to select an area via mouse or by arrow-keys (clicking an position and navigating with arrow-keys while SHIFT is pressed) and and press STRG+C, nothing happens.
The only selection that works after that change is STRG+A (no selection visible, but STRG+A & STRG+C copys all). It might be possible to avoid that by keyboard-events.
Edit: I saw you comment with link to Mozilla Doc Center and while they write it controls only the appearance, all my tests in Firefox 3.6 show that it affects also the selection, not only the appearance. But it might be changed in future Releases...

In the absence of suitable events such as select and selectstart (which are indeed absent in Firefox, which has the select event but only applies it to form controls), all you can do is use mouse and keyboard events, as you suggested in the question. Preventing the default action of all mousedown events in the document is no good because it will prevent all interactive elements such as links and form elements from working. Instead, you could do something like the following that zaps a selection as it is made using the mouse and keyboard.
It won't prevent selection via "Select All" in the context and edit menus though, since there is no way of detecting those at all in Firefox. If you need to deal with this, polling the selection is your only hope.
function killSelection() {
window.getSelection().removeAllRanges();
}
document.addEventListener("mousedown", function(evt) {
document.addEventListener("mousemove", killSelection, false);
}, false);
document.addEventListener("mouseup", function(evt) {
document.removeEventListener("mousemove", killSelection, false);
}, false);
document.addEventListener("keydown", killSelection, false);
window.addEventListener("blur", function(evt) {
document.removeEventListener("mousemove", killSelection, false);
}, false);

You can use css
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;

You can use CSS to prevent the user selecting text. See my answer here: How to disable text selection highlighting using CSS?
To set this via JavaScript in Firefox, you can do the following:
document.body.style.MozUserSelect = "-moz-none";

The Copy command is enabled and disabled by an event. You can get notified of this event by creating a command updater.
<commandset commandupdater="true" events="select"
oncommandupdate="setTimeout(selectNone, 0);"/>

Add the following code to a css file, which is linked with a <link> tag in your popup html:
*,
*::before,
*::after {
user-select: inherit;
}
body {
user-select: none;
}

Related

Stop button losing focus when contextmenu event fires

I've got a react application that has a need for a piece of content to play when a button is held down and then stop when the button is released.
I've implemented this by creating a helper to handle detecting a longpress, when onMouseDown or onTouchStart is fired then it plays, when onMouseUp, onMouseLeave or onTouchEnd fires it stops. This all works perfectly on desktop. The issues comes when we take a look at mobile, mobile treats a long press as a right click in the desktop and tries to launch a contextmenu or highlight an element/piece of text, to deal with this I've added the following css:
touch-action: none;
user-select: none;
-webkit-user-select: none;
-webkit-touch-callout: none;
and the following Javascript:
window.oncontextmenu = function (event) {
event.preventDefault();
event.stopPropagation();
return false;
};
This works as expected in the sense that the contextmenu doesn't display, however the button that is being held does lose focus, meaning that the content continues to play and the onMouseUp, onMouseLeave or onTouchEnd events never fire unless you tap somewhere on the button or screen again, I've tried solutions like reapplying the focus to the button during the onContextMenu event however that doesn't work either.
Mobile user agents do not consider a long touch as a right click when the target element is a button (because there are no mobile compatible actions on a button, other than just click). I suggest you to verify that the button you're talking about is an actual button.
const button = document.querySelector('button');
button.addEventListener('mousedown', function() { this.classList.add('red') });
button.addEventListener('touchstart', function() { this.classList.add('red') });
button.addEventListener('mouseup', function() { this.classList.remove('red') });
button.addEventListener('mouseleave', function() { this.classList.remove('red') });
button.addEventListener('touchend', function() { this.classList.remove('red') });
.red {
background-color: red;
}
This link does trigger a context menu on a long touch <button>This button doesn’t</button>
If that does not answer your question, please add the actual HTML code.
When using this on desktop clicking my mouse would fire the mousedown event, which is expected, when using this on mobile it was firing two events at the same time, meaning when it would fire touchend it would also fire mouseleave or mouseup, i'm unsure why this was happening but to resolve my issue I just conditionally added the event listeners, so for mobile I now only add event listeners for touchstart, touchend and touchcancel.

contenteditable not working in safari but works in chrome

I'm having a strange issue...
This works in chrome as expected but in safari it only gets .. glowing but doesn't react on key input..
this is the method that fires the text edition:
var namebloc = $(event.currentTarget).find('.column_filename');
var oldvalue = namebloc.html();
namebloc.attr('contentEditable', true).focus();
document.execCommand('selectAll',false,null);
namebloc.blur(function()
{
$(this).attr('contentEditable', false).unbind( "keydown" ).unbind( "blur" );
var newvalue = $(this).html().replace('"','"').replace(/(<([^>]+)>)/ig,"");
console.log(newvalue);
});
namebloc.keydown(function(e)
{
if(e.keyCode==27){ $(this).html(oldvalue);}//escape
if(e.keyCode==13){ $(this).blur(); }//enter
});
This is a screenshot in chrome when fired this works as expected...
and this is the result in safari.. no reaction to keyboard or mouse selection:
Any idea why and how to solve this in safari?
this is the HTML before the method is called :
<span field="filename" class="column_filename" style="width:763px;">eiffel (2).JPG</span>
This is when it's called (at the same time as screenshots)
<span field="filename" class="column_filename" style="width:763px;" contenteditable="true">eiffel (2).JPG</span>
Safari has the user-select CSS setting as none by default.
You can use:
[contenteditable] {
-webkit-user-select: text;
user-select: text;
}
To make it work.
In Safari, despite also being WebKit based, there is differing behavior when clicking on an element that has the user-select property set. Chrome seems to key-off that css property and prevent any focus going to the element that was clicked (thanks for continuing to develop a modern and sensible browser Google), while Safari does nothing with that css property regarding focus, and sets focus on the clicked element anyway.
One solution in Safari is to use a proper html button element, but this sucks from a styling perspective.
A better solution is to trap the mousedown event (the first to fire of the Mouse type events in a click), and preventDefault() on the event. This should work in any version of Safari.
For example
<span onclick="document.execCommand('bold', false);" onmousedown="event.preventDefault();">
<i class="material-icons">format_bold</i>
</span>

How do I show a div, but make it completely un-interactive, in Chrome

I have a <div> overlayed onto my page, and that tracks the mouse. However, on occasion the user is able to move the mouse at the appropriate speed to enter the tracking <div>. Also, this <div> will sometimes prevent the user from clicking something else, that is below/behind.
What is the correct way to visually show this <div>, without it 'blocking' or interfering with the underlying DOM, or any of them for that matter? In particular, to stop it interfering with mouse events.
Good answers to this already, one you can consider also is the css:
pointer-events: none;
Which effectively makes events act on the items below the div, not the div itself.
Support for this on IE isn't great, but it's a nice way if you either don't need IE support, or if you have the time to do it properly and include a conditional fallback.
Check out this for support info: http://caniuse.com/pointer-events
you can place above it (with higher z-index) an absolute positioned div element, with an opacity value of 0
OR
you can use jQuery:
$(function(){
$('#divId').click(function(e){
e.preventDefault();
e.stopImmediatePropagation();
e.stopPropagation();
});
});
i personally prefer the opacity approach. but that's me.
hope that helped
Yuo can try to capture the event and prevent its default behavior using
event.preventDefault();
here a pseudo code, it works without jquery
var el = document.getElementById("yourdiv");
el.addEventListener("click", action, false);
function action() {
event.preventDefault();
return false;
}

Preventing cursor change on link click in Chrome

Clicking on a link in Chrome (not Safari or Firefox) changes the cursor from pointer to arrow. Can this behavior be prevented? I.e., is it possible to still have the pointer after clicking, but while the cursor is still hovering over the link?
EDIT: Okay so I've done a little more testing. First of all, the only reason anyone would want the cursor to remain as a pointer after clicking on a link is if the link does not actually load another page but rather fires a JS event instead.
Test
// JQuery
$("a").click(function(event) { event.preventDefault(); }
With the above code, event.preventDefault (or returning false) will allow the cursor to remain a pointer after click. This will suffice for most uses, namely triggering a DOM manipulation and/or AJAX request.
The problem is with history.pushState():
Test
// JQuery
$("a").click(function(event) {
history.pushState(arg1, arg2, url);
event.preventDefault(); return false;
}
Here the pointer DOES change to an arrow. Any ideas on how to stop that from happening?
This sounds like a CSS issue. Look for code like the following:
::-webkit-any-link:hover,
::-webkit-any-link:active { cursor: pointer; }
This will affect all links (like a[href]) but only in WebKit. Perhaps something else is preventing Safari from doing this.
UPDATE GIVEN EXPANDED QUESTION:
Now that we know more about the problem, namely that the cursor changes back to a pointer after clicking on an element fires off a javascript, I would say that this is a Chrome bug.
Please file a report at http://bugs.chromium.org/
You could explicitly set your target element's CSS to include --
#element {
cursor: pointer;
}
See http://www.quirksmode.org/css/cursor.html#note if you have to support IE 5.5.
In the meantime I'm thinking this desperate workaround:
Browser detect Chrome
Apply this tutorial

Jquery: change event to input file on IE

I have a form to upload files, and it should fire the submit after the file selection.
On FireFox/Chrome it goes well, and submits the form after file selection, but I can't do this on Internet Explorer.
Already tried with click/propertychange but nothing happens. Some code I already tried:
$("#attach").attr("onChange", "alert('I changed')");
$("#attach").live($.browser.msie? 'propertychange': 'change', function(e) { ... });
This input file is created on the fly; because of it I use .live() to bind the event.
Any suggestions?
I know this is several months late, but I just ran into the exact same behavior in IE7; in all other browsers, the change event for file inputs happens after file selection. In IE7, it happens only if you trigger the file select again, or on blur.
Here's how I ended up fixing it:
var $input = $('#your-file-input-element');
var someFunction = function()
{
// what you actually want to do
};
if ($.browser.msie)
{
// IE suspends timeouts until after the file dialog closes
$input.click(function(event)
{
setTimeout(function()
{
if($input.val().length > 0) {
someFunction();
}
}, 0);
});
}
else
{
// All other browsers behave
$input.change(someFunction);
}
Technically you could/should filter the hack condition to just IE7, since IE8 behaves properly on the change event, but it also has the same behavior as IE7 on suspending timeouts while browser-related chrome is visible (I guess it considers it blocking I/O), so it works as-is.
This is really late, but I was having the same problem, and I solved it by using a styled <label> tag with a slight workaround for Firefox.
http://jsfiddle.net/djibouti33/uP7A9/
The Goals:
allow user to upload a file by using standard html file input control
hide standard html file input control and apply own styling
after user selects file to upload, automatically submit the form
The Browsers:
Firefox, Chrome, IE8/9, Safari
IE7 didn't work, but it might if you add that browser to the workaround detailed at the bottom
The Initial Solution:
Hide the file input by positioning it offscreen. Important not to display:none as some browsers won't like this.
Add another styled element to the page (link, button).
Listen for a click on that element, then programmatically send a click to the file input to trigger the native 'file explorer'
Listen for the file input's onchange event (occurs after a user chooses their file)
Submit the form
The Problem:
IE: if you programmatically send a click to a file input in order to activate it (2), programmatically submitting the form (5) will throw a security error
The Workaround Solution:
Same as above
Take advantage of the accessibility features built in to the tag (clicking on a label will activate it's associated control) by styling
a tag instead of a link/button
Listen for the file input's onchange event
Submit the form
For some reason Mozilla browsers won't activate a file input by clicking on it's .
For Mozilla, listen for the click on the label and send a click event to the file input to activate it.
Hope this helps! Check out the jsfiddle for details on the html/js/css used to make it all work.
Format it like this:
$("#attach").change(function() {
alert('I Changed');
});
Update: After answering another question on this earlier, we realized this was fixed as part of the jQuery 1.4.2 event re-write, just update to the latest version to resolve the change event issue with <input type="file" /> in IE.
I used the following solution. I tried to make it as self-contained as possible.
(function($) {
if ($.browser.msie == false)
return;
$('input[type=file]').live('click', function(e) {
var self = this;
var blur = function() {
$(self).blur();
}
setTimeout(blur, 0);
});
})(jQuery);
This has always worked for me in IE6 ad IE7.
$('#id-of-input-type-file').change(function(){});
In IE onchange event works fine when it filled out in html tag directly. Like:
<input type="file" onchange="uploader.upload()" />
This is likely a problem with a race condition with input fields in IE. By using setTimeout the function that is executed will then register that a change happened. When the UI code is performed in the onChangeEvent, that event hasn't fired yet as it appears to IE.
I solved a similar situation by doing the following inside my change handler:
if (jQuery.browser.msie) { setTimeout(DoSomeUIChange, 0); } else { DoSomeUIChange(); }
The DoSomeUIChange is executed after the current code on the event queue and so removes the race condition.
I was having the same issue with IE (including IE 9). The UI logic is:
click on a div element triggers the click event on a file-input-element so that user click on a div trigger file open dialog
bind the change event handler to the file-input-element to ensure the form is submitted when file open dialog closed
The app (running inside an iframe) works like a charm on Chrome and FF. But soon I found it doesn't work on IE as when user selected a file and close the dialog the form didn't submit.
The final solution is to drop the logic #1 "click on div element trigger click event on file input element" and let user to click on the file input element directly, and then it works.
BTW, the reason we have a div element is we want to hide the browser rendered controls because we have everything in the background image. However set display to none makes the control not able to respond a user interaction event. So we move the file-input-element to outside of the view port and use a div element to replace it. Since this doesn't work on IE, we end up with move back the file-input-element and set it's opacity to 0. On IE 8 or less which doesn't support opacity, we use filter to make it transparent:
#browse {
filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
filter: alpha(opacity=0);
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
}
I found this solution
In HTML hide file element (don't use display: none, won't work in IE), prepare onchange event of IE:
<div style="width: 0px; height: 0px; overflow: hidden;">
<input id="ifile_template" type="file" onchange="this.focus(); this.blur();"/>
</div>
In javascript for IE bind function to blur, and for FF,CH bind function change():
$(iFile).blur(
function () {
...some code...
}
);
// FF, CH
$(iFile).change(
function () {
...some code...
}
);
For IE You can use the "onfocus" event to catch the change of uploading file. Once the file browsing dialog is closed the onfocus event is triggered. You can check this by adding this line to your page:
<input type="file" onfocus="javascript:alert('test');" />
Once the dialog is closed the alert message is shown.
This solution is only for IE, not for FF or Chrome.
My solution:
setInterval(function()
{
if ($.browser.msie) $("input[type=file]").blur();
},500);
Not pretty, but it works. ;D
I can confirm, at least that it only works after a blur event takes place, similar to a radio and checkbox in IE. I am probably going to have to add some kind of visual element for the user to click and tell me when they have picked their file.
lame.
$("#attach").attr("onChange", "alert('I changed')");
It works in IE, but if you want to emulate "live" behavior, you should add "onChange" attribute to each new element when create its.
jQuery doesn't seem to recognise the propertychange event. I added it to the DOM node using IE's attachEvent().
var userChoseFile = function($input) {
// ...
}
var $input = $(/* your file input */);
$input[0].attachEvent('onpropertychange', function() {
userChoseFile($input);
});
Look at these fiddle http://jsfiddle.net/uP7A9/531/
HTML:
<input type="file" name="PicturePath" id="fileUpload" accept=".png,.jpg,.jpeg,.gif,.tif" />
jQuery:
$("input[type=file]#fileUpload").on("change", function () {
alert('hi')
});
it works for all browsers, tested.

Categories

Resources