commit
						8f10fc291e
					
				|  | @ -1,5 +0,0 @@ | |||
| <html> | ||||
| 	<script src="storage.js"></script> | ||||
| 	<script src="messaging.js"></script> | ||||
| 	<script src="background.js"></script> | ||||
| </html> | ||||
|  | @ -54,7 +54,9 @@ chrome.extension.onMessage.addListener(function(request, sender, sendResponse) { | |||
| 		case "getStyles": | ||||
| 			var styles = getStyles(request, sendResponse); | ||||
| 			// check if this is a main content frame style enumeration
 | ||||
| 			if (request.matchUrl && !request.id && sender && sender.tab && sender.frameId == 0) { | ||||
| 			if (request.matchUrl && !request.id | ||||
| 			&& sender && sender.tab && sender.frameId == 0 | ||||
| 			&& sender.tab.url == request.matchUrl) { | ||||
| 				updateIcon(sender.tab, styles); | ||||
| 			} | ||||
| 			return true; | ||||
|  | @ -88,7 +90,7 @@ chrome.commands.onCommand.addListener(function(command) { | |||
| 			break; | ||||
| 		case "styleDisableAll": | ||||
| 			disableAllStylesToggle(); | ||||
| 			chrome.contextMenus.update("disableAll", {checked: prefs.getPref("disableAll")}); | ||||
| 			chrome.contextMenus.update("disableAll", {checked: prefs.get("disableAll")}); | ||||
| 			break; | ||||
| 	} | ||||
| }); | ||||
|  | @ -98,11 +100,11 @@ chrome.commands.onCommand.addListener(function(command) { | |||
| runTryCatch(function() { | ||||
| 	chrome.contextMenus.create({ | ||||
| 		id: "show-badge", title: chrome.i18n.getMessage("menuShowBadge"), | ||||
| 		type: "checkbox", contexts: ["browser_action"], checked: prefs.getPref("show-badge") | ||||
| 		type: "checkbox", contexts: ["browser_action"], checked: prefs.get("show-badge") | ||||
| 	}, function() { var clearError = chrome.runtime.lastError }); | ||||
| 	chrome.contextMenus.create({ | ||||
| 		id: "disableAll", title: chrome.i18n.getMessage("disableAllStyles"), | ||||
| 		type: "checkbox", contexts: ["browser_action"], checked: prefs.getPref("disableAll") | ||||
| 		type: "checkbox", contexts: ["browser_action"], checked: prefs.get("disableAll") | ||||
| 	}, function() { var clearError = chrome.runtime.lastError }); | ||||
| }); | ||||
| 
 | ||||
|  | @ -110,16 +112,15 @@ chrome.contextMenus.onClicked.addListener(function(info, tab) { | |||
| 	if (info.menuItemId == "disableAll") { | ||||
| 		disableAllStylesToggle(info.checked); | ||||
| 	} else { | ||||
| 		prefs.setPref(info.menuItemId, info.checked); | ||||
| 		prefs.set(info.menuItemId, info.checked); | ||||
| 	} | ||||
| }); | ||||
| 
 | ||||
| function disableAllStylesToggle(newState) { | ||||
| 	if (newState === undefined || newState === null) { | ||||
| 		newState = !prefs.getPref("disableAll"); | ||||
| 		newState = !prefs.get("disableAll"); | ||||
| 	} | ||||
| 	prefs.setPref("disableAll", newState); | ||||
| 	notifyAllTabs({method: "styleDisableAll", disableAll: newState}); | ||||
| 	prefs.set("disableAll", newState); | ||||
| } | ||||
| 
 | ||||
| function getStyles(options, callback) { | ||||
|  | @ -132,7 +133,7 @@ function getStyles(options, callback) { | |||
| 	var asHash = "asHash" in options ? options.asHash : false; | ||||
| 
 | ||||
| 	var callCallback = function() { | ||||
| 		var styles = asHash ? {disableAll: prefs.getPref("disableAll", false)} : []; | ||||
| 		var styles = asHash ? {disableAll: prefs.get("disableAll", false)} : []; | ||||
| 		cachedStyles.forEach(function(style) { | ||||
| 			if (enabled != null && fixBoolean(style.enabled) != enabled) { | ||||
| 				return; | ||||
|  | @ -243,6 +244,10 @@ function sectionAppliesToUrl(section, url) { | |||
| 	if (url.indexOf("http") != 0 && url.indexOf("file") != 0 && url.indexOf("chrome-extension") != 0 && url.indexOf("ftp") != 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	// other extensions can't be styled
 | ||||
| 	if (url.indexOf("chrome-extension") == 0 && url.indexOf(chrome.extension.getURL("")) != 0) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	if (!section.urls && !section.domains && !section.urlPrefixes && !section.regexps) { | ||||
| 		//console.log(section.id + " is global");
 | ||||
| 		return true; | ||||
|  | @ -401,7 +406,7 @@ chrome.tabs.onAttached.addListener(function(tabId, data) { | |||
| 		if (tabData.url.indexOf(editFullUrl) == 0) { | ||||
| 			chrome.windows.get(tabData.windowId, {populate: true}, function(win) { | ||||
| 				// If there's only one tab in this window, it's been dragged to new window
 | ||||
| 				prefs.setPref('openEditInWindow', win.tabs.length == 1); | ||||
| 				prefs.set("openEditInWindow", win.tabs.length == 1); | ||||
| 			}); | ||||
| 		} | ||||
| 	}); | ||||
|  |  | |||
							
								
								
									
										66
									
								
								edit.js
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								edit.js
									
									
									
									
									
								
							|  | @ -11,7 +11,7 @@ var propertyToCss = {urls: "url", urlPrefixes: "url-prefix", domains: "domain", | |||
| var CssToProperty = {"url": "urls", "url-prefix": "urlPrefixes", "domain": "domains", "regexp": "regexps"}; | ||||
| 
 | ||||
| // make querySelectorAll enumeration code readable
 | ||||
| ["forEach", "some", "indexOf"].forEach(function(method) { | ||||
| ["forEach", "some", "indexOf", "map"].forEach(function(method) { | ||||
| 	NodeList.prototype[method]= Array.prototype[method]; | ||||
| }); | ||||
| 
 | ||||
|  | @ -125,26 +125,23 @@ function initCodeMirror() { | |||
| 	var isWindowsOS = navigator.appVersion.indexOf("Windows") > 0; | ||||
| 
 | ||||
| 	// default option values
 | ||||
| 	var userOptions = prefs.getPref("editor.options"); | ||||
| 	var stylishOptions = { | ||||
| 	shallowMerge(CM.defaults, { | ||||
| 		mode: 'css', | ||||
| 		lineNumbers: true, | ||||
| 		lineWrapping: true, | ||||
| 		foldGutter: true, | ||||
| 		gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter", "CodeMirror-lint-markers"], | ||||
| 		matchBrackets: true, | ||||
| 		lint: {getAnnotations: CodeMirror.lint.css, delay: prefs.getPref("editor.lintDelay")}, | ||||
| 		lintReportDelay: prefs.getPref("editor.lintReportDelay"), | ||||
| 		lint: {getAnnotations: CodeMirror.lint.css, delay: prefs.get("editor.lintDelay")}, | ||||
| 		lintReportDelay: prefs.get("editor.lintReportDelay"), | ||||
| 		styleActiveLine: true, | ||||
| 		theme: "default", | ||||
| 		keyMap: prefs.getPref("editor.keyMap"), | ||||
| 		keyMap: prefs.get("editor.keyMap"), | ||||
| 		extraKeys: { // independent of current keyMap
 | ||||
| 			"Alt-PageDown": "nextEditor", | ||||
| 			"Alt-PageUp": "prevEditor" | ||||
| 		} | ||||
| 	} | ||||
| 	shallowMerge(stylishOptions, CM.defaults); | ||||
| 	shallowMerge(userOptions, CM.defaults); | ||||
| 	}, prefs.get("editor.options")); | ||||
| 
 | ||||
| 	// additional commands
 | ||||
| 	CM.commands.jumpToLine = jumpToLine; | ||||
|  | @ -158,11 +155,9 @@ function initCodeMirror() { | |||
| 	// "basic" keymap only has basic keys by design, so we skip it
 | ||||
| 
 | ||||
| 	var extraKeysCommands = {}; | ||||
| 	if (userOptions && typeof userOptions.extraKeys == "object") { | ||||
| 		Object.keys(userOptions.extraKeys).forEach(function(key) { | ||||
| 			extraKeysCommands[userOptions.extraKeys[key]] = true; | ||||
| 		}); | ||||
| 	} | ||||
| 	Object.keys(CM.defaults.extraKeys).forEach(function(key) { | ||||
| 		extraKeysCommands[CM.defaults.extraKeys[key]] = true; | ||||
| 	}); | ||||
| 	if (!extraKeysCommands.jumpToLine) { | ||||
| 		CM.keyMap.sublime["Ctrl-G"] = "jumpToLine"; | ||||
| 		CM.keyMap.emacsy["Ctrl-G"] = "jumpToLine"; | ||||
|  | @ -224,8 +219,8 @@ function initCodeMirror() { | |||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	// preload the theme so that CodeMirror can calculate its metrics in DOMContentLoaded->loadPrefs()
 | ||||
| 	var theme = prefs.getPref("editor.theme"); | ||||
| 	// preload the theme so that CodeMirror can calculate its metrics in DOMContentLoaded->setupLivePrefs()
 | ||||
| 	var theme = prefs.get("editor.theme"); | ||||
| 	document.getElementById("cm-theme").href = theme == "default" ? "" : "codemirror/theme/" + theme + ".css"; | ||||
| 
 | ||||
| 	// initialize global editor controls
 | ||||
|  | @ -246,12 +241,11 @@ function initCodeMirror() { | |||
| 			}); | ||||
| 		} | ||||
| 		document.getElementById("editor.keyMap").innerHTML = optionsHtmlFromArray(Object.keys(CM.keyMap).sort()); | ||||
| 		var controlPrefs = {}; | ||||
| 		document.querySelectorAll("#options *[data-option][id^='editor.']").forEach(function(option) { | ||||
| 			controlPrefs[option.id] = CM.defaults[option.dataset.option]; | ||||
| 		}); | ||||
| 		document.getElementById("options").addEventListener("change", acmeEventListener, false); | ||||
| 		loadPrefs(controlPrefs); | ||||
| 		setupLivePrefs( | ||||
| 			document.querySelectorAll("#options *[data-option][id^='editor.']") | ||||
| 				.map(function(option) { return option.id }) | ||||
| 		); | ||||
| 	}); | ||||
| 
 | ||||
| 	hotkeyRerouter.setState(true); | ||||
|  | @ -276,8 +270,8 @@ function acmeEventListener(event) { | |||
| 			// use non-localized "default" internally
 | ||||
| 			if (!value || value == "default" || value == t("defaultTheme")) { | ||||
| 				value = "default"; | ||||
| 				if (prefs.getPref(el.id) != value) { | ||||
| 					prefs.setPref(el.id, value); | ||||
| 				if (prefs.get(el.id) != value) { | ||||
| 					prefs.set(el.id, value); | ||||
| 				} | ||||
| 				themeLink.href = ""; | ||||
| 				el.selectedIndex = 0; | ||||
|  | @ -400,7 +394,7 @@ document.addEventListener("wheel", function(event) { | |||
| 
 | ||||
| chrome.tabs.query({currentWindow: true}, function(tabs) { | ||||
| 	var windowId = tabs[0].windowId; | ||||
| 	if (prefs.getPref("openEditInWindow")) { | ||||
| 	if (prefs.get("openEditInWindow")) { | ||||
| 		if (tabs.length == 1 && window.history.length == 1) { | ||||
| 			chrome.windows.getAll(function(windows) { | ||||
| 				if (windows.length > 1) { | ||||
|  | @ -434,7 +428,7 @@ function goBackToManage(event) { | |||
| 
 | ||||
| window.onbeforeunload = function() { | ||||
| 	if (saveSizeOnClose) { | ||||
| 		prefs.setPref("windowPosition", { | ||||
| 		prefs.set("windowPosition", { | ||||
| 			left: screenLeft, | ||||
| 			top: screenTop, | ||||
| 			width: outerWidth, | ||||
|  | @ -994,9 +988,9 @@ function beautify(event) { | |||
| 		script.onload = doBeautify; | ||||
| 	} | ||||
| 	function doBeautify() { | ||||
| 		var tabs = prefs.getPref("editor.indentWithTabs"); | ||||
| 		var options = prefs.getPref("editor.beautify"); | ||||
| 		options.indent_size = tabs ? 1 : prefs.getPref("editor.tabSize"); | ||||
| 		var tabs = prefs.get("editor.indentWithTabs"); | ||||
| 		var options = prefs.get("editor.beautify"); | ||||
| 		options.indent_size = tabs ? 1 : prefs.get("editor.tabSize"); | ||||
| 		options.indent_char = tabs ? "\t" : " "; | ||||
| 
 | ||||
| 		var section = getSectionForChild(event.target); | ||||
|  | @ -1045,7 +1039,7 @@ function beautify(event) { | |||
| 		document.querySelector(".beautify-options").addEventListener("change", function(event) { | ||||
| 			var value = event.target.selectedIndex > 0; | ||||
| 			options[event.target.dataset.option] = value; | ||||
| 			prefs.setPref("editor.beautify", options); | ||||
| 			prefs.set("editor.beautify", options); | ||||
| 			event.target.parentNode.setAttribute("newline", value.toString()); | ||||
| 			doBeautify(); | ||||
| 		}); | ||||
|  | @ -1120,7 +1114,7 @@ function initWithStyle(style) { | |||
| 	function add() { | ||||
| 		var sectionDiv = addSection(null, queue.shift()); | ||||
| 		maximizeCodeHeight(sectionDiv, !queue.length); | ||||
| 		updateLintReport(getCodeMirrorForSection(sectionDiv), prefs.getPref("editor.lintDelay")); | ||||
| 		updateLintReport(getCodeMirrorForSection(sectionDiv), prefs.get("editor.lintDelay")); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -1472,12 +1466,12 @@ function showToMozillaHelp() { | |||
| } | ||||
| 
 | ||||
| function showKeyMapHelp() { | ||||
| 	var keyMap = mergeKeyMaps({}, prefs.getPref("editor.keyMap"), CodeMirror.defaults.extraKeys); | ||||
| 	var keyMap = mergeKeyMaps({}, prefs.get("editor.keyMap"), CodeMirror.defaults.extraKeys); | ||||
| 	var keyMapSorted = Object.keys(keyMap) | ||||
| 		.map(function(key) { return {key: key, cmd: keyMap[key]} }) | ||||
| 		.concat([{key: "Shift-Ctrl-Wheel", cmd: "scrollWindow"}]) | ||||
| 		.sort(function(a, b) { return a.cmd < b.cmd || (a.cmd == b.cmd && a.key < b.key) ? -1 : 1 }); | ||||
| 	showHelp(t("cm_keyMap") + ": " + prefs.getPref("editor.keyMap"), | ||||
| 	showHelp(t("cm_keyMap") + ": " + prefs.get("editor.keyMap"), | ||||
| 		'<table class="keymap-list">' + | ||||
| 			'<thead><tr><th><input placeholder="' + t("helpKeyMapHotkey") + '" type="search"></th>' + | ||||
| 				'<th><input placeholder="' + t("helpKeyMapCommand") + '" type="search"></th></tr></thead>' + | ||||
|  | @ -1585,7 +1579,7 @@ function showCodeMirrorPopup(title, html, options) { | |||
| 	var popup = showHelp(title, html); | ||||
| 	popup.classList.add("big"); | ||||
| 
 | ||||
| 	popup.codebox = CodeMirror(popup.querySelector(".contents"), shallowMerge(options, { | ||||
| 	popup.codebox = CodeMirror(popup.querySelector(".contents"), shallowMerge({ | ||||
| 		mode: "css", | ||||
| 		lineNumbers: true, | ||||
| 		lineWrapping: true, | ||||
|  | @ -1594,9 +1588,9 @@ function showCodeMirrorPopup(title, html, options) { | |||
| 		matchBrackets: true, | ||||
| 		lint: {getAnnotations: CodeMirror.lint.css, delay: 0}, | ||||
| 		styleActiveLine: true, | ||||
| 		theme: prefs.getPref("editor.theme"), | ||||
| 		keyMap: prefs.getPref("editor.keyMap") | ||||
| 	})); | ||||
| 		theme: prefs.get("editor.theme"), | ||||
| 		keyMap: prefs.get("editor.keyMap") | ||||
| 	}, options)); | ||||
| 	popup.codebox.focus(); | ||||
| 	popup.codebox.on("focus", function() { hotkeyRerouter.setState(false) }); | ||||
| 	popup.codebox.on("blur", function() { hotkeyRerouter.setState(true) }); | ||||
|  |  | |||
							
								
								
									
										14
									
								
								manage.js
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								manage.js
									
									
									
									
									
								
							|  | @ -110,7 +110,7 @@ function createStyleElement(style) { | |||
| 			event.stopPropagation(); | ||||
| 			if (openWindow || openBackgroundTab || openForegroundTab) { | ||||
| 				if (openWindow) { | ||||
| 					var options = prefs.getPref('windowPosition', {}); | ||||
| 					var options = prefs.get("windowPosition"); | ||||
| 					options.url = url; | ||||
| 					chrome.windows.create(options); | ||||
| 				} else { | ||||
|  | @ -475,12 +475,12 @@ document.addEventListener("DOMContentLoaded", function() { | |||
| 	document.getElementById("search").addEventListener("input", searchStyles); | ||||
| 	searchStyles(true); // re-apply filtering on history Back
 | ||||
| 
 | ||||
| 	loadPrefs({ | ||||
| 		"manage.onlyEnabled": false, | ||||
| 		"manage.onlyEdited": false, | ||||
| 		"show-badge": true, | ||||
| 		"popup.stylesFirst": true | ||||
| 	}); | ||||
| 	setupLivePrefs([ | ||||
| 		"manage.onlyEnabled", | ||||
| 		"manage.onlyEdited", | ||||
| 		"show-badge", | ||||
| 		"popup.stylesFirst" | ||||
| 	]); | ||||
| 	initFilter("enabled-only", document.getElementById("manage.onlyEnabled")); | ||||
| 	initFilter("edited-only", document.getElementById("manage.onlyEdited")); | ||||
| }); | ||||
|  |  | |||
|  | @ -13,11 +13,12 @@ | |||
| 		"tabs", | ||||
| 		"webNavigation", | ||||
| 		"contextMenus", | ||||
| 		"storage", | ||||
| 		"http://userstyles.org/", | ||||
| 		"https://userstyles.org/" | ||||
| 	], | ||||
| 	"background": { | ||||
| 		"page": "background.html" | ||||
| 		"scripts": ["messaging.js", "storage.js", "background.js"] | ||||
| 	}, | ||||
| 	"commands": { | ||||
| 	  "openManage": { | ||||
|  |  | |||
							
								
								
									
										19
									
								
								messaging.js
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								messaging.js
									
									
									
									
									
								
							|  | @ -8,11 +8,7 @@ function notifyAllTabs(request) { | |||
| 		}); | ||||
| 	}); | ||||
| 	// notify all open popups
 | ||||
| 	// use a shallow copy since the original `request` is still being processed
 | ||||
| 	var reqPopup = {}; | ||||
| 	for (var k in request) reqPopup[k] = request[k]; | ||||
| 	reqPopup.reason = request.method; | ||||
| 	reqPopup.method = "updatePopup"; | ||||
| 	var reqPopup = shallowMerge({}, request, {method: "updatePopup", reason: request.method}); | ||||
| 	chrome.extension.sendMessage(reqPopup); | ||||
| } | ||||
| 
 | ||||
|  | @ -48,15 +44,20 @@ function updateIcon(tab, styles) { | |||
| 	}); | ||||
| 
 | ||||
| 	function stylesReceived(styles) { | ||||
| 		var disableAll = "disableAll" in styles ? styles.disableAll : prefs.getPref("disableAll"); | ||||
| 		var disableAll = "disableAll" in styles ? styles.disableAll : prefs.get("disableAll"); | ||||
| 		var postfix = styles.length == 0 || disableAll ? "w" : ""; | ||||
| 		chrome.browserAction.setIcon({ | ||||
| 			path: {19: "19" + postfix + ".png", 38: "38" + postfix + ".png"}, | ||||
| 			tabId: tab.id | ||||
| 		}, function() { | ||||
| 			// if the tab was just closed an error may occur,
 | ||||
| 			// e.g. 'windowPosition' pref updated in edit.js::window.onbeforeunload
 | ||||
| 			if (!chrome.runtime.lastError) { | ||||
| 				var t = prefs.get("show-badge") && styles.length ? ("" + styles.length) : ""; | ||||
| 				chrome.browserAction.setBadgeText({text: t, tabId: tab.id}); | ||||
| 				chrome.browserAction.setBadgeBackgroundColor({color: disableAll ? "#aaa" : [0, 0, 0, 0]}); | ||||
| 			} | ||||
| 		}); | ||||
| 		var t = prefs.getPref("show-badge") && styles.length ? ("" + styles.length) : ""; | ||||
| 		chrome.browserAction.setBadgeText({text: t, tabId: tab.id}); | ||||
| 		chrome.browserAction.setBadgeBackgroundColor({color: disableAll ? "#aaa" : [0, 0, 0, 0]}); | ||||
| 		//console.log("Tab " + tab.id + " (" + tab.url + ") badge text set to '" + t + "'.");
 | ||||
| 	} | ||||
| } | ||||
|  |  | |||
							
								
								
									
										30
									
								
								popup.js
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								popup.js
									
									
									
									
									
								
							|  | @ -3,7 +3,7 @@ writeStyleTemplate.className = "write-style-link"; | |||
| 
 | ||||
| var installed = document.getElementById("installed"); | ||||
| 
 | ||||
| if (!prefs.getPref("popup.stylesFirst")) { | ||||
| if (!prefs.get("popup.stylesFirst")) { | ||||
| 	document.body.insertBefore(document.querySelector("body > .actions"), installed); | ||||
| } | ||||
| 
 | ||||
|  | @ -29,14 +29,14 @@ function updatePopUp(url) { | |||
| 	var urlLink = writeStyleTemplate.cloneNode(true); | ||||
| 	urlLink.href = "edit.html?url-prefix=" + encodeURIComponent(url); | ||||
| 	urlLink.appendChild(document.createTextNode( // switchable; default="this URL"
 | ||||
| 		!prefs.getPref("popup.breadcrumbs.usePath") | ||||
| 		!prefs.get("popup.breadcrumbs.usePath") | ||||
| 		? t("writeStyleForURL").replace(/ /g, "\u00a0") | ||||
| 		: /\/\/[^/]+\/(.*)/.exec(url)[1] | ||||
| 	)); | ||||
| 	urlLink.title = "url-prefix(\"$\")".replace("$", url); | ||||
| 	writeStyleLinks.push(urlLink); | ||||
| 	document.querySelector("#write-style").appendChild(urlLink) | ||||
| 	if (prefs.getPref("popup.breadcrumbs")) { // switchable; default=enabled
 | ||||
| 	if (prefs.get("popup.breadcrumbs")) { // switchable; default=enabled
 | ||||
| 		urlLink.addEventListener("mouseenter", function(event) { this.parentNode.classList.add("url()") }, false); | ||||
| 		urlLink.addEventListener("focus", function(event) { this.parentNode.classList.add("url()") }, false); | ||||
| 		urlLink.addEventListener("mouseleave", function(event) { this.parentNode.classList.remove("url()") }, false); | ||||
|  | @ -63,7 +63,7 @@ function updatePopUp(url) { | |||
| 		link.addEventListener("click", openLinkInTabOrWindow, false); | ||||
| 		container.appendChild(link); | ||||
| 	}); | ||||
| 	if (prefs.getPref("popup.breadcrumbs")) { | ||||
| 	if (prefs.get("popup.breadcrumbs")) { | ||||
| 		container.classList.add("breadcrumbs"); | ||||
| 		container.appendChild(container.removeChild(container.firstChild)); | ||||
| 	} | ||||
|  | @ -71,7 +71,7 @@ function updatePopUp(url) { | |||
| } | ||||
| 
 | ||||
| function showStyles(styles) { | ||||
| 	var enabledFirst = prefs.getPref("popup.enabledFirst"); | ||||
| 	var enabledFirst = prefs.get("popup.enabledFirst"); | ||||
| 	styles.sort(function(a, b) { | ||||
| 		if (enabledFirst && a.enabled !== b.enabled) return !(a.enabled < b.enabled) ? -1 : 1; | ||||
| 		return a.name.localeCompare(b.name); | ||||
|  | @ -146,9 +146,9 @@ function getId(event) { | |||
| 
 | ||||
| function openLinkInTabOrWindow(event) { | ||||
| 	event.preventDefault(); | ||||
| 	if (prefs.getPref('openEditInWindow', false)) { | ||||
| 	if (prefs.get("openEditInWindow", false)) { | ||||
| 		var options = {url: event.target.href} | ||||
| 		var wp = prefs.getPref('windowPosition', {}); | ||||
| 		var wp = prefs.get("windowPosition", {}); | ||||
| 		for (var k in wp) options[k] = wp[k]; | ||||
| 		chrome.windows.create(options); | ||||
| 	} else { | ||||
|  | @ -185,10 +185,6 @@ function handleDelete(id) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| function handleDisableAll(disableAll) { | ||||
| 	installed.classList.toggle("disabled", disableAll); | ||||
| } | ||||
| 
 | ||||
| chrome.extension.onMessage.addListener(function(request, sender, sendResponse) { | ||||
| 	if (request.method == "updatePopup") { | ||||
| 		switch (request.reason) { | ||||
|  | @ -199,12 +195,6 @@ chrome.extension.onMessage.addListener(function(request, sender, sendResponse) { | |||
| 			case "styleDeleted": | ||||
| 				handleDelete(request.id); | ||||
| 				break; | ||||
| 			case "prefChanged": | ||||
| 				if (request.prefName == "disableAll") { | ||||
| 					document.getElementById("disableAll").checked = request.value; | ||||
| 					handleDisableAll(request.value); | ||||
| 				} | ||||
| 				break; | ||||
| 		} | ||||
| 	} | ||||
| }); | ||||
|  | @ -213,9 +203,7 @@ chrome.extension.onMessage.addListener(function(request, sender, sendResponse) { | |||
| 	document.getElementById(id).addEventListener("click", openLink, false); | ||||
| }); | ||||
| 
 | ||||
| loadPrefs({"disableAll": false}); | ||||
| handleDisableAll(prefs.getPref("disableAll")); | ||||
| document.getElementById("disableAll").addEventListener("change", function(event) { | ||||
| 	notifyAllTabs({method: "styleDisableAll", disableAll: event.target.checked}); | ||||
| 	handleDisableAll(event.target.checked); | ||||
| 	installed.classList.toggle("disabled", prefs.get("disableAll")); | ||||
| }); | ||||
| setupLivePrefs(["disableAll"]); | ||||
|  |  | |||
							
								
								
									
										271
									
								
								storage.js
									
									
									
									
									
								
							
							
						
						
									
										271
									
								
								storage.js
									
									
									
									
									
								
							|  | @ -136,96 +136,170 @@ function isCheckbox(el) { | |||
| 	return el.nodeName.toLowerCase() == "input" && "checkbox" == el.type.toLowerCase(); | ||||
| } | ||||
| 
 | ||||
| function changePref(event) { | ||||
| 	var el = event.target; | ||||
| 	prefs.setPref(el.id, isCheckbox(el) ? el.checked : el.value); | ||||
| } | ||||
| 
 | ||||
| // Accepts a hash of pref name to default value
 | ||||
| function loadPrefs(prefs) { | ||||
| 	for (var id in prefs) { | ||||
| 		var value = this.prefs.getPref(id, prefs[id]); | ||||
| 		var el = document.getElementById(id); | ||||
| 		if (isCheckbox(el)) { | ||||
| 			el.checked = value; | ||||
| 		} else { | ||||
| 			el.value = value; | ||||
| // Accepts an array of pref names (values are fetched via prefs.get)
 | ||||
| // and establishes a two-way connection between the document elements and the actual prefs
 | ||||
| function setupLivePrefs(IDs) { | ||||
| 	var localIDs = {}; | ||||
| 	IDs.forEach(function(id) { | ||||
| 		localIDs[id] = true; | ||||
| 		updateElement(id).addEventListener("change", function() { | ||||
| 			prefs.set(this.id, isCheckbox(this) ? this.checked : this.value); | ||||
| 		}); | ||||
| 	}); | ||||
| 	chrome.extension.onMessage.addListener(function(request) { | ||||
| 		if (request.prefName in localIDs) { | ||||
| 			updateElement(request.prefName); | ||||
| 		} | ||||
| 	}); | ||||
| 	function updateElement(id) { | ||||
| 		var el = document.getElementById(id); | ||||
| 		el[isCheckbox(el) ? "checked" : "value"] = prefs.get(id); | ||||
| 		el.dispatchEvent(new Event("change", {bubbles: true, cancelable: true})); | ||||
| 		el.addEventListener("change", changePref); | ||||
| 		return el; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| var prefs = { | ||||
| // NB: localStorage["not_key"] is undefined, localStorage.getItem("not_key") is null
 | ||||
| var prefs = chrome.extension.getBackgroundPage().prefs || new function Prefs() { | ||||
| 	var me = this; | ||||
| 
 | ||||
| 	// defaults
 | ||||
| 	"openEditInWindow": false, // new editor opens in a own browser window
 | ||||
| 	"windowPosition": {},      // detached window position
 | ||||
| 	"show-badge": true,        // display text on popup menu icon
 | ||||
| 	"disableAll": false,       // boss key
 | ||||
| 	var defaults = { | ||||
| 		"openEditInWindow": false,      // new editor opens in a own browser window
 | ||||
| 		"windowPosition": {},           // detached window position
 | ||||
| 		"show-badge": true,             // display text on popup menu icon
 | ||||
| 		"disableAll": false,            // boss key
 | ||||
| 
 | ||||
| 	"popup.breadcrumbs": true, // display "New style" links as URL breadcrumbs
 | ||||
| 	"popup.breadcrumbs.usePath": false, // use URL path for "this URL"
 | ||||
| 	"popup.enabledFirst": true,  // display enabled styles before disabled styles
 | ||||
| 	"popup.stylesFirst": true,  // display enabled styles before disabled styles
 | ||||
| 		"popup.breadcrumbs": true,      // display "New style" links as URL breadcrumbs
 | ||||
| 		"popup.breadcrumbs.usePath": false, // use URL path for "this URL"
 | ||||
| 		"popup.enabledFirst": true,     // display enabled styles before disabled styles
 | ||||
| 		"popup.stylesFirst": true,      // display enabled styles before disabled styles
 | ||||
| 
 | ||||
| 	"manage.onlyEnabled": false, // display only enabled styles
 | ||||
| 	"manage.onlyEdited": false,  // display only styles created locally
 | ||||
| 		"manage.onlyEnabled": false,    // display only enabled styles
 | ||||
| 		"manage.onlyEdited": false,     // display only styles created locally
 | ||||
| 
 | ||||
| 	"editor.options": {},          // CodeMirror.defaults.*
 | ||||
| 	"editor.lineWrapping": true,   // word wrap
 | ||||
| 	"editor.smartIndent": true,    // "smart" indent
 | ||||
| 	"editor.indentWithTabs": false,// smart indent with tabs
 | ||||
| 	"editor.tabSize": 4,           // tab width, in spaces
 | ||||
| 	"editor.keyMap": navigator.appVersion.indexOf("Windows") > 0 ? "sublime" : "default", | ||||
| 	"editor.theme": "default",     // CSS theme
 | ||||
| 	"editor.beautify": {           // CSS beautifier
 | ||||
| 		selector_separator_newline: true, | ||||
| 		newline_before_open_brace: false, | ||||
| 		newline_after_open_brace: true, | ||||
| 		newline_between_properties: true, | ||||
| 		newline_before_close_brace: true, | ||||
| 		newline_between_rules: false, | ||||
| 		end_with_newline: false | ||||
| 	}, | ||||
| 	"editor.lintDelay": 500,        // lint gutter marker update delay, ms
 | ||||
| 	"editor.lintReportDelay": 4500, // lint report update delay, ms
 | ||||
| 		"editor.options": {},           // CodeMirror.defaults.*
 | ||||
| 		"editor.lineWrapping": true,    // word wrap
 | ||||
| 		"editor.smartIndent": true,     // "smart" indent
 | ||||
| 		"editor.indentWithTabs": false, // smart indent with tabs
 | ||||
| 		"editor.tabSize": 4,            // tab width, in spaces
 | ||||
| 		"editor.keyMap": navigator.appVersion.indexOf("Windows") > 0 ? "sublime" : "default", | ||||
| 		"editor.theme": "default",      // CSS theme
 | ||||
| 		"editor.beautify": {            // CSS beautifier
 | ||||
| 			selector_separator_newline: true, | ||||
| 			newline_before_open_brace: false, | ||||
| 			newline_after_open_brace: true, | ||||
| 			newline_between_properties: true, | ||||
| 			newline_before_close_brace: true, | ||||
| 			newline_between_rules: false, | ||||
| 			end_with_newline: false | ||||
| 		}, | ||||
| 		"editor.lintDelay": 500,        // lint gutter marker update delay, ms
 | ||||
| 		"editor.lintReportDelay": 4500, // lint report update delay, ms
 | ||||
| 	}; | ||||
| 	var values = deepCopy(defaults); | ||||
| 
 | ||||
| 	NO_DEFAULT_PREFERENCE: "No default preference for '%s'", | ||||
| 	UNHANDLED_DATA_TYPE: "Default '%s' is of type '%s' - what should be done with it?", | ||||
| 	var syncTimeout; // see broadcast() function below
 | ||||
| 
 | ||||
| 	getPref: function(key, defaultValue) { | ||||
| 	// Returns localStorage[key], defaultValue, this[key], or undefined
 | ||||
| 	//   as type of defaultValue, this[key], or localStorage[key]
 | ||||
| 		var value = localStorage[key]; | ||||
| 		if (value === undefined) { | ||||
| 			return defaultValue === undefined ? shallowCopy(this[key]) : defaultValue; | ||||
| 	Object.defineProperty(this, "readOnlyValues", {value: {}}); | ||||
| 
 | ||||
| 	Prefs.prototype.get = function(key, defaultValue) { | ||||
| 		if (key in values) { | ||||
| 			return values[key]; | ||||
| 		} | ||||
| 		switch (typeof (defaultValue === undefined ? this[key] : defaultValue)) { | ||||
| 			case "boolean": return value.toLowerCase() === "true"; | ||||
| 			case "number": return Number(value); | ||||
| 			case "object": return JSON.parse(value); | ||||
| 			case "string": break; | ||||
| 			case "undefined":  console.warn(this.NO_DEFAULT_PREFERENCE, key); break; | ||||
| 			default: console.error(UNHANDLED_DATA_TYPE, key, typeof defaultValue); | ||||
| 		if (defaultValue !== undefined) { | ||||
| 			return defaultValue; | ||||
| 		} | ||||
| 		if (key in defaults) { | ||||
| 			return defaults[key]; | ||||
| 		} | ||||
| 		console.warn("No default preference for '%s'", key); | ||||
| 	}; | ||||
| 
 | ||||
| 	Prefs.prototype.getAll = function(key) { | ||||
| 		return deepCopy(values); | ||||
| 	}; | ||||
| 
 | ||||
| 	Prefs.prototype.set = function(key, value, options) { | ||||
| 		var oldValue = deepCopy(values[key]); | ||||
| 		values[key] = value; | ||||
| 		defineReadonlyProperty(this.readOnlyValues, key, value); | ||||
| 		if ((!options || !options.noBroadcast) && !equal(value, oldValue)) { | ||||
| 			me.broadcast(key, value, options); | ||||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| 	Prefs.prototype.remove = function(key) { me.set(key, undefined) }; | ||||
| 
 | ||||
| 	Prefs.prototype.broadcast = function(key, value, options) { | ||||
| 		var message = {method: "prefChanged", prefName: key, value: value}; | ||||
| 		notifyAllTabs(message); | ||||
| 		chrome.extension.sendMessage(message); | ||||
| 		if (key == "disableAll") { | ||||
| 			notifyAllTabs({method: "styleDisableAll", disableAll: value}); | ||||
| 		} | ||||
| 		if (!options || !options.noSync) { | ||||
| 			clearTimeout(syncTimeout); | ||||
| 			syncTimeout = setTimeout(function() { | ||||
| 				chrome.storage.sync.set({"settings": values}); | ||||
| 			}, 0); | ||||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| 	Object.keys(defaults).forEach(function(key) { | ||||
| 		me.set(key, defaults[key], {noBroadcast: true}); | ||||
| 	}); | ||||
| 
 | ||||
| 	chrome.storage.sync.get("settings", function(result) { | ||||
| 		var synced = result.settings; | ||||
| 		for (var key in defaults) { | ||||
| 			if (synced && (key in synced)) { | ||||
| 				me.set(key, synced[key], {noSync: true}); | ||||
| 			} else { | ||||
| 				var value = tryMigrating(key); | ||||
| 				if (value !== undefined) { | ||||
| 					me.set(key, value); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| 	chrome.storage.onChanged.addListener(function(changes, area) { | ||||
| 		if (area == "sync" && "settings" in changes) { | ||||
| 			var synced = changes.settings.newValue; | ||||
| 			if (synced) { | ||||
| 				for (key in defaults) { | ||||
| 					if (key in synced) { | ||||
| 						me.set(key, synced[key], {noSync: true}); | ||||
| 					} | ||||
| 				} | ||||
| 			} else { | ||||
| 				// user manually deleted our settings, we'll recreate them
 | ||||
| 				chrome.storage.sync.set({"settings": values}); | ||||
| 			} | ||||
| 		} | ||||
| 	}); | ||||
| 
 | ||||
| 	function tryMigrating(key) { | ||||
| 		if (!(key in localStorage)) { | ||||
| 			return undefined; | ||||
| 		} | ||||
| 		var value = localStorage[key]; | ||||
| 		delete localStorage[key]; | ||||
| 		localStorage["DEPRECATED: " + key] = value; | ||||
| 		switch (typeof defaults[key]) { | ||||
| 			case "boolean": | ||||
| 				return value.toLowerCase() === "true"; | ||||
| 			case "number": | ||||
| 				return Number(value); | ||||
| 			case "object": | ||||
| 				try { | ||||
| 					return JSON.parse(value); | ||||
| 				} catch(e) { | ||||
| 					console.log("Cannot migrate from localStorage %s = '%s': %o", key, value, e); | ||||
| 					return undefined; | ||||
| 				} | ||||
| 		} | ||||
| 		return value; | ||||
| 	}, | ||||
| 	setPref: function(key, value) { | ||||
| 		var oldValue = localStorage[key]; | ||||
| 		if (value === undefined || equal(value, this[key])) { | ||||
| 			delete localStorage[key]; | ||||
| 		} else { | ||||
| 			localStorage[key] = typeof value == "string" ? value : JSON.stringify(value); | ||||
| 		} | ||||
| 		if (!equal(value, oldValue === undefined ? this[key] : oldValue)) { | ||||
| 			var message = {method: "prefChanged", prefName: key, value: value}; | ||||
| 			notifyAllTabs(message); | ||||
| 			chrome.extension.sendMessage(message); | ||||
| 		} | ||||
| 	}, | ||||
| 	removePref: function(key) { setPref(key, undefined) } | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| function getCodeMirrorThemes(callback) { | ||||
|  | @ -261,17 +335,42 @@ function sessionStorageHash(name) { | |||
| 	return hash; | ||||
| } | ||||
| 
 | ||||
| function shallowCopy(obj) { | ||||
| 	return typeof obj == "object" ? shallowMerge(obj, {}) : obj; | ||||
| function deepCopy(obj) { | ||||
| 	if (!obj || typeof obj != "object") { | ||||
| 		return obj; | ||||
| 	} else { | ||||
| 		var emptyCopy = Object.create(Object.getPrototypeOf(obj)); | ||||
| 		return deepMerge(emptyCopy, obj); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| function shallowMerge(from, to) { | ||||
| 	if (typeof from == "object" && typeof to == "object") { | ||||
| 		for (var k in from) { | ||||
| 			to[k] = from[k]; | ||||
| function deepMerge(target, obj1 /* plus any number of object arguments */) { | ||||
| 	for (var i = 1; i < arguments.length; i++) { | ||||
| 		var obj = arguments[i]; | ||||
| 		for (var k in obj) { | ||||
| 			// hasOwnProperty checking is not needed for our non-OOP stuff
 | ||||
| 			var value = obj[k]; | ||||
| 			if (!value || typeof value != "object") { | ||||
| 				target[k] = value; | ||||
| 			} else if (k in target) { | ||||
| 				deepMerge(target[k], value); | ||||
| 			} else { | ||||
| 				target[k] = deepCopy(value); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return to; | ||||
| 	return target; | ||||
| } | ||||
| 
 | ||||
| function shallowMerge(target, obj1 /* plus any number of object arguments */) { | ||||
| 	for (var i = 1; i < arguments.length; i++) { | ||||
| 		var obj = arguments[i]; | ||||
| 		for (var k in obj) { | ||||
| 			target[k] = obj[k]; | ||||
| 			// hasOwnProperty checking is not needed for our non-OOP stuff
 | ||||
| 		} | ||||
| 	} | ||||
| 	return target; | ||||
| } | ||||
| 
 | ||||
| function equal(a, b) { | ||||
|  | @ -288,3 +387,9 @@ function equal(a, b) { | |||
| 	} | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| function defineReadonlyProperty(obj, key, value) { | ||||
| 	var copy = deepCopy(value); | ||||
| 	Object.freeze(copy); | ||||
| 	Object.defineProperty(obj, key, {value: copy, configurable: true}) | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user