diff --git a/README.md b/.github/README.md similarity index 100% rename from README.md rename to .github/README.md diff --git a/_locales/am/messages.json b/_locales/am/messages.json index b40df4c..5175a68 100644 --- a/_locales/am/messages.json +++ b/_locales/am/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/ar/messages.json b/_locales/ar/messages.json index 96b6b0d..cfeff52 100644 --- a/_locales/ar/messages.json +++ b/_locales/ar/messages.json @@ -5,11 +5,8 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "إلغاء" @@ -17,8 +14,11 @@ "description": { "message": "أفضل أداة إطار حسب بإطار. تعمل على جميع المواقع! حرك مؤشر الفأرة على الفيديو و إستعمل مفاتيح الأسهم لتبديل بين الإطارات." }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "disabled": { + "message": "Disabled" + }, + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "إعادة تعيين" - }, - "save": { - "message": "حفظ" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/bg/messages.json b/_locales/bg/messages.json index b40df4c..5175a68 100644 --- a/_locales/bg/messages.json +++ b/_locales/bg/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/bn/messages.json b/_locales/bn/messages.json index b40df4c..5175a68 100644 --- a/_locales/bn/messages.json +++ b/_locales/bn/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/ca/messages.json b/_locales/ca/messages.json index b40df4c..5175a68 100644 --- a/_locales/ca/messages.json +++ b/_locales/ca/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/cs/messages.json b/_locales/cs/messages.json index b40df4c..5175a68 100644 --- a/_locales/cs/messages.json +++ b/_locales/cs/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/da/messages.json b/_locales/da/messages.json index b40df4c..5175a68 100644 --- a/_locales/da/messages.json +++ b/_locales/da/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/de/messages.json b/_locales/de/messages.json index 25cbc60..821748d 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -5,11 +5,8 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" @@ -17,8 +14,11 @@ "description": { "message": "Das beste Frame-by-Frame-Tool. Funktioniert mit allen Websites! Bewegen Sie den Mauszeiger über das Video und verwenden Sie die Pfeiltasten der Tastatur, um die Frames zu wechseln." }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "disabled": { + "message": "Disabled" + }, + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/el/messages.json b/_locales/el/messages.json index b40df4c..5175a68 100644 --- a/_locales/el/messages.json +++ b/_locales/el/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/en/messages.json b/_locales/en/messages.json index b40df4c..5175a68 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/es/messages.json b/_locales/es/messages.json index b40df4c..5175a68 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/et/messages.json b/_locales/et/messages.json index b40df4c..5175a68 100644 --- a/_locales/et/messages.json +++ b/_locales/et/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/fa/messages.json b/_locales/fa/messages.json index b40df4c..5175a68 100644 --- a/_locales/fa/messages.json +++ b/_locales/fa/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/fi/messages.json b/_locales/fi/messages.json index b40df4c..5175a68 100644 --- a/_locales/fi/messages.json +++ b/_locales/fi/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/fil/messages.json b/_locales/fil/messages.json index b40df4c..5175a68 100644 --- a/_locales/fil/messages.json +++ b/_locales/fil/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index b40df4c..5175a68 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/gu/messages.json b/_locales/gu/messages.json index b40df4c..5175a68 100644 --- a/_locales/gu/messages.json +++ b/_locales/gu/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/he/messages.json b/_locales/he/messages.json index 4be85ef..4861bab 100644 --- a/_locales/he/messages.json +++ b/_locales/he/messages.json @@ -5,11 +5,8 @@ "areYouSureYouWantToImportTheData": { "message": "האם אתה בטוח שברצונך לייבא את המידע?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "ביטול" @@ -17,8 +14,11 @@ "description": { "message": "הכלי הטוב ביותר למעבר בין חלוניות (פריימים). עובד עם כל האתרים! יש להזיז את סמן העכבר על גבי סרטון ולהשתמש במקשי החיצים למעבר בין פריימים." }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "disabled": { + "message": "Disabled" + }, + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "ייצוא" @@ -29,25 +29,16 @@ "language": { "message": "שפה" }, - "light": { - "message": "בהיר" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "אישור" }, - "reset": { - "message": "איפוס" - }, - "save": { - "message": "שמירה" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "משהו השתבש. יש לנסות לטעון את העמוד מחדש." - }, - "theme": { - "message": "ערכת נושא" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/hi/messages.json b/_locales/hi/messages.json index b40df4c..5175a68 100644 --- a/_locales/hi/messages.json +++ b/_locales/hi/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/hin/messages.json b/_locales/hin/messages.json index 528455c..5175a68 100644 --- a/_locales/hin/messages.json +++ b/_locales/hin/messages.json @@ -5,17 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "description": { + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" + }, + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -26,16 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/hr/messages.json b/_locales/hr/messages.json index b40df4c..5175a68 100644 --- a/_locales/hr/messages.json +++ b/_locales/hr/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/hu/messages.json b/_locales/hu/messages.json index b40df4c..5175a68 100644 --- a/_locales/hu/messages.json +++ b/_locales/hu/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/id/messages.json b/_locales/id/messages.json index b40df4c..5175a68 100644 --- a/_locales/id/messages.json +++ b/_locales/id/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/it/messages.json b/_locales/it/messages.json index b40df4c..5175a68 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/ja/messages.json b/_locales/ja/messages.json index b40df4c..5175a68 100644 --- a/_locales/ja/messages.json +++ b/_locales/ja/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/kn/messages.json b/_locales/kn/messages.json index b40df4c..5175a68 100644 --- a/_locales/kn/messages.json +++ b/_locales/kn/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/ko/messages.json b/_locales/ko/messages.json index b40df4c..5175a68 100644 --- a/_locales/ko/messages.json +++ b/_locales/ko/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/lt/messages.json b/_locales/lt/messages.json index b40df4c..5175a68 100644 --- a/_locales/lt/messages.json +++ b/_locales/lt/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/lv/messages.json b/_locales/lv/messages.json index b40df4c..5175a68 100644 --- a/_locales/lv/messages.json +++ b/_locales/lv/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/ml/messages.json b/_locales/ml/messages.json index b40df4c..5175a68 100644 --- a/_locales/ml/messages.json +++ b/_locales/ml/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/mr/messages.json b/_locales/mr/messages.json index b40df4c..5175a68 100644 --- a/_locales/mr/messages.json +++ b/_locales/mr/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/ms/messages.json b/_locales/ms/messages.json index b40df4c..5175a68 100644 --- a/_locales/ms/messages.json +++ b/_locales/ms/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/nb_NO/messages.json b/_locales/nb_NO/messages.json index 528455c..5175a68 100644 --- a/_locales/nb_NO/messages.json +++ b/_locales/nb_NO/messages.json @@ -5,17 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "description": { + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" + }, + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -26,16 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/nl/messages.json b/_locales/nl/messages.json index b40df4c..5175a68 100644 --- a/_locales/nl/messages.json +++ b/_locales/nl/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/no/messages.json b/_locales/no/messages.json index b40df4c..5175a68 100644 --- a/_locales/no/messages.json +++ b/_locales/no/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/pl/messages.json b/_locales/pl/messages.json index b40df4c..5175a68 100644 --- a/_locales/pl/messages.json +++ b/_locales/pl/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/pt_BR/messages.json b/_locales/pt_BR/messages.json index b40df4c..5175a68 100644 --- a/_locales/pt_BR/messages.json +++ b/_locales/pt_BR/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/pt_PT/messages.json b/_locales/pt_PT/messages.json index b40df4c..5175a68 100644 --- a/_locales/pt_PT/messages.json +++ b/_locales/pt_PT/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/ro/messages.json b/_locales/ro/messages.json index b40df4c..5175a68 100644 --- a/_locales/ro/messages.json +++ b/_locales/ro/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index b1566b6..5c242a9 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -5,11 +5,8 @@ "areYouSureYouWantToImportTheData": { "message": "Вы действительно хотите испортировать данные?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Отмена" @@ -17,8 +14,11 @@ "description": { "message": "Лучшее Frame By Frame расширение. Работает со всеми веб-сайтами! Наведите курсор на видео, затем используйте клавиатуру, чтобы выбрать нужный кадр." }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "disabled": { + "message": "Disabled" + }, + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Экспорт" @@ -29,25 +29,16 @@ "language": { "message": "Язык" }, - "light": { - "message": "Светлая" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ок" }, - "reset": { - "message": "Сброс" - }, - "save": { - "message": "Сохранить" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Что-то пошло не так. Попробуйте перезагрузить страницу." - }, - "theme": { - "message": "Тема" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/sk/messages.json b/_locales/sk/messages.json index b40df4c..5175a68 100644 --- a/_locales/sk/messages.json +++ b/_locales/sk/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/sl/messages.json b/_locales/sl/messages.json index b40df4c..5175a68 100644 --- a/_locales/sl/messages.json +++ b/_locales/sl/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/sr/messages.json b/_locales/sr/messages.json index b40df4c..5175a68 100644 --- a/_locales/sr/messages.json +++ b/_locales/sr/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/sv/messages.json b/_locales/sv/messages.json index b40df4c..5175a68 100644 --- a/_locales/sv/messages.json +++ b/_locales/sv/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/sw/messages.json b/_locales/sw/messages.json index b40df4c..5175a68 100644 --- a/_locales/sw/messages.json +++ b/_locales/sw/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/ta/messages.json b/_locales/ta/messages.json index b40df4c..5175a68 100644 --- a/_locales/ta/messages.json +++ b/_locales/ta/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/te/messages.json b/_locales/te/messages.json index b40df4c..5175a68 100644 --- a/_locales/te/messages.json +++ b/_locales/te/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/th/messages.json b/_locales/th/messages.json index b40df4c..5175a68 100644 --- a/_locales/th/messages.json +++ b/_locales/th/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/tr/messages.json b/_locales/tr/messages.json index b40df4c..5175a68 100644 --- a/_locales/tr/messages.json +++ b/_locales/tr/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/uk/messages.json b/_locales/uk/messages.json index b40df4c..5175a68 100644 --- a/_locales/uk/messages.json +++ b/_locales/uk/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/vi/messages.json b/_locales/vi/messages.json index b40df4c..5175a68 100644 --- a/_locales/vi/messages.json +++ b/_locales/vi/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json index b40df4c..5175a68 100644 --- a/_locales/zh_CN/messages.json +++ b/_locales/zh_CN/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/_locales/zh_TW/messages.json b/_locales/zh_TW/messages.json index b40df4c..5175a68 100644 --- a/_locales/zh_TW/messages.json +++ b/_locales/zh_TW/messages.json @@ -5,20 +5,20 @@ "areYouSureYouWantToImportTheData": { "message": "Are you sure you want to import the data?" }, - "autoScrollActivation": { - "message": "\"Auto scroll\" activation" - }, - "black": { - "message": "Black" + "automatic": { + "message": "Automatic" }, "cancel": { "message": "Cancel" }, "description": { - "message": "Best Frame By Frame Tool. Works with all websites! Move your mouse cursor over video and use keyboard arrows to switch frames." + "message": "Auto Scroll tool. Works with all websites!" + }, + "disabled": { + "message": "Disabled" }, - "dragDropActivation": { - "message": "\"Drag & Drop\" activation" + "dragDrop": { + "message": "Drag & Drop" }, "export": { "message": "Export" @@ -29,25 +29,16 @@ "language": { "message": "Language" }, - "light": { - "message": "Light" + "leftMouseButton": { + "message": "Left mouse button" }, "ok": { "message": "Ok" }, - "reset": { - "message": "Reset" - }, - "save": { - "message": "Save" - }, - "somethingWentWrongTryReloadingThePage": { - "message": "Something went wrong. Try reloading the page." - }, - "theme": { - "message": "Theme" + "scrollWheel": { + "message": "Scroll wheel" }, - "touchscreenActivation": { - "message": "\"Touchscreen\" activation" + "thePageHostnameIsProtectedByBrowser": { + "message": "The page HOSTNAME is protected by browser." } } \ No newline at end of file diff --git a/assets/fonts/Roboto-Bold.ttf b/assets/fonts/Roboto-Bold.ttf new file mode 100644 index 0000000..3742457 Binary files /dev/null and b/assets/fonts/Roboto-Bold.ttf differ diff --git a/assets/fonts/Roboto-Medium.ttf b/assets/fonts/Roboto-Medium.ttf new file mode 100644 index 0000000..e89b0b7 Binary files /dev/null and b/assets/fonts/Roboto-Medium.ttf differ diff --git a/assets/fonts/Roboto-Regular.ttf b/assets/fonts/Roboto-Regular.ttf new file mode 100644 index 0000000..3d6861b Binary files /dev/null and b/assets/fonts/Roboto-Regular.ttf differ diff --git a/icons/128.png b/assets/icons/128.png similarity index 100% rename from icons/128.png rename to assets/icons/128.png diff --git a/icons/16.png b/assets/icons/16.png similarity index 100% rename from icons/16.png rename to assets/icons/16.png diff --git a/icons/32.png b/assets/icons/32.png similarity index 100% rename from icons/32.png rename to assets/icons/32.png diff --git a/icons/48.png b/assets/icons/48.png similarity index 100% rename from icons/48.png rename to assets/icons/48.png diff --git a/assets/satus/satus.css b/assets/satus/satus.css new file mode 100644 index 0000000..7ab8c36 --- /dev/null +++ b/assets/satus/satus.css @@ -0,0 +1,2028 @@ +/*-------------------------------------------------------------- +# SCROLLBAR +--------------------------------------------------------------*/ + +:where([class^='satus'])::-webkit-scrollbar { + width: 4px; +} + +:where([class^='satus'])::-webkit-scrollbar:hover { + width: 8px; +} + +:where([class^='satus'])::-webkit-scrollbar-thumb { + background: rgba(var(--satus-light), .2); +} + +:where([class^='satus'])::-webkit-scrollbar-thumb:hover { + background: rgba(var(--satus-light), .3); +} +/*-------------------------------------------------------------- +# ANIMATIONS +--------------------------------------------------------------*/ + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes fadeInLeft { + from { + opacity: 0; + transform: translateX(-100%); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes fadeInRight { + from { + opacity: 0; + transform: translateX(100%); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@keyframes fadeOutLeft { + from { + opacity: 1; + transform: translateX(0); + } + to { + opacity: 0; + transform: translateX(-50%); + } +} + +@keyframes fadeOutRight { + from { + opacity: 1; + transform: translateX(0); + } + to { + opacity: 0; + transform: translateX(50%); + } +} + +@keyframes zoomIn { + from { + transform: scale(.8); + opacity: 0; + } + to { + transform: scale(1); + opacity: 1; + } +} + +@keyframes zoomOut { + from { + transform: scale(1); + opacity: 1; + } + to { + transform: scale(.8); + opacity: 0; + } +} +/*-------------------------------------------------------------- +>>> THEMES +--------------------------------------------------------------*/ + +body { + --satus-light: 0, 20, 82; + --satus-primary: #ff4158; + + --satus-alert-background--error: #501616; + --satus-alert-border--error: 1px solid #6f1f1f; + --satus-alert-foreground--error: #d77070; + + --satus-alert-background--success: rgb(246, 180, 101, .32); + --satus-alert-border--success: 1px solid rgb(246, 180, 101, .6); + --satus-alert-foreground--success: rgb(184, 115, 30); + + --satus-base-background: #f3f4f6; + --satus-base-foreground: #565e76; + + --satus-checkbox-background: #f3f4f6; + --satus-checkbox-border: #dcdfe5; + --satus-checkbox-foreground: rgb(255, 255, 255, .96); + + --satus-divider: rgba(var(--satus-light),.1); + + --satus-header-background: #fff; + --satus-header-foreground: inherit; + --satus-header-shadow: 0 1px 0 #dcdee5; + + --satus-layers-background: var(--satus-base-background); + --satus-layers-foreground: inherit; + + --satus-section-background: #fff; + --satus-section-border: #dcdee5; + + --satus-sidebar-background: #fff; + --satus-sidebar-foreground: inherit; + --satus-sidebar-shadow: #dcdee5; + + --satus-modal-foreground: inherit; + --satus-modal-background: #fff; + --satus-modal-shadow: 0 1px 4px #7d86a1; + + --satus-tabs-background: rgba(var(--satus-light), .04); + --satus-tabs-foreground: #fff; + + --satus-text-field-background: #edf0f2; + --satus-text-field-border: #dcdee5; + --satus-text-field-color: #7d8ba1; + --satus-text-field-selection: rgb(149, 166, 178, .35); + --satus-text-field-cursor: #fa0; + + --satus-switch-track: #e1e4ea; + --satus-switch-track--checked: var(--satus-primary); + --satus-switch-thumb: #fff; + + --satus-input-text-background: #e8e8e3; + --satus-input-text-border: #d6d6cd; + --satus-input-text-text: #848471; +} + +body[satus-theme=dark] { + --satus-light: 255, 255, 255; + --satus-primary: #3691bf; + + --satus-alert-background--error: #501616; + --satus-alert-border--error: 1px solid #6f1f1f; + --satus-alert-foreground--error: #d77070; + + --satus-alert-background--success: #143648; + --satus-alert-border--success: 1px solid #1d4f67; + --satus-alert-foreground--success: #50a4ce; + + --satus-base-background: #151528; + --satus-base-foreground: #fafafa; + + --satus-header-background: #313172; + --satus-header-shadow: transparent; + + --satus-section-background: #232343; + --satus-section-border: #232343; + + --satus-modal-background: #313172; + --satus-modal-shadow: 0 1px 4px #22222f; + + --satus-switch-track: #52527a; +} +/*-------------------------------------------------------------- +>>> NORMALIZE +--------------------------------------------------------------*/ + +:where([class^='satus']) { + box-sizing: border-box; +} + +:where([class^='satus'])[hidden]:not([hidden='false']) { + display: none; +} + +:where([class^='satus'])[transparent] { + opacity: 0; +} +/*-------------------------------------------------------------- +>>> MODAL +---------------------------------------------------------------- +# Container +# Scrim +# Surface +# Variants + # Vertical menu +--------------------------------------------------------------*/ + + +/*-------------------------------------------------------------- +# CONTAINER +--------------------------------------------------------------*/ + +.satus-modal { + position: fixed; + z-index: 9; + top: 0; + left: 0; + display: flex; + width: 100vw; + height: 100vh; + justify-content: center; + align-items: center; +} + + +/*-------------------------------------------------------------- +# SCRIM +--------------------------------------------------------------*/ + +.satus-modal__scrim { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + animation: fadeIn 150ms linear forwards; + opacity: 0; + background: rgba(0, 0, 0, .16); + backdrop-filter: blur(8px); +} + +.satus-modal--closing .satus-modal__scrim { + animation: fadeOut 70ms linear forwards; +} + + +/*-------------------------------------------------------------- +# SURFACE +--------------------------------------------------------------*/ + +.satus-modal__surface { + display: flex; + overflow-y: auto; + flex-direction: column; + box-sizing: border-box; + width: 95%; + min-width: 240px; + max-width: 560px; + max-height: 80%; + margin: 8px; + padding: 12px 16px; + transform: scale(.8); + animation: zoomIn 150ms linear forwards; + animation-delay: 20ms; + opacity: 0; + color: var(--satus-modal-foreground); + border-radius: 3px; + background-color: var(--satus-modal-background); + box-shadow: var(--satus-modal-shadow); +} + +.satus-modal--closing .satus-modal__surface { + animation: zoomOut 70ms linear forwards; +} + +.satus-section--actions { + justify-content: flex-end; +} +.satus-section--actions > *:not(:first-child) { + margin-left: 8px; +} + + +/*-------------------------------------------------------------- +# VARIANTS +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# VERTICAL MENU +--------------------------------------------------------------*/ + +.satus-modal--vertical-menu .satus-modal__surface { + position: absolute; + top: 8px; + right: 8px; + left: auto; + min-width: 180px; + max-width: 180px; + margin: 0; + padding: 8px 0; + transform-origin: right top; +} + +.satus-modal--vertical-menu .satus-modal__surface>[class^='satus']:where(:not(.satus-divider)) { + height: 36px; + padding: 0 16px; + border-radius: 0; +} + +.satus-modal--vertical-menu .satus-modal__surface>.satus-span { + font-size: 13px; + font-weight: 500; + margin: 6px 0; + padding: 0 12px; + height: auto; +} + +.satus-modal--vertical-menu .satus-modal__surface>.satus-tabs { + margin: 0 12px; + border-radius: 3px; + height: 26px; + padding: 0; +} + +.satus-modal--vertical-menu .satus-select svg, +.satus-modal--vertical-menu .satus-button svg { + margin: 0 14px 0 0; + opacity: .64; + flex: 0 0 18px; +} + +.satus-modal--vertical-menu .satus-button .satus-span { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.satus-modal--vertical-menu .satus-switch:hover { + cursor: pointer; + + background-color: rgba(var(--satus-light), .06); +} + +.satus-modal--vertical-menu .satus-switch:focus { + background-color: rgba(var(--satus-light), .08); +} +/*-------------------------------------------------------------- +>>> GRID +--------------------------------------------------------------*/ + +.satus-grid { + display: flex; + align-items: stretch; + height: 100%; + padding: 8px; +} +/*-------------------------------------------------------------- +>>> TEXT FIELD +---------------------------------------------------------------- +# Parts + # Container + # Input + # +# Syntax highlighting + # Regular expression +--------------------------------------------------------------*/ + +.satus-text-field { + display: flex; + + min-width: 240px; + height: 36px; + + color: var(--satus-text-field-foreground, inherit); + border-radius: 4px; + background: var(--satus-text-field-background); + + align-items: center; + justify-content: space-between; +} + +.satus-text-field__container { + position: relative; + + overflow: hidden; + + height: 100%; + + flex: 1; +} + +.satus-text-field__textarea { + font: inherit; + + position: absolute; + z-index: 9; + top: 0; + left: 0; + + overflow: auto; + + width: 100%; + min-width: 0; + max-width: none; + height: 100%; + min-height: 0; + max-height: none; + margin: 0; + padding: 0 12px; + + white-space: pre; + + opacity: 0; + color: inherit; + border: none; + border-radius: 4px; + outline: none; + + appearance: none; + overflow-wrap: normal; +} + +.satus-text-field__display { + position: absolute; + top: 0; + left: 0; + + display: flex; + + width: 100%; + height: 100%; +} + +.satus-text-field__line-numbers { + padding: 0 12px 0 0; + + opacity: .5; +} + +.satus-text-field__line-numbers>span { + font-size: inherit; + + display: block; + + width: 100%; + + text-align: right; +} + +.satus-text-field__pre { + font: inherit; + + display: flex; + + margin: 0; +} + +.satus-text-field__hidden-value { + font: inherit; + + position: absolute; + + overflow: auto; + + white-space: pre; + pointer-events: none; + + opacity: 0; + + overflow-wrap: normal; +} + +.satus-text-field__selection { + position: absolute; + top: 0; + left: 0; + + display: none; + + width: 0; + height: 22px; + margin: 6px 12px; + + border: 1px solid var(--satus-text-field-selection); + border-radius: 3px; + background: var(--satus-text-field-selection); +} + +.satus-text-field__cursor { + position: absolute; + top: 0; + left: 0; + + display: none; + + width: 2px; + height: 22px; + margin: -3px 0 0; + + animation: blink 1s step-end 8; + + background: var(--satus-text-field-cursor); +} + +.satus-text-field__textarea:focus+.satus-text-field__display>.satus-text-field__cursor, +.satus-text-field__textarea:focus+.satus-text-field__display>.satus-text-field__selection:not([disabled]) { + display: block; +} + +@keyframes blink { + + from, + to { + opacity: 1; + } + + 50% { + opacity: 0; + } +} + + +/*-------------------------------------------------------------- +# SYNTAX HIGHLIGHTING +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# REGULAR EXPRESSION +--------------------------------------------------------------*/ + +.satus-text-field__pre>.group { + color: #47ff47; + background-color: rgb(71, 255, 71, .16); +} + +.satus-text-field__pre>.character-class { + color: #ffc247; + background-color: rgb(255, 170, 0, .16); +} + +.satus-text-field__pre>.quantifier { + color: #47c2ff; + background-color: rgb(71, 194, 255, .16); +} + +.satus-text-field__pre>.anchor { + color: #47c2ff; + background-color: rgb(71, 194, 255, .16); +} + +.satus-text-field__pre>.metasequence { + color: #47ff47; + background-color: rgb(71, 255, 71, .16); +} + +.satus-text-field__pre>.text { + color: #c4c4d4; + background-color: rgb(196, 196, 212, .16); +} +/*-------------------------------------------------------------- +>>> CHART +--------------------------------------------------------------*/ + +.satus-chart { + font-size: 90%; + + position: relative; + + height: 128px; + margin: 4px 12px; + + color: rgba(var(--satus-light), .32); + border: 1px dashed rgba(var(--satus-light), .2); + border-top: unset; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; +} + +.satus-chart__labels { + position: absolute; + top: 0; + left: 0; + + display: flex; + + width: 100%; + height: 100%; + + justify-content: space-between; + align-items: stretch; +} + +.satus-chart__section { + padding: 4px; + + flex: 1; +} + +.satus-chart__section:not(:last-child) { + border-right: 1px dashed rgba(var(--satus-light), .2); +} + + +.satus-chart__bars { + position: absolute; + top: 0; + left: 0; + + display: flex; + + width: 100%; + height: 100%; + + justify-content: space-between; + align-items: stretch; +} + +.satus-chart__bar { + display: flex; + flex-direction: column; + + margin: 0 1px; + + flex: 1; + align-items: center; + justify-content: flex-end; +} + +.satus-chart__piece { + width: 100%; +} + +.satus-chart__piece:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +/*-------------------------------------------------------------- +>>> SELECT +--------------------------------------------------------------*/ + +.satus-select { + position: relative; + + display: flex; + + cursor: pointer; + + align-items: center; + justify-content: space-between; +} + +.satus-select:hover { + background-color: var(--satus-hover); +} + +.satus-select__content { + display: flex; + + flex: 2; + overflow: hidden; + + align-items: center; +} + +.satus-select svg { + width: 20px; + height: 18px; + margin: 0 14px 0 0; + + opacity: .64; +} + +.satus-select__content .satus-span { + overflow: hidden; + + text-overflow: ellipsis; +} + +.satus-select__value { + display: block; + overflow: hidden; + + flex: 1; + margin-left: 8px; + + text-align: right; + text-overflow: ellipsis; + + opacity: .64; +} + +.satus-select select { + font: inherit; + + position: absolute; + z-index: 1; + top: 0; + left: 0; + + width: 100%; + height: 100%; + margin: 0; + padding: inherit; + + cursor: inherit; + + opacity: 0; + border: none; + outline: none; + + appearance: none; +} + +.satus-select:hover { + cursor: pointer; + + background-color: rgba(var(--satus-light), .06); +} + +.satus-select:focus { + background-color: rgba(var(--satus-light), .08); +} + +.satus-select select::-webkit-scrollbar { + width: 4px; +} + +.satus-select select::-webkit-scrollbar:hover { + width: 8px; +} + +.satus-select select::-webkit-scrollbar-thumb { + background: rgba(0, 0, 0, .2); +} + +.satus-select select::-webkit-scrollbar-thumb:hover { + background: rgba(0, 0, 0, .3); +} + +.satus-select option { + color: var(--satus-select-text); + background: var(--satus-select-background); +} +/*-------------------------------------------------------------- +>>> DIVIDER +--------------------------------------------------------------*/ + +.satus-divider { + height: 1px; + margin: 16px 0 12px; + background: var(--satus-divider); +} +/*-------------------------------------------------------------- +>>> SECTION +---------------------------------------------------------------- +# Variants + # Align start + # Align end + # Card +# Media +--------------------------------------------------------------*/ + +.satus-section { + display: flex; + + flex-wrap: wrap; +} + + +/*-------------------------------------------------------------- +# ALIGN START +--------------------------------------------------------------*/ + +.satus-section--align-start { + align-items: center; +} + +.satus-section--align-start>*:not(:last-child) { + margin-right: 8px; +} + + +/*-------------------------------------------------------------- +# ALIGN END +--------------------------------------------------------------*/ + +.satus-section--align-end { + align-items: center; + justify-content: flex-end; +} + +.satus-section--align-end>*:not(:first-child) { + margin-left: 8px; +} + + +/*-------------------------------------------------------------- +# CARD +--------------------------------------------------------------*/ + +.satus-section--card { + flex-direction: column; + + max-width: 900px; + margin: 12px; + padding: 8px 0; + + border: 1px solid var(--satus-section-border); + border-radius: 3px; + background: var(--satus-section-background); +} + +.satus-section--transparent-card { + max-width: 900px; + margin: 8px 12px; +} + +.satus-section--card[data-title], +.satus-section--transparent-card[data-title] +{ + position: relative; + + margin-top: 32px; +} + +.satus-section--card[data-title]::before, +.satus-section--transparent-card::before +{ + position: absolute; + top: -8px; + left: 0; + + content: attr(data-title); + transform: translateY(-100%); +} + + +.satus-section--transparent-card > [class^='satus'] { + width: 100%; +} + +.satus-section--card>[class^='satus']:not(.satus-list):not(.satus-section) { + display: flex; + + width: 100%; + min-height: 48px; + padding: 8px 12px; + + transition: background-color .18s cubic-bezier(.25, .8, .5, 1); + text-align: left; + + border-radius: 0; + + align-items: center; +} + +.satus-section--card>[class^='satus']:not(.satus-list):not(.satus-span):hover { + background-color: rgba(var(--satus-light), .06); +} + +.satus-section--card>.satus-button { + justify-content: flex-start; +} + +.satus-section--card>.satus-button>svg, +.satus-section--card>.satus-select>svg +{ + width: 20px; + margin: 0 14px 0 0; + + color: var(--satus-primary); +} + +.satus-section--card>.satus-span { + display: flex; + + align-items: center; +} + +.satus-section--transparent { + background: unset; + border: unset; + padding: 0; + border-radius: unset; +} + + +/*-------------------------------------------------------------- +# MEDIA +--------------------------------------------------------------*/ + +@media (min-width: 901px) { + .satus-section--card, + .satus-section--transparent-card { + margin-left: auto; + margin-right: auto; + } +} +/*-------------------------------------------------------------- +>>> BASE +--------------------------------------------------------------*/ + +.satus-base { + display: flex; + flex-direction: column; + + width: 100%; + height: 100%; + + color: var(--satus-base-foreground); + background: var(--satus-base-background); +} +/*-------------------------------------------------------------- +>>> ALERT +---------------------------------------------------------------- +# Media +--------------------------------------------------------------*/ + +.satus-alert { + display: flex; + min-height: 48px; + margin: 12px; + padding: 8px 12px; + border-radius: 3px; + align-items: center; + max-width: 900px; +} + +.satus-alert--error { + color: var(--satus-alert-foreground--error); + border: var(--satus-alert-border--error); + background: var(--satus-alert-background--error); +} + +.satus-alert--success { + color: var(--satus-alert-foreground--success); + border: var(--satus-alert-border--success); + background: var(--satus-alert-background--success); +} + + +/*-------------------------------------------------------------- +# MEDIA +--------------------------------------------------------------*/ + +@media (min-width: 901px) { + .satus-alert { + margin-left: auto; + margin-right: auto; + } +} +/*-------------------------------------------------------------- +>>> INPUT +--------------------------------------------------------------*/ + +.satus-input[type=text], +.satus-input[type=password] { + font: inherit; + box-sizing: border-box; + width: 100%; + margin: 0; + padding: 0 8px; + color: var(--satus-input-text-foreground, inherit); + border: none; + outline: none; + background: none; + appearance: none; + font-size: 16px; + margin: 8px 0; + border: 1px solid var(--satus-input-text-border); + border-radius: 4px; + background-color: var(--satus-input-text-background); +} +/*-------------------------------------------------------------- +>>> MAIN +--------------------------------------------------------------*/ + +.satus-main { + display: flex; + background: var(--satus-base-background); + flex: 1 +} +/*-------------------------------------------------------------- +>>> SIDEBAR +--------------------------------------------------------------*/ + +.satus-sidebar { + z-index: 1; + display: flex; + flex-direction: column; + width: 56px; + padding: 12px 0; + color: var(--satus-sidebar-foreground); + background: var(--satus-sidebar-background); + box-shadow: 1px 0 0 var(--satus-sidebar-shadow) +} +/*-------------------------------------------------------------- +>>> LAYERS +--------------------------------------------------------------*/ + +.satus-layers { + position: relative; + + overflow: hidden; + + flex: 1; +} + +.satus-layers__layer { + position: absolute; + top: 0; + left: 0; + + overflow: auto; + + width: 100%; + height: 100%; + + color: var(--satus-layers-foreground); + background: var(--satus-layers-background); +} +/*-------------------------------------------------------------- +>>> LIST +--------------------------------------------------------------*/ + +.satus-list { + margin: 0; + + list-style: none; +} + +.satus-list__item { + display: flex; + + min-height: 48px; + padding: 0 16px; + + align-items: center; + justify-content: space-between; +} + +.satus-list__item>*:not(:first-child) { + margin-left: 8px; +} + +.satus-list__item>*:last-child { + font-size: 92%; + + text-align: right; + + opacity: .64; +} +/*-------------------------------------------------------------- +>>> COLOR PICKER: +---------------------------------------------------------------- +# Button +# Modal +--------------------------------------------------------------*/ + + +/*-------------------------------------------------------------- +# BUTTON +--------------------------------------------------------------*/ + +.satus-color-picker { + font-size: inherit; + + position: relative; + + display: flex; + + box-sizing: border-box; + margin: 0; + + cursor: pointer; + + color: inherit; + border: none; + outline: none; + background-color: var(--satus-theme-button); + + justify-content: space-between; + -webkit-tap-highlight-color: transparent; + align-items: center; + -webkit-appearance: none; +} + +.satus-color-picker__value { + width: 22px; + height: 22px; + + border: 2px solid rgba(0, 0, 0, .16); + border-radius: 50%; +} + + +/*-------------------------------------------------------------- +# MODAL +--------------------------------------------------------------*/ + +.satus-modal--color-picker .satus-modal__surface { + padding: 8px; +} + +.satus-color-picker__palette { + position: relative; + + overflow: hidden; + + width: 100%; + height: 256px; + margin: 0 0 4px; + + border-radius: 5px; + background-color: #f00; +} + +.satus-color-picker__palette:before { + position: absolute; + top: 0; + left: 0; + + width: 100%; + height: 100%; + + content: ''; + + background-image: linear-gradient(0deg, black, transparent), linear-gradient(90deg, white, transparent); +} + +.satus-color-picker__cursor { + position: absolute; + + width: 5px; + height: 5px; + + transform: translate(-50%, -50%); + pointer-events: none; + + border: 1px solid #fff; + border-radius: 50%; + box-shadow: 0 0 0 1px #000; +} + +.satus-modal--color-picker .satus-modal__surface .satus-section--color { + margin: 8px 4px; + + align-items: center; +} + +.satus-color-picker__color { + width: 32px; + height: 32px; + margin: 0 16px 0 0; + + border: 2px solid rgba(0, 0, 0, .16); + border-radius: 50%; + background: #f00; +} + +.satus-slider.satus-color-picker__hue { + padding: 0; + + flex: 1; +} + +.satus-color-picker__hue .satus-slider__track-container { + height: 16px; + margin: 0; + + border-radius: 4px; + background-image: linear-gradient(90deg, #f00, #ff2a00, #f50, #ff7f00, #fa0, #ffd400, #ff0, #d4ff00, #af0, #80ff00, #5f0, #2bff00, #0f0, #00ff2b, #0f5, #00ff80, #0fa, #00ffd5, #0ff, #00d4ff, #0af, #007fff, #05f, #002bff, #00f, #2a00ff, #50f, #7f00ff, #a0f, #d400ff, #f0f, #ff00d4, #f0a, #ff0080, #f05, #ff002b, #f00); +} + +.satus-color-picker__hue .satus-slider__track-container::before { + display: none; +} + +.satus-color-picker__hue .satus-slider__track { + background: transparent; +} + +.satus-color-picker__hue .satus-slider__track::after { + width: 16px; + height: 16px; + + background: #fff; + box-shadow: 0 0 4px rgb(0, 0, 0, .64); +} +/*-------------------------------------------------------------- +>>> SPAN +--------------------------------------------------------------*/ + +.satus-span--title { + font-weight: 500; + overflow: hidden; + + white-space: nowrap; + text-overflow: ellipsis; + + flex: 1; +} +/*-------------------------------------------------------------- +>>> BUTTON +---------------------------------------------------------------- +# Base +# Basic +# Icon +--------------------------------------------------------------*/ + + +/*-------------------------------------------------------------- +# BASE +--------------------------------------------------------------*/ + +.satus-button { + font: inherit; + + position: relative; + + display: inline-flex; + overflow: hidden; + + height: 36px; + padding: 8px; + + transition: background-color .3s cubic-bezier(.25, .8, .5, 1); + + color: inherit; + border: none; + border-radius: 6px; + outline: none; + background: transparent; + + appearance: none; + align-items: center; +} + +.satus-button:hover { + cursor: pointer; + + background-color: rgba(var(--satus-light), .06); +} + +.satus-button:focus { + background-color: rgba(var(--satus-light), .08); +} + +.satus-button svg { + width: 100%; + max-width: 24px; + height: 100%; + max-height: 24px; +} + + +/*-------------------------------------------------------------- +# BASIC +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# ICON +--------------------------------------------------------------*/ + +.satus-button--icon { + width: 40px; + height: 40px; + + border-radius: 50%; +} + +.satus-button--icon svg { + width: 24px; + height: 24px; +} +/*-------------------------------------------------------------- +>>> HEADER +--------------------------------------------------------------*/ + +.satus-header { + z-index: 1; + + display: flex; + + height: 56px; + padding: 0 12px; + + color: var(--satus-header-foreground); + background: var(--satus-header-background); + box-shadow: var(--satus-header-shadow); + + justify-content: space-between; + align-items: center; +} +/*-------------------------------------------------------------- +>>> RADIO +--------------------------------------------------------------*/ + +.satus-radio { + position: relative; + display: flex; +} + +.satus-radio__input { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + opacity: 0; + margin: 0; + z-index: 9; +} + +.satus-radio__content { + flex: 1; + padding: 0 12px; +} + +.satus-radio__i { + width: 16px; + height: 16px; + border: 1px solid rgba(var(--satus-light),.64); + border-radius: 50%; + transition: 200ms; +} + +.satus-radio__input + .satus-radio__i::before { + width: 8px; + height: 8px; + margin: 3px; + border-radius: 50%; + background: var(--satus-primary); + content: ''; + display: block; + transform: scale(0); + transition: 200ms; +} + +.satus-radio__input:checked + .satus-radio__i { + border-color: var(--satus-primary); +} + +.satus-radio__input:checked + .satus-radio__i::before { + background: var(--satus-primary); + transform: scale(1); +} +/*-------------------------------------------------------------- +>>> SLIDER +--------------------------------------------------------------*/ + +.satus-slider { + display: flex; + + flex-wrap: wrap; +} + +.satus-slider__track-container { + position: relative; + + width: 100%; + height: 20px; + margin: 10px 0 -2px; +} + +.satus-slider__track-container::before { + position: absolute; + top: calc(50% - 1px); + left: 0; + + width: 100%; + height: 2px; + + content: ''; + + opacity: .24; + background: var(--satus-primary); +} + +.satus-slider__input { + position: absolute; + top: 0; + left: 0; + + width: 100%; + height: 100%; + margin: 0; + + opacity: 0; +} + +.satus-slider__track { + position: absolute; + top: calc(50% - 1px); + left: 0; + + width: 0; + height: 2px; + + background: var(--satus-primary); + pointer-events: none; +} + +.satus-slider__track::before { + position: absolute; + top: 50%; + right: 0; + transform: translate(50%, -50%); + display: block; + width: 16px; + height: 16px; + content: ''; + transition: width 200ms, height 200ms, opacity 200ms; + opacity: 0; + border-radius: 50%; + background: var(--satus-primary); +} + +.satus-slider__input:focus + .satus-slider__track::before { + width: 24px; + height: 24px; + opacity: .16; +} + +.satus-slider__input:active + .satus-slider__track::before { + width: 26px; + height: 26px; + opacity: .16; +} + +.satus-slider__track::after { + position: absolute; + top: 50%; + right: 0; + transform: translate(50%, -50%); + + width: 10px; + height: 10px; + + content: ''; + + border-radius: 50%; + background: var(--satus-primary); + pointer-events: none; + transition: width 200ms, height 200ms, opacity 200ms; +} + +.satus-slider__input:active + .satus-slider__track::after +{ + width: 12px; + height: 12px; +} + + + + + +.satus-slider--row { + flex-wrap: nowrap; + justify-content: space-between; +} + +.satus-slider--row .satus-slider__track-container { + margin: 0 0 -2px 12px; + max-width: 50%; +} +/*-------------------------------------------------------------- +>>> TABS +--------------------------------------------------------------*/ + +.satus-tabs { + position: relative; + + display: flex; + + border: 2px solid var(--satus-tabs-background); + border-radius: 4px; + background: var(--satus-tabs-background); +} + +.satus-tabs::before { + position: absolute; + top: 0; + left: calc(calc(100% / var(--satus-tabs-count)) * var(--satus-tabs-current)); + + width: calc(100% / var(--satus-tabs-count)); + height: 100%; + + content: ''; + transition: left .25s; + + border-radius: 3px; + background: var(--satus-tabs-foreground); +} + +.satus-tabs__button { + font: inherit; + + position: relative; + z-index: 1; + + overflow: hidden; + + margin: 0; + padding: 0 8px; + + text-overflow: ellipsis; + + color: inherit; + border: none; + border-radius: 3px; + outline: none; + background: transparent; + + flex: 1; + appearance: none; +} +/*-------------------------------------------------------------- +>>> SHORTCUT: +---------------------------------------------------------------- +# +--------------------------------------------------------------*/ + +.satus-shortcut__value { + font-size: 11px; + + display: flex; + + margin-left: 16px; + + text-transform: uppercase; + + align-items: center; + flex: 1; + justify-content: flex-end; +} + +.satus-shortcut__actions { + display: flex; + + justify-content: flex-end; +} + +.satus-shortcut__actions .satus-button { + height: 32px; + margin: 8px 4px 0; + + border-radius: 8px; + background: rgba(0, 0, 0, .15); +} + +.satus-shortcut__actions .satus-button:hover { + background: rgba(0, 0, 0, .25); +} + +.satus-shortcut__primary { + display: flex; + + height: 64px; + margin: 0 0 12px; + padding: 16px; + + border-radius: 3px; + background: rgba(0, 0, 0, .16); + + align-items: center; +} + +.satus-shortcut__key { + display: flex; + + min-width: 32px; + height: 32px; + padding: 4px 8px; + + color: #242424; + border-radius: 4px; + background: #fff; + box-shadow: 0 1px 3px rgba(0, 0, 0, .15), inset 0 -3px 0 rgba(0, 0, 0, .1); + + align-items: center; + justify-content: center; +} + +.satus-shortcut__value>.satus-shortcut__key { + font-size: 14px; + + min-width: 24px; + height: 24px; +} + +.satus-shortcut__plus { + position: relative; + + width: 12px; + height: 12px; + margin: 8px; +} + +.satus-shortcut__plus::before { + position: absolute; + top: 0; + left: 5px; + + width: 2px; + height: 12px; + + content: ''; + + background-color: #aaa; +} + +.satus-shortcut__plus::after { + position: absolute; + top: 5px; + left: 0; + + width: 12px; + height: 2px; + + content: ''; + + background-color: #aaa; +} + +.satus-shortcut__mouse { + position: relative; + + display: flex; + + width: 28px; + height: 36px; + + border-radius: 50%; + border-top-left-radius: 12px; + border-top-right-radius: 12px; + background: #fff; + box-shadow: 0 1px 3px rgba(0, 0, 0, .15), inset 0 -3px 0 rgba(0, 0, 0, .1); +} + +.satus-shortcut__value>.satus-shortcut__mouse { + width: 22px; + height: 28px; +} + +.satus-shortcut__mouse>div { + position: absolute; + top: 0; + left: calc(50% - 1px); + + width: 2px; + height: 11px; + + border-radius: 2px; + background: #ccc; +} + +.satus-shortcut__mouse::before { + position: absolute; + top: -16%; + right: 14%; + + width: 2px; + height: 60%; + + content: ''; + + background: #f96754; +} + +.satus-shortcut__mouse.false::before { + top: -6%; +} + +.satus-shortcut__mouse.false::after { + position: absolute; + top: -20%; + right: calc(14% - 4px); + + width: 0; + height: 0; + + content: ''; + + border-right: 5px solid transparent; + border-bottom: 8px solid #f96754; + border-left: 5px solid transparent; +} + +.satus-shortcut__mouse.true::after { + position: absolute; + top: 40%; + right: calc(14% - 4px); + + width: 0; + height: 0; + + content: ''; + + border-top: 8px solid #f96754; + border-right: 5px solid transparent; + border-left: 5px solid transparent; +} + +.satus-shortcut__mouse.click::before { + position: absolute; + top: 0; + left: -1px; + + width: 10px; + height: 10px; + + content: ''; + + border-radius: 50%; + background: #f96754; +} + +.satus-shortcut__mouse.middle::before { + position: absolute; + z-index: 1; + top: 0; + left: 50%; + + width: 10px; + height: 10px; + + content: ''; + transform: translateX(-50%); + + border-radius: 50%; + background: #f96754; +} + +.satus-shortcut__mouse.context::before { + position: absolute; + top: 0; + left: 15px; + + width: 10px; + height: 10px; + + content: ''; + + border-radius: 50%; + background: #f96754; +} + +.satus-section_shortcut { + width: 100%; + margin: 8px 0 0; + + justify-content: flex-end; +} + +.satus-button_shortcut { + font-weight: 500; + + overflow: hidden; + + height: 28px; + min-height: 28px; + margin-right: 2px; + padding: 4px 8px; + + text-transform: uppercase; + + color: #f96754; + border-radius: 4px; +} +/*-------------------------------------------------------------- +>>> CHECKBOX +--------------------------------------------------------------*/ + +.satus-checkbox { + position: relative; + + display: flex; + + cursor: pointer; + + align-items: center; +} + +.satus-checkbox__input { + position: absolute; + top: 0; + left: 0; + + width: 100%; + height: 100%; + margin: 0; + padding: 0; + + opacity: 0; + border: none; + + appearance: none; +} + +.satus-checkbox__checkmark { + position: relative; + + display: flex; + + width: 16px; + min-width: 16px; + height: 16px; + min-height: 16px; + margin: 0 12px 0 0; + + content: ''; + + border: 1px solid var(--satus-checkbox-border); + border-radius: 3px; + background: var(--satus-checkbox-background); +} + +.satus-checkbox[data-value=true] .satus-checkbox__checkmark { + border-color: var(--satus-primary); + background: var(--satus-primary); +} + +.satus-checkbox[data-value=true] .satus-checkbox__checkmark::before { + position: absolute; + top: 3px; + left: 2px; + + width: 8px; + height: 4px; + + content: ''; + transform: rotate(-45deg); + + border: 2px solid var(--satus-checkbox-foreground); + border-top: none; + border-right: none; +} +/*-------------------------------------------------------------- +>>> SWITCH +---------------------------------------------------------------- +# Container +# Track +# Thumb +--------------------------------------------------------------*/ + + +/*-------------------------------------------------------------- +# CONTAINER +--------------------------------------------------------------*/ + +.satus-switch { + font: inherit; + + display: flex; + + transition: background-color 75ms; + + color: inherit; + border: none; + outline: none; + background-color: transparent; + + justify-content: space-between; + align-items: center; +} + +.satus-switch:hover { + cursor: pointer; +} + +.satus-switch__content { + display: flex; + + align-items: center; +} + +.satus-switch__content>svg { + width: 20px; + height: 18px; + margin: 0 14px 0 0; + + opacity: .64; +} + + +/*-------------------------------------------------------------- +# TRACK +--------------------------------------------------------------*/ + +.satus-switch>i { + width: 32px; + height: 18px; + + transition: background-color 150ms; + + border-radius: 18px; + background-color: var(--satus-switch-track); + + flex: 0 0 32px; +} + +.satus-section--card .satus-switch>i { + margin-left: 16px; +} + +.satus-switch[data-value='true']>i { + background-color: var(--satus-switch-track--checked); +} + + +/*-------------------------------------------------------------- +# THUMB +--------------------------------------------------------------*/ + +.satus-switch>i::before { + display: block; + + width: 14px; + height: 14px; + margin: 2px; + + content: ''; + transition: transform 150ms cubic-bezier(.4, 0, .2, 1); + + border-radius: 50%; + background-color: var(--satus-switch-thumb); + + will-change: transform; +} + +.satus-switch[data-value='true']>i::before { + transform: translateX(14px); +} +/*-------------------------------------------------------------- +>>> CONTEXT MENU +--------------------------------------------------------------*/ + +.satus-modal--contextmenu .satus-modal__scrim { + visibility: visible; + + transform: none; + animation: none; + + opacity: 1; + background: none; + + backdrop-filter: none; +} + +.satus-modal--contextmenu .satus-modal__surface { + position: absolute; + + visibility: visible; + + min-width: 200px; + max-width: 200px; + margin: 0; + padding: 4px 0; + + transform: none; + animation: none; + + opacity: 1; + border-radius: 4px; + box-shadow: 0 0 0 1px rgba(var(--satus-light), .1); +} + +.satus-modal--contextmenu .satus-modal__surface>* { + display: flex; + + height: 32px; + padding: 0 16px; + + align-items: center; +} + +.satus-modal--contextmenu .satus-modal__surface .satus-button svg { + width: 20px; + height: 18px; + margin: 0 14px 0 0; + + opacity: .75; + + fill: none; + stroke: var(--satus-primary); + flex: 0 0 20px; +} + +.satus-modal--contextmenu .satus-modal__surface .satus-button .satus-span { + overflow: hidden; + + white-space: nowrap; + text-overflow: ellipsis; +} +/*-------------------------------------------------------------- +>>> SORTABLE +--------------------------------------------------------------*/ + +.satus-sortable__chosen { + color: var(--satus-sortable-text) !important; + background-color: var(--satus-sortable-background) !important; +} + +.satus-sortable__ghost { + position: fixed !important; + z-index: 999 !important; + top: 0 !important; + left: 0 !important; + + pointer-events: none !important; + + opacity: .8 !important; + box-shadow: 0 1px 3px rgb(0, 0, 0, .2), 0 4px 8px rgb(0, 0, 0, .1), inset 0 0 0 1px rgb(0, 0, 0, .16) !important; + + will-change: transform !important; +} diff --git a/assets/satus/satus.js b/assets/satus/satus.js new file mode 100644 index 0000000..cfeebd4 --- /dev/null +++ b/assets/satus/satus.js @@ -0,0 +1,3290 @@ +/*-------------------------------------------------------------- +>>> CORE +---------------------------------------------------------------- +# Global variable +# Animations duration +# Append +# Attr +# Camelize +# Snakelize +# Class +# Create element +# CSS +# Empty +# Element index +# Events +# Get property +# Is +# On +# Render +# Sort +# Storage + # Clear + # Get + # Import + # Set + # Remove + # On changed +# Localization +# Log +# Text +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# GLOBAL VARIABLE +--------------------------------------------------------------*/ + +var satus = { + components: {}, + events: { + data: {} + }, + locale: { + data: {} + }, + storage: { + data: {}, + type: 'extension' + } +}; + + +/*-------------------------------------------------------------- +# ANIMATION DURATION +--------------------------------------------------------------*/ + +satus.getAnimationDuration = function (element) { + return Number(window.getComputedStyle(element).getPropertyValue('animation-duration').replace(/[^0-9.]/g, '')) * 1000; +}; + + +/*-------------------------------------------------------------- +# APPEND +--------------------------------------------------------------*/ + +satus.append = function (child, parent) { + (parent || document.body).appendChild(child); +}; + + +/*-------------------------------------------------------------- +# ATTR +--------------------------------------------------------------*/ + +satus.attr = function (element, attributes) { + if (attributes) { + for (var name in attributes) { + var value = attributes[name]; + + if (satus.isFunction(value)) { + value = value(); + } + + if (element.namespaceURI) { + if (value === false) { + element.removeAttributeNS(null, name); + } else { + element.setAttributeNS(null, name, value); + } + } else { + if (value === false) { + element.removeAttribute(name); + } else { + element.setAttribute(name, value); + } + } + } + } +}; + + +/*-------------------------------------------------------------- +# CAMELIZE +--------------------------------------------------------------*/ + +satus.camelize = function (string) { + var result = ''; + + for (var i = 0, l = string.length; i < l; i++) { + var character = string[i]; + + if (character === '_' || character === '-') { + i++; + + result += string[i].toUpperCase(); + } else { + result += character; + } + } + + return result; +}; + + +/*-------------------------------------------------------------- +# SNAKELIZE +--------------------------------------------------------------*/ + +satus.snakelize = function (string) { + return string.replace(/([A-Z])/g, '-$1').toLowerCase(); +}; + + +/*-------------------------------------------------------------- +# CLASS +--------------------------------------------------------------*/ + +satus.class = function (element, className) { + if (className) { + element.classList.add(className); + } +}; + + +/*-------------------------------------------------------------- +# CLONE +--------------------------------------------------------------*/ + +satus.clone = function (item) { + var clone = item.cloneNode(true), + parent_css = window.getComputedStyle(item.parentNode), + css = window.getComputedStyle(item), + style = ''; + + for (var i = 0, l = css.length; i < l; i++) { + var property = css[i], + value = css.getPropertyValue(property); + + if (property === 'background-color') { + value = parent_css.getPropertyValue('background-color'); + } + + if (['box-shadow', 'left', 'top', 'bottom', 'right', 'opacity'].indexOf(property) === -1) { + style += property + ':' + value + ';'; + } + } + + + clone.setAttribute('style', style); + + return clone; +}; + + +/*-------------------------------------------------------------- +# CREATE ELEMENT +--------------------------------------------------------------*/ + +satus.createElement = function (tagName, componentName, namespaceURI) { + var camelizedTagName = this.camelize(tagName), + className = 'satus-' + (componentName || tagName), + element, + match = className.match(/__[^__]+/g); + + if (!namespaceURI) { + if (tagName === 'svg') { + namespaceURI = 'http://www.w3.org/2000/svg'; + } + } + + if (namespaceURI) { + element = document.createElementNS(namespaceURI, tagName); + } else if (this.components[camelizedTagName]) { + element = document.createElement('div'); + } else { + element = document.createElement(tagName); + } + + if (match && match.length > 1) { + className = className.slice(0, className.indexOf('__')) + match[match.length - 1]; + } + + element.componentName = componentName; + element.className = className; + + element.createChildElement = function (tagName, componentName, namespaceURI) { + var element = satus.createElement(tagName, this.componentName + '__' + (componentName || tagName), namespaceURI); + + this.appendChild(element); + + return element; + }; + + return element; +}; + + +/*-------------------------------------------------------------- +# CSS +--------------------------------------------------------------*/ + +satus.css = function (element, property) { + return window.getComputedStyle(element).getPropertyValue(property); +}; + + +/*-------------------------------------------------------------- +# CRYPT +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# DECRYPTION +--------------------------------------------------------------*/ + +satus.decrypt = async function (text, password) { + var iv = text.slice(0, 24).match(/.{2}/g).map(byte => parseInt(byte, 16)), + algorithm = { + name: 'AES-GCM', + iv: new Uint8Array(iv) + }; + + try { + var data = new TextDecoder().decode(await crypto.subtle.decrypt( + algorithm, + await crypto.subtle.importKey( + 'raw', + await crypto.subtle.digest('SHA-256', new TextEncoder().encode(password)), + algorithm, + false, ['decrypt'] + ), + new Uint8Array(atob(text.slice(24)).match(/[\s\S]/g).map(ch => ch.charCodeAt(0))) + )); + } catch (err) { + return false; + } + + return data; +}; + + +/*-------------------------------------------------------------- +# ENCRYPTION +--------------------------------------------------------------*/ + +satus.encrypt = async function (text, password) { + var iv = crypto.getRandomValues(new Uint8Array(12)), + algorithm = { + name: 'AES-GCM', + iv: iv + }; + + return Array.from(iv).map(b => ('00' + b.toString(16)).slice(-2)).join('') + btoa(Array.from(new Uint8Array(await crypto.subtle.encrypt( + algorithm, + await crypto.subtle.importKey('raw', await crypto.subtle.digest('SHA-256', new TextEncoder().encode(password)), algorithm, false, ['encrypt']), + new TextEncoder().encode(text) + ))).map(byte => String.fromCharCode(byte)).join('')); +}; + + +/*-------------------------------------------------------------- +# DATA +--------------------------------------------------------------*/ + +satus.data = function (element, data) { + if (data) { + for (var key in data) { + var value = data[key]; + + if (satus.isFunction(value)) { + value = value(); + } + + element.dataset[key] = value; + } + } +}; + + +/*-------------------------------------------------------------- +# EMPTY +--------------------------------------------------------------*/ + +satus.empty = function (element, exclude = []) { + for (var i = element.childNodes.length - 1; i > -1; i--) { + var child = element.childNodes[i]; + + if (exclude.indexOf(child) === -1) { + child.remove(); + } + } +}; + + +/*-------------------------------------------------------------- +# ELEMENT INDEX +--------------------------------------------------------------*/ + +satus.elementIndex = function (element) { + return Array.prototype.slice.call(element.parentNode.children).indexOf(element); +}; + + +/*-------------------------------------------------------------- +# EVENTS +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# ON +--------------------------------------------------------------*/ + +satus.events.on = function (type, handler) { + if (!this.data[type]) { + this.data[type] = []; + } + + this.data[type].push(handler); +}; + + +/*-------------------------------------------------------------- +# TRIGGER +--------------------------------------------------------------*/ + +satus.events.trigger = function (type, data) { + var handlers = this.data[type]; + + if (handlers) { + for (var i = 0, l = handlers.length; i < l; i++) { + handlers[i](data); + } + } +}; + + +/*-------------------------------------------------------------- +# FETCH +--------------------------------------------------------------*/ + +satus.fetch = function (url, success, error, type) { + fetch(url).then(function (response) { + if (response.ok) { + response[type || 'json']().then(success); + } else { + error(); + } + }).catch(function () { + error(success); + }); +}; + + +/*-------------------------------------------------------------- +# GET PROPERTY +--------------------------------------------------------------*/ + +satus.getProperty = function (object, string) { + var properties = string.split('.'); + + for (var i = 0, l = properties.length; i < l; i++) { + var property = properties[i]; + + console.log(object); + + if (object = object[property]) { + if (i === l - 1) { + return object; + } + } else { + return false; + } + } +}; + + +/*-------------------------------------------------------------- +# INDEX OF +--------------------------------------------------------------*/ + +satus.indexOf = function (child, parent) { + var index = 0; + + if (satus.isArray(parent)) { + index = parent.indexOf(child); + } else { + while ((child = child.previousElementSibling)) { + index++; + } + } + + return index; +}; + + +/*-------------------------------------------------------------- +# TO INDEX +--------------------------------------------------------------*/ + +satus.toIndex = function (index, child, parent) { + if (satus.isArray(parent)) { + parent.splice(index, 0, parent.splice(satus.indexOf(child, parent), 1)[0]) + } +}; + + +/*-------------------------------------------------------------- +# ISSET +--------------------------------------------------------------*/ + +satus.isset = function (target, is_object) { + if (is_object === true) { + var keys = target.split('.').filter(function (value) { + return value != ''; + }); + + for (var i = 0, l = keys.length; i < l; i++) { + if (satus.isset(target[keys[i]])) { + target = target[keys[i]]; + } else { + return undefined; + } + } + + return target; + } else { + if (target === null || target === undefined) { + return false; + } + } + + return true; +}; + + +/*-------------------------------------------------------------- +# IS +--------------------------------------------------------------*/ + +satus.isArray = function (target) { + if (Array.isArray(target)) { + return true; + } else { + return false; + } +}; + +satus.isBoolean = function (target) { + return target === false || target === true; +}; + +satus.isElement = function (target) { + return target instanceof Element || target instanceof HTMLDocument; +}; + +satus.isFunction = function (target) { + return typeof target === 'function'; +}; + +satus.isNodeList = function (target) { + return target instanceof NodeList; +}; + +satus.isNumber = function (target) { + if (typeof target === 'number' && isNaN(target) === false) { + return true; + } else { + return false; + } +}; + +satus.isObject = function (target) { + return target instanceof Object && target !== null; +}; + +satus.isString = function (target) { + if (typeof target === 'string') { + return true; + } else { + return false; + } +}; + + +/*-------------------------------------------------------------- +# ON +--------------------------------------------------------------*/ + +satus.on = function (element, listeners) { + if (listeners) { + for (var type in listeners) { + var listener = listeners[type]; + + if (type === 'selectionchange') { + element = document; + } + + if (satus.isFunction(listener)) { + element.addEventListener(type, listener); + } else if (satus.isArray(listener) || satus.isObject(listener)) { + element.addEventListener(type, function (event) { + var target = this.skeleton.on[event.type], + parent = this.parentNode; + + target.parentSkeleton = this.skeleton; + target.parentElement = this; + + while (parent.componentName !== 'layers' && parent.componentName !== 'base' && parent !== document.body && parent.parentNode) { + parent = parent.parentNode; + } + + if (parent.componentName === 'layers' && target.component !== 'modal') { + parent.open(target); + } else if (this.baseProvider && this.baseProvider.layers.length === 1 && target.component !== 'modal') { + satus.render(target, this.baseProvider.layers[0]); + } else { + satus.render(target, this.baseProvider); + } + }); + } else if (satus.isString(listener)) { + element.addEventListener(type, function () { + var match = this.skeleton.on[event.type].match(/(["'`].+["'`]|[^.()]+)/g), + target = this.baseProvider; + + for (var i = 0, l = match.length; i < l; i++) { + var key = match[i]; + + if (target.skeleton[key]) { + target = target.skeleton[key]; + } else { + if (typeof target[key] === 'function') { + target[key](); + } else { + target = target[key]; + } + } + + if (target.rendered) { + target = target.rendered; + } + } + }); + } + } + } +}; + + +/*-------------------------------------------------------------- +# PARENTIFY +--------------------------------------------------------------*/ + +satus.parentify = function (parentObject, exclude) { + for (var key in parentObject) { + if (exclude.indexOf(key) === -1) { + var child = parentObject[key]; + + child.parentObject = parentObject; + + if (typeof child === 'object' && child.component !== 'shortcut') { + this.parentify(child, exclude); + } + } + } +}; + + +/*-------------------------------------------------------------- +# PREPEND +--------------------------------------------------------------*/ + +satus.prepend = function (child, parent) { + if (this.isElement(child)) { + parent.prepend(child); + } else if (this.isObject(child)) { + this.render(child, parent, undefined, undefined, true); + } +}; + + +/*-------------------------------------------------------------- +# PROPERTIES +--------------------------------------------------------------*/ + +satus.properties = function (element, properties) { + if (properties) { + for (var key in properties) { + var property = properties[key]; + + if (['placeholder', 'title'].indexOf(key) !== -1) { + property = satus.locale.get(property); + } + + element[key] = property; + } + } +}; + + +/*-------------------------------------------------------------- +# REMOVE +--------------------------------------------------------------*/ + +satus.remove = function (child, parent) { + if (satus.isArray(parent)) { + parent.splice(satus.indexOf(child, parent), 1); + } +}; + + +/*-------------------------------------------------------------- +# RENDER +--------------------------------------------------------------*/ + +satus.render = function (skeleton, container, property, childrenOnly, prepend) { + var element; + + if (skeleton.component && childrenOnly !== true) { + var tagName = skeleton.component, + camelizedTagName = this.camelize(tagName), + namespaceURI = skeleton.namespaceURI; + + if (!namespaceURI) { + if (tagName === 'svg') { + namespaceURI = 'http://www.w3.org/2000/svg'; + } else if (skeleton.parentSkeleton && skeleton.parentSkeleton.namespaceURI) { + namespaceURI = skeleton.parentSkeleton.namespaceURI; + } + + skeleton.namespaceURI = namespaceURI; + } + + element = this.createElement(tagName, tagName, namespaceURI); + + skeleton.rendered = element; + element.skeleton = skeleton; + element.childrenContainer = element; + element.componentName = tagName; + + if (skeleton.variant) { + var variant = skeleton.variant; + + if (this.isFunction(variant)) { + variant = variant(); + } + + if (satus.isArray(variant)) { + for (var i = 0, l = variant.length; i < l; i++) { + element.className += ' satus-' + tagName + '--' + variant[i]; + } + } else { + element.className += ' satus-' + tagName + '--' + variant; + } + } + + if (skeleton.id) { + element.id = skeleton.id; + } + + if (container) { + element.baseProvider = container.baseProvider; + } + + this.attr(element, skeleton.attr); + this.style(element, skeleton.style); + this.data(element, skeleton.data); + this.class(element, skeleton.class); + this.properties(element, skeleton.properties); + this.on(element, skeleton.on); + + element.storage = (function () { + var parent = element, + key = skeleton.storage || property || false, + value; + + if (satus.isFunction(key)) { + key = key(); + } + + if (skeleton.storage !== false) { + if (key) { + value = satus.storage.get(key); + } + + if (skeleton.hasOwnProperty('value') && value === undefined) { + value = skeleton.value; + } + } + + return Object.defineProperties({}, { + key: { + get: function () { + return key; + }, + set: function (string) { + key = string; + } + }, + value: { + get: function () { + return value; + }, + set: function (val) { + value = val; + + if (skeleton.storage !== false) { + satus.storage.set(key, val); + } + + parent.dispatchEvent(new CustomEvent('change')); + } + } + }); + }()); + + if (this.components[camelizedTagName]) { + this.components[camelizedTagName](element, skeleton); + } + + this.text(element.childrenContainer, skeleton.text); + this.prepend(skeleton.before, element.childrenContainer); + + if (prepend) { + this.prepend(element, container); + } else { + this.append(element, container); + } + + if (skeleton.hasOwnProperty('parentSkeleton') === false && container) { + skeleton.parentSkeleton = container.skeleton; + } + + satus.events.trigger('render', element); + + element.dispatchEvent(new CustomEvent('render')); + + container = element.childrenContainer || element; + } + + if (!element || element.renderChildren !== false) { + for (var key in skeleton) { + var item = skeleton[key]; + + if (key !== 'parentSkeleton' && key !== 'parentElement' && key !== 'parentObject' && key !== 'before') { + if (item && item.component) { + item.parentSkeleton = skeleton; + + if (element) { + item.parentElement = element; + } + + this.render(item, container, key, undefined, prepend); + } + } + } + } + + return element; +}; + + +/*-------------------------------------------------------------- +# SORT +--------------------------------------------------------------*/ + +satus.sort = function (array, order, property) { + var type; + + if (property) { + type = typeof array[0][property]; + } else { + type = typeof array[0]; + } + + if (order !== 'desc') { + if (type === 'number') { + if (property) { + return array.sort(function (a, b) { + return a[property] - b[property]; + }); + } else { + return array.sort(function (a, b) { + return a - b; + }); + } + } else if (type === 'string') { + if (property) { + return array.sort(function (a, b) { + return a[property].localeCompare(b[property]); + }); + } else { + return array.sort(function (a, b) { + return a.localeCompare(b); + }); + } + } + } else { + if (type === 'number') { + if (property) { + return array.sort(function (a, b) { + return b[property] - a[property]; + }); + } else { + return array.sort(function (a, b) { + return b - a; + }); + } + } else if (type === 'string') { + if (property) { + return array.sort(function (a, b) { + return b[property].localeCompare(a[property]); + }); + } else { + return array.sort(function (a, b) { + return b.localeCompare(a); + }); + } + } + } +}; + + +/*-------------------------------------------------------------- +# STORAGE +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# CLEAR +--------------------------------------------------------------*/ + +satus.storage.clear = function (callback) { + this.data = {}; + + chrome.storage.local.clear(function () { + satus.events.trigger('storage-clear'); + + if (callback) { + callback(); + } + }); +}; + + +/*-------------------------------------------------------------- +# GET +--------------------------------------------------------------*/ + +satus.storage.get = function (key, callback) { + var target = this.data; + + if (typeof key !== 'string') { + return; + } + + key = key.split('/').filter(function (value) { + return value != ''; + }); + + for (var i = 0, l = key.length; i < l; i++) { + if (satus.isset(target[key[i]])) { + target = target[key[i]]; + } else { + return undefined; + } + } + + if (typeof target === 'function') { + return target(); + } else { + return target; + } +}; + + +/*-------------------------------------------------------------- +# IMPORT +--------------------------------------------------------------*/ + +satus.storage.import = function (keys, callback) { + var self = this; + + if (typeof keys === 'function') { + callback = keys; + + keys = undefined; + } + + chrome.storage.local.get(keys, function (items) { + for (var key in items) { + self.data[key] = items[key]; + } + + satus.log('STORAGE: data was successfully imported'); + + satus.events.trigger('storage-import'); + + if (callback) { + callback(items); + } + }); +}; + + +/*-------------------------------------------------------------- +# REMOVE +--------------------------------------------------------------*/ + +satus.storage.remove = function (key, callback) { + var target = this.data; + + if (typeof key !== 'string') { + return; + } + + key = key.split('/').filter(function (value) { + return value != ''; + }); + + for (var i = 0, l = key.length; i < l; i++) { + if (satus.isset(target[key[i]])) { + if (i === l - 1) { + delete target[key[i]]; + } else { + target = target[key[i]]; + } + } else { + return undefined; + } + } + + chrome.storage.local.set(this.data, function () { + satus.events.trigger('storage-remove'); + + if (callback) { + callback(); + } + }); +}; + + +/*-------------------------------------------------------------- +# SET +--------------------------------------------------------------*/ + +satus.storage.set = function (key, value, callback) { + var items = {}, + target = this.data; + + if (typeof key !== 'string') { + return; + } + + key = key.split('/').filter(function (value) { + return value != ''; + }); + + for (var i = 0, l = key.length; i < l; i++) { + var item = key[i]; + + if (i < l - 1) { + + if (target[item]) { + target = target[item]; + } else { + target[item] = {}; + + target = target[item]; + } + } else { + target[item] = value; + } + } + + for (var key in this.data) { + if (typeof this.data[key] !== 'function') { + items[key] = this.data[key]; + } + } + + chrome.storage.local.set(items, function () { + satus.events.trigger('storage-set'); + + if (callback) { + callback(); + } + }); +}; + + +/*-------------------------------------------------------------- +# ON CHANGED +--------------------------------------------------------------*/ + +satus.storage.onchanged = function (callback) { + chrome.storage.onChanged.addListener(function (changes) { + for (var key in changes) { + callback(key, changes[key].newValue); + } + }); +}; + + +/*-------------------------------------------------------------- +# LAST +--------------------------------------------------------------*/ + +satus.last = function (variable) { + if (this.isArray(variable) || this.isNodeList(variable) || variable instanceof HTMLCollection) { + return variable[variable.length - 1]; + } +}; + + +/*-------------------------------------------------------------- +# LOCALIZATION +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# GET +--------------------------------------------------------------*/ + +satus.locale.get = function (string) { + return this.data[string] || string; +}; + + +/*-------------------------------------------------------------- +# IMPORT +---------------------------------------------------------------- +satus.locale.import(url, onload, onsuccess); +--------------------------------------------------------------*/ + +satus.locale.import = function (code, callback, path) { + var language = code || window.navigator.language; + + if (language.indexOf('en') === 0) { + language = 'en'; + } + + if (!path) { + path = '_locales/'; + } + + satus.fetch(chrome.runtime.getURL(path + language + '/messages.json'), function (response) { + for (var key in response) { + satus.locale.data[key] = response[key].message; + } + + satus.log('LOCALE: data was successfully imported'); + + if (callback) { + callback(); + } + }, function (success) { + satus.fetch(chrome.runtime.getURL(path + 'en/messages.json'), success, function () { + success(); + }); + }); +}; + + +/*-------------------------------------------------------------- +# LOG +--------------------------------------------------------------*/ + +satus.log = function () { + console.log.apply(null, arguments); +}; + + +/*-------------------------------------------------------------- +# STYLE +--------------------------------------------------------------*/ + +satus.style = function (element, object) { + if (object) { + for (var key in object) { + element.style[key] = object[key]; + } + } +}; + + +/*-------------------------------------------------------------- +# TEXT +--------------------------------------------------------------*/ + +satus.text = function (element, value) { + if (value) { + if (satus.isFunction(value)) { + value = value(); + } + + element.appendChild(document.createTextNode(this.locale.get(value))); + } +}; +/*-------------------------------------------------------------- +>>> MODAL +---------------------------------------------------------------- +# Confirm +--------------------------------------------------------------*/ + +satus.components.modal = function (component, skeleton) { + component.scrim = component.createChildElement('div', 'scrim'); + component.surface = component.createChildElement('div', 'surface'); + + component.close = function () { + var component = this; + + this.classList.add('satus-modal--closing'); + + setTimeout(function () { + component.remove(); + + component.dispatchEvent(new CustomEvent('close')); + }, Number(satus.css(this.surface, 'animation-duration').replace(/[^0-9.]/g, '')) * 1000); + }; + + component.scrim.addEventListener('click', function () { + this.parentNode.close(); + }); + + if (satus.isset(skeleton.content)) { + component.surface.content = component.surface.createChildElement('p', 'content'); + + if (satus.isObject(skeleton.content)) { + satus.render(skeleton.content, component.surface.content); + } else { + component.surface.content.textContent = satus.locale.get(skeleton.content); + } + } else { + component.childrenContainer = component.surface; + } + + if (satus.components.modal[skeleton.variant]) { + satus.components.modal[skeleton.variant](component, skeleton); + } +}; + + +/*-------------------------------------------------------------- +# CONFIRM +--------------------------------------------------------------*/ + +satus.components.modal.confirm = function (component, skeleton) { + component.surface.actions = satus.render({ + component: 'section', + variant: 'align-end' + }, component.surface); + + if (skeleton.buttons) { + for (var key in skeleton.buttons) { + var button = satus.render(skeleton.buttons[key], component.surface.actions); + + button.modalProvider = component; + } + } else { + satus.render({ + cancel: { + component: 'button', + text: 'cancel', + properties: { + modalProvider: component, + }, + on: { + click: function () { + this.modalProvider.dispatchEvent(new CustomEvent('cancel')); + this.modalProvider.close(); + } + } + }, + ok: { + component: 'button', + text: 'ok', + properties: { + modalProvider: component, + }, + on: { + click: function () { + this.modalProvider.dispatchEvent(new CustomEvent('confirm')); + this.modalProvider.close(); + } + } + } + }, component.surface.actions); + } +}; +/*-------------------------------------------------------------- +>>> GRID +--------------------------------------------------------------*/ + +satus.components.grid = function (component, skeleton) { + console.log(component, skeleton); +}; +/*-------------------------------------------------------------- +>>> TEXT FIELD +--------------------------------------------------------------*/ + +satus.components.textField = function (component, skeleton) { + var container = component.createChildElement('div', 'container'), + input = container.createChildElement('textarea'), + display = container.createChildElement('div', 'display'), + line_numbers = display.createChildElement('div', 'line-numbers'), + pre = display.createChildElement('pre'), + selection = display.createChildElement('div', 'selection'), + cursor = display.createChildElement('div', 'cursor'), + hiddenValue = container.createChildElement('pre', 'hidden-value'); + + component.placeholder = skeleton.placeholder; + component.input = input; + component.display = display; + component.line_numbers = line_numbers; + component.pre = pre; + component.hiddenValue = hiddenValue; + component.selection = selection; + component.cursor = cursor; + component.syntax = { + current: 'text', + handlers: { + regex: function (value, target) { + var regex_token = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g, + char_class_token = /[^\\-]+|-|\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)/g, + char_class_parts = /^(\[\^?)(]?(?:[^\\\]]+|\\[\S\s]?)*)(]?)$/, + quantifier = /^(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??$/, + matches = value.match(regex_token); + + function create(type, string) { + var span = document.createElement('span'); + + span.className = type; + span.textContent = string; + + target.appendChild(span); + } + + for (var i = 0, l = matches.length; i < l; i++) { + var match = matches[i]; + + if (match[0] === '[') { + create('character-class', match); + } else if (match[0] === '(') { + create('group', match); + } else if (match[0] === ')') { + create('group', match); + } else if (match[0] === '\\' || match === '^') { + create('anchor', match); + } else if (quantifier.test(match)) { + create('quantifier', match); + } else if (match === '|' || match === '.') { + create('metasequence', match); + } else { + create('text', match); + } + } + } + }, + set: function (syntax) { + if (this.handlers[syntax]) { + this.current = syntax; + } else { + this.current = 'text'; + } + + pre.update(); + } + }; + component.focus = function () { + this.input.focus(); + }; + + if (satus.isset(skeleton.cols)) { + input.cols = skeleton.cols; + } + + if (satus.isset(skeleton.rows)) { + input.rows = skeleton.rows; + } + + Object.defineProperty(component, 'value', { + get: function () { + return this.input.value; + }, + set: function (value) { + this.input.value = value; + } + }); + + if (skeleton.syntax) { + component.syntax.set(skeleton.syntax); + } + + selection.setAttribute('disabled', ''); + + line_numbers.update = function () { + var component = this.parentNode.parentNode.parentNode, + count = component.input.value.split('\n').length; + + if (count !== this.children.length) { + satus.empty(this); + + for (var i = 1; i <= count; i++) { + var span = document.createElement('span'); + + span.textContent = i; + + this.appendChild(span); + } + } + + component.input.style.paddingLeft = this.offsetWidth + 'px'; + }; + + pre.update = function () { + var component = this.parentNode.parentNode.parentNode, + handler = component.syntax.handlers[component.syntax.current], + value = component.value || ''; + + for (var i = this.childNodes.length - 1; i > -1; i--) { + this.childNodes[i].remove(); + } + + if (handler) { + handler(value, this); + } else { + this.textContent = value; + } + + if (value.length === 0) { + var placeholder = component.placeholder; + + if (typeof placeholder === 'function') { + placeholder = component.placeholder(); + } else { + placeholder = satus.locale.get(placeholder); + } + + this.textContent = placeholder; + } + }; + + cursor.update = function () { + var component = this.parentNode.parentNode.parentNode, + input = component.input, + value = input.value, + rows_count = value.split('\n').length, + start = input.selectionStart, + end = input.selectionEnd, + rows = value.slice(0, start).split('\n'), + top = 0; + + this.style.animation = 'none'; + + if (input.selectionDirection === 'forward') { + component.hiddenValue.textContent = value.substring(0, end); + } else { + component.hiddenValue.textContent = value.substring(0, start); + } + + top = component.hiddenValue.offsetHeight; + + component.hiddenValue.textContent = satus.last(rows); + + top -= component.hiddenValue.offsetHeight; + + this.style.top = top + 'px'; + this.style.left = component.hiddenValue.offsetWidth + component.line_numbers.offsetWidth + 'px'; + + if (start === end) { + component.selection.setAttribute('disabled', ''); + } else { + component.selection.removeAttribute('disabled'); + + /*component.hiddenValue.textContent = value.substring(0, start); + + component.selection.style.left = component.hiddenValue.offsetWidth - input.scrollLeft + 'px'; + + component.hiddenValue.textContent = value.substring(start, end); + + component.selection.style.width = component.hiddenValue.offsetWidth + 'px';*/ + } + + this.style.animation = ''; + + component.hiddenValue.textContent = ''; + }; + + document.addEventListener('selectionchange', function (event) { + component.line_numbers.update(); + component.pre.update(); + component.cursor.update(); + }); + + input.addEventListener('input', function () { + var component = this.parentNode.parentNode; + + component.storage.value = this.value; + + component.line_numbers.update(); + component.pre.update(); + component.cursor.update(); + }); + + input.addEventListener('scroll', function (event) { + var component = this.parentNode.parentNode; + + component.display.style.top = -this.scrollTop + 'px'; + component.display.style.left = -this.scrollLeft + 'px'; + + component.line_numbers.update(); + component.pre.update(); + component.cursor.update(); + }); + + component.addEventListener('change', function () { + this.line_numbers.update(); + this.pre.update(); + this.cursor.update(); + }); + + component.value = component.storage.value || ''; + + component.addEventListener('render', function () { + component.line_numbers.update(); + component.pre.update(); + component.cursor.update(); + }); + + if (skeleton.on) { + for (var type in skeleton.on) { + input.addEventListener(type, function (event) { + this.parentNode.parentNode.dispatchEvent(new Event(event.type)); + }); + } + } +}; +/*-------------------------------------------------------------- +>>> CHART +---------------------------------------------------------------- +# Core + # Bar +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# CORE +--------------------------------------------------------------*/ + +satus.components.chart = function (component, skeleton) { + var type = skeleton.type; + + if (this.chart[type]) { + component.classList.add('satus-chart--' + type); + + this.chart[type](component, skeleton); + } +}; + + +/*-------------------------------------------------------------- +# BAR +--------------------------------------------------------------*/ + +satus.components.chart.bar = function (component, skeleton) { + var labels = skeleton.labels, + datasets = skeleton.datasets, + bars = []; + + if (satus.isFunction(labels)) { + labels = labels(); + } + + if (satus.isFunction(datasets)) { + datasets = datasets(); + } + + if (satus.isArray(labels)) { + var container = component.createChildElement('div', 'labels'); + + for (var i = 0, l = labels.length; i < l; i++) { + var label = labels[i], + section = container.createChildElement('div', 'section'); + + section.textContent = label; + } + } + + if (satus.isArray(datasets)) { + var container = component.createChildElement('div', 'bars'); + + for (var i = 0, l = datasets.length; i < l; i++) { + var dataset = datasets[i]; + + for (var j = 0, k = dataset.data.length; j < k; j++) { + if (!satus.isElement(bars[j])) { + bars.push(container.createChildElement('div', 'bar')); + } + + var piece = bars[j].createChildElement('div', 'piece'); + + piece.title = dataset.label; + piece.style.height = dataset.data[j] + '%'; + piece.style.backgroundColor = 'rgb(' + dataset.color.join(',') + ')'; + } + } + } +}; +/*-------------------------------------------------------------- +>>> SELECT +--------------------------------------------------------------*/ + +satus.components.select = function (component, skeleton) { + var content = component.createChildElement('div', 'content'); + + component.childrenContainer = content; + component.valueElement = document.createElement('span'); + component.selectElement = document.createElement('select'); + + component.valueElement.className = 'satus-select__value'; + + component.appendChild(component.valueElement); + component.appendChild(component.selectElement); + + component.options = skeleton.options || []; + + if (satus.isFunction(component.options)) { + component.options = component.options(); + } + + for (var i = 0, l = component.options.length; i < l; i++) { + var option = document.createElement('option'); + + option.value = component.options[i].value; + + satus.text(option, component.options[i].text); + + component.selectElement.appendChild(option); + } + + Object.defineProperty(component, 'value', { + get() { + return this.selectElement.value; + }, + set(value) { + this.selectElement.value = value; + } + }); + + component.render = function () { + satus.empty(this.valueElement); + + if (this.selectElement.options[this.selectElement.selectedIndex]) { + satus.text(this.valueElement, this.selectElement.options[this.selectElement.selectedIndex].text); + } + + this.dataset.value = this.value; + }; + + component.selectElement.addEventListener('change', function () { + var component = this.parentNode; + + component.storage.value = this.value; + + component.render(); + }); + + component.value = component.storage.value || component.options[0].value; + + component.render(); +}; +/*-------------------------------------------------------------- +>>> DIVIDER +--------------------------------------------------------------*/ + +satus.components.divider = function () {}; +/*-------------------------------------------------------------- +>>> SECTION +--------------------------------------------------------------*/ + +satus.components.section = function (component, skeleton) { + if (satus.isString(skeleton.title)) { + component.dataset.title = satus.locale.get(skeleton.title); + } +}; +/*-------------------------------------------------------------- +>>> BASE +--------------------------------------------------------------*/ + +satus.components.base = function (component) { + component.baseProvider = component; + component.layers = []; +}; +/*-------------------------------------------------------------- +>>> ALERT +--------------------------------------------------------------*/ + +satus.components.alert = function (component, skeleton) {}; +/*-------------------------------------------------------------- +>>> TIME +--------------------------------------------------------------*/ + +satus.components.time = function (component, skeleton) { + var select_skeleton = Object.assign({}, skeleton); + + select_skeleton.component = 'select'; + select_skeleton.options = []; + + if (satus.isFunction(select_skeleton.hour12)) { + select_skeleton.hour12 = select_skeleton.hour12(); + } + + for (var i = 0, l = 24; i < l; i++) { + var hour = i, + value = i; + + if (select_skeleton.hour12 === true && i > 12) { + hour -= 12; + } + + if (hour < 10) { + hour = '0' + hour; + value = '0' + value; + } + + if (select_skeleton.hour12 === true) { + if (i > 12) { + hour += ':00 pm'; + } else { + hour += ':00 am'; + } + } else { + hour += ':00' + } + + select_skeleton.options.push({ + text: hour, + value: value + ':00' + }); + } + + satus.components.select(component, select_skeleton); + + component.classList.add('satus-select'); +}; +/*-------------------------------------------------------------- +>>> SIDEBAR +--------------------------------------------------------------*/ + +satus.components.sidebar = function (component, skeleton) {}; +/*-------------------------------------------------------------- +>>> LAYERS +--------------------------------------------------------------*/ + +satus.components.layers = function (component, skeleton) { + component.path = []; + component.renderChildren = false; + component.baseProvider.layers.push(component); + + component.back = function () { + if (this.path.length > 1) { + this.path.pop(); + + this.open(this.path[this.path.length - 1], false); + } + }; + + component.open = function (skeleton, history) { + var previous_layer = satus.last(this.querySelectorAll('.satus-layers__layer')), + layer = this.createChildElement('div', 'layer'); + + if (history !== false) { + if (previous_layer) { + previous_layer.style.animation = 'fadeOutLeft 100ms linear forwards'; + layer.style.animation = 'fadeInRight 100ms linear forwards'; + } + + this.path.push(skeleton); + } else { + previous_layer.style.animation = 'fadeOutRight 100ms linear forwards'; + layer.style.animation = 'fadeInLeft 100ms linear forwards'; + } + + if (previous_layer) { + setTimeout(function () { + previous_layer.remove(); + }, satus.getAnimationDuration(previous_layer)); + } + + layer.skeleton = skeleton; + layer.baseProvider = this.baseProvider; + + satus.render(skeleton, layer, undefined, skeleton.component === 'layers'); + + this.dispatchEvent(new Event('open')); + }; + + component.update = function () { + var layer = this.querySelector('.satus-layers__layer'); + + satus.empty(layer); + satus.render(layer.skeleton, layer); + }; + + component.open(skeleton); +}; +/*-------------------------------------------------------------- +>>> LIST +--------------------------------------------------------------*/ + +satus.components.list = function (component, skeleton) { + for (var i = 0, l = skeleton.items.length; i < l; i++) { + var li = component.createChildElement('div', 'item'), + item = skeleton.items[i]; + + for (var j = 0, k = item.length; j < k; j++) { + var child = item[j]; + + if (satus.isObject(child)) { + satus.render(child, li); + } else { + var span = li.createChildElement('span'); + + span.textContent = satus.locale.get(child); + } + } + } +}; +/*-------------------------------------------------------------- +>>> COLOR PICKER +--------------------------------------------------------------*/ + +satus.components.colorPicker = function (component, skeleton) { + var component_content = component.createChildElement('div', 'content'), + component_value = component.createChildElement('span', 'value'); + + component.childrenContainer = component_content; + component.valueElement = component_value; + + component.className = 'satus-button'; + + component.addEventListener('click', function () { + var rgb = this.rgb, + hsl = satus.color.rgbToHsl(rgb), + s = hsl[1] / 100, + l = hsl[2] / 100; + + s *= l < .5 ? l : 1 - l; + + var v = l + s; + + s = 2 * s / (l + s); + + satus.render({ + component: 'modal', + variant: 'color-picker', + value: hsl, + parentElement: this, + + palette: { + component: 'div', + class: 'satus-color-picker__palette', + style: { + 'backgroundColor': 'hsl(' + hsl[0] + 'deg, 100%, 50%)' + }, + on: { + mousedown: function () { + var palette = this, + rect = this.getBoundingClientRect(), + cursor = this.children[0]; + + function mousemove(event) { + var hsl = palette.skeleton.parentSkeleton.storage.value, + x = event.clientX - rect.left, + y = event.clientY - rect.top, + s; + + x = Math.min(Math.max(x, 0), rect.width) / (rect.width / 100); + y = Math.min(Math.max(y, 0), rect.height) / (rect.height / 100); + + var v = 100 - y, + l = (2 - x / 100) * v / 2; + + hsl[1] = x * v / (l < 50 ? l * 2 : 200 - l * 2); + hsl[2] = l; + + cursor.style.left = x + '%'; + cursor.style.top = y + '%'; + + palette.nextSibling.children[0].style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; + + event.preventDefault(); + } + + function mouseup() { + window.removeEventListener('mousemove', mousemove); + window.removeEventListener('mouseup', mouseup); + } + + window.addEventListener('mousemove', mousemove); + window.addEventListener('mouseup', mouseup); + } + }, + + cursor: { + component: 'div', + class: 'satus-color-picker__cursor', + style: { + 'left': s * 100 + '%', + 'top': 100 - v * 100 + '%' + } + } + }, + section: { + component: 'section', + variant: 'color', + + color: { + component: 'div', + class: 'satus-color-picker__color', + style: { + 'backgroundColor': 'rgb(' + this.rgb.join(',') + ')' + } + }, + hue: { + component: 'slider', + class: 'satus-color-picker__hue', + storage: false, + value: hsl[0], + max: 360, + on: { + change: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + hsl = modal.storage.value; + + hsl[0] = this.values[0]; + + this.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; + this.parentSkeletonNode.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg, 100%, 50%)'; + } + } + } + }, + actions: { + component: 'section', + variant: 'actions', + + reset: { + component: 'button', + text: 'reset', + on: { + click: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + component = modal.parentSkeleton; + + component.rgb = component.skeleton.value; + + component.storage.value = component.rgb; + + component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; + + modal.rendered.close(); + } + } + }, + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + this.skeleton.parentSkeleton.parentSkeleton.rendered.close(); + } + } + }, + ok: { + component: 'button', + text: 'OK', + on: { + click: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + component = modal.parentSkeleton; + + component.rgb = satus.color.hslToRgb(modal.storage.value); + + component.storage.value = component.rgb; + + component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; + + modal.rendered.close(); + } + } + } + } + }, this.baseProvider.layers[0]); + }); + + component.addEventListener('render', function () { + component.rgb = this.storage.value || [0, 100, 50]; + + component_value.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; + }); +}; + +satus.components.colorPicker = function (component, skeleton) { + component.childrenContainer = component.createChildElement('div', 'content'); + + component.color = (function (element) { + var array; + + Object.defineProperty(element, 'value', { + get: function () { + return array; + }, + set: function (value) { + array = value; + + this.parentNode.storage.value = array; + + element.style.backgroundColor = 'rgb(' + value.join(',') + ')'; + } + }); + + element.value = component.storage.value || component.skeleton.value || [0, 0, 0]; + + return element; + })(component.createChildElement('span', 'value')); + + component.addEventListener('click', function () { + var hsl = satus.color.rgbToHsl(this.color.value), + s = hsl[1] / 100, + l = hsl[2] / 100; + + s *= l < .5 ? l : 1 - l; + + var v = l + s; + + s = 2 * s / (l + s); + + satus.render({ + component: 'modal', + variant: 'color-picker', + value: hsl, + parentElement: this, + + palette: { + component: 'div', + class: 'satus-color-picker__palette', + style: { + 'backgroundColor': 'hsl(' + hsl[0] + 'deg, 100%, 50%)' + }, + on: { + mousedown: function (event) { + if (event.button !== 0) { + return false; + } + + var palette = this, + rect = this.getBoundingClientRect(), + cursor = this.children[0]; + + function mousemove(event) { + var hsl = palette.skeleton.parentSkeleton.value, + x = event.clientX - rect.left, + y = event.clientY - rect.top, + s; + + x = Math.min(Math.max(x, 0), rect.width) / (rect.width / 100); + y = Math.min(Math.max(y, 0), rect.height) / (rect.height / 100); + + var v = 100 - y, + l = (2 - x / 100) * v / 2; + + hsl[1] = x * v / (l < 50 ? l * 2 : 200 - l * 2); + hsl[2] = l; + + cursor.style.left = x + '%'; + cursor.style.top = y + '%'; + + palette.nextSibling.children[0].style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; + + event.preventDefault(); + } + + function mouseup() { + window.removeEventListener('mousemove', mousemove); + window.removeEventListener('mouseup', mouseup); + } + + window.addEventListener('mousemove', mousemove); + window.addEventListener('mouseup', mouseup); + } + }, + + cursor: { + component: 'div', + class: 'satus-color-picker__cursor', + style: { + 'left': s * 100 + '%', + 'top': 100 - v * 100 + '%' + } + } + }, + section: { + component: 'section', + variant: 'color', + + color: { + component: 'div', + class: 'satus-color-picker__color', + style: { + 'backgroundColor': 'rgb(' + this.color.value.join(',') + ')' + } + }, + hue: { + component: 'slider', + class: 'satus-color-picker__hue', + storage: false, + value: hsl[0], + max: 360, + on: { + input: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + hsl = modal.value; + + hsl[0] = this.storage.value; + + this.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; + this.parentNode.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg, 100%, 50%)'; + } + } + } + }, + actions: { + component: 'section', + variant: 'actions', + + reset: { + component: 'button', + text: 'reset', + on: { + click: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + component = modal.parentElement; + + component.color.value = component.skeleton.value || [0, 0, 0]; + + modal.rendered.close(); + } + } + }, + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + this.skeleton.parentSkeleton.parentSkeleton.rendered.close(); + } + } + }, + ok: { + component: 'button', + text: 'OK', + on: { + click: function () { + var modal = this.skeleton.parentSkeleton.parentSkeleton, + component = modal.parentElement; + + component.color.value = satus.color.hslToRgb(modal.value); + + modal.rendered.close(); + } + } + } + } + }, this.baseProvider.layers[0]); + }); +}; +/*-------------------------------------------------------------- +>>> RADIO +--------------------------------------------------------------*/ + +satus.components.radio = function (component, skeleton) { + component.nativeControl = component.createChildElement('input', 'input'); + + component.createChildElement('i'); + + component.childrenContainer = component.createChildElement('div', 'content'); + + component.nativeControl.type = 'radio'; + + if (skeleton.group) { + component.storage.key = skeleton.group; + component.nativeControl.name = skeleton.group; + } + + if (skeleton.value) { + component.nativeControl.value = skeleton.value; + } + + component.storage.value = satus.storage.get(component.storage.key); + + if (satus.isset(component.storage.value)) { + component.nativeControl.checked = component.storage.value === skeleton.value; + } else if (skeleton.checked) { + component.nativeControl.checked = true; + } + + component.nativeControl.addEventListener('change', function () { + var component = this.parentNode; + + component.storage.value = this.value; + }); +}; +/*-------------------------------------------------------------- +>>> SLIDER +--------------------------------------------------------------*/ + +satus.components.slider = function (component, skeleton) { + var content = component.createChildElement('div', 'content'), + track_container = component.createChildElement('div', 'track-container'), + input = track_container.createChildElement('input', 'input'); + + component.childrenContainer = content; + component.input = input; + component.track = track_container.createChildElement('div', 'track'); + + input.type = 'range'; + input.min = skeleton.min || 0; + input.max = skeleton.max || 1; + input.step = skeleton.step || 1; + input.value = component.storage.value || skeleton.value || 0; + + input.addEventListener('input', function () { + var component = this.parentNode.parentNode; + + component.storage.value = Number(this.value); + + component.update(); + }); + + component.update = function () { + var input = this.input; + + this.track.style.width = 100 / (input.max - input.min) * (input.value - input.min) + '%'; + }; + + component.update(); + + if (skeleton.on) { + for (var type in skeleton.on) { + input.addEventListener(type, function (event) { + this.parentNode.parentNode.dispatchEvent(new Event(event.type)); + }); + } + } +}; +/*-------------------------------------------------------------- +>>> TABS +--------------------------------------------------------------*/ + +satus.components.tabs = function (component, skeleton) { + var tabs = skeleton.items, + value = skeleton.value; + + if (satus.isFunction(tabs)) { + tabs = tabs(); + } + + if (satus.isFunction(value)) { + value = value(); + } + + for (var i = 0, l = tabs.length; i < l; i++) { + var tab = tabs[i], + button = component.createChildElement('button'); + + button.addEventListener('click', function () { + var component = this.parentNode, + index = satus.elementIndex(this); + + component.value = index; + + component.style.setProperty('--satus-tabs-current', index); + }); + + satus.text(button, tab); + } + + component.style.setProperty('--satus-tabs-count', tabs.length); + component.style.setProperty('--satus-tabs-current', value || 0); +}; +/*-------------------------------------------------------------- +>>> SHORTCUT +--------------------------------------------------------------*/ + +satus.components.shortcut = function (component, skeleton) { + component.childrenContainer = component.createChildElement('div', 'content'); + component.valueElement = component.createChildElement('div', 'value'); + + component.className = 'satus-button'; + + component.render = function (parent) { + var self = this, + parent = parent || self.primary, + children = parent.children; + + satus.empty(parent); + + function createElement(name) { + var element = document.createElement('div'); + + element.className = 'satus-shortcut__' + name; + + parent.appendChild(element); + + return element; + } + + if (this.data.alt) { + createElement('key').textContent = 'Alt'; + } + + if (this.data.ctrl) { + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + createElement('key').textContent = 'Ctrl'; + } + + if (this.data.shift) { + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + createElement('key').textContent = 'Shift'; + } + + for (var code in this.data.keys) { + var key = this.data.keys[code].key, + arrows = ['ArrowUp', 'ArrowRight', 'ArrowDown', 'ArrowLeft'], + index = arrows.indexOf(key); + + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + if (index !== -1) { + createElement('key').textContent = ['↑', '→', '↓', '←'][index]; + } else if (key === ' ') { + createElement('key').textContent = '␣'; + } else if (key) { + createElement('key').textContent = key.toUpperCase(); + } + } + + if (this.data.wheel) { + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + var mouse = createElement('mouse'), + div = document.createElement('div'); + + mouse.appendChild(div); + + mouse.className += ' ' + (this.data.wheel > 0); + } + + if (this.data.click) { + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + var mouse = createElement('mouse'), + div = document.createElement('div'); + + mouse.appendChild(div); + + mouse.className += ' click'; + } + + if (this.data.middle) { + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + var mouse = createElement('mouse'), + div = document.createElement('div'); + + mouse.appendChild(div); + + mouse.className += ' middle'; + } + + if (this.data.context) { + if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { + createElement('plus'); + } + + var mouse = createElement('mouse'), + div = document.createElement('div'); + + mouse.appendChild(div); + + mouse.className += ' context'; + } + }; + + component.keydown = function (event) { + event.preventDefault(); + event.stopPropagation(); + + component.data = { + alt: event.altKey, + ctrl: event.ctrlKey, + shift: event.shiftKey, + keys: {} + }; + + if (['control', 'alt', 'altgraph', 'shift'].indexOf(event.key.toLowerCase()) === -1) { + component.data.keys[event.keyCode] = { + code: event.code, + key: event.key + }; + } + + component.data.wheel = 0; + + component.render(); + + return false; + }; + + if (skeleton.wheel !== false) { + component.mousewheel = function (event) { + event.stopPropagation(); + + if ( + ( + component.data.wheel === 0 && + ( + Object.keys(component.data.keys).length === 0 && + component.data.alt === false && + component.data.ctrl === false && + component.data.shift === false + ) + ) || + component.data.wheel < 0 && event.deltaY > 0 || + component.data.wheel > 0 && event.deltaY < 0) { + component.data = { + alt: false, + ctrl: false, + shift: false, + keys: {} + }; + } + + component.data.wheel = event.deltaY < 0 ? -1 : 1; + + component.render(); + + return false; + }; + } + + component.addEventListener('click', function () { + satus.render({ + component: 'modal', + properties: { + parent: this + }, + on: { + close: function () { + window.removeEventListener('keydown', component.keydown); + window.removeEventListener('wheel', component.mousewheel); + } + }, + + primary: { + component: 'div', + class: 'satus-shortcut__primary', + on: { + render: function () { + component.primary = this; + + if (component.skeleton.mouseButtons === true) { + this.addEventListener('mousedown', function (event) { + if ( + component.data.click && event.button === 0 || + component.data.middle && event.button === 1 + ) { + component.data = { + alt: false, + ctrl: false, + shift: false, + keys: {} + }; + } + + component.data.click = false; + component.data.middle = false; + component.data.context = false; + + if (event.button === 0) { + component.data.click = true; + + component.render(); + } else if (event.button === 1) { + component.data.middle = true; + + component.render(); + } + }); + + this.addEventListener('contextmenu', function (event) { + event.preventDefault(); + event.stopPropagation(); + + if (component.data.context) { + component.data = { + alt: false, + ctrl: false, + shift: false, + keys: {} + }; + } + + component.data.context = true; + component.data.middle = false; + component.data.click = false; + + component.render(); + + return false; + }); + } + + component.render(); + } + } + }, + actions: { + component: 'section', + variant: 'actions', + + reset: { + component: 'button', + text: 'reset', + on: { + click: function () { + var component = this.parentNode.parentNode.parentNode.parent; + + component.data = component.skeleton.value || {}; + + component.render(component.valueElement); + + satus.storage.remove(component.storage); + + this.parentNode.parentNode.parentNode.close(); + + window.removeEventListener('keydown', component.keydown); + window.removeEventListener('wheel', component.mousewheel); + } + } + }, + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + component.data = satus.storage.get(component.storage) || component.skeleton.value || {}; + + component.render(component.valueElement); + + this.parentNode.parentNode.parentNode.close(); + + window.removeEventListener('keydown', component.keydown); + window.removeEventListener('wheel', component.mousewheel); + } + } + }, + save: { + component: 'button', + text: 'save', + on: { + click: function () { + component.storage.value = component.data; + + component.render(component.valueElement); + + this.parentNode.parentNode.parentNode.close(); + + window.removeEventListener('keydown', component.keydown); + window.removeEventListener('wheel', component.mousewheel); + } + } + } + } + }, this.baseProvider); + + window.addEventListener('keydown', this.keydown); + window.addEventListener('wheel', this.mousewheel); + }); + + component.data = component.storage.value || { + alt: false, + ctrl: false, + shift: false, + keys: {}, + wheel: 0 + }; + + component.render(component.valueElement); +}; +/*-------------------------------------------------------------- +>>> CHECKBOX +--------------------------------------------------------------*/ + +satus.components.checkbox = function (component, skeleton) { + component.input = component.createChildElement('input'); + component.input.type = 'checkbox'; + + component.checkmark = component.createChildElement('div', 'checkmark'); + + component.childrenContainer = component.createChildElement('div', 'content'); + + component.dataset.value = component.storage.value || skeleton.value; + component.input.checked = component.storage.value || skeleton.value; + + component.input.addEventListener('change', function () { + var component = this.parentNode; + + if (this.checked === true) { + component.storage.value = true; + component.dataset.value = 'true'; + } else { + component.storage.value = false; + component.dataset.value = 'false'; + } + }); +}; +/*-------------------------------------------------------------- +>>> SWITCH +--------------------------------------------------------------*/ + +satus.components.switch = function (component, skeleton) { + var value = satus.isset(component.storage.value) ? component.storage.value : skeleton.value; + + if (satus.isFunction(value)) { + value = value(); + } + + component.childrenContainer = component.createChildElement('div', 'content'); + + component.createChildElement('i'); + + component.dataset.value = value; + + component.addEventListener('click', function () { + if (this.dataset.value === 'true') { + this.dataset.value = 'false'; + this.storage.value = false; + } else { + this.dataset.value = 'true'; + this.storage.value = true; + } + }, true); +}; +/*-------------------------------------------------------------- +>>> CONTEXT MENU +--------------------------------------------------------------*/ + +satus.events.on('render', function (component) { + if (component.skeleton.contextMenu) { + component.addEventListener('contextmenu', function (event) { + var base = this.baseProvider, + base_rect = base.getBoundingClientRect(), + x = event.clientX - base_rect.left, + y = event.clientY - base_rect.top, + modal = satus.render({ + component: 'modal', + variant: 'contextmenu', + parentSkeleton: this.skeleton, + baseProvider: base + }, base); + + if (base_rect.width - x < 200) { + x = base_rect.width - x; + + if (x + 200 > base_rect.width) { + x = 0; + } + + modal.childrenContainer.style.right = x + 'px'; + } else { + modal.childrenContainer.style.left = x + 'px'; + } + + modal.childrenContainer.style.top = y + 'px'; + + this.skeleton.contextMenu.parentSkeleton = this.skeleton; + + satus.render(this.skeleton.contextMenu, modal.childrenContainer); + + event.preventDefault(); + event.stopPropagation(); + + return false; + }); + } +}); +/*-------------------------------------------------------------- +>>> SORTABLE +--------------------------------------------------------------*/ + +satus.events.on('render', function (component) { + if (component.skeleton.sortable === true) { + component.addEventListener('mousedown', function (event) { + if (event.button !== 0) { + return false; + } + + var component = this, + rect = this.getBoundingClientRect(), + x = event.clientX, + y = event.clientY, + offset_x = event.clientX - rect.left, + offset_y = event.clientY - rect.top, + ghost = satus.clone(this), + children = this.parentNode.children, + appended = false; + + ghost.classList.add('satus-sortable__ghost'); + + function mousemove(event) { + if (appended === false && (Math.abs(event.clientX - x) > 4 || Math.abs(event.clientY - y) > 4)) { + appended = true; + + component.classList.add('satus-sortable__chosen'); + + component.baseProvider.appendChild(ghost); + } + + ghost.style.transform = 'translate(' + (event.clientX - offset_x) + 'px, ' + (event.clientY - offset_y) + 'px)'; + } + + function mouseup(event) { + component.classList.remove('satus-sortable__chosen'); + ghost.remove(); + + window.removeEventListener('mousemove', mousemove, true); + window.removeEventListener('mouseup', mouseup, true); + + for (var i = 0, l = children.length; i < l; i++) { + var child = children[i]; + + if (child !== component) { + child.removeEventListener('mouseover', siblingMouseOver); + } + } + + component.dispatchEvent(new CustomEvent('sort')); + + event.stopPropagation(); + + return false; + } + + window.addEventListener('mousemove', mousemove, { + passive: true, + capture: true + }); + + window.addEventListener('mouseup', mouseup, { + passive: true, + capture: true + }); + + function siblingMouseOver(event) { + var parent = this.parentNode, + y = event.layerY / (this.offsetHeight / 100); + + if (y < 50 && this.previousSibling !== component || y >= 50 && this.nextSibling === component) { + parent.insertBefore(component, this); + } else { + parent.insertBefore(component, this.nextSibling); + } + } + + for (var i = 0, l = children.length; i < l; i++) { + var child = children[i]; + + if (child !== component) { + child.addEventListener('mouseover', siblingMouseOver); + } + } + + event.stopPropagation(); + event.preventDefault(); + + return false; + }); + } +}); +/*-------------------------------------------------------------- +>>> MANIFEST +--------------------------------------------------------------*/ + +satus.manifest = function () { + var object = {}; + + if (this.isset('chrome.runtime.getManifest')) { + object = chrome.runtime.getManifest(); + } + + return object; +}; +/*-------------------------------------------------------------- +>>> COLOR: +---------------------------------------------------------------- +# String to array +# RGB to HSL +# HUE to RGB +# HSL to RGB +--------------------------------------------------------------*/ + +satus.color = {}; + + +/*-------------------------------------------------------------- +# STRING TO ARRAY +--------------------------------------------------------------*/ + +satus.color.stringToArray = function (string) { + var match = string.match(/[0-9.]+/g); + + if (match) { + for (var i = 0, l = match.length; i < l; i++) { + match[i] = parseFloat(match[i]); + } + } + + return match; +}; + + +/*-------------------------------------------------------------- +# RGB TO HSL +--------------------------------------------------------------*/ + +satus.color.rgbToHsl = function (array) { + var r = array[0] / 255, + g = array[1] / 255, + b = array[2] / 255, + min = Math.min(r, g, b), + max = Math.max(r, g, b), + h = 0, + s = 0, + l = (min + max) / 2; + + if (min === max) { + h = 0; + s = 0; + } else { + var delta = max - min; + + s = l <= 0.5 ? delta / (max + min) : delta / (2 - max - min); + + if (max === r) { + h = (g - b) / delta + (g < b ? 6 : 0); + } else if (max === g) { + h = (b - r) / delta + 2; + } else if (max === b) { + h = (r - g) / delta + 4; + } + + h /= 6; + } + + h *= 360; + s *= 100; + l *= 100; + + if (array.length === 3) { + return [h, s, l]; + } else { + return [h, s, l, array[3]]; + } +}; + + +/*-------------------------------------------------------------- +# HUE TO RGB +--------------------------------------------------------------*/ + +satus.color.hueToRgb = function (array) { + var t1 = array[0], + t2 = array[1], + hue = array[2]; + + if (hue < 0) { + hue += 6; + } + + if (hue >= 6) { + hue -= 6; + } + + if (hue < 1) { + return (t2 - t1) * hue + t1; + } else if (hue < 3) { + return t2; + } else if (hue < 4) { + return (t2 - t1) * (4 - hue) + t1; + } else { + return t1; + } +}; + + +/*-------------------------------------------------------------- +# HSL TO RGB +--------------------------------------------------------------*/ + +satus.color.hslToRgb = function (array) { + var h = array[0] / 360, + s = array[1] / 100, + l = array[2] / 100, + r, g, b; + + if (s == 0) { + r = g = b = l; + } else { + var hue2rgb = function (p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1 / 6) return p + (q - p) * 6 * t; + if (t < 1 / 2) return q; + if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; + return p; + }; + + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hue2rgb(p, q, h + 1 / 3); + g = hue2rgb(p, q, h); + b = hue2rgb(p, q, h - 1 / 3); + } + + return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; +}; +/*-------------------------------------------------------------- +>>> USER +---------------------------------------------------------------- +# OS + # Name + # Bitness +# Browser + # Name + # Version + # Platform + # Manifest + # Languages + # Cookies + # Flash + # Java + # Audio + # Video + # WebGL +# Device + # Screen + # RAM + # GPU + # Cores + # Touch + # Connection +--------------------------------------------------------------*/ + +satus.user = { + browser: {}, + device: {}, + os: {} +}; + +/*-------------------------------------------------------------- +# OS +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# NAME +--------------------------------------------------------------*/ + +satus.user.os.name = function () { + var app_version = navigator.appVersion; + + if (app_version.indexOf('Win') !== -1) { + if (app_version.match(/(Windows 10.0|Windows NT 10.0)/)) { + return 'Windows 10'; + } else if (app_version.match(/(Windows 8.1|Windows NT 6.3)/)) { + return 'Windows 8.1'; + } else if (app_version.match(/(Windows 8|Windows NT 6.2)/)) { + return 'Windows 8'; + } else if (app_version.match(/(Windows 7|Windows NT 6.1)/)) { + return 'Windows 7'; + } else if (app_version.match(/(Windows NT 6.0)/)) { + return 'Windows Vista'; + } else if (app_version.match(/(Windows NT 5.1|Windows XP)/)) { + return 'Windows XP'; + } else { + return 'Windows'; + } + } else if (app_version.indexOf('(iPhone|iPad|iPod)') !== -1) { + return 'iOS'; + } else if (app_version.indexOf('Mac') !== -1) { + return 'macOS'; + } else if (app_version.indexOf('Android') !== -1) { + return 'Android'; + } else if (app_version.indexOf('OpenBSD') !== -1) { + return 'OpenBSD'; + } else if (app_version.indexOf('SunOS') !== -1) { + return 'SunOS'; + } else if (app_version.indexOf('Linux') !== -1) { + return 'Linux'; + } else if (app_version.indexOf('X11') !== -1) { + return 'UNIX'; + } +}; + + +/*-------------------------------------------------------------- +# BITNESS +--------------------------------------------------------------*/ + +satus.user.os.bitness = function () { + if (navigator.appVersion.match(/(Win64|x64|x86_64|WOW64)/)) { + return '64-bit'; + } else { + return '32-bit'; + } +}; + + +/*-------------------------------------------------------------- +# BROWSER +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# NAME +--------------------------------------------------------------*/ + +satus.user.browser.name = function () { + var user_agent = navigator.userAgent; + + if (user_agent.indexOf('Opera') !== -1) { + return 'Opera'; + } else if (user_agent.indexOf('Vivaldi') !== -1) { + return 'Vivaldi'; + } else if (user_agent.indexOf('Edge') !== -1) { + return 'Edge'; + } else if (user_agent.indexOf('Chrome') !== -1) { + return 'Chrome'; + } else if (user_agent.indexOf('Safari') !== -1) { + return 'Safari'; + } else if (user_agent.indexOf('Firefox') !== -1) { + return 'Firefox'; + } else if (user_agent.indexOf('MSIE') !== -1) { + return 'IE'; + } +}; + + +/*-------------------------------------------------------------- +# VERSION +--------------------------------------------------------------*/ + +satus.user.browser.version = function () { + var browser_name = satus.user.browser.name(), + browser_version = navigator.userAgent.match(new RegExp(browser_name + '/([0-9.]+)')); + + return browser_version[1]; +}; + + +/*-------------------------------------------------------------- +# PLATFORM +--------------------------------------------------------------*/ + +satus.user.browser.platform = function () { + return navigator.platform; +}; + + +/*-------------------------------------------------------------- +# MANIFEST +--------------------------------------------------------------*/ + +satus.user.browser.manifest = function () { + return chrome.runtime.getManifest() || {}; +}; + + +/*-------------------------------------------------------------- +# LANGUAGES +--------------------------------------------------------------*/ + +satus.user.browser.languages = function () { + return navigator.languages; +}; + + +/*-------------------------------------------------------------- +# COOKIES +--------------------------------------------------------------*/ + +satus.user.browser.cookies = function () { + if (document.cookie) { + var random_cookie = 'ta{t`nX6cMXK,Wsc'; + + document.cookie = random_cookie; + + if (document.cookie.indexOf(random_cookie) !== -1) { + return true; + } + } + + return false; +}; + + +/*-------------------------------------------------------------- +# FLASH +--------------------------------------------------------------*/ + +satus.user.browser.flash = function () { + try { + if (new ActiveXObject('ShockwaveFlash.ShockwaveFlash')) { + return true; + } + } catch (error) { + if (navigator.mimeTypes['application/x-shockwave-flash']) { + return true; + } + } + + return false; +}; + + +/*-------------------------------------------------------------- +# JAVA +--------------------------------------------------------------*/ + +satus.user.browser.java = function () { + if (satus.isFunction(navigator.javaEnabled) && navigator.javaEnabled()) { + return true; + } else { + return false; + } +}; + + +/*-------------------------------------------------------------- +# AUDIO +--------------------------------------------------------------*/ + +satus.user.browser.audio = function () { + var audio = document.createElement('audio'), + types = { + mp3: 'audio/mpeg', + mp4: 'audio/mp4', + aif: 'audio/x-aiff' + }, + result = []; + + if (satus.isFunction(audio.canPlayType)) { + for (var key in types) { + var can_play_type = audio.canPlayType(types[key]); + + if (can_play_type !== '') { + result.push(key); + } + } + } + + return result; +}; + + +/*-------------------------------------------------------------- +# VIDEO +--------------------------------------------------------------*/ + +satus.user.browser.video = function () { + var video = document.createElement('video'), + types = { + ogg: 'video/ogg; codecs="theora"', + h264: 'video/mp4; codecs="avc1.42E01E"', + webm: 'video/webm; codecs="vp8, vorbis"', + vp9: 'video/webm; codecs="vp9"', + hls: 'application/x-mpegURL; codecs="avc1.42E01E"' + }, + result = []; + + if (satus.isFunction(video.canPlayType)) { + for (var key in types) { + var can_play_type = video.canPlayType(types[key]); + + if (can_play_type !== '') { + result.push(key); + } + } + } + + return result; +}; + + +/*-------------------------------------------------------------- +# WEBGL +--------------------------------------------------------------*/ + +satus.user.browser.webgl = function () { + var cvs = document.createElement('canvas'), + ctx = cvs.getContext('webgl'); + + return ctx && ctx instanceof WebGLRenderingContext; +}; + + +/*-------------------------------------------------------------- +# HARDWARE +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# SCREEN +--------------------------------------------------------------*/ + +satus.user.device.screen = function () { + if (screen) { + return screen.width + 'x' + screen.height; + } +}; + + +/*-------------------------------------------------------------- +# RAM +--------------------------------------------------------------*/ + +satus.user.device.ram = function () { + if ('deviceMemory' in navigator) { + return navigator.deviceMemory + ' GB'; + } +}; + + +/*-------------------------------------------------------------- +# GPU +--------------------------------------------------------------*/ + +satus.user.device.gpu = function () { + var cvs = document.createElement('canvas'), + ctx = cvs.getContext('webgl'); + + if ( + ctx && + ctx instanceof WebGLRenderingContext && + 'getParameter' in ctx && + 'getExtension' in ctx + ) { + var info = ctx.getExtension('WEBGL_debug_renderer_info'); + + if (info) { + return ctx.getParameter(info.UNMASKED_RENDERER_WEBGL); + } + } +}; + + +/*-------------------------------------------------------------- +# CORES +--------------------------------------------------------------*/ + +satus.user.device.cores = function () { + return navigator.deviceConcurrency; +}; + + +/*-------------------------------------------------------------- +# TOUCH +--------------------------------------------------------------*/ + +satus.user.device.touch = function () { + var result = {}; + + if ( + window.hasOwnProperty('ontouchstart') || + window.DocumentTouch && document instanceof window.DocumentTouch || + navigator.maxTouchPoints > 0 || + window.navigator.msMaxTouchPoints > 0 + ) { + result.touch = true; + result.maxTouchPoints = navigator.maxTouchPoints; + } + + return result; +}; + + +/*-------------------------------------------------------------- +# CONNECTION +--------------------------------------------------------------*/ + +satus.user.device.connection = function () { + var result = {}; + + if (typeof navigator.connection === 'object') { + result.type = navigator.connection.effectiveType || null; + + if (navigator.connection.downlink) { + result.speed = navigator.connection.downlink + ' Mbps'; + } + } + + return result; +}; +/*-------------------------------------------------------------- +# SEARCH +--------------------------------------------------------------*/ + +satus.search = function (query, object, callback) { + var elements = ['switch', 'select', 'slider', 'shortcut', 'radio', 'color-picker'], + threads = 0, + results = {}, + excluded = [ + 'baseProvider', + 'childrenContainer', + 'parentElement', + 'parentObject', + 'parentSkeleton', + 'rendered', + 'namespaceURI' + ]; + + query = query.toLowerCase(); + + function parse(items, parent) { + threads++; + + for (var key in items) { + if (excluded.indexOf(key) === -1) { + var item = items[key]; + + if (item.component) { + //console.log(key, item.component); + + if (elements.indexOf(item.component) !== -1 && key.indexOf(query) !== -1) { + results[key] = Object.assign({}, item); + } + } + + if (typeof item === 'object') { + parse(item, items); + } + } + } + + threads--; + + if (threads === 0) { + callback(results); + } + } + + parse(object); +}; diff --git a/background.js b/background.js index 2426298..960623a 100644 --- a/background.js +++ b/background.js @@ -1,43 +1,17 @@ -/*--------------------------------------------------------------- +/*-------------------------------------------------------------- >>> BACKGROUND ------------------------------------------------------------------ -# Listeners - # On Install - # Message ----------------------------------------------------------------*/ - -/*--------------------------------------------------------------- -# LISTENERS ----------------------------------------------------------------*/ - -/*--------------------------------------------------------------- -# ON INSTALL ----------------------------------------------------------------*/ - -chrome.runtime.onInstalled.addListener(function(event){ - if(event.reason === 'install') { - chrome.storage.local.set({ - auto_scroll: { - middle: true - } - }); - } -}); - - -/*--------------------------------------------------------------- -# MESSAGE ----------------------------------------------------------------*/ +--------------------------------------------------------------*/ chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) { - if (message === 'get-tab-url') { - var response = { - url: new URL(sender.tab.url).hostname, - id: sender.tab.id - }; + if (message === 'tab-connected') { + var response = new URL(sender.tab.url).hostname; - sendResponse(response); + sendResponse(response); - return response; - } + return response; + }else if (message === 'options-page-connected') { + sendResponse({ + isPopup: sender.hasOwnProperty('tab') === false + }); + } }); \ No newline at end of file diff --git a/content-script.js b/content-script.js index 28cbcc8..591e450 100644 --- a/content-script.js +++ b/content-script.js @@ -2,20 +2,14 @@ >>> CONTENT SCRIPT ---------------------------------------------------------------- # Global variable -# Message - # Listener - # Sent -# Storage - # Get - # Set - # Import - # On changed -# Find container # Cursor # Set # Reset +# Storage + # Get + # Import # Features - # Auto + # Auto scroll # Drag & Drop # Initialization --------------------------------------------------------------*/ @@ -26,100 +20,66 @@ var extension = { hostname: location.hostname, - request: null, - animationRequest: null + storage: { + data: {} + } }; - - - - - - /*-------------------------------------------------------------- -# MESSAGE +# CURSOR --------------------------------------------------------------*/ -extension.message = {}; +extension.cursor = { + x: 0, + y: 0, + target: document.documentElement +}; /*-------------------------------------------------------------- -# LISTENER +# SET --------------------------------------------------------------*/ -extension.message.listener = function (callback) { - chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) { - if (message === 'init') { - if (window === window.top) { - sendResponse(extension.hostname); - } - } - }); +extension.cursor.set = function (type) { + document.documentElement.dataset.autoScrollCursor = type; }; /*-------------------------------------------------------------- -# SENT +# RESET --------------------------------------------------------------*/ -extension.message.sent = function (message, callback) { - chrome.runtime.sendMessage(message, callback); +extension.cursor.reset = function () { + delete document.documentElement.dataset.autoScrollCursor; }; - - - - - - /*-------------------------------------------------------------- # STORAGE --------------------------------------------------------------*/ -extension.storage = { - items: {} -}; - - /*-------------------------------------------------------------- # GET --------------------------------------------------------------*/ extension.storage.get = function (key) { - return this.items[key]; -}; - - -/*-------------------------------------------------------------- -# SET ---------------------------------------------------------------*/ + var array = key.split('/'), + target = extension.storage.data; -extension.storage.set = function (key, value) { - var object = {}; + for (var i = 0, l = array.length; i < l; i++) { + var j = array[i]; - object[key] = value; + if (target[j] !== undefined) { + target = target[j]; - this.items[key] = value; - - chrome.storage.local.set(object); -}; - - -/*-------------------------------------------------------------- -# IMPORT ---------------------------------------------------------------*/ - -extension.storage.import = function (callback) { - chrome.storage.local.get(function (items) { - extension.storage.items = items; - - document.removeEventListener('storage-import', callback); - document.addEventListener('storage-import', callback); - - document.dispatchEvent(new CustomEvent('storage-import')); - }); + if (i + 1 === l) { + return target; + } + } else { + return undefined; + } + } }; @@ -128,274 +88,27 @@ extension.storage.import = function (callback) { --------------------------------------------------------------*/ extension.storage.onchanged = function (callback) { - chrome.storage.onChanged.addListener(function (changes) { - for (var key in changes) { - var value = changes[key].newValue; - - extension.storage.items[key] = value; - - document.removeEventListener('storage-change', callback); - document.addEventListener('storage-change', callback); - - document.dispatchEvent(new CustomEvent('storage-import'), { - detail: { - key, - value - } - }); - } - }); -}; - - - - - - - - -/*-------------------------------------------------------------- -# EVENTS ---------------------------------------------------------------*/ - -extension.events = { - data: { - alt: false, - ctrl: false, - shift: false, - keys: {} - }, - keyboard: {}, - mouse: {} -}; - - -/*-------------------------------------------------------------- -# CREATE ---------------------------------------------------------------*/ - -extension.events.create = function (target) { - for (var type in this[target]) { - document.addEventListener(type, this[target][type], true); - } -}; - - -/*-------------------------------------------------------------- -# REMOVE ---------------------------------------------------------------*/ - -extension.events.remove = function (target) { - for (var type in this[target]) { - document.removeEventListener(type, this[target][type]); - } -}; - - -/*-------------------------------------------------------------- -# CHECK ACTIVE ELEMENT ---------------------------------------------------------------*/ - -extension.events.checkActiveElement = function () { - if ( - event.target.isContentEditable || - [ - 'EMBED', - 'INPUT', - 'OBJECT', - 'TEXTAREA', - 'IFRAME' - ].includes((document.activeElement || {}).tagName) - ) { - return true; - } -}; - - -/*-------------------------------------------------------------- -# FEATURES ---------------------------------------------------------------*/ - -extension.events.features = {}; - - -/*-------------------------------------------------------------- -# HANDLER ---------------------------------------------------------------*/ - -extension.events.handler = function () { - var prevent = false; - - for (var key in extension.events.features) { - var shortcut = extension.storage.items[key]; - - if (shortcut) { - var same_keys = true; - - if ( - (extension.events.data.alt === shortcut.alt || shortcut.hasOwnProperty('alt') === false) && - (extension.events.data.ctrl === shortcut.ctrl || shortcut.hasOwnProperty('ctrl') === false) && - (extension.events.data.shift === shortcut.shift || shortcut.hasOwnProperty('shift') === false) && - (extension.events.data.click === shortcut.click || shortcut.hasOwnProperty('click') === false) && - (extension.events.data.middle === shortcut.middle || shortcut.hasOwnProperty('middle') === false) && - (extension.events.data.context === shortcut.context || shortcut.hasOwnProperty('context') === false) - ) { - if (shortcut.keys) { - for (var code in extension.events.data.keys) { - if (!shortcut.keys[code]) { - same_keys = false; - } - } - - for (var code in shortcut.keys) { - if (!extension.events.data.keys[code]) { - same_keys = false; - } - } - } - - if (same_keys === true) { - cancelAnimationFrame(extension.animationRequest); - - extension.events.features[key](); - - prevent = true; - } - } - } - } - - return prevent; -}; - - -/*-------------------------------------------------------------- -# KEYBOARD ---------------------------------------------------------------*/ - -extension.events.keyboard.keydown = function (event) { - if (extension.events.checkActiveElement()) { - return false; - } - - if (event.code === 'AltLeft' || event.code === 'AltRight') { - extension.events.data.alt = true; - } else if (event.code === 'ControlLeft' || event.code === 'ControlRight') { - extension.events.data.ctrl = true; - } else if (event.code === 'ShiftLeft' || event.code === 'ShiftRight') { - extension.events.data.shift = true; - } else { - extension.events.data.keys[event.keyCode] = true; - } - - extension.events.data.wheel = 0; - extension.events.data.click = false; - extension.events.data.middle = false; - extension.events.data.context = false; - - if (extension.events.handler()) { - event.preventDefault(); - event.stopPropagation(); - - return false; - } -}; - -extension.events.keyboard.keyup = function (event) { - if (extension.events.checkActiveElement()) { - return false; - } - - if (event.code === 'AltLeft' || event.code === 'AltRight') { - extension.events.data.alt = false; - } else if (event.code === 'ControlLeft' || event.code === 'ControlRight') { - extension.events.data.ctrl = false; - } else if (event.code === 'ShiftLeft' || event.code === 'ShiftRight') { - extension.events.data.shift = false; - } else { - delete extension.events.data.keys[event.keyCode]; - } - - extension.events.data.wheel = 0; - extension.events.data.click = false; - extension.events.data.middle = false; - extension.events.data.context = false; + chrome.storage.onChanged.addListener(function (changes) { + for (var key in changes) { + extension.storage.data[key] = changes[key].newValue; + } + }); }; /*-------------------------------------------------------------- -# MOUSE +# IMPORT --------------------------------------------------------------*/ -extension.events.mouse.mousemove = function (event) { - extension.cursor.x = event.clientX; - extension.cursor.y = event.clientY; - extension.cursor.target = event.target; -}; - -extension.events.mouse.mousedown = function (event) { - if ( - extension.events.data.click && event.button === 0 || - extension.events.data.middle && event.button === 1 - ) { - extension.events.data = { - alt: false, - ctrl: false, - shift: false, - keys: {} - }; - } - - extension.events.data.click = false; - extension.events.data.middle = false; - extension.events.data.context = false; - - if (event.button === 0) { - extension.events.data.click = true; - } else if (event.button === 1) { - extension.events.data.middle = true; - } - - if (extension.events.handler()) { - event.preventDefault(); - event.stopPropagation(); - - extension.mousedown = true; - - return false; - } -}; - -extension.events.mouse.mouseup = function (event) { - if (extension.events.data.context) { - extension.events.data = { - alt: false, - ctrl: false, - shift: false, - keys: {} - }; - } - - extension.events.data.context = true; - extension.events.data.middle = false; - extension.events.data.click = false; - - if (extension.mousedown === true) { - event.preventDefault(); - event.stopPropagation(); - - extension.mousedown = false; +extension.storage.import = function (callback) { + chrome.storage.local.get(function (items) { + extension.storage.data = items; - return false; - } + callback(); + }); }; - - - - - /*-------------------------------------------------------------- # FIND CONTAINER --------------------------------------------------------------*/ @@ -426,485 +139,209 @@ extension.findContainer = function (target) { }; - - - - - - -/*-------------------------------------------------------------- -# CURSOR ---------------------------------------------------------------*/ - -extension.cursor = { - x: 0, - y: 0, - target: document.documentElement -}; - - -/*-------------------------------------------------------------- -# SET ---------------------------------------------------------------*/ - -extension.cursor.set = function (type) { - document.documentElement.dataset.autoScrollCursor = type; -}; - - -/*-------------------------------------------------------------- -# RESET ---------------------------------------------------------------*/ - -extension.cursor.reset = function () { - delete document.documentElement.dataset.autoScrollCursor; -}; - - - - - - - - /*-------------------------------------------------------------- # FEATURES --------------------------------------------------------------*/ /*-------------------------------------------------------------- -# AUTO ---------------------------------------------------------------*/ - -extension.autoMode = { - sensitivity: 10, - mousedown: { - x: 0, - y: 0 - }, - offset: { - x: 0, - y: 0 - } -}; - - -/*-------------------------------------------------------------- -# START +# AUTO SCROLL --------------------------------------------------------------*/ -extension.events.features.auto_scroll = function (event) { - var data = extension.storage.items['auto_scroll']; +extension.automatic = function (event) { + if (event instanceof Event) { + if (event.type === 'mousemove') { + if (extension.automatic.active !== true) { + var x = Math.abs(extension.automatic.mousedown.x - event.clientX), + y = Math.abs(extension.automatic.mousedown.y - event.clientY); - if (data) { - addEventListener('mousemove', extension.autoMode.check, true); + if (x > 5 || y > 5) { + extension.cursor.set('all-scroll'); - if ( - data.click || - data.middle || - data.context - ) { - addEventListener('mouseup', extension.autoMode.end, true); - } else { - addEventListener('keyup', extension.autoMode.end, true); - } - } -}; + extension.findContainer(event.target); + extension.automatic.scroll(); -/*-------------------------------------------------------------- -# CHECK ---------------------------------------------------------------*/ - -extension.autoMode.check = function (event) { - var x = Math.abs(extension.autoMode.mousedown.x - event.clientX), - y = Math.abs(extension.autoMode.mousedown.y - event.clientY); + extension.automatic.active = true; - if (x > 5 || y > 5) { - extension.cursor.set('all-scroll'); + event.preventDefault(); + event.stopPropagation(); + } + } else { + var x = event.clientX - extension.automatic.mousedown.x, + y = event.clientY - extension.automatic.mousedown.y; - extension.autoMode.mousedown.x = event.clientX; - extension.autoMode.mousedown.y = event.clientY; + x = x / 100 * extension.automatic.sensitivity; + y = y / 100 * extension.automatic.sensitivity; - extension.findContainer(event.target); - extension.autoMode.move(event); - extension.autoMode.scroll(); + extension.automatic.offset.x = x; + extension.automatic.offset.y = y; + } + } else if (event.type === 'mousedown') { + var option = extension.storage.get('autoScroll'); - addEventListener('mousemove', extension.autoMode.move, true); - removeEventListener('mousemove', extension.autoMode.check, true); - } -}; + if ((option === undefined || option === 'scroll_wheel') && event.button !== 1) { + return; + } + extension.automatic.mousedown = { + x: event.clientX, + y: event.clientY + }; -/*-------------------------------------------------------------- -# MOVE ---------------------------------------------------------------*/ + extension.automatic.offset = { + x: 0, + y: 0 + }; -extension.autoMode.move = function (event) { - var x = event.clientX - extension.autoMode.mousedown.x, - y = event.clientY - extension.autoMode.mousedown.y; + window.addEventListener('mousemove', extension.automatic, true); + window.addEventListener('mouseup', extension.automatic, true); + } else if (event.type === 'mouseup') { + window.removeEventListener('mousemove', extension.automatic, true); + window.removeEventListener('mouseup', extension.automatic, true); - x = x / 100 * extension.autoMode.sensitivity; - y = y / 100 * extension.autoMode.sensitivity; + if (extension.automatic.request) { + cancelAnimationFrame(extension.automatic.request); + } - extension.autoMode.offset.x = x; - extension.autoMode.offset.y = y; -}; + extension.automatic.active = false; + extension.cursor.reset(); -/*-------------------------------------------------------------- -# SCROLL ---------------------------------------------------------------*/ - -extension.autoMode.scroll = function () { - var target = extension.target, - x = target.scrollLeft + extension.autoMode.offset.x, - y = target.scrollTop + extension.autoMode.offset.y; - - if (target.scroll) { - target.scroll(x, y); + event.preventDefault(); + event.stopPropagation(); + } } else { - target.scrollLeft = x; - target.scrollTop = y; - } - - extension.request = requestAnimationFrame(extension.autoMode.scroll); -}; - - -/*-------------------------------------------------------------- -# END ---------------------------------------------------------------*/ - -extension.autoMode.end = function (event) { - cancelAnimationFrame(extension.request); - - extension.cursor.reset(); - - removeEventListener('mousemove', extension.autoMode.check, true); - removeEventListener('mousemove', extension.autoMode.move, true); - removeEventListener('mouseup', extension.autoMode.end, true); -}; - - - - - - + var option = extension.storage.get('autoScroll'); + if (option !== 'disabled') { + extension.automatic.sensitivity = 10; -/*-------------------------------------------------------------- -# DRAG & DROP ---------------------------------------------------------------*/ - -extension.dragAndDrop = { - mousedown: { - x: 0, - y: 0 - }, - offset: { - x: 0, - y: 0 - }, - scroll: { - x: 0, - y: 0 - } -}; - - -/*-------------------------------------------------------------- -# START ---------------------------------------------------------------*/ - -extension.events.features.drag_and_drop = function (event) { - var data = extension.storage.items['drag_and_drop']; + extension.automatic.scroll = function scroll() { + var target = extension.target, + x = target.scrollLeft + extension.automatic.offset.x, + y = target.scrollTop + extension.automatic.offset.y; - if (data) { - extension.cursor.set('all-scroll'); + if (target.scroll) { + target.scroll(x, y); + } else { + target.scrollLeft = x; + target.scrollTop = y; + } - extension.dragAndDrop.mousedown.x = extension.cursor.x; - extension.dragAndDrop.mousedown.y = extension.cursor.y; + extension.automatic.request = requestAnimationFrame(extension.automatic.scroll); + }; - extension.findContainer(extension.cursor.target); - - extension.dragAndDrop.scroll.x = extension.target.scrollLeft; - extension.dragAndDrop.scroll.y = extension.target.scrollTop; - - extension.dragAndDrop.move(event); - extension.dragAndDrop.scroll(); - - addEventListener('mousemove', extension.dragAndDrop.move, true); - - if ( - data.click || - data.middle || - data.context - ) { - addEventListener('mouseup', extension.dragAndDrop.end, true); + window.addEventListener('mousedown', extension.automatic, true); } else { - addEventListener('keyup', extension.dragAndDrop.end, true); + window.removeEventListener('mousedown', extension.automatic, true); } } }; - /*-------------------------------------------------------------- -# MOVE ---------------------------------------------------------------*/ - -extension.dragAndDrop.move = function (event) { - extension.dragAndDrop.offset.x = extension.cursor.x - extension.dragAndDrop.mousedown.x; - extension.dragAndDrop.offset.y = extension.cursor.y - extension.dragAndDrop.mousedown.y; -}; - - -/*-------------------------------------------------------------- -# SCROLL +# DRAG & DROP --------------------------------------------------------------*/ -extension.dragAndDrop.scroll = function () { - var target = extension.target, - x = extension.dragAndDrop.scroll.x - extension.dragAndDrop.offset.x, - y = extension.dragAndDrop.scroll.y - extension.dragAndDrop.offset.y; - - if (target.scroll) { - target.scroll(x, y); +extension.dragAndDrop = function (event) { + if (event instanceof Event) { + if (event.type === 'mousemove') { + if (extension.dragAndDrop.active !== true) { + var x = Math.abs(extension.dragAndDrop.mousedown.x - event.clientX), + y = Math.abs(extension.dragAndDrop.mousedown.y - event.clientY); + + if (x > 2 || y > 2) { + extension.cursor.set('grabbing'); + + extension.findContainer(event.target); + + extension.dragAndDrop.scroll = { + x: extension.target.scrollLeft, + y: extension.target.scrollTop + }; + + extension.dragAndDrop.active = true; + } + } else { + extension.dragAndDrop.offset.x = event.clientX - extension.dragAndDrop.mousedown.x; + extension.dragAndDrop.offset.y = event.clientY - extension.dragAndDrop.mousedown.y; + + var target = extension.target, + x = extension.dragAndDrop.scroll.x - extension.dragAndDrop.offset.x, + y = extension.dragAndDrop.scroll.y - extension.dragAndDrop.offset.y; + + if (target.scroll) { + target.scroll(x, y); + } else { + target.scrollLeft = x; + target.scrollTop = y; + } + } + + event.preventDefault(); + event.stopPropagation(); + } else if (event.type === 'mousedown') { + var option = extension.storage.get('dragAndDrop'); + + if ( + option === 'left_mouse_button' && event.button !== 0 || + option === 'scroll_wheel' && event.button !== 1 + ) { + return; + } + + extension.dragAndDrop.mousedown = { + x: event.clientX, + y: event.clientY + }; + + extension.dragAndDrop.offset = { + x: 0, + y: 0 + }; + + window.addEventListener('mousemove', extension.dragAndDrop, true); + window.addEventListener('mouseup', extension.dragAndDrop, true); + } else if (event.type === 'mouseup') { + window.removeEventListener('mousemove', extension.dragAndDrop, true); + window.removeEventListener('mouseup', extension.dragAndDrop, true); + + extension.dragAndDrop.active = false; + + extension.cursor.reset(); + + event.preventDefault(); + event.stopPropagation(); + } } else { - target.scrollLeft = x; - target.scrollTop = y; - } - - extension.request = requestAnimationFrame(extension.dragAndDrop.scroll); -}; - - -/*-------------------------------------------------------------- -# END ---------------------------------------------------------------*/ - -extension.dragAndDrop.end = function (event) { - cancelAnimationFrame(extension.request); - - extension.cursor.reset(); - - removeEventListener('mousemove', extension.dragAndDrop.move, true); - removeEventListener('mouseup', extension.dragAndDrop.end, true); -}; - - - - + var option = extension.storage.get('dragAndDrop'); - - - -/*-------------------------------------------------------------- -# TOUCHSCREEN ---------------------------------------------------------------*/ - -extension.touchscreen = { - mousedown: { - x: 0, - y: 0 - }, - offset: { - x: 0, - y: 0 - }, - scroll: { - x: 0, - y: 0 - }, - momentum: { - time: 0, - x: 0, - y: 0, - speedX: 0, - speedY: 0 - } -}; - - -/*-------------------------------------------------------------- -# START ---------------------------------------------------------------*/ - -extension.events.features.touchscreen = function (event) { - var data = extension.storage.items['touchscreen']; - - if (data) { - extension.cursor.set('all-scroll'); - - extension.touchscreen.mousedown.x = extension.cursor.x; - extension.touchscreen.mousedown.y = extension.cursor.y; - - extension.findContainer(extension.cursor.target); - - extension.touchscreen.scroll.x = extension.target.scrollLeft; - extension.touchscreen.scroll.y = extension.target.scrollTop; - - extension.touchscreen.move(event); - extension.touchscreen.scroll(); - - addEventListener('mousemove', extension.touchscreen.move, true); - - if ( - data.click || - data.middle || - data.context - ) { - addEventListener('mouseup', extension.touchscreen.end, true); + if (option !== 'disabled') { + window.addEventListener('mousedown', extension.dragAndDrop, true); } else { - addEventListener('keyup', extension.touchscreen.end, true); + window.removeEventListener('mousedown', extension.dragAndDrop, true); } } }; /*-------------------------------------------------------------- -# MOVE ---------------------------------------------------------------*/ - -extension.touchscreen.move = function (event) { - var now = performance.now(); - - extension.touchscreen.offset.x = extension.cursor.x - extension.touchscreen.mousedown.x; - extension.touchscreen.offset.y = extension.cursor.y - extension.touchscreen.mousedown.y; - - if (now - extension.touchscreen.momentum.time > 150) { - extension.touchscreen.momentum.x = extension.cursor.x; - extension.touchscreen.momentum.y = extension.cursor.y; - - extension.touchscreen.momentum.time = now; - } -}; - - -/*-------------------------------------------------------------- -# SCROLL +# INITIALIZATION --------------------------------------------------------------*/ -extension.touchscreen.scroll = function () { - var target = extension.target, - x = extension.touchscreen.scroll.x - extension.touchscreen.offset.x, - y = extension.touchscreen.scroll.y - extension.touchscreen.offset.y; +chrome.runtime.sendMessage('tab-connected', function (response) { + extension.hostname = response; - target.scrollLeft = x; - target.scrollTop = y; - - extension.request = requestAnimationFrame(extension.touchscreen.scroll); -}; - -extension.touchscreen.animation = function () { - var momentum = extension.touchscreen.momentum; - - if (momentum.speedX !== 0 || momentum.speedY !== 0) { - var target = extension.target; - - if (momentum.speedX > 0) { - momentum.speedX--; - } else if (momentum.speedX < 0) { - momentum.speedX++; + extension.storage.import(function () { + if (extension.storage.get('websites/' + extension.hostname + '/active') !== false) { + extension.automatic(); + extension.dragAndDrop(); } + }); - if (momentum.speedY > 0) { - momentum.speedY--; - } else if (momentum.speedY < 0) { - momentum.speedY++; + extension.storage.onchanged(function () { + if (extension.storage.get('websites/' + extension.hostname + '/active') !== false) { + extension.automatic(); + extension.dragAndDrop(); } - - target.scrollLeft -= momentum.speedX; - target.scrollTop -= momentum.speedY; - - extension.animationRequest = requestAnimationFrame(extension.touchscreen.animation); - } -}; - - -/*-------------------------------------------------------------- -# END ---------------------------------------------------------------*/ - -extension.touchscreen.end = function (event) { - extension.touchscreen.momentum.speedX = Math.min(Math.max(Math.floor((extension.cursor.x - extension.touchscreen.momentum.x) / 10), -40), 40); - extension.touchscreen.momentum.speedY = Math.min(Math.max(Math.floor((extension.cursor.y - extension.touchscreen.momentum.y) / 10), -40), 40); - - console.log(extension.touchscreen.momentum.speedX, extension.touchscreen.momentum.speedY); - - cancelAnimationFrame(extension.request); - - extension.touchscreen.animation(); - - extension.cursor.reset(); - - removeEventListener('mousemove', extension.touchscreen.move, true); - removeEventListener('mouseup', extension.touchscreen.end, true); -}; - - - - - - - - -/*-------------------------------------------------------------- -# ACTIVATION ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# ENABLE ---------------------------------------------------------------*/ - -extension.enable = function () { - extension.events.create('mouse'); - extension.events.create('keyboard'); -}; - -/*-------------------------------------------------------------- -# DISABLE ---------------------------------------------------------------*/ - -extension.disable = function () { - extension.events.remove('mouse'); - extension.events.remove('keyboard'); -}; - - - - - - - - -/*-------------------------------------------------------------- -# INITIALIZATION ---------------------------------------------------------------*/ - -extension.storage.onchanged(function (key, value) { - if (key === 'domains') { - if (value[extension.hostname] !== false) { - extension.enable(); - } else { - extension.disable(); - } - } -}); - -chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) { - if (message === 'init') { - if (window === window.top) { - sendResponse(extension.hostname); - } - } -}); - -chrome.runtime.sendMessage('get-tab-url', function (response) { - extension.hostname = response.url; - - extension.storage.import(function () { - if (!extension.storage.items.domains || extension.storage.items.domains[extension.hostname] !== false) { - extension.enable(); - } - }); + }); }); \ No newline at end of file diff --git a/manifest.json b/manifest.json index f73ee69..29ccc7a 100644 --- a/manifest.json +++ b/manifest.json @@ -2,21 +2,21 @@ "manifest_version": 3, "name": "Auto Scroll", "description": "__MSG_description__", - "version": "0.5", + "version": "1.0", "default_locale": "en", "icons": { - "16": "icons/16.png", - "32": "icons/32.png", - "48": "icons/48.png", - "128": "icons/128.png" + "16": "assets/icons/16.png", + "32": "assets/icons/32.png", + "48": "assets/icons/48.png", + "128": "assets/icons/128.png" + }, + "background": { + "service_worker": "background.js" + }, + "options_page": "options-page/index.html", + "action": { + "default_popup": "options-page/index.html" }, - "background": { - "service_worker": "background.js" - }, - "options_page": "ui/options.html", - "action": { - "default_popup": "ui/popup.html" - }, "content_scripts": [ { "all_frames": true, @@ -32,7 +32,11 @@ "run_at": "document_start" } ], + "host_permissions": [ + "" + ], "permissions": [ + "activeTab", "storage" ], "offline_enabled": true diff --git a/options-page/functions.js b/options-page/functions.js new file mode 100644 index 0000000..452023f --- /dev/null +++ b/options-page/functions.js @@ -0,0 +1,125 @@ +/*-------------------------------------------------------------- +>>> FUNCTIONS +---------------------------------------------------------------- +# Export settings +# Import settings +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# EXPORT SETTINGS +--------------------------------------------------------------*/ + +extension.exportSettings = function () { + if (location.href.indexOf('action=export-settings') !== -1) { + satus.render({ + component: 'modal', + variant: 'confirm', + content: 'areYouSureYouWantToExportTheData', + buttons: { + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + this.modalProvider.close(); + } + } + }, + ok: { + component: 'button', + text: 'ok', + on: { + click: function () { + try { + var blob = new Blob([JSON.stringify(satus.storage.data)], { + type: 'application/json;charset=utf-8' + }); + + chrome.permissions.request({ + permissions: ['downloads'] + }, function (granted) { + if (granted) { + chrome.downloads.download({ + url: URL.createObjectURL(blob), + filename: 'auto-scroll.json', + saveAs: true + }, function () { + setTimeout(function () { + close(); + }, 1000); + }); + } + }); + } catch (error) { + console.error(error); + } + } + } + } + } + }, extension.skeleton.rendered); + } +}; + + +/*-------------------------------------------------------------- +# IMPORT SETTINGS +--------------------------------------------------------------*/ + +extension.importSettings = function () { + if (location.href.indexOf('action=import-settings') !== -1) { + satus.render({ + component: 'modal', + variant: 'confirm', + content: 'areYouSureYouWantToImportTheData', + buttons: { + cancel: { + component: 'button', + text: 'cancel', + on: { + click: function () { + this.modalProvider.close(); + } + } + }, + ok: { + component: 'button', + text: 'ok', + on: { + click: function () { + var input = document.createElement('input'); + + input.type = 'file'; + + input.addEventListener('change', function () { + var file_reader = new FileReader(); + + file_reader.onload = function () { + var data = JSON.parse(this.result); + + for (var key in data) { + satus.storage.set(key, data[key]); + } + + setTimeout(function () { + chrome.runtime.sendMessage({ + action: 'import-settings' + }); + + setTimeout(function () { + close(); + }, 128); + }, 256); + }; + + file_reader.readAsText(this.files[0]); + }); + + input.click(); + } + } + } + } + }, extension.skeleton.rendered); + } +}; \ No newline at end of file diff --git a/options-page/index.css b/options-page/index.css new file mode 100644 index 0000000..9e96e4f --- /dev/null +++ b/options-page/index.css @@ -0,0 +1,78 @@ +/*-------------------------------------------------------------- +>>> OPTIONS PAGE +---------------------------------------------------------------- +# Tab +# Fonts +# Switch +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# TAB +--------------------------------------------------------------*/ + +body[tab] { + width: 100vw; + height: 100vh; + overflow: hidden; +} + +body[tab] .satus-base { + width: 100%; + height: 100%; +} + +body[tab] .satus-alert { + display: none; +} + + +/*-------------------------------------------------------------- +# FONTS +--------------------------------------------------------------*/ + +@font-face { + font-family: Roboto; + + src: url(../assets/fonts/Roboto-Regular.ttf); +} + +@font-face { + font-family: Roboto; + font-weight: 500; + + src: url(../assets/fonts/Roboto-Medium.ttf); +} + +@font-face { + font-family: Roboto; + font-weight: 700; + + src: url(../assets/fonts/Roboto-Bold.ttf); +} + + +/*-------------------------------------------------------------- +# SWITCH +--------------------------------------------------------------*/ + +.satus-alert--success { + overflow: hidden; + + padding: 0; +} + +.satus-alert--success>.satus-switch { + width: 100%; + height: 48px; + padding: 8px 12px; + + transition: background-color .3s cubic-bezier(.25, .8, .5, 1); + + --satus-switch-track: rgba(255, 255, 255, .24); + --satus-switch-track--checked: var(--satus-alert-foreground--success); + --satus-switch-thumb: rgba(255, 255, 255, .88); +} + +.satus-alert--success>.satus-switch:hover { + background-color: rgba(var(--satus-light), .04); +} \ No newline at end of file diff --git a/options-page/index.html b/options-page/index.html new file mode 100644 index 0000000..820de7b --- /dev/null +++ b/options-page/index.html @@ -0,0 +1,25 @@ + + + + + + Auto Scroll + + + + + + + + + + + \ No newline at end of file diff --git a/options-page/index.js b/options-page/index.js new file mode 100644 index 0000000..f65fad2 --- /dev/null +++ b/options-page/index.js @@ -0,0 +1,86 @@ +/*-------------------------------------------------------------- +>>> OPTIONS PAGE +---------------------------------------------------------------- +# Global variable +# Initialization +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# GLOBAL VARIABLE +--------------------------------------------------------------*/ + +var extension = { + skeleton: {} +}; + + +/*-------------------------------------------------------------- +# INITIALIZATION +--------------------------------------------------------------*/ + +satus.storage.import(function (items) { + var language = items.language; + + if (!language || language === 'default') { + language = window.navigator.language; + } + + satus.locale.import(language, function () { + chrome.tabs.query({ + active: true, + currentWindow: true + }, function (tabs) { + var tab = tabs[0]; + + if (tab.url) { + extension.hostname = new URL(tab.url).hostname; + } + + if ( + tab.url && + ( + tab.url.startsWith('about:') || + tab.url.startsWith('chrome') || + tab.url.startsWith('edge') || + tab.url.startsWith('https://addons.mozilla.org') || + tab.url.startsWith('https://chrome.google.com/webstore') || + tab.url.startsWith('https://microsoftedge.microsoft.com/addons') || + tab.url.startsWith('moz') || + tab.url.startsWith('view-source:') || + tab.url.endsWith('.pdf') + ) + ) { + extension.skeleton.main.layers.toolbar = { + component: 'alert', + variant: 'error', + text: function () { + return satus.locale.get('thePageHostnameIsProtectedByBrowser').replace('HOSTNAME', extension.hostname); + } + }; + } else { + extension.skeleton.main.layers.toolbar = { + component: 'alert', + variant: 'success', + + switch: { + component: 'switch', + text: extension.hostname, + storage: 'websites/' + extension.hostname + '/active', + value: true + } + }; + } + + satus.render(extension.skeleton); + + extension.exportSettings(); + extension.importSettings(); + }); + }, '_locales/'); +}); + +chrome.runtime.sendMessage('options-page-connected', function (response) { + if (response && response.isPopup === false) { + document.body.setAttribute('tab', ''); + } +}); \ No newline at end of file diff --git a/options-page/skeleton.js b/options-page/skeleton.js new file mode 100644 index 0000000..310db52 --- /dev/null +++ b/options-page/skeleton.js @@ -0,0 +1,522 @@ +/*-------------------------------------------------------------- +>>> SKELETON +---------------------------------------------------------------- +# Base +# Header +# Main +# Create +--------------------------------------------------------------*/ + +/*-------------------------------------------------------------- +# BASE +--------------------------------------------------------------*/ + +extension.skeleton = { + component: 'base' +}; + + +/*-------------------------------------------------------------- +# HEADER +--------------------------------------------------------------*/ + +extension.skeleton.header = { + component: 'header', + + sectionStart: { + component: 'section', + variant: 'align-start', + + back: { + component: 'button', + variant: 'icon', + attr: { + 'hidden': 'true' + }, + on: { + click: 'main.layers.back' + }, + + svg: { + component: 'svg', + attr: { + 'viewBox': '0 0 24 24', + 'fill': 'none', + 'stroke-width': '1.5', + 'stroke': 'currentColor' + }, + + path: { + component: 'path', + attr: { + 'd': 'M14 18l-6-6 6-6' + } + } + } + }, + title: { + component: 'span', + variant: 'title' + } + }, + sectionEnd: { + component: 'section', + variant: 'align-end', + + menu: { + component: 'button', + variant: 'icon', + on: { + click: { + component: 'modal', + variant: 'vertical-menu', + + language: { + component: 'select', + before: { + component: 'svg', + attr: { + 'viewBox': '0 0 24 24', + 'fill': 'var(--satus-primary)' + }, + + path: { + component: 'path', + attr: { + 'd': 'M12.9 15l-2.6-2.4c1.8-2 3-4.2 3.8-6.6H17V4h-7V2H8v2H1v2h11.2c-.7 2-1.8 3.8-3.2 5.3-1-1-1.7-2.1-2.3-3.3h-2c.7 1.6 1.7 3.2 3 4.6l-5.1 5L4 19l5-5 3.1 3.1.8-2zm5.6-5h-2L12 22h2l1.1-3H20l1.1 3h2l-4.5-12zm-2.6 7l1.6-4.3 1.6 4.3H16z' + } + } + }, + text: 'language', + on: { + change: function (name, value) { + var language = satus.storage.get('language'); + + if (!language || language === 'default') { + language = window.navigator.language; + } + + satus.locale.import(language, function () { + var layers = document.querySelector('.satus-layers'); + + extension.skeleton.main.layers.rendered.dispatchEvent(new CustomEvent('open')); + + satus.empty(layers.firstChild); + + satus.render(satus.last(layers.path), layers.firstChild, undefined, true); + }, '_locales/'); + } + }, + options: [{ + value: "en", + text: "English" + }, { + value: "es", + text: "Español (España)" + }, { + value: "es-419", + text: "Español (Latinoamérica)" + }, { + value: "es-US", + text: "Español (US)" + }, { + value: "ru", + text: "Русский" + }, { + value: "de", + text: "Deutsch" + }, { + value: "pt-PT", + text: "Português" + }, { + value: "pt", + text: "Português (Brasil)" + }, { + value: "fr", + text: "Français" + }, { + value: "pl", + text: "Polski" + }, { + value: "ja", + text: "日本語" + }, { + value: "af", + text: "Afrikaans" + }, { + value: "az", + text: "Azərbaycan" + }, { + value: "id", + text: "Bahasa Indonesia" + }, { + value: "ms", + text: "Bahasa Malaysia" + }, { + value: "bs", + text: "Bosanski" + }, { + value: "ca", + text: "Català" + }, { + value: "cs", + text: "Čeština" + }, { + value: "da", + text: "Dansk" + }, { + value: "et", + text: "Eesti" + }, { + value: "eu", + text: "Euskara" + }, { + value: "fil", + text: "Filipino" + }, { + value: "fr-CA", + text: "Français (Canada)" + }, { + value: "gl", + text: "Galego" + }, { + value: "hr", + text: "Hrvatski" + }, { + value: "zu", + text: "IsiZulu" + }, { + value: "is", + text: "Íslenska" + }, { + value: "it", + text: "Italiano" + }, { + value: "sw", + text: "Kiswahili" + }, { + value: "lv", + text: "Latviešu valoda" + }, { + value: "lt", + text: "Lietuvių" + }, { + value: "hu", + text: "Magyar" + }, { + value: "nl", + text: "Nederlands" + }, { + value: "no", + text: "Norsk" + }, { + value: "uz", + text: "O‘zbek" + }, { + value: "ro", + text: "Română" + }, { + value: "sq", + text: "Shqip" + }, { + value: "sk", + text: "Slovenčina" + }, { + value: "sl", + text: "Slovenščina" + }, { + value: "sr-Latn", + text: "Srpski" + }, { + value: "fi", + text: "Suomi" + }, { + value: "sv", + text: "Svenska" + }, { + value: "vi", + text: "Tiếng Việt" + }, { + value: "tr", + text: "Türkçe" + }, { + value: "be", + text: "Беларуская" + }, { + value: "bg", + text: "Български" + }, { + value: "ky", + text: "Кыргызча" + }, { + value: "kk", + text: "Қазақ Тілі" + }, { + value: "mk", + text: "Македонски" + }, { + value: "mn", + text: "Монгол" + }, { + value: "sr", + text: "Српски" + }, { + value: "uk", + text: "Українська" + }, { + value: "el", + text: "Ελληνικά" + }, { + value: "hy", + text: "Հայերեն" + }, { + value: "iw", + text: "עברית" + }, { + value: "ur", + text: "اردو" + }, { + value: "ar", + text: "العربية" + }, { + value: "fa", + text: "فارسی" + }, { + value: "ne", + text: "नेपाली" + }, { + value: "mr", + text: "मराठी" + }, { + value: "hi", + text: "हिन्दी" + }, { + value: "bn", + text: "বাংলা" + }, { + value: "pa", + text: "ਪੰਜਾਬੀ" + }, { + value: "gu", + text: "ગુજરાતી" + }, { + value: "ta", + text: "தமிழ்" + }, { + value: "te", + text: "తెలుగు" + }, { + value: "kn", + text: "ಕನ್ನಡ" + }, { + value: "ml", + text: "മലയാളം" + }, { + value: "si", + text: "සිංහල" + }, { + value: "th", + text: "ภาษาไทย" + }, { + value: "lo", + text: "ລາວ" + }, { + value: "my", + text: "ဗမာ" + }, { + value: "ka", + text: "ქართული" + }, { + value: "am", + text: "አማርኛ" + }, { + value: "km", + text: "ខ្មែរ" + }, { + value: "zh-CN", + text: "中文 (简体)" + }, { + value: "zh-TW", + text: "中文 (繁體)" + }, { + value: "zh-HK", + text: "中文 (香港)" + }, { + value: "ko", + text: "한국어" + }] + }, + export: { + component: 'button', + before: { + component: 'svg', + attr: { + 'viewBox': '0 0 24 24', + 'fill': 'none', + 'stroke': 'var(--satus-primary)', + 'stroke-linecap': 'round', + 'stroke-linejoin': 'round', + 'stroke-width': '2' + }, + + path: { + component: 'path', + attr: { + 'd': 'M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M17 8l-5-5-5 5M12 3v12' + } + } + }, + text: 'export', + on: { + click: function () { + if (location.href.indexOf('options-page/index.html?action=export-settings') !== -1) { + extension.exportSettings(); + } else { + chrome.tabs.create({ + url: 'options-page/index.html?action=export-settings' + }); + } + } + } + }, + import: { + component: 'button', + before: { + component: 'svg', + attr: { + 'viewBox': '0 0 24 24', + 'fill': 'none', + 'stroke': 'var(--satus-primary)', + 'stroke-linecap': 'round', + 'stroke-linejoin': 'round', + 'stroke-width': '2' + }, + + path: { + component: 'path', + attr: { + 'd': 'M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3' + } + } + }, + text: 'import', + on: { + click: function () { + if (location.href.indexOf('options-page/index.html?action=import-settings') !== -1) { + extension.importSettings(); + } else { + chrome.tabs.create({ + url: 'options-page/index.html?action=import-settings' + }); + } + } + } + } + } + }, + + svg: { + component: 'svg', + attr: { + 'viewBox': '0 0 24 24', + 'fill': 'currentColor' + }, + + circle_1: { + component: 'circle', + attr: { + 'cx': '12', + 'cy': '5.25', + 'r': '1' + } + }, + circle_2: { + component: 'circle', + attr: { + 'cx': '12', + 'cy': '12', + 'r': '1' + } + }, + circle_3: { + component: 'circle', + attr: { + 'cx': '12', + 'cy': '18.75', + 'r': '1' + } + } + } + } + } +}; + + +/*-------------------------------------------------------------- +# MAIN +--------------------------------------------------------------*/ + +extension.skeleton.main = { + component: 'main', + + layers: { + component: 'layers', + on: { + open: function () { + var skeleton = satus.last(this.path), + section = this.baseProvider.skeleton.header.sectionStart, + title = satus.manifest().name; + + if (skeleton.parentSkeleton) { + if (skeleton.parentSkeleton.label) { + title = skeleton.parentSkeleton.label.text; + } else if (skeleton.parentSkeleton.text) { + title = skeleton.parentSkeleton.text; + } + } + + section.back.rendered.hidden = this.path.length <= 1; + section.title.rendered.innerText = satus.locale.get(title); + + var vertical_menu = document.querySelector('.satus-modal--vertical-menu'); + + if (vertical_menu) { + vertical_menu.close(); + } + } + }, + + toolbar: {}, + section: { + component: 'section', + class: 'satus-section--card', + + autoScroll: { + component: 'select', + text: 'automatic', + value: 'scroll_wheel', + options: [{ + text: 'disabled', + value: 'disabled' + }, { + text: 'scrollWheel', + value: 'scroll_wheel' + }] + }, + dragAndDrop: { + component: 'select', + text: 'dragDrop', + options: [{ + text: 'disabled', + value: 'disabled' + }, { + text: 'leftMouseButton', + value: 'left_mouse_button' + }, { + text: 'scrollWheel', + value: 'scroll_wheel' + }] + } + } + } +}; \ No newline at end of file diff --git a/py/locale.py b/py/locale.py index 7d846d5..4e4ae24 100644 --- a/py/locale.py +++ b/py/locale.py @@ -1,22 +1,23 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ # >>> TABLE OF CONTENTS: -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ # 1.0 Import modules # 2.0 Lower camel case # 3.0 Get list of files # 4.0 Add item # 5.0 Remove item -# 6.0 Decode -# 7.0 Add locales -# 8.0 Initialization -# -------------------------------------------------------------- +# 6.0 Change key +# 7.0 Decode +# 8.0 Upgrade +# 9.0 Initialization +# ------------------------------------------------------------------------------ -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ # 1.0 IMPORT MODULES -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ import io import json @@ -26,9 +27,9 @@ import sys -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ # 2.0 LOWER CAMEL CASE -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ def lowerCamelCase(string): string = re.sub(r"(-|_)+", ' ', string).title() @@ -37,21 +38,21 @@ def lowerCamelCase(string): return string[0].lower() + string[1:] -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ # 3.0 GET LIST OF FILES -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ -def getListOfFiles(dirName): +def getListOfFiles(path): allFiles = list() - for entry in os.listdir(dirName): - fullPath = os.path.join(dirName, entry) + for entry in os.listdir(path): + fullPath = os.path.join(path, entry) if not os.path.isdir(fullPath): allFiles.append(fullPath) - for entry in os.listdir(dirName): - fullPath = os.path.join(dirName, entry) + for entry in os.listdir(path): + fullPath = os.path.join(path, entry) if os.path.isdir(fullPath): allFiles = allFiles + getListOfFiles(fullPath) @@ -59,9 +60,9 @@ def getListOfFiles(dirName): return allFiles -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ # 4.0 ADD ITEM -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ def addItem(allFiles): message = input('Enter your message: ') @@ -75,14 +76,13 @@ def addItem(allFiles): data[camelized_message] = {'message': message} json_file.seek(0) - json.dump(data, json_file, ensure_ascii=False, indent=4, - sort_keys=True) + json.dump(data, json_file, ensure_ascii=False, indent=4, sort_keys=True) json_file.truncate() -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ # 5.0 REMOVE ITEM -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ def removeItem(allFiles): key = input('Enter your key (lowerCamelCase): ') @@ -100,9 +100,31 @@ def removeItem(allFiles): json_file.truncate() -# -------------------------------------------------------------- -# 6.0 DECODE -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ +# 6.0 CHANGE KEY +# ------------------------------------------------------------------------------ + +def changeKey(allFiles): + old_key = input('Enter key: ') + new_key = input('Enter new key: ') + + for keyFile in allFiles: + with open(keyFile, 'r+') as file: + data = json.load(file) + + if old_key in data: + data[new_key] = data[old_key] + + del data[old_key] + + file.seek(0) + json.dump(data, file, ensure_ascii=False, indent=4, sort_keys=True) + file.truncate() + + +# ------------------------------------------------------------------------------ +# 7.0 DECODE +# ------------------------------------------------------------------------------ def decodeCharacters(allFiles): for keyFile in allFiles: @@ -115,11 +137,11 @@ def decodeCharacters(allFiles): json_file.truncate() -# -------------------------------------------------------------- -# 7.0 ADD LOCALES -# -------------------------------------------------------------- +# ------------------------------------------------------------------------------ +# 8.0 UPGRADE +# ------------------------------------------------------------------------------ -def addLocales(): +def upgrade(): locales = [ 'am', 'ar', @@ -176,24 +198,49 @@ def addLocales(): 'zh_TW' ] + if os.path.exists('../_locales/en/messages.json'): + file = open('../_locales/en/messages.json', 'r+') + + default_locale = json.load(file) + + file.close() + else: + default_locale = {} + for locale in locales: - if not os.path.exists('../_locales/' + locale): - pathlib.Path('../_locales/' + locale).mkdir(parents=True, - exist_ok=True) + path = '../_locales/' + locale - file = io.open('../_locales/' + locale + '/messages.json', - mode='w', encoding='utf-8') + if not os.path.exists(path): + pathlib.Path(path).mkdir(parents=True, exist_ok=True) - file.write('{}') + file = io.open(path + '/messages.json', mode='w', encoding='utf-8') + json.dump(default_locale, file, ensure_ascii=False, indent=4, sort_keys=True) + file.close() + else: + with open(path + '/messages.json', 'r+') as file: + data = json.load(file) + + file.seek(0) + + for key in default_locale: + if (key in data) == False: + data[key] = default_locale[key] + + json.dump(data, file, ensure_ascii=False, indent=4, sort_keys=True) + + file.truncate() + + file.close() - print(locale) +# ------------------------------------------------------------------------------ +# 9.0 INITIALIZATION +# ------------------------------------------------------------------------------ -# -------------------------------------------------------------- -# 8.0 INITIALIZATION -# -------------------------------------------------------------- +if not os.path.exists('../_locales/'): + pathlib.Path('../_locales/').mkdir(parents=True, exist_ok=True) allFiles = getListOfFiles('../_locales/') @@ -204,5 +251,7 @@ def addLocales(): removeItem(allFiles) elif arg == '-decode': decodeCharacters(allFiles) - elif arg == '-generate': - addLocales() \ No newline at end of file + elif arg == '-change-key': + changeKey(allFiles) + elif arg == '-upgrade': + upgrade() \ No newline at end of file diff --git a/ui/fonts/OpenSans-Medium.ttf b/ui/fonts/OpenSans-Medium.ttf deleted file mode 100644 index 6b41918..0000000 Binary files a/ui/fonts/OpenSans-Medium.ttf and /dev/null differ diff --git a/ui/fonts/OpenSans-Regular.ttf b/ui/fonts/OpenSans-Regular.ttf deleted file mode 100644 index 3a29f26..0000000 Binary files a/ui/fonts/OpenSans-Regular.ttf and /dev/null differ diff --git a/ui/options.html b/ui/options.html deleted file mode 100644 index 7d98a9f..0000000 --- a/ui/options.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - Auto Scroll - - - - - - - - - - \ No newline at end of file diff --git a/ui/popup.html b/ui/popup.html deleted file mode 100644 index e5af895..0000000 --- a/ui/popup.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - Frame By Frame - - - - - - - - - - \ No newline at end of file diff --git a/ui/satus/satus.css b/ui/satus/satus.css deleted file mode 100644 index 3836772..0000000 --- a/ui/satus/satus.css +++ /dev/null @@ -1,1664 +0,0 @@ - -/*-------------------------------------------------------------- ->>> THEMES: ----------------------------------------------------------------- -# Default -# Dark -# Black ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# DEFAULT ---------------------------------------------------------------*/ - -body { - --satus-contrast: 0, 0, 0; - --satus-primary: #f6b465; - --satus-hover: rgba(var(--satus-contrast), .04); - - --satus-alert-error-background: #fde6e6; - --satus-alert-error-border: #ecd7d7; - --satus-alert-error-color: #ad5f5f; - - --satus-checkbox--background: rgb(90, 90, 73, .08); - --satus-checkbox--border: rgb(90, 90, 73, .16); - --satus-checkbox--mark: #fff; - - --satus-divider: rgba(var(--satus-contrast),.1); - - --satus-header-background: #fff; - --satus-header-border: rgba(var(--satus-contrast),.1); - --satus-header-text: #8f8f8f; - - --satus-layers-background: #f6f5f4; - --satus-layers-text: #8f8f8f; - - --satus-modal-background: #f6f6f4; - --satus-modal-border: rgba(var(--satus-contrast), .1); - --satus-modal-text: #8f8f8f; - - --satus-section-card-background: #fff; - --satus-section-card-border: rgba(var(--satus-contrast),.1); - - --satus-select-background: #f6f6f4; - --satus-select-text: #8f8f8f; - - --satus-switch-background: rgba(var(--satus-contrast),.08); - --satus-switch-track: #e0e0e0; - --satus-switch-track--active: var(--satus-primary); - --satus-switch-thumb: #fff; - - --satus-tabs-background: #e8e8e3; - --satus-tabs-foreground: #fff; - --satus-tabs-border: rgba(var(--satus-contrast), .1); - - --satus-text-field--background: #e8e8e3; - --satus-text-field--border: #d6d6cd; - --satus-text-field--text: #8f8f8f; - - - --satus-tooltip: rgba(var(--satus-contrast),.4); - --satus-sortable-ghost: rgba(var(--satus-contrast), .80); - --satus-sortable-background: rgba(var(--satus-contrast), .08); - --satus-sortable-text: currentColor; -} - - -/*-------------------------------------------------------------- -# DARK ---------------------------------------------------------------*/ - -body[data-theme=dark] { - --satus-contrast: 255, 255, 255; - --satus-primary: #8f8f8f; - --satus-switch-background: rgba(var(--satus-contrast),.08); - --satus-header-background: #1f1f1f; - --satus-header-border: rgba(var(--satus-contrast),.08); - --satus-header-text: #ccc; - --satus-layers-background: #000; - --satus-layers-text: #ccc; - --satus-section-card-background: #1e1e1e; - --satus-section-card-border: rgba(var(--satus-contrast),.08); - --satus-modal-background: #212121; - --satus-modal-border: rgba(var(--satus-contrast),.08); - --satus-modal-text: #ccc; - --satus-hover: rgba(var(--satus-contrast), .05); - --satus-text-field--background: #333333; - --satus-text-field--border: #525252; - --satus-text-field--text: #ccc; - --satus-switch-track: #111; - --satus-switch-track--active: var(--satus-primary); - --satus-switch-thumb: #ddd; - --satus-tooltip: rgba(var(--satus-contrast),.4); - --satus-sortable-ghost: rgba(var(--satus-contrast), .8); - --satus-sortable-background: rgba(var(--satus-contrast), .1); - --satus-sortable-text: #fff; - --satus-divider: rgba(var(--satus-contrast),.08); - --satus-tabs-background: #111; - --satus-tabs-foreground: #2e2e2e; - --satus-tabs-border: #2f2f2f; - --satus-checkbox--background: rgb(var(--satus-contrast), .08); - --satus-checkbox--border: #2f2f2f; - --satus-checkbox--mark: #fff; - --satus-alert-error-background: #501616; - --satus-alert-error-border: #6f1f1f; - --satus-alert-error-color: #cf7777; -} - - -/*-------------------------------------------------------------- -# BLACK ---------------------------------------------------------------*/ - -body[data-theme=black] { - --satus-contrast: 255, 255, 255; - --satus-primary: #8f8f8f; - --satus-switch-background: rgba(var(--satus-contrast),.08); - --satus-header-background: #000; - --satus-header-border: rgba(var(--satus-contrast),.16); - --satus-header-text: #ccc; - --satus-layers-background: #000; - --satus-layers-text: #ccc; - --satus-section-card-background: #000; - --satus-section-card-border: rgba(var(--satus-contrast),.16); - --satus-modal-background: #000; - --satus-modal-border: rgba(var(--satus-contrast),.16); - --satus-modal-text: #ccc; - --satus-hover: rgba(var(--satus-contrast), .05); - --satus-text-field--background: #333333; - --satus-text-field--border: #525252; - --satus-text-field--text: #ccc; - --satus-switch-track: rgba(var(--satus-contrast),.16); - --satus-switch-track--active: var(--satus-primary); - --satus-switch-thumb: #ddd; - --satus-tooltip: rgba(var(--satus-contrast),.4); - --satus-sortable-ghost: rgba(var(--satus-contrast), .8); - --satus-sortable-background: rgba(var(--satus-contrast), .1); - --satus-sortable-text: #fff; - --satus-divider: rgba(var(--satus-contrast),.08); - --satus-tabs-background: #111; - --satus-tabs-foreground: #2e2e2e; - --satus-tabs-border: #2f2f2f; - --satus-checkbox--background: rgb(var(--satus-contrast), .08); - --satus-checkbox--border: #2f2f2f; - --satus-checkbox--mark: #fff; - --satus-alert-error-background: #501616; - --satus-alert-error-border: #6f1f1f; - --satus-alert-error-color: #cf7777; -} -/*-------------------------------------------------------------- ->>> ELEMENTS: ----------------------------------------------------------------- -# Reset -# Attributes - # Hidden ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# RESET ---------------------------------------------------------------*/ - -:where([class^=satus]:not(iframe, canvas, img, svg, video, svg *, symbol *)) { - display: revert; - all: unset; -} - -:where([class^=satus]:not(iframe, canvas, img, svg, video, svg *, symbol *)) { - box-sizing: border-box; -} - - -/*-------------------------------------------------------------- -# ATTRIBUTES ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# HIDDEN ---------------------------------------------------------------*/ - -[class^=satus][hidden] { - display: none; -} -/*-------------------------------------------------------------- ->>> PLUVIAM ---------------------------------------------------------------*/ - -.satus-pluviam { - position: absolute; - transform: scale(0); - animation-name: pluviam; - animation-duration: 1000ms; - opacity: var(--satus-pluviam-opacity, .08); - border-radius: 50%; - background: var(--satus-pluviam-background, #000); - animation-fill-mode: forwards; -} - -@keyframes pluviam { - 0% { - transform: scale(0); - opacity: var(--satus-pluviam-opacity, .08); - } - 70% { - transform: scale(.8); - opacity: var(--satus-pluviam-opacity, .08); - } - 100% { - transform: scale(1); - opacity: 0; - } -} -/*-------------------------------------------------------------- ->>> SORTABLE ---------------------------------------------------------------*/ - -.satus-sortable__chosen { - color: var(--satus-sortable-text) !important; - background-color: var(--satus-sortable-background) !important; -} - -.satus-sortable__ghost { - position: fixed !important; - z-index: 999 !important; - top: 0 !important; - left: 0 !important; - pointer-events: none !important; - box-shadow: 0 1px 3px rgb(0, 0, 0, .2), 0 4px 8px rgb(0, 0, 0, .1), inset 0 0 0 1px rgb(0, 0, 0, .16); - will-change: transform !important; - opacity: .8 !important; -} -/*-------------------------------------------------------------- ->>> CONTEXT MENU ---------------------------------------------------------------*/ - -.satus-modal--contextmenu .satus-modal__scrim { - background: none; - backdrop-filter: none; - animation: none; - visibility: visible; - opacity: 1; - transform: none; -} - -.satus-modal--contextmenu .satus-modal__surface { - position: absolute; - margin: 0; - box-sizing: border-box; - min-width: 200px; - max-width: 200px; - padding: 4px 0; - border-radius: 4px; - box-shadow: none; - animation: none; - visibility: visible; - opacity: 1; - transform: none; -} - -.satus-modal--contextmenu .satus-modal__surface > * { - -} - -.satus-modal--contextmenu .satus-modal__surface>* { - display: flex; - height: 32px; - padding: 0 16px; - align-items: center; -} - -.satus-modal--contextmenu .satus-modal__surface .satus-button svg { - width: 20px; - height: 18px; - margin: 0 14px 0 0; - opacity: .75; - fill: none; - stroke: var(--satus-primary); - flex: 0 0 20px; -} - -.satus-modal--contextmenu .satus-modal__surface .satus-button .satus-span { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} -/*-------------------------------------------------------------- ->>> BASE ---------------------------------------------------------------*/ - -.satus-base { - display: flex; - flex-direction: column; - width: 100%; - height: 100% -} -/**/ - -.satus-aside { - color: var(--satus-aside-text); - background: var(--satus-aside-background); - box-sizing: border-box; -} -/*-------------------------------------------------------------- ->>> RADIO ---------------------------------------------------------------*/ -/*-------------------------------------------------------------- ->>> CHECKBOX ---------------------------------------------------------------*/ - -.satus-checkbox { - position: relative; - font: inherit; - display: flex; - color: inherit; - border: none; - background: transparent; - appearance: none; - align-items: center; - justify-content: flex-start; -} - -.satus-checkbox:hover { - cursor: pointer; - background-color: var(--satus-hover); -} - -.satus-checkbox:focus { - outline: none; -} - -.satus-checkbox__content { - display: block; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -} - -.satus-checkbox::before { - display: flex; - min-width: 16px; - width: 16px; - height: 16px; - margin: 0 12px 0 0; - content: ''; - border: 1px solid var(--satus-checkbox--border); - border-radius: 6px; - background: var(--satus-checkbox--background); - align-items: center; - justify-content: center; -} - -.satus-checkbox[data-value=true]::before { - background: var(--satus-primary); -} - -.satus-checkbox[data-value=true]::after { - position: absolute; - top: 20px; - left: 20px; - width: 8px; - height: 4px; - content: ''; - transform: rotate(-45deg); - border: 2px solid var(--satus-checkbox--mark); - border-top: none; - border-right: none; -} -/*-------------------------------------------------------------- ->>> SELECT ---------------------------------------------------------------*/ - -.satus-select { - position: relative; - display: flex; - cursor: pointer; - align-items: center; - justify-content: space-between; -} - -.satus-select:hover { - background-color: var(--satus-hover); -} - -.satus-select>span:nth-child(2) { - display: flex; - align-items: center; -} - -.satus-select>span:nth-child(2)>svg { - width: 20px; - height: 18px; - margin: 0 14px 0 0; - opacity: .75; -} - -.satus-select>span:nth-child(3) { - margin-left: 16px; - text-align: right; - opacity: .75; -} - -.satus-select select { - font: inherit; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - margin: 0; - padding: inherit; - opacity: 0; - border: none; - outline: none; - appearance: none; - z-index: 1; -} - -.satus-select option { - color: var(--satus-select-text); - background: var(--satus-select-background); -} -/*-------------------------------------------------------------- ->>> SHORTCUT: ----------------------------------------------------------------- -# ---------------------------------------------------------------*/ - -.satus-shortcut { - justify-content: space-between; -} - -.satus-shortcut__value { - font-size: 11px; - display: flex; - text-transform: uppercase; - align-items: center; -} - -.satus-shortcut__actions { - display: flex; - justify-content: flex-end; -} - -.satus-shortcut__actions .satus-button { - height: 32px; - margin: 8px 4px 0; - border-radius: 8px; - background: rgba(0, 0, 0, .15); -} - -.satus-shortcut__actions .satus-button:hover { - background: rgba(0, 0, 0, .25); -} - -.satus-shortcut__primary { - display: flex; - box-sizing: border-box; - width: 100%; - height: 68px; - padding: 16px; - background: rgba(0, 0, 0, .16); - align-items: center; -} - -.satus-shortcut__key { - display: flex; - box-sizing: border-box; - min-width: 32px; - height: 32px; - padding: 4px 8px; - border-radius: 4px; - background: #fff; - box-shadow: 0 1px 3px rgba(0, 0, 0, .15), inset 0 -3px 0 rgba(0, 0, 0, .1); - align-items: center; - justify-content: center; -} - -.satus-shortcut__value>.satus-shortcut__key { - font-size: 14px; - min-width: 24px; - height: 24px; -} - -.satus-shortcut__plus { - position: relative; - width: 12px; - height: 12px; - margin: 8px; -} - -.satus-shortcut__plus::before { - position: absolute; - top: 0; - left: 5px; - width: 2px; - height: 12px; - content: ''; - background-color: #aaa; -} - -.satus-shortcut__plus::after { - position: absolute; - top: 5px; - left: 0; - width: 12px; - height: 2px; - content: ''; - background-color: #aaa; -} - -.satus-shortcut__mouse { - position: relative; - display: flex; - width: 28px; - height: 36px; - border-radius: 50%; - border-top-left-radius: 12px; - border-top-right-radius: 12px; - background: #fff; - box-shadow: 0 1px 3px rgba(0, 0, 0, .15), inset 0 -3px 0 rgba(0, 0, 0, .1); -} - -.satus-shortcut__value>.satus-shortcut__mouse { - width: 22px; - height: 28px; -} - -.satus-shortcut__mouse>div { - position: absolute; - top: 0; - left: calc(50% - 1px); - width: 2px; - height: 11px; - border-radius: 2px; - background: #ccc; -} - -.satus-shortcut__mouse::before { - position: absolute; - top: -16%; - right: 14%; - width: 2px; - height: 60%; - content: ''; - background: #f96754; -} - -.satus-shortcut__mouse.false::before { - top: -6%; -} - -.satus-shortcut__mouse.false::after { - position: absolute; - top: -20%; - right: calc(14% - 4px); - width: 0; - height: 0; - content: ''; - border-right: 5px solid transparent; - border-bottom: 8px solid #f96754; - border-left: 5px solid transparent; -} - -.satus-shortcut__mouse.true::after { - position: absolute; - top: 40%; - right: calc(14% - 4px); - width: 0; - height: 0; - content: ''; - border-top: 8px solid #f96754; - border-right: 5px solid transparent; - border-left: 5px solid transparent; -} - -.satus-shortcut__mouse.click::before { - position: absolute; - top: 0; - left: -1px; - width: 10px; - height: 10px; - content: ''; - border-radius: 50%; - background: #f96754; -} - -.satus-shortcut__mouse.middle::before { - position: absolute; - top: 0; - left: 50%; - width: 10px; - height: 10px; - content: ''; - border-radius: 50%; - background: #f96754; - z-index: 1; - transform: translateX(-50%); -} - -.satus-shortcut__mouse.context::before { - position: absolute; - top: 0; - left: 15px; - width: 10px; - height: 10px; - content: ''; - border-radius: 50%; - background: #f96754; -} - -.satus-section_shortcut { - width: 100%; - margin: 8px 0 0; - justify-content: flex-end; -} - -.satus-button_shortcut { - font-weight: 500; - overflow: hidden; - height: 28px; - min-height: 28px; - margin-right: 2px; - padding: 4px 8px; - text-transform: uppercase; - color: #f96754; - border-radius: 4px; -} -/*-------------------------------------------------------------- ->>> SWITCH ----------------------------------------------------------------- -# Container -# Track -# Thumb ---------------------------------------------------------------*/ - - -/*-------------------------------------------------------------- -# CONTAINER ---------------------------------------------------------------*/ - -.satus-switch { - font: inherit; - display: flex; - transition: background-color 75ms; - color: inherit; - border: none; - outline: none; - background-color: transparent; - justify-content: space-between; - align-items: center; -} - -.satus-switch:hover { - cursor: pointer; -} - -.satus-switch__content { - display: flex; - align-items: center; -} - -.satus-switch__content>svg { - width: 20px; - height: 18px; - margin: 0 14px 0 0; - opacity: .75; -} - - -/*-------------------------------------------------------------- -# TRACK ---------------------------------------------------------------*/ - -.satus-switch>i { - width: 32px; - height: 18px; - transition: background-color 150ms; - border-radius: 18px; - background-color: var(--satus-switch-track); - flex: 0 0 32px; -} - -.satus-section--card .satus-switch>i { - margin-left: 16px; -} - -.satus-switch[data-value='true']>i { - background-color: var(--satus-switch-track--active); -} - - -/*-------------------------------------------------------------- -# THUMB ---------------------------------------------------------------*/ - -.satus-switch>i::before { - display: block; - width: 14px; - height: 14px; - margin: 2px; - content: ''; - transition: transform 150ms cubic-bezier(.4, 0, .2, 1); - border-radius: 50%; - background-color: var(--satus-switch-thumb); - will-change: transform; -} - -.satus-switch[data-value='true']>i::before { - transform: translateX(14px); -} -/*-------------------------------------------------------------- ->>> LAYERS ---------------------------------------------------------------*/ - -.satus-layers { - position: relative; - overflow: hidden; - color: var(--satus-layers-text); - background: var(--satus-layers-background); - flex: 1; -} - -.satus-layer { - position: absolute; - top: 0; - left: 0; - display: flex; - overflow-y: auto; - flex-direction: column; - box-sizing: border-box; - width: 100%; - height: 100%; - padding: 0 12px; - align-content: center; -} -/*-------------------------------------------------------------- -# INPUT ---------------------------------------------------------------*/ - -.satus-input[type=text], -.satus-input[type=password] { - font: inherit; - box-sizing: border-box; - width: 100%; - margin: 0; - padding: 6px 8px; - color: var(--satus-text-field--text, inherit); - border: none; - outline: none; - background: none; - appearance: none; - font-size: 16px; - margin: 8px 0; - border: 1px solid var(--satus-text-field--border); - border-radius: 4px; - background-color: var(--satus-text-field--background); -} -/*-------------------------------------------------------------- ->>> MENUBAR ---------------------------------------------------------------*/ - -.satus-menubar { - display: flex; -} - -.satus-menubar, -.satus-menubar ul { - margin: 0; - padding: 0; - list-style: none; - color: var(--satus-menubar-text); - background: var(--satus-menubar-background); -} - -.satus-menubar li { - position: relative; -} - -.satus-menubar li:focus, -.satus-menubar li:hover { - background: var(--satus-menubar-hover); -} - -.satus-menubar>li ul { - position: absolute; - min-width: 126px; -} - -.satus-menubar>li>ul ul { - top: 0; - left: 100%; -} - -.satus-menubar li>ul { - position: absolute; - display: none; -} - -.satus-menubar li>*:not(ul):focus+ul, -.satus-menubar li>*:not(ul):hover+ul, -.satus-menubar li>ul:hover { - display: block; -} - -.satus-menubar li> :not(ul) { - font-size: 14px; - display: flex; - width: 100%; - height: 32px; - align-items: center; -} -/*-------------------------------------------------------------- -# MAIN ---------------------------------------------------------------*/ - -.satus-main { - color: var(--satus-main-text); - background: var(--satus-main-background); - overflow-y: auto; - box-sizing: border-box; -} -/*-------------------------------------------------------------- -# SCROLLBAR ---------------------------------------------------------------*/ - -::-webkit-scrollbar { - width: 4px; -} - -::-webkit-scrollbar:hover { - width: 8px; -} - -::-webkit-scrollbar-thumb { - background: rgba(var(--satus-contrast), .3); -} -/*-------------------------------------------------------------- ->>> TEXTAREA ---------------------------------------------------------------*/ - -.satus-textarea { - position: relative; - display: flex; - overflow: hidden; - color: var(--satus-textarea-color, inherit); - background: var(--satus-textarea-background); -} - -.satus-textarea textarea { - font-size: inherit; - line-height: 1.2; - overflow: auto; - width: 100%; - height: 100%; - padding: 0; - resize: none; - white-space: pre; - word-break: break-all; - color: inherit; - border: none; - outline: none; - background: transparent; - overflow-wrap: normal; -} - -.satus-textarea__line-number { - padding: 0 16px 0 8px; - opacity: .5; -} - -.satus-textarea__line-number>span { - font-size: inherit; - line-height: 1.2; - display: block; - width: 100%; - text-align: right; -} -/*-------------------------------------------------------------- ->>> DIVIDER ---------------------------------------------------------------*/ - -.satus-divider { - height: 1px; - margin: 16px 0 12px; - background: var(--satus-divider); -} -/*-------------------------------------------------------------- ->>> TEXT FIELD ---------------------------------------------------------------*/ - -.satus-text-field { - position: relative; - padding: 0 16px; - background-color: var(--satus-text-field--background); - border-radius: 8px; - color: var(--satus-text-field--text); - overflow: hidden; - display: flex; -} - -.satus-text-field__pre { - display: flex; - position: relative; - height: 100%; - margin: 0; - padding: 0; - overflow: hidden; - align-items: center; - flex: 1; -} - -.satus-text-field__input { - font: inherit; - position: absolute; - top: 0; - left: 0; - width: 100%; - min-width: 0; - max-width: none; - height: 100%; - min-height: 0; - max-height: none; - margin: 0; - padding: 0; - opacity: 0; - border: none; - appearance: none; - z-index: 9; -} - -.satus-text-field__hidden-text { - position: absolute; - pointer-events: none; - opacity: 0; -} - -.satus-text-field__text { - position: absolute; - top: 0; - left: 0; - display: flex; - height: 100%; - margin: 0; - align-items: center; -} - -.satus-text-field__cursor { - position: absolute; - top: 6px; - left: 0; - display: none; - width: 2px; - height: 25px; - animation: blink 1s step-end 8; - background: #fa0; -} - -.satus-text-field__selection { - position: absolute; - top: 5px; - left: 0; - display: none; - width: 0; - height: 25px; - border: 1px solid rgba(255, 255, 255, .2); - border-radius: 3px; - background: rgba(255, 255, 255, .1); -} - -.satus-text-field__input:focus + * + * + * + .satus-text-field__cursor, -.satus-text-field__selection:not([disabled]) { - display: block; -} - -@keyframes blink { - from, - to { - opacity: 1; - } - 50% { - opacity: 0; - } -} - - -/*-------------------------------------------------------------- -# SYNTAX HIGHLIGHTING ---------------------------------------------------------------*/ - -.satus-text-field__text>.group { - color: #47ff47; - background-color: rgb(71, 255, 71, .16); -} - -.satus-text-field__text>.character-class { - color: #ffc247; - background-color: rgb(255, 170, 0, .16); -} - -.satus-text-field__text>.quantifier { - color: #47c2ff; - background-color: rgb(71, 194, 255, .16); -} - -.satus-text-field__text>.anchor { - color: #47c2ff; - background-color: rgb(71, 194, 255, .16); -} - -.satus-text-field__text>.metasequence { - color: #47ff47; - background-color: rgb(71, 255, 71, .16); -} - -.satus-text-field__text>.text { - color: #c4c4d4; - background-color: rgb(196, 196, 212, .16); -} -/*-------------------------------------------------------------- ->>> TABS ---------------------------------------------------------------*/ - -.satus-tabs { - display: flex; - height: 26px !important; -} - -.satus-tabs__content { - position: relative; - overflow: hidden; - width: 100%; - height: 100%; - border: 2px solid var(--satus-tabs-background); - border-radius: 4px; - background: var(--satus-tabs-background); - display: flex; -} - -.satus-tabs__selection { - position: absolute; - z-index: 0; - top: 0; - left: 0; - height: 100%; - transition: left .25s; - border-radius: 4px; - background: var(--satus-tabs-foreground); - box-sizing: border-box; - border: 1px solid var(--satus-tabs-border); -} - -.satus-tabs__button { - font: inherit; - position: relative; - z-index: 1; - overflow: hidden; - height: 100%; - padding: 0 4px; - white-space: nowrap; - text-overflow: ellipsis; - color: inherit; - border: none; - background: transparent; - flex: 1; - text-align: center; -} - -.satus-tabs__button:hover { - cursor: pointer; -} -/*-------------------------------------------------------------- ->>> ALERT ---------------------------------------------------------------*/ - -.satus-alert { - display: flex; - box-sizing: border-box; - min-height: 48px; - margin: 8px 0 0; - padding: 8px 16px; - border-radius: 8px; - align-items: center; -} - -.satus-alert--error { - color: var(--satus-alert-error-color); - border: 1px solid var(--satus-alert-error-border); - background: var(--satus-alert-error-background); -} -/*-------------------------------------------------------------- ->>> SLIDER ---------------------------------------------------------------*/ - -.satus-slider { - box-sizing: border-box; - width: 100%; - padding: 8px 16px 0; - outline: none; -} - -.satus-slider__container { - position: relative; - display: block; - width: 100%; - height: 32px; -} - -.satus-slider__track { - position: absolute; - top: 50%; - left: 0; - width: 100%; - height: 2px; - transform: translateY(-50%); -} - -.satus-slider__track::before { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - content: ''; - opacity: .24; - background: var(--satus-primary); -} - -.satus-slider__handle:focus::after { - position: absolute; - top: -2px; - left: 50%; - display: block; - padding: 1px 4px; - content: attr(data-value); - transform: translate(-50%, -100%); - color: #fff; - border-radius: 4px; - background: var(--satus-primary); -} - -.satus-slider__track-fill { - position: absolute; - top: 0; - left: 0; - height: 100%; - background: var(--satus-primary); -} - -.satus-slider__handle { - position: absolute; - top: 50%; - left: 0; - width: 10px; - height: 10px; - transform: translate(-50%, -50%); - border-radius: 50%; - background: var(--satus-primary); -} - -.satus-slider__handle::before { - position: absolute; - top: 50%; - left: 50%; - width: 1px; - height: 1px; - content: ''; - transition: .2s; - transform: translate(-50%, -50%) scale(1); - opacity: 0; - border-radius: 50%; - background: var(--satus-primary); -} - -.satus-slider:focus .satus-slider__handle::before { - transform: translate(-50%, -50%) scale(26); - opacity: .24; -} -/*-------------------------------------------------------------- ->>> COLOR PICKER: ----------------------------------------------------------------- -# Button -# Modal ---------------------------------------------------------------*/ - - -/*-------------------------------------------------------------- -# BUTTON ---------------------------------------------------------------*/ - -.satus-color-picker { - font-size: inherit; - position: relative; - display: flex; - box-sizing: border-box; - margin: 0; - cursor: pointer; - color: inherit; - border: none; - outline: none; - background-color: var(--satus-theme-button); - justify-content: space-between; - -webkit-tap-highlight-color: transparent; - align-items: center; - -webkit-appearance: none; -} - -.satus-color-picker__value { - width: 22px; - height: 22px; - border: 2px solid rgba(0, 0, 0, .16); - border-radius: 50%; - background: #fff; -} - - -/*-------------------------------------------------------------- -# MODAL ---------------------------------------------------------------*/ - -.satus-modal--color-picker { - position: relative; -} - -.satus-modal--color-picker .satus-modal__surface { - padding-top: 0; -} - -.satus-color-picker__palette { - position: relative; - overflow: hidden; - width: 100%; - height: 256px; - background-color: #f00; -} - -.satus-color-picker__palette:before { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - content: ''; - background-image: linear-gradient(0deg, black, transparent), linear-gradient(90deg, white, transparent); -} - -.satus-color-picker__cursor { - position: absolute; - width: 5px; - height: 5px; - transform: translate(-50%, -50%); - pointer-events: none; - border: 1px solid #fff; - border-radius: 50%; - box-shadow: 0 0 0 1px #000; -} - -.satus-modal--color-picker .satus-modal__surface .satus-section--color { - margin: 8px 16px 0; - align-items: center; -} - -.satus-color-picker__color { - width: 32px; - height: 32px; - margin: 0 16px 0 0; - border: 2px solid rgba(0, 0, 0, .16); - border-radius: 50%; - background: #f00; -} - -.satus-slider.satus-color-picker__hue { - padding: 0; - flex: 1; -} - -.satus-color-picker__hue .satus-slider__track { - height: 16px; - border-radius: 4px; - background-image: linear-gradient(90deg, #f00, #ff2a00, #f50, #ff7f00, #fa0, #ffd400, #ff0, #d4ff00, #af0, #80ff00, #5f0, #2bff00, #0f0, #00ff2b, #0f5, #00ff80, #0fa, #00ffd5, #0ff, #00d4ff, #0af, #007fff, #05f, #002bff, #00f, #2a00ff, #50f, #7f00ff, #a0f, #d400ff, #f0f, #ff00d4, #f0a, #ff0080, #f05, #ff002b, #f00); -} - -.satus-color-picker__hue .satus-slider__handle { - width: 16px; - height: 16px; - background: #fff; - box-shadow: 0 0 4px rgb(0, 0, 0, .64); -} - -.satus-color-picker__hue::before, -.satus-color-picker__hue .satus-slider__track-fill, -.satus-color-picker__hue .satus-slider__handle:focus::after { - display: none; -} -/*-------------------------------------------------------------- ->>> SECTION: ----------------------------------------------------------------- -# Align -# Card ---------------------------------------------------------------*/ - -.satus-section { - display: flex; - box-sizing: border-box; - flex-wrap: wrap; -} - - -/*-------------------------------------------------------------- -# ALIGN ---------------------------------------------------------------*/ - -.satus-section--align-start { - align-items: center; - justify-content: flex-start; -} - -.satus-section--align-end { - align-items: center; - justify-content: flex-end; -} - -.satus-section--space-between { - align-items: center; - justify-content: space-between; -} - -.satus-section--column { - flex-direction: column; -} - - -/*-------------------------------------------------------------- -# CARD ---------------------------------------------------------------*/ - -.satus-section--card { - flex-direction: column; - box-sizing: border-box; - width: 100%; - max-width: 900px; - margin: 8px auto; - padding: 8px 0; - color: var(--satus-section-card-text); - border: 1px solid var(--satus-section-card-border); - border-radius: 8px; - background: var(--satus-section-card-background); - justify-content: stretch; -} - -.satus-section--label { - width: 100%; - max-width: 900px; - margin: 8px auto; -} - -.satus-section--card>*:not(.satus-button) { - box-sizing: border-box; - min-height: 48px; - padding: 0 16px; - text-align: left; -} - -.satus-section--card>.satus-switch, -.satus-section--card>.satus-select, -.satus-section--card>.satus-radio { - display: flex; - justify-content: space-between; - align-items: center; -} - -.satus-section--card>.satus-button:hover, -.satus-section--card>.satus-switch:hover, -.satus-section--card>.satus-select:hover, -.satus-section--card>.satus-slider:hover, -.satus-section--card>.satus-radio:hover { - background-color: var(--satus-hover); -} - -.satus-section--card>.satus-button { - width: 100%; - padding: 0 16px; -} - -.satus-section--card>.satus-button>svg { - width: 20px; - margin: 2px 16px 0 0; - color: var(--satus-primary); -} - -.satus-section--card>.satus-span { - display: flex; - align-items: center; -} -/*-------------------------------------------------------------- ->>> LIST: ---------------------------------------------------------------*/ - -.satus-list { - list-style: none; - margin: 0; -} - -.satus-list__item { - display: flex; - align-items: center; - justify-content: space-between; - min-height: 48px; -} - -.satus-list__item>*:last-child { - text-align: right; -} -/*-------------------------------------------------------------- ->>> HEADER ---------------------------------------------------------------*/ - -.satus-header { - z-index: 1; - display: flex; - box-sizing: border-box; - height: 56px; - padding: 0 12px; - color: var(--satus-header-text); - background: var(--satus-header-background); - border-bottom: 1px solid var(--satus-header-border); - box-shadow: 0 0 3px rgb(0, 0, 0, .1); - align-items: center; - justify-content: space-between; -} - -.satus-header .satus-button { - width: 40px; - min-width: 40px; - height: 40px; - padding: 8px; - color: inherit; - border-radius: 50%; -} - -.satus-header .satus-section--align-start>* { - margin-right: 8px; -} - -.satus-header .satus-span--title { - font-size: 15px; - font-weight: 500; - overflow: hidden; - white-space: nowrap; - letter-spacing: .0125em; - text-overflow: ellipsis; - flex: 1; -} -/*-------------------------------------------------------------- -# BUTTON ---------------------------------------------------------------*/ - -.satus-button { - font: inherit; - position: relative; - display: flex; - overflow: hidden; - height: 48px; - margin: 0; - padding: 8px; - text-align: left; - color: var(--satus-button-text, inherit); - border: none; - background: var(--satus-button-background, transparent); - appearance: none; - align-items: center; -} - -.satus-button:hover { - cursor: pointer; - background-color: var(--satus-hover); -} - -.satus-button[hidden] { - display: none; -} - -.satus-button>svg { - min-width: 20px; -} - -.satus-button>.satus-span--label { - display: block; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} -/*-------------------------------------------------------------- ->>> MODAL ---------------------------------------------------------------*/ - -.satus-modal { - position: absolute; - z-index: 100; - top: 0; - left: 0; - display: flex; - width: 100%; - height: 100vh; - justify-content: center; - align-items: center; -} - -.satus-modal__scrim { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - animation: modalFadeIn 150ms linear forwards; - opacity: 0; - background: rgba(0, 0, 0, .16); - backdrop-filter: blur(8px); -} - -.satus-modal__surface { - display: flex; - overflow-y: auto; - flex-direction: column; - width: 95%; - min-width: 240px; - max-width: 560px; - max-height: 80%; - margin: 0 16px; - padding: 12px 16px; - transform: scale(.8); - animation: modalZoomIn 150ms linear forwards; - animation-delay: 20ms; - opacity: 0; - color: var(--satus-modal-text); - border-radius: 6px; - background-color: var(--satus-modal-background); - border: 1px solid var(--satus-modal-border); - box-shadow: 0 2px 6px rgb(0, 0, 0, .15); - box-sizing: border-box; -} - -.satus-modal__surface .satus-section--actions { - display: flex; - width: 100%; - margin: 8px 0 0; - padding: 0; - justify-content: flex-end; - align-items: center; -} - -.satus-modal__surface .satus-section--actions .satus-button { - font-weight: 500; - height: 32px; - margin-left: 8px; - padding: 0 8px; - letter-spacing: .5px; - color: var(--satus-primary); - border-radius: 4px; -} - -.satus-modal__surface .satus-section--actions .satus-button:hover { - background: rgba(var(--satus-contrast), .075); -} - -.satus-modal--closing .satus-modal__scrim { - animation: modalFadeOut 70ms linear forwards; -} - -.satus-modal--closing .satus-modal__surface { - animation: modalZoomOut 70ms linear forwards; -} - -.satus-modal--vertical .satus-modal__surface { - position: absolute; - top: 8px; - right: 8px; - left: auto; - min-width: 200px; - max-width: 200px; - margin: 0; - padding: 8px 0; - transform-origin: right top; -} - -.satus-modal--vertical .satus-modal__surface>.satus-button, -.satus-modal--vertical .satus-modal__surface>.satus-switch, -.satus-modal--vertical .satus-modal__surface>.satus-select { - height: 36px; - padding: 0 16px; -} - -.satus-modal--vertical .satus-modal__surface>.satus-tabs { - padding: 0 12px; -} - -.satus-modal--vertical .satus-modal__surface>.satus-span { - font-size: 13px; - font-weight: 500; - margin: 6px 0; - padding: 0 12px; -} - -.satus-modal--vertical .satus-modal__surface>.satus-button:hover, -.satus-modal--vertical .satus-modal__surface>.satus-switch:hover, -.satus-modal--vertical .satus-modal__surface>.satus-select:hover { - background-color: var(--satus-hover); -} - -.satus-modal--vertical .satus-button svg { - width: 20px; - height: 18px; - margin: 0 14px 0 0; - opacity: .75; - flex: 0 0 20px; -} - -.satus-modal--vertical .satus-button .satus-span { - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - - -/*-------------------------------------------------------------- -# ANIMATIONS ---------------------------------------------------------------*/ - -@keyframes modalFadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } -} - -@keyframes modalFadeOut { - from { - opacity: 1; - } - to { - opacity: 0; - } -} - -@keyframes modalZoomIn { - from { - transform: scale(.8); - opacity: 0; - } - to { - transform: scale(1); - opacity: 1; - } -} - -@keyframes modalZoomOut { - from { - transform: scale(1); - opacity: 1; - } - to { - transform: scale(.8); - opacity: 0; - } -} \ No newline at end of file diff --git a/ui/satus/satus.js b/ui/satus/satus.js deleted file mode 100644 index 8ec0e8a..0000000 --- a/ui/satus/satus.js +++ /dev/null @@ -1,3226 +0,0 @@ - -/*-------------------------------------------------------------- ->>> CORE: ----------------------------------------------------------------- -# Global variable -# Functions -# Render ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# GLOBAL VARIABLE ---------------------------------------------------------------*/ - -var satus = { - components: {}, - events: {}, - locale: { - strings: {} - }, - storage: { - attributes: {}, - data: {} - } -}; - - -/*-------------------------------------------------------------- -# FUNCTIONS ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# APPEND ---------------------------------------------------------------*/ - -satus.append = function (element, container) { - (container || document.body).appendChild(element); -}; - - -/*-------------------------------------------------------------- -# ANIMATION DURATION ---------------------------------------------------------------*/ - -satus.getAnimationDuration = function (element) { - return Number(window.getComputedStyle(element).getPropertyValue('animation-duration').replace(/[^0-9.]/g, '')) * 1000; -}; - - -/*-------------------------------------------------------------- -# APPEND ---------------------------------------------------------------*/ - -satus.attr = function (element, attributes) { - if (attributes) { - for (var key in attributes) { - if (element.is_svg) { - element.setAttributeNS(null, key, attributes[key]); - } else { - var value = attributes[key]; - - if (['placeholder', 'title'].indexOf(key) !== -1) { - value = satus.locale.get(value); - } - - element.setAttribute(key, value); - } - } - } -}; - -satus.elementIndex = function (element) { - return Array.prototype.slice.call(element.parentNode.children).indexOf(element); -}; - - -/*-------------------------------------------------------------- -# DATA ---------------------------------------------------------------*/ - -satus.data = function (element, data) { - if (data) { - for (var key in data) { - element.dataset[key] = data[key]; - } - } -}; - - -/*-------------------------------------------------------------- -# PROPERTIES ---------------------------------------------------------------*/ - -satus.properties = function (element, properties) { - if (properties) { - for (var key in properties) { - element[key] = properties[key]; - } - } -}; - - -/*-------------------------------------------------------------- -# CAMELIZE ---------------------------------------------------------------*/ - -satus.camelize = function (string) { - var result = ''; - - for (var i = 0, l = string.length; i < l; i++) { - var character = string[i]; - - if (character === '-') { - i++; - - result += string[i].toUpperCase(); - } else { - result += character; - } - } - - return result; -}; - - -/*-------------------------------------------------------------- -# SNAKELIZE ---------------------------------------------------------------*/ - -satus.snakelize = function (string) { - return string.replace(/([A-Z])/g, '-$1').toLowerCase(); -}; - - -/*-------------------------------------------------------------- -# CLASS ---------------------------------------------------------------*/ - -satus.class = function (element, string) { - if (string) { - element.className += ' ' + string; - } -}; - - -/*-------------------------------------------------------------- -# EMPTY ---------------------------------------------------------------*/ - -satus.empty = function (element, exclude = []) { - for (var i = element.childNodes.length - 1; i > -1; i--) { - var child = element.childNodes[i]; - - if (exclude.indexOf(child) === -1) { - child.remove(); - } - } -}; - - -/*-------------------------------------------------------------- -# EVENTS ---------------------------------------------------------------*/ - -Object.defineProperty(satus.events, 'add', { - value: function (type, listener) { - if (this.hasOwnProperty(type) === false) { - this[type] = []; - } - - this[type].push(listener); - } -}); - - -/*-------------------------------------------------------------- -# ISSET ---------------------------------------------------------------*/ - -satus.isset = function (variable) { - if (variable === null || variable === undefined) { - return false; - } - - return true; -}; - - -/*-------------------------------------------------------------- -# FETCH ---------------------------------------------------------------*/ - -satus.fetch = function (url, success, error) { - fetch(url).then(function (response) { - if (response.ok) { - response.json().then(success); - } else { - error(); - } - }).catch(function () { - error(success); - }); -}; - - -/*-------------------------------------------------------------- -# AJAX ---------------------------------------------------------------*/ - -satus.ajax = function (url, success, error) { - var xhr = new XMLHttpRequest(); - - xhr.onload = function () { - success(this.response); - }; - xhr.onerror = function () { - error(success); - }; - - xhr.open('GET', url, true); - xhr.send(); -}; - - -/*-------------------------------------------------------------- -# STORAGE ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# GET ---------------------------------------------------------------*/ - -satus.storage.get = function (name) { - var target = satus.storage.data; - - if (typeof name !== 'string') { - return; - } - - name = name.split('/').filter(function (value) { - return value != ''; - }); - - for (var i = 0, l = name.length; i < l; i++) { - if (satus.isset(target[name[i]])) { - target = target[name[i]]; - } else { - return undefined; - } - } - - return target; -}; - - -/*-------------------------------------------------------------- -# SET ---------------------------------------------------------------*/ - -satus.storage.set = function (name, value, callback) { - var items = {}, - target = satus.storage.data; - - if (typeof name !== 'string') { - return; - } - - name = name.split('/').filter(function (value) { - return value != ''; - }); - - for (var i = 0, l = name.length; i < l; i++) { - var item = name[i]; - - if (i < l - 1) { - - if (target[item]) { - target = target[item]; - } else { - target[item] = {}; - - target = target[item]; - } - } else { - target[item] = value; - } - } - - for (var key in this.data) { - if (typeof this.data[key] !== 'function') { - items[key] = this.data[key]; - } - } - - if (satus.storage.attributes[name]) { - document.body.setAttribute('data-' + name, value); - } - - chrome.storage.local.set(items, callback); -}; - - -/*-------------------------------------------------------------- -# REMOVE ---------------------------------------------------------------*/ - -satus.storage.remove = function (name) { - delete this.data[name]; - - chrome.storage.local.remove(name); -}; - - -/*-------------------------------------------------------------- -# IMPORT ---------------------------------------------------------------*/ - -satus.storage.import = function (keys, callback) { - if (typeof keys === 'function') { - callback = keys; - - keys = undefined; - } - - chrome.storage.local.get(keys, function (items) { - for (var key in items) { - if (satus.storage.attributes[key]) { - document.body.setAttribute('data-' + key, items[key]); - } - - satus.storage.data[key] = items[key]; - } - - if (callback) { - callback(items); - } - }); -}; - - -/*-------------------------------------------------------------- -# CLEAR ---------------------------------------------------------------*/ - -satus.storage.clear = function (callback) { - this.data = {}; - - chrome.storage.local.clear(callback); -}; - - -/*-------------------------------------------------------------- -# LOCALIZATION ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# GET ---------------------------------------------------------------*/ - -satus.locale.get = function (string) { - return this.strings[string] || string; -}; - - -/*-------------------------------------------------------------- -# IMPORT ---------------------------------------------------------------*/ - -satus.locale.import = function (code, path, callback) { - var language = code || window.navigator.language; - - if (language.indexOf('en') === 0) { - language = 'en'; - } - - if (!path) { - path = '_locales/'; - } - - satus.fetch(chrome.runtime.getURL(path + language + '/messages.json'), function (response) { - for (var key in response) { - satus.locale.strings[key] = response[key].message; - } - - callback(); - }, function (success) { - satus.fetch(chrome.runtime.getURL(path + 'en/messages.json'), success, function () { - success(); - }); - }); -}; - - -/*-------------------------------------------------------------- -# ON ---------------------------------------------------------------*/ - -satus.on = function (element, events) { - if (this.isset(events) && typeof events === 'object') { - for (var selector in events) { - var type = typeof events[selector]; - - if (selector === 'selectionchange') { - element = document; - } - - if (type === 'function') { - element.addEventListener(selector, events[selector]); - } else if (type === 'object') { - element.addEventListener(selector, function (event) { - this.skeleton.on[event.type].parent = this.skeleton; - - if (this.skeleton.on[event.type].component !== 'modal' && this.base && this.base.layers) { - this.base.layers.open(this.skeleton.on[event.type]); - } else { - satus.render(this.skeleton.on[event.type], this.base); - } - }); - } else if (type === 'string') { - element.addEventListener(selector, function () { - var match = this.skeleton.on[event.type].match(/(["'`].+["'`]|[^.()]+)/g), - target = this.base; - - for (var i = 0, l = match.length; i < l; i++) { - var key = match[i]; - - if (target.skeleton[key]) { - target = target.skeleton[key]; - } else { - if (typeof target[key] === 'function') { - target[key](); - } else { - target = target[key]; - } - } - - if (target.rendered) { - target = target.rendered; - } - } - }); - } - } - } -}; - - -/*-------------------------------------------------------------- -# STYLE ---------------------------------------------------------------*/ - -satus.style = function (component, object) { - for (var key in object) { - component.style[key] = object[key]; - } -}; - - -/*-------------------------------------------------------------- -# SEARCH ---------------------------------------------------------------*/ - -satus.search = function (query, object, callback) { - var elements = ['switch', 'select', 'slider', 'shortcut', 'radio', 'color-picker'], - threads = 0, - results = {}; - - query = query.toLowerCase(); - - function parse(items, parent) { - threads++; - - for (var key in items) { - if (key !== 'rendered' && key !== 'base' && key !== 'parent') { - var item = items[key]; - - if (elements.indexOf(item.component) !== -1 && key.indexOf(query) !== -1) { - results[key] = Object.assign({}, item); - } - - if (typeof item === 'object') { - parse(item, items); - } - } - } - - threads--; - - if (threads === 0) { - callback(results); - } - } - - parse(object); -}; - - -/*-------------------------------------------------------------- -# PARENTS ---------------------------------------------------------------*/ - -satus.parents = function (object, components_only) { - function parse(items, parent) { - for (var key in items) { - if (key !== 'rendered' && key !== 'base' && key !== 'parent') { - var item = items[key]; - - if (components_only !== true || item.component) { - item.parent = items; - } - - if (typeof item === 'object' && item.component !== 'shortcut') { - parse(item, items); - } - } - } - } - - parse(object); -}; - - -/*-------------------------------------------------------------- -# TEXT ---------------------------------------------------------------*/ - -satus.text = function (component, value) { - if (typeof value === 'function') { - value = value(); - } - - if (value) { - component.appendChild(document.createTextNode(this.locale.get(value))); - } -}; - - -/*-------------------------------------------------------------- -# DECRYPTION ---------------------------------------------------------------*/ - -satus.decrypt = async function (text, password) { - var iv = text.slice(0, 24).match(/.{2}/g).map(byte => parseInt(byte, 16)), - algorithm = { - name: 'AES-GCM', - iv: new Uint8Array(iv) - }; - - try { - var data = new TextDecoder().decode(await crypto.subtle.decrypt( - algorithm, - await crypto.subtle.importKey( - 'raw', - await crypto.subtle.digest('SHA-256', new TextEncoder().encode(password)), - algorithm, - false, ['decrypt'] - ), - new Uint8Array(atob(text.slice(24)).match(/[\s\S]/g).map(ch => ch.charCodeAt(0))) - )); - } catch (err) { - return false; - } - - return data; -}; - - -/*-------------------------------------------------------------- -# ENCRYPTION ---------------------------------------------------------------*/ - -satus.encrypt = async function (text, password) { - var iv = crypto.getRandomValues(new Uint8Array(12)), - algorithm = { - name: 'AES-GCM', - iv: iv - }; - - return Array.from(iv).map(b => ('00' + b.toString(16)).slice(-2)).join('') + btoa(Array.from(new Uint8Array(await crypto.subtle.encrypt( - algorithm, - await crypto.subtle.importKey('raw', await crypto.subtle.digest('SHA-256', new TextEncoder().encode(password)), algorithm, false, ['encrypt']), - new TextEncoder().encode(text) - ))).map(byte => String.fromCharCode(byte)).join('')); -}; - - -/*-------------------------------------------------------------- -# IS ---------------------------------------------------------------*/ - -satus.isArray = function (array) { - if (Array.isArray(array)) { - return true; - } else { - return false; - } -}; - -satus.isNumber = function (number) { - if (typeof number === 'number' && isNaN(number) === false) { - return true; - } else { - return false; - } -}; - - -/*-------------------------------------------------------------- -# INDEX OF ---------------------------------------------------------------*/ - -satus.indexOf = function (child, parent) { - var index = 0; - - if (satus.isArray(parent)) { - index = parent.indexOf(child); - } else { - while ((child = child.previousElementSibling)) { - index++; - } - } - - return index; -}; - - -/*-------------------------------------------------------------- -# TO INDEX ---------------------------------------------------------------*/ - -satus.toIndex = function (index, child, parent) { - if (satus.isArray(parent)) { - parent.splice(index, 0, parent.splice(satus.indexOf(child, parent), 1)[0]) - } -}; - - -/*-------------------------------------------------------------- -# CLONE ---------------------------------------------------------------*/ - -satus.clone = function (item) { - var clone = item.cloneNode(true), - parent_css = window.getComputedStyle(item.parentNode), - css = window.getComputedStyle(item), - style = ''; - - for (var i = 0, l = css.length; i < l; i++) { - var property = css[i], - value = css.getPropertyValue(property); - - if (property === 'background-color') { - value = parent_css.getPropertyValue('background-color'); - } - - if (['box-shadow', 'left', 'top', 'bottom', 'right', 'opacity'].indexOf(property) === -1) { - style += property + ':' + value + ';'; - } - } - - - clone.setAttribute('style', style); - - return clone; -}; - - -/*-------------------------------------------------------------- -# REMOVE ---------------------------------------------------------------*/ - -satus.remove = function (child, parent) { - if (satus.isArray(parent)) { - parent.splice(satus.indexOf(child, parent), 1); - } -}; - - -/*-------------------------------------------------------------- -# RENDER ---------------------------------------------------------------*/ - -satus.render = function (skeleton, container, skip, property) { - var component; - - if (skeleton.hasOwnProperty('component') && skip !== true) { - var name = skeleton.component, - camelized_name = this.camelize(name); - - if (skeleton.on && skeleton.on.beforerender) { - skeleton.on.beforerender(skeleton); - } - - if (this.components[camelized_name]) { - component = this.components[camelized_name](skeleton); - - if (this.isset(component.inner) === false) { - component.inner = component; - } - } else if (name === 'svg' || container && container.is_svg) { - component = document.createElementNS('http://www.w3.org/2000/svg', name); - - component.is_svg = true; - - component.inner = component; - } else { - component = document.createElement(skeleton.component); - - component.inner = component; - } - - if (component.inner.hasOwnProperty('base') === false && container) { - component.inner.base = container.base; - } - - if (component.inner.base && name === 'layers') { - component.inner.base.layers = component; - } - - skeleton.rendered = component; - component.skeleton = skeleton; - - component.className = (component.className + ' satus-' + skeleton.component).trim(); - - if (skeleton.variant) { - component.className += ' satus-' + skeleton.component + '--' + skeleton.variant; - } - - this.append(component, container); - - container = component.inner || component; - - this.class(component, skeleton.class); - this.style(component, skeleton.style); - this.attr(component, skeleton.attr); - this.data(component, skeleton.data); - this.properties(component, skeleton.properties); - this.on(component, skeleton.on); - this.text(container, skeleton.text); - - if (component.hasOwnProperty('storage') === false && skeleton.storage !== false) { - component.storage = skeleton.storage || property || false; - } - - if (component.hasOwnProperty('storageValue') === false) { - if (component.storage !== false) { - component.storageValue = satus.storage.get(component.storage); - } - - if (skeleton.hasOwnProperty('value') && component.storageValue === undefined) { - component.storageValue = skeleton.value; - } - } - - component.storageChange = function () { - if (this.storage) { - var key = this.storage; - - if (typeof key === 'function') { - key = key(); - } - - satus.storage.set(key, this.storageValue); - } - - this.dispatchEvent(new CustomEvent('change')); - }; - - component.dispatchEvent(new CustomEvent('render')); - - if (skeleton.autofocus === true) { - component.focus(); - } - - if (this.events.hasOwnProperty('render')) { - for (var i = 0, l = this.events['render'].length; i < l; i++) { - this.events['render'][i](component, skeleton); - } - } - } - - if (!component || component.render_children !== false) { - for (var key in skeleton) { - if (key !== 'parent' && skeleton[key] && skeleton[key].hasOwnProperty('component')) { - skeleton[key].parent = skeleton; - - this.render(skeleton[key], container, false, key); - } - } - } - - return component; -}; -/*-------------------------------------------------------------- ->>> COLOR: ----------------------------------------------------------------- -# RGB to HSL -# HUE to RGB -# HSL to RGB ---------------------------------------------------------------*/ - -satus.color = {}; - - -/*-------------------------------------------------------------- -# RGB TO HSL ---------------------------------------------------------------*/ - -satus.color.rgbToHsl = function (array) { - var r = array[0] / 255, - g = array[1] / 255, - b = array[2] / 255, - min = Math.min(r, g, b), - max = Math.max(r, g, b), - h = 0, - s = 0, - l = (min + max) / 2; - - if (min === max) { - h = 0; - s = 0; - } else { - var delta = max - min; - - s = l <= 0.5 ? delta / (max + min) : delta / (2 - max - min); - - if (max === r) { - h = (g - b) / delta + (g < b ? 6 : 0); - } else if (max === g) { - h = (b - r) / delta + 2; - } else if (max === b) { - h = (r - g) / delta + 4; - } - - h /= 6; - } - - h *= 360; - s *= 100; - l *= 100; - - if (array.length === 3) { - return [h, s, l]; - } else { - return [h, s, l, array[3]]; - } -}; - - -/*-------------------------------------------------------------- -# HUE TO RGB ---------------------------------------------------------------*/ - -satus.color.hueToRgb = function (array) { - var t1 = array[0], - t2 = array[1], - hue = array[2]; - - if (hue < 0) { - hue += 6; - } - - if (hue >= 6) { - hue -= 6; - } - - if (hue < 1) { - return (t2 - t1) * hue + t1; - } else if (hue < 3) { - return t2; - } else if (hue < 4) { - return (t2 - t1) * (4 - hue) + t1; - } else { - return t1; - } -}; - - -/*-------------------------------------------------------------- -# HSL TO RGB ---------------------------------------------------------------*/ - -satus.color.hslToRgb = function (array) { - var h = array[0] / 360, - s = array[1] / 100, - l = array[2] / 100, - r, g, b; - - if (s == 0) { - r = g = b = l; - } else { - var hue2rgb = function hue2rgb(p, q, t) { - if (t < 0) t += 1; - if (t > 1) t -= 1; - if (t < 1 / 6) return p + (q - p) * 6 * t; - if (t < 1 / 2) return q; - if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; - return p; - } - - var q = l < 0.5 ? l * (1 + s) : l + s - l * s; - var p = 2 * l - q; - r = hue2rgb(p, q, h + 1 / 3); - g = hue2rgb(p, q, h); - b = hue2rgb(p, q, h - 1 / 3); - } - - return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; -}; -/*-------------------------------------------------------------- ->>> PLUVIAM ---------------------------------------------------------------*/ - -satus.events.add('render', function (component, skeleton) { - if (skeleton.pluviam === true) { - function createPluviam(event) { - var pluviam = document.createElement('span'), - rect = this.getBoundingClientRect(), - x = event.clientX - rect.left, - y = event.clientY - rect.top, - diameter = Math.sqrt(Math.pow(rect.width * 2, 2) + Math.pow(rect.height * 2, 2)); - - pluviam.className = 'satus-pluviam'; - - pluviam.style.left = x - diameter / 2 + 'px'; - pluviam.style.top = y - diameter / 2 + 'px'; - pluviam.style.width = diameter + 'px'; - pluviam.style.height = diameter + 'px'; - - this.appendChild(pluviam); - - setTimeout(function () { - pluviam.remove(); - }, 1000); - } - - component.addEventListener('mousedown', createPluviam); - component.addEventListener('mouseover', createPluviam); - } -}); -/*-------------------------------------------------------------- ->>> EXTENSION STORAGE ---------------------------------------------------------------*/ -/*-------------------------------------------------------------- ->>> INDEXEDDB: ----------------------------------------------------------------- -# Global variable -# Methods - # Open - # Get - # Get by key - # Set - # Clear - # Delete - # Search ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# GLOBAL VARIABLE ---------------------------------------------------------------*/ - -satus.indexeddb = { - request: null -}; - - -/*-------------------------------------------------------------- -# METHODS ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# OPEN ----------------------------------------------------------------- -satus.indexeddb.open('rootCellar', { - fruits: { - indexes: [ - 'id', - 'name', - 'amount', - ... - ], - keyOptions: { - keyPath: 'id', - autoIncrement: true - } - }, - ... -}, function () { ... }); ---------------------------------------------------------------*/ - -satus.indexeddb.open = function (name, objects, callback) { - var request = indexedDB.open(name); - - request.onerror = function (event) { - callback(); - }; - - request.onblocked = function(event) { - satus.indexeddb.open(callback); - }; - - request.onsuccess = function (event) { - satus.indexeddb.request = this.result; - - callback(); - }; - - request.onupgradeneeded = function (event) { - satus.indexeddb.request = this.result; - - for (var key in objects) { - var object = objects[key]; - - if (!this.result.objectStoreNames.contains(key)) { - var object_store = this.result.createObjectStore(key, object.keyOptions); - - for (var i = 0, l = object.indexes.length; i < l; i++) { - var name = object.indexes[i]; - - object_store.createIndex(name, name); - } - } - } - - this.result.onversionchange = function (event) { - satus.indexeddb.close(); - - satus.indexeddb.open(callback); - }; - }; -}; - - -/*-------------------------------------------------------------- -# GET ----------------------------------------------------------------- -satus.indexeddb.get({ - fruits: { - direction: 'next', - index: 'name', - offset: 0, - limit: 100 - }, - ... -}, function (result) { ... }); ---------------------------------------------------------------*/ - -satus.indexeddb.get = function (items, callback) { - var queue = [], - results = {}; - - for (var key in items) { - var item = items[key]; - - queue.push({ - name: key, - direction: item.direction, - index: item.index, - offset: item.offset - }); - } - - function handle() { - var item = queue[0], - transaction = satus.indexeddb.request.transaction(item.name, 'readonly'), - object_store = transaction.objectStore(item.name), - object_result = [], - offset = item.offset || 0, - limit = item.limit || 100; - - if (item.index) { - object_store = object_store.index(item.index); - } - - results[item.name] = object_result; - - object_store.openCursor(null, item.direction).onsuccess = function(event) { - var cursor = event.target.result; - - if (cursor) { - if (item.offset > 0) { - cursor.advance(item.offset); - - item.offset = 0; - } else if (object_result.length < limit) { - object_result.push(cursor.value); - - cursor.continue(); - } - } else { - object_store.count().onsuccess = function(event) { - object_result.fullLength = event.target.result; - - queue.shift(); - - if (queue.length === 0) { - callback(results); - } else { - handle(); - } - }; - } - }; - } - - handle(); -}; - - -/*-------------------------------------------------------------- -# GET BY KEY ----------------------------------------------------------------- -satus.indexeddb.getByKey({ - fruits: [1], - ... -}, function (result) { ... }); ---------------------------------------------------------------*/ - -satus.indexeddb.getByKey = function (items, callback) { - var queue = [], - results = {}; - - for (var name in items) { - queue.push({ - name: name, - keys: items[name] - }); - } - - function handle() { - var item = queue[0], - transaction = satus.indexeddb.request.transaction(item.name, 'readonly'), - object_store = transaction.objectStore(item.name), - object_result = []; - - results[item.name] = object_result; - - for (var i = 0, l = item.keys.length; i < l; i++) { - var key = item.keys[i]; - - object_store.get(key).onsuccess = function(event) { - var result = event.target.result; - - if (result) { - object_result.push(result); - } - - object_store.count().onsuccess = function(event) { - object_result.fullLength = event.target.result; - - queue.shift(); - - if (queue.length === 0) { - callback(results); - } else { - handle(); - } - }; - }; - } - } - - handle(); -}; - - -/*-------------------------------------------------------------- -# SET ----------------------------------------------------------------- -satus.indexeddb.set({ - fruits: [ - { name: 'apple', amount: 500 }, - ... - ], - ... -}, function () { ... }); ---------------------------------------------------------------*/ - -satus.indexeddb.set = function (items, callback) { - var threads = 0; - - for (var name in items) { - var item = items[name], - transaction = this.request.transaction(name, 'readwrite'), - object_store = transaction.objectStore(name); - - for (var i = 0, l = item.length; i < l; i++) { - var request = object_store.put(item[i]); - - threads++; - - request.onsuccess = function () { - threads--; - - if (callback && threads === 0) { - callback(); - } - }; - - request.onerror = function () { - threads--; - - if (callback && threads === 0) { - callback(); - } - }; - } - } -}; - - -/*-------------------------------------------------------------- -# CLEAR ----------------------------------------------------------------- -satus.indexeddb.clear(['fruits'], function (result) { ... }); ---------------------------------------------------------------*/ - -satus.indexeddb.clear = function (items) { - if (typeof items === 'string') { - items = [items]; - } - - for (var i = 0, l = items.length; i < l; i++) { - var name = items[i], - transaction = satus.indexeddb.request.transaction(name, 'readwrite'), - object_store = transaction.objectStore(name); - - object_store.clear(); - } -}; - - -/*-------------------------------------------------------------- -# DELETE ----------------------------------------------------------------- -satus.indexeddb.delete({ - fruits: { - name: [ - 'apple' - ] - } -}); ---------------------------------------------------------------*/ - -satus.indexeddb.delete = function (stores, callback) { - var queue = []; - - for (var name in stores) { - var store = stores[name]; - - for (var index in store) { - queue.push({ - object_store_name: name, - index_name: index, - keys: store[index] - }); - } - } - - function handle() { - var item = queue[0], - transaction = satus.indexeddb.request.transaction(item.object_store_name, 'readwrite'), - object_store = transaction.objectStore(item.object_store_name), - object_result = []; - - if (item.index_name) { - object_store = object_store.index(item.index_name); - } - - object_store.openCursor(null, item.direction).onsuccess = function(event) { - var cursor = event.target.result; - - if (cursor) { - cursor.delete(); - } - - queue.shift(); - - if (queue.length === 0) { - callback(); - } else { - handle(); - } - }; - } - - handle(); -}; - - -/*-------------------------------------------------------------- -# SEARCH ----------------------------------------------------------------- -satus.indexeddb.search({ - fruits: { - query: 'apple', // or function () { ... } - direction: 'next', - index: 'name', - offset: 0, - limit: 0 - }, - ... -}, function () { ... }); ---------------------------------------------------------------*/ - -satus.indexeddb.search = function (items, callback) { - var queue = [], - results = {}; - - for (var key in items) { - var item = items[key]; - - queue.push({ - name: key, - direction: item.direction, - index: item.index, - offset: item.offset - }); - } - - function handle() { - var item = queue[0], - transaction = satus.indexeddb.request.transaction(item.name, 'readonly'), - object_store = transaction.objectStore(item.name), - object_result = [], - offset = item.offset || 0, - limit = item.limit || 100; - - if (item.index) { - object_store = object_store.index(item.index); - } - - results[item.name] = object_result; - - object_store.openCursor(null, item.direction).onsuccess = function(event) { - var cursor = event.target.result; - - if (cursor) { - if (item.offset > 0) { - cursor.advance(item.offset); - - item.offset = 0; - } else if (limit && object_result.length < limit) { - object_result.push(cursor.value); - - cursor.continue(); - } - } else { - object_store.count().onsuccess = function(event) { - object_result.fullLength = event.target.result; - - queue.shift(); - - if (queue.length === 0) { - callback(results); - } else { - handle(); - } - }; - } - }; - } - - handle(); -}; -/*-------------------------------------------------------------- ->>> SORTABLE ---------------------------------------------------------------*/ - -satus.events.add('render', function (component, skeleton) { - if (skeleton.sortable === true) { - component.addEventListener('mousedown', function (event) { - if (event.button !== 0) { - return false; - } - - var component = this, - rect = this.getBoundingClientRect(), - x = event.clientX, - y = event.clientY, - offset_x = event.clientX - rect.left, - offset_y = event.clientY - rect.top, - ghost = satus.clone(this), - children = this.parentNode.children, - appended = false; - - ghost.classList.add('satus-sortable__ghost'); - - function mousemove(event) { - if (appended === false && (Math.abs(event.clientX - x) > 4 || Math.abs(event.clientY - y) > 4)) { - appended = true; - - component.classList.add('satus-sortable__chosen'); - - component.parentNode.appendChild(ghost); - } - - ghost.style.transform = 'translate(' + (event.clientX - offset_x) + 'px, ' + (event.clientY - offset_y) + 'px)'; - } - - function mouseup(event) { - component.classList.remove('satus-sortable__chosen'); - ghost.remove(); - - window.removeEventListener('mousemove', mousemove, true); - window.removeEventListener('mouseup', mouseup, true); - - for (var i = 0, l = children.length; i < l; i++) { - var child = children[i]; - - if (child !== component) { - child.removeEventListener('mouseover', siblingMouseOver); - } - } - - component.dispatchEvent(new CustomEvent('sort')); - - event.stopPropagation(); - - return false; - } - - window.addEventListener('mousemove', mousemove, { - passive: true, - capture: true - }); - - window.addEventListener('mouseup', mouseup, { - passive: true, - capture: true - }); - - function siblingMouseOver(event) { - var target = event.target, - parent = target.parentNode, - y = event.layerY / (target.offsetHeight / 100); - - if (y < 50 && target.previousSibling !== component || y >= 50 && target.nextSibling === component) { - parent.insertBefore(component, target); - } else { - parent.insertBefore(component, target.nextSibling); - } - } - - for (var i = 0, l = children.length; i < l; i++) { - var child = children[i]; - - if (child !== component) { - child.addEventListener('mouseover', siblingMouseOver); - } - } - - event.stopPropagation(); - event.preventDefault(); - - return false; - }); - } -}); -/*-------------------------------------------------------------- ->>> USER ---------------------------------------------------------------*/ - -satus.user = function () { - /*-------------------------------------------------------------- - 1.0 VARIABLES - --------------------------------------------------------------*/ - - var user_agent = navigator.userAgent, - random_cookie = 'ta{t`nX6cMXK,Wsc', - video = document.createElement('video'), - video_formats = { - ogg: 'video/ogg; codecs="theora"', - h264: 'video/mp4; codecs="avc1.42E01E"', - webm: 'video/webm; codecs="vp8, vorbis"', - vp9: 'video/webm; codecs="vp9"', - hls: 'application/x-mpegURL; codecs="avc1.42E01E"' - }, - audio = document.createElement('audio'), - audio_formats = { - mp3: 'audio/mpeg', - mp4: 'audio/mp4', - aif: 'audio/x-aiff' - }, - cvs = document.createElement('canvas'), - ctx = cvs.getContext('webgl'), - data = { - browser: { - audio: null, - cookies: null, - flash: null, - java: null, - languages: null, - name: null, - platform: null, - version: null, - video: null, - webgl: null - }, - os: { - name: null, - type: null - }, - device: { - connection: { - type: null, - speed: null - }, - cores: null, - gpu: null, - max_touch_points: null, - ram: null, - screen: null, - touch: null - } - }; - - - /*-------------------------------------------------------------- - 2.0 SOFTWARE - --------------------------------------------------------------*/ - - /*-------------------------------------------------------------- - 2.1.0 OS - --------------------------------------------------------------*/ - - /*-------------------------------------------------------------- - 2.1.1 NAME - --------------------------------------------------------------*/ - - if (navigator.appVersion.indexOf('Win') !== -1) { - if (navigator.appVersion.match(/(Windows 10.0|Windows NT 10.0)/)) { - data.os.name = 'Windows 10'; - } else if (navigator.appVersion.match(/(Windows 8.1|Windows NT 6.3)/)) { - data.os.name = 'Windows 8.1'; - } else if (navigator.appVersion.match(/(Windows 8|Windows NT 6.2)/)) { - data.os.name = 'Windows 8'; - } else if (navigator.appVersion.match(/(Windows 7|Windows NT 6.1)/)) { - data.os.name = 'Windows 7'; - } else if (navigator.appVersion.match(/(Windows NT 6.0)/)) { - data.os.name = 'Windows Vista'; - } else if (navigator.appVersion.match(/(Windows NT 5.1|Windows XP)/)) { - data.os.name = 'Windows XP'; - } else { - data.os.name = 'Windows'; - } - } else if (navigator.appVersion.indexOf('(iPhone|iPad|iPod)') !== -1) { - data.os.name = 'iOS'; - } else if (navigator.appVersion.indexOf('Mac') !== -1) { - data.os.name = 'macOS'; - } else if (navigator.appVersion.indexOf('Android') !== -1) { - data.os.name = 'Android'; - } else if (navigator.appVersion.indexOf('OpenBSD') !== -1) { - data.os.name = 'OpenBSD'; - } else if (navigator.appVersion.indexOf('SunOS') !== -1) { - data.os.name = 'SunOS'; - } else if (navigator.appVersion.indexOf('Linux') !== -1) { - data.os.name = 'Linux'; - } else if (navigator.appVersion.indexOf('X11') !== -1) { - data.os.name = 'UNIX'; - } - - /*-------------------------------------------------------------- - 2.1.2 TYPE - --------------------------------------------------------------*/ - - if (navigator.appVersion.match(/(Win64|x64|x86_64|WOW64)/)) { - data.os.type = '64-bit'; - } else { - data.os.type = '32-bit'; - } - - - /*-------------------------------------------------------------- - 2.2.0 BROWSER - --------------------------------------------------------------*/ - - /*-------------------------------------------------------------- - 2.2.1 NAME - --------------------------------------------------------------*/ - - if (user_agent.indexOf('Opera') !== -1) { - data.browser.name = 'Opera'; - } else if (user_agent.indexOf('Vivaldi') !== -1) { - data.browser.name = 'Vivaldi'; - } else if (user_agent.indexOf('Edge') !== -1) { - data.browser.name = 'Edge'; - } else if (user_agent.indexOf('Chrome') !== -1) { - data.browser.name = 'Chrome'; - } else if (user_agent.indexOf('Safari') !== -1) { - data.browser.name = 'Safari'; - } else if (user_agent.indexOf('Firefox') !== -1) { - data.browser.name = 'Firefox'; - } else if (user_agent.indexOf('MSIE') !== -1) { - data.browser.name = 'IE'; - } - - - /*-------------------------------------------------------------- - 2.2.2 VERSION - --------------------------------------------------------------*/ - - var browser_version = user_agent.match(new RegExp(data.browser.name + '/([0-9.]+)')); - - if (browser_version[1]) { - data.browser.version = browser_version[1]; - } - - - /*-------------------------------------------------------------- - 2.2.3 PLATFORM - --------------------------------------------------------------*/ - - data.browser.platform = navigator.platform || null; - - - /*-------------------------------------------------------------- - 2.2.4 LANGUAGES - --------------------------------------------------------------*/ - - data.browser.languages = navigator.languages || null; - - - /*-------------------------------------------------------------- - 2.2.5 COOKIES - --------------------------------------------------------------*/ - - if (document.cookie) { - document.cookie = random_cookie; - - if (document.cookie.indexOf(random_cookie) !== -1) { - data.browser.cookies = true; - } - } - - - /*-------------------------------------------------------------- - 2.2.6 FLASH - --------------------------------------------------------------*/ - - try { - if (new ActiveXObject('ShockwaveFlash.ShockwaveFlash')) { - data.browser.flash = true; - } - } catch (e) { - if (navigator.mimeTypes['application/x-shockwave-flash']) { - data.browser.flash = true; - } - } - - - /*-------------------------------------------------------------- - 2.2.7 JAVA - --------------------------------------------------------------*/ - - if (typeof navigator.javaEnabled === 'function' && navigator.javaEnabled()) { - data.browser.java = true; - } - - - /*-------------------------------------------------------------- - 2.2.8 VIDEO FORMATS - --------------------------------------------------------------*/ - - if (typeof video.canPlayType === 'function') { - data.browser.video = {}; - - for (var i in video_formats) { - var can_play_type = video.canPlayType(video_formats[i]); - - if (can_play_type === '') { - data.browser.video[i] = false; - } else { - data.browser.video[i] = can_play_type; - } - } - } - - - /*-------------------------------------------------------------- - 2.2.9 AUDIO FORMATS - --------------------------------------------------------------*/ - - if (typeof audio.canPlayType === 'function') { - data.browser.audio = {}; - - for (var i in audio_formats) { - var can_play_type = audio.canPlayType(audio_formats[i]); - - if (can_play_type == '') { - data.browser.audio[i] = false; - } else { - data.browser.audio[i] = can_play_type; - } - } - } - - - /*-------------------------------------------------------------- - 2.2.10 WEBGL - --------------------------------------------------------------*/ - - if (ctx && ctx instanceof WebGLRenderingContext) { - data.browser.webgl = true; - } - - - /*-------------------------------------------------------------- - 3.0 HARDWARE - --------------------------------------------------------------*/ - - /*-------------------------------------------------------------- - 3.1 SCREEN - --------------------------------------------------------------*/ - - if (screen) { - data.device.screen = screen.width + 'x' + screen.height; - } - - - /*-------------------------------------------------------------- - 3.2 RAM - --------------------------------------------------------------*/ - - if ('deviceMemory' in navigator) { - data.device.ram = navigator.deviceMemory + ' GB'; - } - - - /*-------------------------------------------------------------- - 3.3 GPU - --------------------------------------------------------------*/ - - if ( - ctx && - ctx instanceof WebGLRenderingContext && - 'getParameter' in ctx && - 'getExtension' in ctx - ) { - var info = ctx.getExtension('WEBGL_debug_renderer_info'); - - if (info) { - data.device.gpu = ctx.getParameter(info.UNMASKED_RENDERER_WEBGL); - } - } - - - /*-------------------------------------------------------------- - 3.4 CORES - --------------------------------------------------------------*/ - - if (navigator.hardwareConcurrency) { - data.device.cores = navigator.hardwareConcurrency; - } - - - /*-------------------------------------------------------------- - 3.5 TOUCH - --------------------------------------------------------------*/ - - if ( - window.hasOwnProperty('ontouchstart') || - window.DocumentTouch && document instanceof window.DocumentTouch || - navigator.maxTouchPoints > 0 || - window.navigator.msMaxTouchPoints > 0 - ) { - data.device.touch = true; - data.device.max_touch_points = navigator.maxTouchPoints; - } - - - /*-------------------------------------------------------------- - 3.6 CONNECTION - --------------------------------------------------------------*/ - - if (typeof navigator.connection === 'object') { - data.device.connection.type = navigator.connection.effectiveType || null; - - if (navigator.connection.downlink) { - data.device.connection.speed = navigator.connection.downlink + ' Mbps'; - } - } - - - /*-------------------------------------------------------------- - 4.0 CLEARING - --------------------------------------------------------------*/ - - video.remove(); - audio.remove(); - cvs.remove(); - - - return data; -}; -/*-------------------------------------------------------------- ->>> UUID ---------------------------------------------------------------*/ - -satus.uuid = function () { - return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, function (match) { - return (match ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> match / 4).toString(16) - }); -}; -/*-------------------------------------------------------------- ->>> CONTEXT MENU ---------------------------------------------------------------*/ - -satus.events.add('render', function (component, skeleton) { - if (skeleton.contextMenu) { - component.addEventListener('contextmenu', function (event) { - var x = event.clientX, - y = event.clientY, - modal = satus.render({ - component: 'modal', - variant: 'contextmenu', - parent: this.skeleton - }); - - if (window.innerWidth - x < 200) { - x = window.innerWidth - 200; - } - - modal.inner.style.left = x + 'px'; - modal.inner.style.top = y + 'px'; - - satus.render(this.skeleton.contextMenu, modal.inner); - - event.preventDefault(); - event.stopPropagation(); - - return false; - }); - } -}); -/*-------------------------------------------------------------- ->>> BASE ---------------------------------------------------------------*/ - -satus.components.base = function (skeleton) { - var component = document.createElement('div'); - - component.base = component; - - return component; -}; -/*-------------------------------------------------------------- ->>> RADIO ---------------------------------------------------------------*/ - -satus.components.radio = function (skeleton) { - var component = document.createElement('label'), - content = document.createElement('span'), - radio = document.createElement('input'); - - component.inner = content; - - radio.type = 'radio'; - - if (skeleton.group) { - component.storage = skeleton.group; - radio.name = skeleton.group; - } - - if (skeleton.value) { - radio.value = skeleton.value; - } - - component.addEventListener('render', function () { - this.storageValue = satus.storage.get(this.storage); - - if (satus.isset(this.storageValue)) { - radio.checked = this.storageValue === skeleton.value; - } else if (skeleton.checked) { - radio.checked = true; - } - }); - - radio.addEventListener('change', function () { - component.storageValue = this.value; - component.storageChange(); - }); - - component.appendChild(content); - component.appendChild(radio); - - return component; -}; -/*-------------------------------------------------------------- ->>> CHECKBOX ---------------------------------------------------------------*/ - -satus.components.checkbox = function (skeleton) { - var component = document.createElement('button'), - content = document.createElement('span'); - - component.inner = content; - - content.className = 'satus-checkbox__content'; - - component.appendChild(content); - - component.addEventListener('click', function () { - if (this.dataset.value === 'true') { - this.storageValue = false; - this.dataset.value = 'false'; - } else { - this.storageValue = true; - this.dataset.value = 'true'; - } - - this.storageChange(); - }); - - component.addEventListener('render', function () { - this.dataset.value = this.storageValue; - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> SELECT ---------------------------------------------------------------*/ - -satus.components.select = function (skeleton) { - var component = document.createElement('div'), - component_content = document.createElement('span'), - component_value = document.createElement('span'), - component_select = document.createElement('select'); - - for (var i = 0, l = skeleton.options.length; i < l; i++) { - var option = document.createElement('option'); - - option.value = skeleton.options[i].value; - - satus.text(option, skeleton.options[i].text); - - component_select.appendChild(option); - } - - component.inner = component_content; - component.select = component_select; - - Object.defineProperty(component, 'value', { - get() { - return this.select.value; - }, - set(value) { - this.select.value = value; - } - }); - - component.render = function () { - var value_element = this.children[2]; - - satus.empty(value_element); - - satus.text(value_element, this.select.options[this.select.selectedIndex].text); - - this.dataset.value = this.value; - }; - - component.addEventListener('render', function () { - this.value = this.storageValue || this.skeleton.options[0].value; - - this.render(); - }); - - component_select.addEventListener('change', function () { - var component = this.parentNode; - - component.storageValue = this.value; - - component.storageChange(); - - component.render(); - }); - - component.appendChild(component_select); - component.appendChild(component_content); - component.appendChild(component_value); - - return component; -}; -/*-------------------------------------------------------------- ->>> SHORTCUT ---------------------------------------------------------------*/ - -satus.components.shortcut = function (skeleton) { - var component = document.createElement('button'), - content = document.createElement('span'), - value = document.createElement('div'); - - component.inner = content; - - component.className = 'satus-button'; - value.className = 'satus-shortcut__value'; - - component.render = function (parent) { - var self = this, - parent = parent || self.primary, - children = parent.children; - - satus.empty(parent); - - function createElement(name) { - var element = document.createElement('div'); - - element.className = 'satus-shortcut__' + name; - - parent.appendChild(element); - - return element; - } - - if (this.data.alt) { - createElement('key').textContent = 'Alt'; - } - - if (this.data.ctrl) { - if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { - createElement('plus'); - } - - createElement('key').textContent = 'Ctrl'; - } - - if (this.data.shift) { - if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { - createElement('plus'); - } - - createElement('key').textContent = 'Shift'; - } - - for (var code in this.data.keys) { - var key = this.data.keys[code].key, - arrows = ['ArrowUp', 'ArrowRight', 'ArrowDown', 'ArrowLeft'], - index = arrows.indexOf(key); - - if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { - createElement('plus'); - } - - if (index !== -1) { - createElement('key').textContent = ['↑', '→', '↓', '←'][index]; - } else if (key === ' ') { - createElement('key').textContent = '␣'; - } else if (key) { - createElement('key').textContent = key.toUpperCase(); - } - } - - if (this.data.wheel) { - if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { - createElement('plus'); - } - - var mouse = createElement('mouse'), - div = document.createElement('div'); - - mouse.appendChild(div); - - mouse.className += ' ' + (this.data.wheel > 0); - } - - if (this.data.click) { - if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { - createElement('plus'); - } - - var mouse = createElement('mouse'), - div = document.createElement('div'); - - mouse.appendChild(div); - - mouse.className += ' click'; - } - - if (this.data.middle) { - if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { - createElement('plus'); - } - - var mouse = createElement('mouse'), - div = document.createElement('div'); - - mouse.appendChild(div); - - mouse.className += ' middle'; - } - - if (this.data.context) { - if (children.length && children[children.length - 1].className.indexOf('plus') === -1) { - createElement('plus'); - } - - var mouse = createElement('mouse'), - div = document.createElement('div'); - - mouse.appendChild(div); - - mouse.className += ' context'; - } - }; - - component.valueElement = value; - - component.appendChild(content); - component.appendChild(value); - - component.keydown = function (event) { - event.preventDefault(); - event.stopPropagation(); - - component.data = { - alt: event.altKey, - ctrl: event.ctrlKey, - shift: event.shiftKey, - keys: {} - }; - - if (['control', 'alt', 'altgraph', 'shift'].indexOf(event.key.toLowerCase()) === -1) { - component.data.keys[event.keyCode] = { - code: event.code, - key: event.key - }; - } - - component.data.wheel = 0; - - component.render(); - - return false; - }; - - if (skeleton.wheel !== false) { - component.mousewheel = function (event) { - event.stopPropagation(); - - if ( - ( - component.data.wheel === 0 && - ( - Object.keys(component.data.keys).length === 0 && - component.data.alt === false && - component.data.ctrl === false && - component.data.shift === false - ) - ) || - component.data.wheel < 0 && event.deltaY > 0 || - component.data.wheel > 0 && event.deltaY < 0) { - component.data = { - alt: false, - ctrl: false, - shift: false, - keys: {} - }; - } - - component.data.wheel = event.deltaY < 0 ? -1 : 1; - - component.render(); - - return false; - }; - } - - component.addEventListener('render', function () { - this.data = this.storageValue || { - alt: false, - ctrl: false, - shift: false, - keys: {}, - wheel: 0 - }; - - this.render(this.valueElement); - }); - - component.addEventListener('click', function () { - satus.render({ - component: 'modal', - properties: { - parent: this - }, - on: { - close: function () { - window.removeEventListener('keydown', component.keydown); - window.removeEventListener('wheel', component.mousewheel); - } - }, - - primary: { - component: 'div', - class: 'satus-shortcut__primary', - on: { - render: function () { - component.primary = this; - - if (component.skeleton.mouseButtons === true) { - this.addEventListener('mousedown', function (event) { - if ( - component.data.click && event.button === 0 || - component.data.middle && event.button === 1 - ) { - component.data = { - alt: false, - ctrl: false, - shift: false, - keys: {} - }; - } - - component.data.click = false; - component.data.middle = false; - component.data.context = false; - - if (event.button === 0) { - component.data.click = true; - - component.render(); - } else if (event.button === 1) { - component.data.middle = true; - - component.render(); - } - }); - - this.addEventListener('contextmenu', function (event) { - event.preventDefault(); - event.stopPropagation(); - - if (component.data.context) { - component.data = { - alt: false, - ctrl: false, - shift: false, - keys: {} - }; - } - - component.data.context = true; - component.data.middle = false; - component.data.click = false; - - component.render(); - - return false; - }); - } - - component.render(); - } - } - }, - actions: { - component: 'section', - variant: 'actions', - - reset: { - component: 'button', - text: 'reset', - on: { - click: function () { - var component = this.parentNode.parentNode.parentNode.parent; - - component.data = component.skeleton.value || {}; - - component.render(component.valueElement); - - satus.storage.remove(component.storage); - - this.parentNode.parentNode.parentNode.close(); - - window.removeEventListener('keydown', component.keydown); - window.removeEventListener('wheel', component.mousewheel); - } - } - }, - cancel: { - component: 'button', - text: 'cancel', - on: { - click: function () { - component.data = satus.storage.get(component.storage) || component.skeleton.value || {}; - - component.render(component.valueElement); - - this.parentNode.parentNode.parentNode.close(); - - window.removeEventListener('keydown', component.keydown); - window.removeEventListener('wheel', component.mousewheel); - } - } - }, - save: { - component: 'button', - text: 'save', - on: { - click: function () { - component.storageValue = component.data; - - component.storageChange(); - - component.render(component.valueElement); - - this.parentNode.parentNode.parentNode.close(); - - window.removeEventListener('keydown', component.keydown); - window.removeEventListener('wheel', component.mousewheel); - } - } - } - } - }); - - window.addEventListener('keydown', this.keydown); - window.addEventListener('wheel', this.mousewheel); - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> SWITCH ---------------------------------------------------------------*/ - -satus.components.switch = function (skeleton) { - var component = document.createElement('button'), - component_content = document.createElement('span'), - component_thumb = document.createElement('i'); - - component.inner = component_content; - - component_content.className = 'satus-switch__content'; - - component.addEventListener('click', function () { - if (this.dataset.value === 'true') { - this.storageValue = false; - this.dataset.value = 'false'; - } else { - this.storageValue = true; - this.dataset.value = 'true'; - } - - this.storageChange(); - }); - - component.addEventListener('render', function () { - this.dataset.value = this.storageValue; - }); - - component.appendChild(component_content); - component.appendChild(component_thumb); - - return component; -}; -/*-------------------------------------------------------------- ->>> LAYERS ---------------------------------------------------------------*/ - -satus.components.layers = function (skeleton) { - var component = document.createElement('div'); - - component.path = [skeleton]; - - component.back = function () { - if (this.path.length > 1) { - this.path.pop(); - - this.open(); - } - }; - - component.open = function (skeleton) { - var layer = document.createElement('div'); - - if (skeleton) { - this.path.push(skeleton); - } else { - skeleton = this.path[this.path.length - 1]; - } - - layer.className = 'satus-layer'; - - layer.skeleton = skeleton; - layer.base = this.base; - - satus.render(skeleton, layer, skeleton.component === 'layers'); - - satus.empty(this); - - this.appendChild(layer); - - this.dispatchEvent(new Event('open')); - }; - - component.update = function () { - var layer = this.querySelector('.satus-layer'); - - satus.empty(layer); - - satus.render(layer.skeleton, layer); - }; - - component.render_children = false; - - component.addEventListener('render', function () { - this.open(); - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> INPUT ---------------------------------------------------------------*/ - -satus.components.input = function (skeleton) { - var component = document.createElement('input'); - - if (skeleton.attr) { - var key = skeleton.attr.name || skeleton.storage, - value; - - if (satus.isset(satus.storage.get(key))) { - value = satus.storage.get(key); - } else { - value = skeleton.value; - } - - if (skeleton.attr.type === 'radio') { - component.checked = value === skeleton.attr.value || skeleton.value; - } else if (satus.isset(value)) { - component.value = value; - } - - component.addEventListener('change', function () { - var key = this.skeleton.attr.name || this.skeleton.storage; - - satus.storage.set(key, this.value); - }); - } else { - var key = skeleton.name || skeleton.storage, - value; - - component.type = skeleton.type; - - if (satus.isset(satus.storage.get(key))) { - value = satus.storage.get(key); - } else { - value = skeleton.value; - } - - if (skeleton.type === 'radio') { - component.checked = value === skeleton.value || skeleton.value; - } else if (satus.isset(value)) { - component.value = value; - } - - component.addEventListener('change', function () { - var key = this.skeleton.name || this.skeleton.storage; - - satus.storage.set(key, this.value); - }); - } - - return component; -}; -/*-------------------------------------------------------------- ->>> MENUBAR ---------------------------------------------------------------*/ - -satus.components.menubar = function (skeleton) { - function createList(items) { - var ul = document.createElement('ul'); - - for (var key in items) { - var item = items[key], - li = document.createElement('li'); - - satus.render(item, li); - - if (item.items) { - li.appendChild(createList(item.items)); - } - - ul.appendChild(li); - } - - return ul; - } - - return createList(skeleton.items); -}; -/*-------------------------------------------------------------- ->>> TEXTAREA ---------------------------------------------------------------*/ - -satus.components.textarea = function (skeleton) { - var component = document.createElement('div'), - line_number = document.createElement('div'), - textarea = document.createElement('textarea'); - - line_number.className = 'satus-textarea__line-number'; - - component.line_number = line_number; - component.textarea = textarea; - - Object.defineProperty(component, 'value', { - get() { - return this.textarea.value; - }, - set(value) { - this.textarea.value = value; - - this.line_number.update(); - } - }); - - line_number.update = function () { - var count = this.parentNode.textarea.value.split('\n').length; - - if (count !== this.children.length) { - satus.empty(this); - - for (var i = 1; i <= count; i++) { - var span = document.createElement('span'); - - span.textContent = i; - - this.appendChild(span); - } - } - }; - - textarea.addEventListener('input', function () { - this.parentNode.line_number.update(); - }); - - textarea.addEventListener('selectionchange', function () { - this.parentNode.line_number.update(); - }); - - textarea.addEventListener('scroll', function () { - this.parentNode.line_number.style.transform = 'translateY(-' + this.scrollTop + 'px)'; - - this.parentNode.line_number.update(); - }); - - component.appendChild(line_number); - component.appendChild(textarea); - - line_number.update(1); - - return component; -}; -/*-------------------------------------------------------------- ->>> DIVIDER ---------------------------------------------------------------*/ - -satus.components.divider = function () { - var component = document.createElement('div'); - - return component; -}; -/*-------------------------------------------------------------- ->>> TEXT FIELD ---------------------------------------------------------------*/ - -satus.components.textField = function (skeleton) { - var component = document.createElement('div'), - pre = document.createElement('pre'), - input = document.createElement('textarea'), - hidden_text = document.createElement('span'), - text = document.createElement('span'), - selection = document.createElement('div'), - cursor = document.createElement('div'); - - input.className = 'satus-text-field__input'; - pre.className = 'satus-text-field__pre'; - hidden_text.className = 'satus-text-field__hidden-text'; - text.className = 'satus-text-field__text'; - selection.className = 'satus-text-field__selection'; - cursor.className = 'satus-text-field__cursor'; - - component.inputElement = input; - component.textElement = text; - component.languages = { - regex: function (component) { - var regex_token = /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g, - char_class_token = /[^\\-]+|-|\\(?:[0-3][0-7]{0,2}|[4-7][0-7]?|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)/g, - char_class_parts = /^(\[\^?)(]?(?:[^\\\]]+|\\[\S\s]?)*)(]?)$/, - quantifier = /^(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??$/, - matches = component.inputElement.value.match(regex_token); - - function create(type, string) { - var span = document.createElement('span'); - - span.className = type; - span.textContent = string; - - component.textElement.appendChild(span); - } - - for (var i = 0, l = matches.length; i < l; i++) { - var match = matches[i]; - - if (match[0] === '[') { - create('character-class', match); - } else if (match[0] === '(') { - create('group', match); - } else if (match[0] === ')') { - create('group', match); - } else if (match[0] === '\\' || match === '^') { - create('anchor', match); - } else if (quantifier.test(match)) { - create('quantifier', match); - } else if (match === '|' || match === '.') { - create('metasequence', match); - } else { - create('text', match); - } - } - } - }; - component._syntax = skeleton.syntax; - - Object.defineProperty(component, 'value', { - get: function () { - return this.inputElement.value; - }, - set: function (value) { - var input = this.inputElement; - - input.value = value; - - input.updateValue(); - input.updateCursor(); - } - }); - - Object.defineProperty(component, 'syntax', { - get: function () { - return this._syntax; - }, - set: function (value) { - var input = this.inputElement; - - this._syntax = value; - - input.updateValue(); - input.updateCursor(); - } - }); - - input.rows = skeleton.rows || 1; - input.autocapitalize = 'none'; - input.autocomplete = 'off'; - input.autocorrect = 'off'; - input.spellcheck = false; - input.autofocus = true; - input.textElement = text; - input.hiddenTextElement = hidden_text; - input.selectionElement = selection; - input.cursorElement = cursor; - - input.updateValue = function () { - var component = this.parentNode.parentNode; - - for (var i = this.textElement.childNodes.length - 1; i > -1; i--) { - this.textElement.childNodes[i].remove(); - } - - if (this.value.length > 0) { - if (component.languages[component._syntax]) { - component.languages[component._syntax](component); - } else { - this.textElement.textContent = this.value; - } - } - }; - - input.updateCursor = function () { - var cursor = this.cursorElement, - selection = this.selectionElement, - hidden_text = this.hiddenTextElement, - start = this.selectionStart, - end = this.selectionEnd; - - cursor.style.animation = 'none'; - - if (start === end) { - selection.setAttribute('disabled', ''); - } else { - selection.removeAttribute('disabled'); - - hidden_text.textContent = this.value.substring(0, start); - - selection.style.left = hidden_text.offsetWidth - this.scrollLeft + 'px'; - - hidden_text.textContent = this.value.substring(start, end); - - selection.style.width = hidden_text.offsetWidth + 'px'; - } - - if (this.selectionDirection === 'forward') { - hidden_text.textContent = this.value.substring(0, end); - } else { - hidden_text.textContent = this.value.substring(0, start); - } - - cursor.style.left = hidden_text.offsetWidth - this.scrollLeft + 'px'; - - cursor.style.animation = ''; - - hidden_text.textContent = ''; - }; - - input.addEventListener('keydown', function () { - var self = this; - - setTimeout(function () { - var component = self.parentNode.parentNode; - - component.storageValue = self.value; - component.storageChange(); - - self.updateValue(); - self.updateCursor(); - }); - }); - - input.addEventListener('scroll', function (event) { - this.textElement.style.left = -this.scrollLeft + 'px'; - }); - - document.addEventListener('selectionchange', function () { - input.updateCursor(); - }); - - selection.setAttribute('disabled', ''); - - pre.appendChild(input); - pre.appendChild(hidden_text); - pre.appendChild(text); - pre.appendChild(selection); - pre.appendChild(cursor); - component.appendChild(pre); - - component.addEventListener('render', function () { - input.value = this.storageValue; - - this.inputElement.updateValue(); - this.inputElement.updateCursor(); - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> TABS ---------------------------------------------------------------*/ - -satus.components.tabs = function (skeleton) { - var component = document.createElement('div'), - content = document.createElement('div'), - selection = document.createElement('div'); - - content.className = 'satus-tabs__content'; - selection.className = 'satus-tabs__selection'; - selection.style.width = 100 / skeleton.items.length + '%'; - - content.appendChild(selection); - - component.selection = selection; - - for (var i = 0, l = skeleton.items.length; i < l; i++) { - var item = skeleton.items[i], - button = document.createElement('button'); - - button.className = 'satus-tabs__button'; - button.value = item; - button.style.width = 100 / l + '%'; - - satus.text(button, item); - - button.addEventListener('click', function () { - var component = this.parentNode.parentNode; - - component.selection.style.left = 100 / (this.parentNode.children.length - 1) * (satus.indexOf(this) - 1) + '%'; - - component.storageValue = this.value; - component.storageChange(); - }); - - if (skeleton.value === item) { - selection.style.left = i * 50 + '%'; - } - - content.appendChild(button); - } - - component.appendChild(content); - - component.addEventListener('render', function () { - var index = satus.indexOf(this.storageValue, this.skeleton.items); - - if (index === -1) { - index = 0; - } - - this.selection.style.left = 100 / this.skeleton.items.length * index + '%'; - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> ALERT ---------------------------------------------------------------*/ - -satus.components.alert = function (skeleton) { - var component = document.createElement('div'); - - return component; -}; -/*-------------------------------------------------------------- ->>> SLIDER ---------------------------------------------------------------*/ - -satus.components.slider = function (skeleton) { - var component = document.createElement('div'), - content = document.createElement('div'), - container = document.createElement('div'), - track = document.createElement('div'), - track_fill = document.createElement('div'); - - container.className = 'satus-slider__container'; - track.className = 'satus-slider__track'; - track_fill.className = 'satus-slider__track-fill'; - - component.min = skeleton.min || 0; - component.max = skeleton.max || 1; - component.step = (skeleton.step || 1); - component.percent = 100 / ((component.max - component.min) / component.step); - component.precision = String(component.step).replace(/[0-9]./, '').length; - - component.container = container; - component.track = track_fill; - component.handles = []; - component.inner = content; - - component.toPercent = function (number) { - return number / this.step * this.percent + '%'; - }; - - component.createHandle = function (index) { - var handle = document.createElement('div'); - - handle.className = 'satus-slider__handle'; - handle.handleIndex = index; - handle.tabIndex = 0; - - this.handles.push(handle); - - this.container.appendChild(handle); - }; - - component.update = function () { - if (this.values.length > 1) { - var min = Math.min.apply(null, this.values) - this.min, - max = Math.max.apply(null, this.values) - this.min; - - this.track.style.left = this.toPercent(min); - this.track.style.width = this.toPercent(max - min); - - for (var i = 0, l = this.handles.length; i < l; i++) { - var handle = this.handles[i], - value = this.values[i]; - - handle.style.left = this.toPercent(value - this.min); - handle.dataset.value = value; - } - } else { - var value = this.values[0]; - - this.track.style.width = this.toPercent(value - this.min); - this.handles[0].style.left = this.toPercent(value - this.min); - this.handles[0].dataset.value = value; - } - }; - - component.appendChild(content); - track.appendChild(track_fill); - container.appendChild(track); - component.appendChild(container); - - component.addEventListener('keydown', function (event) { - var code = event.keyCode; - - console.log(code); - }); - - component.addEventListener('render', function () { - var value = this.storageValue; - - if (satus.isArray(value)) { - this.values = value; - } else if (satus.isNumber(value)) { - this.values = [value]; - } else { - this.values = this.skeleton.values || [satus.isset(this.skeleton.value) ? this.skeleton.value : 1]; - } - - for (var i = 0, l = this.values.length; i < l; i++) { - this.createHandle(i); - } - - this.update(); - }); - - container.addEventListener('mousedown', function (event) { - if (event.button === 0) { - var component = this.parentNode, - rect = this.getBoundingClientRect(), - cursor_x = event.clientX - rect.left, - percent = cursor_x / rect.width * 100, - steps = percent / component.percent * component.step + component.min, - closest_value = component.values.indexOf(component.values.reduce(function(previous, current, index) { - return Math.abs(current - steps) < Math.abs(previous - steps) ? current : previous; - })), - handle_index = component.handles[closest_value].handleIndex; - - setTimeout(function () { - component.handles[closest_value].focus(); - }); - - function update(event) { - var cursor_x = Math.min(Math.max(event.clientX - rect.left, 0), rect.width), - percent = cursor_x / rect.width * 100, - value = percent / component.percent * component.step + component.min; - - value = (Math.round(value / component.step) * component.step); - - value = Number(value.toFixed(component.precision)); - - if (component.values[handle_index] !== value) { - component.values[handle_index] = value; - - component.storageValue = component.values.length === 1 ? component.values[0] : component.values; - component.value = component.storageValue; - - component.storageChange(); - } - - component.update(); - } - - function mousemove(event) { - update(event); - } - - function mouseup(event) { - window.removeEventListener('mousemove', mousemove); - window.removeEventListener('mouseup', mouseup); - }; - - window.addEventListener('mousemove', mousemove); - window.addEventListener('mouseup', mouseup); - - update(event); - - return true; - } - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> COLOR PICKER ---------------------------------------------------------------*/ - -satus.components.colorPicker = function (skeleton) { - var component = document.createElement('button'), - component_label = document.createElement('span'), - component_value = document.createElement('span'); - - component.inner = component_label; - component.valueElement = component_value; - - component.className = 'satus-button'; - component_value.className = 'satus-color-picker__value'; - - component.appendChild(component_label); - component.appendChild(component_value); - - component.addEventListener('click', function () { - var rgb = this.rgb, - hsl = satus.color.rgbToHsl(rgb), - s = hsl[1] / 100, - l = hsl[2] / 100; - - s *= l < .5 ? l : 1 - l; - - var v = l + s; - - s = 2 * s / (l + s); - - satus.render({ - component: 'modal', - variant: 'color-picker', - value: hsl, - parent: this, - - palette: { - component: 'div', - class: 'satus-color-picker__palette', - style: { - 'backgroundColor': 'hsl(' + hsl[0] + 'deg, 100%, 50%)' - }, - on: { - mousedown: function () { - var palette = this, - rect = this.getBoundingClientRect(), - cursor = this.children[0]; - - function mousemove(event) { - var hsl = palette.skeleton.parent.value, - x = event.clientX - rect.left, - y = event.clientY - rect.top, - s; - - x = Math.min(Math.max(x, 0), rect.width) / (rect.width / 100); - y = Math.min(Math.max(y, 0), rect.height) / (rect.height / 100); - - var v = 100 - y, - l = (2 - x / 100) * v / 2; - - hsl[1] = x * v / (l < 50 ? l * 2 : 200 - l * 2); - hsl[2] = l; - - cursor.style.left = x + '%'; - cursor.style.top = y + '%'; - - palette.nextSibling.children[0].style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; - - event.preventDefault(); - } - - function mouseup() { - window.removeEventListener('mousemove', mousemove); - window.removeEventListener('mouseup', mouseup); - } - - window.addEventListener('mousemove', mousemove); - window.addEventListener('mouseup', mouseup); - } - }, - - cursor: { - component: 'div', - class: 'satus-color-picker__cursor', - style: { - 'left': s * 100 + '%', - 'top': 100 - v * 100 + '%' - } - } - }, - section: { - component: 'section', - variant: 'color', - - color: { - component: 'div', - class: 'satus-color-picker__color', - style: { - 'backgroundColor': 'rgb(' + this.rgb.join(',') + ')' - } - }, - hue: { - component: 'slider', - class: 'satus-color-picker__hue', - storage: false, - value: hsl[0], - max: 360, - on: { - change: function () { - var modal = this.skeleton.parent.parent, - hsl = modal.value; - - hsl[0] = this.values[0]; - - this.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg,' + hsl[1] + '%, ' + hsl[2] + '%)'; - this.parentNode.previousSibling.style.backgroundColor = 'hsl(' + hsl[0] + 'deg, 100%, 50%)'; - } - } - } - }, - actions: { - component: 'section', - variant: 'actions', - - reset: { - component: 'button', - text: 'reset', - on: { - click: function () { - var modal = this.skeleton.parent.parent, - component = modal.parent; - - component.rgb = component.skeleton.value; - - component.storageValue = component.rgb; - component.storageChange(); - - component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; - - modal.rendered.close(); - } - } - }, - cancel: { - component: 'button', - text: 'cancel', - on: { - click: function () { - this.skeleton.parent.parent.rendered.close(); - } - } - }, - ok: { - component: 'button', - text: 'OK', - on: { - click: function () { - var modal = this.skeleton.parent.parent, - component = modal.parent; - - component.rgb = satus.color.hslToRgb(modal.value); - - component.storageValue = component.rgb; - component.storageChange(); - - component.valueElement.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; - - modal.rendered.close(); - } - } - } - } - }); - }); - - component.addEventListener('render', function () { - component.rgb = this.storageValue || [0, 100, 50]; - - component_value.style.backgroundColor = 'rgb(' + component.rgb.join(',') + ')'; - }); - - return component; -}; -/*-------------------------------------------------------------- ->>> LIST ---------------------------------------------------------------*/ - -satus.components.list = function (skeleton) { - var ul = document.createElement('ul'); - - for (var i = 0, l = skeleton.items.length; i < l; i++) { - var li = document.createElement('li'), - item = skeleton.items[i]; - - li.className = 'satus-list__item'; - - for (var j = 0, k = item.length; j < k; j++) { - var child = item[j]; - - if (typeof child === 'string') { - var span = document.createElement('span'); - - span.textContent = satus.locale.get(child); - - li.appendChild(span); - } else { - satus.render(child, li); - } - } - - ul.appendChild(li); - } - - return ul; -}; -/*-------------------------------------------------------------- ->>> MODAL ---------------------------------------------------------------*/ - -satus.components.modal = function (skeleton) { - var component = document.createElement('div'), - scrim = document.createElement('div'), - surface = document.createElement('div'); - - component.inner = surface; - - scrim.className = 'satus-modal__scrim'; - surface.className = 'satus-modal__surface'; - - component.close = function () { - var component = this, - component_surface = this.children[1]; - - this.classList.add('satus-modal--closing'); - - setTimeout(function () { - component.remove(); - - component.dispatchEvent(new CustomEvent('close')); - }, satus.getAnimationDuration(component_surface)); - }; - - scrim.addEventListener('click', function () { - this.parentNode.close(); - }); - - component.appendChild(scrim); - component.appendChild(surface); - - return component; -}; \ No newline at end of file diff --git a/ui/script.js b/ui/script.js deleted file mode 100644 index d05015a..0000000 --- a/ui/script.js +++ /dev/null @@ -1,479 +0,0 @@ -/*-------------------------------------------------------------- ->>> POPUP: ----------------------------------------------------------------- -# Skeleton -# Functions -# Initialization ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# SKELETON ---------------------------------------------------------------*/ - -var skeleton = { - component: 'base', - - header: { - component: 'header', - - section_1: { - component: 'section', - variant: 'align-start', - - back: { - component: 'button', - attr: { - 'hidden': 'true' - }, - on: { - click: 'layers.back' - }, - - svg: { - component: 'svg', - attr: { - 'viewBox': '0 0 24 24', - 'fill': 'none', - 'stroke-width': '1.5', - 'stroke': 'currentColor' - }, - - path: { - component: 'path', - attr: { - 'd': 'M14 18l-6-6 6-6' - } - } - } - }, - title: { - component: 'span', - variant: 'title' - } - }, - section_2: { - component: 'section', - variant: 'align-end', - - menu: { - component: 'button', - on: { - click: { - component: 'modal', - variant: 'vertical', - - label: { - component: 'span', - text: 'theme' - }, - theme: { - component: 'tabs', - items: [ - 'light', - 'black' - ], - value: 'light' - }, - divider: { - component: 'divider' - }, - language: { - component: 'select', - on: { - change: function (name, value) { - var self = this; - - satus.ajax('_locales/' + this.querySelector('select').value + '/messages.json', function (response) { - response = JSON.parse(response); - - for (var key in response) { - satus.locale.strings[key] = response[key].message; - } - - self.base.skeleton.header.section_1.title.rendered.textContent = satus.locale.get('languages'); - - self.base.skeleton.layers.rendered.update(); - }); - } - }, - options: [{ - value: 'en', - text: 'English' - }, - { - value: 'he', - text: 'עברית' - }, { - value: 'ru', - text: 'Русский' - }, { - value: 'de', - text: 'Deutsch' - }, { - value: 'ar', - text: 'العربية' - }], - - svg: { - component: 'svg', - attr: { - 'viewBox': '0 0 24 24', - 'fill': 'currentColor' - }, - - path: { - component: 'path', - attr: { - 'd': 'M12.9 15l-2.6-2.4c1.8-2 3-4.2 3.8-6.6H17V4h-7V2H8v2H1v2h11.2c-.7 2-1.8 3.8-3.2 5.3-1-1-1.7-2.1-2.3-3.3h-2c.7 1.6 1.7 3.2 3 4.6l-5.1 5L4 19l5-5 3.1 3.1.8-2zm5.6-5h-2L12 22h2l1.1-3H20l1.1 3h2l-4.5-12zm-2.6 7l1.6-4.3 1.6 4.3H16z' - } - } - }, - label: { - component: 'span', - text: 'language' - } - }, - export: { - component: 'button', - on: { - click: function () { - if (location.href.indexOf('/options.html?action=export') !== -1) { - exportData(); - } else { - chrome.tabs.create({ - url: 'ui/options.html?action=export' - }); - } - } - }, - - svg: { - component: 'svg', - attr: { - 'viewBox': '0 0 24 24', - 'fill': 'none', - 'stroke': 'currentColor', - 'stroke-linecap': 'round', - 'stroke-linejoin': 'round', - 'stroke-width': '2' - }, - - path: { - component: 'path', - attr: { - 'd': 'M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M17 8l-5-5-5 5M12 3v12' - } - } - }, - label: { - component: 'span', - text: 'export' - } - }, - import: { - component: 'button', - on: { - click: function () { - if (location.href.indexOf('/options.html?action=import') !== -1) { - importData(); - } else { - chrome.tabs.create({ - url: 'ui/options.html?action=import' - }); - } - } - }, - - svg: { - component: 'svg', - attr: { - 'viewBox': '0 0 24 24', - 'fill': 'none', - 'stroke': 'currentColor', - 'stroke-linecap': 'round', - 'stroke-linejoin': 'round', - 'stroke-width': '2' - }, - - path: { - component: 'path', - attr: { - 'd': 'M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M7 10l5 5 5-5M12 15V3' - } - } - }, - label: { - component: 'span', - text: 'import' - } - } - } - }, - - svg: { - component: 'svg', - attr: { - 'viewBox': '0 0 24 24', - 'fill': 'currentColor' - }, - - circle_1: { - component: 'circle', - attr: { - 'cx': '12', - 'cy': '5.25', - 'r': '1' - } - }, - circle_2: { - component: 'circle', - attr: { - 'cx': '12', - 'cy': '12', - 'r': '1' - } - }, - circle_3: { - component: 'circle', - attr: { - 'cx': '12', - 'cy': '18.75', - 'r': '1' - } - } - } - } - } - }, - layers: { - component: 'layers', - on: { - open: function () { - var skeleton = this.path[this.path.length - 1], - parent = skeleton.parent, - section = this.base.skeleton.header.section_1, - is_home = this.path.length <= 1, - title = 'Auto Scroll'; - - if (parent) { - if (parent.label) { - title = parent.label.text; - } else if (parent.text) { - title = parent.text; - } - } - - section.back.rendered.hidden = is_home; - section.title.rendered.innerText = satus.locale.get(title); - } - }, - - toolbar: {}, - - section: { - component: 'section', - class: 'satus-section--card', - - auto_scroll: { - component: 'shortcut', - text: 'autoScrollActivation', - mouseButtons: true, - wheel: false - }, - drag_and_drop: { - component: 'shortcut', - text: 'dragDropActivation', - mouseButtons: true, - wheel: false - }, - touchscreen: { - component: 'shortcut', - text: 'touchscreenActivation', - mouseButtons: true, - wheel: false - } - }, - - made_with_love: { - component: 'a', - class: 'made-with-love', - attr: { - target: '_blank', - href: 'https://chrome.google.com/webstore/detail/improve-youtube-open-sour/bnomihfieiccainjcjblhegjgglakjdd' - }, - properties: { - innerHTML: 'Made with by ImprovedTube' - } - } - } -}; - - -/*-------------------------------------------------------------- -# FUNCTIONS ---------------------------------------------------------------*/ - -function exportData() { - if (location.href.indexOf('action=export') !== -1) { - var blob; - - try { - blob = new Blob([JSON.stringify(satus.storage.data)], { - type: 'application/json;charset=utf-8' - }); - } catch (error) { - return modalError(error); - } - - satus.render({ - component: 'modal', - - label: { - component: 'span', - text: 'areYouSureYouWantToExportTheData' - }, - actions: { - component: 'section', - variant: 'actions', - - ok: { - component: 'button', - text: 'ok', - on: { - click: function () { - try { - chrome.permissions.request({ - permissions: ['downloads'] - }, function (granted) { - if (granted) { - chrome.downloads.download({ - url: URL.createObjectURL(blob), - filename: 'auto-scroll.txt', - saveAs: true - }, function () { - setTimeout(function () { - close(); - }, 1000); - }); - } - }); - } catch (error) { - return modalError(error); - } - - this.parentNode.parentNode.parentNode.close(); - } - } - }, - cancel: { - component: 'button', - text: 'cancel', - on: { - click: function () { - this.parentNode.parentNode.parentNode.close(); - } - } - } - } - }); - } -} - -function importData() { - if (location.href.indexOf('action=import') !== -1) { - satus.render({ - component: 'modal', - - label: { - component: 'span', - text: 'areYouSureYouWantToImportTheData' - }, - actions: { - component: 'section', - variant: 'actions', - - ok: { - component: 'button', - text: 'ok', - on: { - click: function () { - var input = document.createElement('input'); - - input.type = 'file'; - - input.addEventListener('change', function () { - var file_reader = new FileReader(); - - file_reader.onload = function () { - var data = JSON.parse(this.result); - - for (var key in data) { - satus.storage.set(key, data[key]); - } - - close(); - }; - - file_reader.readAsText(this.files[0]); - }); - - input.click(); - - this.parentNode.parentNode.parentNode.close(); - } - } - }, - cancel: { - component: 'button', - text: 'cancel', - on: { - click: function () { - this.parentNode.parentNode.parentNode.close(); - } - } - } - } - }); - } -} - - -/*-------------------------------------------------------------- -# INITIALIZATION ---------------------------------------------------------------*/ - -satus.storage.attributes = { - theme: true -}; - -satus.storage.import(function (items) { - satus.locale.import(items.language, '../_locales/', function () { - chrome.tabs.query({ - active: true, - currentWindow: true - }, function (tabs) { - chrome.tabs.sendMessage(tabs[0].id, 'init', function (response) { - if (!response) { - skeleton.layers.toolbar = { - component: 'alert', - text: 'somethingWentWrongTryReloadingThePage', - variant: 'error' - }; - } else { - skeleton.layers.toolbar = { - component: 'switch', - class: 'satus-switch--domain', - text: response, - storage: 'domains/' + response, - value: true - }; - } - - satus.render(skeleton); - }); - }); - - exportData(); - importData(); - }); -}); \ No newline at end of file diff --git a/ui/styles.css b/ui/styles.css deleted file mode 100644 index 02e5b9a..0000000 --- a/ui/styles.css +++ /dev/null @@ -1,94 +0,0 @@ -/*-------------------------------------------------------------- ->>> POPUP: ----------------------------------------------------------------- -# Body -# Made with love ---------------------------------------------------------------*/ - -/*-------------------------------------------------------------- -# BODY ---------------------------------------------------------------*/ - - - - - - - - - - - - - - - - -.satus-switch--domain { - width: 100%; - margin: 8px 0 0; - height: 48px; - padding: 0 16px; - transition: 150ms; - color: #fff; - border: 1px solid rgb(246, 180, 101, .4); - border-radius: 8px; - background-color: rgb(246, 180, 101, .5); -} - -.satus-switch--domain[data-value='true'] .satus-switch__thumb { - background-color: #375a6c; -} - -.satus-switch--domain:focus, -.satus-switch--domain:hover { - color: #899ea9; - border-color: #2a4350; - background-color: #233843; -} - -.satus-alert { - width: 100%; - margin: 8px 0 0; -} - -.satus-section--label { - font-size: 14px; - font-weight: 600; -} - - -/*-------------------------------------------------------------- -# MADE WITH LOVE ---------------------------------------------------------------*/ - -.made-with-love { - font-size: 13px; - font-weight: 600; - position: absolute; - bottom: 16px; - left: 50%; - width: 100%; - height: auto; - min-height: auto; - padding: 0; - cursor: pointer; - transition: 150ms; - transform: translateX(-50%); - text-align: center; - text-decoration: none; - color: inherit; - justify-content: center; -} - -.made-with-love svg { - position: relative; - top: 4px; - width: 16px; - height: 16px; - fill: #f00; -} - -.made-with-love span { - margin: 0 0 0 4px; -} \ No newline at end of file