瀏覽代碼

new interface

Gerald 11 年之前
父節點
當前提交
05087549a2

+ 110 - 118
_locales/cs/messages.json

@@ -47,10 +47,6 @@
 		"message": "Aktualizace nenalezena.",
 		"message": "Aktualizace nenalezena.",
 		"description": "Message shown when there is no new version of a script."
 		"description": "Message shown when there is no new version of a script."
 	},
 	},
-	"css": {
-		"message": "html{font-family:Calibri,Arial;}",
-		"description": "Additional CSS for all pages."
-	},
 	"labelInstall": {
 	"labelInstall": {
 		"message": "Instaluji skript",
 		"message": "Instaluji skript",
 		"description": "Shown in the title of the confirm page while trying to install a script."
 		"description": "Shown in the title of the confirm page while trying to install a script."
@@ -67,14 +63,6 @@
 		"message": "Zavřít",
 		"message": "Zavřít",
 		"description": "Button to close window."
 		"description": "Button to close window."
 	},
 	},
-	"anchorSupportPage": {
-		"message": "<a href=https://github.com/gera2ld/Violentmonkey/wiki target=_blank>Violentmonkey</a>",
-		"description": "Link to the support page of Violentmonkey."
-	},
-	"anchorAuthor": {
-		"message": "Design od <a href=mailto:[email protected]>Gerald</a>, Přeložil: <a href=http://my.opera.com/ahoj1234 target=_blank>ahoj1234</a>",
-		"description": "Author shown in the footer of options page, translator information may be added."
-	},
 	"msgScriptURL": {
 	"msgScriptURL": {
 		"message": "Skript URL: $1",
 		"message": "Skript URL: $1",
 		"description": "URL of the script to be installed on confirm page."
 		"description": "URL of the script to be installed on confirm page."
@@ -99,38 +87,110 @@
 		"message": "Chyba při načítání požadavky.",
 		"message": "Chyba při načítání požadavky.",
 		"description": "Message shown when not all requirements are loaded successfully."
 		"description": "Message shown when not all requirements are loaded successfully."
 	},
 	},
-	"labelOptions": {
-		"message": "Možnosti",
-		"description": "Options of this extension."
+	"anchorGetMoreScripts": {
+		"message": "<a href=http://userscripts.org target=_blank>Získej více skritpů</a>",
+		"description": "Link to get more scripts."
+	},
+	"sideMenuInstalled": {
+		"message": "Nainstalované skripty",
+		"description": "Side menu: Installed scripts"
+	},
+	"sideMenuSettings": {
+		"message": "Settings",
+		"description": "Side menu: Settings"
+	},
+	"sideMenuAbout": {
+		"message": "About",
+		"description": "Side menu: About"
 	},
 	},
 	"buttonNew": {
 	"buttonNew": {
 		"message": "Nový",
 		"message": "Nový",
 		"description": "Button to create a new script."
 		"description": "Button to create a new script."
 	},
 	},
-	"anchorGetMoreScripts": {
-		"message": "<a href=http://userscripts.org target=_blank>Získej více skritpů z userscripts.org</a>",
-		"description": "Link to get more scripts."
-	},
 	"anchorUpdateAll": {
 	"anchorUpdateAll": {
 		"message": "Zkontrolovat aktualizace",
 		"message": "Zkontrolovat aktualizace",
 		"description": "Check all scripts for updates."
 		"description": "Check all scripts for updates."
 	},
 	},
-	"buttonAdvanced": {
-		"message": "Pokročilé",
-		"description": "Button to show the advanced options."
-	},
-	"labelInstalledScripts": {
-		"message": "Nainstalované skripty",
-		"description": "Label of the list of installed scripts."
-	},
-	"labelShowDetails": {
-		"message": "Zobrazit detaily",
-		"description": "Option to show the details of scripts, such as author, description, etc."
-	},
 	"msgLoading": {
 	"msgLoading": {
 		"message": "Nahrávám ...",
 		"message": "Nahrávám ...",
 		"description": "Message shown in the options page before script list is loaded."
 		"description": "Message shown in the options page before script list is loaded."
 	},
 	},
+	"labelSettings": {
+		"message": "Settings",
+		"description": "Label shown on the top of settings page"
+	},
+	"labelAutoUpdate": {
+		"message": "Automaticky kontrolovat aktualizace skriptu každý den",
+		"description": "Option to allow automatically checking scripts for updates every 24 hours."
+	},
+	"labelSearchLink": {
+		"message": "hledat URL: ",
+		"description": "Label of URL for searching scripts for a site."
+	},
+	"buttonDefault": {
+		"message": "Výchozí",
+		"description": "Button to replace search URL with the default one."
+	},
+	"labelDataImport": {
+		"message": "Data Import",
+		"description": "Section title of data import."
+	},
+	"buttonImportData": {
+		"message": "Importovat ze souboru zip",
+		"description": "Button to choose a file for data import."
+	},
+	"buttonVacuumData": {
+		"message": "Vyprázdnit data",
+		"description": "Button to vacuum extension data."
+	},
+	"labelDataExport": {
+		"message": "Data Export",
+		"description": "Section title of data export."
+	},
+	"labelScriptsToExport": {
+		"message": "Scripts to export",
+		"description": "Label shown on top of the script list for export."
+	},
+	"labelExportScriptData": {
+		"message": "Export data skriptu",
+		"description": "Option to export script data along with scripts."
+	},
+	"buttonAllNone": {
+		"message": "Vše/Žádný",
+		"description": "Button to select all scripts or none."
+	},
+	"buttonExportData": {
+		"message": "Exportovat do souboru zip",
+		"description": "Button to open the data export dialog."
+	},
+	"labelAbout": {
+		"message": "About Violentmonkey",
+		"description": "Label shown on top of the about page."
+	},
+	"labelSupportPage": {
+		"message": "Support page: ",
+		"description": "Label of support page."
+	},
+	"anchorSupportPage": {
+		"message": "<a href=https://github.com/gera2ld/Violentmonkey/wiki target=_blank>Violentmonkey</a>",
+		"description": "Link to the support page of Violentmonkey."
+	},
+	"labelAuthor": {
+		"message": "Autor: ",
+		"description": "Label of author shown in the details of a script."
+	},
+	"anchorAuthor": {
+		"message": "<a href=mailto:[email protected]>Gerald</a>",
+		"description": "Author shown on about tab."
+	},
+	"labelTranslator": {
+		"message": "Translator: ",
+		"description": "Label of translator."
+	},
+	"anchorTranslator": {
+		"message": "<a href=http://my.opera.com/ahoj1234 target=_blank>ahoj1234</a>",
+		"description": "Translator shown on about tab."
+	},
 	"labelScriptEditor": {
 	"labelScriptEditor": {
 		"message": "Editor skriptů",
 		"message": "Editor skriptů",
 		"description": "Shown in the title of the script editing page."
 		"description": "Shown in the title of the script editing page."
@@ -139,18 +199,6 @@
 		"message": "Vlastní meta data",
 		"message": "Vlastní meta data",
 		"description": "Button to edit the custom meta data of a script."
 		"description": "Button to edit the custom meta data of a script."
 	},
 	},
-	"labelAllowUpdate": {
-		"message": "Povolit aktualizace",
-		"description": "Option to allow checking updates for a script."
-	},
-	"buttonSave": {
-		"message": "Uložit",
-		"description": "Button to save modifications of a script."
-	},
-	"buttonSaveClose": {
-		"message": "Uložit a Zavřít",
-		"description": "Button to save modifications of a script and then close the editing page."
-	},
 	"labelName": {
 	"labelName": {
 		"message": "Jméno:",
 		"message": "Jméno:",
 		"description": "Label of script name."
 		"description": "Label of script name."
@@ -211,69 +259,21 @@
 		"message": "Vlastní pravidla pro výjimky: <em>(Jedno na řádek)</em>",
 		"message": "Vlastní pravidla pro výjimky: <em>(Jedno na řádek)</em>",
 		"description": "Label of custom @exclude rules."
 		"description": "Label of custom @exclude rules."
 	},
 	},
-	"buttonOK": {
-		"message": "OK",
-		"description": "Button to confirm modifications."
-	},
-	"buttonCancel": {
-		"message": "Zrušit",
-		"description": "Button to cancel modifications."
-	},
-	"labelExport": {
-		"message": "Export dat",
-		"description": "Label shown in the title of export dialog."
-	},
-	"anchorExportOptions": {
-		"message": "Možnosti",
-		"description": "Options of export."
-	},
-	"labelExportScriptData": {
-		"message": "Export data skriptu",
-		"description": "Option to export script data along with scripts."
-	},
-	"buttonAllNone": {
-		"message": "Vše/Žádný",
-		"description": "Button to select all scripts or none."
-	},
-	"labelAdvanced": {
-		"message": "Pokročilé",
-		"description": "Label shown in the title of advanced dialog."
-	},
-	"labelAutoUpdate": {
-		"message": "Automaticky kontrolovat aktualizace skriptu každý den",
-		"description": "Option to allow automatically checking scripts for updates every 24 hours."
-	},
-	"labelSearchLink": {
-		"message": "hledat URL: ",
-		"description": "Label of URL for searching scripts for a site."
-	},
-	"buttonDefault": {
-		"message": "Výchozí",
-		"description": "Button to replace search URL with the default one."
-	},
-	"labelData": {
-		"message": "Data",
-		"description": "Label of extension data management."
-	},
-	"buttonExportData": {
-		"message": "Exportovat do souboru zip",
-		"description": "Button to open the data export dialog."
-	},
-	"buttonImportData": {
-		"message": "Importovat ze souboru zip",
-		"description": "Button to choose a file for data import."
+	"labelAllowUpdate": {
+		"message": "Povolit aktualizace",
+		"description": "Option to allow checking updates for a script."
 	},
 	},
-	"buttonVacuumData": {
-		"message": "Vyprázdnit data",
-		"description": "Button to vacuum extension data."
+	"buttonSave": {
+		"message": "Uložit",
+		"description": "Button to save modifications of a script."
 	},
 	},
-	"anchorUpdate": {
-		"message": "Zkontrolovat aktualizace",
-		"description": "Check a script for updates."
+	"buttonSaveClose": {
+		"message": "Uložit a Zavřít",
+		"description": "Button to save modifications of a script and then close the editing page."
 	},
 	},
-	"buttonEdit": {
-		"message": "Editovat",
-		"description": "Button to edit a script."
+	"labelNoName": {
+		"message": "Jméno nebylo definováno",
+		"description": "Text as the name of a script when no @name is assigned."
 	},
 	},
 	"buttonDisable": {
 	"buttonDisable": {
 		"message": "Vypnout",
 		"message": "Vypnout",
@@ -283,17 +283,17 @@
 		"message": "Zapnout",
 		"message": "Zapnout",
 		"description": "Button to enable a script."
 		"description": "Button to enable a script."
 	},
 	},
+	"buttonEdit": {
+		"message": "Editovat",
+		"description": "Button to edit a script."
+	},
 	"buttonRemove": {
 	"buttonRemove": {
 		"message": "Odstranit",
 		"message": "Odstranit",
 		"description": "Button to remove a script."
 		"description": "Button to remove a script."
 	},
 	},
-	"labelNoName": {
-		"message": "Jméno nebylo definováno",
-		"description": "Text as the name of a script when no @name is assigned."
-	},
-	"labelAuthor": {
-		"message": "Autor: ",
-		"description": "Label of author shown in the details of a script."
+	"anchorUpdate": {
+		"message": "Zkontrolovat aktualizace",
+		"description": "Check a script for updates."
 	},
 	},
 	"confirmNotSaved": {
 	"confirmNotSaved": {
 		"message": "Modifikace není uložena! Klikni na OK pro zbavení se jí, nebo na zrušit pro zůstání zde.",
 		"message": "Modifikace není uložena! Klikni na OK pro zbavení se jí, nebo na zrušit pro zůstání zde.",
@@ -315,14 +315,6 @@
 		"message": "Zbavit se nadbytečného a zkusit znovu načíst chybějící zdroje v cache.",
 		"message": "Zbavit se nadbytečného a zkusit znovu načíst chybějící zdroje v cache.",
 		"description": "Hint for vacuuming data."
 		"description": "Hint for vacuuming data."
 	},
 	},
-	"buttonExport": {
-		"message": "Exportovat",
-		"description": "Button to confirm export."
-	},
-	"buttonExporting": {
-		"message": "Exportování dat...",
-		"description": "Message shown when data export is in progress."
-	},
 	"buttonVacuumed": {
 	"buttonVacuumed": {
 		"message": "Data vyprázdněna",
 		"message": "Data vyprázdněna",
 		"description": "Message shown when data is vacuumed."
 		"description": "Message shown when data is vacuumed."

+ 110 - 118
_locales/en/messages.json

@@ -47,10 +47,6 @@
 		"message": "No update found.",
 		"message": "No update found.",
 		"description": "Message shown when there is no new version of a script."
 		"description": "Message shown when there is no new version of a script."
 	},
 	},
-	"css": {
-		"message": "html{font-family:Calibri,Arial;}",
-		"description": "Additional CSS for all pages."
-	},
 	"labelInstall": {
 	"labelInstall": {
 		"message": "Installing script",
 		"message": "Installing script",
 		"description": "Shown in the title of the confirm page while trying to install a script."
 		"description": "Shown in the title of the confirm page while trying to install a script."
@@ -67,14 +63,6 @@
 		"message": "Close",
 		"message": "Close",
 		"description": "Button to close window."
 		"description": "Button to close window."
 	},
 	},
-	"anchorSupportPage": {
-		"message": "<a href=https://github.com/gera2ld/Violentmonkey/wiki target=_blank>Violentmonkey</a>",
-		"description": "Link to the support page of Violentmonkey."
-	},
-	"anchorAuthor": {
-		"message": "Designed by <a href=mailto:[email protected]>Gerald</a>",
-		"description": "Author shown in the footer of options page, translator information may be added."
-	},
 	"msgScriptURL": {
 	"msgScriptURL": {
 		"message": "Script URL: $1",
 		"message": "Script URL: $1",
 		"description": "URL of the script to be installed on confirm page."
 		"description": "URL of the script to be installed on confirm page."
@@ -99,38 +87,110 @@
 		"message": "Error loading requirements.",
 		"message": "Error loading requirements.",
 		"description": "Message shown when not all requirements are loaded successfully."
 		"description": "Message shown when not all requirements are loaded successfully."
 	},
 	},
-	"labelOptions": {
-		"message": "Options",
-		"description": "Options of this extension."
+	"anchorGetMoreScripts": {
+		"message": "<a href=http://userscripts.org target=_blank>Get more scripts</a>",
+		"description": "Link to get more scripts."
+	},
+	"sideMenuInstalled": {
+		"message": "Installed scripts",
+		"description": "Side menu: Installed scripts"
+	},
+	"sideMenuSettings": {
+		"message": "Settings",
+		"description": "Side menu: Settings"
+	},
+	"sideMenuAbout": {
+		"message": "About",
+		"description": "Side menu: About"
 	},
 	},
 	"buttonNew": {
 	"buttonNew": {
 		"message": "New",
 		"message": "New",
 		"description": "Button to create a new script."
 		"description": "Button to create a new script."
 	},
 	},
-	"anchorGetMoreScripts": {
-		"message": "<a href=http://userscripts.org target=_blank>Get more scripts from userscripts.org</a>",
-		"description": "Link to get more scripts."
-	},
 	"anchorUpdateAll": {
 	"anchorUpdateAll": {
 		"message": "Check all for updates",
 		"message": "Check all for updates",
 		"description": "Check all scripts for updates."
 		"description": "Check all scripts for updates."
 	},
 	},
-	"buttonAdvanced": {
-		"message": "Advanced",
-		"description": "Button to show the advanced options."
-	},
-	"labelInstalledScripts": {
-		"message": "Installed scripts",
-		"description": "Label of the list of installed scripts."
-	},
-	"labelShowDetails": {
-		"message": "Show details",
-		"description": "Option to show the details of scripts, such as author, description, etc."
-	},
 	"msgLoading": {
 	"msgLoading": {
 		"message": "Loading ...",
 		"message": "Loading ...",
 		"description": "Message shown in the options page before script list is loaded."
 		"description": "Message shown in the options page before script list is loaded."
 	},
 	},
+	"labelSettings": {
+		"message": "Settings",
+		"description": "Label shown on the top of settings page"
+	},
+	"labelAutoUpdate": {
+		"message": "Automatically check scripts for updates every day",
+		"description": "Option to allow automatically checking scripts for updates every 24 hours."
+	},
+	"labelSearchLink": {
+		"message": "Search URL: ",
+		"description": "Label of URL for searching scripts for a site."
+	},
+	"buttonDefault": {
+		"message": "Default",
+		"description": "Button to replace search URL with the default one."
+	},
+	"labelDataImport": {
+		"message": "Data Import",
+		"description": "Section title of data import."
+	},
+	"buttonImportData": {
+		"message": "Import from zip",
+		"description": "Button to choose a file for data import."
+	},
+	"buttonVacuumData": {
+		"message": "Vacuum data",
+		"description": "Button to vacuum extension data."
+	},
+	"labelDataExport": {
+		"message": "Data Export",
+		"description": "Section title of data export."
+	},
+	"labelScriptsToExport": {
+		"message": "Scripts to export",
+		"description": "Label shown on top of the script list for export."
+	},
+	"labelExportScriptData": {
+		"message": "Export script data",
+		"description": "Option to export script data along with scripts."
+	},
+	"buttonAllNone": {
+		"message": "All/None",
+		"description": "Button to select all scripts or none."
+	},
+	"buttonExportData": {
+		"message": "Export to zip",
+		"description": "Button to open the data export dialog."
+	},
+	"labelAbout": {
+		"message": "About Violentmonkey",
+		"description": "Label shown on top of the about page."
+	},
+	"labelSupportPage": {
+		"message": "Support page: ",
+		"description": "Label of support page."
+	},
+	"anchorSupportPage": {
+		"message": "<a href=https://github.com/gera2ld/Violentmonkey/wiki target=_blank>Violentmonkey</a>",
+		"description": "Link to the support page of Violentmonkey."
+	},
+	"labelAuthor": {
+		"message": "Author: ",
+		"description": "Label of author shown in the details of a script."
+	},
+	"anchorAuthor": {
+		"message": "<a href=mailto:[email protected]>Gerald</a>",
+		"description": "Author shown on about tab."
+	},
+	"labelTranslator": {
+		"message": "Translator: ",
+		"description": "Label of translator."
+	},
+	"anchorTranslator": {
+		"message": "<a href=mailto:[email protected]>Gerald</a>",
+		"description": "Translator shown on about tab."
+	},
 	"labelScriptEditor": {
 	"labelScriptEditor": {
 		"message": "Script Editor",
 		"message": "Script Editor",
 		"description": "Shown in the title of the script editing page."
 		"description": "Shown in the title of the script editing page."
@@ -139,18 +199,6 @@
 		"message": "Custom meta data",
 		"message": "Custom meta data",
 		"description": "Button to edit the custom meta data of a script."
 		"description": "Button to edit the custom meta data of a script."
 	},
 	},
-	"labelAllowUpdate": {
-		"message": "Allow update",
-		"description": "Option to allow checking updates for a script."
-	},
-	"buttonSave": {
-		"message": "Save",
-		"description": "Button to save modifications of a script."
-	},
-	"buttonSaveClose": {
-		"message": "Save & Close",
-		"description": "Button to save modifications of a script and then close the editing page."
-	},
 	"labelName": {
 	"labelName": {
 		"message": "Name:",
 		"message": "Name:",
 		"description": "Label of script name."
 		"description": "Label of script name."
@@ -211,69 +259,21 @@
 		"message": "Custom exclude rules: <em>(One per line)</em>",
 		"message": "Custom exclude rules: <em>(One per line)</em>",
 		"description": "Label of custom @exclude rules."
 		"description": "Label of custom @exclude rules."
 	},
 	},
-	"buttonOK": {
-		"message": "OK",
-		"description": "Button to confirm modifications."
-	},
-	"buttonCancel": {
-		"message": "Cancel",
-		"description": "Button to cancel modifications."
-	},
-	"labelExport": {
-		"message": "Data Export",
-		"description": "Label shown in the title of export dialog."
-	},
-	"anchorExportOptions": {
-		"message": "Options",
-		"description": "Options of export."
-	},
-	"labelExportScriptData": {
-		"message": "Export script data",
-		"description": "Option to export script data along with scripts."
-	},
-	"buttonAllNone": {
-		"message": "All/None",
-		"description": "Button to select all scripts or none."
-	},
-	"labelAdvanced": {
-		"message": "Advanced",
-		"description": "Label shown in the title of advanced dialog."
-	},
-	"labelAutoUpdate": {
-		"message": "Automatically check scripts for updates every day",
-		"description": "Option to allow automatically checking scripts for updates every 24 hours."
-	},
-	"labelSearchLink": {
-		"message": "Search URL: ",
-		"description": "Label of URL for searching scripts for a site."
-	},
-	"buttonDefault": {
-		"message": "Default",
-		"description": "Button to replace search URL with the default one."
-	},
-	"labelData": {
-		"message": "Data",
-		"description": "Label of extension data management."
-	},
-	"buttonExportData": {
-		"message": "Export to zip",
-		"description": "Button to open the data export dialog."
-	},
-	"buttonImportData": {
-		"message": "Import from zip",
-		"description": "Button to choose a file for data import."
+	"labelAllowUpdate": {
+		"message": "Allow update",
+		"description": "Option to allow checking updates for a script."
 	},
 	},
-	"buttonVacuumData": {
-		"message": "Vacuum data",
-		"description": "Button to vacuum extension data."
+	"buttonSave": {
+		"message": "Save",
+		"description": "Button to save modifications of a script."
 	},
 	},
-	"anchorUpdate": {
-		"message": "Check for updates",
-		"description": "Check a script for updates."
+	"buttonSaveClose": {
+		"message": "Save & Close",
+		"description": "Button to save modifications of a script and then close the editing page."
 	},
 	},
-	"buttonEdit": {
-		"message": "Edit",
-		"description": "Button to edit a script."
+	"labelNoName": {
+		"message": "No Name",
+		"description": "Text as the name of a script when no @name is assigned."
 	},
 	},
 	"buttonDisable": {
 	"buttonDisable": {
 		"message": "Disable",
 		"message": "Disable",
@@ -283,17 +283,17 @@
 		"message": "Enable",
 		"message": "Enable",
 		"description": "Button to enable a script."
 		"description": "Button to enable a script."
 	},
 	},
+	"buttonEdit": {
+		"message": "Edit",
+		"description": "Button to edit a script."
+	},
 	"buttonRemove": {
 	"buttonRemove": {
 		"message": "Remove",
 		"message": "Remove",
 		"description": "Button to remove a script."
 		"description": "Button to remove a script."
 	},
 	},
-	"labelNoName": {
-		"message": "No Name",
-		"description": "Text as the name of a script when no @name is assigned."
-	},
-	"labelAuthor": {
-		"message": "Author: ",
-		"description": "Label of author shown in the details of a script."
+	"anchorUpdate": {
+		"message": "Check for updates",
+		"description": "Check a script for updates."
 	},
 	},
 	"confirmNotSaved": {
 	"confirmNotSaved": {
 		"message": "Modifications are not saved!\nClick OK to discard them or cancel to stay.",
 		"message": "Modifications are not saved!\nClick OK to discard them or cancel to stay.",
@@ -315,14 +315,6 @@
 		"message": "Discard the redundancy and try to reload the missing resources in cache.",
 		"message": "Discard the redundancy and try to reload the missing resources in cache.",
 		"description": "Hint for vacuuming data."
 		"description": "Hint for vacuuming data."
 	},
 	},
-	"buttonExport": {
-		"message": "Export",
-		"description": "Button to confirm export."
-	},
-	"buttonExporting": {
-		"message": "Exporting data...",
-		"description": "Message shown when data export is in progress."
-	},
 	"buttonVacuumed": {
 	"buttonVacuumed": {
 		"message": "Data vacuumed",
 		"message": "Data vacuumed",
 		"description": "Message shown when data is vacuumed."
 		"description": "Message shown when data is vacuumed."

+ 110 - 118
_locales/pl/messages.json

@@ -47,10 +47,6 @@
 		"message": "Nie znaleziono aktualizacji.",
 		"message": "Nie znaleziono aktualizacji.",
 		"description": "Message shown when there is no new version of a script."
 		"description": "Message shown when there is no new version of a script."
 	},
 	},
-	"css": {
-		"message": "html{font-family:Calibri,Arial;}",
-		"description": "Additional CSS for all pages."
-	},
 	"labelInstall": {
 	"labelInstall": {
 		"message": "Instalowanie skryptu",
 		"message": "Instalowanie skryptu",
 		"description": "Shown in the title of the confirm page while trying to install a script."
 		"description": "Shown in the title of the confirm page while trying to install a script."
@@ -67,14 +63,6 @@
 		"message": "Zamknij",
 		"message": "Zamknij",
 		"description": "Button to close window."
 		"description": "Button to close window."
 	},
 	},
-	"anchorSupportPage": {
-		"message": "<a href=https://github.com/gera2ld/Violentmonkey/wiki target=_blank>Violentmonkey</a>",
-		"description": "Link to the support page of Violentmonkey."
-	},
-	"anchorAuthor": {
-		"message": "Stworzone przez <a href=mailto:[email protected]>Gerald</a>, tłumaczenie MISI90",
-		"description": "Author shown in the footer of options page, translator information may be added."
-	},
 	"msgScriptURL": {
 	"msgScriptURL": {
 		"message": "Skrypt URL: $1",
 		"message": "Skrypt URL: $1",
 		"description": "URL of the script to be installed on confirm page."
 		"description": "URL of the script to be installed on confirm page."
@@ -99,38 +87,110 @@
 		"message": "Błąd podczas ładowania wymagania.",
 		"message": "Błąd podczas ładowania wymagania.",
 		"description": "Message shown when not all requirements are loaded successfully."
 		"description": "Message shown when not all requirements are loaded successfully."
 	},
 	},
-	"labelOptions": {
-		"message": "Opcje",
-		"description": "Options of this extension."
+	"anchorGetMoreScripts": {
+		"message": "<a href=http://userscripts.org target=_blank>Znajdź nowe skrypty</a>",
+		"description": "Link to get more scripts."
+	},
+	"sideMenuInstalled": {
+		"message": "Zainstalowane skrypty",
+		"description": "Side menu: Installed scripts"
+	},
+	"sideMenuSettings": {
+		"message": "Settings",
+		"description": "Side menu: Settings"
+	},
+	"sideMenuAbout": {
+		"message": "About",
+		"description": "Side menu: About"
 	},
 	},
 	"buttonNew": {
 	"buttonNew": {
 		"message": "Nowy",
 		"message": "Nowy",
 		"description": "Button to create a new script."
 		"description": "Button to create a new script."
 	},
 	},
-	"anchorGetMoreScripts": {
-		"message": "<a href=http://userscripts.org target=_blank>Znajdź nowe skrypty na userscripts.org</a>",
-		"description": "Link to get more scripts."
-	},
 	"anchorUpdateAll": {
 	"anchorUpdateAll": {
 		"message": "Sprawdź aktualizacje dla wszystkich",
 		"message": "Sprawdź aktualizacje dla wszystkich",
 		"description": "Check all scripts for updates."
 		"description": "Check all scripts for updates."
 	},
 	},
-	"buttonAdvanced": {
-		"message": "Zaawansowane",
-		"description": "Button to show the advanced options."
-	},
-	"labelInstalledScripts": {
-		"message": "Zainstalowane skrypty",
-		"description": "Label of the list of installed scripts."
-	},
-	"labelShowDetails": {
-		"message": "Pokaż szczegóły",
-		"description": "Option to show the details of scripts, such as author, description, etc."
-	},
 	"msgLoading": {
 	"msgLoading": {
 		"message": "Ładowanie ...",
 		"message": "Ładowanie ...",
 		"description": "Message shown in the options page before script list is loaded."
 		"description": "Message shown in the options page before script list is loaded."
 	},
 	},
+	"labelSettings": {
+		"message": "Settings",
+		"description": "Label shown on the top of settings page"
+	},
+	"labelAutoUpdate": {
+		"message": "Automatycznie sprawdzaj aktualizacje dla skryptów każdego dnia",
+		"description": "Option to allow automatically checking scripts for updates every 24 hours."
+	},
+	"labelSearchLink": {
+		"message": "Adres wyszukiwarki:",
+		"description": "Label of URL for searching scripts for a site."
+	},
+	"buttonDefault": {
+		"message": "Domyślne",
+		"description": "Button to replace search URL with the default one."
+	},
+	"labelDataImport": {
+		"message": "Data Import",
+		"description": "Section title of data import."
+	},
+	"buttonImportData": {
+		"message": "Importuj z pliku zip",
+		"description": "Button to choose a file for data import."
+	},
+	"buttonVacuumData": {
+		"message": "Wyczyść dane",
+		"description": "Button to vacuum extension data."
+	},
+	"labelDataExport": {
+		"message": "Data Export",
+		"description": "Section title of data export."
+	},
+	"labelScriptsToExport": {
+		"message": "Scripts to export",
+		"description": "Label shown on top of the script list for export."
+	},
+	"labelExportScriptData": {
+		"message": "Eksportuj dane skryptu",
+		"description": "Option to export script data along with scripts."
+	},
+	"buttonAllNone": {
+		"message": "Wszystkie/Żaden",
+		"description": "Button to select all scripts or none."
+	},
+	"buttonExportData": {
+		"message": "Eksportuj do pliku zip",
+		"description": "Button to open the data export dialog."
+	},
+	"labelAbout": {
+		"message": "About Violentmonkey",
+		"description": "Label shown on top of the about page."
+	},
+	"labelSupportPage": {
+		"message": "Support page: ",
+		"description": "Label of support page."
+	},
+	"anchorSupportPage": {
+		"message": "<a href=https://github.com/gera2ld/Violentmonkey/wiki target=_blank>Violentmonkey</a>",
+		"description": "Link to the support page of Violentmonkey."
+	},
+	"labelAuthor": {
+		"message": "Autor: ",
+		"description": "Label of author shown in the details of a script."
+	},
+	"anchorAuthor": {
+		"message": "<a href=mailto:[email protected]>Gerald</a>",
+		"description": "Author shown on about tab."
+	},
+	"labelTranslator": {
+		"message": "Translator: ",
+		"description": "Label of translator."
+	},
+	"anchorTranslator": {
+		"message": "MISI90",
+		"description": "Translator shown on about tab."
+	},
 	"labelScriptEditor": {
 	"labelScriptEditor": {
 		"message": "Edytor skryptów",
 		"message": "Edytor skryptów",
 		"description": "Shown in the title of the script editing page."
 		"description": "Shown in the title of the script editing page."
@@ -139,18 +199,6 @@
 		"message": "Własne dane meta",
 		"message": "Własne dane meta",
 		"description": "Button to edit the custom meta data of a script."
 		"description": "Button to edit the custom meta data of a script."
 	},
 	},
-	"labelAllowUpdate": {
-		"message": "Zezwól na aktualizacje",
-		"description": "Option to allow checking updates for a script."
-	},
-	"buttonSave": {
-		"message": "Zapisz",
-		"description": "Button to save modifications of a script."
-	},
-	"buttonSaveClose": {
-		"message": "Zapisz i zamknij",
-		"description": "Button to save modifications of a script and then close the editing page."
-	},
 	"labelName": {
 	"labelName": {
 		"message": "Nazwa:",
 		"message": "Nazwa:",
 		"description": "Label of script name."
 		"description": "Label of script name."
@@ -211,69 +259,21 @@
 		"message": "Własne zasady exclude: <em>(Jedna na linię)</em>",
 		"message": "Własne zasady exclude: <em>(Jedna na linię)</em>",
 		"description": "Label of custom @exclude rules."
 		"description": "Label of custom @exclude rules."
 	},
 	},
-	"buttonOK": {
-		"message": "OK",
-		"description": "Button to confirm modifications."
-	},
-	"buttonCancel": {
-		"message": "Anuluj",
-		"description": "Button to cancel modifications."
-	},
-	"labelExport": {
-		"message": "Eksport danych",
-		"description": "Label shown in the title of export dialog."
-	},
-	"anchorExportOptions": {
-		"message": "Opcje",
-		"description": "Options of export."
-	},
-	"labelExportScriptData": {
-		"message": "Eksportuj dane skryptu",
-		"description": "Option to export script data along with scripts."
-	},
-	"buttonAllNone": {
-		"message": "Wszystkie/Żaden",
-		"description": "Button to select all scripts or none."
-	},
-	"labelAdvanced": {
-		"message": "Zaawansowane",
-		"description": "Label shown in the title of advanced dialog."
-	},
-	"labelAutoUpdate": {
-		"message": "Automatycznie sprawdzaj aktualizacje dla skryptów każdego dnia",
-		"description": "Option to allow automatically checking scripts for updates every 24 hours."
-	},
-	"labelSearchLink": {
-		"message": "Adres wyszukiwarki:",
-		"description": "Label of URL for searching scripts for a site."
-	},
-	"buttonDefault": {
-		"message": "Domyślne",
-		"description": "Button to replace search URL with the default one."
-	},
-	"labelData": {
-		"message": "Dane",
-		"description": "Label of extension data management."
-	},
-	"buttonExportData": {
-		"message": "Eksportuj do pliku zip",
-		"description": "Button to open the data export dialog."
-	},
-	"buttonImportData": {
-		"message": "Importuj z pliku zip",
-		"description": "Button to choose a file for data import."
+	"labelAllowUpdate": {
+		"message": "Zezwól na aktualizacje",
+		"description": "Option to allow checking updates for a script."
 	},
 	},
-	"buttonVacuumData": {
-		"message": "Wyczyść dane",
-		"description": "Button to vacuum extension data."
+	"buttonSave": {
+		"message": "Zapisz",
+		"description": "Button to save modifications of a script."
 	},
 	},
-	"anchorUpdate": {
-		"message": "Sprawdź aktualizacje",
-		"description": "Check a script for updates."
+	"buttonSaveClose": {
+		"message": "Zapisz i zamknij",
+		"description": "Button to save modifications of a script and then close the editing page."
 	},
 	},
-	"buttonEdit": {
-		"message": "Edytuj",
-		"description": "Button to edit a script."
+	"labelNoName": {
+		"message": "Pusta nazwa",
+		"description": "Text as the name of a script when no @name is assigned."
 	},
 	},
 	"buttonDisable": {
 	"buttonDisable": {
 		"message": "Wyłącz",
 		"message": "Wyłącz",
@@ -283,17 +283,17 @@
 		"message": "Włącz",
 		"message": "Włącz",
 		"description": "Button to enable a script."
 		"description": "Button to enable a script."
 	},
 	},
+	"buttonEdit": {
+		"message": "Edytuj",
+		"description": "Button to edit a script."
+	},
 	"buttonRemove": {
 	"buttonRemove": {
 		"message": "Usuń",
 		"message": "Usuń",
 		"description": "Button to remove a script."
 		"description": "Button to remove a script."
 	},
 	},
-	"labelNoName": {
-		"message": "Pusta nazwa",
-		"description": "Text as the name of a script when no @name is assigned."
-	},
-	"labelAuthor": {
-		"message": "Autor: ",
-		"description": "Label of author shown in the details of a script."
+	"anchorUpdate": {
+		"message": "Sprawdź aktualizacje",
+		"description": "Check a script for updates."
 	},
 	},
 	"confirmNotSaved": {
 	"confirmNotSaved": {
 		"message": "Modyfikacje nie zostały zapisane! Kliknij OK aby wyjść lub Anuluj aby zostać.",
 		"message": "Modyfikacje nie zostały zapisane! Kliknij OK aby wyjść lub Anuluj aby zostać.",
@@ -315,14 +315,6 @@
 		"message": "Usuń nadmiarowość i spróbuj przeładować brakujące dane w cache.",
 		"message": "Usuń nadmiarowość i spróbuj przeładować brakujące dane w cache.",
 		"description": "Hint for vacuuming data."
 		"description": "Hint for vacuuming data."
 	},
 	},
-	"buttonExport": {
-		"message": "Eksportuj",
-		"description": "Button to confirm export."
-	},
-	"buttonExporting": {
-		"message": "Eksportowanie danych...",
-		"description": "Message shown when data export is in progress."
-	},
 	"buttonVacuumed": {
 	"buttonVacuumed": {
 		"message": "Dane wyczyszczone",
 		"message": "Dane wyczyszczone",
 		"description": "Message shown when data is vacuumed."
 		"description": "Message shown when data is vacuumed."

+ 111 - 119
_locales/ru/messages.json

@@ -47,10 +47,6 @@
 		"message": "Обновления не найдены.",
 		"message": "Обновления не найдены.",
 		"description": "Message shown when there is no new version of a script."
 		"description": "Message shown when there is no new version of a script."
 	},
 	},
-	"css": {
-		"message": "html{font-family:Calibri,Arial;}",
-		"description": "Additional CSS for all pages."
-	},
 	"labelInstall": {
 	"labelInstall": {
 		"message": "Установка скрипта",
 		"message": "Установка скрипта",
 		"description": "Shown in the title of the confirm page while trying to install a script."
 		"description": "Shown in the title of the confirm page while trying to install a script."
@@ -67,14 +63,6 @@
 		"message": "Закрыть",
 		"message": "Закрыть",
 		"description": "Button to close window."
 		"description": "Button to close window."
 	},
 	},
-	"anchorSupportPage": {
-		"message": "<a href=https://github.com/gera2ld/Violentmonkey/wiki target=_blank>Violentmonkey</a>",
-		"description": "Link to the support page of Violentmonkey."
-	},
-	"anchorAuthor": {
-		"message": "Разработано <a href=mailto:[email protected]>Gerald</a>",
-		"description": "Author shown in the footer of options page, translator information may be added."
-	},
 	"msgScriptURL": {
 	"msgScriptURL": {
 		"message": "URL-адрес скрипта: $1",
 		"message": "URL-адрес скрипта: $1",
 		"description": "URL of the script to be installed on confirm page."
 		"description": "URL of the script to be installed on confirm page."
@@ -99,38 +87,110 @@
 		"message": "Ошибка загрузки требований.",
 		"message": "Ошибка загрузки требований.",
 		"description": "Message shown when not all requirements are loaded successfully."
 		"description": "Message shown when not all requirements are loaded successfully."
 	},
 	},
-	"labelOptions": {
-		"message": "Опции",
-		"description": "Options of this extension."
+	"anchorGetMoreScripts": {
+		"message": "<a href=http://userscripts.org target=_blank>Скачать скрипты</a>",
+		"description": "Link to get more scripts."
+	},
+	"sideMenuInstalled": {
+		"message": "Установленные скрипты",
+		"description": "Side menu: Installed scripts"
+	},
+	"sideMenuSettings": {
+		"message": "Settings",
+		"description": "Side menu: Settings"
+	},
+	"sideMenuAbout": {
+		"message": "About",
+		"description": "Side menu: About"
 	},
 	},
 	"buttonNew": {
 	"buttonNew": {
 		"message": "Создать",
 		"message": "Создать",
 		"description": "Button to create a new script."
 		"description": "Button to create a new script."
 	},
 	},
-	"anchorGetMoreScripts": {
-		"message": "<a href=http://userscripts.org target=_blank>Скачать скрипты с userscripts.org</a>",
-		"description": "Link to get more scripts."
-	},
 	"anchorUpdateAll": {
 	"anchorUpdateAll": {
 		"message": "Проверить обновления скриптов",
 		"message": "Проверить обновления скриптов",
 		"description": "Check all scripts for updates."
 		"description": "Check all scripts for updates."
 	},
 	},
-	"buttonAdvanced": {
-		"message": "Дополнительно",
-		"description": "Button to show the advanced options."
-	},
-	"labelInstalledScripts": {
-		"message": "Установленные скрипты",
-		"description": "Label of the list of installed scripts."
-	},
-	"labelShowDetails": {
-		"message": "Подробно",
-		"description": "Option to show the details of scripts, such as author, description, etc."
-	},
 	"msgLoading": {
 	"msgLoading": {
 		"message": "Загрузка...",
 		"message": "Загрузка...",
 		"description": "Message shown in the options page before script list is loaded."
 		"description": "Message shown in the options page before script list is loaded."
 	},
 	},
+	"labelSettings": {
+		"message": "Settings",
+		"description": "Label shown on the top of settings page"
+	},
+	"labelAutoUpdate": {
+		"message": "Ежедневно проверять обновления скриптов",
+		"description": "Option to allow automatically checking scripts for updates every 24 hours."
+	},
+	"labelSearchLink": {
+		"message": "Поисковый адрес: ",
+		"description": "Label of URL for searching scripts for a site."
+	},
+	"buttonDefault": {
+		"message": "По умолчанию",
+		"description": "Button to replace search URL with the default one."
+	},
+	"labelDataImport": {
+		"message": "Data Import",
+		"description": "Section title of data import."
+	},
+	"buttonImportData": {
+		"message": "Импорт из zip-файла",
+		"description": "Button to choose a file for data import."
+	},
+	"buttonVacuumData": {
+		"message": "Сбросить кэш",
+		"description": "Button to vacuum extension data."
+	},
+	"labelDataExport": {
+		"message": "Data Export",
+		"description": "Section title of data export."
+	},
+	"labelScriptsToExport": {
+		"message": "Scripts to export",
+		"description": "Label shown on top of the script list for export."
+	},
+	"labelExportScriptData": {
+		"message": "Настройки скрипта",
+		"description": "Option to export script data along with scripts."
+	},
+	"buttonAllNone": {
+		"message": "Выбрать Всё/Ничего",
+		"description": "Button to select all scripts or none."
+	},
+	"buttonExportData": {
+		"message": "Экспорт в zip-файл",
+		"description": "Button to open the data export dialog."
+	},
+	"labelAbout": {
+		"message": "About Violentmonkey",
+		"description": "Label shown on top of the about page."
+	},
+	"labelSupportPage": {
+		"message": "Support page: ",
+		"description": "Label of support page."
+	},
+	"anchorSupportPage": {
+		"message": "<a href=https://github.com/gera2ld/Violentmonkey/wiki target=_blank>Violentmonkey</a>",
+		"description": "Link to the support page of Violentmonkey."
+	},
+	"labelAuthor": {
+		"message": "Автор: ",
+		"description": "Label of author shown in the details of a script."
+	},
+	"anchorAuthor": {
+		"message": "<a href=mailto:[email protected]>Gerald</a>",
+		"description": "Author shown on about tab."
+	},
+	"labelTranslator": {
+		"message": "Translator: ",
+		"description": "Label of translator."
+	},
+	"anchorTranslator": {
+		"message": "softovikk",
+		"description": "Translator shown on about tab."
+	},
 	"labelScriptEditor": {
 	"labelScriptEditor": {
 		"message": "Редактор скриптов",
 		"message": "Редактор скриптов",
 		"description": "Shown in the title of the script editing page."
 		"description": "Shown in the title of the script editing page."
@@ -139,18 +199,6 @@
 		"message": "Пользовательские meta-данные",
 		"message": "Пользовательские meta-данные",
 		"description": "Button to edit the custom meta data of a script."
 		"description": "Button to edit the custom meta data of a script."
 	},
 	},
-	"labelAllowUpdate": {
-		"message": "Разрешить обновление",
-		"description": "Option to allow checking updates for a script."
-	},
-	"buttonSave": {
-		"message": "Сохранить",
-		"description": "Button to save modifications of a script."
-	},
-	"buttonSaveClose": {
-		"message": "Сохранить и закрыть",
-		"description": "Button to save modifications of a script and then close the editing page."
-	},
 	"labelName": {
 	"labelName": {
 		"message": "Название:",
 		"message": "Название:",
 		"description": "Label of script name."
 		"description": "Label of script name."
@@ -211,69 +259,21 @@
 		"message": "Пользовательские правила (одно на строку):",
 		"message": "Пользовательские правила (одно на строку):",
 		"description": "Label of custom @exclude rules."
 		"description": "Label of custom @exclude rules."
 	},
 	},
-	"buttonOK": {
-		"message": "Готово",
-		"description": "Button to confirm modifications."
-	},
-	"buttonCancel": {
-		"message": "Отмена",
-		"description": "Button to cancel modifications."
-	},
-	"labelExport": {
-		"message": "Экспорт данных",
-		"description": "Label shown in the title of export dialog."
-	},
-	"anchorExportOptions": {
-		"message": "Параметры экспорта",
-		"description": "Options of export."
-	},
-	"labelExportScriptData": {
-		"message": "Настройки скрипта",
-		"description": "Option to export script data along with scripts."
-	},
-	"buttonAllNone": {
-		"message": "Выбрать Всё/Ничего",
-		"description": "Button to select all scripts or none."
-	},
-	"labelAdvanced": {
-		"message": "Дополнительно",
-		"description": "Label shown in the title of advanced dialog."
-	},
-	"labelAutoUpdate": {
-		"message": "Ежедневно проверять обновления скриптов",
-		"description": "Option to allow automatically checking scripts for updates every 24 hours."
-	},
-	"labelSearchLink": {
-		"message": "Поисковый адрес: ",
-		"description": "Label of URL for searching scripts for a site."
-	},
-	"buttonDefault": {
-		"message": "По умолчанию",
-		"description": "Button to replace search URL with the default one."
-	},
-	"labelData": {
-		"message": "Данные",
-		"description": "Label of extension data management."
-	},
-	"buttonExportData": {
-		"message": "Экспорт в zip-файл",
-		"description": "Button to open the data export dialog."
-	},
-	"buttonImportData": {
-		"message": "Импорт из zip-файла",
-		"description": "Button to choose a file for data import."
+	"labelAllowUpdate": {
+		"message": "Разрешить обновление",
+		"description": "Option to allow checking updates for a script."
 	},
 	},
-	"buttonVacuumData": {
-		"message": "Сбросить кэш",
-		"description": "Button to vacuum extension data."
+	"buttonSave": {
+		"message": "Сохранить",
+		"description": "Button to save modifications of a script."
 	},
 	},
-	"anchorUpdate": {
-		"message": "Проверить обновления",
-		"description": "Check a script for updates."
+	"buttonSaveClose": {
+		"message": "Сохранить и закрыть",
+		"description": "Button to save modifications of a script and then close the editing page."
 	},
 	},
-	"buttonEdit": {
-		"message": "Изменить",
-		"description": "Button to edit a script."
+	"labelNoName": {
+		"message": "Новый скрипт",
+		"description": "Text as the name of a script when no @name is assigned."
 	},
 	},
 	"buttonDisable": {
 	"buttonDisable": {
 		"message": "Выключить",
 		"message": "Выключить",
@@ -283,17 +283,17 @@
 		"message": "Включить",
 		"message": "Включить",
 		"description": "Button to enable a script."
 		"description": "Button to enable a script."
 	},
 	},
+	"buttonEdit": {
+		"message": "Изменить",
+		"description": "Button to edit a script."
+	},
 	"buttonRemove": {
 	"buttonRemove": {
 		"message": "Удалить",
 		"message": "Удалить",
 		"description": "Button to remove a script."
 		"description": "Button to remove a script."
 	},
 	},
-	"labelNoName": {
-		"message": "Новый скрипт",
-		"description": "Text as the name of a script when no @name is assigned."
-	},
-	"labelAuthor": {
-		"message": "Автор: ",
-		"description": "Label of author shown in the details of a script."
+	"anchorUpdate": {
+		"message": "Проверить обновления",
+		"description": "Check a script for updates."
 	},
 	},
 	"confirmNotSaved": {
 	"confirmNotSaved": {
 		"message": "Изменения не сохранены!\nНажмите OK, чтобы выйти или Отмена, чтобы вернуться.",
 		"message": "Изменения не сохранены!\nНажмите OK, чтобы выйти или Отмена, чтобы вернуться.",
@@ -315,14 +315,6 @@
 		"message": "Сбросить избыточность кэша и попробовать подгрузить недостающие ресурсы",
 		"message": "Сбросить избыточность кэша и попробовать подгрузить недостающие ресурсы",
 		"description": "Hint for vacuuming data."
 		"description": "Hint for vacuuming data."
 	},
 	},
-	"buttonExport": {
-		"message": "Экспорт",
-		"description": "Button to confirm export."
-	},
-	"buttonExporting": {
-		"message": "Экспорт данных...",
-		"description": "Message shown when data export is in progress."
-	},
 	"buttonVacuumed": {
 	"buttonVacuumed": {
 		"message": "Сбросить кэш",
 		"message": "Сбросить кэш",
 		"description": "Message shown when data is vacuumed."
 		"description": "Message shown when data is vacuumed."
@@ -363,4 +355,4 @@
 		"message": "Заменить всё",
 		"message": "Заменить всё",
 		"description": "Button to replace all matches."
 		"description": "Button to replace all matches."
 	}
 	}
-}
+}

+ 110 - 118
_locales/zh/messages.json

@@ -47,10 +47,6 @@
 		"message": "未发现新版本。",
 		"message": "未发现新版本。",
 		"description": "Message shown when there is no new version of a script."
 		"description": "Message shown when there is no new version of a script."
 	},
 	},
-	"css": {
-		"message": "html{font-family:微软雅黑;}",
-		"description": "Additional CSS for all pages."
-	},
 	"labelInstall": {
 	"labelInstall": {
 		"message": "安装脚本",
 		"message": "安装脚本",
 		"description": "Shown in the title of the confirm page while trying to install a script."
 		"description": "Shown in the title of the confirm page while trying to install a script."
@@ -67,14 +63,6 @@
 		"message": "关闭",
 		"message": "关闭",
 		"description": "Button to close window."
 		"description": "Button to close window."
 	},
 	},
-	"anchorSupportPage": {
-		"message": "<a href=https://github.com/gera2ld/Violentmonkey/wiki target=_blank>暴力猴</a>",
-		"description": "Link to the support page of Violentmonkey."
-	},
-	"anchorAuthor": {
-		"message": "<a href=mailto:[email protected]>Gerald</a> 制作",
-		"description": "Author shown in the footer of options page, translator information may be added."
-	},
 	"msgScriptURL": {
 	"msgScriptURL": {
 		"message": "脚本URL:$1",
 		"message": "脚本URL:$1",
 		"description": "URL of the script to be installed on confirm page."
 		"description": "URL of the script to be installed on confirm page."
@@ -99,38 +87,110 @@
 		"message": "加载依赖脚本发生错误。",
 		"message": "加载依赖脚本发生错误。",
 		"description": "Message shown when not all requirements are loaded successfully."
 		"description": "Message shown when not all requirements are loaded successfully."
 	},
 	},
-	"labelOptions": {
-		"message": "选项",
-		"description": "Options of this extension."
+	"anchorGetMoreScripts": {
+		"message": "<a href=http://userscripts.org target=_blank>获取更多脚本</a>",
+		"description": "Link to get more scripts."
+	},
+	"sideMenuInstalled": {
+		"message": "已安装的脚本",
+		"description": "Side menu: Installed scripts"
+	},
+	"sideMenuSettings": {
+		"message": "设置",
+		"description": "Side menu: Settings"
+	},
+	"sideMenuAbout": {
+		"message": "关于",
+		"description": "Side menu: About"
 	},
 	},
 	"buttonNew": {
 	"buttonNew": {
 		"message": "新建",
 		"message": "新建",
 		"description": "Button to create a new script."
 		"description": "Button to create a new script."
 	},
 	},
-	"anchorGetMoreScripts": {
-		"message": "<a href=http://userscripts.org target=_blank>从userscripts.org获取更多脚本</a>",
-		"description": "Link to get more scripts."
-	},
 	"anchorUpdateAll": {
 	"anchorUpdateAll": {
 		"message": "全部更新",
 		"message": "全部更新",
 		"description": "Check all scripts for updates."
 		"description": "Check all scripts for updates."
 	},
 	},
-	"buttonAdvanced": {
-		"message": "高级",
-		"description": "Button to show the advanced options."
-	},
-	"labelInstalledScripts": {
-		"message": "已安装的脚本",
-		"description": "Label of the list of installed scripts."
-	},
-	"labelShowDetails": {
-		"message": "显示详情",
-		"description": "Option to show the details of scripts, such as author, description, etc."
-	},
 	"msgLoading": {
 	"msgLoading": {
 		"message": "加载中 ...",
 		"message": "加载中 ...",
 		"description": "Message shown in the options page before script list is loaded."
 		"description": "Message shown in the options page before script list is loaded."
 	},
 	},
+	"labelSettings": {
+		"message": "设置",
+		"description": "Label shown on the top of settings page"
+	},
+	"labelAutoUpdate": {
+		"message": "每天自动更新脚本",
+		"description": "Option to allow automatically checking scripts for updates every 24 hours."
+	},
+	"labelSearchLink": {
+		"message": "搜索网址:",
+		"description": "Label of URL for searching scripts for a site."
+	},
+	"buttonDefault": {
+		"message": "默认",
+		"description": "Button to replace search URL with the default one."
+	},
+	"labelDataImport": {
+		"message": "数据导入",
+		"description": "Section title of data import."
+	},
+	"buttonImportData": {
+		"message": "导入自zip文件",
+		"description": "Button to choose a file for data import."
+	},
+	"buttonVacuumData": {
+		"message": "整理数据",
+		"description": "Button to vacuum extension data."
+	},
+	"labelDataExport": {
+		"message": "数据导出",
+		"description": "Section title of data export."
+	},
+	"labelScriptsToExport": {
+		"message": "要导出的脚本",
+		"description": "Label shown on top of the script list for export."
+	},
+	"labelExportScriptData": {
+		"message": "导出脚本数据",
+		"description": "Option to export script data along with scripts."
+	},
+	"buttonAllNone": {
+		"message": "全选/不选",
+		"description": "Button to select all scripts or none."
+	},
+	"buttonExportData": {
+		"message": "导出为zip文件",
+		"description": "Button to open the data export dialog."
+	},
+	"labelAbout": {
+		"message": "关于暴力猴",
+		"description": "Label shown on top of the about page."
+	},
+	"labelSupportPage": {
+		"message": "支持页面:",
+		"description": "Label of support page."
+	},
+	"anchorSupportPage": {
+		"message": "<a href=https://github.com/gera2ld/Violentmonkey/wiki target=_blank>暴力猴</a>",
+		"description": "Link to the support page of Violentmonkey."
+	},
+	"labelAuthor": {
+		"message": "作者:",
+		"description": "Label of author shown in the details of a script."
+	},
+	"anchorAuthor": {
+		"message": "<a href=mailto:[email protected]>Gerald</a>",
+		"description": "Author shown on about tab."
+	},
+	"labelTranslator": {
+		"message": "翻译者:",
+		"description": "Label of translator."
+	},
+	"anchorTranslator": {
+		"message": "<a href=mailto:[email protected]>Gerald</a>",
+		"description": "Translator shown on about tab."
+	},
 	"labelScriptEditor": {
 	"labelScriptEditor": {
 		"message": "脚本编辑器",
 		"message": "脚本编辑器",
 		"description": "Shown in the title of the script editing page."
 		"description": "Shown in the title of the script editing page."
@@ -139,18 +199,6 @@
 		"message": "自定义元数据",
 		"message": "自定义元数据",
 		"description": "Button to edit the custom meta data of a script."
 		"description": "Button to edit the custom meta data of a script."
 	},
 	},
-	"labelAllowUpdate": {
-		"message": "允许更新",
-		"description": "Option to allow checking updates for a script."
-	},
-	"buttonSave": {
-		"message": "保存",
-		"description": "Button to save modifications of a script."
-	},
-	"buttonSaveClose": {
-		"message": "保存并关闭",
-		"description": "Button to save modifications of a script and then close the editing page."
-	},
 	"labelName": {
 	"labelName": {
 		"message": "名字:",
 		"message": "名字:",
 		"description": "Label of script name."
 		"description": "Label of script name."
@@ -211,69 +259,21 @@
 		"message": "自定义排除规则:<em>(每行一个)</em>",
 		"message": "自定义排除规则:<em>(每行一个)</em>",
 		"description": "Label of custom @exclude rules."
 		"description": "Label of custom @exclude rules."
 	},
 	},
-	"buttonOK": {
-		"message": "确定",
-		"description": "Button to confirm modifications."
-	},
-	"buttonCancel": {
-		"message": "取消",
-		"description": "Button to cancel modifications."
-	},
-	"labelExport": {
-		"message": "数据导出",
-		"description": "Label shown in the title of export dialog."
-	},
-	"anchorExportOptions": {
-		"message": "选项",
-		"description": "Options of export."
-	},
-	"labelExportScriptData": {
-		"message": "导出脚本数据",
-		"description": "Option to export script data along with scripts."
-	},
-	"buttonAllNone": {
-		"message": "全选/不选",
-		"description": "Button to select all scripts or none."
-	},
-	"labelAdvanced": {
-		"message": "高级选项",
-		"description": "Label shown in the title of advanced dialog."
-	},
-	"labelAutoUpdate": {
-		"message": "每天自动更新脚本",
-		"description": "Option to allow automatically checking scripts for updates every 24 hours."
-	},
-	"labelSearchLink": {
-		"message": "搜索网址:",
-		"description": "Label of URL for searching scripts for a site."
-	},
-	"buttonDefault": {
-		"message": "默认",
-		"description": "Button to replace search URL with the default one."
-	},
-	"labelData": {
-		"message": "数据",
-		"description": "Label of extension data management."
-	},
-	"buttonExportData": {
-		"message": "导出为zip文件",
-		"description": "Button to open the data export dialog."
-	},
-	"buttonImportData": {
-		"message": "导入自zip文件",
-		"description": "Button to choose a file for data import."
+	"labelAllowUpdate": {
+		"message": "允许更新",
+		"description": "Option to allow checking updates for a script."
 	},
 	},
-	"buttonVacuumData": {
-		"message": "整理数据",
-		"description": "Button to vacuum extension data."
+	"buttonSave": {
+		"message": "保存",
+		"description": "Button to save modifications of a script."
 	},
 	},
-	"anchorUpdate": {
-		"message": "查找更新",
-		"description": "Check a script for updates."
+	"buttonSaveClose": {
+		"message": "保存并关闭",
+		"description": "Button to save modifications of a script and then close the editing page."
 	},
 	},
-	"buttonEdit": {
-		"message": "编辑",
-		"description": "Button to edit a script."
+	"labelNoName": {
+		"message": "名字为空",
+		"description": "Text as the name of a script when no @name is assigned."
 	},
 	},
 	"buttonDisable": {
 	"buttonDisable": {
 		"message": "禁用",
 		"message": "禁用",
@@ -283,17 +283,17 @@
 		"message": "启用",
 		"message": "启用",
 		"description": "Button to enable a script."
 		"description": "Button to enable a script."
 	},
 	},
+	"buttonEdit": {
+		"message": "编辑",
+		"description": "Button to edit a script."
+	},
 	"buttonRemove": {
 	"buttonRemove": {
 		"message": "移除",
 		"message": "移除",
 		"description": "Button to remove a script."
 		"description": "Button to remove a script."
 	},
 	},
-	"labelNoName": {
-		"message": "名字为空",
-		"description": "Text as the name of a script when no @name is assigned."
-	},
-	"labelAuthor": {
-		"message": "作者:",
-		"description": "Label of author shown in the details of a script."
+	"anchorUpdate": {
+		"message": "查找更新",
+		"description": "Check a script for updates."
 	},
 	},
 	"confirmNotSaved": {
 	"confirmNotSaved": {
 		"message": "修改尚未保存!\n点击确定放弃修改或点击取消停留此页面。",
 		"message": "修改尚未保存!\n点击确定放弃修改或点击取消停留此页面。",
@@ -315,14 +315,6 @@
 		"message": "丢弃多余的数据,并尝试重新获取缺失的资源。",
 		"message": "丢弃多余的数据,并尝试重新获取缺失的资源。",
 		"description": "Hint for vacuuming data."
 		"description": "Hint for vacuuming data."
 	},
 	},
-	"buttonExport": {
-		"message": "导出",
-		"description": "Button to confirm export."
-	},
-	"buttonExporting": {
-		"message": "正在导出...",
-		"description": "Message shown when data export is in progress."
-	},
 	"buttonVacuumed": {
 	"buttonVacuumed": {
 		"message": "数据已整理",
 		"message": "数据已整理",
 		"description": "Message shown when data is vacuumed."
 		"description": "Message shown when data is vacuumed."

+ 6 - 14
common.css

@@ -1,19 +1,11 @@
-h1,h2{text-shadow:#999 3px 3px 5px;}
-a{color:dodgerblue;cursor:pointer;}
-html,body{background:#eee;margin:0;padding:0;}
-.fill,.fill body{height:100%;}
-.center{text-align:center;}
-.float,.frame{position:fixed;background:lightgray;border-spacing:10px;}
-.frame{left:0;right:0;top:0;bottom:0;table-layout:fixed;width:100%;height:100%;}
-.float{margin:0 auto;padding:10px;border-radius:10px;}
-.em{font-style:italic;}
-.new{color:red;}
-.ellipsis{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;}
-.buttons{text-align:right;vertical-align:bottom;}
-.x{clear:both;margin:0;padding:0;}
+html,body{background:#eee;font:menu;height:100%;margin:0;padding:0;}
+h1{text-shadow:#999 3px 3px 5px;}
 .hide{display:none;}
 .hide{display:none;}
 tr{vertical-align:top;padding:0;height:1px;}
 tr{vertical-align:top;padding:0;height:1px;}
 tr.expand{height:auto;}
 tr.expand{height:auto;}
 .expandr{position:relative;}
 .expandr{position:relative;}
 .expanda{position:absolute;width:100%;height:100%;}
 .expanda{position:absolute;width:100%;height:100%;}
-td.right{text-align:right;}
+.ellipsis{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;}
+.frame{position:fixed;background:lightgray;border-spacing:10px;left:0;right:0;top:0;bottom:0;table-layout:fixed;width:100%;height:100%;}
+.right{text-align:right;}
+.bottom{vertical-align:bottom;}

+ 0 - 5
common.js

@@ -6,11 +6,6 @@ function format() {
     return g1;
     return g1;
   });
   });
 }
 }
-function initCSS(){
-	var s=document.createElement('style');
-	s.innerHTML=_('css');
-	document.head.appendChild(s);
-}
 function initI18n(callback){
 function initI18n(callback){
 	window.addEventListener('DOMContentLoaded',function(){
 	window.addEventListener('DOMContentLoaded',function(){
 		var nodes=document.querySelectorAll('*[data-i18n]'),i,t;
 		var nodes=document.querySelectorAll('*[data-i18n]'),i,t;

+ 4 - 5
confirm.html

@@ -1,5 +1,5 @@
 <!doctype html>
 <!doctype html>
-<html class=fill>
+<html>
 	<head>
 	<head>
 		<meta http-equiv="content-type" content="text/html;charset=utf-8">
 		<meta http-equiv="content-type" content="text/html;charset=utf-8">
 		<link rel="shortcut icon" type="image/png" href="images/icon16.png" />
 		<link rel="shortcut icon" type="image/png" href="images/icon16.png" />
@@ -10,16 +10,15 @@
 	<body>
 	<body>
 		<table class=frame>
 		<table class=frame>
 			<tr>
 			<tr>
-				<td><h2><span data-i18n=labelInstall></span> - <span data-i18n=extName></span></h2></td>
-				<td class=buttons>
+				<td><h1><span data-i18n=labelInstall></span> - <span data-i18n=extName></span></h1></td>
+				<td class="right bottom">
 					<input type=checkbox id=cClose><label for=cClose data-i18n=optionClose></label>
 					<input type=checkbox id=cClose><label for=cClose data-i18n=optionClose></label>
 					<button id=bInstall disabled=disabled data-i18n=buttonConfirmInstallation></button>
 					<button id=bInstall disabled=disabled data-i18n=buttonConfirmInstallation></button>
 					<button id=bClose data-i18n=buttonClose></button>
 					<button id=bClose data-i18n=buttonClose></button>
 				</td>
 				</td>
 			</tr>
 			</tr>
-			<tr><td id=url class=ellipsis>&nbsp;</td><td id=msg class="ellipsis right"></td></tr>
+			<tr><td id=url class=ellipsis></td><td id=msg class="ellipsis right">&nbsp;</td></tr>
 			<tr class=expand><td id=eCode colspan=2 class=expandr></td></tr>
 			<tr class=expand><td id=eCode colspan=2 class=expandr></td></tr>
-			<tr><td colspan=2 class=center><span data-i18n=anchorSupportPage></span> - <span data-i18n=anchorAuthor></span> - 2013</td></tr>
 		</table>
 		</table>
 	</body>
 	</body>
 </html>
 </html>

+ 1 - 1
confirm.js

@@ -71,4 +71,4 @@ initEditor(function(o){
 		x.send();
 		x.send();
 	} else error();
 	} else error();
 },{exit:B.onclick,readonly:true});
 },{exit:B.onclick,readonly:true});
-initCSS();initI18n();
+initI18n();

+ 1 - 1
editor.js

@@ -60,7 +60,7 @@ function initCodeMirror(callback,data){
 				CodeMirror.keyMap.vm['Esc']='exit';
 				CodeMirror.keyMap.vm['Esc']='exit';
 				CodeMirror.commands.exit=data.exit;
 				CodeMirror.commands.exit=data.exit;
 			}
 			}
-			var T=CodeMirror($('eCode'),{
+			var T=CodeMirror(document.getElementById('eCode'),{
 				continueComments:true,
 				continueComments:true,
 				matchBrackets:true,
 				matchBrackets:true,
 				autoCloseBrackets:true,
 				autoCloseBrackets:true,

+ 47 - 32
lib/CodeMirror/addon/comment/continuecomment.js

@@ -1,46 +1,61 @@
-(function() {
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
   var modes = ["clike", "css", "javascript"];
   var modes = ["clike", "css", "javascript"];
 
 
   for (var i = 0; i < modes.length; ++i)
   for (var i = 0; i < modes.length; ++i)
     CodeMirror.extendMode(modes[i], {blockCommentContinue: " * "});
     CodeMirror.extendMode(modes[i], {blockCommentContinue: " * "});
 
 
   function continueComment(cm) {
   function continueComment(cm) {
-    var pos = cm.getCursor(), token = cm.getTokenAt(pos);
-    if (token.type != "comment" || cm.getOption("disableInput")) return CodeMirror.Pass;
-    var mode = CodeMirror.innerMode(cm.getMode(), token.state).mode;
+    if (cm.getOption("disableInput")) return CodeMirror.Pass;
+    var ranges = cm.listSelections(), mode, inserts = [];
+    for (var i = 0; i < ranges.length; i++) {
+      var pos = ranges[i].head, token = cm.getTokenAt(pos);
+      if (token.type != "comment") return CodeMirror.Pass;
+      var modeHere = CodeMirror.innerMode(cm.getMode(), token.state).mode;
+      if (!mode) mode = modeHere;
+      else if (mode != modeHere) return CodeMirror.Pass;
 
 
-    var insert;
-    if (mode.blockCommentStart && mode.blockCommentContinue) {
-      var end = token.string.indexOf(mode.blockCommentEnd);
-      var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found;
-      if (end != -1 && end == token.string.length - mode.blockCommentEnd.length && pos.ch >= end) {
-        // Comment ended, don't continue it
-      } else if (token.string.indexOf(mode.blockCommentStart) == 0) {
-        insert = full.slice(0, token.start);
-        if (!/^\s*$/.test(insert)) {
-          insert = "";
-          for (var i = 0; i < token.start; ++i) insert += " ";
+      var insert = null;
+      if (mode.blockCommentStart && mode.blockCommentContinue) {
+        var end = token.string.indexOf(mode.blockCommentEnd);
+        var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found;
+        if (end != -1 && end == token.string.length - mode.blockCommentEnd.length && pos.ch >= end) {
+          // Comment ended, don't continue it
+        } else if (token.string.indexOf(mode.blockCommentStart) == 0) {
+          insert = full.slice(0, token.start);
+          if (!/^\s*$/.test(insert)) {
+            insert = "";
+            for (var j = 0; j < token.start; ++j) insert += " ";
+          }
+        } else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 &&
+                   found + mode.blockCommentContinue.length > token.start &&
+                   /^\s*$/.test(full.slice(0, found))) {
+          insert = full.slice(0, found);
         }
         }
-      } else if ((found = full.indexOf(mode.blockCommentContinue)) != -1 &&
-                 found + mode.blockCommentContinue.length > token.start &&
-                 /^\s*$/.test(full.slice(0, found))) {
-        insert = full.slice(0, found);
+        if (insert != null) insert += mode.blockCommentContinue;
       }
       }
-      if (insert != null) insert += mode.blockCommentContinue;
-    }
-    if (insert == null && mode.lineComment && continueLineCommentEnabled(cm)) {
-      var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment);
-      if (found > -1) {
-        insert = line.slice(0, found);
-        if (/\S/.test(insert)) insert = null;
-        else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\s*/)[0];
+      if (insert == null && mode.lineComment && continueLineCommentEnabled(cm)) {
+        var line = cm.getLine(pos.line), found = line.indexOf(mode.lineComment);
+        if (found > -1) {
+          insert = line.slice(0, found);
+          if (/\S/.test(insert)) insert = null;
+          else insert += mode.lineComment + line.slice(found + mode.lineComment.length).match(/^\s*/)[0];
+        }
       }
       }
+      if (insert == null) return CodeMirror.Pass;
+      inserts[i] = "\n" + insert;
     }
     }
 
 
-    if (insert != null)
-      cm.replaceSelection("\n" + insert, "end");
-    else
-      return CodeMirror.Pass;
+    cm.operation(function() {
+      for (var i = ranges.length - 1; i >= 0; i--)
+        cm.replaceRange(inserts[i], ranges[i].from(), ranges[i].to(), "+insert");
+    });
   }
   }
 
 
   function continueLineCommentEnabled(cm) {
   function continueLineCommentEnabled(cm) {
@@ -64,4 +79,4 @@
       cm.addKeyMap(map);
       cm.addKeyMap(map);
     }
     }
   });
   });
-})();
+});

+ 96 - 40
lib/CodeMirror/addon/edit/closebrackets.js

@@ -1,8 +1,17 @@
-(function() {
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
   var DEFAULT_BRACKETS = "()[]{}''\"\"";
   var DEFAULT_BRACKETS = "()[]{}''\"\"";
   var DEFAULT_EXPLODE_ON_ENTER = "[]{}";
   var DEFAULT_EXPLODE_ON_ENTER = "[]{}";
   var SPACE_CHAR_REGEX = /\s/;
   var SPACE_CHAR_REGEX = /\s/;
 
 
+  var Pos = CodeMirror.Pos;
+
   CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
   CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
     if (old != CodeMirror.Init && old)
     if (old != CodeMirror.Init && old)
       cm.removeKeyMap("autoCloseBrackets");
       cm.removeKeyMap("autoCloseBrackets");
@@ -19,8 +28,8 @@
   });
   });
 
 
   function charsAround(cm, pos) {
   function charsAround(cm, pos) {
-    var str = cm.getRange(CodeMirror.Pos(pos.line, pos.ch - 1),
-                          CodeMirror.Pos(pos.line, pos.ch + 1));
+    var str = cm.getRange(Pos(pos.line, pos.ch - 1),
+                          Pos(pos.line, pos.ch + 1));
     return str.length == 2 ? str : null;
     return str.length == 2 ? str : null;
   }
   }
 
 
@@ -28,57 +37,104 @@
     var map = {
     var map = {
       name : "autoCloseBrackets",
       name : "autoCloseBrackets",
       Backspace: function(cm) {
       Backspace: function(cm) {
-        if (cm.somethingSelected() || cm.getOption("disableInput")) return CodeMirror.Pass;
-        var cur = cm.getCursor(), around = charsAround(cm, cur);
-        if (around && pairs.indexOf(around) % 2 == 0)
-          cm.replaceRange("", CodeMirror.Pos(cur.line, cur.ch - 1), CodeMirror.Pos(cur.line, cur.ch + 1));
-        else
-          return CodeMirror.Pass;
+        if (cm.getOption("disableInput")) return CodeMirror.Pass;
+        var ranges = cm.listSelections();
+        for (var i = 0; i < ranges.length; i++) {
+          if (!ranges[i].empty()) return CodeMirror.Pass;
+          var around = charsAround(cm, ranges[i].head);
+          if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
+        }
+        for (var i = ranges.length - 1; i >= 0; i--) {
+          var cur = ranges[i].head;
+          cm.replaceRange("", Pos(cur.line, cur.ch - 1), Pos(cur.line, cur.ch + 1));
+        }
       }
       }
     };
     };
     var closingBrackets = "";
     var closingBrackets = "";
     for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
     for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
       if (left != right) closingBrackets += right;
       if (left != right) closingBrackets += right;
-      function surround(cm) {
-        var selection = cm.getSelection();
-        cm.replaceSelection(left + selection + right);
-      }
-      function maybeOverwrite(cm) {
-        var cur = cm.getCursor(), ahead = cm.getRange(cur, CodeMirror.Pos(cur.line, cur.ch + 1));
-        if (ahead != right || cm.somethingSelected()) return CodeMirror.Pass;
-        else cm.execCommand("goCharRight");
-      }
       map["'" + left + "'"] = function(cm) {
       map["'" + left + "'"] = function(cm) {
-        if (left == "'" && cm.getTokenAt(cm.getCursor()).type == "comment" ||
-            cm.getOption("disableInput"))
-          return CodeMirror.Pass;
-        if (cm.somethingSelected()) return surround(cm);
-        if (left == right && maybeOverwrite(cm) != CodeMirror.Pass) return;
-        var cur = cm.getCursor(), ahead = CodeMirror.Pos(cur.line, cur.ch + 1);
-        var line = cm.getLine(cur.line), nextChar = line.charAt(cur.ch), curChar = cur.ch > 0 ? line.charAt(cur.ch - 1) : "";
-        if (left == right && CodeMirror.isWordChar(curChar))
-          return CodeMirror.Pass;
-        if (line.length == cur.ch || closingBrackets.indexOf(nextChar) >= 0 || SPACE_CHAR_REGEX.test(nextChar))
-          cm.replaceSelection(left + right, {head: ahead, anchor: ahead});
-        else
-          return CodeMirror.Pass;
+        if (cm.getOption("disableInput")) return CodeMirror.Pass;
+        var ranges = cm.listSelections(), type, next;
+        for (var i = 0; i < ranges.length; i++) {
+          var range = ranges[i], cur = range.head, curType;
+          if (left == "'" && cm.getTokenTypeAt(cur) == "comment")
+            return CodeMirror.Pass;
+          var next = cm.getRange(cur, Pos(cur.line, cur.ch + 1));
+          if (!range.empty())
+            curType = "surround";
+          else if (left == right && next == right) {
+            if (cm.getRange(cur, Pos(cur.line, cur.ch + 3)) == left + left + left)
+              curType = "skipThree";
+            else
+              curType = "skip";
+          } else if (left == right && cur.ch > 1 &&
+                     cm.getRange(Pos(cur.line, cur.ch - 2), cur) == left + left &&
+                     (cur.ch <= 2 || cm.getRange(Pos(cur.line, cur.ch - 3), Pos(cur.line, cur.ch - 2)) != left))
+            curType = "addFour";
+          else if (left == right && CodeMirror.isWordChar(next))
+            return CodeMirror.Pass;
+          else if (cm.getLine(cur.line).length == cur.ch || closingBrackets.indexOf(next) >= 0 || SPACE_CHAR_REGEX.test(next))
+            curType = "both";
+          else
+            return CodeMirror.Pass;
+          if (!type) type = curType;
+          else if (type != curType) return CodeMirror.Pass;
+        }
+
+        cm.operation(function() {
+          if (type == "skip") {
+            cm.execCommand("goCharRight");
+          } else if (type == "skipThree") {
+            for (var i = 0; i < 3; i++)
+              cm.execCommand("goCharRight");
+          } else if (type == "surround") {
+            var sels = cm.getSelections();
+            for (var i = 0; i < sels.length; i++)
+              sels[i] = left + sels[i] + right;
+            cm.replaceSelections(sels, "around");
+          } else if (type == "both") {
+            cm.replaceSelection(left + right, null);
+            cm.execCommand("goCharLeft");
+          } else if (type == "addFour") {
+            cm.replaceSelection(left + left + left + left, "before");
+            cm.execCommand("goCharRight");
+          }
+        });
+      };
+      if (left != right) map["'" + right + "'"] = function(cm) {
+        var ranges = cm.listSelections();
+        for (var i = 0; i < ranges.length; i++) {
+          var range = ranges[i];
+          if (!range.empty() ||
+              cm.getRange(range.head, Pos(range.head.line, range.head.ch + 1)) != right)
+            return CodeMirror.Pass;
+        }
+        cm.execCommand("goCharRight");
       };
       };
-      if (left != right) map["'" + right + "'"] = maybeOverwrite;
     })(pairs.charAt(i), pairs.charAt(i + 1));
     })(pairs.charAt(i), pairs.charAt(i + 1));
     return map;
     return map;
   }
   }
 
 
   function buildExplodeHandler(pairs) {
   function buildExplodeHandler(pairs) {
     return function(cm) {
     return function(cm) {
-      var cur = cm.getCursor(), around = charsAround(cm, cur);
-      if (!around || pairs.indexOf(around) % 2 != 0 || cm.getOption("disableInput"))
-        return CodeMirror.Pass;
+      if (cm.getOption("disableInput")) return CodeMirror.Pass;
+      var ranges = cm.listSelections();
+      for (var i = 0; i < ranges.length; i++) {
+        if (!ranges[i].empty()) return CodeMirror.Pass;
+        var around = charsAround(cm, ranges[i].head);
+        if (!around || pairs.indexOf(around) % 2 != 0) return CodeMirror.Pass;
+      }
       cm.operation(function() {
       cm.operation(function() {
-        var newPos = CodeMirror.Pos(cur.line + 1, 0);
-        cm.replaceSelection("\n\n", {anchor: newPos, head: newPos}, "+input");
-        cm.indentLine(cur.line + 1, null, true);
-        cm.indentLine(cur.line + 2, null, true);
+        cm.replaceSelection("\n\n", null);
+        cm.execCommand("goCharLeft");
+        ranges = cm.listSelections();
+        for (var i = 0; i < ranges.length; i++) {
+          var line = ranges[i].head.line;
+          cm.indentLine(line, null, true);
+          cm.indentLine(line + 1, null, true);
+        }
       });
       });
     };
     };
   }
   }
-})();
+});

+ 74 - 48
lib/CodeMirror/addon/edit/matchbrackets.js

@@ -1,73 +1,96 @@
-(function() {
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
   var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
   var ie_lt8 = /MSIE \d/.test(navigator.userAgent) &&
     (document.documentMode == null || document.documentMode < 8);
     (document.documentMode == null || document.documentMode < 8);
 
 
   var Pos = CodeMirror.Pos;
   var Pos = CodeMirror.Pos;
 
 
   var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
   var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"};
-  function findMatchingBracket(cm, where, strict) {
-    var state = cm.state.matchBrackets;
-    var maxScanLen = (state && state.maxScanLineLength) || 10000;
-    var maxScanLines = (state && state.maxScanLines) || 100;
 
 
-    var cur = where || cm.getCursor(), line = cm.getLineHandle(cur.line), pos = cur.ch - 1;
+  function findMatchingBracket(cm, where, strict, config) {
+    var line = cm.getLineHandle(where.line), pos = where.ch - 1;
     var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
     var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)];
     if (!match) return null;
     if (!match) return null;
-    var forward = match.charAt(1) == ">", d = forward ? 1 : -1;
-    if (strict && forward != (pos == cur.ch)) return null;
-    var style = cm.getTokenTypeAt(Pos(cur.line, pos + 1));
+    var dir = match.charAt(1) == ">" ? 1 : -1;
+    if (strict && (dir > 0) != (pos == where.ch)) return null;
+    var style = cm.getTokenTypeAt(Pos(where.line, pos + 1));
 
 
-    var stack = [line.text.charAt(pos)], re = /[(){}[\]]/;
-    function scan(line, lineNo, start) {
-      if (!line.text) return;
-      var pos = forward ? 0 : line.text.length - 1, end = forward ? line.text.length : -1;
-      if (line.text.length > maxScanLen) return null;
-      if (start != null) pos = start + d;
-      for (; pos != end; pos += d) {
-        var ch = line.text.charAt(pos);
-        if (re.test(ch) && cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style) {
+    var found = scanForBracket(cm, Pos(where.line, pos + (dir > 0 ? 1 : 0)), dir, style || null, config);
+    return {from: Pos(where.line, pos), to: found && found.pos,
+            match: found && found.ch == match.charAt(0), forward: dir > 0};
+  }
+
+  // bracketRegex is used to specify which type of bracket to scan
+  // should be a regexp, e.g. /[[\]]/
+  //
+  // Note: If "where" is on an open bracket, then this bracket is ignored.
+  function scanForBracket(cm, where, dir, style, config) {
+    var maxScanLen = (config && config.maxScanLineLength) || 10000;
+    var maxScanLines = (config && config.maxScanLines) || 500;
+
+    var stack = [];
+    var re = config && config.bracketRegex ? config.bracketRegex : /[(){}[\]]/;
+    var lineEnd = dir > 0 ? Math.min(where.line + maxScanLines, cm.lastLine() + 1)
+                          : Math.max(cm.firstLine() - 1, where.line - maxScanLines);
+    for (var lineNo = where.line; lineNo != lineEnd; lineNo += dir) {
+      var line = cm.getLine(lineNo);
+      if (!line) continue;
+      var pos = dir > 0 ? 0 : line.length - 1, end = dir > 0 ? line.length : -1;
+      if (line.length > maxScanLen) continue;
+      if (lineNo == where.line) pos = where.ch - (dir < 0 ? 1 : 0);
+      for (; pos != end; pos += dir) {
+        var ch = line.charAt(pos);
+        if (re.test(ch) && (style === undefined || cm.getTokenTypeAt(Pos(lineNo, pos + 1)) == style)) {
           var match = matching[ch];
           var match = matching[ch];
-          if (match.charAt(1) == ">" == forward) stack.push(ch);
-          else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false};
-          else if (!stack.length) return {pos: pos, match: true};
+          if ((match.charAt(1) == ">") == (dir > 0)) stack.push(ch);
+          else if (!stack.length) return {pos: Pos(lineNo, pos), ch: ch};
+          else stack.pop();
         }
         }
       }
       }
     }
     }
-    for (var i = cur.line, found, e = forward ? Math.min(i + maxScanLines, cm.lineCount()) : Math.max(-1, i - maxScanLines); i != e; i+=d) {
-      if (i == cur.line) found = scan(line, i, pos);
-      else found = scan(cm.getLineHandle(i), i);
-      if (found) break;
-    }
-    return {from: Pos(cur.line, pos), to: found && Pos(i, found.pos),
-            match: found && found.match, forward: forward};
   }
   }
 
 
-  function matchBrackets(cm, autoclear) {
+  function matchBrackets(cm, autoclear, config) {
     // Disable brace matching in long lines, since it'll cause hugely slow updates
     // Disable brace matching in long lines, since it'll cause hugely slow updates
     var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
     var maxHighlightLen = cm.state.matchBrackets.maxHighlightLineLength || 1000;
-    var found = findMatchingBracket(cm);
-    if (!found || cm.getLine(found.from.line).length > maxHighlightLen ||
-       found.to && cm.getLine(found.to.line).length > maxHighlightLen)
-      return;
+    var marks = [], ranges = cm.listSelections();
+    for (var i = 0; i < ranges.length; i++) {
+      var match = ranges[i].empty() && findMatchingBracket(cm, ranges[i].head, false, config);
+      if (match && cm.getLine(match.from.line).length <= maxHighlightLen &&
+          match.to && cm.getLine(match.to.line).length <= maxHighlightLen) {
+        var style = match.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
+        marks.push(cm.markText(match.from, Pos(match.from.line, match.from.ch + 1), {className: style}));
+        if (match.to)
+          marks.push(cm.markText(match.to, Pos(match.to.line, match.to.ch + 1), {className: style}));
+      }
+    }
+
+    if (marks.length) {
+      // Kludge to work around the IE bug from issue #1193, where text
+      // input stops going to the textare whever this fires.
+      if (ie_lt8 && cm.state.focused) cm.display.input.focus();
 
 
-    var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket";
-    var one = cm.markText(found.from, Pos(found.from.line, found.from.ch + 1), {className: style});
-    var two = found.to && cm.markText(found.to, Pos(found.to.line, found.to.ch + 1), {className: style});
-    // Kludge to work around the IE bug from issue #1193, where text
-    // input stops going to the textarea whenever this fires.
-    if (ie_lt8 && cm.state.focused) cm.display.input.focus();
-    var clear = function() {
-      cm.operation(function() { one.clear(); two && two.clear(); });
-    };
-    if (autoclear) setTimeout(clear, 800);
-    else return clear;
+      var clear = function() {
+        cm.operation(function() {
+          for (var i = 0; i < marks.length; i++) marks[i].clear();
+        });
+      };
+      if (autoclear) setTimeout(clear, 800);
+      else return clear;
+    }
   }
   }
 
 
   var currentlyHighlighted = null;
   var currentlyHighlighted = null;
   function doMatchBrackets(cm) {
   function doMatchBrackets(cm) {
     cm.operation(function() {
     cm.operation(function() {
       if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
       if (currentlyHighlighted) {currentlyHighlighted(); currentlyHighlighted = null;}
-      if (!cm.somethingSelected()) currentlyHighlighted = matchBrackets(cm, false);
+      currentlyHighlighted = matchBrackets(cm, false, cm.state.matchBrackets);
     });
     });
   }
   }
 
 
@@ -81,7 +104,10 @@
   });
   });
 
 
   CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
   CodeMirror.defineExtension("matchBrackets", function() {matchBrackets(this, true);});
-  CodeMirror.defineExtension("findMatchingBracket", function(pos, strict){
-    return findMatchingBracket(this, pos, strict);
+  CodeMirror.defineExtension("findMatchingBracket", function(pos, strict, config){
+    return findMatchingBracket(this, pos, strict, config);
+  });
+  CodeMirror.defineExtension("scanForBracket", function(pos, dir, style, config){
+    return scanForBracket(this, pos, dir, style, config);
   });
   });
-})();
+});

+ 12 - 3
lib/CodeMirror/addon/fold/brace-fold.js

@@ -1,3 +1,13 @@
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+"use strict";
+
 CodeMirror.registerHelper("fold", "brace", function(cm, start) {
 CodeMirror.registerHelper("fold", "brace", function(cm, start) {
   var line = start.line, lineText = cm.getLine(line);
   var line = start.line, lineText = cm.getLine(line);
   var startCh, tokenType;
   var startCh, tokenType;
@@ -45,7 +55,6 @@ CodeMirror.registerHelper("fold", "brace", function(cm, start) {
   return {from: CodeMirror.Pos(line, startCh),
   return {from: CodeMirror.Pos(line, startCh),
           to: CodeMirror.Pos(end, endCh)};
           to: CodeMirror.Pos(end, endCh)};
 });
 });
-CodeMirror.braceRangeFinder = CodeMirror.fold.brace; // deprecated
 
 
 CodeMirror.registerHelper("fold", "import", function(cm, start) {
 CodeMirror.registerHelper("fold", "import", function(cm, start) {
   function hasImport(line) {
   function hasImport(line) {
@@ -70,7 +79,6 @@ CodeMirror.registerHelper("fold", "import", function(cm, start) {
   }
   }
   return {from: cm.clipPos(CodeMirror.Pos(start, has.startCh + 1)), to: end};
   return {from: cm.clipPos(CodeMirror.Pos(start, has.startCh + 1)), to: end};
 });
 });
-CodeMirror.importRangeFinder = CodeMirror.fold["import"]; // deprecated
 
 
 CodeMirror.registerHelper("fold", "include", function(cm, start) {
 CodeMirror.registerHelper("fold", "include", function(cm, start) {
   function hasInclude(line) {
   function hasInclude(line) {
@@ -90,4 +98,5 @@ CodeMirror.registerHelper("fold", "include", function(cm, start) {
   return {from: CodeMirror.Pos(start, has + 1),
   return {from: CodeMirror.Pos(start, has + 1),
           to: cm.clipPos(CodeMirror.Pos(end))};
           to: cm.clipPos(CodeMirror.Pos(end))};
 });
 });
-CodeMirror.includeRangeFinder = CodeMirror.fold.include; // deprecated
+
+});

+ 12 - 0
lib/CodeMirror/addon/fold/comment-fold.js

@@ -1,3 +1,13 @@
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+"use strict";
+
 CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {
 CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {
   return mode.blockCommentStart && mode.blockCommentEnd;
   return mode.blockCommentStart && mode.blockCommentEnd;
 }, function(cm, start) {
 }, function(cm, start) {
@@ -40,3 +50,5 @@ CodeMirror.registerGlobalHelper("fold", "comment", function(mode) {
   return {from: CodeMirror.Pos(line, startCh),
   return {from: CodeMirror.Pos(line, startCh),
           to: CodeMirror.Pos(end, endCh)};
           to: CodeMirror.Pos(end, endCh)};
 });
 });
+
+});

+ 28 - 3
lib/CodeMirror/addon/fold/foldcode.js

@@ -1,4 +1,11 @@
-(function() {
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
   "use strict";
   "use strict";
 
 
   function doFold(cm, pos, options, force) {
   function doFold(cm, pos, options, force) {
@@ -68,9 +75,27 @@
       if (marks[i].__isFold) return true;
       if (marks[i].__isFold) return true;
   });
   });
 
 
-  CodeMirror.commands.fold = function(cm) {
+  CodeMirror.commands.toggleFold = function(cm) {
     cm.foldCode(cm.getCursor());
     cm.foldCode(cm.getCursor());
   };
   };
+  CodeMirror.commands.fold = function(cm) {
+    cm.foldCode(cm.getCursor(), null, "fold");
+  };
+  CodeMirror.commands.unfold = function(cm) {
+    cm.foldCode(cm.getCursor(), null, "unfold");
+  };
+  CodeMirror.commands.foldAll = function(cm) {
+    cm.operation(function() {
+      for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
+        cm.foldCode(CodeMirror.Pos(i, 0), null, "fold");
+    });
+  };
+  CodeMirror.commands.unfoldAll = function(cm) {
+    cm.operation(function() {
+      for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++)
+        cm.foldCode(CodeMirror.Pos(i, 0), null, "unfold");
+    });
+  };
 
 
   CodeMirror.registerHelper("fold", "combine", function() {
   CodeMirror.registerHelper("fold", "combine", function() {
     var funcs = Array.prototype.slice.call(arguments, 0);
     var funcs = Array.prototype.slice.call(arguments, 0);
@@ -89,4 +114,4 @@
       if (cur) return cur;
       if (cur) return cur;
     }
     }
   });
   });
-})();
+});

+ 9 - 2
lib/CodeMirror/addon/fold/foldgutter.js

@@ -1,4 +1,11 @@
-(function() {
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"), require("./foldcode"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror", "./foldcode"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
   "use strict";
   "use strict";
 
 
   CodeMirror.defineOption("foldGutter", false, function(cm, val, old) {
   CodeMirror.defineOption("foldGutter", false, function(cm, val, old) {
@@ -121,4 +128,4 @@
     if (line >= state.from && line < state.to)
     if (line >= state.from && line < state.to)
       updateFoldInfo(cm, line, line + 1);
       updateFoldInfo(cm, line, line + 1);
   }
   }
-})();
+});

+ 12 - 3
lib/CodeMirror/addon/search/match-highlighter.js

@@ -12,7 +12,16 @@
 // actual CSS class name. showToken, when enabled, will cause the
 // actual CSS class name. showToken, when enabled, will cause the
 // current token to be highlighted when nothing is selected.
 // current token to be highlighted when nothing is selected.
 
 
-(function() {
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+  "use strict";
+
   var DEFAULT_MIN_CHARS = 2;
   var DEFAULT_MIN_CHARS = 2;
   var DEFAULT_TOKEN_STYLE = "matchhighlight";
   var DEFAULT_TOKEN_STYLE = "matchhighlight";
   var DEFAULT_DELAY = 100;
   var DEFAULT_DELAY = 100;
@@ -68,7 +77,7 @@
         return;
         return;
       }
       }
       if (cm.getCursor("head").line != cm.getCursor("anchor").line) return;
       if (cm.getCursor("head").line != cm.getCursor("anchor").line) return;
-      var selection = cm.getSelection().replace(/^\s+|\s+$/g, "");
+      var selection = cm.getSelections()[0].replace(/^\s+|\s+$/g, "");
       if (selection.length >= state.minChars)
       if (selection.length >= state.minChars)
         cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style));
         cm.addOverlay(state.overlay = makeOverlay(selection, false, state.style));
     });
     });
@@ -88,4 +97,4 @@
       stream.skipTo(query.charAt(0)) || stream.skipToEnd();
       stream.skipTo(query.charAt(0)) || stream.skipToEnd();
     }};
     }};
   }
   }
-})();
+});

+ 21 - 2
lib/CodeMirror/addon/search/searchcursor.js

@@ -1,4 +1,12 @@
-(function(){
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+  "use strict";
   var Pos = CodeMirror.Pos;
   var Pos = CodeMirror.Pos;
 
 
   function SearchCursor(doc, query, pos, caseFold) {
   function SearchCursor(doc, query, pos, caseFold) {
@@ -164,4 +172,15 @@
   CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
   CodeMirror.defineDocExtension("getSearchCursor", function(query, pos, caseFold) {
     return new SearchCursor(this, query, pos, caseFold);
     return new SearchCursor(this, query, pos, caseFold);
   });
   });
-})();
+
+  CodeMirror.defineExtension("selectMatches", function(query, caseFold) {
+    var ranges = [], next;
+    var cur = this.getSearchCursor(query, this.getCursor("from"), caseFold);
+    while (next = cur.findNext()) {
+      if (CodeMirror.cmpPos(cur.to(), this.getCursor("to")) > 0) break;
+      ranges.push({anchor: cur.from(), head: cur.to()});
+    }
+    if (ranges.length)
+      this.setSelections(ranges, 0);
+  });
+});

+ 38 - 17
lib/CodeMirror/addon/selection/active-line.js

@@ -4,7 +4,14 @@
 // active line's wrapping <div> the CSS class "CodeMirror-activeline",
 // active line's wrapping <div> the CSS class "CodeMirror-activeline",
 // and gives its background <div> the class "CodeMirror-activeline-background".
 // and gives its background <div> the class "CodeMirror-activeline-background".
 
 
-(function() {
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
   "use strict";
   "use strict";
   var WRAP_CLASS = "CodeMirror-activeline";
   var WRAP_CLASS = "CodeMirror-activeline";
   var BACK_CLASS = "CodeMirror-activeline-background";
   var BACK_CLASS = "CodeMirror-activeline-background";
@@ -12,34 +19,48 @@
   CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
   CodeMirror.defineOption("styleActiveLine", false, function(cm, val, old) {
     var prev = old && old != CodeMirror.Init;
     var prev = old && old != CodeMirror.Init;
     if (val && !prev) {
     if (val && !prev) {
-      updateActiveLine(cm, cm.getCursor().line);
+      cm.state.activeLines = [];
+      updateActiveLines(cm, cm.listSelections());
       cm.on("beforeSelectionChange", selectionChange);
       cm.on("beforeSelectionChange", selectionChange);
     } else if (!val && prev) {
     } else if (!val && prev) {
       cm.off("beforeSelectionChange", selectionChange);
       cm.off("beforeSelectionChange", selectionChange);
-      clearActiveLine(cm);
-      delete cm.state.activeLine;
+      clearActiveLines(cm);
+      delete cm.state.activeLines;
     }
     }
   });
   });
 
 
-  function clearActiveLine(cm) {
-    if ("activeLine" in cm.state) {
-      cm.removeLineClass(cm.state.activeLine, "wrap", WRAP_CLASS);
-      cm.removeLineClass(cm.state.activeLine, "background", BACK_CLASS);
+  function clearActiveLines(cm) {
+    for (var i = 0; i < cm.state.activeLines.length; i++) {
+      cm.removeLineClass(cm.state.activeLines[i], "wrap", WRAP_CLASS);
+      cm.removeLineClass(cm.state.activeLines[i], "background", BACK_CLASS);
     }
     }
   }
   }
 
 
-  function updateActiveLine(cm, selectedLine) {
-    var line = cm.getLineHandleVisualStart(selectedLine);
-    if (cm.state.activeLine == line) return;
+  function sameArray(a, b) {
+    if (a.length != b.length) return false;
+    for (var i = 0; i < a.length; i++)
+      if (a[i] != b[i]) return false;
+    return true;
+  }
+
+  function updateActiveLines(cm, ranges) {
+    var active = [];
+    for (var i = 0; i < ranges.length; i++) {
+      var line = cm.getLineHandleVisualStart(ranges[i].head.line);
+      if (active[active.length - 1] != line) active.push(line);
+    }
+    if (sameArray(cm.state.activeLines, active)) return;
     cm.operation(function() {
     cm.operation(function() {
-      clearActiveLine(cm);
-      cm.addLineClass(line, "wrap", WRAP_CLASS);
-      cm.addLineClass(line, "background", BACK_CLASS);
-      cm.state.activeLine = line;
+      clearActiveLines(cm);
+      for (var i = 0; i < active.length; i++) {
+        cm.addLineClass(active[i], "wrap", WRAP_CLASS);
+        cm.addLineClass(active[i], "background", BACK_CLASS);
+      }
+      cm.state.activeLines = active;
     });
     });
   }
   }
 
 
   function selectionChange(cm, sel) {
   function selectionChange(cm, sel) {
-    updateActiveLine(cm, sel.head.line);
+    updateActiveLines(cm, sel.ranges);
   }
   }
-})();
+});

+ 13 - 6
lib/CodeMirror/lib/codemirror.css

@@ -44,7 +44,6 @@
 
 
 .CodeMirror div.CodeMirror-cursor {
 .CodeMirror div.CodeMirror-cursor {
   border-left: 1px solid black;
   border-left: 1px solid black;
-  z-index: 3;
 }
 }
 /* Shown when moving in bi-directional text */
 /* Shown when moving in bi-directional text */
 .CodeMirror div.CodeMirror-secondarycursor {
 .CodeMirror div.CodeMirror-secondarycursor {
@@ -54,10 +53,9 @@
   width: auto;
   width: auto;
   border: 0;
   border: 0;
   background: #7e7;
   background: #7e7;
-  z-index: 1;
 }
 }
 /* Can style cursor different in overwrite (non-insert) mode */
 /* Can style cursor different in overwrite (non-insert) mode */
-.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite {}
+div.CodeMirror-overwrite div.CodeMirror-cursor {}
 
 
 .cm-tab { display: inline-block; }
 .cm-tab { display: inline-block; }
 
 
@@ -237,16 +235,22 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
 
 
 .CodeMirror div.CodeMirror-cursor {
 .CodeMirror div.CodeMirror-cursor {
   position: absolute;
   position: absolute;
-  visibility: hidden;
   border-right: none;
   border-right: none;
   width: 0;
   width: 0;
 }
 }
-.CodeMirror-focused div.CodeMirror-cursor {
+
+div.CodeMirror-cursors {
+  visibility: hidden;
+  position: relative;
+  z-index: 1;
+}
+.CodeMirror-focused div.CodeMirror-cursors {
   visibility: visible;
   visibility: visible;
 }
 }
 
 
 .CodeMirror-selected { background: #d9d9d9; }
 .CodeMirror-selected { background: #d9d9d9; }
 .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
 .CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
+.CodeMirror-crosshair { cursor: crosshair; }
 
 
 .cm-searching {
 .cm-searching {
   background: #ffa;
   background: #ffa;
@@ -256,9 +260,12 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
 /* IE7 hack to prevent it from returning funny offsetTops on the spans */
 /* IE7 hack to prevent it from returning funny offsetTops on the spans */
 .CodeMirror span { *vertical-align: text-bottom; }
 .CodeMirror span { *vertical-align: text-bottom; }
 
 
+/* Used to force a border model for a node */
+.cm-force-border { padding-right: .1px; }
+
 @media print {
 @media print {
   /* Hide the cursor when printing */
   /* Hide the cursor when printing */
-  .CodeMirror div.CodeMirror-cursor {
+  .CodeMirror div.CodeMirror-cursors {
     visibility: hidden;
     visibility: hidden;
   }
   }
 }
 }

文件差異過大導致無法顯示
+ 506 - 355
lib/CodeMirror/lib/codemirror.js


+ 18 - 4
lib/CodeMirror/mode/javascript/javascript.js

@@ -1,5 +1,15 @@
 // TODO actually recognize syntax of TypeScript constructs
 // TODO actually recognize syntax of TypeScript constructs
 
 
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("../../lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["../../lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+"use strict";
+
 CodeMirror.defineMode("javascript", function(config, parserConfig) {
 CodeMirror.defineMode("javascript", function(config, parserConfig) {
   var indentUnit = config.indentUnit;
   var indentUnit = config.indentUnit;
   var statementIndent = parserConfig.statementIndent;
   var statementIndent = parserConfig.statementIndent;
@@ -301,11 +311,12 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
   poplex.lex = true;
   poplex.lex = true;
 
 
   function expect(wanted) {
   function expect(wanted) {
-    return function(type) {
+    function exp(type) {
       if (type == wanted) return cont();
       if (type == wanted) return cont();
       else if (wanted == ";") return pass();
       else if (wanted == ";") return pass();
-      else return cont(arguments.callee);
+      else return cont(exp);
     };
     };
+    return exp;
   }
   }
 
 
   function statement(type, value) {
   function statement(type, value) {
@@ -345,7 +356,7 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
 
 
     var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
     var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
     if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
     if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
-    if (type == "function") return cont(functiondef);
+    if (type == "function") return cont(functiondef, maybeop);
     if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
     if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
     if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
     if (type == "(") return cont(pushlex(")"), maybeexpression, comprehension, expect(")"), poplex, maybeop);
     if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
     if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression);
@@ -571,7 +582,8 @@ CodeMirror.defineMode("javascript", function(config, parserConfig) {
         context: parserConfig.localVars && {vars: parserConfig.localVars},
         context: parserConfig.localVars && {vars: parserConfig.localVars},
         indented: 0
         indented: 0
       };
       };
-      if (parserConfig.globalVars) state.globalVars = parserConfig.globalVars;
+      if (parserConfig.globalVars && typeof parserConfig.globalVars == "object")
+        state.globalVars = parserConfig.globalVars;
       return state;
       return state;
     },
     },
 
 
@@ -636,3 +648,5 @@ CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
 CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
 CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true});
 CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
 CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
 CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
 CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
+
+});

+ 1 - 1
manifest.json

@@ -1,6 +1,6 @@
 {
 {
 	"name": "Violent monkey",
 	"name": "Violent monkey",
-	"version" : "2.0.1",
+	"version" : "2.1",
 	"manifest_version" : 2,
 	"manifest_version" : 2,
 	"description" : "__MSG_extDescription__",
 	"description" : "__MSG_extDescription__",
 	"developer": {"name" : "Gerald", "url" : "http://geraldl.tk"},
 	"developer": {"name" : "Gerald", "url" : "http://geraldl.tk"},

+ 43 - 43
options.css

@@ -1,44 +1,44 @@
-div.left{float:left;}
-div.right{float:right;}
-#main{background:transparent;width:800px;margin:0 auto;border-spacing:0;}
-#main fieldset{position:relative;height:100%;padding:0;}
-#main legend{margin-left:10px;}
-#meta label,#advanced label{display:block;}
-#meta table{width:100%;}
-#meta td{width:1px;white-space:nowrap;}
-#meta td.expand{width:auto;padding-right:10px;}
-#meta td.expand>*{width:100%;}
-#sList{overflow-x:hidden;overflow-y:auto;position:absolute;top:22px;left:0;right:0;bottom:10px;}
-#sList>.hint{position:fixed;top:40%;left:40%;right:40%;border:2px solid silver;border-radius:5px;padding:20px;z-index:9999;box-shadow:5px 10px 15px rgba(0,0,0,0.4);text-align:center;}
-#sList>div{display:block;padding:10px;border-top:1px dashed gray;overflow:hidden;height:80px;position:relative;}
-#sList>div:last-child{border-bottom:1px dashed gray;}
-#sList>div.moving{background:#bb6;border:1px outset gray;cursor:move;}
-#sList.simple>div{height:50px;}
-#sList .version,#sList .author{margin-left:20px;color:gray;font-style:italic;}
-#sList.simple .author,#sList.simple .descrip{display:none;}
-#sList .message{color:gray;position:absolute;bottom:10px;left:50px;}
-#sList .icon{width:32px;height:32px;margin:2px;position:absolute;}
-#sList .name{font-weight:bold;line-height:150%;display:inline-block;max-width:400px;margin-left:40px;}
-#sList .descrip{margin-left:40px;}
-#sList .move{cursor:move;margin-left:20px;color:gray;}
-#sList .panelB,#sList .panelT{position:absolute;right:10px;}
-#sList .panelB{bottom:10px;}
-#sList .panelT{top:10px;}
-#sList .panelB>button{width:80px;}
-#sList .disabled{color:gray;background:silver;}
-#sList .disabled a{color:gray;}
-#sList .disabled img{opacity:0.3;}
-#overlay{background:#000;position:fixed;top:0;bottom:0;left:0;right:0;transition:all .5s linear;opacity:0;}
-#overlay.overlay{opacity:0.6;}
-#advanced{padding:20px;}
-#advanced legend{margin:0;}
-textarea{box-sizing:border-box;width:100%;}
-fieldset{border-radius:5px;}
-#export .list{width:400px;height:420px;}
-#xOptions{display:inline-block;position:relative;}
-#xOptions>div{display:none;position:absolute;padding:10px;background:#eee;box-shadow:5px 10px 15px rgba(0,0,0,0.4);border:1px solid gray;}
-#xOptions>div>label{display:block;white-space:nowrap;}
-#xOptions:hover>div{display:block;}
-.list{background:white;overflow-x:hidden;overflow-y:auto;}
-.list>div{display:block;padding:2px 10px;cursor:pointer;border-bottom:1px dashed lightgray;}
+a{color:dodgerblue;}
+textarea,input[type=text]{box-sizing:border-box;width:100%;}
+.main{max-width:900px;height:100%;margin:0 auto;}
+.sidebar{position:fixed;background:#fafafa;width:200px;margin-top:30px;box-sizing:border-box;border:1px solid darkgray;border-radius:10px 0 0 10px;border-right:none;padding:20px 10px 10px;text-align:right;}
+.sidebar img{width:64px;}
+.sidebar>hr{border:none;border-top:1px solid darkgray;}
+.sidemenu>div{cursor:pointer;line-height:2em;}
+.sidemenu>div.selected,.sidemenu>div:hover{text-shadow:blue 1px 1px 2px;}
+.content{background:white;margin-left:200px;box-sizing:border-box;border-left:1px solid darkgray;border-right:1px solid darkgray;height:100%;overflow-y:auto;position:relative;}
+.content>div{margin:20px;}
+.controls{height:1px;}
+.controls>div{padding:5px 10px;}
+.list{background:white;}
+.list>div{border-bottom:1px dashed lightgray;line-height:2em;}
 .list .selected{background:gray;color:white;}
 .list .selected{background:gray;color:white;}
+
+/* Installed scripts */
+#tabInstalled{height:100%;width:100%;}
+#sList{height:100%;overflow-y:auto;box-sizing:border-box;padding:0 10px 10px;border-top:1px solid darkgray;}
+#sList h3{display:inline-block;margin-right:10px;margin-left:60px;}
+#sList>div{border-bottom:1px dashed silver;padding-bottom:10px;position:relative;}
+#sList>div.disabled{background:lightgray;color:gray;}
+#sList>div.disabled .name{color:blueviolet;}
+#sList>div.disabled .icon{opacity:0.5;}
+#sList>div.moving{background:lightgreen;border:1px outset gray;cursor:move;}
+#sList .icon{top:1em;width:40px;height:40px;margin:2px;position:absolute;}
+#sList .version{margin-right:10px;}
+#sList .descrip{margin-left:60px;margin-bottom:0.5em;}
+#sList .move{cursor:move;margin-left:20px;color:gray;font-size:1.5em;}
+#sList .panelT{position:absolute;top:10px;right:10px;}
+
+/* Editor */
+#eMeta{max-width:450px;max-height:100%;height:auto;background:lightgray;z-index:10;right:-1px;padding:10px;box-sizing:border-box;overflow-y:auto;box-shadow:gray -2px 4px 4px;}
+#eMeta table{width:100%;}
+#eMeta td{width:1px;white-space:nowrap;vertical-align:middle;}
+#eMeta td.expand{width:auto;}
+
+/* Settings */
+#tabSettings>table{width:100%;}
+#tabSettings>table td{width:1px;white-space:nowrap;vertical-align:middle;}
+#tabSettings>table td.expand{width:auto;}
+#tabSettings fieldset{border:none;border-top:1px solid silver;margin:20px 0 0;}
+#tabSettings .list{min-height:100px;max-height:400px;border:1px solid darkgray;cursor:pointer;overflow-y:auto;}
+#tabSettings .list>div{display:inline-block;width:180px;margin:2px;padding:0 5px;border:1px dashed lightgray;}

+ 115 - 108
options.html

@@ -1,133 +1,140 @@
 <!doctype html>
 <!doctype html>
-<html class=fill>
+<html>
 	<head>
 	<head>
 		<meta http-equiv="content-type" content="text/html;charset=utf-8">
 		<meta http-equiv="content-type" content="text/html;charset=utf-8">
 		<link rel="shortcut icon" type="image/png" href="images/icon16.png">
 		<link rel="shortcut icon" type="image/png" href="images/icon16.png">
 		<link rel="stylesheet" type="text/css" href="common.css">
 		<link rel="stylesheet" type="text/css" href="common.css">
 		<link rel="stylesheet" type="text/css" href="options.css">
 		<link rel="stylesheet" type="text/css" href="options.css">
-		<script type="text/javascript" src="lib/zip.js/zip.js"></script>
-		<script type="text/javascript" src="load.js"></script>
+		<script src="lib/zip.js/zip.js"></script>
+		<script src="load.js"></script>
 		<title data-i18n=extName></title>
 		<title data-i18n=extName></title>
 	</head>
 	</head>
 	<body>
 	<body>
-		<table id=main class=frame>
-			<tr><td><h1 class=center><span data-i18n=labelOptions></span> - <span data-i18n=extName></span></h1></td></tr>
+		<div class=main>
+			<div class=sidebar>
+				<img src=images/icon128.png>
+				<h1 data-i18n=extName></h1>
+				<p>2013-2014</p>
+				<div data-i18n=anchorGetMoreScripts></div>
+				<hr>
+				<div class=sidemenu>
+					<div id=smInstalled data-i18n=sideMenuInstalled></div>
+					<div id=smSettings data-i18n=sideMenuSettings></div>
+					<div id=smAbout data-i18n=sideMenuAbout></div>
+				</div>
+			</div>
+			<div class=content>
+				<table id=tabInstalled class=hide>
+					<tr>
+						<td>
+							<button id=bNew data-i18n=buttonNew></button>
+							<button id=bUpdate data-i18n=anchorUpdateAll></button>
+						</td>
+					</tr>
+					<tr class=expand>
+						<td class=expandr>
+							<div id=sList class=expanda>
+								<span id=message data-i18n=msgLoading></span>
+							</div>
+						</td>
+					</tr>
+				</table>
+				<div id=tabSettings class=hide>
+					<h1 data-i18n=labelSettings></h1>
+					<div><label><input type=checkbox id=cUpdate><span data-i18n=labelAutoUpdate></span></label></div>
+					<table>
+						<tr>
+							<td><span data-i18n=labelSearchLink></span></td>
+							<td class=expand><input type=text id=tSearch></td>
+							<td><button id=bDefSearch data-i18n=buttonDefault></button></td>
+						</tr>
+					</table>
+					<fieldset>
+						<legend data-i18n=labelDataImport></legend>
+						<button id=bImport data-i18n=buttonImportData></button><input type=file class=hide id=iImport>
+						<button id=bVacuum data-i18n=buttonVacuumData></button>
+					</fieldset>
+					<fieldset>
+						<legend data-i18n=labelDataExport></legend>
+						<b data-i18n=labelScriptsToExport></b>
+						<label><input type=checkbox id=cWithData><span data-i18n=labelExportScriptData></span></label>
+						<div id=xList class=list></div>
+						<button id=bSelect data-i18n=buttonAllNone></button>
+						<a id=xHelper></a><button id=bExport data-i18n=buttonExportData></button>
+					</fieldset>
+				</div>
+				<div id=tabAbout class=hide>
+					<h1 data-i18n=labelAbout></h1>
+					<p data-i18n=extDescription></p>
+					<p><label data-i18n=labelSupportPage></label><span data-i18n=anchorSupportPage></span></p>
+					<p><label data-i18n=labelAuthor></label><span data-i18n=anchorAuthor></span></p>
+					<p><label data-i18n=labelTranslator></label><span data-i18n=anchorTranslator></span></p>
+				</div>
+			</div>
+		</div>
+		<table id=wndEditor class="frame hide">
 			<tr>
 			<tr>
-				<td>
-					<div class=left>
-						<button id=bNew data-i18n=buttonNew></button>
-						<span data-i18n=anchorGetMoreScripts></span>
-					</div>
-					<div class=right>
-						<a id=bUpdate href=# data-i18n=anchorUpdateAll></a>
-						<button id=bAdvanced data-i18n=buttonAdvanced></button>
-					</div>
-					<div class=x></div>
-				</td>
+				<td><h2 data-i18n=labelScriptEditor></h2></td>
+				<td class="right bottom"><button id=bCustom><span id=sCustom></span> <span data-i18n=buttonCustomMeta></span></button></td>
 			</tr>
 			</tr>
 			<tr class=expand>
 			<tr class=expand>
-				<td class=expandr>
-					<div class=expanda>
-						<fieldset>
+				<td colspan=2 class=expandr>
+					<div id=eCode class=expanda></div>
+					<div id=eMeta class="expanda hide">
+						<table>
+							<tr>
+								<td title="@name" data-i18n=labelName></td><td class=expand><input type=text id=mName></td>
+								<td title="@run-at" data-i18n=labelRunAt></td><td>
+									<select id=mRunAt>
+										<option value=default data-i18n=labelRunAtDefault></option>
+										<option value=start>document-start</option>
+										<option value=idle>document-idle</option>
+										<option value=end>document-end</option>
+									</select>
+								</td>
+							</tr>
+							<tr title="@homepage"><td data-i18n=labelHomepage></td><td colspan=3 class=expand><input type=text id=mHomepage></td></tr>
+						</table>
+						<table>
+							<tr title="@updateURL"><td data-i18n=labelUpdateURL></td><td class=expand><input type=text id=mUpdateURL></td></tr>
+							<tr title="@downloadURL"><td data-i18n=labelDownloadURL></td><td class=expand><input type=text id=mDownloadURL></td></tr>
+						</table>
+						<fieldset title="@include">
+							<legend>
+								<span data-i18n=labelInclude></span>
+								<label><input type=checkbox id=cInclude><span data-i18n=labelKeepInclude></span></label>
+							</legend>
+							<div data-i18n=labelCustomInclude></div>
+							<textarea id=mInclude></textarea>
+						</fieldset>
+						<fieldset title="@match">
+							<legend>
+								<span data-i18n=labelMatch></span>
+								<label><input type=checkbox id=cMatch><span data-i18n=labelKeepMatch></span></label>
+							</legend>
+							<div data-i18n=labelCustomMatch></div>
+							<textarea id=mMatch></textarea>
+						</fieldset>
+						<fieldset title="@exclude">
 							<legend>
 							<legend>
-								<span data-i18n=labelInstalledScripts></span>
-								<label><input type=checkbox id=cDetail><span data-i18n=labelShowDetails></span></label>
+								<span data-i18n=labelExclude></span>
+								<label><input type=checkbox id=cExclude><span data-i18n=labelKeepExclude></span></label>
 							</legend>
 							</legend>
-							<div id=sList><span class=hint data-i18n=msgLoading></span></div>
+							<div data-i18n=labelCustomExclude></div>
+							<textarea id=mExclude></textarea>
 						</fieldset>
 						</fieldset>
 					</div>
 					</div>
 				</td>
 				</td>
 			</tr>
 			</tr>
-			<tr><td class=center><span data-i18n=anchorSupportPage></span> 2013-2014 | <span data-i18n=anchorAuthor></span></td></tr>
-		</table>
-		<div id=overlay class=hide></div>
-		<table id=editor class="frame hide">
 			<tr>
 			<tr>
-				<td><h2 data-i18n=labelScriptEditor></h2></td>
-				<td class=buttons><button id=bcustom data-i18n=buttonCustomMeta></button></td>
-			</tr>
-			<tr class=expand><td id=eCode colspan=2 class=expandr></td></tr>
-			<tr>
-				<td colspan=2>
-					<label><input type=checkbox id=eUpdate><span data-i18n=labelAllowUpdate></span></label>
-					<div class=right>
-						<button id=eSave data-i18n=buttonSave></button>
-						<button id=eSaveClose data-i18n=buttonSaveClose></button>
-						<button id=eClose data-i18n=buttonClose></button>
-					</div>
+				<td><label><input type=checkbox id=eUpdate><span data-i18n=labelAllowUpdate></span></label></td>
+				<td class=right>
+					<button id=eSave data-i18n=buttonSave></button>
+					<button id=eSaveClose data-i18n=buttonSaveClose></button>
+					<button id=eClose data-i18n=buttonClose></button>
 				</td>
 				</td>
 			</tr>
 			</tr>
 		</table>
 		</table>
-		<div id=meta class="float hide">
-			<table>
-				<tr>
-					<td title="@name" data-i18n=labelName></td><td class=expand><input type=text id=mName></td>
-					<td title="@run-at" data-i18n=labelRunAt></td><td>
-						<select id=mRunAt>
-							<option value=default data-i18n=labelRunAtDefault></option>
-							<option value=start>document-start</option>
-							<option value=idle>document-idle</option>
-							<option value=end>document-end</option>
-						</select>
-					</td>
-				</tr>
-				<tr title="@homepage"><td data-i18n=labelHomepage></td><td colspan=3 class=expand><input type=text id=mHomepage></td></tr>
-			</table>
-			<table>
-				<tr title="@updateURL"><td data-i18n=labelUpdateURL></td><td class=expand><input type=text id=mUpdateURL></td></tr>
-				<tr title="@downloadURL"><td data-i18n=labelDownloadURL></td><td class=expand><input type=text id=mDownloadURL></td></tr>
-			</table>
-			<fieldset title="@include">
-				<legend data-i18n=labelInclude></legend>
-				<label><input type=checkbox id=cInclude><span data-i18n=labelKeepInclude></span></label>
-				<span data-i18n=labelCustomInclude></span>
-				<textarea id=mInclude></textarea>
-			</fieldset>
-			<fieldset title="@match">
-				<legend data-i18n=labelMatch></legend>
-				<label><input type=checkbox id=cMatch><span data-i18n=labelKeepMatch></span></label>
-				<span data-i18n=labelCustomMatch></span>
-				<textarea id=mMatch></textarea>
-			</fieldset>
-			<fieldset title="@exclude">
-				<legend data-i18n=labelExclude></legend>
-				<label><input type=checkbox id=cExclude><span data-i18n=labelKeepExclude></span></label>
-				<span data-i18n=labelCustomExclude></span>
-				<textarea id=mExclude></textarea>
-			</fieldset>
-			<div class=right><button id=mOK data-i18n=buttonOK></button> <button id=mCancel data-i18n=buttonCancel></button></div>
-		</div>
-		<div id=export class="float hide">
-			<h2 data-i18n=labelExport></h2>
-			<span data-i18n=labelInstalledScripts></span>
-			<div id=xOptions class=right>
-				<a data-i18n=anchorExportOptions></a>
-				<div>
-					<label><input type=checkbox id=cWithData><span data-i18n=labelExportScriptData></span></label>
-				</div>
-			</div>
-			<div id=xList class=list></div>
-			<div class=left><button id=bSelect data-i18n=buttonAllNone></button></div>
-			<div class=right>
-				<button id=bExport></button>
-				<button id=bClose data-i18n=buttonClose></button>
-			</div>
-		</div>
-		<div id=advanced class="float hide">
-			<h2 data-i18n=labelAdvanced></h2>
-			<label><input type=checkbox id=cUpdate><span data-i18n=labelAutoUpdate></span></label>
-			<div>
-				<span data-i18n=labelSearchLink></span> <button id=bDefSearch data-i18n=buttonDefault></button><br>
-				<textarea id=tSearch></textarea><br>
-			</div>
-			<fieldset>
-				<legend data-i18n=labelData></legend>
-				<button id=aExport data-i18n=buttonExportData></button>
-				<button id=aImport data-i18n=buttonImportData></button><input type=file class=hide id=iImport>
-				<button id=aVacuum data-i18n=buttonVacuumData></button>
-			</fieldset>
-			<div class=right><button id=aClose data-i18n=buttonClose></button></div>
-		</div>
 	</body>
 	</body>
 </html>
 </html>
 <script src="common.js"></script>
 <script src="common.js"></script>

+ 103 - 118
options.js

@@ -1,46 +1,51 @@
-var $=document.getElementById.bind(document),
-		N=$('main'),L=$('sList'),O=$('overlay');
+var $=document.querySelector.bind(document),L=$('#sList'),cur=null,C=$('.content');
 zip.workerScriptsPath='lib/zip.js/';
 zip.workerScriptsPath='lib/zip.js/';
+initI18n();
 function split(t){return t.replace(/^\s+|\s+$/g,'').split(/\s*\n\s*/).filter(function(e){return e;});}
 function split(t){return t.replace(/^\s+|\s+$/g,'').split(/\s*\n\s*/).filter(function(e){return e;});}
+function getName(d,n,def){
+	d.title=n||'';
+	d.innerHTML=n?n.replace(/&/g,'&amp;').replace(/</g,'&lt;'):(def||'<em>'+_('labelNoName')+'</em>');
+}
 
 
 // Main options
 // Main options
 function allowUpdate(n){return n.update&&(n.custom.updateURL||n.meta.updateURL);}
 function allowUpdate(n){return n.update&&(n.custom.updateURL||n.meta.updateURL);}
 function setIcon(n,d){
 function setIcon(n,d){
 	d.src=cache[n.meta.icon]||'images/icon48.png';
 	d.src=cache[n.meta.icon]||'images/icon48.png';
 }
 }
-function modifyItem(d,r){
-	if(r) {
-		if(r.message) d.querySelector('.message').innerHTML=r.message;
-		if(d=d.querySelector('.update')) d.classList[r.hideUpdate?'add':'remove']('hide');
-	}
+function modifyItem(r){
+	var o=map[r.id],d=o.div,n=o.obj;
+	if(r.message) d.querySelector('.message').innerHTML=r.message;
+	d.className=n.enabled?'':'disabled';
+	var a=d.querySelector('.update');
+	if(a) a.classList[r.hideUpdate?'add':'remove']('hide');
+	a=d.querySelector('.name');
+	getName(a,n.custom.name||n.meta.name);
+	if(o=n.custom.homepage||n.meta.homepage) a.href=o;
+	if(n.meta.author) d.querySelector('.author').innerText=_('labelAuthor')+n.meta.author;
+	a=d.querySelector('.descrip');
+	getName(a,n.meta.description||'','&nbsp;');
+	setIcon(n,d.querySelector('.icon'));
+	a=d.querySelector('.enable');
+	a.innerHTML=n.enabled?_('buttonDisable'):_('buttonEnable');
 }
 }
 function loadItem(o,r){
 function loadItem(o,r){
-	var d=o.div,n=o.obj;
+	var d=o.div,n=o.obj;if(!r) r={id:n.id};
 	d.innerHTML='<img class=icon>'
 	d.innerHTML='<img class=icon>'
-	+'<a class="name ellipsis" target=_blank></a>'
+	+'<h3><a class="name ellipsis" target=_blank></a></h3>'
 	+'<span class=version>'+(n.meta.version?'v'+n.meta.version:'')+'</span>'
 	+'<span class=version>'+(n.meta.version?'v'+n.meta.version:'')+'</span>'
 	+'<span class=author></span>'
 	+'<span class=author></span>'
 	+'<div class=panelT>'
 	+'<div class=panelT>'
-		+(allowUpdate(n)?'<a data=update class=update href=#>'+_('anchorUpdate')+'</a> ':'')
 		+'<span class=move data=move>&equiv;</span>'
 		+'<span class=move data=move>&equiv;</span>'
 	+'</div>'
 	+'</div>'
 	+'<div class="descrip ellipsis"></div>'
 	+'<div class="descrip ellipsis"></div>'
-	+'<span class=message></span>'
 	+'<div class=panelB>'
 	+'<div class=panelB>'
 		+'<button data=edit>'+_('buttonEdit')+'</button> '
 		+'<button data=edit>'+_('buttonEdit')+'</button> '
-		+'<button data=enable>'+(n.enabled?_('buttonDisable'):_('buttonEnable'))+'</button> '
-		+'<button data=remove>'+_('buttonRemove')+'</button>'
+		+'<button data=enable class=enable></button> '
+		+'<button data=remove>'+_('buttonRemove')+'</button> '
+		+(allowUpdate(n)?'<button data=update class=update>'+_('anchorUpdate')+'</button> ':'')
+		+'<span class=message></span>'
 	+'</div>';
 	+'</div>';
-	d.className=n.enabled?'':'disabled';
-	setIcon(n,d.querySelector('.icon'));
-	var a=d.querySelector('.name'),b=n.custom.name||n.meta.name;
-	a.title=b||'';
-	a.innerHTML=b?b.replace(/&/g,'&amp;').replace(/</g,'&lt;'):'<em>'+_('labelNoName')+'</em>';
-	if(b=n.custom.homepage||n.meta.homepage) a.href=b;
-	if(n.meta.author) d.querySelector('.author').innerText=_('labelAuthor')+n.meta.author;
-	a=d.querySelector('.descrip');
-	a.innerText=a.title=n.meta.description||'';
-	modifyItem(d,r);
+	modifyItem(r);
 }
 }
 function addItem(o){
 function addItem(o){
 	o.div=document.createElement('div');
 	o.div=document.createElement('div');
@@ -111,52 +116,37 @@ function addItem(o){
 		}
 		}
 	};
 	};
 })();
 })();
-$('bNew').onclick=function(){chrome.runtime.sendMessage({cmd:'NewScript'},function(o){
+$('#bNew').onclick=function(){chrome.runtime.sendMessage({cmd:'NewScript'},function(o){
 	E.cur=null;gotScript(o);
 	E.cur=null;gotScript(o);
 });};
 });};
-$('bUpdate').onclick=function(){chrome.runtime.sendMessage({cmd:'CheckUpdateAll'});};
-$('cDetail').onchange=function(){L.classList.toggle('simple');chrome.runtime.sendMessage({cmd:'SetOption',data:{key:'showDetails',value:this.checked}});};
-var panel=null;
-function switchTo(D){
-	if(panel) panel.classList.add('hide');
-	D.classList.remove('hide');panel=D;
-}
-var dialogs=[];
-function showDialog(D,z){
-	if(!dialogs.length) {
-		O.classList.remove('hide');
-		setTimeout(function(){O.classList.add('overlay');},1);
+$('#bUpdate').onclick=function(){chrome.runtime.sendMessage({cmd:'CheckUpdateAll'});};
+function switchTab(e){
+	var t=e.target,i=t.id.slice(2),o=C.querySelector('#tab'+i);
+	if(!o) return;
+	if(cur) {
+		if(cur.tab==o) return;
+		cur.menu.classList.remove('selected');
+		cur.tab.classList.add('hide');
 	}
 	}
-	if(!z) z=dialogs.length?dialogs[dialogs.length-1].zIndex+1:1;
-	dialogs.push(D);
-	O.style.zIndex=D.style.zIndex=D.zIndex=z;
-	D.classList.remove('hide');
-	D.style.top=(window.innerHeight-D.offsetHeight)/2+'px';
-	D.style.left=(window.innerWidth-D.offsetWidth)/2+'px';
-}
-function closeDialog(){
-	dialogs.pop().classList.add('hide');
-	if(dialogs.length) O.style.zIndex=dialogs.length>1?dialogs[dialogs.length-1]:1;
-	else {
-		O.classList.remove('overlay');
-		setTimeout(function(){O.classList.add('hide');},500);
+	cur={menu:t,tab:o};
+	t.classList.add('selected');
+	o.classList.remove('hide');
+	switch(i) {	// init
+		case 'Settings':xLoad();break;
 	}
 	}
 }
 }
-O.onclick=function(){
-	if(dialogs.length) (dialogs[dialogs.length-1].close||closeDialog)();
-};
+$('.sidemenu').onclick=switchTab;
+switchTab({target:$('#smInstalled')});
 function confirmCancel(dirty){
 function confirmCancel(dirty){
 	return !dirty||confirm(_('confirmNotSaved'));
 	return !dirty||confirm(_('confirmNotSaved'));
 }
 }
-initCSS();initI18n();
 
 
 // Advanced
 // Advanced
-var A=$('advanced'),H=$('iImport');
-$('bAdvanced').onclick=function(){showDialog(A);};
-$('cUpdate').onchange=function(){chrome.runtime.sendMessage({cmd:'AutoUpdate',data:this.checked});};
-$('bDefSearch').onclick=function(){$('tSearch').value=_('defaultSearch');};
-$('tSearch').title=_('hintSearchLink');
-$('aExport').onclick=function(){showDialog(X);xLoad();};
+var H=$('#iImport'),S=$('#tSearch'),V=$('#bVacuum');
+$('#cUpdate').onchange=function(){chrome.runtime.sendMessage({cmd:'AutoUpdate',data:this.checked});};
+S.title=_('hintSearchLink');
+S.onchange=function(){chrome.runtime.sendMessage({cmd:'SetOption',data:{key:'search',value:S.value}});};
+$('#bDefSearch').onclick=function(){S.value=_('defaultSearch');S.onchange();};
 H.onchange=function(e){
 H.onchange=function(e){
 	zip.createReader(new zip.BlobReader(e.target.files[0]),function(r){
 	zip.createReader(new zip.BlobReader(e.target.files[0]),function(r){
 		r.getEntries(function(e){
 		r.getEntries(function(e){
@@ -191,30 +181,26 @@ H.onchange=function(e){
 		});
 		});
 	},function(e){console.log(e);});
 	},function(e){console.log(e);});
 };
 };
-$('aImport').onclick=function(){
+$('#bImport').onclick=function(){
 	var e=document.createEvent('MouseEvent');
 	var e=document.createEvent('MouseEvent');
 	e.initMouseEvent('click',true,true,window,0,0,0,0,0,false,false,false,false,0,null);
 	e.initMouseEvent('click',true,true,window,0,0,0,0,0,false,false,false,false,0,null);
 	H.dispatchEvent(e);
 	H.dispatchEvent(e);
 };
 };
-$('aVacuum').onclick=function(){
+V.onclick=function(){
 	this.disabled=true;
 	this.disabled=true;
 	this.innerHTML=_('buttonVacuuming');
 	this.innerHTML=_('buttonVacuuming');
 	chrome.runtime.sendMessage({cmd:'Vacuum'});
 	chrome.runtime.sendMessage({cmd:'Vacuum'});
 };
 };
-$('aVacuum').title=_('hintVacuumData');
-A.close=$('aClose').onclick=function(){
-	chrome.runtime.sendMessage({cmd:'SetOption',data:{key:'search',value:$('tSearch').value}});
-	closeDialog();
-};
+V.title=_('hintVacuumData');
 
 
 // Export
 // Export
-var X=$('export'),xL=$('xList'),xE=$('bExport'),xC=$('cCompress'),xD=$('cWithData');
+var xL=$('#xList'),xE=$('#bExport'),xD=$('#cWithData');
 function xLoad() {
 function xLoad() {
-	xL.innerHTML='';xE.disabled=false;xE.innerHTML=_('buttonExport');
+	xL.innerHTML='';xE.disabled=false;
 	ids.forEach(function(i){
 	ids.forEach(function(i){
 		var d=document.createElement('div');
 		var d=document.createElement('div');
 		d.className='ellipsis';
 		d.className='ellipsis';
-		d.innerText=d.title=map[i].obj.meta.name;
+		getName(d,map[i].obj.meta.name);
 		xL.appendChild(d);
 		xL.appendChild(d);
 	});
 	});
 }
 }
@@ -224,13 +210,12 @@ xL.onclick=function(e){
 	if(t.parentNode!=this) return;
 	if(t.parentNode!=this) return;
 	t.classList.toggle('selected');
 	t.classList.toggle('selected');
 };
 };
-$('bSelect').onclick=function(){
+$('#bSelect').onclick=function(){
 	var c=xL.childNodes,v,i;
 	var c=xL.childNodes,v,i;
 	for(i=0;i<c.length;i++) if(!c[i].classList.contains('selected')) break;
 	for(i=0;i<c.length;i++) if(!c[i].classList.contains('selected')) break;
 	v=i<c.length;
 	v=i<c.length;
 	for(i=0;i<c.length;i++) if(v) c[i].classList.add('selected'); else c[i].classList.remove('selected');
 	for(i=0;i<c.length;i++) if(v) c[i].classList.add('selected'); else c[i].classList.remove('selected');
 };
 };
-X.close=$('bClose').onclick=closeDialog;
 function exported(o){
 function exported(o){
 	function addFiles(){
 	function addFiles(){
 		adding=true;
 		adding=true;
@@ -245,7 +230,7 @@ function exported(o){
 				return;
 				return;
 			} else	// finished
 			} else	// finished
 				writer.close(function(b){
 				writer.close(function(b){
-					var u=URL.createObjectURL(b),e=document.createEvent('MouseEvent'),xH=document.createElement('a');
+					var u=URL.createObjectURL(b),e=document.createEvent('MouseEvent');
 					e.initMouseEvent('click',true,true,window,0,0,0,0,0,false,false,false,false,0,null);
 					e.initMouseEvent('click',true,true,window,0,0,0,0,0,false,false,false,false,0,null);
 					xH.href=u;
 					xH.href=u;
 					xH.download='scripts.zip';
 					xH.download='scripts.zip';
@@ -261,7 +246,7 @@ function exported(o){
 		files.push(o);
 		files.push(o);
 		if(!adding) addFiles();
 		if(!adding) addFiles();
 	}
 	}
-	var writer=null,files=[],adding=false,
+	var writer=null,files=[],adding=false,xH=$('#xHelper'),
 			n,_n,names={},vm={scripts:{},settings:o.settings};
 			n,_n,names={},vm={scripts:{},settings:o.settings};
 	if(xD.checked) vm.values={};
 	if(xD.checked) vm.values={};
 	o.scripts.forEach(function(c){
 	o.scripts.forEach(function(c){
@@ -277,7 +262,7 @@ function exported(o){
 }
 }
 xE.onclick=function(e){
 xE.onclick=function(e){
 	e.preventDefault();
 	e.preventDefault();
-	this.disabled=true;this.innerHTML=_('buttonExporting');
+	this.disabled=true;
 	var i,c=[];
 	var i,c=[];
 	for(i=0;i<ids.length;i++)
 	for(i=0;i<ids.length;i++)
 		if(xL.childNodes[i].classList.contains('selected')) c.push(ids[i]);
 		if(xL.childNodes[i].classList.contains('selected')) c.push(ids[i]);
@@ -285,42 +270,19 @@ xE.onclick=function(e){
 };
 };
 
 
 // Script Editor
 // Script Editor
-var E=$('editor'),U=$('eUpdate'),M=$('meta'),
-		mN=$('mName'),mH=$('mHomepage'),mR=$('mRunAt'),
-		mU=$('mUpdateURL'),mD=$('mDownloadURL'),
-    mI=$('mInclude'),mE=$('mExclude'),mM=$('mMatch'),
-    cI=$('cInclude'),cE=$('cExclude'),cM=$('cMatch'),
-		eS=$('eSave'),eSC=$('eSaveClose'),T;
+var E=$('#wndEditor'),U=$('#eUpdate'),M=$('#eMeta'),
+		mN=$('#mName'),mH=$('#mHomepage'),mR=$('#mRunAt'),
+		mU=$('#mUpdateURL'),mD=$('#mDownloadURL'),
+    mI=$('#mInclude'),mE=$('#mExclude'),mM=$('#mMatch'),
+    cI=$('#cInclude'),cE=$('#cExclude'),cM=$('#cMatch'),
+		eS=$('#eSave'),eSC=$('#eSaveClose'),T,sC=$('#sCustom');
 function markClean(){
 function markClean(){
 	eS.disabled=eSC.disabled=true;
 	eS.disabled=eSC.disabled=true;
 }
 }
-function gotScript(o){
-	switchTo(E);E.scr=o;U.checked=o.update;
-	T.setValueAndFocus(o.code);
-	T.clearHistory();markClean();
-}
-function eSave(){
-	chrome.runtime.sendMessage({
-		cmd:'ParseScript',
-		data:{
-			id:E.scr.id,
-			code:T.getValue(),
-			message:'',
-			more:{
-				custom:E.scr.custom,
-				update:E.scr.update=U.checked
-			}
-		}
-	});
-	markClean();
-}
-function eClose(){switchTo(N);}
-U.onchange=E.markDirty=function(){eS.disabled=eSC.disabled=false;};
-function metaChange(){M.dirty=true;}
-[mN,mH,mR,mU,mD,mI,mM,mE,cI,cM,cE].forEach(function(i){i.onchange=metaChange;});
-$('bcustom').onclick=function(){
+function mReset(){
+	M.classList.add('hide');
+	sC.innerHTML='&laquo;';
 	var e=[],c=E.scr.custom;M.dirty=false;
 	var e=[],c=E.scr.custom;M.dirty=false;
-	showDialog(M,10);
 	mN.value=c.name||'';
 	mN.value=c.name||'';
 	mH.value=c.homepage||'';
 	mH.value=c.homepage||'';
 	mU.value=c.updateURL||'';
 	mU.value=c.updateURL||'';
@@ -337,10 +299,14 @@ $('bcustom').onclick=function(){
 	mM.value=(c.match||e).join('\n');
 	mM.value=(c.match||e).join('\n');
 	cE.checked=c._exclude!=false;
 	cE.checked=c._exclude!=false;
 	mE.value=(c.exclude||e).join('\n');
 	mE.value=(c.exclude||e).join('\n');
-};
-M.close=function(){if(confirmCancel(M.dirty)) closeDialog();};
-$('mCancel').onclick=closeDialog;
-$('mOK').onclick=function(){
+}
+function gotScript(o){
+	E.classList.remove('hide');
+	E.scr=o;U.checked=o.update;
+	T.setValueAndFocus(o.code);
+	T.clearHistory();markClean();mReset();
+}
+function eSave(){
 	if(M.dirty) {
 	if(M.dirty) {
 		var c=E.scr.custom;
 		var c=E.scr.custom;
 		c.name=mN.value;
 		c.name=mN.value;
@@ -359,13 +325,33 @@ $('mOK').onclick=function(){
 		c.match=split(mM.value);
 		c.match=split(mM.value);
 		c._exclude=cE.checked;
 		c._exclude=cE.checked;
 		c.exclude=split(mE.value);
 		c.exclude=split(mE.value);
-		E.markDirty();
 	}
 	}
-	closeDialog();
+	chrome.runtime.sendMessage({
+		cmd:'ParseScript',
+		data:{
+			id:E.scr.id,
+			code:T.getValue(),
+			message:'',
+			more:{
+				custom:E.scr.custom,
+				update:E.scr.update=U.checked
+			}
+		}
+	});
+	markClean();
+}
+function mClose(){M.classList.add('hide');}
+function eClose(){E.classList.add('hide');E.scr=null;}
+U.onchange=E.markDirty=function(){eS.disabled=eSC.disabled=false;};
+M.markDirty=function(){M.dirty=true;E.markDirty();};
+[mN,mH,mR,mU,mD,mI,mM,mE,cI,cM,cE].forEach(function(i){i.onchange=M.markDirty;});
+$('#bCustom').onclick=function(){
+	var r=M.classList.toggle('hide');
+	sC.innerHTML=r?'&laquo;':'&raquo;';
 };
 };
 eS.onclick=eSave;
 eS.onclick=eSave;
 eSC.onclick=function(){eSave();eClose();};
 eSC.onclick=function(){eSave();eClose();};
-E.close=$('eClose').onclick=function(){if(confirmCancel(!eS.disabled)) eClose();};
+E.close=$('#eClose').onclick=function(){if(confirmCancel(!eS.disabled)) eClose();};
 initEditor(function(o){T=o;},{save:eSave,exit:E.close,onchange:E.markDirty});
 initEditor(function(o){T=o;},{save:eSave,exit:E.close,onchange:E.markDirty});
 
 
 // Load at last
 // Load at last
@@ -376,9 +362,8 @@ function loadOptions(o){
 	o.scripts.forEach(function(i){
 	o.scripts.forEach(function(i){
 		ids.push(i.id);addItem(map[i.id]={obj:i});
 		ids.push(i.id);addItem(map[i.id]={obj:i});
 	});
 	});
-	$('cUpdate').checked=o.settings.autoUpdate;
-	$('tSearch').value=o.settings.search;
-	if(!($('cDetail').checked=o.settings.showDetails)) L.classList.add('simple');
+	$('#cUpdate').checked=o.settings.autoUpdate;
+	S.value=o.settings.search;
 	xD.checked=o.settings.withData;
 	xD.checked=o.settings.withData;
 }
 }
 function updateItem(r){
 function updateItem(r){
@@ -389,7 +374,7 @@ function updateItem(r){
 	switch(r.status){
 	switch(r.status){
 		case 0:loadItem(m,r);break;
 		case 0:loadItem(m,r);break;
 		case 1:ids.push(r.id);addItem(m);break;
 		case 1:ids.push(r.id);addItem(m);break;
-		default:modifyItem(m.div,r);
+		default:modifyItem(r);
 	}
 	}
 }
 }
 chrome.runtime.sendMessage({cmd:'GetData'},loadOptions);
 chrome.runtime.sendMessage({cmd:'GetData'},loadOptions);
@@ -397,7 +382,7 @@ chrome.runtime.onMessage.addListener(function(req,src){
 	var maps={
 	var maps={
 		Vacuumed: function(){
 		Vacuumed: function(){
 			for(var i=0;i<ids.length;i++) map[ids[i]].obj.position=i+1;
 			for(var i=0;i<ids.length;i++) map[ids[i]].obj.position=i+1;
-			$('aVacuum').innerHTML=_('buttonVacuumed');
+			V.innerHTML=_('buttonVacuumed');
 		},
 		},
 	},f=maps[req.cmd];
 	},f=maps[req.cmd];
 	if(f) f(req.data,src);
 	if(f) f(req.data,src);

+ 3 - 1
popup.css

@@ -1,4 +1,4 @@
-body{margin:0;padding:8px;}
+html,body{height:auto;background:inherit;}
 .menu{overflow-y:auto;max-width:300px;}
 .menu{overflow-y:auto;max-width:300px;}
 .menu>div{cursor:pointer;padding:5px;display:block;}
 .menu>div{cursor:pointer;padding:5px;display:block;}
 .menu>div:hover{background:gray;color:gold;}
 .menu>div:hover{background:gray;color:gold;}
@@ -6,3 +6,5 @@ body{margin:0;padding:8px;}
 .menu>div.disabled:hover{color:silver;}
 .menu>div.disabled:hover{color:silver;}
 .menu>div span{display:inline-block;width:20px;}
 .menu>div span{display:inline-block;width:20px;}
 .menu>hr{border:none;border-top:1px dashed gray;}
 .menu>hr{border:none;border-top:1px dashed gray;}
+.expand>td{border-top:1px dashed gray;}
+table{width:100%;height:100%;}

+ 8 - 8
popup.html

@@ -7,15 +7,15 @@
 		<title>Popup Menu - Violentmonkey</title>
 		<title>Popup Menu - Violentmonkey</title>
 	</head>
 	</head>
 	<body>
 	<body>
-		<div id="popup">
-			<div class="top menu x ellipsis"></div>
-			<div class="bot menu x ellipsis"></div>
+		<div id=popup>
+			<div class="top menu ellipsis"></div>
+			<div class="bot menu ellipsis"></div>
 		</div>
 		</div>
-		<div class="hide" id="commands">
-			<div class="top menu x ellipsis"></div>
-			<div class="bot menu x ellipsis"></div>
+		<div class=hide id=commands>
+			<div class="top menu ellipsis"></div>
+			<div class="bot menu ellipsis"></div>
 		</div>
 		</div>
 	</body>
 	</body>
 </html>
 </html>
-<script src="common.js"></script>
-<script src="popup.js"></script>
+<script src=common.js></script>
+<script src=popup.js></script>

+ 0 - 1
popup.js

@@ -133,4 +133,3 @@ chrome.runtime.onMessage.addListener(function(req,src,callback) {
 chrome.tabs.query({currentWindow:true,active:true},function(t) {
 chrome.tabs.query({currentWindow:true,active:true},function(t) {
 	tab=t[0];initMenu();chrome.tabs.sendMessage(tab.id,{cmd:'GetPopup'});
 	tab=t[0];initMenu();chrome.tabs.sendMessage(tab.id,{cmd:'GetPopup'});
 });
 });
-initCSS();

部分文件因文件數量過多而無法顯示