to StackOverflow
to StackOverflow

Reputation: 124696

disableSelection on everything but input[type=text]

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:

Upvotes: 4

Views: 2330

Answers (3)

to StackOverflow
to StackOverflow

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

RustyTheBoyRobot
RustyTheBoyRobot

Reputation: 5945

Well, cinch up your suspenders and get ready for a really dirty hack.

Disclaimer:

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/.

Drawbacks:

  • Styling becomes a big headache. Any element that relies on a parent's style (i.e., position, size, colors, etc.) cannot be cloned since the clones reside in a separate place.
  • Forms become much harder to manage since (again) the clone isn't in the same place as the cloned element.
  • You have to deal with naming collisions since the clone will have the same ID as the cloned element. (It's doable; I just didn't want to code it since it would probably need specific attention by anyone that uses this idea)

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

mvbl fst
mvbl fst

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

Related Questions