witten
/
luminotes
Archived
1
0
Fork 0

Better range restoration when transitioning from a div to an iframe in IE. Also got rid of click_position, as it's no longer used.

This commit is contained in:
Dan Helfman 2009-01-24 13:57:33 -08:00
parent 42d4d514d2
commit a4648981c7
1 changed files with 64 additions and 46 deletions

View File

@ -203,7 +203,7 @@ Editor.prototype.connect_note_controls = function ( store_control_buttons ) {
} }
} }
Editor.prototype.claim_iframe = function ( position_after, click_position ) { Editor.prototype.claim_iframe = function ( position_after ) {
var self = this; var self = this;
var iframe_id = "note_" + this.id; var iframe_id = "note_" + this.id;
@ -244,7 +244,7 @@ Editor.prototype.claim_iframe = function ( position_after, click_position ) {
addElementClass( this.div, "invisible" ); addElementClass( this.div, "invisible" );
function finish_init() { function finish_init() {
self.position_cursor( click_position, range ); self.position_cursor( range );
self.connect_handlers(); self.connect_handlers();
signal( self, "focused", self ); signal( self, "focused", self );
} }
@ -293,52 +293,59 @@ Editor.prototype.focus_default_text_field = function () {
} }
Editor.prototype.add_selection_bookmark = function () { Editor.prototype.add_selection_bookmark = function () {
if ( !window.getSelection ) // IE if ( window.getSelection ) { // browsers such as Firefox
return null; // grab the current range for this editor's div so that it can be duplicated within the iframe
var selection = window.getSelection();
if ( selection.rangeCount > 0 )
var range = selection.getRangeAt( 0 );
else
var range = document.createRange();
// grab the current range for this editor's div so that it can be duplicated within the iframe // if the current range is not within this editor's static note div, then bail
var selection = window.getSelection(); if ( range.startContainer == document || range.endContainer == document )
if ( selection.rangeCount > 0 ) return null;
var range = selection.getRangeAt( 0 ); if ( !isChildNode( range.startContainer.parentNode, this.div ) || !isChildNode( range.endContainer.parentNode, this.div ) )
else return null;
var range = document.createRange();
// if the current range is not within this editor's static note div, then bail // mark the nodes that are start and end containers for the current range. we have to mark the
if ( range.startContainer == document || range.endContainer == document ) // parent node instead of the start/end container itself, because text nodes can't have classes
return null; var parent_node = range.startContainer.parentNode
if ( !isChildNode( range.startContainer.parentNode, this.div ) || !isChildNode( range.endContainer.parentNode, this.div ) ) addElementClass( parent_node, "range_start_container" );
return null; for ( var i in parent_node.childNodes ) {
var child_node = parent_node.childNodes[ i ];
if ( child_node == range.startContainer )
range.start_child_offset = i;
}
// mark the nodes that are start and end containers for the current range. we have to mark the var parent_node = range.endContainer.parentNode
// parent node instead of the start/end container itself, because text nodes can't have classes addElementClass( parent_node, "range_end_container" );
var parent_node = range.startContainer.parentNode for ( var i in parent_node.childNodes ) {
addElementClass( parent_node, "range_start_container" ); var child_node = parent_node.childNodes[ i ];
for ( var i in parent_node.childNodes ) { if ( child_node == range.endContainer )
var child_node = parent_node.childNodes[ i ]; range.end_child_offset = i;
if ( child_node == range.startContainer ) }
range.start_child_offset = i;
return range;
} else if ( document.selection ) { // browsers such as IE
var range = document.selection.createRange();
if ( !isChildNode( range.parentElement(), this.div ) )
return null;
return range;
} }
var parent_node = range.endContainer.parentNode return null;
addElementClass( parent_node, "range_end_container" );
for ( var i in parent_node.childNodes ) {
var child_node = parent_node.childNodes[ i ];
if ( child_node == range.endContainer )
range.end_child_offset = i;
}
return range;
} }
Editor.prototype.remove_selection_bookmark = function ( range ) { Editor.prototype.remove_selection_bookmark = function ( range ) {
// unmark the nodes that are start and end containers for the given range // unmark the nodes that are start and end containers for the given range
if ( range ) { if ( range && range.startContainer && range.endContainer ) {
removeElementClass( range.startContainer.parentNode, "range_start_container" ); removeElementClass( range.startContainer.parentNode, "range_start_container" );
removeElementClass( range.endContainer.parentNode, "range_end_container" ); removeElementClass( range.endContainer.parentNode, "range_end_container" );
} }
} }
Editor.prototype.position_cursor = function ( click_position, div_range ) { Editor.prototype.position_cursor = function ( div_range ) {
if ( this.init_focus ) { if ( this.init_focus ) {
this.init_focus = false; this.init_focus = false;
if ( this.iframe ) if ( this.iframe )
@ -377,13 +384,29 @@ Editor.prototype.position_cursor = function ( click_position, div_range ) {
selection.addRange( range ); selection.addRange( range );
return; return;
} }
} else if ( click_position && this.document.selection ) { // browsers such as IE } else if ( div_range && this.document.selection ) { // browsers such as IE
// position the cursor by using given click position coordinates function text_length( text ) {
var count = 0;
for ( var i = 0; i < text.length; i++ ) {
if ( text.charAt( i ) != "\r" )
count++;
}
return count;
}
// create a range that extends from the start of the div to the start of the original range
var before_div_range = div_range.duplicate();
before_div_range.moveToElementText( this.div );
before_div_range.setEndPoint( "EndToStart", div_range );
// calculate the start offset based on the size of that range in characters
var start = text_length( before_div_range.text ) - 1;
var end = start + text_length( div_range.text );
// finally, position the text cursor within the iframe
var range = this.document.selection.createRange(); var range = this.document.selection.createRange();
range.moveToPoint( range.moveEnd( "character", end );
click_position.x - this.iframe.offsetLeft - FRAME_BORDER_WIDTH, range.moveStart( "character", start );
click_position.y - this.iframe.offsetTop - FRAME_BORDER_WIDTH
);
range.select(); range.select();
return; return;
@ -765,12 +788,7 @@ Editor.prototype.mouse_clicked = function ( event ) {
if ( !link_clicked && this.div ) { if ( !link_clicked && this.div ) {
this.init_focus = true; this.init_focus = true;
if ( MSIE ) this.claim_iframe( null );
var click_position = { "x": window.event.x, "y": window.event.y };
else
var click_position = event.mouse().page;
this.claim_iframe( null, click_position );
} }
// in case the cursor has moved, update the state // in case the cursor has moved, update the state