Mooeypoo has uploaded a new change for review. https://gerrit.wikimedia.org/r/78925
Change subject: [WIP] LanguageBlock Inspector ...................................................................... [WIP] LanguageBlock Inspector Adding a <div> element with lang/dir attributes around blocks of content. This is still work in progress. Current problem: ve.dm.LanguageBlockNode doesn't have 'attributes' accessible despite the fact I'm setting them up in the definition. I'm not sure why. This stops the addition of the node to the widget (which will be added after I solve this issue). Change-Id: Ic40f4265792a227a70460d865e251d4a80c0064c --- M VisualEditor.i18n.php M VisualEditor.php M modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js M modules/ve/init/ve.init.Target.js A modules/ve/ui/actions/ve.ui.LanguageBlockAction.js A modules/ve/ui/inspectors/ve.ui.LanguageBlockInspector.js A modules/ve/ui/tools/buttons/ve.ui.LanguageBlockButtonTool.js 7 files changed, 304 insertions(+), 2 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor refs/changes/25/78925/1 diff --git a/VisualEditor.i18n.php b/VisualEditor.i18n.php index b992b1e..e488c33 100644 --- a/VisualEditor.i18n.php +++ b/VisualEditor.i18n.php @@ -135,6 +135,8 @@ 'visualeditor-mwalienextensioninspector-title' => 'MediaWiki extension', 'visualeditor-mwhieroinspector-title' => 'Hieroglyphics', 'visualeditor-mwmathinspector-title' => 'LaTeX', + 'visualeditor-languageblock-tooltip' => 'Language Block', + 'visualeditor-languageblock-inspector-title' => 'Language Block', 'visualeditor-languageinspector-title' => 'Language', 'visualeditor-languageinspector-block-tooltip' => 'Language block: $1', 'visualeditor-languageinspector-block-tooltip-rtldirection' => ': Right to Left', @@ -438,6 +440,8 @@ 'visualeditor-mwmathinspector-title' => 'Used as title for MathInspector. See [[w:LaTeX]].', + 'visualeditor-languageblock-tooltip' => 'Tooltip text for language block button', + 'visualeditor-languageblock-inspector-title' => 'Title of the language block inspector dialog', 'visualeditor-languageinspector-title' => 'Title of the language inspector dialog. {{Identical|Language}}', 'visualeditor-languageinspector-block-tooltip' => 'Tooltip identifying language block properties inside VisualEditor. Parameters: $1 - the language code (for example "en")', diff --git a/VisualEditor.php b/VisualEditor.php index e5007a7..438997d 100644 --- a/VisualEditor.php +++ b/VisualEditor.php @@ -734,6 +734,9 @@ 've/ui/tools/buttons/ve.ui.StrikethroughButtonTool.js', 've/ce/nodes/ve.ce.LanguageBlockNode.js', 've/dm/nodes/ve.dm.LanguageBlockNode.js', + 've/ui/tools/buttons/ve.ui.LanguageBlockButtonTool.js', + 've/ui/inspectors/ve.ui.LanguageBlockInspector.js', + 've/ui/actions/ve.ui.LanguageBlockAction.js', ), 'dependencies' => array( 'ext.visualEditor.core', @@ -746,6 +749,8 @@ 'visualeditor-mwmathinspector-title', 'visualeditor-annotationbutton-language-tooltip', 'visualeditor-annotationbutton-strikethrough-tooltip', + 'visualeditor-languageblock-tooltip', + 'visualeditor-languageblock-inspector-title', ), ), diff --git a/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js b/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js index 16b7d41..8ffeb73 100644 --- a/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js +++ b/modules/ve-mw/init/targets/ve.init.mw.ViewPageTarget.js @@ -171,7 +171,7 @@ { 'items': [ 'undo', 'redo' ] }, { 'items': [ 'mwFormat' ] }, { 'items': [ 'bold', 'italic', 'mwLink', 'language', 'code', 'strikethrough', 'clear' ] }, - { 'items': [ 'number', 'bullet', 'outdent', 'indent' ] }, + { 'items': [ 'number', 'bullet', 'outdent', 'indent', 'languageblock' ] }, { 'items': [ 'mwMediaInsert', 'mwReference', 'mwReferenceList', 'mwTransclusion', 'mwMath', 'mwHiero' ] } ]; diff --git a/modules/ve/init/ve.init.Target.js b/modules/ve/init/ve.init.Target.js index 28c246d..74d0a6c 100644 --- a/modules/ve/init/ve.init.Target.js +++ b/modules/ve/init/ve.init.Target.js @@ -33,7 +33,7 @@ { 'items': ['undo', 'redo'] }, { 'items': ['format'] }, { 'items': ['bold', 'italic', 'link', 'code', 'language', 'strikethrough', 'clear'] }, - { 'items': ['number', 'bullet', 'outdent', 'indent'] } + { 'items': ['number', 'bullet', 'outdent', 'indent', 'languageblock'] } ]; ve.init.Target.static.surfaceCommands = [ diff --git a/modules/ve/ui/actions/ve.ui.LanguageBlockAction.js b/modules/ve/ui/actions/ve.ui.LanguageBlockAction.js new file mode 100644 index 0000000..240d0d6 --- /dev/null +++ b/modules/ve/ui/actions/ve.ui.LanguageBlockAction.js @@ -0,0 +1,147 @@ +/*! + * VisualEditor UserInterface LanguageBlockAction class. + * + * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt + * @license The MIT License (MIT); see LICENSE.txt + */ + +/** + * List action. + * + * @class + * @extends ve.ui.Action + * @constructor + * @param {ve.ui.Surface} surface Surface to act on + */ +ve.ui.LanguageBlockAction = function VeUiLanguageBlockAction( surface ) { + // Parent constructor + ve.ui.Action.call( this, surface ); +}; + +/* Inheritance */ + +ve.inheritClass( ve.ui.LanguageBlockAction, ve.ui.Action ); + +/* Static Properties */ + +/** + * List of allowed methods for the action. + * + * @static + * @property + */ +ve.ui.LanguageBlockAction.static.methods = ['wrap', 'unwrap']; + +/* Methods */ + +/** + * Add a languageblock div around content. + * + ******************************************************************* + ******************************************************************* + ******************************************************************* + ******************************************************************* + * This entire method (and the 'unwrap' method) should be completely + * rewritten + ******************************************************************* + ******************************************************************* + ******************************************************************* + ******************************************************************* + * + * @method + * @param {string} attrs - the lang/dir attributes + */ +ve.ui.LanguageBlockAction.prototype.wrap = function ( attrs ) { + var tx, i, previousList, groupRange, group, + surfaceModel = this.surface.getModel(), + documentModel = surfaceModel.getDocument(), + selection = surfaceModel.getSelection(), + groups; + + surfaceModel.breakpoint(); + + console.log( attrs ); + if ( + selection.isCollapsed() && + !documentModel.data.isContentOffset( selection.to ) && + this.surface.view.documentView.getSlugAtOffset( selection.to ) + ) { + // Inside block level slug + surfaceModel.change( ve.dm.Transaction.newFromInsertion( + documentModel, + selection.from, + [ + { 'type': 'languageblock', 'attributes': attrs }, + ] + ), new ve.Range( selection.to + 3 ) ); + } else { + groups = documentModel.getCoveredSiblingGroups( selection ); + for ( i = 0; i < groups.length; i++ ) { + group = groups[i]; + if ( group.grandparent && group.grandparent.getType() === 'languageblock' ) { + if ( group.grandparent !== previousList ) { + // Change the list style + surfaceModel.change( + ve.dm.Transaction.newFromAttributeChanges( + documentModel, group.grandparent.getOffset(), { 'attributes': attrs } + ), + selection + ); + // Skip this one next time + previousList = group.grandparent; + } + } else { + // Get a range that covers the whole group + groupRange = new ve.Range( + group.nodes[0].getOuterRange().start, + group.nodes[group.nodes.length - 1].getOuterRange().end + ); + // Convert everything to paragraphs first +// surfaceModel.change( +// ve.dm.Transaction.newFromContentBranchConversion( +// documentModel, groupRange, 'paragraph' +// ), +// selection +// ); + // Wrap everything in a div and each content branch in a listItem + tx = ve.dm.Transaction.newFromWrap( + documentModel, + groupRange, + [], + [{ 'type': 'languageblock', 'attributes': attrs }], + [], + [] + ); + surfaceModel.change( tx, tx.translateRange( selection ) ); + } + } + } + surfaceModel.breakpoint(); +}; + +/** + * Remove list around content. + * + * TODO: Refactor functionality into {ve.dm.SurfaceFragment}. + * + * @method + */ +ve.ui.LanguageBlockAction.prototype.unwrap = function () { + var node, + surfaceModel = this.surface.getModel(), + documentModel = surfaceModel.getDocument(); + + surfaceModel.breakpoint(); + + node = documentModel.getNodeFromOffset( surfaceModel.getSelection().start ); +// while ( node.hasMatchingAncestor( 'languageblock' ) ) { + // this.surface.execute( 'indentation', 'decrease' ); +// node = documentModel.getNodeFromOffset( surfaceModel.getSelection().start ); +// } + + surfaceModel.breakpoint(); +}; + +/* Registration */ + +ve.ui.actionFactory.register( 'languageblock', ve.ui.LanguageBlockAction ); \ No newline at end of file diff --git a/modules/ve/ui/inspectors/ve.ui.LanguageBlockInspector.js b/modules/ve/ui/inspectors/ve.ui.LanguageBlockInspector.js new file mode 100644 index 0000000..9d992d3 --- /dev/null +++ b/modules/ve/ui/inspectors/ve.ui.LanguageBlockInspector.js @@ -0,0 +1,103 @@ +/*! + * VisualEditor UserInterface MWExtensionInspector class. + * + * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt + * @license The MIT License (MIT); see LICENSE.txt + */ + +/** + * MediaWiki language block inspector. + * + * @class + * @abstract + * @extends ve.ui.Inspector + * + * @constructor + * @param {ve.ui.Surface} surface + * @param {Object} [config] Config options + */ +ve.ui.LanguageBlockInspector = function VeUiLanguageBlockInspectorInspector( surface, config ) { + // Parent constructor + ve.ui.Inspector.call( this, surface, config ); + + this.initLang = ''; + this.initDir = ''; +}; + +/* Inheritance */ + +ve.inheritClass( ve.ui.LanguageBlockInspector, ve.ui.Inspector ); + +/* Static properties */ + +ve.ui.LanguageBlockInspector.static.nodeView = ve.ce.LanguageBlockNode; + +ve.ui.LanguageBlockInspector.static.nodeModel = ve.dm.LanguageBlockNode; + +// TODO: Figure out a better icon: +ve.ui.LanguageBlockInspector.static.icon = 'language'; + +ve.ui.LanguageBlockInspector.static.titleMessage = 'visualeditor-languageblock-inspector-title'; + +/* Methods */ + +/** + * Handle frame ready events. + * + * @method + */ +ve.ui.LanguageBlockInspector.prototype.initialize = function () { + // Parent method + ve.ui.Inspector.prototype.initialize.call( this ); + + // Properties + this.input = new ve.ui.LanguageInputWidget( { + '$$': this.frame.$$, + '$overlay': this.surface.$localOverlay + } ); + + // Define as node: + this.input.dataType = 'node'; + + // Initialization + this.$form.append( this.input.$ ); + this.input.$.addClass( 've-ui-languageBlockInspector-input' ); + + // Initialization + this.$form.append( this.input.$ ); +}; + + +/** + * Handle the inspector being opened. + */ +ve.ui.LanguageBlockInspector.prototype.onOpen = function () { + var selectionNode, langBlockDOM, newNode; + // Parent method + ve.ui.Inspector.prototype.onOpen.call( this ); + + selectionNode = this.surface.getView().documentView.getNodeFromOffset( this.initialSelection.start ); + + langBlockDOM = selectionNode.$.closest( 'div[lang]' ) || selectionNode.$.closest( 'div[dir]' ); + + newNode = new ve.dm.LanguageBlockNode({ + 'type': 'languageblock', + 'attributes': { + 'lang': langBlockDOM.attr( 'lang' ) || '', + 'dir': langBlockDOM.css( 'direction' ) + } + }); + + // Something's wrong here with 'newNode' + // for some reason, the attributes aren't accessible! + console.log( newNode ); + + // Wait for animation to complete +/* setTimeout( ve.bind( function () { + // Setup initial node: + this.input.setNode( newNode ); + }, this ), 200 );*/ +}; + +/* Registration */ +ve.ui.inspectorFactory.register( 'languageblock', ve.ui.LanguageBlockInspector ); \ No newline at end of file diff --git a/modules/ve/ui/tools/buttons/ve.ui.LanguageBlockButtonTool.js b/modules/ve/ui/tools/buttons/ve.ui.LanguageBlockButtonTool.js new file mode 100644 index 0000000..513bdd3 --- /dev/null +++ b/modules/ve/ui/tools/buttons/ve.ui.LanguageBlockButtonTool.js @@ -0,0 +1,43 @@ +/*! + * VisualEditor UserInterface LanguageButtonTool class. + * + * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt + * @license The MIT License (MIT); see LICENSE.txt + */ + +/** + * UserInterface language block button tool. + * + * @class + * @extends ve.ui.InspectorButtonTool + * @constructor + * @param {ve.ui.SurfaceToolbar} toolbar + * @param {Object} [config] Config options + */ +ve.ui.LanguageBlockButtonTool = function VeUiLanguageBlockButtonTool( toolbar, config ) { + // Parent constructor + ve.ui.InspectorButtonTool.call( this, toolbar, config ); +}; + +/* Inheritance */ + +ve.inheritClass( ve.ui.LanguageBlockButtonTool, ve.ui.InspectorButtonTool ); + +/* Static Properties */ + +ve.ui.LanguageBlockButtonTool.static.name = 'languageblock'; + +// TODO: replace this icon with something more suitable: +ve.ui.LanguageBlockButtonTool.static.icon = 'language'; + +ve.ui.LanguageBlockButtonTool.static.titleMessage = 'visualeditor-annotationbutton-languageblock-tooltip'; + +ve.ui.LanguageBlockButtonTool.static.inspector = 'languageblock'; + +ve.ui.LanguageBlockButtonTool.static.modelClasses = [ ve.dm.LanguageBlockNode ]; + +/* Registration */ + +ve.ui.toolFactory.register( 'languageblock', ve.ui.LanguageBlockButtonTool ); + +ve.ui.commandRegistry.register( 'languageblock', 'inspector', 'open', 'languageblock' ); \ No newline at end of file -- To view, visit https://gerrit.wikimedia.org/r/78925 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ic40f4265792a227a70460d865e251d4a80c0064c Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/VisualEditor Gerrit-Branch: master Gerrit-Owner: Mooeypoo <mor...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits