mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-15 18:39:52 +00:00
a8a5c74d8b
The phantoms prevent direct clicking into aliens, and the recent selection changes prevent keyboard navigation into aliens, but one issue remained. Clicking to place the cursor just after an alien would actually focus within the alien. Typing modified the alien content. By nesting ce="true" within ce="true", IE ceases this behavior. Dragging state is now set to false when blurring the document. The mouseup event sets dragging to false, but the event is cancelled because blur happens between mousedown and mouseup. Phantom display logic uses on this property. Change-Id: I162dea89838756fd28d63ff66cc4a5e5bda2873a
153 lines
3.4 KiB
JavaScript
153 lines
3.4 KiB
JavaScript
/*!
|
|
* VisualEditor ContentEditable AlienNode class.
|
|
*
|
|
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
*/
|
|
|
|
/**
|
|
* ContentEditable alien node.
|
|
*
|
|
* @class
|
|
* @extends ve.ce.LeafNode
|
|
* @constructor
|
|
* @param {ve.dm.AlienNode} model Model to observe
|
|
*/
|
|
ve.ce.AlienNode = function VeCeAlienNode( model ) {
|
|
// Parent constructor
|
|
ve.ce.LeafNode.call( this, model );
|
|
|
|
// DOM Changes
|
|
this.$.addClass( 've-ce-alienNode' );
|
|
|
|
// ce="false" inside of ce="true" does not prevent editing in IE
|
|
// Strangely enough, ce="true" inside of ce="true" does.
|
|
this.$.attr( 'contenteditable', !!$.browser.msie );
|
|
|
|
// Events
|
|
this.model.addListenerMethod( this, 'update', 'onUpdate' );
|
|
this.addListenerMethod( this, 'live', 'onLive' );
|
|
this.$.on( 'mouseenter', ve.bind( this.onMouseEnter, this ) );
|
|
|
|
// Initialization
|
|
this.onUpdate();
|
|
};
|
|
|
|
/* Inheritance */
|
|
|
|
ve.inheritClass( ve.ce.AlienNode, ve.ce.LeafNode );
|
|
|
|
/* Static Properties */
|
|
|
|
ve.ce.AlienNode.static.name = 'alien';
|
|
|
|
/* Methods */
|
|
|
|
/**
|
|
* Handle mouse enter events.
|
|
*
|
|
* @method
|
|
* @param {jQuery.Event} e Mouse enter event
|
|
*/
|
|
ve.ce.AlienNode.prototype.onMouseEnter = function () {
|
|
var $phantoms = $( [] ),
|
|
$phantomTemplate = ve.ce.Surface.static.$phantomTemplate,
|
|
surface = this.root.getSurface();
|
|
if ( surface.dragging ) {
|
|
return;
|
|
}
|
|
this.$.find( '.ve-ce-node-shield' ).each( function () {
|
|
var $shield = $( this ),
|
|
offset = $shield.offset();
|
|
$phantoms = $phantoms.add(
|
|
$phantomTemplate.clone().css( {
|
|
'top': offset.top,
|
|
'left': offset.left,
|
|
'height': $shield.height(),
|
|
'width': $shield.width(),
|
|
'background-position': -offset.left + 'px ' + -offset.top + 'px'
|
|
} )
|
|
);
|
|
} );
|
|
surface.replacePhantoms( $phantoms );
|
|
surface.$.on({
|
|
'mousemove.phantoms': ve.bind( this.onSurfaceMouseMove, this ),
|
|
'mouseout.phantoms': ve.bind( this.onSurfaceMouseOut, this )
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Handle live events.
|
|
*
|
|
* @method
|
|
*/
|
|
ve.ce.AlienNode.prototype.onLive = function () {
|
|
if( this.live === true ) {
|
|
var $shieldTemplate = this.constructor.static.$shieldTemplate;
|
|
this.$.add( this.$.find( '*' ) ).each( function () {
|
|
var $this = $( this );
|
|
if ( this.nodeType === Node.ELEMENT_NODE ) {
|
|
if (
|
|
( $this.css( 'float' ) === 'none' || $this.css( 'float' ) === '' ) &&
|
|
!$this.hasClass( 've-ce-alienNode' )
|
|
) {
|
|
return;
|
|
}
|
|
$this.append( $shieldTemplate.clone() );
|
|
}
|
|
} );
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Handle update events.
|
|
*
|
|
* @method
|
|
*/
|
|
ve.ce.AlienNode.prototype.onUpdate = function () {
|
|
this.$.html( this.model.getAttribute( 'html' ) );
|
|
};
|
|
|
|
/**
|
|
* Handle surface mouse move events.
|
|
*
|
|
* @method
|
|
* @param {jQuery.Event} e Mouse move event
|
|
*/
|
|
ve.ce.AlienNode.prototype.onSurfaceMouseMove = function ( e ) {
|
|
var $target = $( e.target );
|
|
if (
|
|
!$target.hasClass( 've-ce-surface-phantom' ) &&
|
|
$target.closest( '.ve-ce-alienNode' ).length === 0
|
|
) {
|
|
this.clearPhantoms();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Handle surface mouse out events.
|
|
*
|
|
* @method
|
|
* @param {jQuery.Event} e
|
|
*/
|
|
ve.ce.AlienNode.prototype.onSurfaceMouseOut = function ( e ) {
|
|
if ( e.toElement === null) {
|
|
this.clearPhantoms();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Clears all phantoms and unbinds .phantoms namespace event handlers
|
|
*
|
|
* @method
|
|
*/
|
|
ve.ce.AlienNode.prototype.clearPhantoms = function() {
|
|
var surface = this.root.getSurface();
|
|
surface.replacePhantoms( null );
|
|
surface.$.unbind( '.phantoms' );
|
|
};
|
|
|
|
/* Registration */
|
|
|
|
ve.ce.nodeFactory.register( ve.ce.AlienNode );
|