Allow phantoms and focus areas to be overridden

And actually use this functionality on MWBlockImage to
highlight centred images correctly.

FocusableNode
* Actually use $focusable to render the highlight correctly

ProtectedNode
* Allow a $phantomable element to define which element to
  highlight on mouseenter
* As phatoms are built off shields, make sure a shield is
  given to $phantomable

RelocatableNode
* Allow a $relocatable element to define which element the
  relocatable marker is measured against

ui.Context
* Use $focusable (when available) for positioning the popup

Plus some documentation fixes

Change-Id: I370337239af4fc935cd86757b3ce03011bae5ba8
This commit is contained in:
Ed Sanders 2013-08-19 16:22:29 +01:00
parent 88504aa3d9
commit 2d720bd6d9
4 changed files with 21 additions and 15 deletions

View file

@ -6,7 +6,7 @@
*/
/**
* ContentEditable resizable node.
* ContentEditable focusable node.
*
* Focusable elements have a special treatment by ve.ce.Surface. When the user selects only a single
* node, if it is focusable, the surface will set the focusable node's focused state. Other systems,
@ -22,7 +22,7 @@
* @abstract
*
* @constructor
* @param {jQuery} [$focusable] Primary element user is focusing on
* @param {jQuery} [$focusable=this.$] Primary element user is focusing on
*/
ve.ce.FocusableNode = function VeCeFocusableNode( $focusable ) {
// Properties
@ -135,11 +135,11 @@ ve.ce.FocusableNode.prototype.setFocused = function ( value ) {
this.focused = value;
if ( this.focused ) {
this.emit( 'focus' );
this.$.addClass( 've-ce-node-focused' );
this.$focusable.addClass( 've-ce-node-focused' );
this.createHighlight();
} else {
this.emit( 'blur' );
this.$.removeClass( 've-ce-node-focused' );
this.$focusable.removeClass( 've-ce-node-focused' );
this.clearHighlight();
}
}
@ -151,7 +151,7 @@ ve.ce.FocusableNode.prototype.setFocused = function ( value ) {
* @method
*/
ve.ce.FocusableNode.prototype.createHighlight = function () {
this.$.find( '*' ).add( this.$ ).each(
this.$focusable.find( '*' ).add( this.$focusable ).each(
ve.bind( function( i, element ) {
var offset, $element = $( element );
if ( !$element.is( ':visible' ) ) {

View file

@ -6,17 +6,19 @@
*/
/**
* ContentEditable relocatable node.
* ContentEditable protected node.
*
* @class
* @abstract
*
* @constructor
* @param {jQuery} [$phantomable=this.$] Element to show a phantom for
*/
ve.ce.ProtectedNode = function VeCeProtectedNode() {
ve.ce.ProtectedNode = function VeCeProtectedNode( $phantomable ) {
// Properties
this.$phantoms = $( [] );
this.$shields = $( [] );
this.$phantomable = $phantomable || this.$;
this.isSetup = false;
// Events
@ -89,7 +91,9 @@ ve.ce.ProtectedNode.prototype.onProtectedSetup = function () {
if ( this.nodeType === Node.ELEMENT_NODE ) {
if (
( $this.css( 'float' ) === 'none' || $this.css( 'float' ) === '' ) &&
!$this.hasClass( 've-ce-protectedNode' )
!$this.hasClass( 've-ce-protectedNode' ) &&
// Phantoms are built off shields, so make sure $phantomable has a shield
!$this.is( node.$phantomable )
) {
return;
}
@ -210,7 +214,7 @@ ve.ce.ProtectedNode.prototype.createPhantoms = function () {
var $phantomTemplate = this.constructor.static.$phantomTemplate,
surface = this.root.getSurface();
this.$.find( '.ve-ce-protectedNode-shield' ).each(
this.$phantomable.find( '.ve-ce-protectedNode-shield' ).each(
ve.bind( function () {
this.$phantoms = this.$phantoms.add(
$phantomTemplate.clone().on( 'mousedown', ve.bind( this.onPhantomMouseDown, this ) )
@ -232,7 +236,7 @@ ve.ce.ProtectedNode.prototype.createPhantoms = function () {
* @method
*/
ve.ce.ProtectedNode.prototype.positionPhantoms = function () {
this.$.find( '.ve-ce-protectedNode-shield' ).each(
this.$phantomable.find( '.ve-ce-protectedNode-shield' ).each(
ve.bind( function ( i, element ) {
var $shield = $( element ),
offset = ve.Element.getRelativePosition(

View file

@ -14,10 +14,12 @@
* @abstract
*
* @constructor
* @param {jQuery} [$relocatable=this.$] Element which can be relocated
*/
ve.ce.RelocatableNode = function VeCeRelocatableNode() {
ve.ce.RelocatableNode = function VeCeRelocatableNode( $relocatable ) {
// Properties
this.relocatingSurface = null;
this.$relocatable = $relocatable || this.$;
this.$relocatableMarker = this.$$( '<img>' );
// Events
@ -125,12 +127,12 @@ ve.ce.RelocatableNode.prototype.onRelocatableDragEnd = function () {
*/
ve.ce.RelocatableNode.prototype.setRelocatableMarkerSizeAndPosition = function () {
var offset = ve.Element.getRelativePosition(
this.$, this.getRoot().getSurface().getSurface().$
this.$relocatable, this.getRoot().getSurface().getSurface().$
);
this.$relocatableMarker.css( {
'height': this.$.height(),
'width': this.$.width(),
'height': this.$relocatable.height(),
'width': this.$relocatable.width(),
'top': offset.top,
'left': offset.left
} );

View file

@ -255,7 +255,7 @@ ve.ui.Context.prototype.updateDimensions = function ( transition ) {
$container = inspector ? this.inspectors.$ : this.$menu;
if ( focusedNode ) {
// We're on top of a node
$node = focusedNode.$;
$node = focusedNode.$focusable || focusedNode.$;
nodePosition = $node.position();
if ( this.embedded ) {
// Get the position relative to the surface it is embedded in