views:

662

answers:

3

I am working on a cross browser web based annotation toolset, which allows the users to select any part of a web page

  • HIGHLIGHT, if you select:

john is <li>big</li> <li>dump</li>

Result

<span style="background-color: rgb(106, 168, 79)">john is</span> <li><span style="background-color: rgb(106, 168, 79)">big</span></li> <li><span style="background-color: rgb(106, 168, 79)">dump</span></li>

  • REMOVE FORMAT: if you select:

john

from

<span style="background-color: rgb(106, 168, 79)">john is</span> <li><span style="background-color: rgb(106, 168, 79)">big</span></li> <li><span style="background-color: rgb(106, 168, 79)">dump</span></li>

Result

<span style="background-color: rgb(106, 168, 79)"></span> john <span style="background-color: rgb(106, 168, 79)">is</span> <li><span style="background-color: rgb(106, 168, 79)">big</span></li> <li><span style="background-color: rgb(106, 168, 79)">dump</span></li>

  • UNDO/REDO: nice to have feature

To be able to undo and redo the actions performed

I have a partial solution for highlighting

function highlight(colour) {
var range, sel;
if (document.selection && (!window.getSelection)) {
 // IE case
    range = document.selection.createRange();  
    range.execCommand("BackColor", false, colour);  
} else if (window.getSelection) {    
// Non-IE case 
    sel = window.getSelection();
    if (sel.getRangeAt) {
        range = sel.getRangeAt(0);
    }
//without designmode=on, you can't highlight the selected html (chrome)
    document.designMode = "on";
    if (range) {
        sel.removeAllRanges();
        sel.addRange(range);
    }
    // HiliteColor avoids FF3.5 from painting the background of the whole block
    if (!document.execCommand("HiliteColor", false, colour) ) {
        document.execCommand("BackColor", false, colour);
    }
    document.designMode = "off";
}

}

Since my requirements had much similarity with a richtext editor, I looked into the codes of ckeditor and (extensively) in google closures editor. I have given up hope in both of them because, they work in only an editable iframe. One of my requirement is that users are not allowed to change the original text but only to add there own annotations(highlight, inline notes,etc).

I would love to here all of your opinions and if possible to point me to the right direction.

--Choesang

A: 

Here's a good resource that helped me with something similiar: http://www.quirksmode.org/dom/execCommand.html

linked from the first page as an example:

http://www.quirksmode.org/dom/execCommand/

rosscj2533
it is a great example and an awsome website but i found out that readonly button is not cross browser (IE8, chrome do not obey the rules)Thanks for your suggestion
tchoesang
+1  A: 

I think you can still use "rich-text-editor" way (iframe), but then try to catch "onkeypress","onkeydown" and other interactive events to stop default behavior (editing the document).

nemisj
I wish it is feasable, tried to do exactly what you are saying for the last one week with google closure editor.
tchoesang
tchoesang
A: 

You will find the solution in the forum: http://cksource.com/forums/viewtopic.php?f=11&amp;t=15659

For the sake of clarity, i am inserting the code below:

// Temporary workaround for providing editor 'read-only' toggling functionality.  
   ( function()
  {
   var cancelEvent = function( evt )
  {
     evt.cancel();
  };

 CKEDITOR.editor.prototype.readOnly = function( isReadOnly )
 {
  // Turn off contentEditable.
  this.document.$.body.disabled = isReadOnly;
  CKEDITOR.env.ie ? this.document.$.body.contentEditable = !isReadOnly
  : this.document.$.designMode = isReadOnly ? "off" : "on";

  // Prevent key handling.
  this[ isReadOnly ? 'on' : 'removeListener' ]( 'key', cancelEvent, null, null, 0 );
  this[ isReadOnly ? 'on' : 'removeListener' ]( 'selectionChange', cancelEvent, null, null, 0 );

  // Disable all commands in wysiwyg mode.
  var command,
     commands = this._.commands,
     mode = this.mode;

  for ( var name in commands )
  {
     command = commands[ name ];
     isReadOnly ? command.disable() : command[ command.modes[ mode ] ? 'enable' : 'disable' ]();
     this[ isReadOnly ? 'on' : 'removeListener' ]( 'state', cancelEvent, null, null, 0 );
  }
 }
} )();

and in your javascript, call as following

// Turn CKEditor into 'ready-only' mode or vice versa.
CKEDITOR.instances.editor1.readOnly( true );
CKEDITOR.instances.editor1.readOnly( false );

The above basically provides an area (iframe) that is editable and it the same time read-only (you can not input from keyboard). It completely fulfills all my desired functionalities. I do not have to care about how to implement: highlighting, remove format, undo and redo. Everything is taken cared of ckeditor :)

tchoesang