JavaScript: Disable text selection via doubleclick - javascript

When double-clicking on a html page most browsers select the word you double-click on (or the paragraph you triple-click on). Is there a way to get rid of this behavior?
Note that I do not want to disable regular selection via single-click+dragging; i.e. jQuery UI's $('body').disableSelection() and the document.onselectstart DOM event are not what I want.

I fear you can't prevent the selection itself being "native behavior" of the browser, but you can clear the selection right after it's made:
<script type="text/javascript">
document.ondblclick = function(evt) {
if (window.getSelection)
window.getSelection().removeAllRanges();
else if (document.selection)
document.selection.empty();
}
</script>
Edit: to also prevent selecting whole paragraph by "triple click", here is the required code:
var _tripleClickTimer = 0;
var _mouseDown = false;
document.onmousedown = function() {
_mouseDown = true;
};
document.onmouseup = function() {
_mouseDown = false;
};
document.ondblclick = function DoubleClick(evt) {
ClearSelection();
window.clearTimeout(_tripleClickTimer);
//handle triple click selecting whole paragraph
document.onclick = function() {
ClearSelection();
};
_tripleClickTimer = window.setTimeout(RemoveDocumentClick, 1000);
};
function RemoveDocumentClick() {
if (!_mouseDown) {
document.onclick = null;
return true;
}
_tripleClickTimer = window.setTimeout(RemoveDocumentClick, 1000);
return false;
}
function ClearSelection() {
if (window.getSelection)
window.getSelection().removeAllRanges();
else if (document.selection)
document.selection.empty();
}​
Live test case.
Should be cross browser, please report any browser where it's not working.

The following works for me in the current Chrome (v56), Firefox (v51) and MS Edge (v38) browsers.
var test = document.getElementById('test');
test.addEventListener('mousedown', function(e){
if (e.detail > 1){
e.preventDefault();
}
});
<p id="test">This is a test area</p>
The MouseEvent.detail property keeps track of the current click count which can be used to determine whether the event is a double, tripple, or more click.
Internet explorer unfortunately does not reset the counter after a timeout period so instead of getting a count of burst-clicks you get a count of how many times the user has clicked since the page was loaded.

Just put this on the css interested section
-moz-user-select : none;
-khtml-user-select : none;
-webkit-user-select : none;
-o-user-select : none;
user-select : none;

If you really want to disable selection on double-click and not just remove the selection afterwards (looks ugly to me), you need to return false in the second mousedown event (ondblclick won't work because the selection is made onmousedown).
**If somebody wants no selection at all, the best solution is to use CSS user-select : none; like Maurizio Battaghini proposed.
// set to true if you want to disable also the triple click event
// works in Chrome, always disabled in IE11
var disable_triple_click = true;
// set a global var to save the timestamp of the last mousedown
var down = new Date().getTime();
var old_down = down;
jQuery(document).ready(function($)
{
$('#demo').on('mousedown', function(e)
{
var time = new Date().getTime();
if((time - down) < 500 &&
(disable_triple_click || (down - old_down) > 500))
{
old_down = down;
down = time;
e.preventDefault(); // just in case
return false; // mandatory
}
old_down = down;
down = time;
});
});
Live demo here
Important notice: I set the sensitivity to 500ms but Double-click sensitivity (maximum time between clicks that is detected as a double click) can vary by operating system and browser, and is often user-configurable. - api.jquery.com
Tested in Chrome and IE11.

Just to throw this out there, but here's the code I slap into my pages where I expect users to be clicking rapidly. However, this will also disable standard click-n-drag text selection.
document.body.onselectstart = function() {
return false;
}
document.body.style.MozUserSelect = "none";
if (navigator.userAgent.toLowerCase().indexOf("opera") != -1) {
document.body.onmousedown = function() {
return false;
}
}
Seems to work well for me.

Related

Keypress Gestures using Tampermonkey for Chrome

I'm working on a tampermonkey userscript to replace a feature that existed with FireGestures back in Pre-Quantum Firefox. The ability to open all hovered links into new background tabs. So having a combination keypress, which in FG was Ctrl + Right Click and drawing a gesture trail though every link you wanted open. Everything I have so far has been written for me by somebody else so I'm not trying to take credit and I in am way over my head. I don't have the know-how to edit and fix what is needed. This is what I have so far.
(function(delay, t, lnk, clicked) {
//config: delay before click. mouse movement will reset the delay timer.
delay = 1000; //in milliseconds. 1sec = 1000ms
t = 0;
function mousemove() {
clearTimeout(t);
if (lnk) t = setTimeout(clickLink, delay);
}
function clickLink() {
removeEventListener("mousemove", mousemove);
clearTimeout(t);
if (lnk) {
lnk.target = "_blank";
lnk.click();
lnk.target = "";
clicked = true;
}
}
addEventListener("mouseover", function(ev, el, el2) {
el = ev.target;
removeEventListener("mousemove", mousemove);
clearTimeout(t);
while (el) {
if (el.tagName === "A") {
el2 = el;
if (el !== lnk) {
lnk = el;
clicked = false;
addEventListener("mousemove", mousemove);
clearTimeout(t);
t = setTimeout(clickLink, delay);
}
return;
}
el = el.parentNode;
}
if (!el2) {
lnk = null;
clicked = false;
removeEventListener("mousemove", mousemove);
clearTimeout(t);
}
});
})();
There is a couple issues I face.
1. This doesn't require any sort of button combination. It is continually active and will click any link that is hovered over for the specified length of time. I would prefer it to only function when a button combination is pressed, ideally Ctrl + Rightclick. I found a thread dealing with combination keypresses but wouldn't know how to edit it and insert it into the existing script to fit my needs.
document.addEventListener ("keydown", function (zEvent) {
if (zEvent.ctrlKey && zEvent.altKey && zEvent.code === "KeyE") {
// DO YOUR STUFF HERE
}
} );
2. The pop-up blocker in chrome actually prevents these tabs from opening. I don't know if there is any way of remedying this other than turning off the pop-up blocker, but if there was I'd appreciate the help
3. This script opens up tabs in the foreground rather than the background. So opening up a bunch of links on a page wouldn't be possible because it would navigate to the new tab as soon as the first link is clicked. My original idea for fixing this was to just have the script just do a middle-click mouse event over every link it passed over, but I don't even know if that is something that is possible or practical.
I know I am asking a lot but I was just hoping that someone out there that knows what they are doing could help me out by either editing what I already have or writing something out themselves. I appreciate any help provided.
here's my spin on it. This is toggled rather than going on while you are holding onto the keys.
you could had the following to your TamperMonkey script, and when you press "Ctrl + Alt + S", the links on the page are modified and appended a onmouseover event. when you hit the key combination again, the event gets removed from the link. Short and simple.
document.addEventListener('keydown', function (zEvent) {
if (zEvent.ctrlKey && zEvent.altKey && zEvent.code === 'KeyS') {
var links = document.getElementsByTagName('a');
console.log(links.length);//how many links have been grabbed
for (var i = 0; i < links.length; i++) {
if (links[i].onmouseover !== null && links[i].onmouseover.toString().indexOf('function openit') > -1)
{
//toggling the funcitonality off
//remove it
links[i].setAttribute('target', '');
links[i].setAttribute('onmouseover', '');
}
else
{
//toggling the funcitonality on
//add it
links[i].setAttribute('target', 'blank');
links[i].setAttribute('onmouseover', 'function openit(elem){console.log(\'userScript will click on the link\');elem.click();};openit(this);');
}
}
}
}
);
As for popup blocking... I don't know.

PrtScn Button in the IE not behaving as other browsers using java script

I've been using the following javascript code that blocks Normal users (not professionals of course) from using print screen & Ctrl+A & Ctrl+C on the browser.
it does work as expected on Firefox & Chrome but it sometimes works on IE and some other times it fails. Please review the code if you can a little help of maybe what's going wrong on IE. and why it fails?
function disableselect(e) {
return false;
}
function reEnable() {
return true;
}
document.onselectstart = new Function("return false");
if (window.sidebar) {
document.onmousedown = disableselect;
document.onclick = reEnable;
}
function copyToClipboard() {
// Create a "hidden" input
var aux = document.createElement("input");
// Assign it the value of the specified element
aux.setAttribute("value", "You can no longer give print-screen. This is part of the new system security measure");
// Append it to the body
document.body.appendChild(aux);
// Highlight its content
aux.select();
// Copy the highlighted text
document.execCommand("copy");
// Remove it from the body
document.body.removeChild(aux);
alert("You can no longer give print-screen. This is part of the new system security measure.");
}
$(window).keyup(function(e){
if(e.keyCode == 44){
copyToClipboard();
}
});
$(window).focus(function() {
$("body").show();
}).blur(function() {
$("body").hide();
});
I have tested it and it works for me using Chrome, Firefox, IE11.
But, if someone use Inspect Element to disable CSS restriction, then he will disable it :)

Event fired when clearing text input on IE10 with clear icon

On chrome, the "search" event is fired on search inputs when user clicks the clear button.
Is there a way to capture the same event in javascript on Internet Explorer 10?
The only solution I finally found:
// There are 2 events fired on input element when clicking on the clear button:
// mousedown and mouseup.
$("input").bind("mouseup", function(e){
var $input = $(this),
oldValue = $input.val();
if (oldValue == "") return;
// When this event is fired after clicking on the clear button
// the value is not cleared yet. We have to wait for it.
setTimeout(function(){
var newValue = $input.val();
if (newValue == ""){
// Gotcha
$input.trigger("cleared");
}
}, 1);
});
The oninput event fires with this.value set to an empty string. This solved the problem for me, since I want to execute the same action whether they clear the search box with the X or by backspacing. This works in IE 10 only.
Use input instead. It works with the same behaviour under all the browsers.
$(some-input).on("input", function() {
// update panel
});
Why not
$("input").bind('input propertychange', function() {
if (this.value == ""){
$input.trigger("cleared");
}
});
I realize this question has been answered, but the accepted answer did not work in our situation. IE10 did not recognize/fire the $input.trigger("cleared"); statement.
Our final solution replaced that statement with a keydown event on the ENTER key (code 13). For posterity, this is what worked in our case:
$('input[type="text"]').bind("mouseup", function(event) {
var $input = $(this);
var oldValue = $input.val();
if (oldValue == "") {
return;
}
setTimeout(function() {
var newValue = $input.val();
if (newValue == "") {
var enterEvent = $.Event("keydown");
enterEvent.which = 13;
$input.trigger(enterEvent);
}
}, 1);
});
In addition, we wanted to apply this binding only to the "search" inputs, not every input on the page. Naturally, IE made this difficult as well... although we had coded <input type="search"...>, IE rendered them as type="text". That's why the jQuery selector references the type="text".
Cheers!
We can just listen to the input event. Please see the reference for details. This is how I fixed an issue with clear button in Sencha ExtJS on IE:
Ext.define('Override.Ext.form.field.ComboBox', {
override: 'Ext.form.field.ComboBox',
onRender: function () {
this.callParent();
var me = this;
this.inputEl.dom.addEventListener('input', function () {
// do things here
});
}
});
An out of the box solution is to just get rid of the X entirely with CSS:
::-ms-clear { display: none; } /* see https://stackoverflow.com/questions/14007655 */
This has the following benefits:
Much simpler solution - fits on one line
Applies to all inputs so you don't have to have a handler for each input
No risk of breaking javascript with bug in logic (less QA necessary)
Standardizes behavior across browsers - makes IE behave same as chrome in that chrome does not have the X
for my asp.net server control
<asp:TextBox ID="tbSearchName" runat="server" oninput="jsfun_tbSearchName_onchange();"></asp:TextBox>
js
function jsfun_tbSearchName_onchange() {
if (objTbNameSearch.value.trim() == '')
objBTSubmitSearch.setAttribute('disabled', true);
else
objBTSubmitSearch.removeAttribute('disabled');
return false;
}
ref
MSDN onchange event
- tested in IE10.
... or to hide with CSS :
input[type=text]::-ms-clear { display: none; }
The above code was not working in my case and I have changed one line and introduced $input.typeahead('val', ''); which works in my case..
// There are 2 events fired on input element when clicking on the clear button:// mousedown and mouseup.
$("input").on('mouseup', function(e){
var $input = $(this),
oldValue = $input.val();
if (oldValue === ''){
return;
}
// When this event is fired after clicking on the clear button // the value is not cleared yet. We have to wait for it.
setTimeout(function(){
var newValue = $input.val();
if (newValue === ''){
$input.typeahead('val', '');
e.preventDefault();
}
}, 1);
});

RadioButton doesn't "receive" focus

I've pieced together some code to use in ASP.NET to prevent controls from losing focus on postback so a tab OR click of another control saves the users position and returns it.
In Page_Load I have the following:
PartNum_tb.Attributes["onfocus"] = "gotFocus(this)";
Department_tb.Attributes["onfocus"] = "gotFocus(this)";
PartWeight_tb.Attributes["onfocus"] = "gotFocus(this)";
Standard_rb.Attributes.Add("onfocus","gotFocus(this)");
Special_rb.Attributes.Add("onfocus","gotFocus(this)");
if (Page.IsPostBack)
Page.SetFocus(tabSelected.Value);
This is my Javascript (tabSelected is a hidden field):
<script type="text/javascript">
function gotFocus(control) {
document.getElementById('form1').tabSelected.value = control.id;
if (control.type == "text") {
if (control.createTextRange) {
//IE
var FieldRange = control.createTextRange();
FieldRange.moveStart('character', control.value.length);
FieldRange.collapse();
FieldRange.select();
}
else {
//Firefox and Opera
control.focus();
var length = control.value.length;
control.setSelectionRange(length, length);
}
}
}
</script>
The problem is when I tab or click onto one of the radio buttons, it returns focus to whatever the last control was instead which is unintuitive and confusing to a user. It does this because the RadioButton never gets focus, therefore the cursor position doesn't get updated. After extensive Google searching it appears that its not really possible to know when a RadioButton gains focus. Is there any solution known to even just work around this problem?
A solution may be adding a keypress event to the previous field and use the click event on the radios. Also, move the control.focus(); out of the if statement:
Javascript
function changeFocus(next) {
gotFocus(next);
}
function gotFocus(control) {
document.getElementById('form1').tabSelected.value = control.id;
control.focus();
if (control.type == "text") {
if (control.createTextRange) {
//IE
var FieldRange = control.createTextRange();
FieldRange.moveStart('character', control.value.length);
FieldRange.collapse();
FieldRange.select();
}
else {
//Firefox and Opera
var length = control.value.length;
control.setSelectionRange(length, length);
}
}
}

Detect single tap in UIWebView, but still support text selection and links

I'm using JavaScript to detect taps in a page I'm showing in a UIWebView, like so:
<div id="wrapper">
Apple
</div>
<script>
document.getElementById("wrapper").addEventListener('click', function() {
document.location = 'internal://tap';
}, false);
</script>
I'm intercepting links with my web view delegate, and look for "internal://tap". When I get that, I prevent the web view from navigating, and respond to the tap. However doing this I lose the ability to select text. Tapping the link does still work correctly.
In fact, just adding an event listener for 'click' removes the ability to select text, even if the handler doesn't attempt to change the document location.
Any idea what I'm doing wrong?
Apparently if you put a click listener on an element, you can no longer select text within that element on iOS. My solution was to detect taps using a combination of touchstart, touchmove, and touchend events, along with a timer to ignore multi-taps, and checking the current document selection to make sure a selection event is not going on.
Here's the JS code I used:
SingleTapDetector = function(element, handler) {
this.element = element;
this.handler = handler;
element.addEventListener('touchstart', this, false);
};
SingleTapDetector.prototype.handleEvent = function(event) {
switch (event.type) {
case 'touchstart': this.onTouchStart(event); break;
case 'touchmove': this.onTouchMove(event); break;
case 'touchend': this.onTouchEnd(event); break;
}
};
SingleTapDetector.prototype.onTouchStart = function(event) {
this.element.addEventListener('touchend', this, false);
document.body.addEventListener('touchmove', this, false);
this.startX = this.currentX = event.touches[0].clientX;
this.startY = this.currentY = event.touches[0].clientY;
this.startTime = new Date().getTime();
};
SingleTapDetector.prototype.onTouchMove = function(event) {
this.currentX = event.touches[0].clientX;
this.currentY = event.touches[0].clientY;
};
SingleTapDetector.prototype.onTouchEnd = function(event) {
var that = this;
// Has there been one or more taps in this sequence already?
if (this.tapTimer) {
// Reset the timer to catch any additional taps in this sequence
clearTimeout(this.tapTimer);
this.tapTimer = setTimeout(function() {
that.tapTimer = null;
}, 300);
} else {
// Make sure the user didn't move too much
if (Math.abs(this.currentX - this.startX) < 4 &&
Math.abs(this.currentY - this.startY) < 4) {
// Make sure this isn't a long press
if (new Date().getTime() - this.startTime <= 300) {
// Make sure this tap wasn't part of a selection event
if (window.getSelection() + '' == '') {
// Make sure this tap is in fact a single tap
this.tapTimer = setTimeout(function() {
that.tapTimer = null;
// This is a single tap
that.handler(event);
}, 300);
}
}
}
}
};
new SingleTapDetector(document.body, function(event) {
document.location = "internal://tap";
});
There is no need to use Javascript for this, it's overkill when the UIGestureRecognizerDelegate has adequate methods. All you need to do is make sure that when text selection is taking place, the tap recogniser isn't triggered.
- (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
BOOL hasTap = ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]] ||
[otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]);
BOOL hasLongTouch = ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]] ||
[otherGestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]);
if (hasTap && hasLongTouch) {
// user is selecting text
return NO;
}
return YES;
}
That takes care of text selection, and links should work fine anyway (at least they do for me).

Categories