mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-27 07:40:48 +00:00
99 lines
2.5 KiB
JavaScript
99 lines
2.5 KiB
JavaScript
ve.ce.CursorObserver = function( documentView ) {
|
|
// Inheritance
|
|
ve.EventEmitter.call( this );
|
|
|
|
this.documentView = documentView;
|
|
this.anchorNode = null;
|
|
this.anchorOffset = null;
|
|
this.focusNode = null;
|
|
this.focusOffset = null;
|
|
};
|
|
|
|
ve.ce.CursorObserver.prototype.update = function() {
|
|
var _this = this;
|
|
|
|
setTimeout( function() {
|
|
if ( !_this.documentView.$.is(':focus') ) {
|
|
if (
|
|
_this.anchorNode !== null ||
|
|
_this.anchorOffset !== null ||
|
|
_this.focusNode !== null ||
|
|
_this.focusOffset !== null
|
|
) {
|
|
_this.anchorNode = _this.anchorOffset = _this.focusNode = _this.focusOffset = null;
|
|
_this.emit( 'change', null );
|
|
}
|
|
} else {
|
|
var rangySel = rangy.getSelection(),
|
|
range;
|
|
if ( rangySel.anchorNode !== _this.anchorNode ||
|
|
rangySel.anchorOffset !== _this.anchorOffset ||
|
|
rangySel.focusNode !== _this.focusNode ||
|
|
rangySel.focusOffset !== _this.focusOffset
|
|
) {
|
|
_this.anchorNode = rangySel.anchorNode;
|
|
_this.anchorOffset = rangySel.anchorOffset;
|
|
_this.focusNode = rangySel.focusNode;
|
|
_this.focusOffset = rangySel.focusOffset;
|
|
|
|
if ( rangySel.isCollapsed ) {
|
|
range = new ve.Range( _this.getOffset( _this.anchorNode, _this.anchorOffset ) );
|
|
} else {
|
|
range = new ve.Range(
|
|
_this.getOffset( _this.anchorNode, _this.anchorOffset ),
|
|
_this.getOffset( _this.focusNode, _this.focusOffset )
|
|
);
|
|
}
|
|
_this.emit( 'change', range );
|
|
}
|
|
}
|
|
}, 0 );
|
|
};
|
|
|
|
ve.ce.CursorObserver.prototype.getOffset = function( selectionNode, selectionOffset ) {
|
|
var $leafNode = ve.ce.Surface.getLeafNode( selectionNode ),
|
|
current = [$leafNode.contents(), 0],
|
|
stack = [current],
|
|
offset = 0;
|
|
|
|
while ( stack.length > 0 ) {
|
|
if ( current[1] >= current[0].length ) {
|
|
stack.pop();
|
|
current = stack[ stack.length - 1 ];
|
|
continue;
|
|
}
|
|
var item = current[0][current[1]];
|
|
var $item = current[0].eq( current[1] );
|
|
|
|
if ( item.nodeType === 3 ) {
|
|
if ( item === selectionNode ) {
|
|
offset += selectionOffset;
|
|
break;
|
|
} else {
|
|
offset += item.textContent.length;
|
|
}
|
|
} else if ( item.nodeType === 1 ) {
|
|
if ( $( item ).attr( 'contentEditable' ) === 'false' ) {
|
|
offset += 1;
|
|
} else {
|
|
if ( item === selectionNode ) {
|
|
offset += selectionOffset;
|
|
break;
|
|
}
|
|
stack.push( [$item.contents(), 0] );
|
|
current[1]++;
|
|
current = stack[stack.length-1];
|
|
continue;
|
|
}
|
|
}
|
|
current[1]++;
|
|
}
|
|
return this.documentView.getOffsetFromNode(
|
|
$leafNode.data( 'view' )
|
|
) + 1 + offset;
|
|
};
|
|
|
|
/* Inheritance */
|
|
|
|
ve.extendClass( ve.ce.CursorObserver , ve.EventEmitter );
|