mediawiki-extensions-Visual.../modules/ve-mw/ce/nodes/ve.ce.MWReferenceNode.js
Marc Ordinas i Llopis 7a33613d23 Use Parsoid's new Cite HTML and CSS
Starting with I21fbbd3247bf7801e5ef9bd5312f95777f4dd6ef, Parsoid
will emit a new HTML for its Cite extension, which enables CSS
styling. In I487095df8a7c4241a14f7b4480360f6774130bec the new
module 'ext.cite.style' is added to the Cite extension to style
this new HTML format.

This patch
* Loads the ext.cite.style module if the Cite extension is
  present.
* Uses the new HTML format for the internal structure of
  reference and reference list nodes, so they are correctly
  styled.

Backwards compatibility: Only new HTML is used internally in VE,
so as long as ext.cite.style can be loaded the new styles will be
used. It does not depend on which format Parsoid returns, so this
patch only depends on the Cite extension patch, not on the Parsoid
one.

Note: The only way I've found of adding a ext.cite.style dependency
only if Cite is present is to register the whole
ext.visualEditor.mwreference module in the
onResourceLoaderRegisterModules hook. Maybe someone can point to
a better way?

Bug: T86782
Change-Id: Ibf333a502d64d2ed6e029221458b7c606554e414
2015-07-06 14:23:18 -07:00

134 lines
3.6 KiB
JavaScript

/*!
* VisualEditor ContentEditable MWReferenceNode class.
*
* @copyright 2011-2015 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* ContentEditable MediaWiki reference node.
*
* @class
* @extends ve.ce.LeafNode
* @mixins ve.ce.FocusableNode
*
* @constructor
* @param {ve.dm.MWReferenceNode} model Model to observe
* @param {Object} [config] Configuration options
*/
ve.ce.MWReferenceNode = function VeCeMWReferenceNode( model, config ) {
// Parent constructor
ve.ce.LeafNode.call( this, model, config );
// Mixin constructors
ve.ce.FocusableNode.call( this );
// DOM changes
this.$link = $( '<a>' ).attr( 'href', '#' );
this.$element.addClass( 've-ce-mwReferenceNode mw-ref' ).append( this.$link )
// In case we have received a version with old-style Cite HTML, remove the
// old reference class
.removeClass( 'reference' );
// Add a backwards-compatible text for browsers that don't support counters
this.$text = $( '<span>' ).addClass( 'mw-reflink-text' );
this.$link.append( this.$text );
this.index = '';
this.internalList = this.model.getDocument().internalList;
// Events
this.connect( this, { setup: 'onSetup' } );
this.connect( this, { teardown: 'onTeardown' } );
// Initialization
this.update();
};
/* Inheritance */
OO.inheritClass( ve.ce.MWReferenceNode, ve.ce.LeafNode );
OO.mixinClass( ve.ce.MWReferenceNode, ve.ce.FocusableNode );
/* Static Properties */
ve.ce.MWReferenceNode.static.name = 'mwReference';
ve.ce.MWReferenceNode.static.tagName = 'span';
ve.ce.MWReferenceNode.static.primaryCommandName = 'reference';
/* Methods */
/**
* Handle setup event.
* @method
*/
ve.ce.MWReferenceNode.prototype.onSetup = function () {
ve.ce.MWReferenceNode.super.prototype.onSetup.call( this );
this.internalList.connect( this, { update: 'onInternalListUpdate' } );
};
/**
* Handle teardown event.
* @method
*/
ve.ce.MWReferenceNode.prototype.onTeardown = function () {
// As we are listening to the internal list, we need to make sure
// we remove the listeners when this object is removed from the document
this.internalList.disconnect( this );
ve.ce.MWReferenceNode.super.prototype.onTeardown.call( this );
};
/**
* 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.MWReferenceNode.prototype.onInternalListUpdate = function ( groupsChanged ) {
// Only update if this group has been changed
if ( groupsChanged.indexOf( this.model.getAttribute( 'listGroup' ) ) !== -1 ) {
this.update();
}
};
/**
* Handle update events.
*
* @method
*/
ve.ce.MWReferenceNode.prototype.update = function () {
var group = this.model.getGroup();
this.$text.text( this.model.getIndexLabel() );
this.$link.css( 'counterReset', 'mw-Ref ' + this.model.getIndex() );
if ( group ) {
this.$link.attr( 'data-mw-group', group );
} else {
this.$link.removeAttr( 'data-mw-group' );
}
};
/** */
ve.ce.MWReferenceNode.prototype.createHighlights = function () {
// Mixin method
ve.ce.FocusableNode.prototype.createHighlights.call( this );
if ( !this.getModel().isInspectable() ) {
// TODO: Move this into one of the classes mixin or inherit from
// as any focusable node that isn't inspectable should have this
// as it would be bad UX to have a focusable nodes where one of the
// same type doesn't show an inspector.
this.$highlights
.addClass( 've-ce-mwReferenceNode-missingref' )
.attr( 'title', ve.msg( 'visualeditor-referenceslist-missingref' ) );
}
};
/* Registration */
ve.ce.nodeFactory.register( ve.ce.MWReferenceNode );