views:

31

answers:

2

I have an iframe with designMode set to 'on'. In it, there are multiple divs, and because the iframe is editable, the user is able to type in and edit any one of those divs. I need to disable the ability for the user to edit one of the divs.

I can prevent the user from clicking on the div like this:

document.getElementById('mydiv').addEventListener('mousedown', function(event) {
  event.preventDefault();
  return false;
}, true);

However, the user is still able to use the keyboard arrow keys, move the cursor over to the div, and edit it. I tried firing a callback when the div receives focus, like this:

document.getElementById('mydiv').addEventListener('focus', function(event) {
  ...
}, true);

but that callback is never called. Then I tried to prevent keypresses:

document.getElementById('mydiv').addEventListener('keydown', function(event) {
  event.preventDefault();
  return false;
}, true);

but again, the callback is never called. I even tried attaching the callback to the document:

document.addEventListener('keydown', function(event) {
  ...
}, true);

and the callback does get called then, but I need a way to cancel the event only if the target element is the div in concern.

Any ideas on how to achieve the goal are welcome.

A: 

You could simply apply an 'editable' class to any editable elements, and remove it when that is not the case.

YUI provides a nice simple test for this: YAHOO.util.Dom.hasClass( yourEl, 'editable' );

Then within your handler, if the target has no 'editable' class, cancel/return/preventDefault/stopEvent.

-d

ADDITION http://developer.yahoo.com/yui/examples/event/event-delegation.html

Danjah
Hmm...but what callback do I use, and for what element? 'focus' and 'keypress' will only fire for the document element, not document.getElementById('mydiv'). If I use 'keydown' for document, then target is always set to document...
Chad Johnson
What I'm suggesting is delegating click behaviour of a container to a set of child elements, each of which have a class name 'editable' applied if that's what they are to be. When the click event is fired, you receive the clicked target, in the default scope of the container, so you can check for 'editable' className in the event callback. So let the clicks roll in, and squash their activity if they aren't supposed to be editable.
Danjah
+1  A: 

If you can afford to ignore a few older browsers such as Firefox 2, the easiest way to do this would be not to use designMode and instead use contentEditable on each of the editable <div>s and not on the non-editable <div>s.

<div contenteditable="true">Some editable stuff</div>

<div>Some non-editable stuff</div>

<div contenteditable="true">Some more editable stuff</div>

Otherwise, as you've discovered, you're fighting a losing battle with built-in browser behaviour.

Tim Down
Are there any actual differences between contentEditable and designMode (besides that the former is for specific elements and the latter for the entire document)?
Chad Johnson
I've seen some wrinkles with `contentEditable` in Firefox that are probably due to it having been implemented a lot more recently than `designMode` but in general you're correct: there's no difference apart from scope.
Tim Down