MediaWiki:FormRestorer.js

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
/**
Save form contents in a cookie, and read them from there again.

Author: [[User:Lupo]], January 2008
License: Quadruple licensed GFDL, GPL, LGPL and Creative Commons Attribution 3.0 (CC-BY-3.0)

Choose whichever license of these you like best :-)
*/
/* global FormRestorer:true */
/* eslint one-var:0, vars-on-top:0, indent:0, curly:0, space-in-parens:0, computed-property-spacing:0, array-bracket-spacing:0 */
// <nowiki>
(function () {
'use strict';
window.FormRestorer = {
	getCookie: function (cookieName) {
		if (!document.cookie || !document.cookie.length || !cookieName || !cookieName.length)
			return '';
		var start = document.cookie.indexOf(cookieName + '=');
		if (start < 0)
			return '';
		start += cookieName.length + 1;
		var end = document.cookie.indexOf(';', start);
		if (end < 0)
			return document.cookie.substring(start);
		else
			return document.cookie.substring(start, end);
	},

	saveForm: function (cookieName, formId, additionalData, cookieAttributes) {
		var form = document.getElementById(formId);
		if (!form || !form.elements || !form.elements.length)
			return;
		var cookieVal = null;
		var formVal = formId;
		if (additionalData) {
			formVal += '/=' + additionalData;
			cookieVal = '';
		}
		for (var i = 0; i < form.elements.length; i++) {
			var element = form.elements[i];
			if (element.nodeName.toLowerCase() === 'form')
				continue; // Don't do nested forms.
			var elementValue = null;
			var singleSelect = false;
			switch (element.type) {
				case 'checkbox':
				case 'radio':
					elementValue = (element.checked ? 'T' : 'F');
					break;
				case 'select-one':
					singleSelect = true;
				/* fall through*/
				// eslint-disable-next-line no-fallthrough
				case 'select-multiple':
					for (var j = 0; j < element.length; j++) {
						if (element[j].selected) {
							if (elementValue === null) {
								elementValue = String(j);
								if (singleSelect)
									break;
							} else { elementValue = elementValue + '/' + j; }
						}
					}
					break;
				// case 'file': // Is read-only anyway, we cannot set it (security policies)
				case 'text':
				case 'password':
				case 'textarea':
					elementValue = element.value;
					if (elementValue === null)
						elementValue = '';
					break;
				default:
		// We don't do 'hidden' inputs. We also don't do buttons yet. Would we need to?
					break;
			} // end switch
			if (elementValue !== null) {
				var thisItem = element.id;
				if (!thisItem || !thisItem.length)
					thisItem = element.name;
				thisItem += '/' + element.type + '=' + elementValue;
				if (!cookieVal || !cookieVal.length)
					cookieVal = thisItem;
				else
					cookieVal += '\f' + thisItem;
			}
		} // end for
		if (cookieVal) {
			document.cookie = cookieName + '=' + encodeURIComponent(formVal + '\f' + cookieVal) + (cookieAttributes || '');
		}
	},

	readForm: function (cookieName) {
		try {
			var cookie = FormRestorer.getCookie(cookieName);
			if (cookie.length < 3)
				return null;
			var pairs = decodeURIComponent(cookie).split('\f');
			if (pairs.length < 2)
				return null;
			var values = [pairs.length];
			// First one is the form id
			for (var i = 0; i < pairs.length; i++) {
				var j = pairs[i].indexOf('=');
				var k = pairs[i].lastIndexOf('/', j);
				if (j < 0 || k < 0) {
					values[i] = null;
					continue;
				}
				var elementName = pairs[i].substring(0, k);
				var elementType = pairs[i].substring(k + 1, j);
				var val = pairs[i].substring(j + 1);
				var value = null;
				switch (elementType) {
					case 'checkbox':
					case 'radio':
						value = (val === 'T');
						break;
					case 'select-one':
						value = Number(val);
						break;
					case 'select-multiple': {
						var numbers = val.split('/');
						value = [numbers.length];
						for (j = 0; j < numbers.length; j++)
							value[j] = Number(numbers[j]);
					}
						break;
					default:
						value = val;
						break;
				} // end switch
				values[i] = {
					id: elementName,
					type: elementType,
					val: value
				};
			} // end for
			return values;
		} catch (error) {
			return null;
		}
	}
}; // end FormRestorer
}()); 
// </nowiki>