User:Nikki/LexemeAddIPA.js

From Wikidata
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/* This script adds a link in the header for forms on lexeme pages which opens
   a dialog for adding IPA statements to forms which don't have any yet.
   More than one pronunciation can be added at the same time - use | (ASCII
   vertical bar/pipe character) to separate them.
   ASCII ' : and g are automatically converted into the proper IPA characters
   before saving.

   To use it, add the following line to your common.js:
   mw.loader.load("//www.wikidata.org/w/index.php?title=User:Nikki/LexemeAddIPA.js&action=raw&ctype=text/javascript");

   By default, the script only shows forms without IPA statements. To always
   show all forms, add a line in your common.js before the one which loads this
   script like so:

      addipa_alwaysshown = true;

   The script also supports adding a "pronunciation variety" (P5237) qualifier.
   To specify which qualifier to use for which language, add a line in your
   common.js before the one which loads this script like so:

      addipa_p5237 = { "Q25167": "Q6457972" };

   where Q25167 is the ID of the language item (here: Norwegian Bokmål) and
   Q6457972 is the value to use as the qualifier (here: urban East Norwegian).

   It triggers "addipa-loaded" hooks after loading and "addipa-dialog-opened"
   hooks after opening the dialog, which you can use if you would like to extend
   the script.

   License: CC0
*/
(async function () {
	"use strict";
	
	var api = new mw.Api();
	api.loadMessages(["cancel"]);
	let translations = new mw.Title("User:Nikki/translations.json").getUrl() +
		"?action=raw&ctype=application/json";
	await $.i18n().load(translations);

	function addIPA (e) {
		function IpaDialog (config) {
			IpaDialog.super.call(this, config);
			this.forms = config.forms;
		}
		OO.inheritClass(IpaDialog, OO.ui.ProcessDialog);
		IpaDialog.static.name = 'ipaDialog';
		IpaDialog.static.title = $.i18n("add-ipa");
		IpaDialog.static.actions = [
			{
				action: 'save',
				label: $.i18n("save-and-reload"),
				flags: ['primary', 'progressive'],
			},
			{
				label: mw.msg("cancel"),
				flags: ['safe', 'close'],
			},
		];

		IpaDialog.prototype.initialize = function () {
			var dialog = this;
			IpaDialog.super.prototype.initialize.apply(dialog, arguments);
			dialog.fields = [];
			for (let form in dialog.forms) {
				let input = new OO.ui.TextInputWidget({
					data: dialog.forms[form],
					classes: ["addipa-ipa-input"],
				});
				input.on("enter", function () {
					return dialog.executeAction("save");
				});
				let field = new OO.ui.FieldLayout(input, {
					label: form,
				});
				dialog.fields.push(field);
			}
			this.content = new OO.ui.PanelLayout({
				content: [new OO.ui.FieldsetLayout({
					items: dialog.fields,
				})],
				padded: true,
				expanded: false,
			});
			this.$body.append(dialog.content.$element);
		};

		IpaDialog.prototype.getActionProcess = function (action) {
			if (action == 'save') {
				var self = this;
				return new OO.ui.Process(function () {
					let data = [];
					for (let field of self.fields) {
						let input = field.getField();
						if (!input.value) // No IPA was entered for this field
							continue;

						let forms = input.data;
						for (let f of forms) {
							let obj = {"id": f, "claims":{"P898":[]}};
							for (let ipa of input.value.split("|")) {
								ipa = ipa.trim().replace(/  /g, " ").replace(/:/g, "ː").replace(/'/g, "ˈ").replace(/g/g, "ɡ");

								let claim = {"mainsnak":{"snaktype":"value","property":"P898","datavalue":{"value": ipa ,"type":"string"}},"type":"statement"};
								if (typeof addipa_p5237 !== "undefined" && addipa_p5237.hasOwnProperty(e.language)) {
									claim.qualifiers = {
										"P5237":[{"snaktype":"value","property":"P5237","datavalue":{"value":{"entity-type":"item","id": addipa_p5237[e.language] },"type":"wikibase-entityid"}}]
									};
								}
								obj.claims.P898.push(claim);
							}
							data.push(obj);
						}
					}

					var mw_api = new mw.Api();
					mw_api.postWithEditToken({
						action: "wbeditentity",
						id: e.id,
						summary: "add IPA",
						data: JSON.stringify({"forms": data})
					}).then(function (data) {
						location.reload();
					}).catch(function (err) {
						alert("Failed: " + err);
					});
				});
			} else {
				return IpaDialog.super.prototype.getActionProcess.call(this, action);
			}
		};

		IpaDialog.prototype.getBodyHeight = function () {
			return this.content.$element.outerHeight(true);
		};

		IpaDialog.prototype.getReadyProcess = function (data) {
			return IpaDialog.parent.prototype.getReadyProcess.call(this, data).next(function () {
				this.fields[0].getField().focus();
			}, this);
		};

		let forms = {};
		for (let f of e.forms) {
			// f.claims is an array when empty - T241422
			if (typeof f.claims !== "object")
				continue;
			if (f.claims["P898"] && typeof addipa_alwaysshown === "undefined")
				continue;

			let form = f.representations[ Object.keys(f.representations)[0] ].value;
			if (!forms[form])
				forms[form] = [];
			forms[form].push(f.id);
		}

		if (!Object.keys(forms).length) // All forms have IPA
			return;

		let dialog = new IpaDialog({
			forms: forms,
		});

		OO.ui.getWindowManager().addWindows([dialog]);

		$(".wikibase-lexeme-forms-section > h2.wb-section-heading").append("<span style=\"padding-left: 10px; padding-right: 10px; cursor: pointer\" id=\"addipa\" title=\"" + $.i18n("add-ipa") + "\"\>[ə]</span>");
		$("#addipa").on("click", function () {
			OO.ui.getWindowManager().openWindow(dialog);
			mw.hook("addipa-dialog-opened").fire();
		});

		mw.hook("addipa-loaded").fire();
	}

	mw.hook('wikibase.entityPage.entityView.rendered').add(function () {
	mw.hook("wikibase.entityPage.entityLoaded").add(function (e) {
		if (!e.language)
			return; // Not on a lexeme page

		mw.loader.using([
			'oojs',
			'oojs-ui-core',
			'oojs-ui-widgets',
			'oojs-ui-windows',
		]).then(function () { addIPA(e); });
	});
	});

})();