Robmoen has uploaded a new change for review.
https://gerrit.wikimedia.org/r/108945
Change subject: WIP: TOC widget
......................................................................
WIP: TOC widget
Change-Id: I488cfbbdb060e50d81f51e0f757e67d0114b8936
---
M VisualEditor.php
M modules/ve-mw/ce/nodes/ve.ce.MWHeadingNode.js
A modules/ve-mw/ui/widgets/ve.ui.MWTocItemWidget.js
A modules/ve-mw/ui/widgets/ve.ui.MWTocSectionWidget.js
A modules/ve-mw/ui/widgets/ve.ui.MWTocWidget.js
5 files changed, 187 insertions(+), 0 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor
refs/changes/45/108945/1
diff --git a/VisualEditor.php b/VisualEditor.php
index e57bf07..6c7daf1 100644
--- a/VisualEditor.php
+++ b/VisualEditor.php
@@ -584,6 +584,9 @@
'modules/ve-mw/ui/widgets/ve.ui.MWReferenceSearchWidget.js',
'modules/ve-mw/ui/widgets/ve.ui.MWReferenceResultWidget.js',
'modules/ve-mw/ui/widgets/ve.ui.MWTitleInputWidget.js',
+ 'modules/ve-mw/ui/widgets/ve.ui.MWTocItemWidget.js',
+ 'modules/ve-mw/ui/widgets/ve.ui.MWTocSectionWidget.js',
+ 'modules/ve-mw/ui/widgets/ve.ui.MWTocWidget.js',
'modules/ve-mw/ui/pages/ve.ui.MWSettingsPage.js',
'modules/ve-mw/ui/pages/ve.ui.MWCategoriesPage.js',
diff --git a/modules/ve-mw/ce/nodes/ve.ce.MWHeadingNode.js
b/modules/ve-mw/ce/nodes/ve.ce.MWHeadingNode.js
index 053474d..fb56d21 100644
--- a/modules/ve-mw/ce/nodes/ve.ce.MWHeadingNode.js
+++ b/modules/ve-mw/ce/nodes/ve.ce.MWHeadingNode.js
@@ -27,6 +27,18 @@
ve.ce.MWHeadingNode.static.name = 'mwHeading';
+/* Methods */
+
+ve.ce.MWHeadingNode.prototype.onSetup = function () {
+ ve.ce.HeadingNode.prototype.onSetup.call( this );
+ var surface = this.root.getSurface().getSurface();
+ // Lazy load TOC widget
+ if( !( 'toc' in surface ) ) {
+ surface.toc = new ve.ui.MWTocWidget( surface );
+ }
+ surface.toc.addItem( this );
+};
+
/* Registration */
ve.ce.nodeFactory.register( ve.ce.MWHeadingNode );
diff --git a/modules/ve-mw/ui/widgets/ve.ui.MWTocItemWidget.js
b/modules/ve-mw/ui/widgets/ve.ui.MWTocItemWidget.js
new file mode 100644
index 0000000..7431d87
--- /dev/null
+++ b/modules/ve-mw/ui/widgets/ve.ui.MWTocItemWidget.js
@@ -0,0 +1,41 @@
+ve.ui.MWTocItemWidget = function VeCeMWTocItemWidget ( node, config ) {
+ OO.ui.Element.call( this, config );
+ this.node = node;
+ this.config = $.extend( { 'node': node }, config );
+ // Setup
+ this.$element.append(
+ this.$( '<span>' ).addClass( 'tocnumber' ),
+ this.$( '<span>' ).addClass( 'toctext' )
+ );
+ this.update();
+ // Events
+ this.node.model.connect( this, { 'update': 'onUpdate' } );
+ this.node.connect( this, { 'update': 'onUpdate', 'teardown':
'onTeardown' } );
+};
+
+/* Inheritance */
+
+OO.inheritClass( ve.ui.MWTocItemWidget, OO.ui.Element );
+
+/* Static Properties */
+ve.ui.MWTocItemWidget.static.tagName = 'li';
+
+ve.ui.MWTocItemWidget.prototype.onUpdate = function () {
+ // Timeout needed to let the dom element actually update
+ setTimeout( ve.bind( function () {
+ this.update();
+ }, this ), 0 );
+};
+
+ve.ui.MWTocItemWidget.prototype.update = function () {
+ this.$element
+ .addClass( 'toclevel-' + this.config.tocLevel )
+ .addClass( 'tocsection-' + this.config.tocIndex )
+ .addClass( 'tocnumber-' + this.config.tocNumber )
+ .find( '.tocnumber' ).text( this.config.sectionPrefix ).end()
+ .find( '.toctext' ).text( this.node.$element.text() );
+};
+
+ve.ui.MWTocItemWidget.prototype.onTeardown = function () {
+ this.$element.detach();
+};
diff --git a/modules/ve-mw/ui/widgets/ve.ui.MWTocSectionWidget.js
b/modules/ve-mw/ui/widgets/ve.ui.MWTocSectionWidget.js
new file mode 100644
index 0000000..1a0b78c
--- /dev/null
+++ b/modules/ve-mw/ui/widgets/ve.ui.MWTocSectionWidget.js
@@ -0,0 +1,28 @@
+//ve.ui.MWTocSectionWidget.js
+ve.ui.MWTocSectionWidget = function VeUiMWTocSectionWidget ( toc, config ) {
+ // Parent constructor
+ OO.ui.Widget.call( this, config );
+
+ // Mixin constructors
+ OO.ui.GroupElement.call( this, this.$( '<ul>' ), config );
+
+ // Properties
+ this.surface = toc.surface;
+ this.config = config;
+
+ config.$parent.append( this.$group );
+};
+
+/* Inheritance */
+
+
+OO.inheritClass( ve.ui.MWTocSectionWidget, OO.ui.Widget );
+
+OO.mixinClass( ve.ui.MWTocSectionWidget, OO.ui.GroupElement );
+
+ve.ui.MWTocSectionWidget.prototype.addItem = function ( node, config ) {
+ OO.ui.GroupElement.prototype.addItems.call( this,
+ [ new ve.ui.MWTocItemWidget( node, config ) ],
+ config.tocIndex
+ );
+};
\ No newline at end of file
diff --git a/modules/ve-mw/ui/widgets/ve.ui.MWTocWidget.js
b/modules/ve-mw/ui/widgets/ve.ui.MWTocWidget.js
new file mode 100644
index 0000000..0d2691d
--- /dev/null
+++ b/modules/ve-mw/ui/widgets/ve.ui.MWTocWidget.js
@@ -0,0 +1,103 @@
+ve.ui.MWTocWidget = function VeUiMWTocWidget ( surface, config ) {
+ // Parent constructor
+ OO.ui.Widget.call( this, config );
+
+ // Mixin constructors
+ OO.ui.GroupElement.call( this, this.$( '<ul>' ), config );
+
+ this.surface = surface;
+ this.sections = {};
+
+ surface.$element.append( this.$group.addClass( 'toc' ) );
+};
+
+/* Inheritance */
+
+OO.inheritClass( ve.ui.MWTocWidget, OO.ui.Widget );
+
+OO.mixinClass( ve.ui.MWTocWidget, OO.ui.GroupElement );
+
+/**
+ * Adds a Toc item.
+ *
+ * @method
+ * @param {ve.ce.MWHeadingNode} node mwHeading node
+ */
+ve.ui.MWTocWidget.prototype.addItem = function ( node ) {
+ var config = $.extend( { '$': this.$ }, this.getTocItemConfig( node ) ),
+ parentSectionArray, key;
+ if( config.sectionPrefix in this.sections ) {
+ // Update this guy
+ this.sections[config.sectionPrefix].$element.detach();
+ }
+ parentSectionArray = config.sectionPrefix.split( '.' );
+ parentSectionArray.pop();
+ if( parentSectionArray.length > 1 ) {
+ key = parentSectionArray.join( '.' );
+ config.$parent =
this.sections[key].items[this.sections[key].items.length-1].$element;
+ } else {
+ config.$parent = this.$group;
+ }
+ this.sections[config.sectionPrefix] = new ve.ui.MWTocSectionWidget(
this, config );
+ this.sections[config.sectionPrefix].addItem( node, config );
+};
+
+ve.ui.MWTocWidget.prototype.update = function () {
+ var section;
+ for( section in this.sections ) {
+ section.update( this.getTocItemConfig( section.node ) );
+ }
+};
+
+/**
+ * Returns item configuration for a heading node
+ *
+ * @method
+ * @param {ve.ce.MWHeadingNode} node mwHeading node
+ */
+ve.ui.MWTocWidget.prototype.getTocItemConfig = function ( node ) {
+ var doc = this.surface.getModel().getDocument(),
+ nodes = doc.selectNodes( new ve.Range( 0,
doc.getDocumentNode().getLength(), 'covered' ) ),
+ i = 0, headingLevel = 0, lastHeadingLevel = 0, tocNumber = 0,
tocLevel = 0, tocSection = 0, tocIndex = 0,
+ sectionPrefix = [];
+ for ( i; i < nodes.length - 1; i++ ) {
+ if ( nodes[i].node.parent.getType() === 'mwHeading' ) {
+ tocIndex++;
+ headingLevel = nodes[i].node.parent.getAttribute(
'level' );
+ if ( headingLevel === 1 || headingLevel === 2 &&
lastHeadingLevel !== 1 ) {
+ tocSection++;
+ sectionPrefix = [ tocSection ];
+ tocLevel = 0;
+ } else {
+ if( headingLevel === lastHeadingLevel ) {
+ tocNumber++;
+ sectionPrefix.pop();
+ sectionPrefix.push( tocNumber );
+ } else {
+ tocNumber = 1;
+ // Heading not the same as before
+ if ( headingLevel > lastHeadingLevel ) {
+ tocLevel++;
+ sectionPrefix.push( tocNumber );
+ } else if ( headingLevel <
lastHeadingLevel ) {
+ tocLevel--;
+ sectionPrefix.pop();
+ tocNumber =
sectionPrefix[sectionPrefix.length-1] + 1;
+ sectionPrefix.pop();
+ sectionPrefix.push( tocNumber );
+ }
+ }
+ }
+ if ( node.getModel() === nodes[i].node.parent ) {
+ return {
+ 'tocIndex': tocIndex--,
+ 'tocLevel': tocLevel,
+ 'tocNumber': tocNumber,
+ 'tocSection': tocSection,
+ 'sectionPrefix': sectionPrefix.join(
'.' )
+ };
+ }
+ lastHeadingLevel = headingLevel;
+ }
+ }
+};
--
To view, visit https://gerrit.wikimedia.org/r/108945
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I488cfbbdb060e50d81f51e0f757e67d0114b8936
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Robmoen <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits