User:BrandonXLF/FloatingTOC.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
/*** Floating TOC ***/

// Adds a floating TOC to the page
// Documentation at [[en:w:User:BrandonXLF/FloatingTOC]]
// By [[en:w:User:BrandonXLF]]

$(function() {
	var data = JSON.parse(mw.user.options.get('userjs-floatingtoc') || '{}'),
		toc2 = (data.remove ? $('#toc') : $('#toc').clone().attr('id', 'toc2'))
			.addClass('floatingtoc')
			.css({
				position: 'fixed',
				left: data.left ? 10 : undefined,
				right: data.left ? undefined : 10,
				bottom: 10,
				maxHeight: '70vh',
				maxWidth: '30em',
				overflow: 'auto',
				display: 'block',
				zIndex: 999
			})
			.appendTo(mw.util.$content.find('.mw-parser-output'));

	toc2.find('#toctogglecheckbox').attr('id', 'toctogglecheckbox2').prop('checked', !data.expand);
	!data.remove && $('#toc').find('#toctogglecheckbox').prop('checked', !!data.hide);
	toc2.find('[for="toctogglecheckbox"]').attr('for', 'toctogglecheckbox2');
	toc2.find('h2').before('[', $('<a href="#">edit</a>').click(function(e) {
		var expand = new OO.ui.CheckboxInputWidget().setSelected(data.expand),
			hide = new OO.ui.CheckboxInputWidget().setSelected(data.hide),
			remove = new OO.ui.CheckboxInputWidget().setSelected(data.remove),
			left = new OO.ui.CheckboxInputWidget().setSelected(data.left);

		e.preventDefault();
		function ProcessDialog(config) {
			ProcessDialog.super.call(this, config);
		}

		OO.inheritClass(ProcessDialog, OO.ui.ProcessDialog);

		ProcessDialog.static.name = 'floatingtoc-settings';
		ProcessDialog.static.title = 'Floating TOC Settings';
		ProcessDialog.static.actions = [
			{
				action: 'save',
				label: 'Save',
				flags: ['primary', 'progressive']
			},
			{
				label: 'Cancel',
				flags: 'safe'
			}
		];
		ProcessDialog.prototype.initialize = function() {
			ProcessDialog.super.prototype.initialize.apply(this, arguments);
			this.content = new OO.ui.PanelLayout({
				padded: true,
				expanded: false
			});
			this.content.$element.append(
				(new OO.ui.FieldLayout(expand, {
					align: 'inline',
					label: 'Expand the floating TOC by default'
				})).$element
			);
			this.content.$element.append(
				(new OO.ui.FieldLayout(hide, {
					align: 'inline',
					label: 'Hide the inline TOC by default'
				})).$element
			);
			this.content.$element.append(
				(new OO.ui.FieldLayout(remove, {
					align: 'inline',
					label: 'Remove the inline TOC'
				})).$element
			);
			this.content.$element.append(
				(new OO.ui.FieldLayout(left, {
					align: 'inline',
					label: 'Move the floating TOC of the left'
				})).$element
			);
			this.$body.append(this.content.$element);
		};

		ProcessDialog.prototype.getActionProcess = function(action) {
			var dialog = this;
			if (action) {
				return new OO.ui.Process(function() {
					var saveDeferred = $.Deferred(),
						api = new mw.Api();
					data = {
						remove: remove.isSelected(),
						expand: expand.isSelected(),
						hide: hide.isSelected(),
						left: left.isSelected()
					};
					api.saveOption('userjs-floatingtoc', JSON.stringify(data)).then(function() {
						saveDeferred.resolve();
						mw.user.options.set('userjs-floatingtoc', JSON.stringify(data));
						dialog.close();
					}, function(_, data) {
						saveDeferred.reject([new OO.ui.Error(api.getErrorMessage(data), {recoverable: false})]);
					});
					return saveDeferred.promise();
				});
			}
			return new OO.ui.Process(function() {
				dialog.close();
			});
		};

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

		var windowManager = new OO.ui.WindowManager(),
			processDialog = new ProcessDialog({
				size: 'large'
			});

		$(document.body).append(windowManager.$element);

		windowManager.addWindows([processDialog]);
		windowManager.openWindow(processDialog);
	}), '] ');

	if (!$('.toctogglelabel').length) {
		mw.loader.load('mediawiki.toc.styles');
		toc2.find('.toctitle').before('<input type="checkbox" role="button" id="addedtoccheck" class="toctogglecheckbox" style="display:none">');
		toc2.find('.toctitle h2').before($('<span class="toctogglespan">').append('<label class="toctogglelabel" for="addedtoccheck"></label>'));
	}
});