Object backup

Allows users to backup and restore the localStorage by typing "backup" into the console

Click here to install Browse More Scripts
// ==UserScript==
// @name         Object backup
// @namespace    1a720a78dfc854aac465944cd881fe5dabfa9d0e
// @version      0.4
// @description  Allows users to backup and restore the localStorage by typing "backup" into the console
// @author       /u/AyrA_ch
// @include      http://*
// @include      https://*
// @grant        none
// ==/UserScript==

//Changelog
// 0.1 - Initial Release
// 0.2 - Add CSS to make it readable on conflicting styles from body.
// 0.3 - No longer adding div immediately to body.
// 0.4 - Fix unreadable text when using dark bootstrap theme
(function () {
	"use strict";

	var btnStyle = "font-size:12pt;font-family:sans-serif;width:100%;display:block;margin-top:5px;padding:5px;";

	var shown = false;

	//implement JSON.tryParse.
	//Instead of crashing on invalid JSON strings, it returns undefined
	if (typeof(JSON.tryParse) != typeof(window.alert)) {
		JSON.tryParse = function (a, b, c) {
			if (typeof(a) === typeof("") || typeof(a) === typeof(1)) {
				try {
					return JSON.parse(a, b, c);
				} catch (e) {
					window.console.warn("attempt to convert invalid JSON\r\n", a.substr(0, 200), e);
				}
			} else {
				window.console.warn("attempt to convert invalid JSON (not a string)\r\n", typeof(a));
			}
		};
	}

	//Renders a div using proper DOM instead of just doing "innerHTML+=..." because that will erase event handlers
	var renderDiv = function () {
		//generate new random ID each time we do this
		var randID = "backupEle_" + (Math.random() * 1000000 | 0);

		//create DIV element for user control
		var div = document.createElement("div");
		//We set many attributes to override conflicting defaults from the sites stylesheet
		div.setAttribute("style",
			"all:unset;z-index:" + Number.MAX_SAFE_INTEGER + ";position:fixed;" +
			"padding:10px;background-color:#FFFFFF;color:#000000;background-image:none;" +
			"border:2px solid #000000;border-radius:5px;width:500px;height:auto;" +
			"left:10px;top:10px;right:auto;bottom:auto;");
		div.setAttribute("id", randID);

		//file input control for user upload of json file
		var inpFile = document.createElement("input");
		inpFile.setAttribute("type", "file");
		inpFile.setAttribute("accept", "application/json,.json,.js,text/json,text/javascript");
		//Even though we hide the control, we can still trigger it by calling ".click()"
		inpFile.style.display = "none";

		//This will parse the uploaded file
		inpFile.addEventListener("change", function (e) {
			var f = e.target && e.target.files[0];
			if (f) {
				var fr = new FileReader();
				fr.onloadend = function (e) {
					var fileData = JSON.tryParse(e.result || e.currentTarget.result);
					if (fileData) {
						localStorage.clear();
						for (var x in fileData) {
							localStorage.setItem(x, fileData[x]);
						}
						//It is usually a good idea to reload the site after changing the localStorage object
						if (confirm("localStorage restored. Reload site?")) {
							location.reload();
						}
					} else {
						console.error("No file data to restore localStorage with. Invalid file?");
					}
				};
				fr.readAsText(f);
			}
		}, false);

		div.appendChild(inpFile);

		//Backup button
		var btnBackup = document.createElement("input");
		btnBackup.setAttribute("type", "button");
		btnBackup.value = "Backup localStorage";
		btnBackup.setAttribute("style", btnStyle);
		btnBackup.addEventListener("click", function () {
			window.backup.backup();
		}, false);
		div.appendChild(btnBackup);

		div.appendChild(document.createElement("br"));

		//restore button
		var btnRestore = document.createElement("input");
		btnRestore.setAttribute("type", "button");
		btnRestore.value = "Restore localStorage";
		btnRestore.setAttribute("style", btnStyle);
		btnRestore.addEventListener("click", function (e) {
			inpFile.click(e);
		}, false);
		div.appendChild(btnRestore);

		div.appendChild(document.createElement("br"));

		//clear button
		var btnErase = document.createElement("input");
		btnErase.setAttribute("type", "button");
		btnErase.value = "Erase localStorage";
		btnErase.setAttribute("style", btnStyle);
		btnErase.addEventListener("click", function () {
			if (window.confirm("Erase all stored information?")) {
				localStorage.clear();
				if (confirm("reload site?")) {
					location.reload();
				}
			}
		}, false);
		div.appendChild(btnErase);

		div.appendChild(document.createElement("br"));

		//close button
		var btnClose = document.createElement("input");
		btnClose.setAttribute("type", "button");
		btnClose.value = "Close";
		btnClose.setAttribute("style", btnStyle);
		btnClose.addEventListener("click", function () {
			shown = false;
			div.remove();
		}, false);
		div.appendChild(btnClose);

		div.appendChild(document.createElement("br"));

		//reminder text
		var txt = document.createElement("span");
		txt.setAttribute("style", "display:block;margin-top:10px;margin-bottom:10px;font-family:Sans-Serif;font-size:10pt;color:#FF0000;background-color:#FFFFFF;font-weight:bold;");
		txt.textContent = "Restoring localStorage will erase all existing information";
		div.appendChild(txt);

		div.appendChild(document.createElement("br"));

		//text area for localStorage display
		var txtField = document.createElement("textarea");
		txtField.setAttribute("readonly", true);
		txtField.style = "width:100%;height:300px;";

		//Show localStorage button
		var btnShow = document.createElement("input");
		btnShow.setAttribute("type", "button");
		btnShow.value = "Show current storage";
		btnShow.setAttribute("style", btnStyle);
		btnShow.addEventListener("click", function () {
			txtField.value = JSON.stringify(localStorage, null, 4);
		}, false);

		div.appendChild(btnShow);
		div.appendChild(document.createElement("br"));
		div.appendChild(txtField);

		return div;
	};

	//This will show the backup div
	window.backup = function () {
		if (!shown) {
			shown = true;
			document.body.appendChild(renderDiv());
		}
	};

	//Hack to execute the backup function just by typing "backup" instead of "backup()"
	window.backup.valueOf = function () {
		window.backup();
		return "[Function backup]";
	};

	//Hack to execute the backup function just by typing "backup" instead of "backup()"
	window.backup.toString = function () {
		return window.backup.valueOf();
	};

	//Saves localStorage
	window.backup.backup = function () {
		window.backup.save(localStorage, location.hostname + "_localStorage.json");
	};

	//Saves a JSON object to a file and downloads it automatically
	window.backup.save = function (q, t) {
		var a = document.createElement("a");
		var s = JSON.tryParse(q) || q;
		if (typeof(s) !== typeof("")) {
			s = JSON.stringify(s, null, 4);
		}
		a.href = (URL.createObjectURL(new Blob(s.split(''))));
		a.setAttribute("download", t || window.prompt("File name", "download.json"));
		a.click();
	};
})();

/*
LICENSE:
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
The full license text can be found here: http://creativecommons.org/licenses/by-nc-sa/4.0/
The link has an easy to understand version of the license and the full license text.

DISCLAIMER:
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
THE POSSIBILITY OF SUCH DAMAGE.
*/

Copyright © 2018 by Kevin Gut 📧 | More services | Generated for 54.236.62.49