Change format rule
This commit is contained in:
parent
a3bdaeca75
commit
d3bcce91b6
|
@ -10,278 +10,282 @@ browser.runtime.onInstalled.addListener(function(){
|
||||||
browser.runtime.openOptionsPage();
|
browser.runtime.openOptionsPage();
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
function settingsObj() {};
|
function settingsObj() {}
|
||||||
(function () {
|
(function() {
|
||||||
|
//オプションページを書き換え,設定の初期化
|
||||||
|
//Rewrite option page, initialize setting
|
||||||
|
settingsObj.prototype.initOptionsPage = function() {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
labelSet();
|
||||||
|
getSettingsByHtml();
|
||||||
|
overRideSettingsByStorage().then(function() {
|
||||||
|
overRideHtml();
|
||||||
|
saveSettings();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//オプションページから設定を保存
|
||||||
|
//Save settings from options page
|
||||||
|
settingsObj.prototype.saveOptionsPage = function() {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
getSettingsByHtml();
|
||||||
|
saveSettings().then(function() {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//設定を初期化
|
||||||
|
//Initialize setting
|
||||||
|
settingsObj.prototype.init = function() {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
getSettings().then(function() {
|
||||||
|
resolve(Settings);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//設定を返す
|
||||||
|
//return settings
|
||||||
|
settingsObj.prototype.get = function() {
|
||||||
|
return Settings;
|
||||||
|
};
|
||||||
|
//受け取ったオブジェクトを保存
|
||||||
|
//Save the received object
|
||||||
|
settingsObj.prototype.save = function(settings) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
for (let i in settings) {
|
||||||
|
Settings[i] = settings[i];
|
||||||
|
}
|
||||||
|
saveSettings().then(function() {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//設定を削除
|
||||||
|
//Delete settings
|
||||||
|
settingsObj.prototype.clear = function(setting) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
delete Settings[setting];
|
||||||
|
saveSettings().then(function() {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//全ての設定を削除
|
||||||
|
//Delete all settings
|
||||||
|
settingsObj.prototype.clearAll = function() {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
Settings = new settingsObj();
|
||||||
|
saveSettings().then(function() {
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
settingsObj.prototype.labelSet = function() {
|
||||||
|
labelSet();
|
||||||
|
};
|
||||||
|
|
||||||
//オプションページを書き換え,設定の初期化
|
//let Settings = new settingsObj();
|
||||||
//Rewrite option page, initialize setting
|
let Settings = {};
|
||||||
settingsObj.prototype.initOptionsPage = function () {
|
//S = new settingsObj(); //外部から呼び出し Call from outside
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
labelSet();
|
//spanやoptionのid,buttonのclassに"Label"が含まれるときi18nから値を取得して書き換え
|
||||||
getSettingsByHtml();
|
//When "label" is included in span and option id, button class Retrieve the value from i18n and rewrite it
|
||||||
overRideSettingsByStorage().then(function () {
|
function labelSet() {
|
||||||
overRideHtml();
|
textLabelSet("p");
|
||||||
saveSettings();
|
textLabelSet("span");
|
||||||
resolve();
|
textLabelSet("option");
|
||||||
});
|
textLabelSet("input");
|
||||||
})
|
|
||||||
};
|
function textLabelSet(tagName) {
|
||||||
//オプションページから設定を保存
|
const items = document.getElementsByTagName(tagName);
|
||||||
//Save settings from options page
|
for (let i of items) {
|
||||||
settingsObj.prototype.saveOptionsPage = function () {
|
let label;
|
||||||
return new Promise(function (resolve, reject) {
|
if (i.id != undefined && i.id.includes("Label")) {
|
||||||
getSettingsByHtml();
|
label = browser.i18n.getMessage(i.id);
|
||||||
saveSettings().then(function () {
|
} else if (i.className != undefined && i.className.includes("Label")) {
|
||||||
resolve();
|
const labelList = i.className.split(" ").filter((element, index, array) => {
|
||||||
});
|
return element.includes("Label");
|
||||||
})
|
});
|
||||||
};
|
label = browser.i18n.getMessage(labelList[0]);
|
||||||
//設定を初期化
|
} else {
|
||||||
//Initialize setting
|
continue;
|
||||||
settingsObj.prototype.init = function () {
|
}
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
getSettings().then(function () {
|
if (!label == "") {
|
||||||
resolve(Settings);
|
if (tagName == "input") {
|
||||||
})
|
switch (i.type) {
|
||||||
})
|
case "button":
|
||||||
}
|
case "submit":
|
||||||
//設定を返す
|
i.value = label;
|
||||||
//return settings
|
break;
|
||||||
settingsObj.prototype.get = function () {
|
case "text":
|
||||||
return Settings;
|
i.placeholder = label;
|
||||||
};
|
break;
|
||||||
//受け取ったオブジェクトを保存
|
|
||||||
//Save the received object
|
|
||||||
settingsObj.prototype.save = function (settings) {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
for (let i in settings) {
|
|
||||||
Settings[i] = settings[i];
|
|
||||||
}
|
}
|
||||||
saveSettings().then(function () {
|
} else {
|
||||||
resolve();
|
i.innerHTML = label;
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//storageからSettingsの項目を取得して存在しない物をSettingsに上書き
|
||||||
|
//Retrieve the Settings item from storage and overwrite Settings that do not exist
|
||||||
|
function overRideSettingsByStorage() {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
browser.storage.local.get("Settings", function(value) {
|
||||||
|
for (let i in Settings) {
|
||||||
|
if (value.Settings != undefined && value.Settings[i] != undefined) {
|
||||||
|
Settings[i] = value.Settings[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i in value.Settings) {
|
||||||
|
if (Settings[i] == undefined) Settings[i] = value.Settings[i];
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//オプションページにSettingsを反映
|
||||||
|
//Reflect Settings on option page
|
||||||
|
function overRideHtml() {
|
||||||
|
let inputs = document.getElementsByTagName("input");
|
||||||
|
for (let i in inputs) {
|
||||||
|
if (inputs[i].id == undefined) continue;
|
||||||
|
if (inputs[i].className != undefined && inputs[i].className.indexOf("noSetting") != -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (inputs[i].type) {
|
||||||
|
case "text":
|
||||||
|
case "number":
|
||||||
|
case "search":
|
||||||
|
case "tel":
|
||||||
|
case "url":
|
||||||
|
case "email":
|
||||||
|
case "password":
|
||||||
|
case "datetime":
|
||||||
|
case "month":
|
||||||
|
case "week":
|
||||||
|
case "time":
|
||||||
|
case "datetime-local":
|
||||||
|
case "range":
|
||||||
|
case "color":
|
||||||
|
inputs[i].value = Settings[inputs[i].id];
|
||||||
|
break;
|
||||||
|
case "checkbox":
|
||||||
|
inputs[i].checked = Settings[inputs[i].id];
|
||||||
|
break;
|
||||||
|
case "radio":
|
||||||
|
if (Settings[inputs[i].name] == inputs[i].value) {
|
||||||
|
inputs[i].checked = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let textareas = document.getElementsByTagName("textarea");
|
||||||
|
for (let i in textareas) {
|
||||||
|
if (textareas[i].id == undefined) continue;
|
||||||
|
if (textareas[i].className != undefined && textareas[i].className.indexOf("noSetting") != -1)
|
||||||
|
continue;
|
||||||
|
textareas[i].value = Settings[textareas[i].id];
|
||||||
|
}
|
||||||
|
|
||||||
|
let selects = document.getElementsByTagName("select");
|
||||||
|
for (let i in selects) {
|
||||||
|
if (selects[i].id == undefined) continue;
|
||||||
|
if (selects[i].className != undefined && inputs[i].className.indexOf("noSetting") != -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
selects[i].value = Settings[selects[i].id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//オプションページから設定の値を取得
|
||||||
|
//Get setting value from option page
|
||||||
|
function getSettingsByHtml() {
|
||||||
|
let inputs = document.getElementsByTagName("input");
|
||||||
|
|
||||||
|
for (let i in inputs) {
|
||||||
|
if (inputs[i].id == undefined) continue;
|
||||||
|
if (inputs[i].className != undefined && inputs[i].className.indexOf("noSetting") != -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (inputs[i].type) {
|
||||||
|
case "text":
|
||||||
|
case "number":
|
||||||
|
case "search":
|
||||||
|
case "tel":
|
||||||
|
case "url":
|
||||||
|
case "email":
|
||||||
|
case "password":
|
||||||
|
case "datetime":
|
||||||
|
case "month":
|
||||||
|
case "week":
|
||||||
|
case "time":
|
||||||
|
case "datetime-local":
|
||||||
|
case "range":
|
||||||
|
case "color":
|
||||||
|
Settings[inputs[i].id] = inputs[i].value;
|
||||||
|
break;
|
||||||
|
case "checkbox":
|
||||||
|
Settings[inputs[i].id] = inputs[i].checked;
|
||||||
|
break;
|
||||||
|
case "radio":
|
||||||
|
if (inputs[i].checked == true) {
|
||||||
|
Settings[inputs[i].name] = inputs[i].value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let textareas = document.getElementsByTagName("textarea");
|
||||||
|
for (let i in textareas) {
|
||||||
|
if (textareas[i].id == undefined) continue;
|
||||||
|
if (textareas[i].className != undefined && textareas[i].className.indexOf("noSetting") != -1)
|
||||||
|
continue;
|
||||||
|
Settings[textareas[i].id] = textareas[i].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
let selects = document.getElementsByTagName("select");
|
||||||
|
for (let i in selects) {
|
||||||
|
if (selects[i].id == undefined) continue;
|
||||||
|
if (selects[i].className != undefined && selects[i].className.indexOf("noSetting") != -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Settings[selects[i].id] = selects[i].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ストレージが変更されたらget
|
||||||
|
browser.storage.onChanged.addListener(changedSettings);
|
||||||
|
|
||||||
|
function changedSettings(changes, area) {
|
||||||
|
if (Object.keys(changes).includes("Settings")) {
|
||||||
|
Settings = changes.Settings.newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSettings() {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
browser.storage.local.get("Settings", function(value) {
|
||||||
|
Settings = value.Settings;
|
||||||
|
resolve(Settings);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveSettings() {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
browser.storage.local
|
||||||
|
.set({
|
||||||
|
Settings: Settings
|
||||||
})
|
})
|
||||||
};
|
.then(function() {
|
||||||
//設定を削除
|
resolve(Settings);
|
||||||
//Delete settings
|
});
|
||||||
settingsObj.prototype.clear = function (setting) {
|
});
|
||||||
return new Promise(function (resolve, reject) {
|
}
|
||||||
delete Settings[setting];
|
})();
|
||||||
saveSettings().then(function () {
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
//全ての設定を削除
|
|
||||||
//Delete all settings
|
|
||||||
settingsObj.prototype.clearAll = function () {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
Settings = new settingsObj();
|
|
||||||
saveSettings().then(function () {
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
settingsObj.prototype.labelSet = function () {
|
|
||||||
labelSet();
|
|
||||||
}
|
|
||||||
|
|
||||||
//let Settings = new settingsObj();
|
|
||||||
let Settings = {};
|
|
||||||
//S = new settingsObj(); //外部から呼び出し Call from outside
|
|
||||||
|
|
||||||
//spanやoptionのid,buttonのclassに"Label"が含まれるときi18nから値を取得して書き換え
|
|
||||||
//When "label" is included in span and option id, button class Retrieve the value from i18n and rewrite it
|
|
||||||
function labelSet() {
|
|
||||||
textLabelSet("p");
|
|
||||||
textLabelSet("span");
|
|
||||||
textLabelSet("option");
|
|
||||||
textLabelSet("input");
|
|
||||||
|
|
||||||
function textLabelSet(tagName) {
|
|
||||||
const items = document.getElementsByTagName(tagName);
|
|
||||||
for (let i of items) {
|
|
||||||
let label;
|
|
||||||
if (i.id != undefined && i.id.includes("Label")) {
|
|
||||||
label = browser.i18n.getMessage(i.id);
|
|
||||||
} else if (i.className != undefined && i.className.includes("Label")) {
|
|
||||||
const labelList = i.className.split(' ').filter((element, index, array) => {
|
|
||||||
return element.includes("Label");
|
|
||||||
});
|
|
||||||
label = browser.i18n.getMessage(labelList[0]);
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!label == "") {
|
|
||||||
if (tagName == "input") {
|
|
||||||
switch (i.type) {
|
|
||||||
case "button":
|
|
||||||
case "submit":
|
|
||||||
i.value = label;
|
|
||||||
break;
|
|
||||||
case "text":
|
|
||||||
i.placeholder = label;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
i.innerHTML = label;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//storageからSettingsの項目を取得して存在しない物をSettingsに上書き
|
|
||||||
//Retrieve the Settings item from storage and overwrite Settings that do not exist
|
|
||||||
function overRideSettingsByStorage() {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
browser.storage.local.get("Settings", function (value) {
|
|
||||||
|
|
||||||
for (let i in Settings) {
|
|
||||||
if (value.Settings != undefined && value.Settings[i] != undefined) {
|
|
||||||
Settings[i] = value.Settings[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let i in value.Settings) {
|
|
||||||
if (Settings[i] == undefined) Settings[i] = value.Settings[i];
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
//オプションページにSettingsを反映
|
|
||||||
//Reflect Settings on option page
|
|
||||||
function overRideHtml() {
|
|
||||||
let inputs = document.getElementsByTagName("input");
|
|
||||||
for (let i in inputs) {
|
|
||||||
if (inputs[i].id == undefined) continue;
|
|
||||||
if (inputs[i].className != undefined && inputs[i].className.indexOf("noSetting") != -1) continue;
|
|
||||||
|
|
||||||
switch (inputs[i].type) {
|
|
||||||
case "text":
|
|
||||||
case "number":
|
|
||||||
case "search":
|
|
||||||
case "tel":
|
|
||||||
case "url":
|
|
||||||
case "email":
|
|
||||||
case "password":
|
|
||||||
case "datetime":
|
|
||||||
case "month":
|
|
||||||
case "week":
|
|
||||||
case "time":
|
|
||||||
case "datetime-local":
|
|
||||||
case "range":
|
|
||||||
case "color":
|
|
||||||
inputs[i].value = Settings[inputs[i].id];
|
|
||||||
break;
|
|
||||||
case "checkbox":
|
|
||||||
inputs[i].checked = Settings[inputs[i].id];
|
|
||||||
break;
|
|
||||||
case "radio":
|
|
||||||
if (Settings[inputs[i].name] == inputs[i].value) {
|
|
||||||
inputs[i].checked = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let textareas = document.getElementsByTagName("textarea");
|
|
||||||
for (let i in textareas) {
|
|
||||||
if (textareas[i].id == undefined) continue;
|
|
||||||
if (textareas[i].className != undefined && textareas[i].className.indexOf("noSetting") != -1) continue;
|
|
||||||
textareas[i].value = Settings[textareas[i].id];
|
|
||||||
}
|
|
||||||
|
|
||||||
let selects = document.getElementsByTagName("select");
|
|
||||||
for (let i in selects) {
|
|
||||||
if (selects[i].id == undefined) continue;
|
|
||||||
if (selects[i].className != undefined && inputs[i].className.indexOf("noSetting") != -1) continue;
|
|
||||||
|
|
||||||
selects[i].value = Settings[selects[i].id];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//オプションページから設定の値を取得
|
|
||||||
//Get setting value from option page
|
|
||||||
function getSettingsByHtml() {
|
|
||||||
let inputs = document.getElementsByTagName("input");
|
|
||||||
|
|
||||||
for (let i in inputs) {
|
|
||||||
if (inputs[i].id == undefined) continue;
|
|
||||||
if (inputs[i].className != undefined && inputs[i].className.indexOf("noSetting") != -1) continue;
|
|
||||||
|
|
||||||
switch (inputs[i].type) {
|
|
||||||
case "text":
|
|
||||||
case "number":
|
|
||||||
case "search":
|
|
||||||
case "tel":
|
|
||||||
case "url":
|
|
||||||
case "email":
|
|
||||||
case "password":
|
|
||||||
case "datetime":
|
|
||||||
case "month":
|
|
||||||
case "week":
|
|
||||||
case "time":
|
|
||||||
case "datetime-local":
|
|
||||||
case "range":
|
|
||||||
case "color":
|
|
||||||
Settings[inputs[i].id] = inputs[i].value;
|
|
||||||
break;
|
|
||||||
case "checkbox":
|
|
||||||
Settings[inputs[i].id] = inputs[i].checked;
|
|
||||||
break;
|
|
||||||
case "radio":
|
|
||||||
if (inputs[i].checked == true) {
|
|
||||||
Settings[inputs[i].name] = inputs[i].value;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let textareas = document.getElementsByTagName("textarea");
|
|
||||||
for (let i in textareas) {
|
|
||||||
if (textareas[i].id == undefined) continue;
|
|
||||||
if (textareas[i].className != undefined && textareas[i].className.indexOf("noSetting") != -1) continue;
|
|
||||||
Settings[textareas[i].id] = textareas[i].value;
|
|
||||||
}
|
|
||||||
|
|
||||||
let selects = document.getElementsByTagName("select");
|
|
||||||
for (let i in selects) {
|
|
||||||
if (selects[i].id == undefined) continue;
|
|
||||||
if (selects[i].className != undefined && selects[i].className.indexOf("noSetting") != -1) continue;
|
|
||||||
|
|
||||||
Settings[selects[i].id] = selects[i].value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//ストレージが変更されたらget
|
|
||||||
browser.storage.onChanged.addListener(changedSettings);
|
|
||||||
|
|
||||||
function changedSettings(changes, area) {
|
|
||||||
if (Object.keys(changes).includes("Settings")) {
|
|
||||||
Settings = changes.Settings.newValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getSettings() {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
browser.storage.local.get("Settings", function (value) {
|
|
||||||
Settings = value.Settings;
|
|
||||||
resolve(Settings);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function saveSettings() {
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
browser.storage.local.set({
|
|
||||||
'Settings': Settings
|
|
||||||
}).then(function () {
|
|
||||||
resolve(Settings);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}());
|
|
||||||
|
|
|
@ -1,178 +1,182 @@
|
||||||
{
|
{
|
||||||
"extName": {
|
"extName": {
|
||||||
"message": "Simple Translate"
|
"message": "Simple Translate"
|
||||||
},
|
},
|
||||||
"extDescription": {
|
"extDescription": {
|
||||||
"message": "View translations easily as you browse the web."
|
"message": "View translations easily as you browse the web."
|
||||||
},
|
},
|
||||||
|
|
||||||
"donateWithPaypalLabel": {
|
"donateWithPaypalLabel": {
|
||||||
"message": "Donate with PayPal"
|
"message": "Donate with PayPal"
|
||||||
},
|
},
|
||||||
"initialTextArea": {
|
"initialTextArea": {
|
||||||
"message": "Enter text"
|
"message": "Enter text"
|
||||||
},
|
},
|
||||||
"showLink": {
|
"showLink": {
|
||||||
"message": "Translate this page"
|
"message": "Translate this page"
|
||||||
},
|
},
|
||||||
"targetLangLabel": {
|
"targetLangLabel": {
|
||||||
"message": "Target language"
|
"message": "Target language"
|
||||||
},
|
},
|
||||||
"langList": {
|
"langList": {
|
||||||
"message": "af:Afrikaans, sq:Albanian, am:Amharic, ar:Arabic, hy:Armenian, az:Azerbaijani, eu:Basque, be:Belarusian, bn:Bengali, bs:Bosnian, bg:Bulgarian, ca:Catalan, ceb:Cebuano, ny:Chewa, zh-CN:Chinese (PRC), zh-TW:Chinese (Taiwan), co:Corsican, hr:Croatian, cs:Czech, da:Danish, nl:Dutch, en:English, eo:Esperanto, et:Estonian, fi:Finnish, fr:French, fy:Frisian, gl:Galician, ka:Georgian, de:German, el:Greek, gu:Gujarati, ht:Haitian, ha:Hausa, haw:Hawaiian, he:Hebrew, hi:Hindi, hu:Hungarian, is:Icelandic, ig:Igbo, id:Indonesian, ga:Irish, it:Italian, ja:Japanese, jv:Javanese, kn:Kannada, kk:Kazakh, km:Khmer, ky:Kirghiz, ko:Korean, ku:Kurdish, lo:Laotian, la:Latin, lv:Latvian, lt:Lithuanian, lb:Luxembourgish, mk:Macedonian, mg:Malagasy, ms:Malay, ml:Malayalam, mt:Maltese, mi:Maori, mr:Marathi, mn:Mongolian, hmn:Monk, my:Myanmar, ne:Nepali, no:Norwegian, fa:Persian, pl:Polish, pt:Portuguese, pa:Punjabi, ps:Pushto, ro:Romanian, ru:Russian, sm:Samoan, gd:Scottish Gaelic, sr:Serbian, sn:Shona, sd:Sindhi, si:Sinhala, sk:Slovak, sl:Slovenian, so:Somali, sx:Sotho, es:Spanish, su:Sundanese, sw:Swahili, sv:Swedish, tl:Tagalog, tg:Tajiki, ta:Tamil, te:Telugu, th:Thai, tr:Turkish, uk:Ukrainian, ur:Urdu, uz:Uzbek, vi:Vietnamese, cy:Welsh, xh:Xosa, yi:Yiddish, yo:Yoruba, zu:Zulu"
|
"message":
|
||||||
},
|
"af:Afrikaans, sq:Albanian, am:Amharic, ar:Arabic, hy:Armenian, az:Azerbaijani, eu:Basque, be:Belarusian, bn:Bengali, bs:Bosnian, bg:Bulgarian, ca:Catalan, ceb:Cebuano, ny:Chewa, zh-CN:Chinese (PRC), zh-TW:Chinese (Taiwan), co:Corsican, hr:Croatian, cs:Czech, da:Danish, nl:Dutch, en:English, eo:Esperanto, et:Estonian, fi:Finnish, fr:French, fy:Frisian, gl:Galician, ka:Georgian, de:German, el:Greek, gu:Gujarati, ht:Haitian, ha:Hausa, haw:Hawaiian, he:Hebrew, hi:Hindi, hu:Hungarian, is:Icelandic, ig:Igbo, id:Indonesian, ga:Irish, it:Italian, ja:Japanese, jv:Javanese, kn:Kannada, kk:Kazakh, km:Khmer, ky:Kirghiz, ko:Korean, ku:Kurdish, lo:Laotian, la:Latin, lv:Latvian, lt:Lithuanian, lb:Luxembourgish, mk:Macedonian, mg:Malagasy, ms:Malay, ml:Malayalam, mt:Maltese, mi:Maori, mr:Marathi, mn:Mongolian, hmn:Monk, my:Myanmar, ne:Nepali, no:Norwegian, fa:Persian, pl:Polish, pt:Portuguese, pa:Punjabi, ps:Pushto, ro:Romanian, ru:Russian, sm:Samoan, gd:Scottish Gaelic, sr:Serbian, sn:Shona, sd:Sindhi, si:Sinhala, sk:Slovak, sl:Slovenian, so:Somali, sx:Sotho, es:Spanish, su:Sundanese, sw:Swahili, sv:Swedish, tl:Tagalog, tg:Tajiki, ta:Tamil, te:Telugu, th:Thai, tr:Turkish, uk:Ukrainian, ur:Urdu, uz:Uzbek, vi:Vietnamese, cy:Welsh, xh:Xosa, yi:Yiddish, yo:Yoruba, zu:Zulu"
|
||||||
|
},
|
||||||
|
|
||||||
"settingsLabel": {
|
"settingsLabel": {
|
||||||
"message": "Settings"
|
"message": "Settings"
|
||||||
},
|
},
|
||||||
"generalLabel": {
|
"generalLabel": {
|
||||||
"message": "General"
|
"message": "General"
|
||||||
},
|
},
|
||||||
"targetLangCaptionLabel": {
|
"targetLangCaptionLabel": {
|
||||||
"message": "Select the default target language."
|
"message": "Select the default target language."
|
||||||
},
|
},
|
||||||
"webPageLabel": {
|
"webPageLabel": {
|
||||||
"message": "Web page"
|
"message": "Web page"
|
||||||
},
|
},
|
||||||
"ifShowCandidateLabel": {
|
"ifShowCandidateLabel": {
|
||||||
"message": "Show translation candidates"
|
"message": "Show translation candidates"
|
||||||
},
|
},
|
||||||
"ifShowCandidateCaptionLabel": {
|
"ifShowCandidateCaptionLabel": {
|
||||||
"message": "Show multiple translation candidates when a single word is translated."
|
"message": "Show multiple translation candidates when a single word is translated."
|
||||||
},
|
},
|
||||||
"whenSelectTextLabel": {
|
"whenSelectTextLabel": {
|
||||||
"message": "Behavior when selecting text"
|
"message": "Behavior when selecting text"
|
||||||
},
|
},
|
||||||
"ifAutoTranslateLabel": {
|
"ifAutoTranslateLabel": {
|
||||||
"message": "Display translation panel"
|
"message": "Display translation panel"
|
||||||
},
|
},
|
||||||
"ifAutoTranslateCaptionLabel": {
|
"ifAutoTranslateCaptionLabel": {
|
||||||
"message": "Directly display the translation panel without displaying the button."
|
"message": "Directly display the translation panel without displaying the button."
|
||||||
},
|
},
|
||||||
"ifShowButtonLabel": {
|
"ifShowButtonLabel": {
|
||||||
"message": "Display translation button"
|
"message": "Display translation button"
|
||||||
},
|
},
|
||||||
"ifShowButtonCaptionLabel": {
|
"ifShowButtonCaptionLabel": {
|
||||||
"message": "Display the translation button to open the panel when clicked."
|
"message": "Display the translation button to open the panel when clicked."
|
||||||
},
|
},
|
||||||
"dontshowbuttonlabel": {
|
"dontshowbuttonlabel": {
|
||||||
"message": "Don't display button or panel"
|
"message": "Don't display button or panel"
|
||||||
},
|
},
|
||||||
"dontshowbuttonCaptionlabel": {
|
"dontshowbuttonCaptionlabel": {
|
||||||
"message": "Don't display the translation button or the translation panel."
|
"message": "Don't display the translation button or the translation panel."
|
||||||
},
|
},
|
||||||
"ifCheckLangLabel": {
|
"ifCheckLangLabel": {
|
||||||
"message": "Do not display the button if translation is not required"
|
"message": "Do not display the button if translation is not required"
|
||||||
},
|
},
|
||||||
"ifCheckLangCaptionLabel": {
|
"ifCheckLangCaptionLabel": {
|
||||||
"message": "Detects the language of the selected text, and if it is the same as the target language, the button is not displayed."
|
"message":
|
||||||
},
|
"Detects the language of the selected text, and if it is the same as the target language, the button is not displayed."
|
||||||
|
},
|
||||||
|
|
||||||
"toolbarLabel": {
|
"toolbarLabel": {
|
||||||
"message": "Toolbar popup"
|
"message": "Toolbar popup"
|
||||||
},
|
},
|
||||||
"ifChangeSecondLangLabel": {
|
"ifChangeSecondLangLabel": {
|
||||||
"message": "Automatically switch to the second language"
|
"message": "Automatically switch to the second language"
|
||||||
},
|
},
|
||||||
"ifChangeSecondLangCaptionLabel": {
|
"ifChangeSecondLangCaptionLabel": {
|
||||||
"message": "Detects the language of the input text, and if it is the same as the default target language, translate it into the second language."
|
"message":
|
||||||
},
|
"Detects the language of the input text, and if it is the same as the default target language, translate it into the second language."
|
||||||
"secondTargetLangLabel": {
|
},
|
||||||
"message": "Second language"
|
"secondTargetLangLabel": {
|
||||||
},
|
"message": "Second language"
|
||||||
"secondTargetLangCaptionLabel": {
|
},
|
||||||
"message": "Select the second target language."
|
"secondTargetLangCaptionLabel": {
|
||||||
},
|
"message": "Select the second target language."
|
||||||
|
},
|
||||||
|
|
||||||
"menuLabel":{
|
"menuLabel": {
|
||||||
"message": "Context menu"
|
"message": "Context menu"
|
||||||
},
|
},
|
||||||
"ifShowMenuLabel": {
|
"ifShowMenuLabel": {
|
||||||
"message": "Display the context menu"
|
"message": "Display the context menu"
|
||||||
},
|
},
|
||||||
"ifShowMenuCaptionLabel": {
|
"ifShowMenuCaptionLabel": {
|
||||||
"message": "Add items to the context menu displayed when right clicking on the web page or the tab."
|
"message":
|
||||||
},
|
"Add items to the context menu displayed when right clicking on the web page or the tab."
|
||||||
|
},
|
||||||
|
|
||||||
"styleLabel": {
|
"styleLabel": {
|
||||||
"message": "Style"
|
"message": "Style"
|
||||||
},
|
},
|
||||||
"buttonStyleLabel": {
|
"buttonStyleLabel": {
|
||||||
"message": "Translation button"
|
"message": "Translation button"
|
||||||
},
|
},
|
||||||
"buttonStyleCaptionLabel": {
|
"buttonStyleCaptionLabel": {
|
||||||
"message": "Specify the style of the translation button displayed on the web page."
|
"message": "Specify the style of the translation button displayed on the web page."
|
||||||
},
|
},
|
||||||
"buttonSizeLabel": {
|
"buttonSizeLabel": {
|
||||||
"message": "Size"
|
"message": "Size"
|
||||||
},
|
},
|
||||||
"buttonPositionLabel": {
|
"buttonPositionLabel": {
|
||||||
"message": "Display position"
|
"message": "Display position"
|
||||||
},
|
},
|
||||||
"rightUpLabel": {
|
"rightUpLabel": {
|
||||||
"message": "Top right"
|
"message": "Top right"
|
||||||
},
|
},
|
||||||
"rightDownLabel": {
|
"rightDownLabel": {
|
||||||
"message": "Bottom right"
|
"message": "Bottom right"
|
||||||
},
|
},
|
||||||
"leftUpLabel": {
|
"leftUpLabel": {
|
||||||
"message": "Top left"
|
"message": "Top left"
|
||||||
},
|
},
|
||||||
"leftDownLabel": {
|
"leftDownLabel": {
|
||||||
"message": "Bottom left"
|
"message": "Bottom left"
|
||||||
},
|
},
|
||||||
"panelStyleLabel": {
|
"panelStyleLabel": {
|
||||||
"message": "Translation panel"
|
"message": "Translation panel"
|
||||||
},
|
},
|
||||||
"panelStyleCaptionLabel": {
|
"panelStyleCaptionLabel": {
|
||||||
"message": "Specify the style of the translation panel displayed on the web page."
|
"message": "Specify the style of the translation panel displayed on the web page."
|
||||||
},
|
},
|
||||||
"widthLabel": {
|
"widthLabel": {
|
||||||
"message": "Width"
|
"message": "Width"
|
||||||
},
|
},
|
||||||
"heightLabel": {
|
"heightLabel": {
|
||||||
"message": "Height"
|
"message": "Height"
|
||||||
},
|
},
|
||||||
"fontSizeLabel": {
|
"fontSizeLabel": {
|
||||||
"message": "Font size"
|
"message": "Font size"
|
||||||
},
|
},
|
||||||
"bgColorLabel": {
|
"bgColorLabel": {
|
||||||
"message": "Background color"
|
"message": "Background color"
|
||||||
},
|
},
|
||||||
|
|
||||||
"informationLabel": {
|
"informationLabel": {
|
||||||
"message": "Information"
|
"message": "Information"
|
||||||
},
|
},
|
||||||
"licenseLabel": {
|
"licenseLabel": {
|
||||||
"message": "License"
|
"message": "License"
|
||||||
},
|
},
|
||||||
"donationLabel": {
|
"donationLabel": {
|
||||||
"message": "Please make a donation"
|
"message": "Please make a donation"
|
||||||
},
|
},
|
||||||
"donationCaptionLabel": {
|
"donationCaptionLabel": {
|
||||||
"message": "Thank you for using Simple Translate.<br>Your support will be a big encouragement, as I continue to develop the add-on.<br>If you like Simple Translate, I would be pleased if you could consider donating."
|
"message":
|
||||||
},
|
"Thank you for using Simple Translate.<br>Your support will be a big encouragement, as I continue to develop the add-on.<br>If you like Simple Translate, I would be pleased if you could consider donating."
|
||||||
"amazonTitleLabel": {
|
},
|
||||||
"message": "amazon.co.jp eGift Cards"
|
"amazonTitleLabel": {
|
||||||
},
|
"message": "amazon.co.jp eGift Cards"
|
||||||
"addonPageLabel": {
|
},
|
||||||
"message": "Add-on page"
|
"addonPageLabel": {
|
||||||
},
|
"message": "Add-on page"
|
||||||
"amazonUrl": {
|
},
|
||||||
"message": "https://www.amazon.co.jp/dp/B004N3APGO?language=en_US"
|
"amazonUrl": {
|
||||||
},
|
"message": "https://www.amazon.co.jp/dp/B004N3APGO?language=en_US"
|
||||||
"addonUrl": {
|
},
|
||||||
"message": "https:\/\/addons.mozilla.org\/en-US\/firefox\/addon\/simple-translate\/?src=optionpage"
|
"addonUrl": {
|
||||||
},
|
"message": "https://addons.mozilla.org/en-US/firefox/addon/simple-translate/?src=optionpage"
|
||||||
|
},
|
||||||
|
|
||||||
|
"translatePageMenu": {
|
||||||
"translatePageMenu": {
|
"message": "Translate this page"
|
||||||
"message": "Translate this page"
|
},
|
||||||
},
|
"translateTextMenu": {
|
||||||
"translateTextMenu": {
|
"message": "Translate selected text"
|
||||||
"message": "Translate selected text"
|
},
|
||||||
},
|
"translateLinkMenu": {
|
||||||
"translateLinkMenu": {
|
"message": "Translate selected link"
|
||||||
"message": "Translate selected link"
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,121 +4,127 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
//初回起動時にオプションページを表示して設定を初期化
|
//初回起動時にオプションページを表示して設定を初期化
|
||||||
browser.runtime.onInstalled.addListener((details) => {
|
browser.runtime.onInstalled.addListener(details => {
|
||||||
if (details.reason != 'install' && details.reason != 'update') return;
|
if (details.reason != "install" && details.reason != "update") return;
|
||||||
|
|
||||||
browser.tabs.create({
|
browser.tabs.create({
|
||||||
url: "options/options.html#information?action=updated",
|
url: "options/options.html#information?action=updated",
|
||||||
active: false
|
active: false
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let S = new settingsObj();
|
let S = new settingsObj();
|
||||||
|
|
||||||
browser.storage.onChanged.addListener(showMenu);
|
browser.storage.onChanged.addListener(showMenu);
|
||||||
if (typeof (browser.contextMenus.onShown) != 'undefined') browser.contextMenus.onShown.addListener(updateMenu);
|
if (typeof browser.contextMenus.onShown != "undefined")
|
||||||
|
browser.contextMenus.onShown.addListener(updateMenu);
|
||||||
|
|
||||||
S.init().then(function () {
|
S.init().then(function() {
|
||||||
showMenu();
|
showMenu();
|
||||||
});
|
});
|
||||||
|
|
||||||
function showMenu() {
|
function showMenu() {
|
||||||
if (S.get().ifShowMenu) {
|
if (S.get().ifShowMenu) {
|
||||||
menuRemove();
|
menuRemove();
|
||||||
menuCreate();
|
menuCreate();
|
||||||
} else menuRemove();
|
} else menuRemove();
|
||||||
}
|
}
|
||||||
|
|
||||||
//テキストまたはリンクの選択時はページ翻訳を非表示にする
|
//テキストまたはリンクの選択時はページ翻訳を非表示にする
|
||||||
function updateMenu(info, tab) {
|
function updateMenu(info, tab) {
|
||||||
if (info.contexts.includes('selection') || info.contexts.includes('link')) {
|
if (info.contexts.includes("selection") || info.contexts.includes("link")) {
|
||||||
browser.contextMenus.update('translatePage', { contexts: ['password'] }); //passwordにすることで事実上無効にする
|
browser.contextMenus.update("translatePage", { contexts: ["password"] }); //passwordにすることで事実上無効にする
|
||||||
} else {
|
} else {
|
||||||
browser.contextMenus.update('translatePage', { contexts: ['all'] });
|
browser.contextMenus.update("translatePage", { contexts: ["all"] });
|
||||||
}
|
}
|
||||||
browser.contextMenus.refresh();
|
browser.contextMenus.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
//メニューを表示
|
//メニューを表示
|
||||||
function menuCreate() {
|
function menuCreate() {
|
||||||
browser.contextMenus.create({
|
browser.contextMenus.create({
|
||||||
id: "translatePageOnTab",
|
id: "translatePageOnTab",
|
||||||
title: browser.i18n.getMessage("translatePageMenu"),
|
title: browser.i18n.getMessage("translatePageMenu"),
|
||||||
contexts: ["tab"],
|
contexts: ["tab"]
|
||||||
});
|
});
|
||||||
|
|
||||||
browser.contextMenus.create({
|
browser.contextMenus.create({
|
||||||
id: "translatePage",
|
id: "translatePage",
|
||||||
title: browser.i18n.getMessage("translatePageMenu"),
|
title: browser.i18n.getMessage("translatePageMenu"),
|
||||||
contexts: ["all"],
|
contexts: ["all"]
|
||||||
});
|
});
|
||||||
|
|
||||||
browser.contextMenus.create({
|
browser.contextMenus.create({
|
||||||
id: "translateText",
|
id: "translateText",
|
||||||
title: browser.i18n.getMessage("translateTextMenu"),
|
title: browser.i18n.getMessage("translateTextMenu"),
|
||||||
contexts: ["selection"],
|
contexts: ["selection"]
|
||||||
});
|
});
|
||||||
|
|
||||||
browser.contextMenus.create({
|
browser.contextMenus.create({
|
||||||
id: "translateLink",
|
id: "translateLink",
|
||||||
title: browser.i18n.getMessage("translateLinkMenu"),
|
title: browser.i18n.getMessage("translateLinkMenu"),
|
||||||
contexts: ["link"],
|
contexts: ["link"]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//メニューを削除
|
//メニューを削除
|
||||||
function menuRemove() {
|
function menuRemove() {
|
||||||
browser.contextMenus.removeAll();
|
browser.contextMenus.removeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//メニュークリック時
|
//メニュークリック時
|
||||||
browser.contextMenus.onClicked.addListener(function (info, tab) {
|
browser.contextMenus.onClicked.addListener(function(info, tab) {
|
||||||
switch (info.menuItemId) {
|
switch (info.menuItemId) {
|
||||||
case "translatePage":
|
case "translatePage":
|
||||||
case "translatePageOnTab":
|
case "translatePageOnTab":
|
||||||
translatePageMenu(info, tab);
|
translatePageMenu(info, tab);
|
||||||
break;
|
break;
|
||||||
case "translateText":
|
case "translateText":
|
||||||
translateTextMenu(info, tab);
|
translateTextMenu(info, tab);
|
||||||
break;
|
break;
|
||||||
case "translateLink":
|
case "translateLink":
|
||||||
translateLinkMenu(info, tab);
|
translateLinkMenu(info, tab);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//テキストを翻訳
|
//テキストを翻訳
|
||||||
function translateTextMenu(info, tab) {
|
function translateTextMenu(info, tab) {
|
||||||
browser.tabs.sendMessage(
|
browser.tabs.sendMessage(tab.id, {
|
||||||
tab.id, {
|
message: "showPanelFromMenu"
|
||||||
message: "showPanelFromMenu"
|
});
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//ページ全体を翻訳
|
//ページ全体を翻訳
|
||||||
function translatePageMenu(info, tab) {
|
function translatePageMenu(info, tab) {
|
||||||
browser.tabs.create({
|
browser.tabs.create({
|
||||||
'url': "https://translate.google.com/translate?hl=" + S.get().targetLang + "&sl=auto&u=" + encodeURIComponent(info.pageUrl),
|
url:
|
||||||
'active': true,
|
"https://translate.google.com/translate?hl=" +
|
||||||
'index': tab.index + 1
|
S.get().targetLang +
|
||||||
});
|
"&sl=auto&u=" +
|
||||||
|
encodeURIComponent(info.pageUrl),
|
||||||
|
active: true,
|
||||||
|
index: tab.index + 1
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//リンクを翻訳
|
//リンクを翻訳
|
||||||
function translateLinkMenu(info, tab) {
|
function translateLinkMenu(info, tab) {
|
||||||
browser.tabs.create({
|
browser.tabs.create({
|
||||||
'url': "https://translate.google.com/translate?hl=" + S.get().targetLang + "&sl=auto&u=" + encodeURIComponent(info.linkUrl),
|
url:
|
||||||
'active': true,
|
"https://translate.google.com/translate?hl=" +
|
||||||
'index': tab.index + 1
|
S.get().targetLang +
|
||||||
});
|
"&sl=auto&u=" +
|
||||||
|
encodeURIComponent(info.linkUrl),
|
||||||
|
active: true,
|
||||||
|
index: tab.index + 1
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//スクリプトからのメッセージに返信
|
//スクリプトからのメッセージに返信
|
||||||
browser.runtime.onMessage.addListener(function (request) {
|
browser.runtime.onMessage.addListener(function(request) {
|
||||||
switch (request.message) {
|
switch (request.message) {
|
||||||
case "getSetting":
|
case "getSetting":
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,57 +1,56 @@
|
||||||
{
|
{
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"version": "1.8.2",
|
"version": "1.8.2",
|
||||||
|
|
||||||
"name": "__MSG_extName__",
|
"name": "__MSG_extName__",
|
||||||
"description": "__MSG_extDescription__",
|
"description": "__MSG_extDescription__",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
|
|
||||||
"applications": {
|
"applications": {
|
||||||
"gecko": {
|
"gecko": {
|
||||||
"id": "simple-translate@sienori"
|
"id": "simple-translate@sienori"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"permissions": ["<all_urls>", "storage", "contextMenus"],
|
||||||
|
|
||||||
|
"options_ui": {
|
||||||
|
"page": "options/options.html",
|
||||||
|
"open_in_tab": true
|
||||||
|
},
|
||||||
|
|
||||||
|
"icons": {
|
||||||
|
"512": "icons/512.png",
|
||||||
|
"128": "icons/128.png",
|
||||||
|
"64": "icons/64.png",
|
||||||
|
"48": "icons/48.png",
|
||||||
|
"32": "icons/32.png"
|
||||||
|
},
|
||||||
|
|
||||||
|
"background": {
|
||||||
|
"scripts": ["Settings.js", "background.js"]
|
||||||
|
},
|
||||||
|
|
||||||
|
"browser_action": {
|
||||||
|
"default_icon": {
|
||||||
|
"512": "icons/512.png",
|
||||||
|
"128": "icons/128.png",
|
||||||
|
"64": "icons/64.png",
|
||||||
|
"48": "icons/48.png",
|
||||||
|
"38": "icons/38.png",
|
||||||
|
"32": "icons/32.png",
|
||||||
|
"19": "icons/19.png",
|
||||||
|
"16": "icons/16.png"
|
||||||
},
|
},
|
||||||
|
"default_popup": "popup/popup.html"
|
||||||
|
},
|
||||||
|
|
||||||
"permissions": ["<all_urls>", "storage", "contextMenus"],
|
"content_scripts": [
|
||||||
|
{
|
||||||
"options_ui": {
|
"all_frames": true,
|
||||||
"page": "options/options.html",
|
"matches": ["http://*/*", "https://*/*", "<all_urls>"],
|
||||||
"open_in_tab": true
|
"css": ["simple-translate.css"],
|
||||||
},
|
"js": ["Settings.js", "translate.js", "simple-translate.js"]
|
||||||
|
}
|
||||||
"icons": {
|
]
|
||||||
"512": "icons/512.png",
|
|
||||||
"128": "icons/128.png",
|
|
||||||
"64": "icons/64.png",
|
|
||||||
"48": "icons/48.png",
|
|
||||||
"32": "icons/32.png"
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
"background": {
|
|
||||||
"scripts": ["Settings.js", "background.js"]
|
|
||||||
},
|
|
||||||
|
|
||||||
"browser_action": {
|
|
||||||
"default_icon": {
|
|
||||||
"512": "icons/512.png",
|
|
||||||
"128": "icons/128.png",
|
|
||||||
"64": "icons/64.png",
|
|
||||||
"48": "icons/48.png",
|
|
||||||
"38": "icons/38.png",
|
|
||||||
"32": "icons/32.png",
|
|
||||||
"19": "icons/19.png",
|
|
||||||
"16": "icons/16.png"
|
|
||||||
},
|
|
||||||
"default_popup": "popup/popup.html"
|
|
||||||
},
|
|
||||||
|
|
||||||
"content_scripts": [
|
|
||||||
{
|
|
||||||
"all_frames":true,
|
|
||||||
"matches": ["http://*/*", "https://*/*", "<all_urls>"],
|
|
||||||
"css": ["simple-translate.css"],
|
|
||||||
"js": ["Settings.js", "translate.js", "simple-translate.js"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,221 +1,218 @@
|
||||||
:root {
|
:root {
|
||||||
--main-text: #0c0c0d;
|
--main-text: #0c0c0d;
|
||||||
--sub-text: #737373;
|
--sub-text: #737373;
|
||||||
--line: #ededf0;
|
--line: #ededf0;
|
||||||
--button: #d7d7db;
|
--button: #d7d7db;
|
||||||
--highlight: #5595ff;
|
--highlight: #5595ff;
|
||||||
--main-bg: #ffffff;
|
--main-bg: #ffffff;
|
||||||
--new: #ff4f4f;
|
--new: #ff4f4f;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Segoe UI', 'San Francisco', 'Ubuntu', 'Fira Sans', 'Roboto', 'Arial', 'Helvetica', sans-serif;
|
font-family: "Segoe UI", "San Francisco", "Ubuntu", "Fira Sans", "Roboto", "Arial", "Helvetica",
|
||||||
font-size: 15px;
|
sans-serif;
|
||||||
font-weight: 400;
|
font-size: 15px;
|
||||||
color: var(--main-text);
|
font-weight: 400;
|
||||||
background-color: var(--main-bg);
|
color: var(--main-text);
|
||||||
line-height: 1.5;
|
background-color: var(--main-bg);
|
||||||
display: flex;
|
line-height: 1.5;
|
||||||
flex-direction: row;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: var(--line);
|
background-color: var(--line);
|
||||||
height: 1px;
|
height: 1px;
|
||||||
border: none;
|
border: none;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*----sidebar----*/
|
/*----sidebar----*/
|
||||||
|
|
||||||
#sidebar {
|
#sidebar {
|
||||||
font-size: 17px;
|
font-size: 17px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.titleContainer {
|
.titleContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logo {
|
.logo {
|
||||||
height: 64px;
|
height: 64px;
|
||||||
width: 64px;
|
width: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.logotitle {
|
.logotitle {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
color: var(--sub-text);
|
color: var(--sub-text);
|
||||||
/*margin: auto;*/
|
/*margin: auto;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebarItem:hover {
|
.sidebarItem:hover {
|
||||||
text-decoration-line: underline;
|
text-decoration-line: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar > ul {
|
#sidebar > ul {
|
||||||
padding-left: 40px;
|
padding-left: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar > ul > li {
|
#sidebar > ul > li {
|
||||||
padding: 10px 15px;
|
padding: 10px 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sidebar .selected {
|
#sidebar .selected {
|
||||||
color: var(--highlight);
|
color: var(--highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*----contents----*/
|
/*----contents----*/
|
||||||
|
|
||||||
#contents {
|
#contents {
|
||||||
padding-top: 20px;
|
padding-top: 20px;
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
padding-bottom: 50px;
|
padding-bottom: 50px;
|
||||||
width: 650px;
|
width: 650px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.contentTitle {
|
.contentTitle {
|
||||||
font-size: 33px;
|
font-size: 33px;
|
||||||
font-weight: 200;
|
font-weight: 200;
|
||||||
color: var(--sub-text);
|
color: var(--sub-text);
|
||||||
line-height: 2;
|
line-height: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.caption {
|
.caption {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: var(--sub-text);
|
color: var(--sub-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
#contents ul {
|
#contents ul {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.childElements {
|
.childElements {
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
border-left: solid 10px var(--line);
|
border-left: solid 10px var(--line);
|
||||||
}
|
}
|
||||||
|
|
||||||
.categoryContainer {}
|
.categoryContainer {
|
||||||
|
}
|
||||||
|
|
||||||
.categoryElements {
|
.categoryElements {
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.categoryTitle {
|
.categoryTitle {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--sub-text);
|
color: var(--sub-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.optionContainer {
|
.optionContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 10px 0px 10px 0px;
|
padding: 10px 0px 10px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.optionContainer.reverse {
|
.optionContainer.reverse {
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttonsContainer {
|
.buttonsContainer {
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.optionText {
|
.optionText {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.new p:nth-child(1)::after {
|
.new p:nth-child(1)::after {
|
||||||
content: "New";
|
content: "New";
|
||||||
color: var(--new);
|
color: var(--new);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
border: 1px solid var(--new);
|
border: 1px solid var(--new);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding: 0px 5px;
|
padding: 0px 5px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.updated p:nth-child(1)::after {
|
.updated p:nth-child(1)::after {
|
||||||
content: "Updated";
|
content: "Updated";
|
||||||
color: var(--new);
|
color: var(--new);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
border: 1px solid var(--new);
|
border: 1px solid var(--new);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding: 0px 5px;
|
padding: 0px 5px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.optionForm {
|
.optionForm {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reverse .optionForm {
|
.reverse .optionForm {
|
||||||
flex-basis: 40px;
|
flex-basis: 40px;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
#importClear {
|
#importClear {
|
||||||
position: relative;
|
position: relative;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.favicon {
|
.favicon {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
padding: 1px;
|
padding: 1px;
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*----forms----*/
|
/*----forms----*/
|
||||||
|
|
||||||
input {
|
input {
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="number"],
|
input[type="number"],
|
||||||
input[type="text"],
|
input[type="text"],
|
||||||
input[type="color"] {
|
input[type="color"] {
|
||||||
-moz-appearance: textfield;
|
-moz-appearance: textfield;
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
padding-left: 5px;
|
padding-left: 5px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
border: 1px solid var(--button);
|
border: 1px solid var(--button);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="number"]:hover,
|
input[type="number"]:hover,
|
||||||
|
@ -224,197 +221,195 @@ input[type="color"]:hover,
|
||||||
input[type="number"]:focus,
|
input[type="number"]:focus,
|
||||||
input[type="text"]:focus,
|
input[type="text"]:focus,
|
||||||
input[type="color"]:focus {
|
input[type="color"]:focus {
|
||||||
border-color: var(--highlight);
|
border-color: var(--highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"] {
|
input[type="text"] {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="color"] {
|
input[type="color"] {
|
||||||
background-color: var(--main-bg);
|
background-color: var(--main-bg);
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: var(--main-text);
|
color: var(--main-text);
|
||||||
border: 1px solid var(--button);
|
border: 1px solid var(--button);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
background-color: #fbfbfb;
|
background-color: #fbfbfb;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.includeSpan {
|
.includeSpan {
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button:hover {
|
.button:hover {
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
border-color: var(--highlight);
|
border-color: var(--highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
::-moz-selection {
|
::-moz-selection {
|
||||||
background: var(--line);
|
background: var(--line);
|
||||||
}
|
}
|
||||||
|
|
||||||
a:link {
|
a:link {
|
||||||
color: var(--sub-text);
|
color: var(--sub-text);
|
||||||
text-decoration-line: none;
|
text-decoration-line: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
a:visited {
|
a:visited {
|
||||||
color: var(--sub-text);
|
color: var(--sub-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.pageLink {
|
.pageLink {
|
||||||
color: var(--highlight) !important;
|
color: var(--highlight) !important;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pageLink:hover {
|
.pageLink:hover {
|
||||||
color: var(--highlight);
|
color: var(--highlight);
|
||||||
text-decoration-line: underline;
|
text-decoration-line: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
input[type="checkbox"] {
|
input[type="checkbox"] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox {
|
.checkbox {
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
position: relative;
|
position: relative;
|
||||||
/*margin-right: 20px;*/
|
/*margin-right: 20px;*/
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox::before {
|
.checkbox::before {
|
||||||
content: "";
|
content: "";
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: -2px;
|
left: -2px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
border: 1px solid var(--button);
|
border: 1px solid var(--button);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox:hover::before {
|
.checkbox:hover::before {
|
||||||
border-color: var(--highlight);
|
border-color: var(--highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"]:checked + .checkbox {
|
input[type="checkbox"]:checked + .checkbox {
|
||||||
color: var(--highlight);
|
color: var(--highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="checkbox"]:checked + .checkbox::after {
|
input[type="checkbox"]:checked + .checkbox::after {
|
||||||
content: "";
|
content: "";
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
left: 4px;
|
left: 4px;
|
||||||
width: 6px;
|
width: 6px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
transform: rotate(40deg);
|
transform: rotate(40deg);
|
||||||
border-bottom: 3px solid var(--highlight);
|
border-bottom: 3px solid var(--highlight);
|
||||||
border-right: 3px solid var(--highlight);
|
border-right: 3px solid var(--highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"] {
|
input[type="radio"] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio {
|
.radio {
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio::before {
|
.radio::before {
|
||||||
content: "";
|
content: "";
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: -2px;
|
left: -2px;
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
border: 1px solid var(--button);
|
border: 1px solid var(--button);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.radio:hover::before {
|
.radio:hover::before {
|
||||||
border-color: var(--highlight);
|
border-color: var(--highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"]:checked + .radio {
|
input[type="radio"]:checked + .radio {
|
||||||
color: var(--highlight);
|
color: var(--highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="radio"]:checked + .radio::after {
|
input[type="radio"]:checked + .radio::after {
|
||||||
content: "";
|
content: "";
|
||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 6px;
|
top: 6px;
|
||||||
left: 4px;
|
left: 4px;
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background-color: var(--highlight);
|
background-color: var(--highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
border: var(--button) solid 1px;
|
border: var(--button) solid 1px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding: 3px 5px;
|
padding: 3px 5px;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
select:hover {
|
select:hover {
|
||||||
border: var(--highlight) solid 1px;
|
border: var(--highlight) solid 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectWrap {
|
.selectWrap {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectWrap:before {
|
.selectWrap:before {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
content: "";
|
content: "";
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 40%;
|
top: 40%;
|
||||||
right: 7px;
|
right: 7px;
|
||||||
width: 5px;
|
width: 5px;
|
||||||
height: 5px;
|
height: 5px;
|
||||||
|
|
||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
border-bottom: 2px solid var(--sub-text);
|
border-bottom: 2px solid var(--sub-text);
|
||||||
border-right: 2px solid var(--sub-text);
|
border-right: 2px solid var(--sub-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectWrap:hover::before {
|
.selectWrap:hover::before {
|
||||||
border-bottom: 2px solid var(--highlight);
|
border-bottom: 2px solid var(--highlight);
|
||||||
border-right: 2px solid var(--highlight);
|
border-right: 2px solid var(--highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
option {
|
option {
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,66 +2,68 @@
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
const S = new settingsObj()
|
const S = new settingsObj();
|
||||||
let targetLang = document.getElementById("targetLang");
|
let targetLang = document.getElementById("targetLang");
|
||||||
let secondTargetLang = document.getElementById("secondTargetLang");
|
let secondTargetLang = document.getElementById("secondTargetLang");
|
||||||
|
|
||||||
setLangList();
|
setLangList();
|
||||||
|
|
||||||
function setLangList() {
|
function setLangList() {
|
||||||
let langList = browser.i18n.getMessage("langList");
|
let langList = browser.i18n.getMessage("langList");
|
||||||
langList = langList.split(", ");
|
langList = langList.split(", ");
|
||||||
|
|
||||||
for (let i in langList) {
|
for (let i in langList) {
|
||||||
langList[i] = langList[i].split(":");
|
langList[i] = langList[i].split(":");
|
||||||
}
|
}
|
||||||
langList = langList.sort(alphabeticallySort);
|
langList = langList.sort(alphabeticallySort);
|
||||||
|
|
||||||
let langListHtml = "";
|
let langListHtml = "";
|
||||||
for (let i of langList) {
|
for (let i of langList) {
|
||||||
langListHtml += `<option value=${i[0]}>${i[1]}</option>`
|
langListHtml += `<option value=${i[0]}>${i[1]}</option>`;
|
||||||
}
|
}
|
||||||
targetLang.innerHTML = langListHtml;
|
targetLang.innerHTML = langListHtml;
|
||||||
secondTargetLang.innerHTML = langListHtml;
|
secondTargetLang.innerHTML = langListHtml;
|
||||||
|
|
||||||
initialSetting();
|
initialSetting();
|
||||||
}
|
}
|
||||||
|
|
||||||
function alphabeticallySort(a, b) {
|
function alphabeticallySort(a, b) {
|
||||||
if (a[1].toString() > b[1].toString()) {
|
if (a[1].toString() > b[1].toString()) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initialSetting() {
|
function initialSetting() {
|
||||||
switch (browser.i18n.getUILanguage()) { //一部の言語はブラウザの設定に合わせる
|
switch (
|
||||||
case "ja":
|
browser.i18n.getUILanguage() //一部の言語はブラウザの設定に合わせる
|
||||||
case "zh-CN":
|
) {
|
||||||
case "zh-TW":
|
case "ja":
|
||||||
case "ko":
|
case "zh-CN":
|
||||||
case "ru":
|
case "zh-TW":
|
||||||
case "de":
|
case "ko":
|
||||||
case "fr":
|
case "ru":
|
||||||
case "it":
|
case "de":
|
||||||
targetLang.value = browser.i18n.getUILanguage();
|
case "fr":
|
||||||
secondTargetLang.value = "en";
|
case "it":
|
||||||
break;
|
targetLang.value = browser.i18n.getUILanguage();
|
||||||
default:
|
secondTargetLang.value = "en";
|
||||||
targetLang.value = "en";
|
break;
|
||||||
secondTargetLang.value = "ja";
|
default:
|
||||||
break;
|
targetLang.value = "en";
|
||||||
}
|
secondTargetLang.value = "ja";
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
S.initOptionsPage().then(function () {
|
S.initOptionsPage().then(function() {
|
||||||
const saveByChangeItems = document.getElementsByClassName("saveByChange");
|
const saveByChangeItems = document.getElementsByClassName("saveByChange");
|
||||||
for (let item of saveByChangeItems) {
|
for (let item of saveByChangeItems) {
|
||||||
item.addEventListener("change", save)
|
item.addEventListener("change", save);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
S.saveOptionsPage();
|
S.saveOptionsPage();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
let e = {};
|
let e = {};
|
||||||
e.hash = location.href;
|
e.hash = location.href;
|
||||||
|
|
||||||
if (e.hash.indexOf('#') != -1) {
|
if (e.hash.indexOf("#") != -1) {
|
||||||
e.hash = '#' + e.hash.split('#')[1];
|
e.hash = "#" + e.hash.split("#")[1];
|
||||||
} else {
|
} else {
|
||||||
e.hash = "#settings";
|
e.hash = "#settings";
|
||||||
}
|
}
|
||||||
readHash(e);
|
readHash(e);
|
||||||
|
|
||||||
|
@ -18,52 +18,55 @@ tm.HashObserver.enable();
|
||||||
document.addEventListener("changehash", readHash, false);
|
document.addEventListener("changehash", readHash, false);
|
||||||
|
|
||||||
function readHash(e) {
|
function readHash(e) {
|
||||||
const hash = e.hash.split('?')[0];
|
const hash = e.hash.split("?")[0];
|
||||||
|
|
||||||
let selected = document.getElementsByClassName("selected");
|
let selected = document.getElementsByClassName("selected");
|
||||||
selected[0].classList.remove("selected");
|
selected[0].classList.remove("selected");
|
||||||
|
|
||||||
document.getElementById("settings").style.display = "none";
|
document.getElementById("settings").style.display = "none";
|
||||||
document.getElementById("information").style.display = "none";
|
document.getElementById("information").style.display = "none";
|
||||||
|
|
||||||
switch (hash) {
|
switch (hash) {
|
||||||
case "#settings":
|
case "#settings":
|
||||||
document.getElementById("settings").style.display = "block";
|
document.getElementById("settings").style.display = "block";
|
||||||
document.getElementsByClassName("settingsLabel")[0].classList.add("selected");
|
document.getElementsByClassName("settingsLabel")[0].classList.add("selected");
|
||||||
break;
|
break;
|
||||||
case "#information":
|
case "#information":
|
||||||
document.getElementById("information").style.display = "block";
|
document.getElementById("information").style.display = "block";
|
||||||
document.getElementsByClassName("informationLabel")[0].classList.add("selected");
|
document.getElementsByClassName("informationLabel")[0].classList.add("selected");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
document.getElementById("settings").style.display = "block";
|
document.getElementById("settings").style.display = "block";
|
||||||
document.getElementsByClassName("settingsLabel")[0].classList.add("selected");
|
document.getElementsByClassName("settingsLabel")[0].classList.add("selected");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = getParams(e.hash);
|
const params = getParams(e.hash);
|
||||||
switch (params.action) {
|
switch (params.action) {
|
||||||
case 'updated':
|
case "updated":
|
||||||
showUpdated();
|
showUpdated();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getParams(hash) {
|
function getParams(hash) {
|
||||||
let params = {};
|
let params = {};
|
||||||
if (hash.split('?')[1] == undefined) return params;
|
if (hash.split("?")[1] == undefined) return params;
|
||||||
hash = hash.split('?')[1].split('&');
|
hash = hash.split("?")[1].split("&");
|
||||||
for (let i of hash) {
|
for (let i of hash) {
|
||||||
params[i.split('=')[0]] = i.split('=')[1];
|
params[i.split("=")[0]] = i.split("=")[1];
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
function showUpdated() {
|
function showUpdated() {
|
||||||
const version = document.getElementsByClassName('addonVersion')[0];
|
const version = document.getElementsByClassName("addonVersion")[0];
|
||||||
version.classList.add('updated');
|
version.classList.add("updated");
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementsByClassName("addonUrl")[0].href = browser.i18n.getMessage("addonUrl");
|
document.getElementsByClassName("addonUrl")[0].href = browser.i18n.getMessage("addonUrl");
|
||||||
document.getElementsByClassName("amazonUrl")[0].href = browser.i18n.getMessage("amazonUrl");
|
document.getElementsByClassName("amazonUrl")[0].href = browser.i18n.getMessage("amazonUrl");
|
||||||
document.getElementsByClassName('addonVersion')[0].getElementsByClassName('caption')[0].getElementsByTagName('a')[0].innerText = `Version ${browser.runtime.getManifest().version}`;
|
document
|
||||||
|
.getElementsByClassName("addonVersion")[0]
|
||||||
|
.getElementsByClassName("caption")[0]
|
||||||
|
.getElementsByTagName("a")[0].innerText = `Version ${browser.runtime.getManifest().version}`;
|
||||||
|
|
|
@ -1,227 +1,227 @@
|
||||||
:root {
|
:root {
|
||||||
--main-text: #0c0c0d;
|
--main-text: #0c0c0d;
|
||||||
--sub-text: #737373;
|
--sub-text: #737373;
|
||||||
--line: #ededf0;
|
--line: #ededf0;
|
||||||
--button: #d7d7db;
|
--button: #d7d7db;
|
||||||
--highlight: #5595ff;
|
--highlight: #5595ff;
|
||||||
--main-bg: #ffffff;
|
--main-bg: #ffffff;
|
||||||
--confirm: #ff4f4f;
|
--confirm: #ff4f4f;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font-family: 'Segoe UI', 'San Francisco', 'Ubuntu', 'Fira Sans', 'Roboto', 'Arial', 'Helvetica', sans-serif;
|
font-family: "Segoe UI", "San Francisco", "Ubuntu", "Fira Sans", "Roboto", "Arial", "Helvetica",
|
||||||
text-align: left;
|
sans-serif;
|
||||||
font-size: 13px;
|
text-align: left;
|
||||||
width: 348px;
|
font-size: 13px;
|
||||||
overflow: hidden;
|
width: 348px;
|
||||||
background-color: var(--main-bg);
|
overflow: hidden;
|
||||||
|
background-color: var(--main-bg);
|
||||||
|
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
svg {
|
svg {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header {
|
#header {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background-color: var(--line);
|
background-color: var(--line);
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#title {
|
#title {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: #666;
|
color: #666;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
|
||||||
#header .rightButtons {
|
#header .rightButtons {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
#donate {
|
#donate {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#donate svg {
|
#donate svg {
|
||||||
height: 18px;
|
height: 18px;
|
||||||
width: 18px;
|
width: 18px;
|
||||||
fill: var(--sub-text);
|
fill: var(--sub-text);
|
||||||
transition: all 100ms;
|
transition: all 100ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
#donate:hover svg {
|
#donate:hover svg {
|
||||||
fill: var(--confirm);
|
fill: var(--confirm);
|
||||||
}
|
}
|
||||||
|
|
||||||
#setting {
|
#setting {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#setting svg {
|
#setting svg {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
height: 18px;
|
height: 18px;
|
||||||
width: 18px;
|
width: 18px;
|
||||||
fill: var(--sub-text);
|
fill: var(--sub-text);
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
transition: fill 100ms, transform 300ms ease;
|
transition: fill 100ms, transform 300ms ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
#setting:hover svg {
|
#setting:hover svg {
|
||||||
fill: var(--highlight);
|
fill: var(--highlight);
|
||||||
transform: rotate(270deg);
|
transform: rotate(270deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#main {
|
#main {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
font: inherit;
|
font: inherit;
|
||||||
resize: none;
|
resize: none;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background-color: var(--main-bg);
|
background-color: var(--main-bg);
|
||||||
|
|
||||||
max-height: 215px;
|
max-height: 215px;
|
||||||
height: 37px;
|
height: 37px;
|
||||||
|
|
||||||
/* 100% - padding*2 - border*2 */
|
/* 100% - padding*2 - border*2 */
|
||||||
width: calc(100% - 22px);
|
width: calc(100% - 22px);
|
||||||
|
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border: solid 1px var(--button);
|
border: solid 1px var(--button);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
transition: border-color 100ms ease-out;
|
transition: border-color 100ms ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea:hover,
|
textarea:hover,
|
||||||
textarea:focus {
|
textarea:focus {
|
||||||
border-color: var(--highlight)
|
border-color: var(--highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: solid 1px var(--button);
|
border-top: solid 1px var(--button);
|
||||||
height: 1px;
|
height: 1px;
|
||||||
margin: 10px 0px;
|
margin: 10px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#target {
|
#target {
|
||||||
max-height: 215px;
|
max-height: 215px;
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
padding: 0px 5px 0px;
|
padding: 0px 5px 0px;
|
||||||
background-color: var(--main-bg);
|
background-color: var(--main-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#target p {
|
#target p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background-color: var(--main-bg);
|
background-color: var(--main-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#target .result{
|
#target .result {
|
||||||
background-color: var(--main-bg);
|
background-color: var(--main-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#target .candidate {
|
#target .candidate {
|
||||||
color: var(--sub-text);
|
color: var(--sub-text);
|
||||||
margin-top:1em;
|
margin-top: 1em;
|
||||||
background-color: var(--main-bg);
|
background-color: var(--main-bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#target .candidate:empty {
|
#target .candidate:empty {
|
||||||
margin-top:0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#footer {
|
#footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 0px 10px 10px;
|
padding: 0px 10px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#link {
|
#link {
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#link a {
|
#link a {
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: var(--highlight);
|
color: var(--highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
#link a:hover {
|
#link a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
border: var(--button) solid 1px;
|
border: var(--button) solid 1px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding: 3px 5px;
|
padding: 3px 5px;
|
||||||
padding-right: 20px;
|
padding-right: 20px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
transition: border-color 100ms ease-out;
|
transition: border-color 100ms ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
select:hover {
|
select:hover {
|
||||||
border: var(--highlight) solid 1px;
|
border: var(--highlight) solid 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectWrap {
|
.selectWrap {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectWrap:before {
|
.selectWrap:before {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
content: "";
|
content: "";
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 40%;
|
top: 40%;
|
||||||
right: 7px;
|
right: 7px;
|
||||||
width: 5px;
|
width: 5px;
|
||||||
height: 5px;
|
height: 5px;
|
||||||
|
|
||||||
transform: rotate(45deg);
|
transform: rotate(45deg);
|
||||||
border-bottom: 2px solid var(--sub-text);
|
border-bottom: 2px solid var(--sub-text);
|
||||||
border-right: 2px solid var(--sub-text);
|
border-right: 2px solid var(--sub-text);
|
||||||
|
|
||||||
transition: border-color 100ms ease-out;
|
transition: border-color 100ms ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.selectWrap:hover::before {
|
.selectWrap:hover::before {
|
||||||
border-bottom: 2px solid var(--highlight);
|
border-bottom: 2px solid var(--highlight);
|
||||||
border-right: 2px solid var(--highlight);
|
border-right: 2px solid var(--highlight);
|
||||||
}
|
}
|
||||||
|
|
||||||
::-moz-selection {
|
::-moz-selection {
|
||||||
background: var(--line);
|
background: var(--line);
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,4 +78,4 @@
|
||||||
<script src="popup.js"></script>
|
<script src="popup.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -7,14 +7,14 @@ const S = new settingsObj();
|
||||||
const T = new Translate();
|
const T = new Translate();
|
||||||
|
|
||||||
//設定を読み出し
|
//設定を読み出し
|
||||||
S.init().then(function (value) {
|
S.init().then(function(value) {
|
||||||
defaultTargetLang = value.targetLang;
|
defaultTargetLang = value.targetLang;
|
||||||
secondTargetLang = value.secondTargetLang;
|
secondTargetLang = value.secondTargetLang;
|
||||||
langList.value = value.targetLang; //リスト初期値をセット
|
langList.value = value.targetLang; //リスト初期値をセット
|
||||||
langList.addEventListener("change", changeLang);
|
langList.addEventListener("change", changeLang);
|
||||||
|
|
||||||
document.body.style.fontSize = value.fontSize;
|
document.body.style.fontSize = value.fontSize;
|
||||||
})
|
});
|
||||||
|
|
||||||
let target = document.getElementById("target");
|
let target = document.getElementById("target");
|
||||||
let langList = document.getElementById("langList");
|
let langList = document.getElementById("langList");
|
||||||
|
@ -30,156 +30,165 @@ let sourceWord = "";
|
||||||
setLangList();
|
setLangList();
|
||||||
|
|
||||||
function setLangList() {
|
function setLangList() {
|
||||||
let langListStr = browser.i18n.getMessage("langList");
|
let langListStr = browser.i18n.getMessage("langList");
|
||||||
langListStr = langListStr.split(", ");
|
langListStr = langListStr.split(", ");
|
||||||
|
|
||||||
for (let i in langListStr) {
|
for (let i in langListStr) {
|
||||||
langListStr[i] = langListStr[i].split(":");
|
langListStr[i] = langListStr[i].split(":");
|
||||||
}
|
}
|
||||||
langListStr = langListStr.sort(alphabeticallySort);
|
langListStr = langListStr.sort(alphabeticallySort);
|
||||||
|
|
||||||
let langListHtml = "";
|
let langListHtml = "";
|
||||||
for (let i of langListStr) {
|
for (let i of langListStr) {
|
||||||
langListHtml += `<option value=${i[0]}>${i[1]}</option>`
|
langListHtml += `<option value=${i[0]}>${i[1]}</option>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
langList.innerHTML = langListHtml;
|
langList.innerHTML = langListHtml;
|
||||||
}
|
}
|
||||||
|
|
||||||
setTitles();
|
setTitles();
|
||||||
function setTitles(){
|
function setTitles() {
|
||||||
document.getElementById('donate').title = browser.i18n.getMessage('donateWithPaypalLabel');
|
document.getElementById("donate").title = browser.i18n.getMessage("donateWithPaypalLabel");
|
||||||
document.getElementById("setting").title = browser.i18n.getMessage('settingsLabel');
|
document.getElementById("setting").title = browser.i18n.getMessage("settingsLabel");
|
||||||
document.getElementById("langList").title = browser.i18n.getMessage('targetLangLabel');
|
document.getElementById("langList").title = browser.i18n.getMessage("targetLangLabel");
|
||||||
}
|
}
|
||||||
|
|
||||||
function alphabeticallySort(a, b) {
|
function alphabeticallySort(a, b) {
|
||||||
if (a[1].toString() > b[1].toString()) {
|
if (a[1].toString() > b[1].toString()) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//翻訳先言語変更時に更新
|
//翻訳先言語変更時に更新
|
||||||
async function changeLang() {
|
async function changeLang() {
|
||||||
if (typeof (url) != "undefined") showLink();
|
if (typeof url != "undefined") showLink();
|
||||||
|
|
||||||
if (sourceWord !== "") {
|
if (sourceWord !== "") {
|
||||||
const resultData = await T.translate(sourceWord, undefined, langList.value);
|
const resultData = await T.translate(sourceWord, undefined, langList.value);
|
||||||
showResult(resultData.resultText, resultData.candidateText);
|
showResult(resultData.resultText, resultData.candidateText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//アクティブなタブを取得して渡す
|
//アクティブなタブを取得して渡す
|
||||||
browser.tabs.query({
|
browser.tabs
|
||||||
|
.query({
|
||||||
currentWindow: true,
|
currentWindow: true,
|
||||||
active: true
|
active: true
|
||||||
}).then(function (tabs) {
|
})
|
||||||
|
.then(function(tabs) {
|
||||||
getSelectionWord(tabs);
|
getSelectionWord(tabs);
|
||||||
});
|
});
|
||||||
|
|
||||||
//アクティブタブから選択文字列とurlを取得
|
//アクティブタブから選択文字列とurlを取得
|
||||||
function getSelectionWord(tabs) {
|
function getSelectionWord(tabs) {
|
||||||
for (let tab of tabs) {
|
for (let tab of tabs) {
|
||||||
browser.tabs.sendMessage(
|
browser.tabs
|
||||||
tab.id, {
|
.sendMessage(tab.id, {
|
||||||
message: "fromPopup"
|
message: "fromPopup"
|
||||||
}
|
})
|
||||||
).then(response => {
|
.then(response => {
|
||||||
sourceWord = response.word;
|
sourceWord = response.word;
|
||||||
url = response.url;
|
url = response.url;
|
||||||
refleshSource();
|
refleshSource();
|
||||||
showLink();
|
showLink();
|
||||||
}).catch(()=>{});
|
})
|
||||||
}
|
.catch(() => {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//ページ翻訳へのリンクを表示
|
//ページ翻訳へのリンクを表示
|
||||||
function showLink() {
|
function showLink() {
|
||||||
document.getElementById("link").innerHTML = "<a href=https://translate.google.com/translate?hl=" + langList.value + "&sl=auto&u=" + encodeURIComponent(url) + ">" + browser.i18n.getMessage('showLink') + "</a>";
|
document.getElementById("link").innerHTML =
|
||||||
|
"<a href=https://translate.google.com/translate?hl=" +
|
||||||
|
langList.value +
|
||||||
|
"&sl=auto&u=" +
|
||||||
|
encodeURIComponent(url) +
|
||||||
|
">" +
|
||||||
|
browser.i18n.getMessage("showLink") +
|
||||||
|
"</a>";
|
||||||
}
|
}
|
||||||
|
|
||||||
//翻訳元テキストを表示
|
//翻訳元テキストを表示
|
||||||
function refleshSource() {
|
function refleshSource() {
|
||||||
if (sourceWord !== "") {
|
if (sourceWord !== "") {
|
||||||
textarea.innerHTML = sourceWord;
|
textarea.innerHTML = sourceWord;
|
||||||
resize();
|
resize();
|
||||||
inputText();
|
inputText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea.addEventListener("paste", resize)
|
textarea.addEventListener("paste", resize);
|
||||||
|
|
||||||
textarea.addEventListener("keydown", resize);
|
textarea.addEventListener("keydown", resize);
|
||||||
|
|
||||||
textarea.addEventListener("keyup", function (event) {
|
textarea.addEventListener("keyup", function(event) {
|
||||||
//if (event.keyCode == 13) resize();
|
//if (event.keyCode == 13) resize();
|
||||||
resize();
|
resize();
|
||||||
inputText();
|
inputText();
|
||||||
});
|
});
|
||||||
|
|
||||||
//テキストボックスをリサイズ
|
//テキストボックスをリサイズ
|
||||||
function resize() {
|
function resize() {
|
||||||
setTimeout(function () {
|
setTimeout(function() {
|
||||||
textarea.style.height = "0px";
|
textarea.style.height = "0px";
|
||||||
textarea.style.height = parseInt(textarea.scrollHeight) + "px";
|
textarea.style.height = parseInt(textarea.scrollHeight) + "px";
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea.addEventListener("click", textAreaClick, {
|
textarea.addEventListener("click", textAreaClick, {
|
||||||
once: true
|
once: true
|
||||||
});
|
});
|
||||||
//テキストエリアクリック時の処理
|
//テキストエリアクリック時の処理
|
||||||
function textAreaClick() {
|
function textAreaClick() {
|
||||||
textarea.select();
|
textarea.select();
|
||||||
}
|
}
|
||||||
|
|
||||||
//文字入力時の処理
|
//文字入力時の処理
|
||||||
async function inputText() {
|
async function inputText() {
|
||||||
sourceWord = textarea.value;
|
sourceWord = textarea.value;
|
||||||
|
|
||||||
const resultData = await T.translate(sourceWord, 'auto', langList.value);
|
const resultData = await T.translate(sourceWord, "auto", langList.value);
|
||||||
changeSecondLang(defaultTargetLang, resultData.sourceLanguage, resultData.percentage);
|
changeSecondLang(defaultTargetLang, resultData.sourceLanguage, resultData.percentage);
|
||||||
showResult(resultData.resultText, resultData.candidateText);
|
showResult(resultData.resultText, resultData.candidateText);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showResult(resultText, candidateText) {
|
function showResult(resultText, candidateText) {
|
||||||
const resultArea = target.getElementsByClassName("result")[0];
|
const resultArea = target.getElementsByClassName("result")[0];
|
||||||
const candidateArea = target.getElementsByClassName("candidate")[0];
|
const candidateArea = target.getElementsByClassName("candidate")[0];
|
||||||
|
|
||||||
resultArea.innerText = resultText;
|
resultArea.innerText = resultText;
|
||||||
if (S.get().ifShowCandidate) candidateArea.innerText = candidateText;
|
if (S.get().ifShowCandidate) candidateArea.innerText = candidateText;
|
||||||
}
|
}
|
||||||
|
|
||||||
let changeLangFlag = false;
|
let changeLangFlag = false;
|
||||||
|
|
||||||
function changeSecondLang(defaultTargetLang, sourceLang, percentage) {
|
function changeSecondLang(defaultTargetLang, sourceLang, percentage) {
|
||||||
if(!S.get().ifChangeSecondLang) return;
|
if (!S.get().ifChangeSecondLang) return;
|
||||||
//検出された翻訳元言語がターゲット言語と一致
|
//検出された翻訳元言語がターゲット言語と一致
|
||||||
const equalsSourceAndTarget = sourceLang == langList.value && percentage > 0;
|
const equalsSourceAndTarget = sourceLang == langList.value && percentage > 0;
|
||||||
|
|
||||||
//検出された翻訳元言語がデフォルト言語と一致
|
//検出された翻訳元言語がデフォルト言語と一致
|
||||||
const equalsSourceAndDefault = sourceLang == defaultTargetLang && percentage > 0;
|
const equalsSourceAndDefault = sourceLang == defaultTargetLang && percentage > 0;
|
||||||
|
|
||||||
if (!changeLangFlag) {
|
if (!changeLangFlag) {
|
||||||
//通常時
|
//通常時
|
||||||
if (equalsSourceAndTarget && equalsSourceAndDefault) {
|
if (equalsSourceAndTarget && equalsSourceAndDefault) {
|
||||||
//ソースとターゲットとデフォルトが一致する場合
|
//ソースとターゲットとデフォルトが一致する場合
|
||||||
//ターゲットを第2言語に変更
|
//ターゲットを第2言語に変更
|
||||||
changeLangFlag = true;
|
changeLangFlag = true;
|
||||||
langList.value = secondTargetLang;
|
langList.value = secondTargetLang;
|
||||||
changeLang();
|
changeLang();
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//第2言語に切替した後
|
|
||||||
if (!equalsSourceAndDefault) {
|
|
||||||
//ソースとデフォルトが異なる場合
|
|
||||||
//ターゲットをデフォルトに戻す
|
|
||||||
changeLangFlag = false;
|
|
||||||
langList.value = defaultTargetLang;
|
|
||||||
changeLang();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
//第2言語に切替した後
|
||||||
|
if (!equalsSourceAndDefault) {
|
||||||
|
//ソースとデフォルトが異なる場合
|
||||||
|
//ターゲットをデフォルトに戻す
|
||||||
|
changeLangFlag = false;
|
||||||
|
langList.value = defaultTargetLang;
|
||||||
|
changeLang();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,94 +1,95 @@
|
||||||
:root {
|
:root {
|
||||||
--simple-translate-main-text: #0c0c0d;
|
--simple-translate-main-text: #0c0c0d;
|
||||||
--simple-translate-sub-text: #737373;
|
--simple-translate-sub-text: #737373;
|
||||||
--simple-translate-line: #ededf0;
|
--simple-translate-line: #ededf0;
|
||||||
--simple-translate-button: #d7d7db;
|
--simple-translate-button: #d7d7db;
|
||||||
--simple-translate-highlight: #5595ff;
|
--simple-translate-highlight: #5595ff;
|
||||||
--simple-translate-main-bg: #ffffff;
|
--simple-translate-main-bg: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
#simple-translate-button {
|
#simple-translate-button {
|
||||||
all: initial;
|
all: initial;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08);
|
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08);
|
||||||
border-radius: 10%;
|
border-radius: 10%;
|
||||||
background-image: url("icons/512.png");
|
background-image: url("icons/512.png");
|
||||||
background-size: 75%;
|
background-size: 75%;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
width: 22px;
|
width: 22px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
z-index: 2147483647;
|
z-index: 2147483647;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
display: none;
|
display: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
animation-duration: 200ms;
|
animation-duration: 200ms;
|
||||||
animation-name: simple-translate-showButton;
|
animation-name: simple-translate-showButton;
|
||||||
}
|
}
|
||||||
|
|
||||||
#simple-translate-panel {
|
#simple-translate-panel {
|
||||||
all: initial;
|
all: initial;
|
||||||
background-color: var(--simple-translate-main-bg);
|
background-color: var(--simple-translate-main-bg);
|
||||||
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08);
|
box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.16), 0 0 0 1px rgba(0, 0, 0, 0.08);
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
min-height: 20px;
|
min-height: 20px;
|
||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
line-height: 150%;
|
line-height: 150%;
|
||||||
height: auto;
|
height: auto;
|
||||||
min-width: 10px;
|
min-width: 10px;
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
padding: 10px 18px;
|
padding: 10px 18px;
|
||||||
z-index: 2147483646;
|
z-index: 2147483646;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
display: none;
|
display: none;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
#simple-translate-panel p {
|
#simple-translate-panel p {
|
||||||
all: initial;
|
all: initial;
|
||||||
font-family: 'Segoe UI', 'San Francisco', 'Ubuntu', 'Fira Sans', 'Roboto', 'Arial', 'Helvetica', sans-serif !important;
|
font-family: "Segoe UI", "San Francisco", "Ubuntu", "Fira Sans", "Roboto", "Arial", "Helvetica",
|
||||||
text-align: left;
|
sans-serif !important;
|
||||||
display: block;
|
text-align: left;
|
||||||
font-size: inherit;
|
display: block;
|
||||||
color: var(--simple-translate-main-text);
|
font-size: inherit;
|
||||||
margin: 0;
|
color: var(--simple-translate-main-text);
|
||||||
word-wrap: break-word;
|
margin: 0;
|
||||||
|
word-wrap: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
#simple-translate-panel p::-moz-selection {
|
#simple-translate-panel p::-moz-selection {
|
||||||
background: var(--simple-translate-line);
|
background: var(--simple-translate-line);
|
||||||
}
|
}
|
||||||
|
|
||||||
#simple-translate-panel .candidate {
|
#simple-translate-panel .candidate {
|
||||||
color: var(--simple-translate-sub-text);
|
color: var(--simple-translate-sub-text);
|
||||||
margin-top:1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#simple-translate-panel .candidate:empty {
|
#simple-translate-panel .candidate:empty {
|
||||||
margin-top:0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes simple-translate-showButton {
|
@keyframes simple-translate-showButton {
|
||||||
0% {
|
0% {
|
||||||
transform: scale3d(1, 1, 1);
|
transform: scale3d(1, 1, 1);
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
transform: scale3d(1.1, 1.1, 1.1);
|
transform: scale3d(1.1, 1.1, 1.1);
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
transform: scale3d(1, 1, 1);
|
transform: scale3d(1, 1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes simple-translate-fadein {
|
@keyframes simple-translate-fadein {
|
||||||
from {
|
from {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,10 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
document.body.insertAdjacentHTML("afterend", "<div id='simple-translate-button'></div><div id='simple-translate-panel'><p>...</p></div>"); //bodyの直後にボタン配置
|
document.body.insertAdjacentHTML(
|
||||||
|
"afterend",
|
||||||
|
"<div id='simple-translate-button'></div><div id='simple-translate-panel'><p>...</p></div>"
|
||||||
|
); //bodyの直後にボタン配置
|
||||||
var button = document.getElementById("simple-translate-button");
|
var button = document.getElementById("simple-translate-button");
|
||||||
var panel = document.getElementById("simple-translate-panel");
|
var panel = document.getElementById("simple-translate-panel");
|
||||||
var selectionWord;
|
var selectionWord;
|
||||||
|
@ -15,180 +18,199 @@ S.init();
|
||||||
window.addEventListener("mouseup", Select, false);
|
window.addEventListener("mouseup", Select, false);
|
||||||
//テキスト選択時の処理 ダブルクリックした時2回処理が走るのを何とかしたい
|
//テキスト選択時の処理 ダブルクリックした時2回処理が走るのを何とかしたい
|
||||||
async function Select(e) {
|
async function Select(e) {
|
||||||
hidePanel(e);
|
hidePanel(e);
|
||||||
if (e.target.tagName == "INPUT" && e.target.type == "password") return;
|
if (e.target.tagName == "INPUT" && e.target.type == "password") return;
|
||||||
|
|
||||||
setTimeout(async () => { //誤動作防止の為ディレイを設ける
|
setTimeout(async () => {
|
||||||
//選択文の取得 テキストフィールド内を選択した場合にも対応
|
//誤動作防止の為ディレイを設ける
|
||||||
const isTextField = (e.target.tagName == "INPUT") || (e.target.tagName == "TEXTAREA");
|
//選択文の取得 テキストフィールド内を選択した場合にも対応
|
||||||
if (isTextField) selectionWord = e.target.value.substring(e.target.selectionStart, e.target.selectionEnd);
|
const isTextField = e.target.tagName == "INPUT" || e.target.tagName == "TEXTAREA";
|
||||||
else selectionWord = String(window.getSelection());
|
if (isTextField)
|
||||||
|
selectionWord = e.target.value.substring(e.target.selectionStart, e.target.selectionEnd);
|
||||||
|
else selectionWord = String(window.getSelection());
|
||||||
|
|
||||||
//選択文が存在し,パネル外を左クリックした場合は翻訳する
|
//選択文が存在し,パネル外を左クリックした場合は翻訳する
|
||||||
const existsSelectionWord = (selectionWord.length !== 0);
|
const existsSelectionWord = selectionWord.length !== 0;
|
||||||
const isLeftClick = (e.button == 0);
|
const isLeftClick = e.button == 0;
|
||||||
const isPanelOutside = (e.target.id !== 'simple-translate-panel') && (e.target.parentElement.id !== 'simple-translate-panel');
|
const isPanelOutside =
|
||||||
const shouldTranslate = existsSelectionWord && isLeftClick && isPanelOutside;
|
e.target.id !== "simple-translate-panel" &&
|
||||||
if (!shouldTranslate) return;
|
e.target.parentElement.id !== "simple-translate-panel";
|
||||||
|
const shouldTranslate = existsSelectionWord && isLeftClick && isPanelOutside;
|
||||||
|
if (!shouldTranslate) return;
|
||||||
|
|
||||||
//選択した言語が翻訳先言語と異なれば翻訳する
|
//選択した言語が翻訳先言語と異なれば翻訳する
|
||||||
const needTranslate = await checkLang(selectionWord, 'auto', S.get().targetLang);
|
const needTranslate = await checkLang(selectionWord, "auto", S.get().targetLang);
|
||||||
if (!needTranslate) return;
|
if (!needTranslate) return;
|
||||||
|
|
||||||
clickPosition = e;
|
clickPosition = e;
|
||||||
switch (S.get().whenSelectText) {
|
switch (S.get().whenSelectText) {
|
||||||
case 'showButton':
|
case "showButton":
|
||||||
if (selectionWord.length == 0) return;
|
if (selectionWord.length == 0) return;
|
||||||
popupButton(e);
|
popupButton(e);
|
||||||
break;
|
break;
|
||||||
case 'showPanel':
|
case "showPanel":
|
||||||
translate(selectionWord, 'auto', S.get().targetLang);
|
translate(selectionWord, "auto", S.get().targetLang);
|
||||||
if (selectionWord.length == 0) return;
|
if (selectionWord.length == 0) return;
|
||||||
showPanel(e);
|
showPanel(e);
|
||||||
break;
|
break;
|
||||||
case 'dontShowButton':
|
case "dontShowButton":
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//選択テキストの言語をチェックして返す
|
//選択テキストの言語をチェックして返す
|
||||||
async function checkLang(sourceWord, sourceLang, targetLang) {
|
async function checkLang(sourceWord, sourceLang, targetLang) {
|
||||||
if (!S.get().ifCheckLang) return true; //設定がオフならtrue
|
if (!S.get().ifCheckLang) return true; //設定がオフならtrue
|
||||||
sourceWord = sourceWord.substr(0, 100); //先頭100字で言語を判定
|
sourceWord = sourceWord.substr(0, 100); //先頭100字で言語を判定
|
||||||
|
|
||||||
const resultData = await T.translate(sourceWord, sourceLang, targetLang);
|
const resultData = await T.translate(sourceWord, sourceLang, targetLang);
|
||||||
const needTranslate = (S.get().targetLang != resultData.sourceLanguage) && (resultData.percentage > 0);
|
const needTranslate =
|
||||||
return needTranslate; //ターゲットとソースの言語が不一致ならtrue
|
S.get().targetLang != resultData.sourceLanguage && resultData.percentage > 0;
|
||||||
|
return needTranslate; //ターゲットとソースの言語が不一致ならtrue
|
||||||
}
|
}
|
||||||
|
|
||||||
//ボタンを表示
|
//ボタンを表示
|
||||||
function popupButton(e) {
|
function popupButton(e) {
|
||||||
let topPosition = 10;
|
let topPosition = 10;
|
||||||
let leftPosition = 10;
|
let leftPosition = 10;
|
||||||
let buttonSize = S.get().buttonSize;
|
let buttonSize = S.get().buttonSize;
|
||||||
|
|
||||||
switch (S.get().buttonPosition) {
|
switch (S.get().buttonPosition) {
|
||||||
case "rightUp":
|
case "rightUp":
|
||||||
topPosition = (-1 * buttonSize) - 10;
|
topPosition = -1 * buttonSize - 10;
|
||||||
break;
|
break;
|
||||||
case "rightDown":
|
case "rightDown":
|
||||||
break;
|
break;
|
||||||
case "leftUp":
|
case "leftUp":
|
||||||
topPosition = (-1 * buttonSize) - 10;
|
topPosition = -1 * buttonSize - 10;
|
||||||
leftPosition = (-1 * buttonSize) - 10;
|
leftPosition = -1 * buttonSize - 10;
|
||||||
break;
|
break;
|
||||||
case "leftDown":
|
case "leftDown":
|
||||||
leftPosition = (-1 * buttonSize) - 10;
|
leftPosition = -1 * buttonSize - 10;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.style.left = e.clientX + leftPosition + 'px';
|
button.style.left = e.clientX + leftPosition + "px";
|
||||||
button.style.top = e.clientY + topPosition + 'px';
|
button.style.top = e.clientY + topPosition + "px";
|
||||||
button.style.width = S.get().buttonSize + "px";
|
button.style.width = S.get().buttonSize + "px";
|
||||||
button.style.height = S.get().buttonSize + "px";
|
button.style.height = S.get().buttonSize + "px";
|
||||||
button.style.display = 'block';
|
button.style.display = "block";
|
||||||
}
|
}
|
||||||
button.addEventListener("click", function (e) {
|
button.addEventListener(
|
||||||
translate(selectionWord, 'auto', S.get().targetLang);
|
"click",
|
||||||
|
function(e) {
|
||||||
|
translate(selectionWord, "auto", S.get().targetLang);
|
||||||
showPanel(e);
|
showPanel(e);
|
||||||
}, false);
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
async function translate(sourceWord, sourceLang, targetLang) {
|
async function translate(sourceWord, sourceLang, targetLang) {
|
||||||
const resultData = await T.translate(sourceWord, sourceLang, targetLang);
|
const resultData = await T.translate(sourceWord, sourceLang, targetLang);
|
||||||
showResult(resultData.resultText, resultData.candidateText);
|
showResult(resultData.resultText, resultData.candidateText);
|
||||||
panelPosition(clickPosition);
|
panelPosition(clickPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
function showResult(resultText, candidateText) {
|
function showResult(resultText, candidateText) {
|
||||||
panel.innerHTML = '<p class=result></p><p class=candidate>';
|
panel.innerHTML = "<p class=result></p><p class=candidate>";
|
||||||
const resultArea = panel.getElementsByClassName("result")[0];
|
const resultArea = panel.getElementsByClassName("result")[0];
|
||||||
const candidateArea = panel.getElementsByClassName("candidate")[0];
|
const candidateArea = panel.getElementsByClassName("candidate")[0];
|
||||||
|
|
||||||
resultArea.innerText = resultText;
|
resultArea.innerText = resultText;
|
||||||
if (S.get().ifShowCandidate) candidateArea.innerText = candidateText;
|
if (S.get().ifShowCandidate) candidateArea.innerText = candidateText;
|
||||||
}
|
}
|
||||||
|
|
||||||
//パネル表示
|
//パネル表示
|
||||||
function showPanel(e) {
|
function showPanel(e) {
|
||||||
clickPosition = e;
|
clickPosition = e;
|
||||||
panel.style.display = 'block';
|
panel.style.display = "block";
|
||||||
panelPosition(e);
|
panelPosition(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
//パネル非表示
|
//パネル非表示
|
||||||
function hidePanel(e) {
|
function hidePanel(e) {
|
||||||
button.style.display = 'none'; //ボタンを非表示
|
button.style.display = "none"; //ボタンを非表示
|
||||||
if ((e.target.id !== "simple-translate-panel") && (e.target.parentElement.id !== "simple-translate-panel")) { //パネル以外の場所をクリックでパネルを非表示
|
if (
|
||||||
panel.style.display = 'none';
|
e.target.id !== "simple-translate-panel" &&
|
||||||
panel.innerHTML = "<p>...</p>";
|
e.target.parentElement.id !== "simple-translate-panel"
|
||||||
}
|
) {
|
||||||
|
//パネル以外の場所をクリックでパネルを非表示
|
||||||
|
panel.style.display = "none";
|
||||||
|
panel.innerHTML = "<p>...</p>";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Esc押下でパネルを閉じる
|
//Esc押下でパネルを閉じる
|
||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener("keydown", e => {
|
||||||
if (e.key == 'Escape') hidePanel(e);
|
if (e.key == "Escape") hidePanel(e);
|
||||||
})
|
});
|
||||||
|
|
||||||
//パネルがウィンドウ外にはみ出る時に位置を調整
|
//パネルがウィンドウ外にはみ出る時に位置を調整
|
||||||
function panelPosition(e) {
|
function panelPosition(e) {
|
||||||
var p = new Object();
|
var p = new Object();
|
||||||
panel.style.width = S.get().width + 'px'; //300px
|
panel.style.width = S.get().width + "px"; //300px
|
||||||
var panelHeight = panel.clientHeight;
|
var panelHeight = panel.clientHeight;
|
||||||
var panelWidth = parseInt(window.getComputedStyle(panel.getElementsByTagName("p")[0], null).width);
|
var panelWidth = parseInt(
|
||||||
//一旦パネルの横幅を300にしてpの横幅を取得
|
window.getComputedStyle(panel.getElementsByTagName("p")[0], null).width
|
||||||
|
);
|
||||||
|
//一旦パネルの横幅を300にしてpの横幅を取得
|
||||||
|
|
||||||
if (e.clientX + panelWidth > window.innerWidth - 80) {
|
if (e.clientX + panelWidth > window.innerWidth - 80) {
|
||||||
p.x = window.innerWidth - panelWidth - 80;
|
p.x = window.innerWidth - panelWidth - 80;
|
||||||
} else {
|
} else {
|
||||||
p.x = e.clientX;
|
p.x = e.clientX;
|
||||||
}
|
}
|
||||||
if (e.clientY + panelHeight > window.innerHeight - 30) {
|
if (e.clientY + panelHeight > window.innerHeight - 30) {
|
||||||
p.y = window.innerHeight - panelHeight - 30;
|
p.y = window.innerHeight - panelHeight - 30;
|
||||||
} else {
|
} else {
|
||||||
p.y = e.clientY;
|
p.y = e.clientY;
|
||||||
}
|
}
|
||||||
panel.style.width = 'auto'; //panelWidth + 'px';
|
panel.style.width = "auto"; //panelWidth + 'px';
|
||||||
panel.style.top = p.y + 'px';
|
panel.style.top = p.y + "px";
|
||||||
panel.style.left = p.x + 'px';
|
panel.style.left = p.x + "px";
|
||||||
|
|
||||||
panel.style.maxWidth = S.get().width + "px";
|
panel.style.maxWidth = S.get().width + "px";
|
||||||
panel.style.maxHeight = S.get().height + "px";
|
panel.style.maxHeight = S.get().height + "px";
|
||||||
panel.style.fontSize = S.get().fontSize + "px";
|
panel.style.fontSize = S.get().fontSize + "px";
|
||||||
panel.style.backgroundColor = S.get().bgColor;
|
panel.style.backgroundColor = S.get().bgColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//スクリプトからのメッセージに返信
|
//スクリプトからのメッセージに返信
|
||||||
browser.runtime.onMessage.addListener(function (request) {
|
browser.runtime.onMessage.addListener(function(request) {
|
||||||
switch (request.message) {
|
switch (request.message) {
|
||||||
case "fromPopup":
|
case "fromPopup":
|
||||||
return sendToPopup();
|
return sendToPopup();
|
||||||
break;
|
break;
|
||||||
case "showPanelFromMenu":
|
case "showPanelFromMenu":
|
||||||
showPanelFromMenu();
|
showPanelFromMenu();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//popupにテキストとurlを返す
|
//popupにテキストとurlを返す
|
||||||
function sendToPopup() {
|
function sendToPopup() {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
word: String(window.getSelection()),
|
word: String(window.getSelection()),
|
||||||
url: window.location.href
|
url: window.location.href
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//コンテキストメニュークリックでパネルを表示
|
//コンテキストメニュークリックでパネルを表示
|
||||||
function showPanelFromMenu() {
|
function showPanelFromMenu() {
|
||||||
button.style.display = "none";
|
button.style.display = "none";
|
||||||
|
|
||||||
//キャレットブラウズモードに対応
|
|
||||||
const isTextField = (document.activeElement.tagName == "INPUT") || (document.activeElement.tagName == "TEXTAREA");
|
|
||||||
if (isTextField) selectionWord = document.activeElement.value.substring(document.activeElement.selectionStart, document.activeElement.selectionEnd);
|
|
||||||
else selectionWord = String(window.getSelection());
|
|
||||||
if (typeof (clickPosition) == 'undefined') clickPosition = { 'clientX': 0, 'clientY': 0 }
|
|
||||||
|
|
||||||
translate(selectionWord, 'auto', S.get().targetLang);
|
//キャレットブラウズモードに対応
|
||||||
showPanel(clickPosition);
|
const isTextField =
|
||||||
|
document.activeElement.tagName == "INPUT" || document.activeElement.tagName == "TEXTAREA";
|
||||||
|
if (isTextField)
|
||||||
|
selectionWord = document.activeElement.value.substring(
|
||||||
|
document.activeElement.selectionStart,
|
||||||
|
document.activeElement.selectionEnd
|
||||||
|
);
|
||||||
|
else selectionWord = String(window.getSelection());
|
||||||
|
if (typeof clickPosition == "undefined") clickPosition = { clientX: 0, clientY: 0 };
|
||||||
|
|
||||||
|
translate(selectionWord, "auto", S.get().targetLang);
|
||||||
|
showPanel(clickPosition);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,83 +4,84 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
class Translate {
|
class Translate {
|
||||||
constructor() {
|
constructor() {}
|
||||||
|
|
||||||
|
set sourceWord(word) {
|
||||||
|
this.sourceWord = word;
|
||||||
|
}
|
||||||
|
|
||||||
|
translate(sourceWord, sourceLang = "auto", targetLang) {
|
||||||
|
//改行で分割
|
||||||
|
const sourceLines = sourceWord.trim().split("\n");
|
||||||
|
|
||||||
|
let promises = [];
|
||||||
|
for (let sourceLine of sourceLines) {
|
||||||
|
promises.push(this.sendRequest(sourceLine, sourceLang, targetLang));
|
||||||
}
|
}
|
||||||
|
|
||||||
set sourceWord(word) {
|
return new Promise(resolve => {
|
||||||
this.sourceWord = word;
|
Promise.all(promises).then(results => {
|
||||||
}
|
resolve(this.formatResult(results));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
translate(sourceWord, sourceLang = 'auto', targetLang) {
|
sendRequest(word, sourceLang, targetLang) {
|
||||||
//改行で分割
|
const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${sourceLang}&tl=${targetLang}&dt=t&dt=bd&q=${encodeURIComponent(
|
||||||
const sourceLines = sourceWord.trim().split("\n");
|
word
|
||||||
|
)}`;
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.responseType = "json";
|
||||||
|
xhr.open("GET", url);
|
||||||
|
xhr.send();
|
||||||
|
|
||||||
let promises = [];
|
return new Promise((resolve, reject) => {
|
||||||
for (let sourceLine of sourceLines) {
|
xhr.onload = () => {
|
||||||
promises.push(this.sendRequest(sourceLine, sourceLang, targetLang));
|
resolve(xhr);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
formatResult(results) {
|
||||||
|
const resultData = {
|
||||||
|
resultText: "",
|
||||||
|
candidateText: "",
|
||||||
|
sourceLanguage: "",
|
||||||
|
percentage: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
//翻訳元言語を取得
|
||||||
|
resultData.sourceLanguage = results[0].response[2];
|
||||||
|
resultData.percentage = results[0].response[6];
|
||||||
|
|
||||||
|
let candidateText = "";
|
||||||
|
let wordCount = 0;
|
||||||
|
let lineCount = 0;
|
||||||
|
|
||||||
|
for (const result of results) {
|
||||||
|
lineCount++;
|
||||||
|
|
||||||
|
//翻訳文を取得
|
||||||
|
for (const response of result.response[0]) {
|
||||||
|
resultData.resultText += response[0];
|
||||||
|
}
|
||||||
|
resultData.resultText += "\n";
|
||||||
|
|
||||||
|
//訳候補を取得
|
||||||
|
if (result.response[1]) {
|
||||||
|
wordCount++;
|
||||||
|
for (let i = 0; i < result.response[1].length; i++) {
|
||||||
|
const partsOfSpeech = result.response[1][i][0];
|
||||||
|
const candidates = result.response[1][i][1];
|
||||||
|
candidateText += `${partsOfSpeech}${partsOfSpeech != "" ? ": " : ""}${candidates.join(
|
||||||
|
", "
|
||||||
|
)}\n`;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return new Promise(resolve => {
|
|
||||||
Promise.all(promises)
|
|
||||||
.then((results) => {
|
|
||||||
resolve(this.formatResult(results));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
//訳候補が一つの単語のみに対して存在するとき返す
|
||||||
|
if (wordCount == 1 && lineCount == 1) resultData.candidateText = candidateText;
|
||||||
|
|
||||||
|
return resultData;
|
||||||
sendRequest(word, sourceLang, targetLang) {
|
}
|
||||||
const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=${sourceLang}&tl=${targetLang}&dt=t&dt=bd&q=${encodeURIComponent(word)}`;
|
}
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.responseType = 'json';
|
|
||||||
xhr.open("GET", url);
|
|
||||||
xhr.send();
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
xhr.onload = () => {
|
|
||||||
resolve(xhr);
|
|
||||||
};
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
formatResult(results) {
|
|
||||||
const resultData = {
|
|
||||||
resultText: '',
|
|
||||||
candidateText: '',
|
|
||||||
sourceLanguage: '',
|
|
||||||
percentage: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
//翻訳元言語を取得
|
|
||||||
resultData.sourceLanguage = results[0].response[2];
|
|
||||||
resultData.percentage = results[0].response[6];
|
|
||||||
|
|
||||||
let candidateText = '';
|
|
||||||
let wordCount = 0;
|
|
||||||
let lineCount = 0;
|
|
||||||
|
|
||||||
for (const result of results) {
|
|
||||||
lineCount++;
|
|
||||||
|
|
||||||
//翻訳文を取得
|
|
||||||
for (const response of result.response[0]) {
|
|
||||||
resultData.resultText += response[0];
|
|
||||||
}
|
|
||||||
resultData.resultText += '\n';
|
|
||||||
|
|
||||||
//訳候補を取得
|
|
||||||
if (result.response[1]) {
|
|
||||||
wordCount++;
|
|
||||||
for (let i = 0; i < result.response[1].length; i++) {
|
|
||||||
const partsOfSpeech = result.response[1][i][0];
|
|
||||||
const candidates = result.response[1][i][1];
|
|
||||||
candidateText += `${partsOfSpeech}${partsOfSpeech != '' ? ': ' : ''}${candidates.join(', ')}\n`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//訳候補が一つの単語のみに対して存在するとき返す
|
|
||||||
if (wordCount == 1 && lineCount == 1) resultData.candidateText = candidateText;
|
|
||||||
|
|
||||||
return resultData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue