Reputation: 124696
I have a requirement to disable selection on a web page for everything except input[type=text] elements.
This accepted answer to a similar question almost does the trick, but it doesn't disable selection for containers that contain input[type=text] elements. Therefore the user can still select by starting a drag operation from within one of these containers.
Is this even possible, i.e. is it possible to disable selection for a container element, while enabling it for child elements (specifically, child input=text elements).
@Pointy, "Why not just take out that first .not() call?"
Taking out the first .not
call, will give:
$('body').not('input').disableSelection();
which, as pointed out in the linked question, will still disable everything on the page, including the input[type=text] elements.
@David Thomas, "Do you have a live demo ..."
I don't have a live demo, but it's fairly trivial. For example, a div with a bit of padding that contains an input[type=text] element. The result is:
With $('body').not('input').disableSelection();
selectiopn is disabled for all the page, including the input elements.
With $('body *').not(':has(input)').not('input').disableSelection();
selection is disabled for all elements that don't contain an input element. But it is possible to select the whole page by starting a drag operation from within a container that contains an input element.
Upvotes: 4
Views: 2330
Reputation: 124696
I've found a solution that appears to do what I want, and would be interested in comments / improvements from jquery / javascript experts.
$(document).ready(function () {
$("body").disableSelection();
$("body").delegate('input[type=text],textarea', "focus", function () {
$("body").enableSelection();
});
$("body").delegate("input[type=text],textarea", "blur", function () {
$("body").disableSelection();
});
});
When a textbox (input[type=text] or textarea) has the focus, then dragging with the mouse only selects text within the textbox. Therefore it's "safe" to enable selection for the whole page while a textbox has focus (between focus and blur events).
There is a noticeable delay when tabbing between textboxes on IE8/9. It's not noticeable on Google Chrome, which I understand has a faster javascript engine. So I can live with the performance hit, especially since IE10 is going to have a faster javascript engine.
UPDATE
When using ASP.NET UpdatePanel
, this needs to be modified to disable selection after each partial postback:
Sys.Application.add_load(function () {
$("body").disableSelection();
});
Upvotes: 1
Reputation: 5945
Well, cinch up your suspenders and get ready for a really dirty hack.
I don't think this is a good way to do things. I simply wanted to tackle the challenge of getting the OP's desired functionality. If someone else can get this to work in a cleaner way, please post it.
After playing around with the disableSelection()
function, it seemed that if a parent element had been disabled, all of its children would be unselectable as well (please correct me if I'm wrong). So, I decided that if you wanted everything to be unselectable except small parts, you could put all of your markup in one unselectable <div>
and use absolute positioning to place selectable clones of your <input>
tags (or any tag, really) on top of the unselectable ones. These clones would reside in a second <div>
that was not disabled.
Here's an example of this idea: http://jsfiddle.net/pnCxE/2/.
So, while you can work around the selectable limitations, you might be better off just accepting the container selection. I would think long and hard before putting this code into a production environment.
Upvotes: 1
Reputation: 5263
Try this, although it is same with what you're already using:
$('* :not(input)').disableSelection();
I don't get though why do you have to use entire body
element and not narrow it down to text nodes (p, h[..], ul, ol etc.)
And I agree with @David Thomas - it would be easier to see a test page you're working on.
Upvotes: 0