mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-29 16:44:51 +00:00
22d1908bd4
The easy part is getting the correct numbers from the InternalList and generating the ordered list HTML. The tricky part is connecting up the events to make sure the renumberings/list generations are triggered when required. InternalList can emit an update event on document transaction, which triggers the renumbering/relisting if any references have been added or deleted during that transaction. ve.ce.MWReferenceListNode also listens to changes on the InternalListNode (i.e. changes to the contents of the references) and always triggers a rebuild. Change-Id: I1b48ef5240e433c3b314259aa68cde13841ea98b
121 lines
3.3 KiB
JavaScript
121 lines
3.3 KiB
JavaScript
/*!
|
|
* VisualEditor ContentEditable MWReferenceListNode class.
|
|
*
|
|
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
*/
|
|
|
|
/**
|
|
* ContentEditable MediaWiki reference list node.
|
|
*
|
|
* @class
|
|
* @extends ve.ce.LeafNode
|
|
* @mixins ve.ce.ProtectedNode
|
|
*
|
|
* @constructor
|
|
* @param {ve.dm.MWReferenceListNode} model Model to observe
|
|
* @param {Object} [config] Config options
|
|
*/
|
|
ve.ce.MWReferenceListNode = function VeCeMWReferenceListNode( model, config ) {
|
|
// Parent constructor
|
|
ve.ce.LeafNode.call( this, model, config );
|
|
|
|
// Mixin constructors
|
|
ve.ce.ProtectedNode.call( this );
|
|
|
|
// DOM Changes
|
|
this.$.addClass( 've-ce-mwReferenceListNode', 'reference' )
|
|
.attr( 'contenteditable', false );
|
|
|
|
// Events
|
|
this.model.getDocument().internalList.connect( this, { 'update': 'onInternalListUpdate' } );
|
|
this.model.getDocument().internalList.getListNode().connect( this, { 'update': 'onListNodeUpdate' } );
|
|
|
|
// Initialization
|
|
this.update();
|
|
};
|
|
|
|
/* Inheritance */
|
|
|
|
ve.inheritClass( ve.ce.MWReferenceListNode, ve.ce.LeafNode );
|
|
|
|
ve.mixinClass( ve.ce.MWReferenceListNode, ve.ce.ProtectedNode );
|
|
|
|
/* Static Properties */
|
|
|
|
ve.ce.MWReferenceListNode.static.name = 'mwReferenceList';
|
|
|
|
/* Methods */
|
|
|
|
/**
|
|
* Handle the updating of the InternalList object.
|
|
*
|
|
* This will occur after a document transaction.
|
|
*
|
|
* @method
|
|
* @param {string[]} groupsChanged A list of groups which have changed in this transaction
|
|
*/
|
|
ve.ce.MWReferenceListNode.prototype.onInternalListUpdate = function ( groupsChanged ) {
|
|
// Only update if this group has been changed
|
|
if ( ve.indexOf( this.model.getAttribute( 'listGroup' ), groupsChanged ) !== -1 ) {
|
|
this.update();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Handle the updating of the InternalListNode.
|
|
*
|
|
* This will occur after changes to any InternalItemNode.
|
|
*
|
|
* @method
|
|
*/
|
|
ve.ce.MWReferenceListNode.prototype.onListNodeUpdate = function () {
|
|
// When the list node updates we're not sure which list group the item
|
|
// belonged to so we always update
|
|
// TODO: Only re-render the reference which has been edited
|
|
this.update();
|
|
};
|
|
|
|
/**
|
|
* Update the reference list.
|
|
*/
|
|
ve.ce.MWReferenceListNode.prototype.update = function () {
|
|
var i, j, iLen, jLen, key, keyNodes, $li, itemNode,
|
|
$ol = $( '<ol class="references">' ),
|
|
internalList = this.model.getDocument().internalList,
|
|
listGroup = this.model.getAttribute( 'listGroup' ),
|
|
nodes = internalList.getNodeGroup( listGroup );
|
|
|
|
if ( nodes && nodes.keyOrder.length ) {
|
|
for ( i = 0, iLen = nodes.keyOrder.length; i < iLen; i++ ) {
|
|
key = nodes.keyOrder[i];
|
|
keyNodes = nodes.keyNodes[key];
|
|
|
|
$li = $( '<li>' );
|
|
|
|
for ( j = 0, jLen = keyNodes.length; j < jLen; j++ ) {
|
|
if ( keyNodes.length > 1 ) {
|
|
$li.append(
|
|
$( '<sup>' ).append(
|
|
$( '<a>' ).text( ( i + 1 ) + '.' + j )
|
|
)
|
|
).append( ' ' );
|
|
}
|
|
}
|
|
|
|
// Generate reference HTML from first item in key
|
|
itemNode = new ve.ce.InternalItemNode(
|
|
internalList.getItemNode( keyNodes[0].getAttribute( 'listIndex' ) )
|
|
);
|
|
$li.append( $( '<span class="reference-text">' ).html( itemNode.$.show() ) );
|
|
$ol.append( $li );
|
|
}
|
|
} // TODO: Show a placeholder for an empty reference list in the 'else' section
|
|
|
|
this.$.html( $ol );
|
|
};
|
|
|
|
/* Registration */
|
|
|
|
ve.ce.nodeFactory.register( ve.ce.MWReferenceListNode );
|