Talk:VisualEditor/Gadgets

From MediaWiki.org
Jump to: navigation, search

Better[edit]

Can you please make this document better? This is the one resource available to build VE plugins but i can't understand this article. You didn't specify exactly how to use scripts? — Preceding unsigned comment added by Santosh2201 (talkcontribs)

I rewrote some of the guide so it would be easier to understand. Please follow VisualEditor gadgets#Deployment. If you have more specific questions or suggestion I would like to hear. Eran (talk) 19:49, 22 March 2014 (UTC)

Breaking change for VisualEditor gadgets/scripts[edit]

From https://lists.wikimedia.org/pipermail/wikitech-ambassadors/2015-September/001256.html. HTH, --Elitre (WMF) (talk) 12:53, 9 September 2015 (UTC)

All, A month or so ago the main access point for VisualEditor was renamed from:

   ext.visualEditor.*viewPageTarget*.init
   ext.visualEditor.*viewPageTarget*.noscript

… to:

   ext.visualEditor.*desktopArticleTarget*.init
   ext.visualEditor.*desktopArticleTarget*.noscript

… ​ as part of our work for merging the mobile and desktop interfaces. We temporarily retained the old names as fall-backs for cached HTML purposes and to give a moment for VisualEditor gadgets and scripts to be fixed before the breaking change to their access API was moved.

This will now be merged into master today, after the cut, and so go out to production from Tuesday 15 September as part of MediaWiki 1.26wmf23. For the few gadgets and scripts that hook into VisualEditor, please switch over now so your users aren't disrupted.

J.​ -- James D. Forrester Lead Product Manager, Editing

Working with the underlying wikitext[edit]

I'm not sure whether someone here will be able to help me, but I just hope so. For some of my usecases it is much easier to work with the underlying wikitext rather than with the VE data, and this actually works pretty well so far.

To get the wikitext of the current document I use

function getWikitext (callback) {
	ve.init.target.serialize(ve.init.target.getSurface().getDom(), function (wikitext) {
		callback(wikitext);
	});
}

which works as expected.

To replace the current document with some wikitext I use

function replaceWithWikitext (wikitext) {
	var url = mw.config.get('wgVisualEditorConfig').fullRestbaseUrl +
		'v1/transform/wikitext/to/html/' +
		encodeURIComponent(mw.config.get('wgPageName'));
	$.post(url, {
		title: mw.config.get('wgPageName'),
		wikitext: wikitext
	}).done(function (html) {
		var newDoc = ve.dm.converter.getModelFromDom(ve.parseXhtml(html), {
			lang: mw.config.get('wgVisualEditor').pageLanguageCode,
			dir: mw.config.get('wgVisualEditor').pageLanguageDir
		}), surfaceModel = ve.init.target.getSurface().getModel(),
			documentModel = surfaceModel.getDocument(),
			range = documentModel.getDocumentNode().getOuterRange();
		surfaceModel.breakpoint();
		surfaceModel.change([
			ve.dm.Transaction.newFromRemoval(documentModel, range, true),
			ve.dm.Transaction.newFromDocumentInsertion(documentModel, 0, newDoc)
		]);
		surfaceModel.breakpoint();
	});
}

which almost works as expected. It changes the document to something that has a wikitext equivalent to the one I added with the function, but spaces etc. are changed.

E.g. calling

getWikitext(function (wikitext) {
	replaceWithWikitext('{{cite web|first=first name|last=last name|title=title|url=http://en.wikipedia.org}}\n\n' + wikitext);
});

will add the template at the start as expected, but will add spaces around the equal signs.

As this doesn't happen when I switch between VE and source code editor, it must be possible to add wikitext, that will be kept in the exact form that was provided. Can someone help me to fix my code to do so? And, are there chances to include these functions as helper methods for gadgets in VE, so I don't have worry about updating the duplicated code? --Schnark (talk) 10:00, 27 February 2016 (UTC)

A very hacky variant, which works in most, but not in all cases:
function replaceWithWikitext (wikitext) {
	var url = mw.config.get('wgVisualEditorConfig').fullRestbaseUrl +
		'v1/transform/wikitext/to/html/' +
		encodeURIComponent(mw.config.get('wgPageName')) + '/' +
		ve.init.target.revid;
	$.post(url, {
		title: mw.config.get('wgPageName'),
		oldid: ve.init.target.revid,
		wikitext: wikitext,
		stash: 'true'
	}).done(function (html, status, jqxhr) {
		ve.init.target.etag = jqxhr.getResponseHeader('etag');
		var newDoc = ve.dm.converter.getModelFromDom(ve.parseXhtml(html), {
			lang: mw.config.get('wgVisualEditor').pageLanguageCode,
			dir: mw.config.get('wgVisualEditor').pageLanguageDir
		}), surfaceModel = ve.init.target.getSurface().getModel(),
			documentModel = surfaceModel.getDocument(),
			range = documentModel.getDocumentNode().getOuterRange();
		surfaceModel.breakpoint();
		surfaceModel.change([
			ve.dm.Transaction.newFromRemoval(documentModel, range, true),
			ve.dm.Transaction.newFromDocumentInsertion(documentModel, 0, newDoc)
		]);
		surfaceModel.breakpoint();
	});
}
Anyone with any better ideas? --Schnark (talk) 09:11, 9 March 2016 (UTC)
Well, now with NWE I can use
function setWikitext (wikitext) {
 var target = ve.init.target;
 target.reloadSurface('visual', mw.libs.ve.targetLoader.requestParsoidData(
  target.pageName,
  target.revid,
  'schnark-tool',
  true,
  wikitext
 ));
}

function getWikitext(callback) {
 var target = ve.init.target;
 target.serialize(target.getDocToSave(), callback);
}

getWikitext(function (wikitext) {
 setWikitext('[[foo]]bar ' + wikitext);
});
But still the question: Anyone with a less hacky idea? (I.e. no message about “converting to visual mode”, possibility to undo the change.) –Schnark (talk) 09:50, 7 January 2017 (UTC)

Examples[edit]

This guide is hard to follow because it does not have little working examples. I could not succeed adding a new dummy toolbar button to visual editor toolbar this way. I ask you to expand the guide.

Also, I would like to manipulate templates in my user script. For example, find all {{myTemplate|foo=345}} templates in a section and increment the value on each, then save the wikitext back. It is not clear to me how to do that from the guide.

It is also in English only. I propose to add translations.

--Gryllida 23:59, 29 November 2016 (UTC)

Perhaps User:Schnark may be able to help here? :) --Elitre (WMF) (talk) 09:55, 30 November 2016 (UTC)
Gryllida, thank you for the comments. As for translations - you are welcome to mark relevant sections for translation with translate tag. As for dummy buttons - VisualEditor/Gadgets#Real examples for gadgets/scripts that interact with VE give some real world examples. Specifically VeExtendedBar.js in hewiki is a very simple gadget for adding a button, and pressing on it adds template. Eran (talk) 15:09, 30 November 2016 (UTC)
Well, inserting templates is pretty easy, but this is about changing them. Once I understand how to do so, this will be covered in the example VisualEditor/Gadgets/Creating a custom command (the example is about changing link annotation, but changing templates should be similar), but unfortunately I currently don't understand it yet. --Schnark (talk) 08:47, 1 December 2016 (UTC)

Adding a toolbar item to a particular group[edit]

How can I add an extra toolbar item (Tool) that I create in run time to a particular group?

If I don't specify anything, as I try in this revision, then it goes into the Insert menu, which is not quite what I want.

The toolbar groups order is specified in the configuration, which is an array. I guess I need to modify it dynamically, but how? I couldn't find it on this page or in doc.wikimedia.org.

Thanks! (Tagging @ערן: [Eran], @Matma Rex:, @ESanders (WMF):)) --Amir E. Aharoni (talk) 07:35, 28 December 2016 (UTC)

@Amire80: You can specify a group, like below. I don't think the group names are documented anywhere, you have to find them out from VE's source code, I guess. :/ For example:
 DirectionFlipTool.static.group = 'textStyle';
Matma Rex (talk) 11:27, 28 December 2016 (UTC)
Matma Rex thanks, and can I make a whole new section? For example, to make it into a whole separate button after the Special Characters button (Ω)? --Amir E. Aharoni (talk) 12:27, 29 December 2016 (UTC)
Amir E. Aharoni, have a look at https://phabricator.wikimedia.org/diffusion/ECIT/browse/master/modules/ve-cite/ve.ui.MWReference.init.js, which adds the group for inserting references. Probably a simple ve.init.mw.DesktopArticleTarget.static.toolbarGroups.push( { include: [ 'nameOfYourTool' ] } ); will work, too, in your case. –Schnark (talk) 08:47, 2 January 2017 (UTC)

Shortcut aka Accelerator[edit]

When I add a tool to a toolbar (see the section above), how can I associate an accelerator with it?

After digging in the VE source code, I managed to do this for my gadget:

ve.ui.triggerRegistry.register(
	// This emulates Firefox's shortcut for direction flipping.
	// In other browsers it's Ctrl-Shift, but it's impossible to use that.
	'DirectionFlipTool', {
		mac: new ve.ui.Trigger( 'cmd+shift+x' ),
		pc: new ve.ui.Trigger( 'ctrl+shift+x' )
	}
);

This actually adds the shortcut to the menu item, but actually pressing the keys doesn't seem to do anything. I also tried with other keys, and it didn't help.

Any idea? --Amir E. Aharoni (talk) 17:26, 30 December 2016 (UTC)

The triggerRegistry wants the name of a Command, not of a Tool. So you have to split out the code that is currently inside the onSelect method into a Command. Have a look at VisualEditor/Gadgets/Creating a custom command. –Schnark (talk) 08:53, 2 January 2017 (UTC)

Only in source (NWE) or visual mode[edit]

Is there a way to make a toolbar item appear only source mode (NWE) or only in visual mode? --Amir E. Aharoni (talk) 17:51, 30 December 2016 (UTC)

When you created the Command, you can use the isExecutable method to tell when it is not executable. This will disable the tool. Again, see VisualEditor/Gadgets/Creating a custom command. –Schnark (talk) 08:57, 2 January 2017 (UTC)