From 10e872cb4ab469c29f4060f364b365cad1739758 Mon Sep 17 00:00:00 2001 From: victor-savinov Date: Tue, 14 Jul 2020 18:55:48 +0300 Subject: [PATCH] v1.9 (fixes & polishing) --- _locales/en/messages.json | 3 + _locales/ru/messages.json | 3 + index.html | 4 + manifest.json | 3 +- popup.css | 902 ++++---- popup.js | 1754 ++++++++------- satus.css | 2759 ++++++++++++------------ satus.js | 4226 ++++++++++++++++++------------------- src/css/basic.css | 109 +- src/css/header.css | 86 +- src/css/main.css | 247 ++- src/css/themes.css | 26 +- src/js/header.js | 28 + src/js/index.js | 34 +- src/js/main.js | 63 +- 15 files changed, 5237 insertions(+), 5010 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 7363a8f..8728593 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -134,6 +134,9 @@ "systemPeference": { "message": "System preference" }, + "theListIsEmpty": { + "message": "The list is empty" + }, "theme": { "message": "Theme" }, diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index bdf185a..f36a6fa 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -143,6 +143,9 @@ "systemPeference": { "message": "Определено системой" }, + "theListIsEmpty": { + "message": "Список пуст" + }, "thisWillResetAllSettings": { "message": "This will reset all settings" }, diff --git a/index.html b/index.html index f0e33ba..a3c0f86 100644 --- a/index.html +++ b/index.html @@ -10,5 +10,9 @@ + +
+
+
\ No newline at end of file diff --git a/manifest.json b/manifest.json index 3bf1ceb..39ebe3a 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Night Mode", - "version": "1.8", + "version": "1.9", "description": "Dark Mode, read at night. Blue Light Filter for Every Website. Relax your eyes at night and day.", "default_locale": "en", @@ -47,6 +47,5 @@ ], "update_url": "https://clients2.google.com/service/update2/crx", - "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'" } diff --git a/popup.css b/popup.css index b5a9cef..f7d29b9 100644 --- a/popup.css +++ b/popup.css @@ -1,383 +1,521 @@ + +/*--------------------------------------------------------------- +>>> TABLE OF CONTENTS: +----------------------------------------------------------------- +1.0 Variables +2.0 Scroll bar +---------------------------------------------------------------*/ -/*--------------------------------------------------------------- ->>> TABLE OF CONTENTS: ------------------------------------------------------------------ -1.0 Variables -2.0 Scroll bar ----------------------------------------------------------------*/ - -/*--------------------------------------------------------------- -1.0 VARIABLES ----------------------------------------------------------------*/ - -html { - --satus-theme-primary: #e8bd70; - --background-1: #2c2b2c; - --text-1: #b5b5b5; - --icon-1: #e8bd70; - --satus-theme-surface: #343334; - --satus-theme-on-surface: #e5e5e5; - --satus-theme-on-surface: #e5e5e5; - --background-3: #2c2b2c; - --text-3: #b5b5b5; - --icon-3: #b5b5b5; -} - - -/*--------------------------------------------------------------- -2.0 SCROLL BAR ----------------------------------------------------------------*/ - -.satus-scrollbar__thumb::after { - background-color: rgba(255, 255, 255, .2); -} -/*--------------------------------------------------------------- ->>> TABLE OF CONTENTS: ------------------------------------------------------------------ -1.0 Fonts -2.0 Body ----------------------------------------------------------------*/ - -/*--------------------------------------------------------------- -1.0 FONTS ----------------------------------------------------------------*/ - -@font-face { - font-family: 'Open Sans'; - font-weight: 400; - src: url('assets/fonts/OpenSans-Regular.ttf'); -} - -@font-face { - font-family: 'Open Sans'; - font-weight: 700; - src: url('assets/fonts/OpenSans-SemiBold.ttf'); -} - - -/*--------------------------------------------------------------- -2.0 BODY ----------------------------------------------------------------*/ - -body { - font-family: 'Open Sans', sans-serif; - font-size: .875rem; - display: flex; - overflow: hidden; - flex-direction: column; - width: 18.75rem; - height: 31.25rem; - margin: 0; - background-color: #2c2b2c; -} -/*--------------------------------------------------------------- ->>> TABLE OF CONTENTS: ------------------------------------------------------------------ -1.0 Header -2.0 Buttons -3.0 Back button -4.0 Title -5.0 Right section -6.0 Switch ----------------------------------------------------------------*/ - -/*--------------------------------------------------------------- -1.0 HEADER ----------------------------------------------------------------*/ - -.satus-header { - z-index: 1; - box-shadow: 0 2px 4px rgba(0, 0, 0, .1); -} - - -/*--------------------------------------------------------------- -2.0 BUTTONS ----------------------------------------------------------------*/ - -.satus-header .satus-button { - width: 36px; - height: 36px; - padding: 6px; -} - -.satus-header .satus-button::before { - border-radius: 50%; -} - - -/*--------------------------------------------------------------- -3.0 BACK BUTTON ----------------------------------------------------------------*/ - -.satus-button--back { - position: absolute; -} - -.satus-button--back svg { - fill: none; - stroke: currentColor; -} - -body[data-appearance='home'] .satus-button--back { - visibility: hidden; -} - - -/*--------------------------------------------------------------- -4.0 TITLE ----------------------------------------------------------------*/ - -.satus-text--title { - font-size: .9375rem; - font-weight: 600; - position: absolute; - left: 56px; - letter-spacing: .0125em; -} - -body[data-appearance='home'] .satus-text--title { - left: 14px; -} - - -/*--------------------------------------------------------------- -5.0 RIGHT SECTION ----------------------------------------------------------------*/ - -.satus-section--align-end { - justify-content: flex-end; -} - - -/*--------------------------------------------------------------- -6.0 SWITCH ----------------------------------------------------------------*/ - -.satus-switch--night-mode { - padding: 0; -} - -.satus-switch--night-mode:hover { - background-color: transparent; -} - -.satus-switch--night-mode[data-value=false]>svg:last-child { - opacity: .5; -} - -.satus-switch--night-mode[data-value=true]>svg:first-child { - opacity: .5; -} - -.satus-switch--night-mode .satus-switch__track { - margin: 0 4px; -} -/*--------------------------------------------------------------- ->>> TABLE OF CONTENTS: ------------------------------------------------------------------ -1.0 Main -2.0 Section -3.0 Button -4.0 Folder -5.0 Swith -6.0 Textarea -7.0 Websites -8.0 Language -9.0 About -10.0 Made with love ----------------------------------------------------------------*/ - -/*--------------------------------------------------------------- -1.0 MAIN ----------------------------------------------------------------*/ - -.satus-main { - flex: 1; -} - -.satus-main, -.satus-main__container { - background-color: #2c2b2c; -} - - -/*--------------------------------------------------------------- -2.0 SECTION ----------------------------------------------------------------*/ - -.satus-main .satus-section { - display: block; - width: calc(100% - 16px); - max-width: 900px; - margin: 8px auto; - padding: 8px 0; - color: var(--satus-theme-on-surface, #777); - border: 1px solid rgba(0, 0, 0, .1); - border-radius: 8px; - background-color: var(--satus-theme-surface, #fff); -} - -.satus-main .satus-section--message { - padding-right: 8px; - padding-left: 8px; -} - - -/*--------------------------------------------------------------- -3.0 BUTTON ----------------------------------------------------------------*/ - -.satus-main .satus-button { - width: 100%; - height: 48px; - min-height: 48px; - padding: 0 16px; -} - - -/*--------------------------------------------------------------- -4.0 FOLDER ----------------------------------------------------------------*/ - -.satus-main .satus-folder svg { - width: 20px; - height: 20px; - margin: 0 14px 0 0; - stroke: none; - fill: var(--satus-theme-primary); -} - - -/*--------------------------------------------------------------- -5.0 SWITCH ----------------------------------------------------------------*/ - -.satus-switch:hover, -.satus-switch:hover input { - cursor: pointer; -} - -.satus-switch--night-mode { - width: auto; -} - -.satus-switch__icon { - width: 20px; - height: 20px; -} - - -/*--------------------------------------------------------------- -6.0 TEXTAREA ----------------------------------------------------------------*/ - -.satus-textarea { - width: calc(100% - 32px); -} - - -/*--------------------------------------------------------------- -7.0 WEBSITES ----------------------------------------------------------------*/ - -.satus-main__container[data-appearance=websites] .satus-section>.satus-section { - position: relative; - width: 100%; - margin: 0; - padding: 0; - border: none; - background: transparent; - box-shadow: none; -} - -.satus-main__container[data-appearance=websites] .satus-section>.satus-section .satus-switch { - position: absolute; - top: 0; - right: 0; - width: auto; - height: 100%; -} - -.satus[data-path='main/websites'] .satus-main .satus-section { - position: relative; - padding: 0; -} - -.satus[data-path='main/websites'] .satus-main .satus-section .satus-switch { - position: absolute; - top: 0; - right: 0; - width: auto; -} - - -/*--------------------------------------------------------------- -8.0 LANGUAGE ----------------------------------------------------------------*/ - -.satus-select[data-storage-key=language] { - padding-left: 50px; -} - -.satus-select[data-storage-key=language] svg { - position: absolute; - left: 16px; - width: 20px; - height: 20px; - stroke: none; - fill: var(--satus-theme-primary); -} - - -/*--------------------------------------------------------------- -9.0 ABOUT ----------------------------------------------------------------*/ - -.satus-main__container[data-appearance='about'] .satus-text { - display: flex; - box-sizing: border-box; - width: 100%; - min-height: 48px; - padding: 0 8px; - justify-content: space-between; - align-items: center; -} - -.satus-main__container[data-appearance='about'] .satus-text__value { - text-align: right; - opacity: .7; -} - - -/*--------------------------------------------------------------- -10.0 MADE WITH LOVE ----------------------------------------------------------------*/ - -.made-with-love { - font-size: 13px; - position: absolute; - bottom: 16px; - left: 50%; - width: 100%; - height: auto; - min-height: auto; - padding: 0; - cursor: pointer; - transform: translateX(-50%); - text-align: center; - color: var(--satus-theme-on-surface, #d62121); - justify-content: center; -} - -.made-with-love svg { - position: relative; - top: 4px; - width: 16px; - height: 16px; - fill: #d62121; -} - -.made-with-love span { - margin: 0 0 0 4px; -} \ No newline at end of file +/*--------------------------------------------------------------- +1.0 VARIABLES +---------------------------------------------------------------*/ + +/*.satus.dark { + --satus-theme-ripple: rgba(255, 255, 255, .04); + --satus-theme-primary: #e8bd70; + --background-1: #2c2b2c; + --text-1: #b5b5b5; + --icon-1: #e8bd70; + --satus-theme-surface: #343334; + --satus-theme-on-surface: #e5e5e5; + --satus-theme-on-surface: #e5e5e5; + --background-3: #2c2b2c; + --text-3: #b5b5b5; + --icon-3: #b5b5b5; +}*/ + +.satus.dark +{ + --satus-theme-primary: #f6b465; + + --satus-theme-dialog: #2c2b2c; + --satus-theme-dialog-text: #b5b5b5; + + --satus-theme-header: #343334; + --satus-theme-header-text: #b5b5b5; + + --satus-theme-main: #2c2b2c; + --satus-theme-main-text: #b5b5b5; + + --satus-theme-section: #343334; + + --satus-theme-button: transparent; + + --satus-theme-scrollbar: rgba(255, 255, 255, .2); + --satus-theme-scrollbar-focus: rgba(255, 255, 255, .4); + + --satus-theme-ripple: rgba(255, 255, 255, .04); +} + + +/*--------------------------------------------------------------- +2.0 SCROLL BAR +---------------------------------------------------------------*/ + +.satus-scrollbar__thumb::after { + background-color: rgba(255, 255, 255, .2); +} +/*--------------------------------------------------------------- +>>> TABLE OF CONTENTS: +----------------------------------------------------------------- +1.0 Fonts +2.0 Body +3.0 Button +---------------------------------------------------------------*/ + +/*--------------------------------------------------------------- +1.0 FONTS +---------------------------------------------------------------*/ + +@font-face +{ + font-family: 'Open Sans'; + font-weight: 400; + + src: url('assets/fonts/OpenSans-Regular.ttf'); +} + +@font-face +{ + font-family: 'Open Sans'; + font-weight: 700; + + src: url('assets/fonts/OpenSans-SemiBold.ttf'); +} + + +/*--------------------------------------------------------------- +2.0 BODY +---------------------------------------------------------------*/ + +body +{ + font-family: 'Open Sans', sans-serif; + font-size: .875rem; + + width: 300px; + height: 500px; + margin: 0; +} + +.satus +{ + position: absolute; + z-index: 1; + top: -250px; + left: -350px; + + overflow: hidden; + + width: 1000px; + height: 1000px; + + transition: all .5s linear, opacity .4s; + + opacity: 1; + border-radius: 50%; + background-color: var(--satus-theme-main); +} + +.satus__wrapper +{ + position: absolute; + top: 250px; + left: 350px; + + display: flex; + flex-direction: column; + + width: 300px; + height: 500px; + + transition: .5s linear; +} + + + + +.satus.loading +{ + top: 14px; + left: calc(100% - 64px); + + width: 32px; + height: 32px; + + transition: 0s linear; + + opacity: 0; +} + +.satus.loading .satus__wrapper +{ + top: -14px; + left: -236px; + + transition: 0s linear; +} + + +/*--------------------------------------------------------------- +3.0 BUTTON +---------------------------------------------------------------*/ + +button +{ + font-family: 'Open Sans', sans-serif; +} + +/*--------------------------------------------------------------- +>>> TABLE OF CONTENTS: +----------------------------------------------------------------- +1.0 Header +2.0 Buttons +3.0 Back button +4.0 Title +5.0 Right section +6.0 Switch +---------------------------------------------------------------*/ + +/*--------------------------------------------------------------- +1.0 HEADER +---------------------------------------------------------------*/ + +.satus-header +{ + z-index: 1; + + box-shadow: 0 2px 4px rgba(0, 0, 0, .1); +} + + +/*--------------------------------------------------------------- +2.0 BUTTONS +---------------------------------------------------------------*/ + +.satus-header .satus-button +{ + width: 36px; + height: 36px; + padding: 6px; +} + +.satus-header .satus-button::before +{ + border-radius: 50%; +} + + +/*--------------------------------------------------------------- +3.0 BACK BUTTON +---------------------------------------------------------------*/ + +.satus-button--back +{ + position: absolute; +} + +.satus-button--back svg +{ + fill: none; + stroke: currentColor; +} + +body[data-appearance='home'] .satus-button--back +{ + visibility: hidden; +} + + +/*--------------------------------------------------------------- +4.0 TITLE +---------------------------------------------------------------*/ + +.satus-text--title +{ + position: absolute; + left: 56px; +} + +body[data-appearance='home'] .satus-text--title +{ + left: 14px; +} + + +/*--------------------------------------------------------------- +5.0 RIGHT SECTION +---------------------------------------------------------------*/ + +.satus-section--align-end +{ + justify-content: flex-end; +} + + +/*--------------------------------------------------------------- +6.0 SWITCH +---------------------------------------------------------------*/ + +.satus-switch--night-mode +{ + padding: 0; +} + +.satus-switch--night-mode:hover +{ + background-color: transparent; +} + +.satus-switch--night-mode[data-value=false] > svg:last-child +{ + opacity: .5; +} + +.satus-switch--night-mode[data-value=true] > svg:first-child +{ + opacity: .5; +} + +.satus-switch--night-mode .satus-switch__track +{ + margin: 0 4px; +} + +/*--------------------------------------------------------------- +>>> TABLE OF CONTENTS: +----------------------------------------------------------------- +1.0 Main +2.0 Section +3.0 Button +4.0 Folder +5.0 Swith +6.0 Textarea +7.0 Websites +8.0 Language +9.0 About +10.0 Made with love +---------------------------------------------------------------*/ + +/*--------------------------------------------------------------- +1.0 MAIN +---------------------------------------------------------------*/ + +.satus-main +{ + flex: 1; +} + + +/*--------------------------------------------------------------- +2.0 SECTION +---------------------------------------------------------------*/ + +.satus-main .satus-section +{ + display: block; + + width: calc(100% - 16px); + max-width: 900px; + margin: 8px auto; + padding: 8px 0; + + border: 1px solid rgba(0, 0, 0, .1); + border-radius: 8px; +} + +.satus-main .satus-section--message +{ + padding-right: 8px; + padding-left: 8px; +} + + +/*--------------------------------------------------------------- +3.0 BUTTON +---------------------------------------------------------------*/ + +.satus-main .satus-button +{ + width: 100%; + height: 48px; + min-height: 48px; + padding: 0 16px; +} + + +/*--------------------------------------------------------------- +4.0 FOLDER +---------------------------------------------------------------*/ + +.satus-main .satus-folder svg +{ + width: 20px; + height: 20px; + margin: 0 14px 0 0; + + stroke: none; +} + + +/*--------------------------------------------------------------- +5.0 SWITCH +---------------------------------------------------------------*/ + +.satus-switch:hover, +.satus-switch:hover input +{ + cursor: pointer; +} + +.satus-switch--night-mode +{ + width: auto; +} + +.satus-switch__icon +{ + width: 20px; + height: 20px; +} + + +/*--------------------------------------------------------------- +6.0 TEXTAREA +---------------------------------------------------------------*/ + +.satus-textarea +{ + width: calc(100% - 32px); +} + + +/*--------------------------------------------------------------- +7.0 WEBSITES +---------------------------------------------------------------*/ + +.satus-main__container[data-appearance=websites] .satus-section > .satus-section +{ + position: relative; + + width: 100%; + margin: 0; + padding: 0; + + border: none; + background: transparent; + box-shadow: none; +} + +.satus-main__container[data-appearance=websites] .satus-section > .satus-section .satus-switch +{ + position: absolute; + top: 0; + right: 0; + + width: auto; + height: 100%; +} + +.satus[data-path='main/websites'] .satus-main .satus-section +{ + position: relative; + + padding: 0; +} + +.satus[data-path='main/websites'] .satus-main .satus-section .satus-switch +{ + position: absolute; + top: 0; + right: 0; + + width: auto; +} + + +/*--------------------------------------------------------------- +8.0 LANGUAGE +---------------------------------------------------------------*/ + +.satus-select[data-storage-key=language] +{ + padding-left: 50px; +} + +.satus-select[data-storage-key=language] svg +{ + position: absolute; + left: 16px; + + width: 20px; + height: 20px; + + stroke: none; +} + + +/*--------------------------------------------------------------- +9.0 ABOUT +---------------------------------------------------------------*/ + +.satus-main__container[data-appearance='about'] .satus-text +{ + display: flex; + + box-sizing: border-box; + width: 100%; + min-height: 48px; + padding: 0 8px; + + justify-content: space-between; + align-items: center; +} + +.satus-main__container[data-appearance='about'] .satus-text__value +{ + text-align: right; + + opacity: .7; +} + + +/*--------------------------------------------------------------- +10.0 MADE WITH LOVE +---------------------------------------------------------------*/ + +.made-with-love +{ + font-size: 13px; + + position: absolute; + bottom: 16px; + left: 50%; + + width: 100%; + height: auto; + min-height: auto; + padding: 0; + + cursor: pointer; + transform: translateX(-50%); + text-align: center; + + justify-content: center; +} + +.made-with-love svg +{ + position: relative; + top: 4px; + + width: 16px; + height: 16px; + + fill: #d62121; +} + +.made-with-love span +{ + margin: 0 0 0 4px; +} diff --git a/popup.js b/popup.js index ec4ccf2..72ef689 100644 --- a/popup.js +++ b/popup.js @@ -1,885 +1,873 @@ + +function update(container) { + var self = (this === window ? document.querySelector('.satus-main') : this), + item = self.history[self.history.length - 1], + id = item.appearanceKey; -function update(container) { - var self = (this === window ? document.querySelector('.satus-main') : this), - item = self.history[self.history.length - 1], - id = item.appearanceKey; - - if (!Satus.isset(container)) { - container = document.querySelector('.satus-main__container'); - } - - document.body.dataset.appearance = id; - container.dataset.appearance = id; - - document.querySelector('.satus-text--title').innerText = Satus.locale.getMessage(item.label) || 'Night Mode'; + if (!Satus.isset(container)) { + container = document.querySelector('.satus-main__container'); + } + + document.body.dataset.appearance = id; + container.dataset.appearance = id; + + document.querySelector('.satus-text--title').innerText = Satus.locale.getMessage(item.label) || 'Night Mode'; +} +/*----------------------------------------------------------------------------- +>>> «HEADER» TEMPLATE +-----------------------------------------------------------------------------*/ + +var HOSTNAME; + +var Menu = { + header: { + type: 'header', + + section_start: { + type: 'section', + class: 'satus-section--align-start', + + go_back: { + type: 'button', + class: 'satus-button--back', + before: '', + onclick: function() { + document.querySelector('.satus-main').back(); + } + }, + title: { + type: 'text', + class: 'satus-text--title', + label: 'Night Mode' + } + }, + section_end: { + type: 'section', + class: 'satus-section--align-end', + + mode: { + type: 'switch', + class: 'satus-switch--night-mode', + before: '', + after: '', + value: true, + onchange: function() { + var container = document.createElement('div'), + wrapper = document.createElement('div'); + + this.dataset.value = this.querySelector('input').checked; + + container.classList.add('satus'); + container.classList.add('loading'); + + wrapper.classList.add('satus__wrapper'); + + if (this.querySelector('input').checked) { + container.classList.add('dark'); + } + + Satus.render(Menu, wrapper); + + container.appendChild(wrapper); + + document.body.appendChild(container); + + setTimeout(function() { + container.classList.remove('loading'); + }); + + setTimeout(function() { + container.previousElementSibling.remove(); + }, 500); + }, + onrender: function() { + this.dataset.value = this.querySelector('input').checked; + } + } + } + } +}; +Menu.main = { + type: 'main', + appearanceKey: 'home', + on: { + change: update + }, + + section: { + type: 'section', + + only_on_this_website: { + type: 'button', + label: 'onlyEnableForThisWebsite', + onclick: function() { + var websites = Satus.storage.get('websites') || {}; + + for (var key in websites) { + if (key != HOSTNAME) { + Satus.storage.set('websites/' + key + '/enabled', false); + Satus.storage.set('websites/' + key + '/exclude_this_website', true); + } else { + Satus.storage.set('websites/' + key + '/enabled', true); + Satus.storage.set('websites/' + key + '/exclude_this_website', false); + document.querySelector('#exclude').dataset.value = false; + } + } + } + }, + exclude_this_website: { + type: 'switch', + label: 'excludeThisWebsite' + }, + filters: { + type: 'folder', + label: 'filters', + before: '', + + section: { + type: 'section', + + invert_colors: { + label: 'invertColors', + type: 'switch', + value: true + }, + bluelight: { + label: 'bluelight', + type: 'slider', + max: 90 + }, + brightness: { + label: 'brightness', + type: 'slider', + max: 100, + value: 100 + }, + contrast: { + label: 'contrast', + type: 'slider', + max: 100, + value: 100 + }, + grayscale: { + label: 'grayscale', + type: 'slider', + max: 100 + }, + sepia: { + label: 'sepia', + type: 'slider', + max: 100 + } + } + }, + styles: { + type: 'folder', + label: 'styles', + before: '', + + textfield: { + type: 'text-field', + placeholder: 'html, body { ... }', + style: { + margin: '16px', + height: 'calc(100vh - 96px)', + fontFamily: 'monospace' + }, + rows: 6, + onrender: function(object) { + this.dataset.storageKey = object.storage_key; + this.value = Satus.storage.get(object.storage_key) || ''; + }, + oninput: function() { + Satus.storage.set(this.dataset.storageKey, this.value); + } + } + }, + websites: { + type: 'folder', + label: 'websites', + appearanceKey: 'websites', + before: '', + + section: { + type: 'section' + } + }, + schedule: { + type: 'folder', + label: 'schedule', + before: '', + + ection: { + type: 'section', + + schedule: { + type: 'select', + label: 'schedule', + + options: [{ + label: 'disabled', + value: 'disabled' + }, { + label: 'sunsetToSunrise', + value: 'sunset_to_sunrise' + }, { + label: 'systemPeference', + value: 'system_peference' + }] + }, + time_from: { + type: 'select', + label: 'timeFrom', + options: [{ + label: '00:00', + value: '00:00' + }, { + label: '01:00', + value: '01:00' + }, { + label: '02:00', + value: '02:00' + }, { + label: '03:00', + value: '03:00' + }, { + label: '04:00', + value: '04:00' + }, { + label: '05:00', + value: '05:00' + }, { + label: '06:00', + value: '06:00' + }, { + label: '07:00', + value: '07:00' + }, { + label: '08:00', + value: '08:00' + }, { + label: '09:00', + value: '09:00' + }, { + label: '10:00', + value: '10:00' + }, { + label: '11:00', + value: '11:00' + }, { + label: '12:00', + value: '12:00' + }, { + label: '13:00', + value: '13:00' + }, { + label: '14:00', + value: '14:00' + }, { + label: '15:00', + value: '15:00' + }, { + label: '16:00', + value: '16:00' + }, { + label: '17:00', + value: '17:00' + }, { + label: '18:00', + value: '18:00' + }, { + label: '19:00', + value: '19:00' + }, { + label: '20:00', + value: '20:00' + }, { + label: '21:00', + value: '21:00' + }, { + label: '22:00', + value: '22:00' + }, { + label: '23:00', + value: '23:00' + }] + }, + time_to: { + type: 'select', + label: 'timeTo', + options: [{ + label: '00:00', + value: '00:00' + }, { + label: '01:00', + value: '01:00' + }, { + label: '02:00', + value: '02:00' + }, { + label: '03:00', + value: '03:00' + }, { + label: '04:00', + value: '04:00' + }, { + label: '05:00', + value: '05:00' + }, { + label: '06:00', + value: '06:00' + }, { + label: '07:00', + value: '07:00' + }, { + label: '08:00', + value: '08:00' + }, { + label: '09:00', + value: '09:00' + }, { + label: '10:00', + value: '10:00' + }, { + label: '11:00', + value: '11:00' + }, { + label: '12:00', + value: '12:00' + }, { + label: '13:00', + value: '13:00' + }, { + label: '14:00', + value: '14:00' + }, { + label: '15:00', + value: '15:00' + }, { + label: '16:00', + value: '16:00' + }, { + label: '17:00', + value: '17:00' + }, { + label: '18:00', + value: '18:00' + }, { + label: '19:00', + value: '19:00' + }, { + label: '20:00', + value: '20:00' + }, { + label: '21:00', + value: '21:00' + }, { + label: '22:00', + value: '22:00' + }, { + label: '23:00', + value: '23:00' + }] + } + } + }, + settings: { + type: 'folder', + before: '', + label: 'settings', + parent: '.satus-main__container', + + section: { + type: 'section', + + language: { + label: 'language', + type: 'select', + before: '', + onchange: function(name, value) { + Satus.memory.set('locale', {}); + + Satus.locale(function() { + document.querySelector('.satus-main__container').innerHTML = ''; + + document.querySelector('.satus-header__title').innerText = Satus.locale.getMessage('languages'); + document.querySelector('#search').placeholder = Satus.locale.getMessage('search'); + + Satus.render(document.querySelector('.satus-main__container'), Menu.main.section.settings.section.languages); + }); + }, + options: [{ + value: "en", + label: "English" + }, { + value: "ru", + label: "Русский" + }] + }, + backup_and_reset: { + type: 'folder', + label: 'backupAndReset', + before: '', + + section: { + type: 'section', + import_settings: { + type: 'button', + label: 'importSettings', + + onclick: function() { + try { + 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 i in data) { + Satus.storage.set(i, data[i]); + } + + Satus.render({ + type: 'dialog', + class: 'satus-dialog--confirm', + + message: { + type: 'text', + label: 'successfullyImportedSettings' + }, + section: { + type: 'section', + class: 'controls', + style: { + 'justify-content': 'flex-end', + 'display': 'flex' + }, + + cancel: { + type: 'button', + label: 'cancel', + onclick: function() { + var scrim = document.querySelectorAll('.satus-dialog__scrim'); + + scrim[scrim.length - 1].click(); + } + }, + ok: { + type: 'button', + label: 'OK', + onclick: function() { + var scrim = document.querySelectorAll('.satus-dialog__scrim'); + + scrim[scrim.length - 1].click(); + } + } + } + }); + }; + + file_reader.readAsText(this.files[0]); + }); + + input.click(); + } catch (err) { + chrome.runtime.sendMessage({ + name: 'dialog-error', + value: err + }); + } + } + }, + export_settings: { + type: 'button', + label: 'exportSettings', + + onclick: function() { + chrome.runtime.sendMessage({ + name: 'download', + filename: 'improvedtube-settings.json', + value: Satus.storage + }); + } + }, + reset_all_settings: { + type: 'button', + label: 'resetAllSettings', + + onclick: function() { + Satus.render({ + type: 'dialog', + class: 'satus-dialog--confirm', + + message: { + type: 'text', + label: 'thisWillResetAllSettings' + }, + section: { + type: 'section', + class: 'controls', + style: { + 'justify-content': 'flex-end', + 'display': 'flex' + }, + + cancel: { + type: 'button', + label: 'cancel', + onclick: function() { + var scrim = document.querySelectorAll('.satus-dialog__scrim'); + + scrim[scrim.length - 1].click(); + } + }, + accept: { + type: 'button', + label: 'accept', + onclick: function() { + var scrim = document.querySelectorAll('.satus-dialog__scrim'); + + Satus.storage.clear(); + + scrim[scrim.length - 1].click(); + } + } + } + }); + } + } + } + }, + date_and_time: { + type: 'folder', + label: 'dateAndTime', + before: '', + + section: { + type: 'section', + + use_24_hour_format: { + type: 'switch', + label: 'use24HourFormat', + value: true + } + } + }, + about: { + type: 'folder', + before: '', + label: 'about', + appearanceKey: 'about', + + section: { + type: 'section', + + onrender: function() { + var component = this, + manifest = chrome.runtime.getManifest(), + user = Satus.modules.user(), + object = { + extension_section: { + type: 'section', + label: 'extension', + style: { + 'flex-direction': 'column', + 'flex': '0' + }, + + version: { + type: 'text', + label: 'version', + value: manifest.version + }, + permissions: { + type: 'text', + label: 'permissions', + value: manifest.permissions.join(', ').replace('https://www.youtube.com/', 'YouTube') + }, + }, + browser_section: { + type: 'section', + label: 'browser', + style: { + 'flex-direction': 'column', + 'flex': '0' + }, + + name: { + type: 'text', + label: 'name', + value: user.browser.name + }, + version: { + type: 'text', + label: 'version', + value: user.browser.version + }, + platform: { + type: 'text', + label: 'platform', + value: user.browser.platform + }, + video_formats: { + type: 'text', + label: 'videoFormats', + value: user.browser.video + }, + audio_formats: { + type: 'text', + label: 'audioFormats', + value: user.browser.audio + }, + flash: { + type: 'text', + label: 'flash', + value: user.browser.flash ? true : false + } + }, + os_section: { + type: 'section', + label: 'os', + style: { + 'flex-direction': 'column', + 'flex': '0' + }, + + os_name: { + type: 'text', + label: 'name', + value: user.os.name + }, + + os_type: { + type: 'text', + label: 'type', + value: user.os.type + } + }, + device_section: { + type: 'section', + label: 'device', + style: { + 'flex-direction': 'column', + 'flex': '0' + }, + + screen: { + type: 'text', + label: 'screen', + value: user.device.screen + }, + cores: { + type: 'text', + label: 'cores', + value: user.device.cores + }, + gpu: { + type: 'text', + label: 'gpu', + value: user.device.gpu + }, + ram: { + type: 'text', + label: 'ram', + value: user.device.ram + } + } + }; + + setTimeout(function() { + Satus.render(object, component.parentNode); + + component.remove(); + }); + } + } + } + } + } + }, + + made_with_love: { + type: 'text', + class: 'made-with-love', + innerHTML: 'Made with by ImprovedTube', + onclick: function() { + window.open('https://chrome.google.com/webstore/detail/improve-youtube-open-sour/bnomihfieiccainjcjblhegjgglakjdd'); + } + } +}; +/*--------------------------------------------------------------- +>>> TABLE OF CONTENTS: +----------------------------------------------------------------- +1.0 +---------------------------------------------------------------*/ + +/*--------------------------------------------------------------- +1.0 +---------------------------------------------------------------*/ + +function init(response) { + var TAB_URL = response ? new URL(response) : '', + language = Satus.storage.get('language') || 'en'; + + HOSTNAME = TAB_URL.hostname || 'empty'; + + Satus.storage.import(function() { + if (!Satus.isset(Satus.storage.get('mode')) || Satus.storage.get('mode') === true) { + document.querySelector('.satus').classList.add('dark'); + } + + Satus.locale.import('_locales/' + language + '/messages.json', function() { + Satus.modules.updateStorageKeys(Menu, function() { + Menu.main.section.exclude_this_website.storage_key = 'websites/' + HOSTNAME + '/exclude_this_website'; + Menu.main.section.filters.section.invert_colors.storage_key = 'websites/' + HOSTNAME + '/filters/invert_colors'; + Menu.main.section.filters.section.bluelight.storage_key = 'websites/' + HOSTNAME + '/filters/bluelight'; + Menu.main.section.filters.section.brightness.storage_key = 'websites/' + HOSTNAME + '/filters/brightness'; + Menu.main.section.filters.section.contrast.storage_key = 'websites/' + HOSTNAME + '/filters/contrast'; + Menu.main.section.filters.section.grayscale.storage_key = 'websites/' + HOSTNAME + '/filters/grayscale'; + Menu.main.section.filters.section.sepia.storage_key = 'websites/' + HOSTNAME + '/filters/sepia'; + + Menu.main.section.styles.textfield.storage_key = 'websites/' + HOSTNAME + '/styles'; + + var websites = Satus.storage.get('websites') || {}, + count = 0; + + for (var key in websites) { + if (key !== 'empty') { + count++; + + Menu.main.section.websites.section[key] = { + type: 'section', + + folder: { + type: 'folder', + label: key, + + section: { + type: 'section', + + filters: { + type: 'folder', + label: 'filters', + before: '', + + section: { + type: 'section', + + invert_colors: { + label: 'invertColors', + type: 'switch', + value: true, + storage_key: 'websites/' + key + '/filters/invert_colors' + }, + bluelight: { + label: 'bluelight', + type: 'slider', + max: 90, + storage_key: 'websites/' + key + '/filters/bluelight' + }, + brightness: { + label: 'brightness', + type: 'slider', + max: 100, + value: 100, + storage_key: 'websites/' + key + '/filters/brightness' + }, + contrast: { + label: 'contrast', + type: 'slider', + max: 100, + value: 100, + storage_key: 'websites/' + key + '/filters/contrast' + }, + grayscale: { + label: 'grayscale', + type: 'slider', + max: 100, + storage_key: 'websites/' + key + '/filters/grayscale' + }, + sepia: { + label: 'sepia', + type: 'slider', + max: 100, + storage_key: 'websites/' + key + '/filters/sepia' + } + } + }, + styles: { + type: 'folder', + label: 'styles', + before: '', + + textfield: { + type: 'text-field', + placeholder: 'html, body { ... }', + style: { + margin: '16px', + height: 'calc(100vh - 96px)', + fontFamily: 'monospace' + }, + rows: 6, + storage_key: 'websites/' + key + '/styles', + onrender: function(object) { + this.dataset.storageKey = object.storage_key; + this.value = Satus.storage.get(object.storage_key) || ''; + }, + oninput: function() { + Satus.storage.set(this.dataset.storageKey, this.value); + } + } + } + } + }, + enabled: { + type: 'switch', + storage_key: 'websites/' + key + '/exclude_this_website', + onrender: function(obj) { + var item = this.querySelector('input'); + + item.checked = item.checked ? false : true; + }, + onchange: function(obj) { + var item = this.querySelector('input'); + + Satus.storage.set(item.dataset.storageKey, item.checked ? false : true); + } + } + }; + } + } + + if (count === 0) { + Menu.main.section.websites.section.message = { + type: 'text', + label: 'theListIsEmpty', + style: { + 'display': 'block', + 'text-align': 'center', + 'margin': '32px 0' + } + }; + } + + Satus.render(Menu, document.querySelector('.satus__wrapper')); + }); + }); + }); } -/*----------------------------------------------------------------------------- ->>> «HEADER» TEMPLATE ------------------------------------------------------------------------------*/ - -var Menu = { - header: { - type: 'header', - - section_start: { - type: 'section', - class: 'satus-section--align-start', - - go_back: { - type: 'button', - class: 'satus-button--back', - before: '', - onclick: function() { - document.querySelector('.satus-main').back(); - } - }, - title: { - type: 'text', - class: 'satus-text--title', - label: 'Night Mode' - } - }, - section_end: { - type: 'section', - class: 'satus-section--align-end', - - mode: { - type: 'switch', - class: 'satus-switch--night-mode', - before: '', - after: '', - value: true, - onchange: function() { - this.dataset.value = this.querySelector('input').checked; - }, - onrender: function() { - this.dataset.value = this.querySelector('input').checked; - } - } - } - } -}; -Menu.main = { - type: 'main', - appearanceKey: 'home', - on: { - change: update - }, - - section: { - type: 'section', - - only_on_this_website: { - type: 'button', - label: 'onlyEnableForThisWebsite', - onclick: function() { - var websites = Satus.storage.get('websites'); - - for (var key in websites) { - if (key != HOSTNAME) { - Satus.storage.set('websites/' + key + '/enabled', false); - Satus.storage.set('websites/' + key + '/exclude_this_website', true); - } else { - Satus.storage.set('websites/' + key + '/enabled', true); - Satus.storage.set('websites/' + key + '/exclude_this_website', false); - document.querySelector('#exclude').dataset.value = false; - } - } - } - }, - exclude_this_website: { - type: 'switch', - label: 'excludeThisWebsite' - }, - filters: { - type: 'folder', - label: 'filters', - before: '', - - section: { - type: 'section', - - invert_colors: { - label: 'invertColors', - type: 'switch', - value: true - }, - bluelight: { - label: 'bluelight', - type: 'slider', - max: 90 - }, - brightness: { - label: 'brightness', - type: 'slider', - max: 100, - value: 100 - }, - contrast: { - label: 'contrast', - type: 'slider', - max: 100, - value: 100 - }, - grayscale: { - label: 'grayscale', - type: 'slider', - max: 100 - }, - sepia: { - label: 'sepia', - type: 'slider', - max: 100 - } - } - }, - styles: { - type: 'folder', - label: 'styles', - before: '', - - textfield: { - type: 'text-field', - placeholder: 'html, body { ... }', - style: { - margin: '16px', - height: 'calc(100vh - 96px)', - fontFamily: 'monospace' - }, - rows: 6, - onrender: function(object) { - this.dataset.storageKey = object.storage_key; - this.value = Satus.storage.get(object.storage_key) || ''; - }, - oninput: function() { - Satus.storage.set(this.dataset.storageKey, this.value); - } - } - }, - websites: { - type: 'folder', - label: 'websites', - appearanceKey: 'websites', - before: '', - - section: { - type: 'section' - } - }, - schedule: { - type: 'folder', - label: 'schedule', - before: '', - - ection: { - type: 'section', - - schedule: { - type: 'select', - label: 'schedule', - - options: [{ - label: 'disabled', - value: 'disabled' - }, { - label: 'sunsetToSunrise', - value: 'sunset_to_sunrise' - }, { - label: 'systemPeference', - value: 'system_peference' - }] - }, - time_from: { - type: 'select', - label: 'timeFrom', - options: [{ - label: '00:00', - value: '00:00' - }, { - label: '01:00', - value: '01:00' - }, { - label: '02:00', - value: '02:00' - }, { - label: '03:00', - value: '03:00' - }, { - label: '04:00', - value: '04:00' - }, { - label: '05:00', - value: '05:00' - }, { - label: '06:00', - value: '06:00' - }, { - label: '07:00', - value: '07:00' - }, { - label: '08:00', - value: '08:00' - }, { - label: '09:00', - value: '09:00' - }, { - label: '10:00', - value: '10:00' - }, { - label: '11:00', - value: '11:00' - }, { - label: '12:00', - value: '12:00' - }, { - label: '13:00', - value: '13:00' - }, { - label: '14:00', - value: '14:00' - }, { - label: '15:00', - value: '15:00' - }, { - label: '16:00', - value: '16:00' - }, { - label: '17:00', - value: '17:00' - }, { - label: '18:00', - value: '18:00' - }, { - label: '19:00', - value: '19:00' - }, { - label: '20:00', - value: '20:00' - }, { - label: '21:00', - value: '21:00' - }, { - label: '22:00', - value: '22:00' - }, { - label: '23:00', - value: '23:00' - }] - }, - time_to: { - type: 'select', - label: 'timeTo', - options: [{ - label: '00:00', - value: '00:00' - }, { - label: '01:00', - value: '01:00' - }, { - label: '02:00', - value: '02:00' - }, { - label: '03:00', - value: '03:00' - }, { - label: '04:00', - value: '04:00' - }, { - label: '05:00', - value: '05:00' - }, { - label: '06:00', - value: '06:00' - }, { - label: '07:00', - value: '07:00' - }, { - label: '08:00', - value: '08:00' - }, { - label: '09:00', - value: '09:00' - }, { - label: '10:00', - value: '10:00' - }, { - label: '11:00', - value: '11:00' - }, { - label: '12:00', - value: '12:00' - }, { - label: '13:00', - value: '13:00' - }, { - label: '14:00', - value: '14:00' - }, { - label: '15:00', - value: '15:00' - }, { - label: '16:00', - value: '16:00' - }, { - label: '17:00', - value: '17:00' - }, { - label: '18:00', - value: '18:00' - }, { - label: '19:00', - value: '19:00' - }, { - label: '20:00', - value: '20:00' - }, { - label: '21:00', - value: '21:00' - }, { - label: '22:00', - value: '22:00' - }, { - label: '23:00', - value: '23:00' - }] - } - } - }, - settings: { - type: 'folder', - before: '', - label: 'settings', - parent: '.satus-main__container', - onclick: function() { - document.querySelector('.satus-dialog__scrim').click(); - }, - - section: { - type: 'section', - - language: { - label: 'language', - type: 'select', - before: '', - onchange: function(name, value) { - Satus.memory.set('locale', {}); - - Satus.locale(function() { - document.querySelector('.satus-main__container').innerHTML = ''; - - document.querySelector('.satus-header__title').innerText = Satus.locale.getMessage('languages'); - document.querySelector('#search').placeholder = Satus.locale.getMessage('search'); - - Satus.render(document.querySelector('.satus-main__container'), Menu.main.section.settings.section.languages); - }); - }, - options: [{ - value: "en", - label: "English" - }, { - value: "ru", - label: "Русский" - }] - }, - backup_and_reset: { - type: 'folder', - label: 'backupAndReset', - before: '', - - section: { - type: 'section', - import_settings: { - type: 'button', - label: 'importSettings', - - onclick: function() { - try { - 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 i in data) { - Satus.storage.set(i, data[i]); - } - - Satus.render({ - type: 'dialog', - class: 'satus-dialog--confirm', - - message: { - type: 'text', - label: 'successfullyImportedSettings' - }, - section: { - type: 'section', - class: 'controls', - style: { - 'justify-content': 'flex-end', - 'display': 'flex' - }, - - cancel: { - type: 'button', - label: 'cancel', - onclick: function() { - var scrim = document.querySelectorAll('.satus-dialog__scrim'); - - scrim[scrim.length - 1].click(); - } - }, - ok: { - type: 'button', - label: 'OK', - onclick: function() { - var scrim = document.querySelectorAll('.satus-dialog__scrim'); - - scrim[scrim.length - 1].click(); - } - } - } - }); - }; - - file_reader.readAsText(this.files[0]); - }); - - input.click(); - } catch (err) { - chrome.runtime.sendMessage({ - name: 'dialog-error', - value: err - }); - } - } - }, - export_settings: { - type: 'button', - label: 'exportSettings', - - onclick: function() { - chrome.runtime.sendMessage({ - name: 'download', - filename: 'improvedtube-settings.json', - value: Satus.storage - }); - } - }, - reset_all_settings: { - type: 'button', - label: 'resetAllSettings', - - onclick: function() { - Satus.render({ - type: 'dialog', - class: 'satus-dialog--confirm', - - message: { - type: 'text', - label: 'thisWillResetAllSettings' - }, - section: { - type: 'section', - class: 'controls', - style: { - 'justify-content': 'flex-end', - 'display': 'flex' - }, - - cancel: { - type: 'button', - label: 'cancel', - onclick: function() { - var scrim = document.querySelectorAll('.satus-dialog__scrim'); - - scrim[scrim.length - 1].click(); - } - }, - accept: { - type: 'button', - label: 'accept', - onclick: function() { - var scrim = document.querySelectorAll('.satus-dialog__scrim'); - - Satus.storage.clear(); - - scrim[scrim.length - 1].click(); - } - } - } - }); - } - }, - delete_youtube_cookies: { - type: 'button', - label: 'deleteYoutubeCookies', - - onclick: function() { - document.querySelector('.satus').appendChild(Satus.components.dialog({ - type: 'dialog', - - message: { - type: 'text', - label: 'thisWillRemoveAllYouTubeCookies', - style: { - 'width': '100%', - 'opacity': '.8' - } - }, - section: { - type: 'section', - class: 'controls', - style: { - 'justify-content': 'flex-end', - 'display': 'flex' - }, - - cancel: { - type: 'button', - label: 'cancel', - onclick: function() { - var scrim = document.querySelectorAll('.satus-dialog__scrim'); - - scrim[scrim.length - 1].click(); - } - }, - accept: { - type: 'button', - label: 'accept', - onclick: function() { - var scrim = document.querySelectorAll('.satus-dialog__scrim'); - - chrome.tabs.query({}, function(tabs) { - for (var i = 0, l = tabs.length; i < l; i++) { - if (tabs[i].hasOwnProperty('url')) { - chrome.tabs.sendMessage(tabs[i].id, { - name: 'delete_youtube_cookies' - }); - } - } - }); - - scrim[scrim.length - 1].click(); - } - } - } - })); - } - } - } - }, - date_and_time: { - type: 'folder', - label: 'dateAndTime', - before: '', - - section: { - type: 'section', - - use_24_hour_format: { - type: 'switch', - label: 'use24HourFormat', - value: true - } - } - }, - about: { - type: 'folder', - before: '', - label: 'about', - appearanceKey: 'about', - - section: { - type: 'section', - - onrender: function() { - var component = this, - manifest = chrome.runtime.getManifest(), - user = Satus.modules.user(), - object = { - extension_section: { - type: 'section', - label: 'extension', - style: { - 'flex-direction': 'column', - 'flex': '0' - }, - - version: { - type: 'text', - label: 'version', - value: manifest.version - }, - permissions: { - type: 'text', - label: 'permissions', - value: manifest.permissions.join(', ').replace('https://www.youtube.com/', 'YouTube') - }, - }, - browser_section: { - type: 'section', - label: 'browser', - style: { - 'flex-direction': 'column', - 'flex': '0' - }, - - name: { - type: 'text', - label: 'name', - value: user.browser.name - }, - version: { - type: 'text', - label: 'version', - value: user.browser.version - }, - platform: { - type: 'text', - label: 'platform', - value: user.browser.platform - }, - video_formats: { - type: 'text', - label: 'videoFormats', - value: user.browser.video - }, - audio_formats: { - type: 'text', - label: 'audioFormats', - value: user.browser.audio - }, - flash: { - type: 'text', - label: 'flash', - value: user.browser.flash ? true : false - } - }, - os_section: { - type: 'section', - label: 'os', - style: { - 'flex-direction': 'column', - 'flex': '0' - }, - - os_name: { - type: 'text', - label: 'name', - value: user.os.name - }, - - os_type: { - type: 'text', - label: 'type', - value: user.os.type - } - }, - device_section: { - type: 'section', - label: 'device', - style: { - 'flex-direction': 'column', - 'flex': '0' - }, - - screen: { - type: 'text', - label: 'screen', - value: user.device.screen - }, - cores: { - type: 'text', - label: 'cores', - value: user.device.cores - }, - gpu: { - type: 'text', - label: 'gpu', - value: user.device.gpu - }, - ram: { - type: 'text', - label: 'ram', - value: user.device.ram - } - } - }; - - setTimeout(function() { - Satus.render(object, component.parentNode); - - component.remove(); - }); - } - } - } - } - } - }, - - made_with_love: { - type: 'text', - class: 'made-with-love', - innerHTML: 'Made with by ImprovedTube', - onclick: function() { - window.open('https://chrome.google.com/webstore/detail/improve-youtube-open-sour/bnomihfieiccainjcjblhegjgglakjdd'); - } - } -}; - -/*--------------------------------------------------------------- ->>> TABLE OF CONTENTS: ------------------------------------------------------------------ -1.0 ----------------------------------------------------------------*/ - -/*--------------------------------------------------------------- -1.0 ----------------------------------------------------------------*/ - -function init(response) { - var TAB_URL = response ? new URL(response) : '', - HOSTNAME = TAB_URL.hostname || 'empty', - language = Satus.storage.get('language') || 'en'; - - Satus.storage.import(function() { - Satus.locale.import('_locales/' + language + '/messages.json', function() { - Satus.modules.updateStorageKeys(Menu, function() { - Menu.main.section.exclude_this_website.storage_key = 'websites/' + HOSTNAME + '/exclude_this_website'; - Menu.main.section.filters.section.invert_colors.storage_key = 'websites/' + HOSTNAME + '/filters/invert_colors'; - Menu.main.section.filters.section.bluelight.storage_key = 'websites/' + HOSTNAME + '/filters/bluelight'; - Menu.main.section.filters.section.brightness.storage_key = 'websites/' + HOSTNAME + '/filters/brightness'; - Menu.main.section.filters.section.contrast.storage_key = 'websites/' + HOSTNAME + '/filters/contrast'; - Menu.main.section.filters.section.grayscale.storage_key = 'websites/' + HOSTNAME + '/filters/grayscale'; - Menu.main.section.filters.section.sepia.storage_key = 'websites/' + HOSTNAME + '/filters/sepia'; - - Menu.main.section.styles.textfield.storage_key = 'websites/' + HOSTNAME + '/styles'; - - var websites = Satus.storage.get('websites') || {}; - - for (var key in websites) { - if (key !== 'empty') { - Menu.main.section.websites.section[key] = { - type: 'section', - - folder: { - type: 'folder', - label: key, - - section: { - type: 'section', - - filters: { - type: 'folder', - label: 'filters', - before: '', - - section: { - type: 'section', - - invert_colors: { - label: 'invertColors', - type: 'switch', - value: true, - storage_key: 'websites/' + key + '/filters/invert_colors' - }, - bluelight: { - label: 'bluelight', - type: 'slider', - max: 90, - storage_key: 'websites/' + key + '/filters/bluelight' - }, - brightness: { - label: 'brightness', - type: 'slider', - max: 100, - value: 100, - storage_key: 'websites/' + key + '/filters/brightness' - }, - contrast: { - label: 'contrast', - type: 'slider', - max: 100, - value: 100, - storage_key: 'websites/' + key + '/filters/contrast' - }, - grayscale: { - label: 'grayscale', - type: 'slider', - max: 100, - storage_key: 'websites/' + key + '/filters/grayscale' - }, - sepia: { - label: 'sepia', - type: 'slider', - max: 100, - storage_key: 'websites/' + key + '/filters/sepia' - } - } - }, - styles: { - type: 'folder', - label: 'styles', - before: '', - - textfield: { - type: 'text-field', - placeholder: 'html, body { ... }', - style: { - margin: '16px', - height: 'calc(100vh - 96px)', - fontFamily: 'monospace' - }, - rows: 6, - storage_key: 'websites/' + key + '/styles', - onrender: function(object) { - this.dataset.storageKey = object.storage_key; - this.value = Satus.storage.get(object.storage_key) || ''; - }, - oninput: function() { - Satus.storage.set(this.dataset.storageKey, this.value); - } - } - } - } - }, - enabled: { - type: 'switch', - storage_key: 'websites/' + key + '/exclude_this_website', - onrender: function(obj) { - var item = this.querySelector('input'); - - item.checked = item.checked ? false : true; - }, - onchange: function(obj) { - var item = this.querySelector('input'); - - Satus.storage.set(item.dataset.storageKey, item.checked ? false : true); - } - } - }; - } - } - - Satus.render(Menu, document.body); - }); - }); - }); -} - -chrome.tabs.query({ - currentWindow: true, - active: true -}, function(tabs) { - if (tabs[0].hasOwnProperty('url')) { - chrome.tabs.sendMessage(tabs[0].id, 'requestTabUrl', init); - } else { - init(); - } -}); + +chrome.tabs.query({ + currentWindow: true, + active: true +}, function(tabs) { + if (tabs[0].hasOwnProperty('url')) { + chrome.tabs.sendMessage(tabs[0].id, 'requestTabUrl', init); + } else { + init(); + } +}); \ No newline at end of file diff --git a/satus.css b/satus.css index 5fbfaa1..af05ba1 100644 --- a/satus.css +++ b/satus.css @@ -1,1392 +1,1369 @@ + +/*-------------------------------------------------------------- +>>> BUTTON +--------------------------------------------------------------*/ -/*-------------------------------------------------------------- ->>> BUTTON ---------------------------------------------------------------*/ - -.satus-button -{ - font-size: inherit; - - position: relative; - - display: flex; - - margin: 0; - - cursor: pointer; - - color: inherit; - border: none; - outline: none; - background-color: var(--satus-theme-button, transparent); - - -webkit-tap-highlight-color: transparent; - align-items: center; - -webkit-appearance: none; -} - -.satus-button::before -{ - position: absolute; - top: 0; - left: 0; - - width: 100%; - height: 100%; - - content: ''; - - opacity: 0; - background-color: var(--satus-theme-button, #000); -} - -.satus-button:focus::before, -.satus-button:hover::before -{ - opacity: .04; -} - -.satus-button__icon -{ - width: 24px; - height: 24px; -} - -.satus-button svg -{ - width: 100%; - - color: inherit; - - fill: currentColor; -} - -.satus-button__icon + .satus-button__label -{ - margin-left: 8px; -} - -/*-------------------------------------------------------------- ->>> COLOR PICKER ---------------------------------------------------------------*/ - -.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, transparent); - - justify-content: space-between; - -webkit-tap-highlight-color: transparent; - align-items: center; - -webkit-appearance: none; -} - -.satus-color-picker__value -{ - width: 24px; - height: 24px; - - border-radius: 50%; -} - -.satus-dialog--color-picker .satus-scrollbar__content -{ - display: flex; - flex-direction: column; - - align-items: center; -} - -.satus-dialog--color-picker .satus-button -{ - box-sizing: unset; - width: 24px; - height: 24px; - margin: 0 0 8px; - padding: 8px; - - border-radius: 50%; -} - -.satus-dialog--color-picker .satus-button:hover -{ - background-color: rgba(0,0,0,.1); -} - -.satus-dialog--color-picker .satus-button::before -{ - content: unset; -} - -.satus-dialog--color-picker .satus-button svg -{ - fill: transparent; - stroke: currentColor; -} - -.satus-dialog--color-picker canvas -{ - width: 200px; - height: 200px; - margin: 0 0 16px; -} - -/*-------------------------------------------------------------- ->>> DIALOG ---------------------------------------------------------------*/ - -.satus-dialog -{ - position: absolute; - z-index: 100; - top: 0; - left: 0; - - display: flex; - - width: 100%; - height: 100vh; - - justify-content: center; - align-items: center; -} - -.satus-dialog__scrim -{ - position: absolute; - top: 0; - left: 0; - - width: 100%; - height: 100%; - - animation: fadeIn 150ms linear forwards; - - opacity: 0; - background: rgba(25,25,25,.2); - - fill: var(--satus-theme-on-surface, #777); - backdrop-filter: blur(8px); -} - -.satus-dialog__surface -{ - font-size: 14px; - - display: flex; - flex-direction: column; - - width: 95%; - min-width: 240px; - max-width: 560px; - max-height: 80%; - padding: 8px 0; - - transform: scale(.8); - animation: zoomIn 150ms linear forwards; - animation-delay: 20ms; - - opacity: 0; - color: var(--satus-theme-on-surface, #777); - border-radius: 6px; - background-color: var(--satus-theme-surface, #f7f7f6); - box-shadow: inset 0 -1px 1px 1px rgba(0,0,0,.1), 0 2px 6px rgba(0, 0, 0, .15); -} - -.satus-dialog--closing .satus-dialog__scrim -{ - animation: fadeOut 70ms linear forwards; -} - -.satus-dialog--closing .satus-dialog__surface -{ - animation: zoomOut 70ms linear forwards; -} - -@keyframes fadeIn -{ - from - { - opacity: 0; - } - to - { - opacity: 1; - } -} - -@keyframes fadeOut -{ - from - { - opacity: 1; - } - to - { - opacity: 0; - } -} - -@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; - } -} - -/*-------------------------------------------------------------- ->>> FOLDER ---------------------------------------------------------------*/ - -.satus-folder -{ - font-size: inherit; - - display: flex; - - box-sizing: border-box; - width: 100%; - height: 48px; - margin: 0; - padding: 0 16px; - - cursor: pointer; - - color: inherit; - border: none; - outline: none; - background-color: var(--satus-theme-button, transparent); - - -webkit-tap-highlight-color: transparent; - align-items: center; - -webkit-appearance: none; -} - -.satus-folder:focus, -.satus-folder:hover -{ - background-color: rgba(0,0,0,.04); -} - -/*-------------------------------------------------------------- ->>> HEADER ---------------------------------------------------------------*/ - -.satus-header -{ - position: relative; - z-index: 1; - - display: flex; - - box-sizing: border-box; - width: 100%; - min-height: 58px; - padding: 0 8px; - - color: var(--satus-theme-on-surface, #777); - background-color: var(--satus-theme-surface, #fff); - box-shadow: 0 0 3px rgba(0,0,0,.1); - - fill: var(--satus-theme-on-surface, #777); -} - -/*-------------------------------------------------------------- ->>> LIST ---------------------------------------------------------------*/ - -.satus-list--compact, -.satus-list--compact li -{ - margin: 0; - padding: 0; - - list-style: none; -} - -/*----------------------------------------------------------------------------- ->>> MAIN -------------------------------------------------------------------------------- -1.0 General -2.0 Animations - 2.1 Opening - 2.2 Closing ------------------------------------------------------------------------------*/ - -/*----------------------------------------------------------------------------- -1.0 General ------------------------------------------------------------------------------*/ - -.satus-main -{ - position: relative; - - overflow: hidden; - - width: 100%; - height: 100%; - - color: var(--satus-theme-on-surface, #777); - background-color: var(--satus-theme-surface, #f7f7f6); - - fill: var(--satus-theme-on-surface, #777); -} - -.satus-main__container -{ - position: absolute; - top: 0; - left: 0; - - overflow: auto; - - box-sizing: border-box; - width: 100%; - height: 100%; - - transition: 250ms; - - background-color: var(--satus-theme-surface, #f7f7f6); - - will-change: transform; -} - - -/*----------------------------------------------------------------------------- -2.0 Animations ------------------------------------------------------------------------------*/ - -.satus-main__container--fade-in-left -{ - animation: fadeInLeft 250ms; -} - -.satus-main__container--fade-in-right -{ - animation: fadeInRight 250ms; -} - -.satus-main__container--fade-out-left -{ - animation: fadeOutLeft 250ms; -} - -.satus-main__container--fade-out-right -{ - animation: fadeOutRight 250ms; -} - -@keyframes fadeInLeft -{ - from - { - transform: translateX(-10%); - - opacity: 0; - } - to - { - transform: translateX(0%); - - opacity: 1; - } -} - -@keyframes fadeInRight -{ - from - { - transform: translateX(10%); - - opacity: 0; - } - to - { - transform: translateX(0%); - - opacity: 1; - } -} - -@keyframes fadeOutLeft -{ - from - { - transform: translateX(0%); - - opacity: 1; - } - to - { - transform: translateX(-10%); - - opacity: 0; - } -} - -@keyframes fadeOutRight -{ - from - { - transform: translateX(0%); - - opacity: 1; - } - to - { - transform: translateX(10%); - - opacity: 0; - } -} - -.satus-scrollbar -{ - position: relative; - - overflow: hidden; - - width: 100%; - height: 100%; -} - -.satus-scrollbar__wrapper -{ - overflow-y: scroll; - - width: 150%; - height: 100%; -} - -.satus-scrollbar__thumb -{ - position: absolute; - z-index: 999; - top: 0; - right: 0; - - min-height: 32px; - padding: 0 2px; - - transition: background-color 200ms, opacity 300ms; - - opacity: 0; -} - -.satus-scrollbar__thumb::after -{ - display: block; - - width: 3px; - height: 100%; - - content: ''; - - background-color: rgba(0,0,0,.2); -} - -.satus-scrollbar__thumb:hover::after -{ - background-color: rgba(0,0,0,.4); -} - -.satus-scrollbar.active .satus-scrollbar__thumb, -.satus-scrollbar__thumb:hover -{ - transition: background-color 200ms, opacity 100ms; - - opacity: 1; -} - -/*-------------------------------------------------------------- ->>> SECTION ---------------------------------------------------------------*/ - -.satus-section -{ - display: inline-flex; - - box-sizing: border-box; - - align-items: center; - flex: 1; -} -/*-------------------------------------------------------------- ->>> SELECT ---------------------------------------------------------------*/ - -.satus-select -{ - font-size: inherit; - - position: relative; - - display: flex; - - width: 100%; - height: 48px; - margin: 0; - padding: 0 16px; - - text-align: left; - - color: inherit; - border: none; - outline: none; - background-color: transparent; - - justify-content: space-between; - -webkit-tap-highlight-color: transparent; - align-items: center; - -webkit-appearance: none; -} - -.satus-select:focus, -.satus-select:hover -{ - background-color: rgba(0,0,0,.04); -} - -.satus-select__value -{ - font-size: 12px; - - text-align: right; - - opacity: .7; -} - - -.satus-dialog--select-component .satus-dialog__surface -{ - position: absolute; - - max-width: unset; - - transform: unset; - animation: unset; - - opacity: 1; -} - -.satus-dialog--select-component .satus-section -{ - top: 48px; - - flex-direction: column; - - transform: translateY(-16px); - animation: listIn 50ms linear forwards; - animation-delay: 20ms; - - opacity: .5; -} - -.satus-dialog--select-component .satus-button -{ - width: 100%; - height: 48px; - padding: 0 16px; -} - -@keyframes listIn -{ - from - { - transform: translateY(-16px); - - opacity: .5; - } - to - { - transform: translateY(0); - - opacity: 1; - } -} - -.satus-shortcut -{ - position: relative; - - display: flex; - - box-sizing: border-box; - width: 100%; - height: 48px; - min-height: 48px; - padding: 0 16px; - - cursor: pointer; - - justify-content: space-between; - align-items: center; -} - -.satus-shortcut:hover -{ - background-color: rgba(0,0,0,.04); -} - -.satus-shortcut > .label -{ - margin: 0 0 4px 0; -} - -.satus-shortcut > .value -{ - font-size: 13px; - - opacity: .5; -} - -.satus-shortcut-dialog-label -{ - font-size: 16px; - font-weight: 500; - - box-sizing: border-box; - width: 100%; - margin: 4px 0 10px; - padding: 0 16px; -} - -.satus-shortcut__canvas -{ - display: flex; - - box-sizing: border-box; - width: 100%; - height: 68px; - padding: 16px; - - background: #dedede; - - 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__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__mouse > div -{ - position: absolute; - top: 0; - left: 13px; - - width: 2px; - height: 11px; - - border-radius: 2px; - background: #ccc; -} - -.satus-shortcut__mouse::before -{ - position: absolute; - top: -4px; - left: 21px; - - width: 2px; - height: 18px; - - content: ''; - - background: #f96754; -} - -.satus-shortcut__mouse.false::after -{ - position: absolute; - top: -12px; - left: 17px; - - 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: 14px; - left: 17px; - - width: 0; - height: 0; - - content: ''; - - border-top: 8px solid #f96754; - border-right: 5px solid transparent; - border-left: 5px solid transparent; -} - -.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; -} - -/*-------------------------------------------------------------- ->>> SLIDER ---------------------------------------------------------------*/ - -.satus-slider -{ - position: relative; - - display: flex; - flex-direction: column; - - box-sizing: border-box; - width: 100%; - min-height: 64px; - padding: 0 16px; - - -webkit-user-select: none; - -moz-user-select: -moz-none; - user-select: none; - - outline: none; - - align-items: flex-start; - justify-content: center; -} - -.satus-slider::before -{ - position: absolute; - top: 0; - left: 0; - - width: 100%; - height: 100%; - - content: ''; - - opacity: 0; - background-color: var(--satus-theme-button, #000); -} - -.satus-slider:hover::before -{ - opacity: .04; -} - - -/* LABEL */ - -.satus-slider__label -{ - cursor: default; -} - - -.satus-slider__range -{ - position: absolute; - z-index: 1; - top: 0; - left: 0; - - box-sizing: border-box; - width: 100%; - height: 100%; - margin: 0; - padding: 0; - - opacity: 0; -} - - -/* TRACK */ - -.satus-slider__container -{ - position: relative; - - width: 100%; - height: 12px; - margin: 8px 0 0; -} - -.satus-slider__track-container -{ - position: absolute; - top: calc(50% - 1px); - - width: 100%; - height: 2px; - - pointer-events: none; -} - -.satus-slider__track-container::before -{ - position: absolute; - top: 0; - left: 0; - - width: 100%; - height: 2px; - - content: ''; - - opacity: .26; - background-color: var(--satus-theme-primary, #54d2a3); -} - -.satus-slider__track -{ - position: relative; - - width: 0; - height: 100%; - - background-color: var(--satus-theme-primary, #54d2a3); - - will-change: width; -} - -.satus-slider:not(.satus-slider--dragging) .satus-slider__track -{ - transition: width 100ms ease-out; -} - -.satus-slider__thumb -{ - position: absolute; - top: -5px; - right: -12px; - - width: 12px; - height: 12px; - - border-radius: 50%; - background-color: var(--satus-theme-primary, #54d2a3); - box-shadow: 0 1px 5px rgba(0, 0, 0, .15); -} - -.satus-slider .satus-slider__thumb::before -{ - font-size: 13px; - - position: absolute; - top: -34px; - left: 50%; - - visibility: hidden; - - box-sizing: border-box; - min-width: 28px; - padding: 4px 4px; - - content: attr(data-value); - transform: translateX(-50%); - text-align: center; - pointer-events: none; - - color: #fff; - border-radius: 4px; - background: rgba(0,0,0,.5); -} - -.satus-slider:hover .satus-slider__thumb::before, -.satus-slider__range:focus .satus-slider__container .satus-slider__thumb::before -{ - visibility: visible; -} - -.satus-slider__ring -{ - position: absolute; - top: -11px; - right: -18px; - - width: 24px; - height: 24px; - - transition: 100ms; - transform: scale(0); - - opacity: 0; - border-radius: 50%; - background-color: var(--satus-theme-primary, #54d2a3); -} - -.satus-slider__range:focus + .satus-slider__container .satus-slider__ring -{ - transform: scale(1); - - opacity: .25; -} - -/*-------------------------------------------------------------- ->>> SWITCH ---------------------------------------------------------------*/ - -.satus-switch -{ - position: relative; - - display: flex; - - box-sizing: border-box; - width: 100%; - height: 48px; - padding: 0 16px; - - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: -moz-none; - user-select: none; - - background-color: transparent; - - align-items: center; - justify-content: space-between; -} - -.satus-switch:hover -{ - background-color: rgba(0,0,0,.04); -} - -.satus-switch__input -{ - position: absolute; - z-index: 1; - top: 0; - left: 0; - - width: 100%; - height: 100%; - margin: 0; - padding: 0; - - opacity: 0; - outline: none; - - -webkit-appearance: none; -} - - -/* LABEL */ - -.satus-switch__label -{ - padding: 0 16px 0 0; -} - - -/* TRACK*/ - -.satus-switch__track -{ - position: relative; - - width: 32px; - min-width: 32px; - height: 18px; - - border-radius: 18px; - background: #bdbdbd; -} - -.satus-switch__track::before -{ - position: absolute; - top: -7px; - left: -7px; - - width: 32px; - height: 32px; - - content: ''; - transition: left .1s cubic-bezier(.4, 0, .2, 1), transform 200ms, background-color 200ms; - transform: scale(0); - - opacity: 0; - border-radius: 50%; - background-color: #000; - - will-change: left, transform, background-color; -} - -.satus-switch__input:checked + .satus-switch__track::before -{ - left: 8px; - - background-color: var(--satus-theme-primary, #54d2a3); -} - -.satus-switch__input:focus + .satus-switch__track::before -{ - transform: scale(1); - - opacity: .08; -} - -.satus-switch__input:checked:focus + .satus-switch__track::before -{ - opacity: .25; -} - -.satus-switch__track::after -{ - position: absolute; - - width: 14px; - height: 14px; - - content: ''; - transition: transform .1s cubic-bezier(.4, 0, .2, 1); - transform: translate(2px, 2px); - - border-radius: 50%; - background-color: #fff; - - will-change: transform; -} - -.satus-switch__input:checked + .satus-switch__track -{ - background: var(--satus-theme-primary, #54d2a3); -} - -.satus-switch__input:checked + .satus-switch__track::after -{ - transform: translate(16px, 2px); -} - -/*-------------------------------------------------------------- ->>> TABLE ---------------------------------------------------------------*/ - -.satus-table -{ - font-size: .875rem; - - position: relative; - - overflow: hidden; - - box-sizing: border-box; - - border: 1px solid #ececec; - border-radius: 6px; -} - -.satus-table__head -{ - position: absolute; - z-index: 1; - top: 0; - left: 0; - - display: flex; - - box-sizing: border-box; - width: 100%; - height: 48px; - padding: 0 8px; - - background: #fff; - box-shadow: 0 2px 4px rgba(0, 0, 0, .1); -} - -.satus-table__head > div -{ - font-weight: 600; - - display: inline-flex; - - opacity: .7; - - flex-shrink: 0; - align-items: center; -} - -.satus-table__head > div:hover -{ - cursor: pointer; - - opacity: 1; -} - -.satus-table__head > div > span -{ - position: relative; -} - -.satus-table__head > div[data-sorting=asc] > span::after -{ - position: absolute; - top: calc(50% - 2px); - right: -14px; - - width: 0; - height: 0; - - content: ''; - - border-right: 4px solid transparent; - border-bottom: 5px solid currentColor; - border-left: 4px solid transparent; -} - -.satus-table__head > div[data-sorting=desc] > span::after -{ - position: absolute; - top: calc(50% - 2px); - right: -13px; - - width: 0; - height: 0; - - content: ''; - - border-top: 5px solid currentColor; - border-right: 4px solid transparent; - border-left: 4px solid transparent; -} - -.satus-table__body -{ - overflow: hidden; - - width: 100%; - height: 100%; - - background: #fff; -} - -.satus-table table -{ - width: 100%; - - border-spacing: 0; - border-collapse: collapse; -} - -.satus-table thead -{ - font-weight: 700; - - visibility: hidden; -} - -.satus-table thead th -{ - height: 48px; -} - -.satus-table th -{ - padding: 0 0 0 8px; -} - -.satus-table th:last-child -{ - padding: 0 8px; -} - -.satus-table td -{ - padding: 4px 0 4px 8px; -} - -.satus-table td:last-child -{ - padding: 4px 8px; -} - -.satus-table td > span -{ - display: block; - overflow: hidden; - - max-width: 100px; -} - - - -.satus-table__paging > button -{ - min-width: 32px; - height: 32px; - padding: 0 8px; - - cursor: pointer; - - color: var(--satus-theme-on-surface, #555); - border: none; - background: transparent; -} - -.satus-table__paging > button.active -{ - color: #2979ff; -} - -/*-------------------------------------------------------------- ->>> TEXT ---------------------------------------------------------------*/ - -.satus-text -{ - margin: 0; - - color: inherit; - border: none; -} - -/*-------------------------------------------------------------- ->>> TEXT ---------------------------------------------------------------*/ - -.satus-text-field -{ - font: inherit; - - box-sizing: border-box; - width: 100%; - margin: 0; - padding: 0; - padding: 0 8px; - - color: inherit; - border: none; - outline: none; - background: unset; -} +.satus-button +{ + font-size: inherit; + + position: relative; + + display: flex; + + margin: 0; + + cursor: pointer; + + color: inherit; + border: none; + outline: none; + background-color: var(--satus-theme-button); + + -webkit-tap-highlight-color: transparent; + align-items: center; + -webkit-appearance: none; +} + +.satus-button::before +{ + position: absolute; + top: 0; + left: 0; + + width: 100%; + height: 100%; + + content: ''; + + opacity: 0; + background-color: var(--satus-theme-ripple); +} + +.satus-button:focus::before, +.satus-button:hover::before +{ + opacity: 1; +} + +.satus-button__icon +{ + width: 24px; + height: 24px; +} + +.satus-button svg +{ + width: 100%; + + color: inherit; + + fill: var(--satus-theme-primary); +} + +.satus-button__icon + .satus-button__label +{ + margin-left: 8px; +} + +/*-------------------------------------------------------------- +>>> COLOR PICKER +--------------------------------------------------------------*/ + +.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: 24px; + height: 24px; + + border-radius: 50%; +} + +.satus-dialog--color-picker .satus-scrollbar__content +{ + display: flex; + flex-direction: column; + + align-items: center; +} + +.satus-dialog--color-picker .satus-button +{ + box-sizing: unset; + width: 24px; + height: 24px; + margin: 0 0 8px; + padding: 8px; + + border-radius: 50%; +} + +.satus-dialog--color-picker .satus-button:hover +{ + background-color: var(--satus-theme-ripple); +} + +.satus-dialog--color-picker .satus-button::before +{ + content: unset; +} + +.satus-dialog--color-picker .satus-button svg +{ + fill: transparent; + stroke: var(--satus-theme-primary); +} + +.satus-dialog--color-picker canvas +{ + width: 200px; + height: 200px; + margin: 0 0 16px; +} + +/*-------------------------------------------------------------- +>>> DIALOG +--------------------------------------------------------------*/ + +.satus-dialog +{ + position: absolute; + z-index: 100; + top: 0; + left: 0; + + display: flex; + + width: 100%; + height: 100vh; + + justify-content: center; + align-items: center; +} + +.satus-dialog__scrim +{ + position: absolute; + top: 0; + left: 0; + + width: 100%; + height: 100%; + + animation: fadeIn 150ms linear forwards; + + opacity: 0; + background: rgba(25,25,25,.2); + + fill: var(--satus-theme-dialog-text); + backdrop-filter: blur(8px); +} + +.satus-dialog__surface +{ + font-size: 14px; + + display: flex; + flex-direction: column; + + width: 95%; + min-width: 240px; + max-width: 560px; + max-height: 80%; + padding: 8px 0; + + transform: scale(.8); + animation: zoomIn 150ms linear forwards; + animation-delay: 20ms; + + opacity: 0; + color: var(--satus-theme-dialog-text); + border-radius: 6px; + background-color: var(--satus-theme-dialog); + box-shadow: inset 0 -1px 1px 1px rgba(0,0,0,.1), 0 2px 6px rgba(0, 0, 0, .15); +} + +.satus-dialog--closing .satus-dialog__scrim +{ + animation: fadeOut 70ms linear forwards; +} + +.satus-dialog--closing .satus-dialog__surface +{ + animation: zoomOut 70ms linear forwards; +} + +@keyframes fadeIn +{ + from + { + opacity: 0; + } + to + { + opacity: 1; + } +} + +@keyframes fadeOut +{ + from + { + opacity: 1; + } + to + { + opacity: 0; + } +} + +@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; + } +} + +/*-------------------------------------------------------------- +>>> HEADER +--------------------------------------------------------------*/ + +.satus-header +{ + position: relative; + z-index: 1; + + display: flex; + + box-sizing: border-box; + width: 100%; + min-height: 58px; + padding: 0 8px; + + color: var(--satus-theme-header-text); + background-color: var(--satus-theme-header); + box-shadow: 0 0 3px rgba(0,0,0,.1); + + fill: var(--satus-theme-header-text); +} + +.satus-header .satus-text--title +{ + font-size: 15px; + font-weight: 400; +} + +/*-------------------------------------------------------------- +>>> LIST +--------------------------------------------------------------*/ + +.satus-list--compact, +.satus-list--compact li +{ + margin: 0; + padding: 0; + + list-style: none; +} + +/*----------------------------------------------------------------------------- +>>> MAIN +------------------------------------------------------------------------------- +1.0 General +2.0 Animations + 2.1 Opening + 2.2 Closing +-----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------- +1.0 General +-----------------------------------------------------------------------------*/ + +.satus-main +{ + position: relative; + + overflow: hidden; + + width: 100%; + height: 100%; + + color: var(--satus-theme-main-text); + background-color: var(--satus-theme-main); + + fill: var(--satus-theme-main-text); +} + +.satus-main__container +{ + position: absolute; + top: 0; + left: 0; + + overflow: auto; + + box-sizing: border-box; + width: 100%; + height: 100%; + + transition: 250ms; + + background-color: var(--satus-theme-main); + + will-change: transform; +} + + +/*----------------------------------------------------------------------------- +2.0 Animations +-----------------------------------------------------------------------------*/ + +.satus-main__container--fade-in-left +{ + animation: fadeInLeft 250ms; +} + +.satus-main__container--fade-in-right +{ + animation: fadeInRight 250ms; +} + +.satus-main__container--fade-out-left +{ + animation: fadeOutLeft 250ms; +} + +.satus-main__container--fade-out-right +{ + animation: fadeOutRight 250ms; +} + +@keyframes fadeInLeft +{ + from + { + transform: translateX(-10%); + + opacity: 0; + } + to + { + transform: translateX(0%); + + opacity: 1; + } +} + +@keyframes fadeInRight +{ + from + { + transform: translateX(10%); + + opacity: 0; + } + to + { + transform: translateX(0%); + + opacity: 1; + } +} + +@keyframes fadeOutLeft +{ + from + { + transform: translateX(0%); + + opacity: 1; + } + to + { + transform: translateX(-10%); + + opacity: 0; + } +} + +@keyframes fadeOutRight +{ + from + { + transform: translateX(0%); + + opacity: 1; + } + to + { + transform: translateX(10%); + + opacity: 0; + } +} + +.satus-scrollbar +{ + position: relative; + + overflow: hidden; + + width: 100%; + height: 100%; +} + +.satus-scrollbar__wrapper +{ + overflow-y: scroll; + + width: 150%; + height: 100%; +} + +.satus-scrollbar__thumb +{ + position: absolute; + z-index: 999; + top: 0; + right: 0; + + min-height: 32px; + padding: 0 2px; + + transition: background-color 200ms, opacity 300ms; + + opacity: 0; +} + +.satus-scrollbar__thumb::after +{ + display: block; + + width: 3px; + height: 100%; + + content: ''; + + background-color: var(--satus-theme-scrollbar); +} + +.satus-scrollbar__thumb:hover::after +{ + background-color: var(--satus-theme-scrollbar-focus); +} + +.satus-scrollbar.active .satus-scrollbar__thumb, +.satus-scrollbar__thumb:hover +{ + transition: background-color 200ms, opacity 100ms; + + opacity: 1; +} + +/*-------------------------------------------------------------- +>>> SECTION +--------------------------------------------------------------*/ + +.satus-section +{ + display: inline-flex; + + box-sizing: border-box; + + background-color: var(--satus-theme-section); + + align-items: center; + flex: 1; +} + +/*-------------------------------------------------------------- +>>> SELECT +--------------------------------------------------------------*/ + +.satus-select +{ + justify-content: space-between; +} + +.satus-select__value +{ + font-size: 12px; + + text-align: right; + + opacity: .7; +} + + +.satus-dialog--select-component .satus-dialog__surface +{ + position: absolute; + + max-width: unset; + + transform: unset; + animation: unset; + + opacity: 1; +} + +.satus-dialog--select-component .satus-section +{ + top: 48px; + + flex-direction: column; + + transform: translateY(-16px); + animation: listIn 50ms linear forwards; + animation-delay: 20ms; + + opacity: .5; +} + +.satus-dialog--select-component .satus-button +{ + width: 100%; + height: 48px; + padding: 0 16px; +} + +@keyframes listIn +{ + from + { + transform: translateY(-16px); + + opacity: .5; + } + to + { + transform: translateY(0); + + opacity: 1; + } +} + +.satus-shortcut +{ + position: relative; + + display: flex; + + box-sizing: border-box; + width: 100%; + height: 48px; + min-height: 48px; + padding: 0 16px; + + cursor: pointer; + + justify-content: space-between; + align-items: center; +} + +.satus-shortcut:hover +{ + background-color: var(--satus-theme-ripple); +} + +.satus-shortcut > .label +{ + margin: 0 0 4px 0; +} + +.satus-shortcut > .value +{ + font-size: 13px; + + opacity: .5; +} + +.satus-shortcut-dialog-label +{ + font-size: 16px; + font-weight: 500; + + box-sizing: border-box; + width: 100%; + margin: 4px 0 10px; + padding: 0 16px; +} + +.satus-shortcut__canvas +{ + display: flex; + + box-sizing: border-box; + width: 100%; + height: 68px; + padding: 16px; + + background: #dedede; + + 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__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__mouse > div +{ + position: absolute; + top: 0; + left: 13px; + + width: 2px; + height: 11px; + + border-radius: 2px; + background: #ccc; +} + +.satus-shortcut__mouse::before +{ + position: absolute; + top: -4px; + left: 21px; + + width: 2px; + height: 18px; + + content: ''; + + background: #f96754; +} + +.satus-shortcut__mouse.false::after +{ + position: absolute; + top: -12px; + left: 17px; + + 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: 14px; + left: 17px; + + width: 0; + height: 0; + + content: ''; + + border-top: 8px solid #f96754; + border-right: 5px solid transparent; + border-left: 5px solid transparent; +} + +.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; +} + +/*-------------------------------------------------------------- +>>> SLIDER +--------------------------------------------------------------*/ + +.satus-slider +{ + position: relative; + + display: flex; + flex-direction: column; + + box-sizing: border-box; + width: 100%; + min-height: 64px; + padding: 0 16px; + + -webkit-user-select: none; + -moz-user-select: -moz-none; + user-select: none; + + outline: none; + + align-items: flex-start; + justify-content: center; +} + +.satus-slider::before +{ + position: absolute; + top: 0; + left: 0; + + width: 100%; + height: 100%; + + content: ''; + + opacity: 0; + background-color: var(--satus-theme-button); +} + +.satus-slider:hover::before +{ + opacity: 1; +} + + +/* LABEL */ + +.satus-slider__label +{ + cursor: default; +} + + +.satus-slider__range +{ + position: absolute; + z-index: 1; + top: 0; + left: 0; + + box-sizing: border-box; + width: 100%; + height: 100%; + margin: 0; + padding: 0; + + opacity: 0; +} + + +/* TRACK */ + +.satus-slider__container +{ + position: relative; + + width: 100%; + height: 12px; + margin: 8px 0 0; +} + +.satus-slider__track-container +{ + position: absolute; + top: calc(50% - 1px); + + width: 100%; + height: 2px; + + pointer-events: none; +} + +.satus-slider__track-container::before +{ + position: absolute; + top: 0; + left: 0; + + width: 100%; + height: 2px; + + content: ''; + + opacity: .26; + background-color: var(--satus-theme-primary); +} + +.satus-slider__track +{ + position: relative; + + width: 0; + height: 100%; + + background-color: var(--satus-theme-primary); + + will-change: width; +} + +.satus-slider:not(.satus-slider--dragging) .satus-slider__track +{ + transition: width 100ms ease-out; +} + +.satus-slider__thumb +{ + position: absolute; + top: -5px; + right: -12px; + + width: 12px; + height: 12px; + + border-radius: 50%; + background-color: var(--satus-theme-primary); + box-shadow: 0 1px 5px rgba(0, 0, 0, .15); +} + +.satus-slider .satus-slider__thumb::before +{ + font-size: 13px; + + position: absolute; + top: -34px; + left: 50%; + + visibility: hidden; + + box-sizing: border-box; + min-width: 28px; + padding: 4px 4px; + + content: attr(data-value); + transform: translateX(-50%); + text-align: center; + pointer-events: none; + + color: #fff; + border-radius: 4px; + background: var(--satus-theme-ripple); +} + +.satus-slider:hover .satus-slider__thumb::before, +.satus-slider__range:focus .satus-slider__container .satus-slider__thumb::before +{ + visibility: visible; +} + +.satus-slider__ring +{ + position: absolute; + top: -11px; + right: -18px; + + width: 24px; + height: 24px; + + transition: 100ms; + transform: scale(0); + + opacity: 0; + border-radius: 50%; + background-color: var(--satus-theme-primary); +} + +.satus-slider__range:focus + .satus-slider__container .satus-slider__ring +{ + transform: scale(1); + + opacity: .25; +} + +/*-------------------------------------------------------------- +>>> SWITCH +--------------------------------------------------------------*/ + +.satus-switch +{ + position: relative; + + display: flex; + + box-sizing: border-box; + width: 100%; + height: 48px; + padding: 0 16px; + + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: -moz-none; + user-select: none; + + background-color: transparent; + + align-items: center; + justify-content: space-between; +} + +.satus-switch:hover +{ + background-color: var(--satus-theme-ripple); +} + +.satus-switch__input +{ + position: absolute; + z-index: 1; + top: 0; + left: 0; + + width: 100%; + height: 100%; + margin: 0; + padding: 0; + + opacity: 0; + outline: none; + + -webkit-appearance: none; +} + + +/* LABEL */ + +.satus-switch__label +{ + padding: 0 16px 0 0; +} + + +/* TRACK*/ + +.satus-switch__track +{ + position: relative; + + width: 32px; + min-width: 32px; + height: 18px; + + border-radius: 18px; + background: #bdbdbd; +} + +.satus-switch__track::before +{ + position: absolute; + top: -7px; + left: -7px; + + width: 32px; + height: 32px; + + content: ''; + transition: left .1s cubic-bezier(.4, 0, .2, 1), transform 200ms, background-color 200ms; + transform: scale(0); + + opacity: 0; + border-radius: 50%; + background-color: #000; + + will-change: left, transform, background-color; +} + +.satus-switch__input:checked + .satus-switch__track::before +{ + left: 8px; + + background-color: var(--satus-theme-primary, #54d2a3); +} + +.satus-switch__input:focus + .satus-switch__track::before +{ + transform: scale(1); + + opacity: .08; +} + +.satus-switch__input:checked:focus + .satus-switch__track::before +{ + opacity: .25; +} + +.satus-switch__track::after +{ + position: absolute; + + width: 14px; + height: 14px; + + content: ''; + transition: transform .1s cubic-bezier(.4, 0, .2, 1); + transform: translate(2px, 2px); + + border-radius: 50%; + background-color: #fff; + + will-change: transform; +} + +.satus-switch__input:checked + .satus-switch__track +{ + background: var(--satus-theme-primary, #54d2a3); +} + +.satus-switch__input:checked + .satus-switch__track::after +{ + transform: translate(16px, 2px); +} + +/*-------------------------------------------------------------- +>>> TABLE +--------------------------------------------------------------*/ + +.satus-table +{ + font-size: .875rem; + + position: relative; + + overflow: hidden; + + box-sizing: border-box; + + border: 1px solid #ececec; + border-radius: 6px; +} + +.satus-table__head +{ + position: absolute; + z-index: 1; + top: 0; + left: 0; + + display: flex; + + box-sizing: border-box; + width: 100%; + height: 48px; + padding: 0 8px; + + background: #fff; + box-shadow: 0 2px 4px rgba(0, 0, 0, .1); +} + +.satus-table__head > div +{ + font-weight: 600; + + display: inline-flex; + + opacity: .7; + + flex-shrink: 0; + align-items: center; +} + +.satus-table__head > div:hover +{ + cursor: pointer; + + opacity: 1; +} + +.satus-table__head > div > span +{ + position: relative; +} + +.satus-table__head > div[data-sorting=asc] > span::after +{ + position: absolute; + top: calc(50% - 2px); + right: -14px; + + width: 0; + height: 0; + + content: ''; + + border-right: 4px solid transparent; + border-bottom: 5px solid currentColor; + border-left: 4px solid transparent; +} + +.satus-table__head > div[data-sorting=desc] > span::after +{ + position: absolute; + top: calc(50% - 2px); + right: -13px; + + width: 0; + height: 0; + + content: ''; + + border-top: 5px solid currentColor; + border-right: 4px solid transparent; + border-left: 4px solid transparent; +} + +.satus-table__body +{ + overflow: hidden; + + width: 100%; + height: 100%; + + background: #fff; +} + +.satus-table table +{ + width: 100%; + + border-spacing: 0; + border-collapse: collapse; +} + +.satus-table thead +{ + font-weight: 700; + + visibility: hidden; +} + +.satus-table thead th +{ + height: 48px; +} + +.satus-table th +{ + padding: 0 0 0 8px; +} + +.satus-table th:last-child +{ + padding: 0 8px; +} + +.satus-table td +{ + padding: 4px 0 4px 8px; +} + +.satus-table td:last-child +{ + padding: 4px 8px; +} + +.satus-table td > span +{ + display: block; + overflow: hidden; + + max-width: 100px; +} + + + +.satus-table__paging > button +{ + min-width: 32px; + height: 32px; + padding: 0 8px; + + cursor: pointer; + + color: var(--satus-theme-on-surface, #555); + border: none; + background: transparent; +} + +.satus-table__paging > button.active +{ + color: #2979ff; +} + +/*-------------------------------------------------------------- +>>> TEXT +--------------------------------------------------------------*/ + +.satus-text +{ + margin: 0; + + color: inherit; + border: none; +} + +/*-------------------------------------------------------------- +>>> TEXT +--------------------------------------------------------------*/ + +.satus-text-field +{ + font: inherit; + + box-sizing: border-box; + width: 100%; + margin: 0; + padding: 0; + padding: 0 8px; + + color: inherit; + border: none; + outline: none; + background: unset; +} + +/*----------------------------------------------------------------------------- +>>> THEMES +------------------------------------------------------------------------------- +1.0 Default +-----------------------------------------------------------------------------*/ + +html +{ + --satus-theme-primary: #f6b465; + + --satus-theme-dialog: #f7f7f6; + --satus-theme-dialog-text: #777; + + --satus-theme-header: #fff; + --satus-theme-header-text: #777; + + --satus-theme-main: #f7f7f6; + --satus-theme-main-text: #777; + + --satus-theme-section: #fff; + + --satus-theme-button: transparent; + + --satus-theme-scrollbar: rgba(0, 0, 0, .2); + --satus-theme-scrollbar-focus: rgba(0, 0, 0, .4); + + --satus-theme-ripple: rgba(0, 0, 0, .04); +} \ No newline at end of file diff --git a/satus.js b/satus.js index b3e5a35..a1d37bc 100644 --- a/satus.js +++ b/satus.js @@ -1,2128 +1,2118 @@ + +/*-------------------------------------------------------------- +>>> TABLE OF CONTENTS: +---------------------------------------------------------------- +# Events +# Render +# Camelize +# Animation duration +--------------------------------------------------------------*/ -/*-------------------------------------------------------------- ->>> TABLE OF CONTENTS: ----------------------------------------------------------------- -# Events -# Render -# Camelize -# Animation duration ---------------------------------------------------------------*/ - -var Satus = {}; - - -/*-------------------------------------------------------------- -# EVENTS ---------------------------------------------------------------*/ - -Satus.events = {}; - -Satus.on = function(event, handler) { - if (!this.isset(this.events[event])) { - this.events[event] = []; - } - - this.events[event].push(handler); -}; - - -/*-------------------------------------------------------------- -# COMPONENTS ---------------------------------------------------------------*/ - -Satus.components = {}; - - -/*-------------------------------------------------------------- -# MODULES ---------------------------------------------------------------*/ - -Satus.modules = {}; - - -/*-------------------------------------------------------------- -# ISSET ---------------------------------------------------------------*/ - -Satus.isset = function(variable) { - if (typeof variable === 'undefined' || variable === null) { - return false; - } - - return true; -}; - - -/*-------------------------------------------------------------- -# CAMELIZE ---------------------------------------------------------------*/ - -Satus.camelize = function(string) { - return string.replace(/-[a-z]/g, function(match) { - return match[1].toUpperCase(); - }); -}; - - -/*-------------------------------------------------------------- -# ANIMATION DURATION ---------------------------------------------------------------*/ - -Satus.getAnimationDuration = function(element) { - return Number(window.getComputedStyle(element).getPropertyValue('animation-duration').replace(/[^0-9.]/g, '')) * 1000; -}; -/*-------------------------------------------------------------- ->>> CHROMIUM STORAGE ----------------------------------------------------------------- -1.0 Get -2.0 Set -3.0 Import -4.0 Clear ---------------------------------------------------------------*/ - -Satus.storage = {}; - -/*-------------------------------------------------------------- -# GET ---------------------------------------------------------------*/ - -Satus.storage.get = function(name) { - var target = Satus.storage; - - 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) { - var items = {}, - target = Satus.storage; - - 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 Satus.storage) { - if (typeof items[key] !== 'function') { - items[key] = Satus.storage[key]; - } - } - - chrome.storage.local.set(items); -}; - - -/*-------------------------------------------------------------- -# IMPORT ---------------------------------------------------------------*/ - -Satus.storage.import = function(callback) { - chrome.storage.local.get(function(items) { - for (var key in items) { - Satus.storage[key] = items[key]; - } - - if (callback) { - callback(); - } - }); -}; - - -/*-------------------------------------------------------------- -# CLEAR ---------------------------------------------------------------*/ - -Satus.storage.clear = function() { - chrome.storage.local.clear(); - - for (var key in Satus.storage) { - if (typeof Satus.storage[key] !== 'function') { - delete Satus.storage[key]; - } - } -}; - -/*-------------------------------------------------------------- -# LOCALE ---------------------------------------------------------------*/ - -Satus.locale = { - messages: {} -}; - - -/*-------------------------------------------------------------- -# GET MESSAGE ---------------------------------------------------------------*/ - -Satus.locale.getMessage = function(string) { - return this.messages[string] || string; -}; - -/*-------------------------------------------------------------- -# IMPORT LOCALE ---------------------------------------------------------------*/ - -Satus.locale.import = function(src, callback) { - var xhr = new XMLHttpRequest(); - - xhr.onload = function() { - try { - var object = JSON.parse(this.responseText); - - for (var key in object) { - Satus.locale.messages[key] = object[key].message; - } - - callback(); - } catch (err) { - function listener(request) { - if (request !== null && typeof request === 'object') { - if (request.name === 'translation_response') { - var object = JSON.parse(request.value); - - chrome.runtime.onMessage.removeListener(listener); - - for (var key in object) { - Satus.locale.messages[key] = object[key].message; - } - - callback(); - } - } - } - - chrome.runtime.onMessage.addListener(listener); - - chrome.runtime.sendMessage({ - name: 'translation_request', - path: src - }); - } - }; - - xhr.onerror = xhr.onload; - - xhr.open('GET', src, true); - xhr.send(); -}; -/*-------------------------------------------------------------- ->>> RENDER ---------------------------------------------------------------*/ - -Satus.render = function(element, container, callback) { - function convert(object) { - if (object && object.type) { - var type = Satus.camelize(object.type), - component = Satus.components[type](object), - excluded_properties = ['type', 'label', 'class', 'title', 'storage']; - - function applyProperties(object, target) { - for (var key in object) { - if (Satus.isset(object[key]) && typeof object[key] === 'object' && !object[key].type) { - if (typeof target[key] !== 'object') { - target[key] = {}; - } - - applyProperties(object[key], target[key]); - } else if (excluded_properties.indexOf(key) === -1) { - target[key] = object[key]; - } - } - } - - applyProperties(object, component); - - component.classList.add('satus-' + object.type); - - if (object.class) { - var class_list = object.class.split(' '); - - for (var i = 0, l = class_list.length; i < l; i++) { - component.classList.add(class_list[i]); - } - } - - if (object.before) { - var component_before = document.createElement('span'); - - component_before.innerHTML = object.before; - - for (var i = component_before.children.length - 1; i > -1; i--) { - component.insertBefore(component_before.children[i], component.firstChild); - } - } - - if (object.after) { - var component_after = document.createElement('span'); - - component_after.innerHTML = object.after; - - for (var i = component_after.children.length - 1; i > -1; i--) { - component.appendChild(component_after.children[i]); - } - } - - (container || document.body).appendChild(component); - - if (typeof component.onClickRender === 'object') { - component.addEventListener('click', function() { - Satus.render(component.onClickRender); - }); - } - - if (Satus.isset(Satus.events.render)) { - for (var i = 0, l = Satus.events.render.length; i < l; i++) { - Satus.events.render[i](component, object); - } - } - - if (typeof component.onrender === 'function') { - component.onrender(object); - } - - if (callback) { - callback(); - } - } - } - - if (element.type) { - convert(element); - } else { - for (var key in element) { - convert(element[key]); - } - } -}; -/*-------------------------------------------------------------- -# CLONE NODE STYLES ---------------------------------------------------------------*/ - -Satus.cloneNodeStyles = function(origin, target) { - target.style.cssText = window.getComputedStyle(origin, '').cssText; - - for (var i = 0, l = origin.children.length; i < l; i++) { - Satus.cloneNodeStyles(origin.children[i], target.children[i]); - } -}; -/*----------------------------------------------------------------------------- ->>> «SEARCH» MODULE ------------------------------------------------------------------------------*/ - -Satus.search = function(query, object, callback) { - var threads = 0, - results = {}; - - function parse(items) { - threads++; - - for (var key in items) { - var item = items[key]; - - - if (['switch', 'select', 'slider'].indexOf(item.type) !== -1 && key.indexOf(query) !== -1) { - results[key] = item; - } - - if (typeof item === 'object') { - parse(item); - } - } - - threads--; - - if (threads === 0) { - callback(results); - } - } - - parse(object); -}; -/*-------------------------------------------------------------- ->>> STORAGE KEYS ---------------------------------------------------------------*/ - -Satus.modules.updateStorageKeys = function(object, callback) { - var threads = 0; - - function parse(items) { - threads++; - - for (var key in items) { - var item = items[key]; - - - if (item.type) { - item.storage_key = key; - } - - if (typeof item === 'object') { - parse(item); - } - } - - threads--; - - if (threads === 0) { - callback(); - } - } - - parse(object); -}; -/*----------------------------------------------------------------------------- ->>> «USER» MODULE -------------------------------------------------------------------------------- -1.0 Variables -2.0 Software - 2.1 OS - 2.2.1 Name - 2.2.2 Type - 2.2 Browser - 2.2.1 Name - 2.2.2 Version - 2.2.3 Platform - 2.2.4 Languages - 2.2.5 Cookies - 2.2.6 Flash - 2.2.8 Video formats - 2.2.9 Audio formats - 2.2.10 WebGL -3.0 Hardware - 3.1 Screen - 3.2 RAM - 3.3 GPU - 3.4 Cores - 3.5 Touch - 3.6 Connection -4.0 Clearing ------------------------------------------------------------------------------*/ - -Satus.modules.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; -}; -Satus.on('render', function(component, data) { - if (data.perspective === true) { - component.style.willChange = 'transform'; - component.style.transformStyle = 'preserve-3d'; - component.style.transition = '.4s'; - - component.addEventListener('mousemove', function(event) { - var bounding = component.getBoundingClientRect(), - dx = event.clientX - bounding.left - bounding.width / 2, - dy = event.clientY - bounding.top - bounding.height / 2; - - this.style.transform = 'perspective(440px) rotateX(' + dy * -1 + 'deg) rotateY(' + dx + 'deg) translateZ(0)'; - }); - - component.addEventListener('mouseout', function(event) { - this.style.transform = 'perspective(440px) rotateX(0deg) rotateY(0deg) translateZ(0)'; - }); - } -}); -/*-------------------------------------------------------------- ->>> BUTTON ---------------------------------------------------------------*/ - -Satus.components.button = function(element) { - var component = document.createElement('button'); - - if (Satus.isset(element.icon)) { - var component_icon = document.createElement('span'); - - component_icon.className = 'satus-button__icon'; - component_icon.innerHTML = element.icon; - - component.appendChild(component_icon); - } - - if (Satus.isset(element.label)) { - var component_label = document.createElement('span'); - - component_label.className = 'satus-button__label'; - component_label.innerText = Satus.locale.getMessage(element.label); - - component.appendChild(component_label); - } - - return component; -}; -/*-------------------------------------------------------------- ->>> COLOR PICKER ---------------------------------------------------------------*/ - -Satus.components.colorPicker = function(element) { - var component = document.createElement('div'), - component_value = document.createElement('div'); - - element.class = 'satus-button'; - component_value.className = 'satus-color-picker__value'; - component_value.style.backgroundColor = Satus.storage.get(element.storage_key) || element.value || ''; - - if (Satus.isset(element.label)) { - var component_label = document.createElement('span'); - - component_label.className = 'satus-button__label'; - component_label.innerText = Satus.locale.getMessage(element.label); - - component.appendChild(component_label); - } - - component.addEventListener('click', function() { - var component = document.createElement('div'), - component_canvas = document.createElement('canvas'), - close = document.createElement('button'), - ctx = component_canvas.getContext('2d'), - image = new Image(), - dialog = Satus.components.dialog({}); - - close.className = 'satus-button'; - close.innerHTML = ''; - close.onclick = function() { - dialog.querySelector('.satus-dialog__scrim').click(); - }; - - dialog.className = 'satus-dialog satus-dialog--color-picker'; - - component_canvas.width = 200; - component_canvas.height = 200; - - function select(event) { - var coordinates = component_canvas.getBoundingClientRect(), - x = event.clientX - coordinates.left, - y = event.clientY - coordinates.top, - color = ctx.getImageData(x, y, 1, 1).data; - - component_value.style.backgroundColor = 'rgb(' + color[0] + ',' + color[1] + ',' + color[2] + ')'; - - Satus.storage.set(element.storage_key, component_value.style.backgroundColor); - } - - function mouseup(event) { - component_canvas.removeEventListener('mousemove', select); - window.removeEventListener('mouseup', mouseup); - } - - component_canvas.addEventListener('mousedown', function() { - select(event); - this.addEventListener('mousemove', select); - window.addEventListener('mouseup', mouseup); - }); - - image.onload = function() { - ctx.drawImage(image, 0, 0); - - image.remove(); - }; - - image.src = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNzAgMjcwIj48ZGVmcz48cmFkaWFsR3JhZGllbnQgaWQ9ImEiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmZmYiIHN0b3Atb3BhY2l0eT0iMCIvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxnIGZpbGw9Im5vbmUiIHN0cm9rZS13aWR0aD0iMTMzIiBjbGFzcz0iSXJvV2hlZWxIdWUiPjxwYXRoIHN0cm9rZT0iaHNsKDI0MCwgMTAwJSwgNTAlKSIgZD0iTTIwMS40NzcgMTM2Ljc0YTY2LjUgNjYuNSAwIDAwLjAyMy0xLjc0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjQxLCAxMDAlLCA1MCUpIiBkPSJNMjAxLjQzNyAxMzcuOWE2Ni41IDY2LjUgMCAwMC4wNTMtMS43NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI0MiwgMTAwJSwgNTAlKSIgZD0iTTIwMS4zNzYgMTM5LjA2YTY2LjUgNjYuNSAwIDAwLjA4My0xLjc0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjQzLCAxMDAlLCA1MCUpIiBkPSJNMjAxLjI5NSAxNDAuMjE4YTY2LjUgNjYuNSAwIDAwLjExNC0xLjczOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI0NCwgMTAwJSwgNTAlKSIgZD0iTTIwMS4xOTQgMTQxLjM3NGE2Ni41IDY2LjUgMCAwMC4xNDQtMS43MzUiLz48cGF0aCBzdHJva2U9ImhzbCgyNDUsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuMDczIDE0Mi41MjhhNjYuNSA2Ni41IDAgMDAuMTc0LTEuNzMyIi8+PHBhdGggc3Ryb2tlPSJoc2woMjQ2LCAxMDAlLCA1MCUpIiBkPSJNMjAwLjkzMSAxNDMuNjhhNjYuNSA2Ni41IDAgMDAuMjA1LTEuNzI5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjQ3LCAxMDAlLCA1MCUpIiBkPSJNMjAwLjc3IDE0NC44M2E2Ni41IDY2LjUgMCAwMC4yMzQtMS43MjYiLz48cGF0aCBzdHJva2U9ImhzbCgyNDgsIDEwMCUsIDUwJSkiIGQ9Ik0yMDAuNTg4IDE0NS45NzZhNjYuNSA2Ni41IDAgMDAuMjY1LTEuNzIxIi8+PHBhdGggc3Ryb2tlPSJoc2woMjQ5LCAxMDAlLCA1MCUpIiBkPSJNMjAwLjM4NiAxNDcuMTE5YTY2LjUgNjYuNSAwIDAwLjI5NS0xLjcxNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI1MCwgMTAwJSwgNTAlKSIgZD0iTTIwMC4xNjUgMTQ4LjI1OGE2Ni41IDY2LjUgMCAwMC4zMjUtMS43MSIvPjxwYXRoIHN0cm9rZT0iaHNsKDI1MSwgMTAwJSwgNTAlKSIgZD0iTTE5OS45MjQgMTQ5LjM5M2E2Ni41IDY2LjUgMCAwMC4zNTQtMS43MDQiLz48cGF0aCBzdHJva2U9ImhzbCgyNTIsIDEwMCUsIDUwJSkiIGQ9Ik0xOTkuNjYzIDE1MC41MjRhNjYuNSA2Ni41IDAgMDAuMzg0LTEuNjk4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjUzLCAxMDAlLCA1MCUpIiBkPSJNMTk5LjM4MiAxNTEuNjVhNjYuNSA2Ni41IDAgMDAuNDE0LTEuNjkiLz48cGF0aCBzdHJva2U9ImhzbCgyNTQsIDEwMCUsIDUwJSkiIGQ9Ik0xOTkuMDgxIDE1Mi43NzFhNjYuNSA2Ni41IDAgMDAuNDQ0LTEuNjgzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjU1LCAxMDAlLCA1MCUpIiBkPSJNMTk4Ljc2MiAxNTMuODg3YTY2LjUgNjYuNSAwIDAwLjQ3Mi0xLjY3NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI1NiwgMTAwJSwgNTAlKSIgZD0iTTE5OC40MjIgMTU0Ljk5N2E2Ni41IDY2LjUgMCAwMC41MDItMS42NjciLz48cGF0aCBzdHJva2U9ImhzbCgyNTcsIDEwMCUsIDUwJSkiIGQ9Ik0xOTguMDY0IDE1Ni4xYTY2LjUgNjYuNSAwIDAwLjUzLTEuNjU3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjU4LCAxMDAlLCA1MCUpIiBkPSJNMTk3LjY4NiAxNTcuMTk4YTY2LjUgNjYuNSAwIDAwLjU2LTEuNjQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjU5LCAxMDAlLCA1MCUpIiBkPSJNMTk3LjI4OSAxNTguMjg5YTY2LjUgNjYuNSAwIDAwLjU4OC0xLjYzOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDI2MCwgMTAwJSwgNTAlKSIgZD0iTTE5Ni44NzMgMTU5LjM3MmE2Ni41IDY2LjUgMCAwMC42MTctMS42MjgiLz48cGF0aCBzdHJva2U9ImhzbCgyNjEsIDEwMCUsIDUwJSkiIGQ9Ik0xOTYuNDM4IDE2MC40NDhhNjYuNSA2Ni41IDAgMDAuNjQ1LTEuNjE3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjYyLCAxMDAlLCA1MCUpIiBkPSJNMTk1Ljk4NCAxNjEuNTE3YTY2LjUgNjYuNSAwIDAwLjY3NC0xLjYwNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI2MywgMTAwJSwgNTAlKSIgZD0iTTE5NS41MTIgMTYyLjU3N2E2Ni41IDY2LjUgMCAwMC43MDItMS41OTMiLz48cGF0aCBzdHJva2U9ImhzbCgyNjQsIDEwMCUsIDUwJSkiIGQ9Ik0xOTUuMDIyIDE2My42MjlhNjYuNSA2Ni41IDAgMDAuNzI5LTEuNTgxIi8+PHBhdGggc3Ryb2tlPSJoc2woMjY1LCAxMDAlLCA1MCUpIiBkPSJNMTk0LjUxMyAxNjQuNjcyYTY2LjUgNjYuNSAwIDAwLjc1Ni0xLjU2OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI2NiwgMTAwJSwgNTAlKSIgZD0iTTE5My45ODYgMTY1LjcwNmE2Ni41IDY2LjUgMCAwMC43ODQtMS41NTQiLz48cGF0aCBzdHJva2U9ImhzbCgyNjcsIDEwMCUsIDUwJSkiIGQ9Ik0xOTMuNDQxIDE2Ni43MzFhNjYuNSA2Ni41IDAgMDAuODEtMS41NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI2OCwgMTAwJSwgNTAlKSIgZD0iTTE5Mi44NzkgMTY3Ljc0NmE2Ni41IDY2LjUgMCAwMC44MzctMS41MjYiLz48cGF0aCBzdHJva2U9ImhzbCgyNjksIDEwMCUsIDUwJSkiIGQ9Ik0xOTIuMjk4IDE2OC43NTFhNjYuNSA2Ni41IDAgMDAuODY0LTEuNTExIi8+PHBhdGggc3Ryb2tlPSJoc2woMjcwLCAxMDAlLCA1MCUpIiBkPSJNMTkxLjcgMTY5Ljc0NmE2Ni41IDY2LjUgMCAwMC44OS0xLjQ5NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3MSwgMTAwJSwgNTAlKSIgZD0iTTE5MS4wODYgMTcwLjczYTY2LjUgNjYuNSAwIDAwLjkxNi0xLjQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjcyLCAxMDAlLCA1MCUpIiBkPSJNMTkwLjQ1MyAxNzEuNzA0YTY2LjUgNjYuNSAwIDAwLjk0Mi0xLjQ2NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3MywgMTAwJSwgNTAlKSIgZD0iTTE4OS44MDQgMTcyLjY2NmE2Ni41IDY2LjUgMCAwMC45NjgtMS40NDgiLz48cGF0aCBzdHJva2U9ImhzbCgyNzQsIDEwMCUsIDUwJSkiIGQ9Ik0xODkuMTM5IDE3My42MTdhNjYuNSA2Ni41IDAgMDAuOTkyLTEuNDMiLz48cGF0aCBzdHJva2U9ImhzbCgyNzUsIDEwMCUsIDUwJSkiIGQ9Ik0xODguNDU2IDE3NC41NTZhNjYuNSA2Ni41IDAgMDAxLjAxOC0xLjQxMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3NiwgMTAwJSwgNTAlKSIgZD0iTTE4Ny43NTggMTc1LjQ4M2E2Ni41IDY2LjUgMCAwMDEuMDQyLTEuMzk1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjc3LCAxMDAlLCA1MCUpIiBkPSJNMTg3LjA0MyAxNzYuMzk3YTY2LjUgNjYuNSAwIDAwMS4wNjYtMS4zNzYiLz48cGF0aCBzdHJva2U9ImhzbCgyNzgsIDEwMCUsIDUwJSkiIGQ9Ik0xODYuMzEzIDE3Ny4zYTY2LjUgNjYuNSAwIDAwMS4wOS0xLjM1OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3OSwgMTAwJSwgNTAlKSIgZD0iTTE4NS41NjcgMTc4LjE4OGE2Ni41IDY2LjUgMCAwMDEuMTEzLTEuMzM4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjgwLCAxMDAlLCA1MCUpIiBkPSJNMTg0LjgwNiAxNzkuMDY0YTY2LjUgNjYuNSAwIDAwMS4xMzYtMS4zMTkiLz48cGF0aCBzdHJva2U9ImhzbCgyODEsIDEwMCUsIDUwJSkiIGQ9Ik0xODQuMDI5IDE3OS45MjdhNjYuNSA2Ni41IDAgMDAxLjE2LTEuMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDI4MiwgMTAwJSwgNTAlKSIgZD0iTTE4My4yMzcgMTgwLjc3NmE2Ni41IDY2LjUgMCAwMDEuMTgyLTEuMjc5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjgzLCAxMDAlLCA1MCUpIiBkPSJNMTgyLjQzMSAxODEuNjFhNjYuNSA2Ni41IDAgMDAxLjIwNC0xLjI1NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDI4NCwgMTAwJSwgNTAlKSIgZD0iTTE4MS42MSAxODIuNDMxYTY2LjUgNjYuNSAwIDAwMS4yMjYtMS4yMzYiLz48cGF0aCBzdHJva2U9ImhzbCgyODUsIDEwMCUsIDUwJSkiIGQ9Ik0xODAuNzc2IDE4My4yMzdhNjYuNSA2Ni41IDAgMDAxLjI0Ny0xLjIxNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI4NiwgMTAwJSwgNTAlKSIgZD0iTTE3OS45MjcgMTg0LjAyOWE2Ni41IDY2LjUgMCAwMDEuMjY4LTEuMTkzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjg3LCAxMDAlLCA1MCUpIiBkPSJNMTc5LjA2NCAxODQuODA2YTY2LjUgNjYuNSAwIDAwMS4yODktMS4xNzEiLz48cGF0aCBzdHJva2U9ImhzbCgyODgsIDEwMCUsIDUwJSkiIGQ9Ik0xNzguMTg4IDE4NS41NjdhNjYuNSA2Ni41IDAgMDAxLjMxLTEuMTQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjg5LCAxMDAlLCA1MCUpIiBkPSJNMTc3LjMgMTg2LjMxM2E2Ni41IDY2LjUgMCAwMDEuMzI4LTEuMTI1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjkwLCAxMDAlLCA1MCUpIiBkPSJNMTc2LjM5NyAxODcuMDQzYTY2LjUgNjYuNSAwIDAwMS4zNDgtMS4xMDEiLz48cGF0aCBzdHJva2U9ImhzbCgyOTEsIDEwMCUsIDUwJSkiIGQ9Ik0xNzUuNDgzIDE4Ny43NThhNjYuNSA2Ni41IDAgMDAxLjM2Ny0xLjA3OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI5MiwgMTAwJSwgNTAlKSIgZD0iTTE3NC41NTYgMTg4LjQ1NmE2Ni41IDY2LjUgMCAwMDEuMzg1LTEuMDUzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjkzLCAxMDAlLCA1MCUpIiBkPSJNMTczLjYxNyAxODkuMTM5YTY2LjUgNjYuNSAwIDAwMS40MDQtMS4wMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDI5NCwgMTAwJSwgNTAlKSIgZD0iTTE3Mi42NjYgMTg5LjgwNGE2Ni41IDY2LjUgMCAwMDEuNDIyLTEuMDA0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjk1LCAxMDAlLCA1MCUpIiBkPSJNMTcxLjcwNCAxOTAuNDUzYTY2LjUgNjYuNSAwIDAwMS40MzktLjk4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjk2LCAxMDAlLCA1MCUpIiBkPSJNMTcwLjczIDE5MS4wODZhNjYuNSA2Ni41IDAgMDAxLjQ1Ni0uOTU1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjk3LCAxMDAlLCA1MCUpIiBkPSJNMTY5Ljc0NiAxOTEuN2E2Ni41IDY2LjUgMCAwMDEuNDcyLS45MjgiLz48cGF0aCBzdHJva2U9ImhzbCgyOTgsIDEwMCUsIDUwJSkiIGQ9Ik0xNjguNzUxIDE5Mi4yOThhNjYuNSA2Ni41IDAgMDAxLjQ4OS0uOTAzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjk5LCAxMDAlLCA1MCUpIiBkPSJNMTY3Ljc0NiAxOTIuODc5YTY2LjUgNjYuNSAwIDAwMS41MDQtLjg3NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwMCwgMTAwJSwgNTAlKSIgZD0iTTE2Ni43MzEgMTkzLjQ0MWE2Ni41IDY2LjUgMCAwMDEuNTE5LS44NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwMSwgMTAwJSwgNTAlKSIgZD0iTTE2NS43MDYgMTkzLjk4NmE2Ni41IDY2LjUgMCAwMDEuNTM0LS44MjQiLz48cGF0aCBzdHJva2U9ImhzbCgzMDIsIDEwMCUsIDUwJSkiIGQ9Ik0xNjQuNjcyIDE5NC41MTNhNjYuNSA2Ni41IDAgMDAxLjU0OC0uNzk3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzAzLCAxMDAlLCA1MCUpIiBkPSJNMTYzLjYyOSAxOTUuMDIyYTY2LjUgNjYuNSAwIDAwMS41NjEtLjc3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzA0LCAxMDAlLCA1MCUpIiBkPSJNMTYyLjU3NyAxOTUuNTEyYTY2LjUgNjYuNSAwIDAwMS41NzUtLjc0MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwNSwgMTAwJSwgNTAlKSIgZD0iTTE2MS41MTcgMTk1Ljk4NGE2Ni41IDY2LjUgMCAwMDEuNTg3LS43MTUiLz48cGF0aCBzdHJva2U9ImhzbCgzMDYsIDEwMCUsIDUwJSkiIGQ9Ik0xNjAuNDQ4IDE5Ni40MzhhNjYuNSA2Ni41IDAgMDAxLjYtLjY4NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwNywgMTAwJSwgNTAlKSIgZD0iTTE1OS4zNzIgMTk2Ljg3M2E2Ni41IDY2LjUgMCAwMDEuNjEyLS42NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwOCwgMTAwJSwgNTAlKSIgZD0iTTE1OC4yODkgMTk3LjI4OWE2Ni41IDY2LjUgMCAwMDEuNjIyLS42MzEiLz48cGF0aCBzdHJva2U9ImhzbCgzMDksIDEwMCUsIDUwJSkiIGQ9Ik0xNTcuMTk4IDE5Ny42ODZhNjYuNSA2Ni41IDAgMDAxLjYzMy0uNjAzIi8+PHBhdGggc3Ryb2tlPSJoc2woMzEwLCAxMDAlLCA1MCUpIiBkPSJNMTU2LjEgMTk4LjA2NGE2Ni41IDY2LjUgMCAwMDEuNjQ0LS41NzQiLz48cGF0aCBzdHJva2U9ImhzbCgzMTEsIDEwMCUsIDUwJSkiIGQ9Ik0xNTQuOTk3IDE5OC40MjJhNjYuNSA2Ni41IDAgMDAxLjY1My0uNTQ1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzEyLCAxMDAlLCA1MCUpIiBkPSJNMTUzLjg4NyAxOTguNzYyYTY2LjUgNjYuNSAwIDAwMS42NjMtLjUxNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxMywgMTAwJSwgNTAlKSIgZD0iTTE1Mi43NzEgMTk5LjA4MWE2Ni41IDY2LjUgMCAwMDEuNjcyLS40ODciLz48cGF0aCBzdHJva2U9ImhzbCgzMTQsIDEwMCUsIDUwJSkiIGQ9Ik0xNTEuNjUgMTk5LjM4MmE2Ni41IDY2LjUgMCAwMDEuNjgtLjQ1OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxNSwgMTAwJSwgNTAlKSIgZD0iTTE1MC41MjQgMTk5LjY2M2E2Ni41IDY2LjUgMCAwMDEuNjg3LS40MjkiLz48cGF0aCBzdHJva2U9ImhzbCgzMTYsIDEwMCUsIDUwJSkiIGQ9Ik0xNDkuMzkzIDE5OS45MjRhNjYuNSA2Ni41IDAgMDAxLjY5NS0uNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxNywgMTAwJSwgNTAlKSIgZD0iTTE0OC4yNTggMjAwLjE2NWE2Ni41IDY2LjUgMCAwMDEuNzAxLS4zNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxOCwgMTAwJSwgNTAlKSIgZD0iTTE0Ny4xMTkgMjAwLjM4NmE2Ni41IDY2LjUgMCAwMDEuNzA3LS4zNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxOSwgMTAwJSwgNTAlKSIgZD0iTTE0NS45NzYgMjAwLjU4OGE2Ni41IDY2LjUgMCAwMDEuNzEzLS4zMSIvPjxwYXRoIHN0cm9rZT0iaHNsKDMyMCwgMTAwJSwgNTAlKSIgZD0iTTE0NC44MyAyMDAuNzdhNjYuNSA2Ni41IDAgMDAxLjcxOC0uMjgiLz48cGF0aCBzdHJva2U9ImhzbCgzMjEsIDEwMCUsIDUwJSkiIGQ9Ik0xNDMuNjggMjAwLjkzMWE2Ni41IDY2LjUgMCAwMDEuNzIzLS4yNSIvPjxwYXRoIHN0cm9rZT0iaHNsKDMyMiwgMTAwJSwgNTAlKSIgZD0iTTE0Mi41MjggMjAxLjA3M2E2Ni41IDY2LjUgMCAwMDEuNzI3LS4yMiIvPjxwYXRoIHN0cm9rZT0iaHNsKDMyMywgMTAwJSwgNTAlKSIgZD0iTTE0MS4zNzQgMjAxLjE5NGE2Ni41IDY2LjUgMCAwMDEuNzMtLjE5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzI0LCAxMDAlLCA1MCUpIiBkPSJNMTQwLjIxOCAyMDEuMjk1YTY2LjUgNjYuNSAwIDAwMS43MzMtLjE2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzI1LCAxMDAlLCA1MCUpIiBkPSJNMTM5LjA2IDIwMS4zNzZhNjYuNSA2Ni41IDAgMDAxLjczNi0uMTMiLz48cGF0aCBzdHJva2U9ImhzbCgzMjYsIDEwMCUsIDUwJSkiIGQ9Ik0xMzcuOSAyMDEuNDM3YTY2LjUgNjYuNSAwIDAwMS43MzktLjA5OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDMyNywgMTAwJSwgNTAlKSIgZD0iTTEzNi43NCAyMDEuNDc3YTY2LjUgNjYuNSAwIDAwMS43NC0uMDY4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzI4LCAxMDAlLCA1MCUpIiBkPSJNMTM1LjU4IDIwMS40OTdhNjYuNSA2Ni41IDAgMDAxLjc0LS4wMzgiLz48cGF0aCBzdHJva2U9ImhzbCgzMjksIDEwMCUsIDUwJSkiIGQ9Ik0xMzQuNDIgMjAxLjQ5N2E2Ni41IDY2LjUgMCAwMDEuNzQtLjAwNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMzMCwgMTAwJSwgNTAlKSIgZD0iTTEzMy4yNiAyMDEuNDc3YTY2LjUgNjYuNSAwIDAwMS43NC4wMjMiLz48cGF0aCBzdHJva2U9ImhzbCgzMzEsIDEwMCUsIDUwJSkiIGQ9Ik0xMzIuMSAyMDEuNDM3YTY2LjUgNjYuNSAwIDAwMS43NC4wNTMiLz48cGF0aCBzdHJva2U9ImhzbCgzMzIsIDEwMCUsIDUwJSkiIGQ9Ik0xMzAuOTQgMjAxLjM3NmE2Ni41IDY2LjUgMCAwMDEuNzQuMDgzIi8+PHBhdGggc3Ryb2tlPSJoc2woMzMzLCAxMDAlLCA1MCUpIiBkPSJNMTI5Ljc4MiAyMDEuMjk1YTY2LjUgNjYuNSAwIDAwMS43MzguMTE0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM0LCAxMDAlLCA1MCUpIiBkPSJNMTI4LjYyNiAyMDEuMTk0YTY2LjUgNjYuNSAwIDAwMS43MzUuMTQ0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM1LCAxMDAlLCA1MCUpIiBkPSJNMTI3LjQ3MiAyMDEuMDczYTY2LjUgNjYuNSAwIDAwMS43MzIuMTc0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM2LCAxMDAlLCA1MCUpIiBkPSJNMTI2LjMyIDIwMC45MzFhNjYuNSA2Ni41IDAgMDAxLjcyOS4yMDUiLz48cGF0aCBzdHJva2U9ImhzbCgzMzcsIDEwMCUsIDUwJSkiIGQ9Ik0xMjUuMTcgMjAwLjc3YTY2LjUgNjYuNSAwIDAwMS43MjYuMjM0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM4LCAxMDAlLCA1MCUpIiBkPSJNMTI0LjAyNCAyMDAuNTg4YTY2LjUgNjYuNSAwIDAwMS43MjEuMjY1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM5LCAxMDAlLCA1MCUpIiBkPSJNMTIyLjg4MSAyMDAuMzg2YTY2LjUgNjYuNSAwIDAwMS43MTYuMjk1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzQwLCAxMDAlLCA1MCUpIiBkPSJNMTIxLjc0MiAyMDAuMTY1YTY2LjUgNjYuNSAwIDAwMS43MS4zMjUiLz48cGF0aCBzdHJva2U9ImhzbCgzNDEsIDEwMCUsIDUwJSkiIGQ9Ik0xMjAuNjA3IDE5OS45MjRhNjYuNSA2Ni41IDAgMDAxLjcwNC4zNTQiLz48cGF0aCBzdHJva2U9ImhzbCgzNDIsIDEwMCUsIDUwJSkiIGQ9Ik0xMTkuNDc2IDE5OS42NjNhNjYuNSA2Ni41IDAgMDAxLjY5OC4zODQiLz48cGF0aCBzdHJva2U9ImhzbCgzNDMsIDEwMCUsIDUwJSkiIGQ9Ik0xMTguMzUgMTk5LjM4MmE2Ni41IDY2LjUgMCAwMDEuNjkuNDE0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzQ0LCAxMDAlLCA1MCUpIiBkPSJNMTE3LjIyOSAxOTkuMDgxYTY2LjUgNjYuNSAwIDAwMS42ODMuNDQ0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzQ1LCAxMDAlLCA1MCUpIiBkPSJNMTE2LjExMyAxOTguNzYyYTY2LjUgNjYuNSAwIDAwMS42NzYuNDcyIi8+PHBhdGggc3Ryb2tlPSJoc2woMzQ2LCAxMDAlLCA1MCUpIiBkPSJNMTE1LjAwMyAxOTguNDIyYTY2LjUgNjYuNSAwIDAwMS42NjcuNTAyIi8+PHBhdGggc3Ryb2tlPSJoc2woMzQ3LCAxMDAlLCA1MCUpIiBkPSJNMTEzLjkgMTk4LjA2NGE2Ni41IDY2LjUgMCAwMDEuNjU3LjUzIi8+PHBhdGggc3Ryb2tlPSJoc2woMzQ4LCAxMDAlLCA1MCUpIiBkPSJNMTEyLjgwMiAxOTcuNjg2YTY2LjUgNjYuNSAwIDAwMS42NDguNTYiLz48cGF0aCBzdHJva2U9ImhzbCgzNDksIDEwMCUsIDUwJSkiIGQ9Ik0xMTEuNzExIDE5Ny4yODlhNjYuNSA2Ni41IDAgMDAxLjYzOS41ODgiLz48cGF0aCBzdHJva2U9ImhzbCgzNTAsIDEwMCUsIDUwJSkiIGQ9Ik0xMTAuNjI4IDE5Ni44NzNhNjYuNSA2Ni41IDAgMDAxLjYyOC42MTciLz48cGF0aCBzdHJva2U9ImhzbCgzNTEsIDEwMCUsIDUwJSkiIGQ9Ik0xMDkuNTUyIDE5Ni40MzhhNjYuNSA2Ni41IDAgMDAxLjYxNy42NDUiLz48cGF0aCBzdHJva2U9ImhzbCgzNTIsIDEwMCUsIDUwJSkiIGQ9Ik0xMDguNDgzIDE5NS45ODRhNjYuNSA2Ni41IDAgMDAxLjYwNi42NzQiLz48cGF0aCBzdHJva2U9ImhzbCgzNTMsIDEwMCUsIDUwJSkiIGQ9Ik0xMDcuNDIzIDE5NS41MTJhNjYuNSA2Ni41IDAgMDAxLjU5My43MDIiLz48cGF0aCBzdHJva2U9ImhzbCgzNTQsIDEwMCUsIDUwJSkiIGQ9Ik0xMDYuMzcxIDE5NS4wMjJhNjYuNSA2Ni41IDAgMDAxLjU4MS43MjkiLz48cGF0aCBzdHJva2U9ImhzbCgzNTUsIDEwMCUsIDUwJSkiIGQ9Ik0xMDUuMzI4IDE5NC41MTNhNjYuNSA2Ni41IDAgMDAxLjU2OC43NTYiLz48cGF0aCBzdHJva2U9ImhzbCgzNTYsIDEwMCUsIDUwJSkiIGQ9Ik0xMDQuMjk0IDE5My45ODZhNjYuNSA2Ni41IDAgMDAxLjU1NC43ODQiLz48cGF0aCBzdHJva2U9ImhzbCgzNTcsIDEwMCUsIDUwJSkiIGQ9Ik0xMDMuMjY5IDE5My40NDFhNjYuNSA2Ni41IDAgMDAxLjU0LjgxIi8+PHBhdGggc3Ryb2tlPSJoc2woMzU4LCAxMDAlLCA1MCUpIiBkPSJNMTAyLjI1NCAxOTIuODc5YTY2LjUgNjYuNSAwIDAwMS41MjYuODM3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzU5LCAxMDAlLCA1MCUpIiBkPSJNMTAxLjI0OSAxOTIuMjk4YTY2LjUgNjYuNSAwIDAwMS41MTEuODY0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMCwgMTAwJSwgNTAlKSIgZD0iTTEwMC4yNTQgMTkxLjdhNjYuNSA2Ni41IDAgMDAxLjQ5Ni44OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDEsIDEwMCUsIDUwJSkiIGQ9Ik05OS4yNyAxOTEuMDg2YTY2LjUgNjYuNSAwIDAwMS40OC45MTYiLz48cGF0aCBzdHJva2U9ImhzbCgyLCAxMDAlLCA1MCUpIiBkPSJNOTguMjk2IDE5MC40NTNhNjYuNSA2Ni41IDAgMDAxLjQ2NC45NDIiLz48cGF0aCBzdHJva2U9ImhzbCgzLCAxMDAlLCA1MCUpIiBkPSJNOTcuMzM0IDE4OS44MDRhNjYuNSA2Ni41IDAgMDAxLjQ0OC45NjgiLz48cGF0aCBzdHJva2U9ImhzbCg0LCAxMDAlLCA1MCUpIiBkPSJNOTYuMzgzIDE4OS4xMzlhNjYuNSA2Ni41IDAgMDAxLjQzLjk5MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDUsIDEwMCUsIDUwJSkiIGQ9Ik05NS40NDQgMTg4LjQ1NmE2Ni41IDY2LjUgMCAwMDEuNDEzIDEuMDE4Ii8+PHBhdGggc3Ryb2tlPSJoc2woNiwgMTAwJSwgNTAlKSIgZD0iTTk0LjUxNyAxODcuNzU4YTY2LjUgNjYuNSAwIDAwMS4zOTUgMS4wNDIiLz48cGF0aCBzdHJva2U9ImhzbCg3LCAxMDAlLCA1MCUpIiBkPSJNOTMuNjAzIDE4Ny4wNDNhNjYuNSA2Ni41IDAgMDAxLjM3NiAxLjA2NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDgsIDEwMCUsIDUwJSkiIGQ9Ik05Mi43IDE4Ni4zMTNhNjYuNSA2Ni41IDAgMDAxLjM1OSAxLjA5Ii8+PHBhdGggc3Ryb2tlPSJoc2woOSwgMTAwJSwgNTAlKSIgZD0iTTkxLjgxMiAxODUuNTY3YTY2LjUgNjYuNSAwIDAwMS4zMzggMS4xMTMiLz48cGF0aCBzdHJva2U9ImhzbCgxMCwgMTAwJSwgNTAlKSIgZD0iTTkwLjkzNiAxODQuODA2YTY2LjUgNjYuNSAwIDAwMS4zMTkgMS4xMzYiLz48cGF0aCBzdHJva2U9ImhzbCgxMSwgMTAwJSwgNTAlKSIgZD0iTTkwLjA3MyAxODQuMDI5YTY2LjUgNjYuNSAwIDAwMS4zIDEuMTYiLz48cGF0aCBzdHJva2U9ImhzbCgxMiwgMTAwJSwgNTAlKSIgZD0iTTg5LjIyNCAxODMuMjM3YTY2LjUgNjYuNSAwIDAwMS4yNzkgMS4xODIiLz48cGF0aCBzdHJva2U9ImhzbCgxMywgMTAwJSwgNTAlKSIgZD0iTTg4LjM5IDE4Mi40MzFhNjYuNSA2Ni41IDAgMDAxLjI1NyAxLjIwNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE0LCAxMDAlLCA1MCUpIiBkPSJNODcuNTY5IDE4MS42MWE2Ni41IDY2LjUgMCAwMDEuMjM2IDEuMjI2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTUsIDEwMCUsIDUwJSkiIGQ9Ik04Ni43NjMgMTgwLjc3NmE2Ni41IDY2LjUgMCAwMDEuMjE0IDEuMjQ3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTYsIDEwMCUsIDUwJSkiIGQ9Ik04NS45NzEgMTc5LjkyN2E2Ni41IDY2LjUgMCAwMDEuMTkzIDEuMjY4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTcsIDEwMCUsIDUwJSkiIGQ9Ik04NS4xOTQgMTc5LjA2NGE2Ni41IDY2LjUgMCAwMDEuMTcxIDEuMjg5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTgsIDEwMCUsIDUwJSkiIGQ9Ik04NC40MzMgMTc4LjE4OGE2Ni41IDY2LjUgMCAwMDEuMTQ4IDEuMzEiLz48cGF0aCBzdHJva2U9ImhzbCgxOSwgMTAwJSwgNTAlKSIgZD0iTTgzLjY4NyAxNzcuM2E2Ni41IDY2LjUgMCAwMDEuMTI1IDEuMzI4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjAsIDEwMCUsIDUwJSkiIGQ9Ik04Mi45NTcgMTc2LjM5N2E2Ni41IDY2LjUgMCAwMDEuMTAxIDEuMzQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjEsIDEwMCUsIDUwJSkiIGQ9Ik04Mi4yNDIgMTc1LjQ4M2E2Ni41IDY2LjUgMCAwMDEuMDc4IDEuMzY3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjIsIDEwMCUsIDUwJSkiIGQ9Ik04MS41NDQgMTc0LjU1NmE2Ni41IDY2LjUgMCAwMDEuMDUzIDEuMzg1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjMsIDEwMCUsIDUwJSkiIGQ9Ik04MC44NjEgMTczLjYxN2E2Ni41IDY2LjUgMCAwMDEuMDMgMS40MDQiLz48cGF0aCBzdHJva2U9ImhzbCgyNCwgMTAwJSwgNTAlKSIgZD0iTTgwLjE5NiAxNzIuNjY2YTY2LjUgNjYuNSAwIDAwMS4wMDQgMS40MjIiLz48cGF0aCBzdHJva2U9ImhzbCgyNSwgMTAwJSwgNTAlKSIgZD0iTTc5LjU0NyAxNzEuNzA0YTY2LjUgNjYuNSAwIDAwLjk4IDEuNDM5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjYsIDEwMCUsIDUwJSkiIGQ9Ik03OC45MTQgMTcwLjczYTY2LjUgNjYuNSAwIDAwLjk1NSAxLjQ1NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3LCAxMDAlLCA1MCUpIiBkPSJNNzguMyAxNjkuNzQ2YTY2LjUgNjYuNSAwIDAwLjkyOCAxLjQ3MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI4LCAxMDAlLCA1MCUpIiBkPSJNNzcuNzAyIDE2OC43NTFhNjYuNSA2Ni41IDAgMDAuOTAzIDEuNDg5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjksIDEwMCUsIDUwJSkiIGQ9Ik03Ny4xMjEgMTY3Ljc0NmE2Ni41IDY2LjUgMCAwMC44NzcgMS41MDQiLz48cGF0aCBzdHJva2U9ImhzbCgzMCwgMTAwJSwgNTAlKSIgZD0iTTc2LjU1OSAxNjYuNzMxYTY2LjUgNjYuNSAwIDAwLjg1IDEuNTE5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzEsIDEwMCUsIDUwJSkiIGQ9Ik03Ni4wMTQgMTY1LjcwNmE2Ni41IDY2LjUgMCAwMC44MjQgMS41MzQiLz48cGF0aCBzdHJva2U9ImhzbCgzMiwgMTAwJSwgNTAlKSIgZD0iTTc1LjQ4NyAxNjQuNjcyYTY2LjUgNjYuNSAwIDAwLjc5NyAxLjU0OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDMzLCAxMDAlLCA1MCUpIiBkPSJNNzQuOTc4IDE2My42MjlhNjYuNSA2Ni41IDAgMDAuNzcgMS41NjEiLz48cGF0aCBzdHJva2U9ImhzbCgzNCwgMTAwJSwgNTAlKSIgZD0iTTc0LjQ4OCAxNjIuNTc3YTY2LjUgNjYuNSAwIDAwLjc0MiAxLjU3NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDM1LCAxMDAlLCA1MCUpIiBkPSJNNzQuMDE2IDE2MS41MTdhNjYuNSA2Ni41IDAgMDAuNzE1IDEuNTg3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzYsIDEwMCUsIDUwJSkiIGQ9Ik03My41NjIgMTYwLjQ0OGE2Ni41IDY2LjUgMCAwMC42ODcgMS42Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzcsIDEwMCUsIDUwJSkiIGQ9Ik03My4xMjcgMTU5LjM3MmE2Ni41IDY2LjUgMCAwMC42NiAxLjYxMiIvPjxwYXRoIHN0cm9rZT0iaHNsKDM4LCAxMDAlLCA1MCUpIiBkPSJNNzIuNzExIDE1OC4yODlhNjYuNSA2Ni41IDAgMDAuNjMxIDEuNjIyIi8+PHBhdGggc3Ryb2tlPSJoc2woMzksIDEwMCUsIDUwJSkiIGQ9Ik03Mi4zMTQgMTU3LjE5OGE2Ni41IDY2LjUgMCAwMC42MDMgMS42MzMiLz48cGF0aCBzdHJva2U9ImhzbCg0MCwgMTAwJSwgNTAlKSIgZD0iTTcxLjkzNiAxNTYuMWE2Ni41IDY2LjUgMCAwMC41NzQgMS42NDQiLz48cGF0aCBzdHJva2U9ImhzbCg0MSwgMTAwJSwgNTAlKSIgZD0iTTcxLjU3OCAxNTQuOTk3YTY2LjUgNjYuNSAwIDAwLjU0NSAxLjY1MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDQyLCAxMDAlLCA1MCUpIiBkPSJNNzEuMjM4IDE1My44ODdhNjYuNSA2Ni41IDAgMDAuNTE3IDEuNjYzIi8+PHBhdGggc3Ryb2tlPSJoc2woNDMsIDEwMCUsIDUwJSkiIGQ9Ik03MC45MTkgMTUyLjc3MWE2Ni41IDY2LjUgMCAwMC40ODcgMS42NzIiLz48cGF0aCBzdHJva2U9ImhzbCg0NCwgMTAwJSwgNTAlKSIgZD0iTTcwLjYxOCAxNTEuNjVhNjYuNSA2Ni41IDAgMDAuNDU4IDEuNjgiLz48cGF0aCBzdHJva2U9ImhzbCg0NSwgMTAwJSwgNTAlKSIgZD0iTTcwLjMzNyAxNTAuNTI0YTY2LjUgNjYuNSAwIDAwLjQyOSAxLjY4NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDQ2LCAxMDAlLCA1MCUpIiBkPSJNNzAuMDc2IDE0OS4zOTNhNjYuNSA2Ni41IDAgMDAuNCAxLjY5NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDQ3LCAxMDAlLCA1MCUpIiBkPSJNNjkuODM1IDE0OC4yNThhNjYuNSA2Ni41IDAgMDAuMzcgMS43MDEiLz48cGF0aCBzdHJva2U9ImhzbCg0OCwgMTAwJSwgNTAlKSIgZD0iTTY5LjYxNCAxNDcuMTE5YTY2LjUgNjYuNSAwIDAwLjM0IDEuNzA3Ii8+PHBhdGggc3Ryb2tlPSJoc2woNDksIDEwMCUsIDUwJSkiIGQ9Ik02OS40MTIgMTQ1Ljk3NmE2Ni41IDY2LjUgMCAwMC4zMSAxLjcxMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDUwLCAxMDAlLCA1MCUpIiBkPSJNNjkuMjMgMTQ0LjgzYTY2LjUgNjYuNSAwIDAwLjI4IDEuNzE4Ii8+PHBhdGggc3Ryb2tlPSJoc2woNTEsIDEwMCUsIDUwJSkiIGQ9Ik02OS4wNjkgMTQzLjY4YTY2LjUgNjYuNSAwIDAwLjI1IDEuNzIzIi8+PHBhdGggc3Ryb2tlPSJoc2woNTIsIDEwMCUsIDUwJSkiIGQ9Ik02OC45MjcgMTQyLjUyOGE2Ni41IDY2LjUgMCAwMC4yMiAxLjcyNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDUzLCAxMDAlLCA1MCUpIiBkPSJNNjguODA2IDE0MS4zNzRhNjYuNSA2Ni41IDAgMDAuMTkgMS43MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDU0LCAxMDAlLCA1MCUpIiBkPSJNNjguNzA1IDE0MC4yMThhNjYuNSA2Ni41IDAgMDAuMTYgMS43MzMiLz48cGF0aCBzdHJva2U9ImhzbCg1NSwgMTAwJSwgNTAlKSIgZD0iTTY4LjYyNCAxMzkuMDZhNjYuNSA2Ni41IDAgMDAuMTMgMS43MzYiLz48cGF0aCBzdHJva2U9ImhzbCg1NiwgMTAwJSwgNTAlKSIgZD0iTTY4LjU2MyAxMzcuOWE2Ni41IDY2LjUgMCAwMC4wOTkgMS43MzkiLz48cGF0aCBzdHJva2U9ImhzbCg1NywgMTAwJSwgNTAlKSIgZD0iTTY4LjUyMyAxMzYuNzRhNjYuNSA2Ni41IDAgMDAuMDY4IDEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCg1OCwgMTAwJSwgNTAlKSIgZD0iTTY4LjUwMyAxMzUuNThhNjYuNSA2Ni41IDAgMDAuMDM4IDEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCg1OSwgMTAwJSwgNTAlKSIgZD0iTTY4LjUwMyAxMzQuNDJhNjYuNSA2Ni41IDAgMDAuMDA3IDEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCg2MCwgMTAwJSwgNTAlKSIgZD0iTTY4LjUyMyAxMzMuMjZBNjYuNSA2Ni41IDAgMDA2OC41IDEzNSIvPjxwYXRoIHN0cm9rZT0iaHNsKDYxLCAxMDAlLCA1MCUpIiBkPSJNNjguNTYzIDEzMi4xYTY2LjUgNjYuNSAwIDAwLS4wNTMgMS43NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDYyLCAxMDAlLCA1MCUpIiBkPSJNNjguNjI0IDEzMC45NGE2Ni41IDY2LjUgMCAwMC0uMDgzIDEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCg2MywgMTAwJSwgNTAlKSIgZD0iTTY4LjcwNSAxMjkuNzgyYTY2LjUgNjYuNSAwIDAwLS4xMTQgMS43MzgiLz48cGF0aCBzdHJva2U9ImhzbCg2NCwgMTAwJSwgNTAlKSIgZD0iTTY4LjgwNiAxMjguNjI2YTY2LjUgNjYuNSAwIDAwLS4xNDQgMS43MzUiLz48cGF0aCBzdHJva2U9ImhzbCg2NSwgMTAwJSwgNTAlKSIgZD0iTTY4LjkyNyAxMjcuNDcyYTY2LjUgNjYuNSAwIDAwLS4xNzQgMS43MzIiLz48cGF0aCBzdHJva2U9ImhzbCg2NiwgMTAwJSwgNTAlKSIgZD0iTTY5LjA2OSAxMjYuMzJhNjYuNSA2Ni41IDAgMDAtLjIwNSAxLjcyOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDY3LCAxMDAlLCA1MCUpIiBkPSJNNjkuMjMgMTI1LjE3YTY2LjUgNjYuNSAwIDAwLS4yMzQgMS43MjYiLz48cGF0aCBzdHJva2U9ImhzbCg2OCwgMTAwJSwgNTAlKSIgZD0iTTY5LjQxMiAxMjQuMDI0YTY2LjUgNjYuNSAwIDAwLS4yNjUgMS43MjEiLz48cGF0aCBzdHJva2U9ImhzbCg2OSwgMTAwJSwgNTAlKSIgZD0iTTY5LjYxNCAxMjIuODgxYTY2LjUgNjYuNSAwIDAwLS4yOTUgMS43MTYiLz48cGF0aCBzdHJva2U9ImhzbCg3MCwgMTAwJSwgNTAlKSIgZD0iTTY5LjgzNSAxMjEuNzQyYTY2LjUgNjYuNSAwIDAwLS4zMjUgMS43MSIvPjxwYXRoIHN0cm9rZT0iaHNsKDcxLCAxMDAlLCA1MCUpIiBkPSJNNzAuMDc2IDEyMC42MDdhNjYuNSA2Ni41IDAgMDAtLjM1NCAxLjcwNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDcyLCAxMDAlLCA1MCUpIiBkPSJNNzAuMzM3IDExOS40NzZhNjYuNSA2Ni41IDAgMDAtLjM4NCAxLjY5OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDczLCAxMDAlLCA1MCUpIiBkPSJNNzAuNjE4IDExOC4zNWE2Ni41IDY2LjUgMCAwMC0uNDE0IDEuNjkiLz48cGF0aCBzdHJva2U9ImhzbCg3NCwgMTAwJSwgNTAlKSIgZD0iTTcwLjkxOSAxMTcuMjI5YTY2LjUgNjYuNSAwIDAwLS40NDQgMS42ODMiLz48cGF0aCBzdHJva2U9ImhzbCg3NSwgMTAwJSwgNTAlKSIgZD0iTTcxLjIzOCAxMTYuMTEzYTY2LjUgNjYuNSAwIDAwLS40NzIgMS42NzYiLz48cGF0aCBzdHJva2U9ImhzbCg3NiwgMTAwJSwgNTAlKSIgZD0iTTcxLjU3OCAxMTUuMDAzYTY2LjUgNjYuNSAwIDAwLS41MDIgMS42NjciLz48cGF0aCBzdHJva2U9ImhzbCg3NywgMTAwJSwgNTAlKSIgZD0iTTcxLjkzNiAxMTMuOWE2Ni41IDY2LjUgMCAwMC0uNTMgMS42NTciLz48cGF0aCBzdHJva2U9ImhzbCg3OCwgMTAwJSwgNTAlKSIgZD0iTTcyLjMxNCAxMTIuODAyYTY2LjUgNjYuNSAwIDAwLS41NiAxLjY0OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDc5LCAxMDAlLCA1MCUpIiBkPSJNNzIuNzExIDExMS43MTFhNjYuNSA2Ni41IDAgMDAtLjU4OCAxLjYzOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDgwLCAxMDAlLCA1MCUpIiBkPSJNNzMuMTI3IDExMC42MjhhNjYuNSA2Ni41IDAgMDAtLjYxNyAxLjYyOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDgxLCAxMDAlLCA1MCUpIiBkPSJNNzMuNTYyIDEwOS41NTJhNjYuNSA2Ni41IDAgMDAtLjY0NSAxLjYxNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDgyLCAxMDAlLCA1MCUpIiBkPSJNNzQuMDE2IDEwOC40ODNhNjYuNSA2Ni41IDAgMDAtLjY3NCAxLjYwNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDgzLCAxMDAlLCA1MCUpIiBkPSJNNzQuNDg4IDEwNy40MjNhNjYuNSA2Ni41IDAgMDAtLjcwMiAxLjU5MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDg0LCAxMDAlLCA1MCUpIiBkPSJNNzQuOTc4IDEwNi4zNzFhNjYuNSA2Ni41IDAgMDAtLjcyOSAxLjU4MSIvPjxwYXRoIHN0cm9rZT0iaHNsKDg1LCAxMDAlLCA1MCUpIiBkPSJNNzUuNDg3IDEwNS4zMjhhNjYuNSA2Ni41IDAgMDAtLjc1NiAxLjU2OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDg2LCAxMDAlLCA1MCUpIiBkPSJNNzYuMDE0IDEwNC4yOTRhNjYuNSA2Ni41IDAgMDAtLjc4NCAxLjU1NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDg3LCAxMDAlLCA1MCUpIiBkPSJNNzYuNTU5IDEwMy4yNjlhNjYuNSA2Ni41IDAgMDAtLjgxIDEuNTQiLz48cGF0aCBzdHJva2U9ImhzbCg4OCwgMTAwJSwgNTAlKSIgZD0iTTc3LjEyMSAxMDIuMjU0YTY2LjUgNjYuNSAwIDAwLS44MzcgMS41MjYiLz48cGF0aCBzdHJva2U9ImhzbCg4OSwgMTAwJSwgNTAlKSIgZD0iTTc3LjcwMiAxMDEuMjQ5YTY2LjUgNjYuNSAwIDAwLS44NjQgMS41MTEiLz48cGF0aCBzdHJva2U9ImhzbCg5MCwgMTAwJSwgNTAlKSIgZD0iTTc4LjMgMTAwLjI1NGE2Ni41IDY2LjUgMCAwMC0uODkgMS40OTYiLz48cGF0aCBzdHJva2U9ImhzbCg5MSwgMTAwJSwgNTAlKSIgZD0iTTc4LjkxNCA5OS4yN2E2Ni41IDY2LjUgMCAwMC0uOTE2IDEuNDgiLz48cGF0aCBzdHJva2U9ImhzbCg5MiwgMTAwJSwgNTAlKSIgZD0iTTc5LjU0NyA5OC4yOTZhNjYuNSA2Ni41IDAgMDAtLjk0MiAxLjQ2NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDkzLCAxMDAlLCA1MCUpIiBkPSJNODAuMTk2IDk3LjMzNGE2Ni41IDY2LjUgMCAwMC0uOTY4IDEuNDQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woOTQsIDEwMCUsIDUwJSkiIGQ9Ik04MC44NjEgOTYuMzgzYTY2LjUgNjYuNSAwIDAwLS45OTIgMS40MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDk1LCAxMDAlLCA1MCUpIiBkPSJNODEuNTQ0IDk1LjQ0NGE2Ni41IDY2LjUgMCAwMC0xLjAxOCAxLjQxMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDk2LCAxMDAlLCA1MCUpIiBkPSJNODIuMjQyIDk0LjUxN2E2Ni41IDY2LjUgMCAwMC0xLjA0MiAxLjM5NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDk3LCAxMDAlLCA1MCUpIiBkPSJNODIuOTU3IDkzLjYwM2E2Ni41IDY2LjUgMCAwMC0xLjA2NiAxLjM3NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDk4LCAxMDAlLCA1MCUpIiBkPSJNODMuNjg3IDkyLjdhNjYuNSA2Ni41IDAgMDAtMS4wOSAxLjM1OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDk5LCAxMDAlLCA1MCUpIiBkPSJNODQuNDMzIDkxLjgxMmE2Ni41IDY2LjUgMCAwMC0xLjExMyAxLjMzOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwMCwgMTAwJSwgNTAlKSIgZD0iTTg1LjE5NCA5MC45MzZhNjYuNSA2Ni41IDAgMDAtMS4xMzYgMS4zMTkiLz48cGF0aCBzdHJva2U9ImhzbCgxMDEsIDEwMCUsIDUwJSkiIGQ9Ik04NS45NzEgOTAuMDczYTY2LjUgNjYuNSAwIDAwLTEuMTYgMS4zIi8+PHBhdGggc3Ryb2tlPSJoc2woMTAyLCAxMDAlLCA1MCUpIiBkPSJNODYuNzYzIDg5LjIyNGE2Ni41IDY2LjUgMCAwMC0xLjE4MiAxLjI3OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwMywgMTAwJSwgNTAlKSIgZD0iTTg3LjU2OSA4OC4zOWE2Ni41IDY2LjUgMCAwMC0xLjIwNCAxLjI1NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwNCwgMTAwJSwgNTAlKSIgZD0iTTg4LjM5IDg3LjU2OWE2Ni41IDY2LjUgMCAwMC0xLjIyNiAxLjIzNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwNSwgMTAwJSwgNTAlKSIgZD0iTTg5LjIyNCA4Ni43NjNhNjYuNSA2Ni41IDAgMDAtMS4yNDcgMS4yMTQiLz48cGF0aCBzdHJva2U9ImhzbCgxMDYsIDEwMCUsIDUwJSkiIGQ9Ik05MC4wNzMgODUuOTcxYTY2LjUgNjYuNSAwIDAwLTEuMjY4IDEuMTkzIi8+PHBhdGggc3Ryb2tlPSJoc2woMTA3LCAxMDAlLCA1MCUpIiBkPSJNOTAuOTM2IDg1LjE5NGE2Ni41IDY2LjUgMCAwMC0xLjI4OSAxLjE3MSIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwOCwgMTAwJSwgNTAlKSIgZD0iTTkxLjgxMiA4NC40MzNhNjYuNSA2Ni41IDAgMDAtMS4zMSAxLjE0OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwOSwgMTAwJSwgNTAlKSIgZD0iTTkyLjcgODMuNjg3YTY2LjUgNjYuNSAwIDAwLTEuMzI4IDEuMTI1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTEwLCAxMDAlLCA1MCUpIiBkPSJNOTMuNjAzIDgyLjk1N2E2Ni41IDY2LjUgMCAwMC0xLjM0OCAxLjEwMSIvPjxwYXRoIHN0cm9rZT0iaHNsKDExMSwgMTAwJSwgNTAlKSIgZD0iTTk0LjUxNyA4Mi4yNDJhNjYuNSA2Ni41IDAgMDAtMS4zNjcgMS4wNzgiLz48cGF0aCBzdHJva2U9ImhzbCgxMTIsIDEwMCUsIDUwJSkiIGQ9Ik05NS40NDQgODEuNTQ0YTY2LjUgNjYuNSAwIDAwLTEuMzg1IDEuMDUzIi8+PHBhdGggc3Ryb2tlPSJoc2woMTEzLCAxMDAlLCA1MCUpIiBkPSJNOTYuMzgzIDgwLjg2MWE2Ni41IDY2LjUgMCAwMC0xLjQwNCAxLjAzIi8+PHBhdGggc3Ryb2tlPSJoc2woMTE0LCAxMDAlLCA1MCUpIiBkPSJNOTcuMzM0IDgwLjE5NmE2Ni41IDY2LjUgMCAwMC0xLjQyMiAxLjAwNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDExNSwgMTAwJSwgNTAlKSIgZD0iTTk4LjI5NiA3OS41NDdhNjYuNSA2Ni41IDAgMDAtMS40MzkuOTgiLz48cGF0aCBzdHJva2U9ImhzbCgxMTYsIDEwMCUsIDUwJSkiIGQ9Ik05OS4yNyA3OC45MTRhNjYuNSA2Ni41IDAgMDAtMS40NTYuOTU1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTE3LCAxMDAlLCA1MCUpIiBkPSJNMTAwLjI1NCA3OC4zYTY2LjUgNjYuNSAwIDAwLTEuNDcyLjkyOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDExOCwgMTAwJSwgNTAlKSIgZD0iTTEwMS4yNDkgNzcuNzAyYTY2LjUgNjYuNSAwIDAwLTEuNDg5LjkwMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDExOSwgMTAwJSwgNTAlKSIgZD0iTTEwMi4yNTQgNzcuMTIxYTY2LjUgNjYuNSAwIDAwLTEuNTA0Ljg3NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDEyMCwgMTAwJSwgNTAlKSIgZD0iTTEwMy4yNjkgNzYuNTU5YTY2LjUgNjYuNSAwIDAwLTEuNTE5Ljg1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTIxLCAxMDAlLCA1MCUpIiBkPSJNMTA0LjI5NCA3Ni4wMTRhNjYuNSA2Ni41IDAgMDAtMS41MzQuODI0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTIyLCAxMDAlLCA1MCUpIiBkPSJNMTA1LjMyOCA3NS40ODdhNjYuNSA2Ni41IDAgMDAtMS41NDguNzk3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTIzLCAxMDAlLCA1MCUpIiBkPSJNMTA2LjM3MSA3NC45NzhhNjYuNSA2Ni41IDAgMDAtMS41NjEuNzciLz48cGF0aCBzdHJva2U9ImhzbCgxMjQsIDEwMCUsIDUwJSkiIGQ9Ik0xMDcuNDIzIDc0LjQ4OGE2Ni41IDY2LjUgMCAwMC0xLjU3NS43NDIiLz48cGF0aCBzdHJva2U9ImhzbCgxMjUsIDEwMCUsIDUwJSkiIGQ9Ik0xMDguNDgzIDc0LjAxNmE2Ni41IDY2LjUgMCAwMC0xLjU4Ny43MTUiLz48cGF0aCBzdHJva2U9ImhzbCgxMjYsIDEwMCUsIDUwJSkiIGQ9Ik0xMDkuNTUyIDczLjU2MmE2Ni41IDY2LjUgMCAwMC0xLjYuNjg3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTI3LCAxMDAlLCA1MCUpIiBkPSJNMTEwLjYyOCA3My4xMjdhNjYuNSA2Ni41IDAgMDAtMS42MTIuNjYiLz48cGF0aCBzdHJva2U9ImhzbCgxMjgsIDEwMCUsIDUwJSkiIGQ9Ik0xMTEuNzExIDcyLjcxMWE2Ni41IDY2LjUgMCAwMC0xLjYyMi42MzEiLz48cGF0aCBzdHJva2U9ImhzbCgxMjksIDEwMCUsIDUwJSkiIGQ9Ik0xMTIuODAyIDcyLjMxNGE2Ni41IDY2LjUgMCAwMC0xLjYzMy42MDMiLz48cGF0aCBzdHJva2U9ImhzbCgxMzAsIDEwMCUsIDUwJSkiIGQ9Ik0xMTMuOSA3MS45MzZhNjYuNSA2Ni41IDAgMDAtMS42NDQuNTc0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTMxLCAxMDAlLCA1MCUpIiBkPSJNMTE1LjAwMyA3MS41NzhhNjYuNSA2Ni41IDAgMDAtMS42NTMuNTQ1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTMyLCAxMDAlLCA1MCUpIiBkPSJNMTE2LjExMyA3MS4yMzhhNjYuNSA2Ni41IDAgMDAtMS42NjMuNTE3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTMzLCAxMDAlLCA1MCUpIiBkPSJNMTE3LjIyOSA3MC45MTlhNjYuNSA2Ni41IDAgMDAtMS42NzIuNDg3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTM0LCAxMDAlLCA1MCUpIiBkPSJNMTE4LjM1IDcwLjYxOGE2Ni41IDY2LjUgMCAwMC0xLjY4LjQ1OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDEzNSwgMTAwJSwgNTAlKSIgZD0iTTExOS40NzYgNzAuMzM3YTY2LjUgNjYuNSAwIDAwLTEuNjg3LjQyOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDEzNiwgMTAwJSwgNTAlKSIgZD0iTTEyMC42MDcgNzAuMDc2YTY2LjUgNjYuNSAwIDAwLTEuNjk1LjQiLz48cGF0aCBzdHJva2U9ImhzbCgxMzcsIDEwMCUsIDUwJSkiIGQ9Ik0xMjEuNzQyIDY5LjgzNWE2Ni41IDY2LjUgMCAwMC0xLjcwMS4zNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDEzOCwgMTAwJSwgNTAlKSIgZD0iTTEyMi44ODEgNjkuNjE0YTY2LjUgNjYuNSAwIDAwLTEuNzA3LjM0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTM5LCAxMDAlLCA1MCUpIiBkPSJNMTI0LjAyNCA2OS40MTJhNjYuNSA2Ni41IDAgMDAtMS43MTMuMzEiLz48cGF0aCBzdHJva2U9ImhzbCgxNDAsIDEwMCUsIDUwJSkiIGQ9Ik0xMjUuMTcgNjkuMjNhNjYuNSA2Ni41IDAgMDAtMS43MTguMjgiLz48cGF0aCBzdHJva2U9ImhzbCgxNDEsIDEwMCUsIDUwJSkiIGQ9Ik0xMjYuMzIgNjkuMDY5YTY2LjUgNjYuNSAwIDAwLTEuNzIzLjI1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTQyLCAxMDAlLCA1MCUpIiBkPSJNMTI3LjQ3MiA2OC45MjdhNjYuNSA2Ni41IDAgMDAtMS43MjcuMjIiLz48cGF0aCBzdHJva2U9ImhzbCgxNDMsIDEwMCUsIDUwJSkiIGQ9Ik0xMjguNjI2IDY4LjgwNmE2Ni41IDY2LjUgMCAwMC0xLjczLjE5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTQ0LCAxMDAlLCA1MCUpIiBkPSJNMTI5Ljc4MiA2OC43MDVhNjYuNSA2Ni41IDAgMDAtMS43MzMuMTYiLz48cGF0aCBzdHJva2U9ImhzbCgxNDUsIDEwMCUsIDUwJSkiIGQ9Ik0xMzAuOTQgNjguNjI0YTY2LjUgNjYuNSAwIDAwLTEuNzM2LjEzIi8+PHBhdGggc3Ryb2tlPSJoc2woMTQ2LCAxMDAlLCA1MCUpIiBkPSJNMTMyLjEgNjguNTYzYTY2LjUgNjYuNSAwIDAwLTEuNzM5LjA5OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE0NywgMTAwJSwgNTAlKSIgZD0iTTEzMy4yNiA2OC41MjNhNjYuNSA2Ni41IDAgMDAtMS43NC4wNjgiLz48cGF0aCBzdHJva2U9ImhzbCgxNDgsIDEwMCUsIDUwJSkiIGQ9Ik0xMzQuNDIgNjguNTAzYTY2LjUgNjYuNSAwIDAwLTEuNzQuMDM4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTQ5LCAxMDAlLCA1MCUpIiBkPSJNMTM1LjU4IDY4LjUwM2E2Ni41IDY2LjUgMCAwMC0xLjc0LjAwNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1MCwgMTAwJSwgNTAlKSIgZD0iTTEzNi43NCA2OC41MjNBNjYuNSA2Ni41IDAgMDAxMzUgNjguNSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1MSwgMTAwJSwgNTAlKSIgZD0iTTEzNy45IDY4LjU2M2E2Ni41IDY2LjUgMCAwMC0xLjc0LS4wNTMiLz48cGF0aCBzdHJva2U9ImhzbCgxNTIsIDEwMCUsIDUwJSkiIGQ9Ik0xMzkuMDYgNjguNjI0YTY2LjUgNjYuNSAwIDAwLTEuNzQtLjA4MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1MywgMTAwJSwgNTAlKSIgZD0iTTE0MC4yMTggNjguNzA1YTY2LjUgNjYuNSAwIDAwLTEuNzM4LS4xMTQiLz48cGF0aCBzdHJva2U9ImhzbCgxNTQsIDEwMCUsIDUwJSkiIGQ9Ik0xNDEuMzc0IDY4LjgwNmE2Ni41IDY2LjUgMCAwMC0xLjczNS0uMTQ0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTU1LCAxMDAlLCA1MCUpIiBkPSJNMTQyLjUyOCA2OC45MjdhNjYuNSA2Ni41IDAgMDAtMS43MzItLjE3NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1NiwgMTAwJSwgNTAlKSIgZD0iTTE0My42OCA2OS4wNjlhNjYuNSA2Ni41IDAgMDAtMS43MjktLjIwNSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1NywgMTAwJSwgNTAlKSIgZD0iTTE0NC44MyA2OS4yM2E2Ni41IDY2LjUgMCAwMC0xLjcyNi0uMjM0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTU4LCAxMDAlLCA1MCUpIiBkPSJNMTQ1Ljk3NiA2OS40MTJhNjYuNSA2Ni41IDAgMDAtMS43MjEtLjI2NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1OSwgMTAwJSwgNTAlKSIgZD0iTTE0Ny4xMTkgNjkuNjE0YTY2LjUgNjYuNSAwIDAwLTEuNzE2LS4yOTUiLz48cGF0aCBzdHJva2U9ImhzbCgxNjAsIDEwMCUsIDUwJSkiIGQ9Ik0xNDguMjU4IDY5LjgzNWE2Ni41IDY2LjUgMCAwMC0xLjcxLS4zMjUiLz48cGF0aCBzdHJva2U9ImhzbCgxNjEsIDEwMCUsIDUwJSkiIGQ9Ik0xNDkuMzkzIDcwLjA3NmE2Ni41IDY2LjUgMCAwMC0xLjcwNC0uMzU0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTYyLCAxMDAlLCA1MCUpIiBkPSJNMTUwLjUyNCA3MC4zMzdhNjYuNSA2Ni41IDAgMDAtMS42OTgtLjM4NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE2MywgMTAwJSwgNTAlKSIgZD0iTTE1MS42NSA3MC42MThhNjYuNSA2Ni41IDAgMDAtMS42OS0uNDE0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTY0LCAxMDAlLCA1MCUpIiBkPSJNMTUyLjc3MSA3MC45MTlhNjYuNSA2Ni41IDAgMDAtMS42ODMtLjQ0NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE2NSwgMTAwJSwgNTAlKSIgZD0iTTE1My44ODcgNzEuMjM4YTY2LjUgNjYuNSAwIDAwLTEuNjc2LS40NzIiLz48cGF0aCBzdHJva2U9ImhzbCgxNjYsIDEwMCUsIDUwJSkiIGQ9Ik0xNTQuOTk3IDcxLjU3OGE2Ni41IDY2LjUgMCAwMC0xLjY2Ny0uNTAyIi8+PHBhdGggc3Ryb2tlPSJoc2woMTY3LCAxMDAlLCA1MCUpIiBkPSJNMTU2LjEgNzEuOTM2YTY2LjUgNjYuNSAwIDAwLTEuNjU3LS41MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDE2OCwgMTAwJSwgNTAlKSIgZD0iTTE1Ny4xOTggNzIuMzE0YTY2LjUgNjYuNSAwIDAwLTEuNjQ4LS41NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDE2OSwgMTAwJSwgNTAlKSIgZD0iTTE1OC4yODkgNzIuNzExYTY2LjUgNjYuNSAwIDAwLTEuNjM5LS41ODgiLz48cGF0aCBzdHJva2U9ImhzbCgxNzAsIDEwMCUsIDUwJSkiIGQ9Ik0xNTkuMzcyIDczLjEyN2E2Ni41IDY2LjUgMCAwMC0xLjYyOC0uNjE3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTcxLCAxMDAlLCA1MCUpIiBkPSJNMTYwLjQ0OCA3My41NjJhNjYuNSA2Ni41IDAgMDAtMS42MTctLjY0NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE3MiwgMTAwJSwgNTAlKSIgZD0iTTE2MS41MTcgNzQuMDE2YTY2LjUgNjYuNSAwIDAwLTEuNjA2LS42NzQiLz48cGF0aCBzdHJva2U9ImhzbCgxNzMsIDEwMCUsIDUwJSkiIGQ9Ik0xNjIuNTc3IDc0LjQ4OGE2Ni41IDY2LjUgMCAwMC0xLjU5My0uNzAyIi8+PHBhdGggc3Ryb2tlPSJoc2woMTc0LCAxMDAlLCA1MCUpIiBkPSJNMTYzLjYyOSA3NC45NzhhNjYuNSA2Ni41IDAgMDAtMS41ODEtLjcyOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE3NSwgMTAwJSwgNTAlKSIgZD0iTTE2NC42NzIgNzUuNDg3YTY2LjUgNjYuNSAwIDAwLTEuNTY4LS43NTYiLz48cGF0aCBzdHJva2U9ImhzbCgxNzYsIDEwMCUsIDUwJSkiIGQ9Ik0xNjUuNzA2IDc2LjAxNGE2Ni41IDY2LjUgMCAwMC0xLjU1NC0uNzg0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTc3LCAxMDAlLCA1MCUpIiBkPSJNMTY2LjczMSA3Ni41NTlhNjYuNSA2Ni41IDAgMDAtMS41NC0uODEiLz48cGF0aCBzdHJva2U9ImhzbCgxNzgsIDEwMCUsIDUwJSkiIGQ9Ik0xNjcuNzQ2IDc3LjEyMWE2Ni41IDY2LjUgMCAwMC0xLjUyNi0uODM3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTc5LCAxMDAlLCA1MCUpIiBkPSJNMTY4Ljc1MSA3Ny43MDJhNjYuNSA2Ni41IDAgMDAtMS41MTEtLjg2NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE4MCwgMTAwJSwgNTAlKSIgZD0iTTE2OS43NDYgNzguM2E2Ni41IDY2LjUgMCAwMC0xLjQ5Ni0uODkiLz48cGF0aCBzdHJva2U9ImhzbCgxODEsIDEwMCUsIDUwJSkiIGQ9Ik0xNzAuNzMgNzguOTE0YTY2LjUgNjYuNSAwIDAwLTEuNDgtLjkxNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDE4MiwgMTAwJSwgNTAlKSIgZD0iTTE3MS43MDQgNzkuNTQ3YTY2LjUgNjYuNSAwIDAwLTEuNDY0LS45NDIiLz48cGF0aCBzdHJva2U9ImhzbCgxODMsIDEwMCUsIDUwJSkiIGQ9Ik0xNzIuNjY2IDgwLjE5NmE2Ni41IDY2LjUgMCAwMC0xLjQ0OC0uOTY4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTg0LCAxMDAlLCA1MCUpIiBkPSJNMTczLjYxNyA4MC44NjFhNjYuNSA2Ni41IDAgMDAtMS40My0uOTkyIi8+PHBhdGggc3Ryb2tlPSJoc2woMTg1LCAxMDAlLCA1MCUpIiBkPSJNMTc0LjU1NiA4MS41NDRhNjYuNSA2Ni41IDAgMDAtMS40MTMtMS4wMTgiLz48cGF0aCBzdHJva2U9ImhzbCgxODYsIDEwMCUsIDUwJSkiIGQ9Ik0xNzUuNDgzIDgyLjI0MmE2Ni41IDY2LjUgMCAwMC0xLjM5NS0xLjA0MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDE4NywgMTAwJSwgNTAlKSIgZD0iTTE3Ni4zOTcgODIuOTU3YTY2LjUgNjYuNSAwIDAwLTEuMzc2LTEuMDY2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTg4LCAxMDAlLCA1MCUpIiBkPSJNMTc3LjMgODMuNjg3YTY2LjUgNjYuNSAwIDAwLTEuMzU5LTEuMDkiLz48cGF0aCBzdHJva2U9ImhzbCgxODksIDEwMCUsIDUwJSkiIGQ9Ik0xNzguMTg4IDg0LjQzM2E2Ni41IDY2LjUgMCAwMC0xLjMzOC0xLjExMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDE5MCwgMTAwJSwgNTAlKSIgZD0iTTE3OS4wNjQgODUuMTk0YTY2LjUgNjYuNSAwIDAwLTEuMzE5LTEuMTM2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTkxLCAxMDAlLCA1MCUpIiBkPSJNMTc5LjkyNyA4NS45NzFhNjYuNSA2Ni41IDAgMDAtMS4zLTEuMTYiLz48cGF0aCBzdHJva2U9ImhzbCgxOTIsIDEwMCUsIDUwJSkiIGQ9Ik0xODAuNzc2IDg2Ljc2M2E2Ni41IDY2LjUgMCAwMC0xLjI3OS0xLjE4MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDE5MywgMTAwJSwgNTAlKSIgZD0iTTE4MS42MSA4Ny41NjlhNjYuNSA2Ni41IDAgMDAtMS4yNTctMS4yMDQiLz48cGF0aCBzdHJva2U9ImhzbCgxOTQsIDEwMCUsIDUwJSkiIGQ9Ik0xODIuNDMxIDg4LjM5YTY2LjUgNjYuNSAwIDAwLTEuMjM2LTEuMjI2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTk1LCAxMDAlLCA1MCUpIiBkPSJNMTgzLjIzNyA4OS4yMjRhNjYuNSA2Ni41IDAgMDAtMS4yMTQtMS4yNDciLz48cGF0aCBzdHJva2U9ImhzbCgxOTYsIDEwMCUsIDUwJSkiIGQ9Ik0xODQuMDI5IDkwLjA3M2E2Ni41IDY2LjUgMCAwMC0xLjE5My0xLjI2OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE5NywgMTAwJSwgNTAlKSIgZD0iTTE4NC44MDYgOTAuOTM2YTY2LjUgNjYuNSAwIDAwLTEuMTcxLTEuMjg5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTk4LCAxMDAlLCA1MCUpIiBkPSJNMTg1LjU2NyA5MS44MTJhNjYuNSA2Ni41IDAgMDAtMS4xNDgtMS4zMSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE5OSwgMTAwJSwgNTAlKSIgZD0iTTE4Ni4zMTMgOTIuN2E2Ni41IDY2LjUgMCAwMC0xLjEyNS0xLjMyOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwMCwgMTAwJSwgNTAlKSIgZD0iTTE4Ny4wNDMgOTMuNjAzYTY2LjUgNjYuNSAwIDAwLTEuMTAxLTEuMzQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjAxLCAxMDAlLCA1MCUpIiBkPSJNMTg3Ljc1OCA5NC41MTdhNjYuNSA2Ni41IDAgMDAtMS4wNzgtMS4zNjciLz48cGF0aCBzdHJva2U9ImhzbCgyMDIsIDEwMCUsIDUwJSkiIGQ9Ik0xODguNDU2IDk1LjQ0NGE2Ni41IDY2LjUgMCAwMC0xLjA1My0xLjM4NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwMywgMTAwJSwgNTAlKSIgZD0iTTE4OS4xMzkgOTYuMzgzYTY2LjUgNjYuNSAwIDAwLTEuMDMtMS40MDQiLz48cGF0aCBzdHJva2U9ImhzbCgyMDQsIDEwMCUsIDUwJSkiIGQ9Ik0xODkuODA0IDk3LjMzNGE2Ni41IDY2LjUgMCAwMC0xLjAwNC0xLjQyMiIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwNSwgMTAwJSwgNTAlKSIgZD0iTTE5MC40NTMgOTguMjk2YTY2LjUgNjYuNSAwIDAwLS45OC0xLjQzOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwNiwgMTAwJSwgNTAlKSIgZD0iTTE5MS4wODYgOTkuMjdhNjYuNSA2Ni41IDAgMDAtLjk1NS0xLjQ1NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwNywgMTAwJSwgNTAlKSIgZD0iTTE5MS43IDEwMC4yNTRhNjYuNSA2Ni41IDAgMDAtLjkyOC0xLjQ3MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwOCwgMTAwJSwgNTAlKSIgZD0iTTE5Mi4yOTggMTAxLjI0OWE2Ni41IDY2LjUgMCAwMC0uOTAzLTEuNDg5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjA5LCAxMDAlLCA1MCUpIiBkPSJNMTkyLjg3OSAxMDIuMjU0YTY2LjUgNjYuNSAwIDAwLS44NzctMS41MDQiLz48cGF0aCBzdHJva2U9ImhzbCgyMTAsIDEwMCUsIDUwJSkiIGQ9Ik0xOTMuNDQxIDEwMy4yNjlhNjYuNSA2Ni41IDAgMDAtLjg1LTEuNTE5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjExLCAxMDAlLCA1MCUpIiBkPSJNMTkzLjk4NiAxMDQuMjk0YTY2LjUgNjYuNSAwIDAwLS44MjQtMS41MzQiLz48cGF0aCBzdHJva2U9ImhzbCgyMTIsIDEwMCUsIDUwJSkiIGQ9Ik0xOTQuNTEzIDEwNS4zMjhhNjYuNSA2Ni41IDAgMDAtLjc5Ny0xLjU0OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDIxMywgMTAwJSwgNTAlKSIgZD0iTTE5NS4wMjIgMTA2LjM3MWE2Ni41IDY2LjUgMCAwMC0uNzctMS41NjEiLz48cGF0aCBzdHJva2U9ImhzbCgyMTQsIDEwMCUsIDUwJSkiIGQ9Ik0xOTUuNTEyIDEwNy40MjNhNjYuNSA2Ni41IDAgMDAtLjc0Mi0xLjU3NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDIxNSwgMTAwJSwgNTAlKSIgZD0iTTE5NS45ODQgMTA4LjQ4M2E2Ni41IDY2LjUgMCAwMC0uNzE1LTEuNTg3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjE2LCAxMDAlLCA1MCUpIiBkPSJNMTk2LjQzOCAxMDkuNTUyYTY2LjUgNjYuNSAwIDAwLS42ODctMS42Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjE3LCAxMDAlLCA1MCUpIiBkPSJNMTk2Ljg3MyAxMTAuNjI4YTY2LjUgNjYuNSAwIDAwLS42Ni0xLjYxMiIvPjxwYXRoIHN0cm9rZT0iaHNsKDIxOCwgMTAwJSwgNTAlKSIgZD0iTTE5Ny4yODkgMTExLjcxMWE2Ni41IDY2LjUgMCAwMC0uNjMxLTEuNjIyIi8+PHBhdGggc3Ryb2tlPSJoc2woMjE5LCAxMDAlLCA1MCUpIiBkPSJNMTk3LjY4NiAxMTIuODAyYTY2LjUgNjYuNSAwIDAwLS42MDMtMS42MzMiLz48cGF0aCBzdHJva2U9ImhzbCgyMjAsIDEwMCUsIDUwJSkiIGQ9Ik0xOTguMDY0IDExMy45YTY2LjUgNjYuNSAwIDAwLS41NzQtMS42NDQiLz48cGF0aCBzdHJva2U9ImhzbCgyMjEsIDEwMCUsIDUwJSkiIGQ9Ik0xOTguNDIyIDExNS4wMDNhNjYuNSA2Ni41IDAgMDAtLjU0NS0xLjY1MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIyMiwgMTAwJSwgNTAlKSIgZD0iTTE5OC43NjIgMTE2LjExM2E2Ni41IDY2LjUgMCAwMC0uNTE3LTEuNjYzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjIzLCAxMDAlLCA1MCUpIiBkPSJNMTk5LjA4MSAxMTcuMjI5YTY2LjUgNjYuNSAwIDAwLS40ODctMS42NzIiLz48cGF0aCBzdHJva2U9ImhzbCgyMjQsIDEwMCUsIDUwJSkiIGQ9Ik0xOTkuMzgyIDExOC4zNWE2Ni41IDY2LjUgMCAwMC0uNDU4LTEuNjgiLz48cGF0aCBzdHJva2U9ImhzbCgyMjUsIDEwMCUsIDUwJSkiIGQ9Ik0xOTkuNjYzIDExOS40NzZhNjYuNSA2Ni41IDAgMDAtLjQyOS0xLjY4NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIyNiwgMTAwJSwgNTAlKSIgZD0iTTE5OS45MjQgMTIwLjYwN2E2Ni41IDY2LjUgMCAwMC0uNC0xLjY5NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDIyNywgMTAwJSwgNTAlKSIgZD0iTTIwMC4xNjUgMTIxLjc0MmE2Ni41IDY2LjUgMCAwMC0uMzctMS43MDEiLz48cGF0aCBzdHJva2U9ImhzbCgyMjgsIDEwMCUsIDUwJSkiIGQ9Ik0yMDAuMzg2IDEyMi44ODFhNjYuNSA2Ni41IDAgMDAtLjM0LTEuNzA3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjI5LCAxMDAlLCA1MCUpIiBkPSJNMjAwLjU4OCAxMjQuMDI0YTY2LjUgNjYuNSAwIDAwLS4zMS0xLjcxMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIzMCwgMTAwJSwgNTAlKSIgZD0iTTIwMC43NyAxMjUuMTdhNjYuNSA2Ni41IDAgMDAtLjI4LTEuNzE4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjMxLCAxMDAlLCA1MCUpIiBkPSJNMjAwLjkzMSAxMjYuMzJhNjYuNSA2Ni41IDAgMDAtLjI1LTEuNzIzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjMyLCAxMDAlLCA1MCUpIiBkPSJNMjAxLjA3MyAxMjcuNDcyYTY2LjUgNjYuNSAwIDAwLS4yMi0xLjcyNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIzMywgMTAwJSwgNTAlKSIgZD0iTTIwMS4xOTQgMTI4LjYyNmE2Ni41IDY2LjUgMCAwMC0uMTktMS43MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIzNCwgMTAwJSwgNTAlKSIgZD0iTTIwMS4yOTUgMTI5Ljc4MmE2Ni41IDY2LjUgMCAwMC0uMTYtMS43MzMiLz48cGF0aCBzdHJva2U9ImhzbCgyMzUsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuMzc2IDEzMC45NGE2Ni41IDY2LjUgMCAwMC0uMTMtMS43MzYiLz48cGF0aCBzdHJva2U9ImhzbCgyMzYsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuNDM3IDEzMi4xYTY2LjUgNjYuNSAwIDAwLS4wOTktMS43MzkiLz48cGF0aCBzdHJva2U9ImhzbCgyMzcsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuNDc3IDEzMy4yNmE2Ni41IDY2LjUgMCAwMC0uMDY4LTEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCgyMzgsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuNDk3IDEzNC40MmE2Ni41IDY2LjUgMCAwMC0uMDM4LTEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCgyMzksIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuNDk3IDEzNS41OGE2Ni41IDY2LjUgMCAwMC0uMDA3LTEuNzQiLz48L2c+PGNpcmNsZSBjeD0iMTM1IiBjeT0iMTM1IiByPSIxMzMiIGZpbGw9InVybCgjYSkiIGNsYXNzPSJJcm9XaGVlbFNhdHVyYXRpb24iLz48Y2lyY2xlIGN4PSIxMzUiIGN5PSIxMzUiIHI9IjEzMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjIiIGNsYXNzPSJJcm9XaGVlbEJvcmRlciIvPjwvc3ZnPg=='; - - dialog.querySelector('.satus-scrollbar__content').appendChild(close); - dialog.querySelector('.satus-scrollbar__content').appendChild(component_canvas); - - document.body.appendChild(dialog); - }); - - component.appendChild(component_value); - - return component; -}; -/*-------------------------------------------------------------- ->>> DIALOG ---------------------------------------------------------------*/ - -Satus.components.dialog = function(element) { - var component = document.createElement('div'), - component_scrim = document.createElement('div'), - component_surface = document.createElement('div'), - component_scrollbar = Satus.components.scrollbar(component_surface), - options = element.options || {}; - - component_scrim.className = 'satus-dialog__scrim'; - component_surface.className = 'satus-dialog__surface'; - - for (var key in element) { - Satus.render(element[key], component_scrollbar); - } - - function close() { - window.removeEventListener('keydown', keydown); - - component.classList.add('satus-dialog--closing'); - - if (typeof element.onclose === 'function') { - element.onclose(); - } - - setTimeout(function() { - component.remove(); - }, Satus.getAnimationDuration(component_surface)); - } - - function keydown(event) { - if (event.keyCode === 27) { - event.preventDefault(); - close(); - } - - if (event.keyCode === 9) { - var elements = component_surface.querySelectorAll('button, input'), - focused = false; - - event.preventDefault(); - - for (var i = 0, l = elements.length; i < l; i++) { - if (elements[i] === document.activeElement && elements[i + 1]) { - elements[i + 1].focus(); - - focused = true; - - i = l; - } - } - - if (focused === false) { - elements[0].focus(); - } - } - } - - component_scrim.addEventListener('click', close); - window.addEventListener('keydown', keydown); - - component.appendChild(component_scrim); - component.appendChild(component_surface); - - // OPTIONS - - if (options.left) { - component_surface.style.left = options.left + 'px'; - } - - if (options.top) { - component_surface.style.top = options.top + 'px'; - } - - if (options.width) { - component_surface.style.width = options.width + 'px'; - } - - if (options.height) { - component_surface.style.height = options.height + 'px'; - } - - // END OPTIONS - - return component; -}; -/*-------------------------------------------------------------- ->>> FOLDER ---------------------------------------------------------------*/ - -Satus.components.folder = function(object) { - var component = document.createElement('button'); - - component.object = object; - - component.addEventListener('click', function() { - var parent = document.querySelector(component.object.parent) || document.querySelector('.satus-main'); - - if (!component.object.parent || !parent.classList.contains('satus-main')) { - while (!parent.classList.contains('satus-main')) { - parent = parent.parentNode; - } - } - - parent.open(this.object, object.onopen); - }); - - if (Satus.isset(object.label)) { - var component_label = document.createElement('span'); - - component_label.className = 'satus-folder__label'; - component_label.innerText = Satus.locale.getMessage(object.label); - - component.appendChild(component_label); - } - - return component; -}; -/*-------------------------------------------------------------- ->>> HEADER ---------------------------------------------------------------*/ - -Satus.components.header = function(object) { - var component = document.createElement('header'); - - for (var key in object) { - Satus.render(object[key], component); - } - - return component; -}; -/*-------------------------------------------------------------- ->>> LIST ---------------------------------------------------------------*/ - -Satus.components.list = function(object) { - var ul = document.createElement('ul'); - - if (object.compact === true) { - ul.classList.add('satus-list'); - ul.classList.add('satus-list--compact'); - } - - for (var key in object) { - if (Satus.isset(object[key].type)) { - var li = document.createElement('li'); - - if (object.sortable === true) { - function mousedown(event) { - if (event.button === 0) { - var self = this, - dragging = false, - clone = false, - current_index = Array.from(self.parentNode.children).indexOf(self), - bounding = this.getBoundingClientRect(), - offset_x = event.clientX - bounding.left, - offset_y = event.clientY - bounding.top; - - function mousemove(event) { - if (dragging === false) { - clone = self.cloneNode(true); - - Satus.cloneNodeStyles(self, clone); - clone.style.position = 'fixed'; - clone.style.pointerEvents = 'none'; - clone.style.backgroundColor = '#fff'; - self.style.visibility = 'hidden'; - - document.body.appendChild(clone); - - dragging = true; - } - - var x = bounding.left, //event.clientX - offset_x - y = event.clientY - offset_y, - index = Math.floor(y / self.offsetHeight) - 1; - - clone.style.left = x + 'px'; - clone.style.top = y + 'px'; - - if (index !== current_index && self.parentNode.children[index]) { - var new_clone = self.cloneNode(true); - - if (index > 0) { - self.parentNode.insertBefore(new_clone, self.parentNode.children[index].nextSibling); - } else { - self.parentNode.insertBefore(new_clone, self.parentNode.children[index]); - } - - self.remove(); - - self = new_clone; - - self.addEventListener('mousedown', mousedown); - - if (typeof object.onchange === 'function') { - object.onchange(current_index, index); - } - - current_index = index; - } - } - - function mouseup(event) { - if (clone) { - clone.remove(); - self.style.visibility = ''; - } - - window.removeEventListener('mousemove', mousemove); - window.removeEventListener('mouseup', mouseup); - } - - window.addEventListener('mousemove', mousemove); - window.addEventListener('mouseup', mouseup); - } - } - - li.addEventListener('mousedown', mousedown); - } - - Satus.render(object[key], li); - - ul.appendChild(li); - } - } - - return ul; -}; -/*-------------------------------------------------------------- ->>> MAIN ---------------------------------------------------------------*/ - -Satus.components.main = function(object) { - var component = document.createElement('main'), - component_container = document.createElement('div'), - component_scrollbar = Satus.components.scrollbar(component_container, object.scrollbar); - - component.history = [object]; - - component.back = function() { - var container = this.querySelector('.satus-main__container'), - component_container = document.createElement('div'), - component_scrollbar = Satus.components.scrollbar(component_container); - - container.classList.add('satus-main__container--fade-out-right'); - component_container.className = 'satus-main__container satus-main__container--fade-in-left'; - - this.history.pop(); - - for (var key in this.history[this.history.length - 1]) { - Satus.render(this.history[this.history.length - 1][key], component_scrollbar); - } - - this.appendChild(component_container); - - if (this.historyListener) { - this.historyListener(component_container); - } - - if (this.history[this.history.length - 1].onopen) { - component_scrollbar.onopen = this.history[this.history.length - 1].onopen; - - component_scrollbar.onopen(); - } - - setTimeout(function() { - container.remove(); - }, Satus.getAnimationDuration(container)); - }; - - component.open = function(element, callback) { - var container = this.querySelector('.satus-main__container'), - component_container = document.createElement('div'), - component_scrollbar = Satus.components.scrollbar(component_container); - - container.classList.add('satus-main__container--fade-out-left'); - component_container.className = 'satus-main__container satus-main__container--fade-in-right'; - - this.history.push(element); - - for (var key in this.history[this.history.length - 1]) { - Satus.render(this.history[this.history.length - 1][key], component_scrollbar); - } - - this.appendChild(component_container); - - if (this.historyListener) { - this.historyListener(component_container); - } - - if (callback) { - component_scrollbar.onopen = callback; - - component_scrollbar.onopen(); - } - - setTimeout(function() { - container.remove(); - }, Satus.getAnimationDuration(container)); - }; - - component_container.className = 'satus-main__container'; - - if (object.on && object.on.change) { - component.historyListener = object.on.change; - } - - if (component.historyListener) { - component.historyListener(component_container); - } - - for (var key in object) { - Satus.render(object[key], component_scrollbar); - } - - component.appendChild(component_container); - - return component; +var Satus = {}; + + +/*-------------------------------------------------------------- +# EVENTS +--------------------------------------------------------------*/ + +Satus.events = {}; + +Satus.on = function(event, handler) { + if (!this.isset(this.events[event])) { + this.events[event] = []; + } + + this.events[event].push(handler); }; -/*----------------------------------------------------------------------------- ->>> SCROLL BAR ------------------------------------------------------------------------------*/ - -Satus.components.scrollbar = function(parent, enabled) { - if (enabled === false) { - return parent; - } - - var component = document.createElement('div'), - component_wrapper = document.createElement('div'), - component_content = document.createElement('div'), - component_thumb = document.createElement('div'); - - component.className = 'satus-scrollbar'; - component_wrapper.className = 'satus-scrollbar__wrapper'; - component_content.className = 'satus-scrollbar__content'; - component_thumb.className = 'satus-scrollbar__thumb'; - - - // RESIZE - - function resize() { - component_content.style.width = component.offsetWidth + 'px'; - component_wrapper.style.height = component.offsetHeight + 'px'; - - if (component_wrapper.scrollHeight > component_wrapper.offsetHeight) { - component_thumb.style.height = component_wrapper.offsetHeight / component_wrapper.scrollHeight * component_wrapper.offsetHeight + 'px'; - } - } - - window.addEventListener('resize', resize); - - new MutationObserver(resize).observe(component_content, { - subtree: true, - childList: true - }); - - - // HOVER - - component.timeout = false; - - function active() { - if (component.timeout) { - clearTimeout(component.timeout); - - component.timeout = false; - } - - component.classList.add('active'); - - component.timeout = setTimeout(function() { - component.classList.remove('active'); - - component.timeout = false; - }, 1000); - } - - component.addEventListener('mousemove', active); - - - // SCROLL - - component_wrapper.addEventListener('scroll', function(event) { - active(); - - component_thumb.style.top = Math.floor(component_wrapper.scrollTop * (component_wrapper.offsetHeight - component_thumb.offsetHeight) / (component_wrapper.scrollHeight - component_wrapper.offsetHeight)) + 'px'; - }); - - component_thumb.addEventListener('mousedown', function(event) { - var offsetY = event.layerY; - - if (event.button !== 0) { - return false; - } - - function mousemove(event) { - var offset = 100 / ((component.offsetHeight - component_thumb.offsetHeight) / (event.clientY - offsetY - component.getBoundingClientRect().top)), - scroll = component_wrapper.scrollHeight - component.offsetHeight; - - component_wrapper.scrollTop = scroll / 100 * offset; - - event.preventDefault(); - - return false; - } - - function mouseup() { - window.removeEventListener('mouseup', mouseup); - window.removeEventListener('mousemove', mousemove); - } - - window.addEventListener('mouseup', mouseup); - window.addEventListener('mousemove', mousemove); - }); - - component_wrapper.appendChild(component_content); - component.appendChild(component_wrapper); - component.appendChild(component_thumb); - - parent.appendChild(component); - - return component_content; + + +/*-------------------------------------------------------------- +# COMPONENTS +--------------------------------------------------------------*/ + +Satus.components = {}; + + +/*-------------------------------------------------------------- +# MODULES +--------------------------------------------------------------*/ + +Satus.modules = {}; + + +/*-------------------------------------------------------------- +# ISSET +--------------------------------------------------------------*/ + +Satus.isset = function(variable) { + if (typeof variable === 'undefined' || variable === null) { + return false; + } + + return true; }; -/*-------------------------------------------------------------- ->>> SECTION ---------------------------------------------------------------*/ - -Satus.components.section = function(element) { - var component = document.createElement('section'); - - for (var key in element) { - Satus.render(element[key], component); - } - - return component; + + +/*-------------------------------------------------------------- +# CAMELIZE +--------------------------------------------------------------*/ + +Satus.camelize = function(string) { + return string.replace(/-[a-z]/g, function(match) { + return match[1].toUpperCase(); + }); }; -/*-------------------------------------------------------------- ->>> SELECT ---------------------------------------------------------------*/ - -Satus.components.select = function(element) { - var component = document.createElement('button'), - component_label = document.createElement('span'), - component_value = document.createElement('span'), - label = Satus.locale.getMessage(element.label); - - component_label.className = 'satus-select__label'; - component_label.innerText = label; - - component_value.className = 'satus-select__value'; - - if (element.storage_key) { - var value = Satus.storage.get(element.storage_key); - - component.dataset.storageKey = element.storage_key; - - for (var i = 0, l = element.options.length; i < l; i++) { - if (value === element.options[i].value) { - value = element.options[i].label; - } - } - - component_value.innerText = Satus.locale.getMessage(value || element.options[0].label); - } - - component.onclick = function() { - var position = this.getBoundingClientRect(), - dialog = { - type: 'dialog', - class: 'satus-dialog--select-component' - }; - - for (var key in element.options) { - dialog[key] = element.options[key]; - - dialog[key].type = 'button'; - dialog[key].dataset = {}; - dialog[key].dataset.key = element.options[key].label; - dialog[key].dataset.value = element.options[key].value; - dialog[key].onclick = function() { - component_value.innerText = Satus.locale.getMessage(this.dataset.key); - - Satus.storage.set(component.dataset.storageKey, this.dataset.value); - - var parent = this.parentNode; - - while (!parent.classList.contains('satus-dialog')) { - parent = parent.parentNode; - } - - parent.querySelector('.satus-dialog__scrim').click(); - }; - } - - Satus.render(dialog); - }; - - component.appendChild(component_label); - component.appendChild(component_value); - - return component; + + +/*-------------------------------------------------------------- +# ANIMATION DURATION +--------------------------------------------------------------*/ + +Satus.getAnimationDuration = function(element) { + return Number(window.getComputedStyle(element).getPropertyValue('animation-duration').replace(/[^0-9.]/g, '')) * 1000; +}; +/*-------------------------------------------------------------- +>>> CHROMIUM STORAGE +---------------------------------------------------------------- +1.0 Get +2.0 Set +3.0 Import +4.0 Clear +--------------------------------------------------------------*/ + +Satus.storage = {}; + +/*-------------------------------------------------------------- +# GET +--------------------------------------------------------------*/ + +Satus.storage.get = function(name) { + var target = Satus.storage; + + 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; }; -/*------------------------------------------------------------------------------ ->>> SHORTCUT -------------------------------------------------------------------------------*/ - -Satus.components.shortcut = function(element) { - var self = this, - value = (Satus.storage.get(element.storage_key) ? JSON.parse(Satus.storage.get(element.storage_key)) : false) || element.value || {}, - component = document.createElement('div'), - component_label = document.createElement('span'), - component_value = document.createElement('span'), - mousewheel_timeout = false, - mousewheel_only = false; - - component_label.className = 'satus-shortcut__label'; - component_value.className = 'satus-shortcut__value'; - - function update(canvas) { - let text_value = [], - keys_value = []; - - if (value.altKey === true) { - text_value.push('Alt'); - keys_value.push('
Alt
'); - } - - if (value.ctrlKey === true) { - text_value.push('Ctrl'); - keys_value.push('
Ctrl
'); - } - - if (value.shiftKey === true) { - text_value.push('Shift'); - keys_value.push('
Shift
'); - } - - if (value.key === ' ') { - text_value.push('Space bar'); - keys_value.push('
Space bar
'); - - } else if (typeof value.key === 'string' && ['Shift', 'Control', 'Alt'].indexOf(value.key) === -1) { - if (value.key === 'ArrowUp') { - text_value.push('↑'); - keys_value.push('
'); - } else if (value.key === 'ArrowRight') { - text_value.push('→'); - keys_value.push('
'); - } else if (value.key === 'ArrowDown') { - text_value.push('↓'); - keys_value.push('
'); - } else if (value.key === 'ArrowLeft') { - text_value.push('←'); - keys_value.push('
'); - } else { - let key = value.key.toUpperCase(); - - text_value.push(key); - keys_value.push('
' + key + '
'); - } - } - - if (value.wheel) { - keys_value.push('
'); - } - - component_value.innerText = text_value.join('+'); - - if (canvas) { - if (keys_value.length > 0) { - canvas.innerHTML = keys_value.join('
'); - } else { - canvas.innerText = Satus.locale.getMessage('pressAnyKeyOrUseMouseWheel'); - } - } - } - - update(); - - component_value.dataset.value = component_value.innerText; - - component_label.innerText = Satus.locale.getMessage(element.label); - - component.addEventListener('click', function() { - let component_dialog = document.createElement('div'), - component_dialog_label = document.createElement('span'), - component_scrim = document.createElement('div'), - component_surface = document.createElement('div'), - component_canvas = document.createElement('div'), - component_section = document.createElement('section'), - component_button_reset = document.createElement('div'), - component_button_cancel = document.createElement('div'), - component_button_save = document.createElement('div'); - - component_dialog.className = 'satus-dialog satus-dialog_open'; - component_dialog_label.className = 'satus-shortcut-dialog-label'; - component_scrim.className = 'satus-dialog__scrim'; - component_surface.className = 'satus-dialog__surface satus-dialog__surface_shortcut'; - component_canvas.className = 'satus-shortcut__canvas'; - component_section.className = 'satus-section satus-section--align-end satus-section_shortcut'; - component_button_reset.className = 'satus-button satus-button_shortcut'; - component_button_cancel.className = 'satus-button satus-button_shortcut'; - component_button_save.className = 'satus-button satus-button_shortcut'; - - component_dialog_label.innerText = component_label.innerText; - component_button_reset.innerText = Satus.locale.getMessage('reset'); - component_button_cancel.innerText = Satus.locale.getMessage('cancel'); - component_button_save.innerText = Satus.locale.getMessage('save'); - - update(component_canvas); - - function keydown(event) { - event.preventDefault(); - event.stopPropagation(); - - mousewheel_only = false; - clearTimeout(mousewheel_timeout); - - value = { - key: event.key, - keyCode: event.keyCode, - shiftKey: event.shiftKey, - ctrlKey: event.ctrlKey, - altKey: event.altKey - }; - - update(component_canvas); - - return false; - } - - function mousewheel(event) { - event.stopPropagation(); - - if (mousewheel_only === true) { - delete value.shiftKey; - delete value.altKey; - delete value.ctrlKey; - delete value.keyCode; - delete value.key; - } - - clearTimeout(mousewheel_timeout); - - mousewheel_timeout = setTimeout(function() { - mousewheel_only = true; - }, 300); - - value.wheel = event.deltaY; - - update(component_canvas); - - return false; - } - - window.addEventListener('keydown', keydown); - window.addEventListener('mousewheel', mousewheel); - - function close(clear = true) { - window.removeEventListener('keydown', keydown); - window.removeEventListener('mousewheel', mousewheel); - - if (clear === true) { - component_value.innerText = component_value.dataset.value; - } - - component_dialog.classList.remove('satus-dialog_open'); - - setTimeout(function() { - component_dialog.remove(); - }, Number(document.defaultView.getComputedStyle(component_dialog, '').getPropertyValue('animation-duration').replace(/[^0-9.]/g, '') * 1000)); - } - - component_scrim.addEventListener('click', close); - component_button_reset.addEventListener('click', function() { - Satus.storage.set(element.storage_key, null); - close(); - value = (Satus.storage.get(element.storage_key) ? JSON.parse(Satus.storage.get(element.storage_key)) : false) || object.value || {}; - update(); - }); - component_button_cancel.addEventListener('click', close); - component_button_save.addEventListener('click', function() { - Satus.storage.set(element.storage_key, JSON.stringify(value)); - close(false); - }); - - component_section.appendChild(component_button_reset); - component_section.appendChild(component_button_cancel); - component_section.appendChild(component_button_save); - - component_surface.appendChild(component_dialog_label); - component_surface.appendChild(component_canvas); - component_surface.appendChild(component_section); - - component_dialog.appendChild(component_scrim); - component_dialog.appendChild(component_surface); - - document.body.appendChild(component_dialog); - }); - - component.appendChild(component_label); - component.appendChild(component_value); - - return component; + + +/*-------------------------------------------------------------- +# SET +--------------------------------------------------------------*/ + +Satus.storage.set = function(name, value) { + var items = {}, + target = Satus.storage; + + 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 Satus.storage) { + if (typeof items[key] !== 'function') { + items[key] = Satus.storage[key]; + } + } + + chrome.storage.local.set(items); }; -/*-------------------------------------------------------------- ->>> SLIDER ---------------------------------------------------------------*/ - -Satus.components.slider = function(element) { - var component = document.createElement('div'); - - // LABEL - if (Satus.isset(element.label)) { - var component_label = document.createElement('span'); - - component_label.className = 'satus-slider__label'; - component_label.innerText = Satus.locale.getMessage(element.label); - - component.appendChild(component_label); - } - - - // RANGE - var component_range = document.createElement('input'); - - component_range.type = 'range'; - component_range.className = 'satus-slider__range'; - component_range.min = element.min || 0; - component_range.max = element.max || 10; - component_range.step = element.step || 1; - - component_range.oninput = function() { - var track = this.parentNode.querySelector('.satus-slider__track'), - thumb = this.parentNode.querySelector('.satus-slider__thumb'), - min = Number(this.min) || 0, - max = Number(this.max) || 1, - step = Number(this.step) || 1, - value = Number(this.value) || 0, - offset = (value - min) / (max - min) * 100; - - track.style.width = 'calc(' + offset + '% - ' + Math.floor(offset * 12 / 100) + 'px)'; - - Satus.storage.set(this.dataset.storageKey, Number(this.value)); - - component_thumb.dataset.value = this.value; - - if (component.onchange) { - component.onchange(Number(this.value)); - } - }; - - component.change = function(value) { - component_range.value = value; - - component_thumb.dataset.value = value; - - component_range.oninput(); - }; - - component.addEventListener('mousedown', function() { - function mousemove() { - component.classList.add('satus-slider--dragging'); - } - - function mouseup() { - component.classList.remove('satus-slider--dragging'); - - window.removeEventListener('mousemove', mousemove); - window.removeEventListener('mouseup', mouseup); - } - - window.addEventListener('mousemove', mousemove); - window.addEventListener('mouseup', mouseup); - }); - - if (element.onchange) { - component.onchange = element.onchange; - } - - component.appendChild(component_range); - - - // CONTAINER - var component_container = document.createElement('div'); - - component_container.className = 'satus-slider__container'; - - component.appendChild(component_container); - - - // TRACK - var component_track_container = document.createElement('div'), - component_track = document.createElement('div'); - - component_track_container.className = 'satus-slider__track-container'; - component_track.className = 'satus-slider__track'; - - component_track_container.appendChild(component_track); - component_container.appendChild(component_track_container); - - - // FOCUS RING - var component_ring = document.createElement('div'); - - component_ring.className = 'satus-slider__ring'; - - component_track.appendChild(component_ring); - - - // THUMB - var component_thumb = document.createElement('div'); - - component_thumb.className = 'satus-slider__thumb'; - - component_track.appendChild(component_thumb); - - if (element.storage_key) { - var value = Satus.storage.get(element.storage_key); - - if (!Satus.isset(value)) { - value = element.value; - } - - component_range.dataset.storageKey = element.storage_key; - - if (value) { - component_range.value = value; - - if (!Satus.isset(value)) { - value = element.value; - } - - var offset = (Number(component_range.value) - Number(component_range.min)) / (Number(component_range.max) - Number(component_range.min)) * 100; - - component_track.style.width = 'calc(' + offset + '% - ' + Math.floor(offset * 12 / 100) + 'px)'; - component_thumb.dataset.value = value; - } else { - component_range.value = 0; - component_thumb.dataset.value = 0; - } - } - - - return component; -}; - -/*-------------------------------------------------------------- ->>> SWITCH ---------------------------------------------------------------*/ - -Satus.components.switch = function(element) { - var component = document.createElement('div'), - value; - - // LABEL - if (Satus.isset(element.label)) { - var component_label = document.createElement('span'); - - component_label.className = 'satus-switch__label'; - component_label.innerText = Satus.locale.getMessage(element.label); - - component.appendChild(component_label); - } - - - // INPUT - var component_input = document.createElement('input'); - - component_input.type = 'checkbox'; - component_input.className = 'satus-switch__input'; - - if (element.storage_key) { - value = Satus.storage.get(element.storage_key); - - component_input.dataset.storageKey = element.storage_key; - } - - if (!Satus.isset(value)) { - value = element.value; - } - - if (value) { - component_input.checked = value; - } - - component_input.addEventListener('change', function() { - //if (this.dataset.storageKey) { - Satus.storage.set(this.dataset.storageKey, this.checked); - //} - - if (typeof component.onchange === 'function') { - component.onchange(); - } - }); - - component.appendChild(component_input); - - - // TRACK - var component_track = document.createElement('div'); - - component_track.className = 'satus-switch__track'; - - component.appendChild(component_track); - - - // MOUSE MOVE - component_track.addEventListener('mousedown', function(event) { - var prevent = false, - difference = 0; - - function click(event) { - event.preventDefault(); - event.stopPropagation(); - - component.removeEventListener('click', click); - - return false; - } - - function mousemove(event) { - var checkbox = component.querySelector('input'), - movement = event.movementX; - - if (movement * difference < 0) { - difference = 0; - } else { - difference += movement; - - if (prevent === false) { - prevent = true; - component.addEventListener('click', click); - } - } - - if (difference < -5) { - checkbox.checked = false; - } else if (difference > 5) { - checkbox.checked = true; - } - } - - function mouseup(event) { - window.removeEventListener('mousemove', mousemove); - window.removeEventListener('mouseup', mouseup); - } - - window.addEventListener('mousemove', mousemove); - window.addEventListener('mouseup', mouseup); - }); - - - // TOUCH MOVE - component_track.addEventListener('touchstart', function(event) { - var previous_x = 0, - difference = 0; - - function mousemove(event) { - var checkbox = component.querySelector('input'), - movement = event.touches[0].clientX - previous_x; - - previous_x = event.touches[0].clientX; - - if (movement * difference < 0) { - difference = 0; - } else { - difference += movement; - } - - if (difference < -5) { - checkbox.checked = false; - } else if (difference > 5) { - checkbox.checked = true; - } - } - - function mouseup(event) { - window.removeEventListener('touchmove', mousemove); - window.removeEventListener('touchend', mouseup); - } - - window.addEventListener('touchmove', mousemove); - window.addEventListener('touchend', mouseup); - }); - - - return component; + + +/*-------------------------------------------------------------- +# IMPORT +--------------------------------------------------------------*/ + +Satus.storage.import = function(callback) { + chrome.storage.local.get(function(items) { + for (var key in items) { + Satus.storage[key] = items[key]; + } + + if (callback) { + callback(); + } + }); }; -Satus.components.table = function(item) { - var component = document.createElement('div'), - component_head = document.createElement('div'), - component_body = document.createElement('div'), - component_scrollbar = Satus.components.scrollbar(component_body, item.scrollbar), - table = document.createElement('table'), - thead = document.createElement('thead'), - thead_tr = document.createElement('tr'), - tbody = document.createElement('tbody'); - - component_head.className = 'satus-table__head'; - component_body.className = 'satus-table__body'; - - function update(data) { - var pages = Math.ceil(component.data.length / component.paging), - start = Math.max((component.pagingIndex - 1) * component.paging, 0), - end = component.pagingIndex * component.paging; - - if (end > data.length) { - end = data.length; - } else if (end === 0) { - end = component.paging; - } - - tbody.innerHTML = ''; - - if (data) { - for (var i = start, l = end; i < l; i++) { - if (data[i]) { - var tr = document.createElement('tr'); - - for (var j = 0, k = data[i].length; j < k; j++) { - var td = document.createElement('td'), - span = document.createElement('span'); - - span.innerText = data[i][j]; - - td.appendChild(span); - tr.appendChild(td); - } - - tbody.appendChild(tr); - } - } - } - - component.pagingUpdate(); - } - - function sortArray(array, index, mode) { - if (mode === 'asc') { - if (typeof array[0][index] === 'number') { - sorted = array.sort(function(a, b) { - return a[index] - b[index]; - }); - } else { - sorted = array.sort(function(a, b) { - return a[index].localeCompare(b[index]); - }); - } - } else { - if (typeof array[0][index] === 'number') { - sorted = array.sort(function(a, b) { - return b[index] - a[index]; - }); - } else { - sorted = array.sort(function(a, b) { - return b[index].localeCompare(a[index]); - }); - } - } - - return array; - } - - function sort() { - var mode = this.dataset.sorting, - index = Array.prototype.indexOf.call(this.parentElement.children, this), - sorted; - - if (mode === 'none') { - mode = 'asc'; - } else if (mode === 'asc') { - mode = 'desc'; - } else if (mode === 'desc') { - mode = 'asc'; - } - - if (this.parentNode.querySelector('div[data-sorting=asc], div[data-sorting=desc]')) { - this.parentNode.querySelector('div[data-sorting=asc], div[data-sorting=desc]').dataset.sorting = 'none'; - } - - this.dataset.sorting = mode; - - sorted = sortArray(component.data, index, mode); - - update(sorted); - } - - function resize() { - for (var i = 0, l = component_head.children.length; i < l; i++) { - component_head.children[i].style.width = thead.querySelectorAll('th')[i].offsetWidth + 'px'; - } - } - - for (var i = 0, l = item.columns.length; i < l; i++) { - var column = document.createElement('div'), - th = document.createElement('th'); - - column.dataset.sorting = 'none'; - column.addEventListener('click', sort); - column.innerHTML = '' + item.columns[i].title + ''; - th.innerText = item.columns[i].title; - - component_head.appendChild(column); - thead_tr.appendChild(th); - } - - thead.appendChild(thead_tr); - table.appendChild(thead); - table.appendChild(tbody); - component_scrollbar.appendChild(table); - - component.appendChild(component_head); - component.appendChild(component_body); - - component.data = item.data; - component.paging = item.paging; - component.pagingIndex = 0; - - component.update = function(data, index, mode) { - if (Satus.isset(data)) { - this.data = data; - } - - if (Satus.isset(index) && Satus.isset(mode)) { - this.querySelectorAll('.satus-table__head > div')[index].dataset.sorting = mode; - - this.data = sortArray(this.data, index, mode); - } - - update(this.data); - }; - - - // PAGING - - function pagingUpdate() { - if (typeof this.paging === 'number') { - var pages = Math.ceil(this.data.length / this.paging); - - this.querySelector('.satus-table__paging').innerHTML = ''; - - for (var i = 1; i <= pages; i++) { - var button = document.createElement('button'); - - if (i === (this.pagingIndex || 1)) { - button.className = 'active'; - } - - button.innerText = i; - button.parentComponent = this; - button.addEventListener('click', function() { - if (this.parentNode.querySelector('button.active')) { - this.parentNode.querySelector('button.active').classList.remove('active'); - } - - this.classList.add('active'); - - this.parentComponent.pagingIndex = Number(this.innerText); - this.parentComponent.update(this.parentComponent.data); - }); - - this.querySelector('.satus-table__paging').appendChild(button); - } - } - } - - component.pagingUpdate = pagingUpdate; - - component_paging = document.createElement('div'); - - component_paging.className = 'satus-table__paging'; - - component_scrollbar.appendChild(component_paging); - - // END PAGING - - - var sorting; - - for (var i = 0, l = item.columns.length; i < l; i++) { - if (item.columns[i].hasOwnProperty('sorting')) { - component_head.querySelectorAll('div')[i].dataset.sorting = item.columns[i].sorting; - - update(sortArray(item.data, i, item.columns[i].sorting)); - - i = l; - } - } - - setTimeout(resize); - - return component; + + +/*-------------------------------------------------------------- +# CLEAR +--------------------------------------------------------------*/ + +Satus.storage.clear = function() { + chrome.storage.local.clear(); + + for (var key in Satus.storage) { + if (typeof Satus.storage[key] !== 'function') { + delete Satus.storage[key]; + } + } +}; +/*-------------------------------------------------------------- +# LOCALE +--------------------------------------------------------------*/ + +Satus.locale = { + messages: {} }; -/*-------------------------------------------------------------- ->>> TEXT ---------------------------------------------------------------*/ - -Satus.components.text = function(element) { - var component = document.createElement('span'); - - if (Satus.isset(element.label)) { - var component_label = document.createElement('span'); - - component_label.className = 'satus-text__label'; - component_label.innerText = Satus.locale.getMessage(element.label); - - component.appendChild(component_label); - } - - if (Satus.isset(element.value)) { - var component_value = document.createElement('span'); - - component_value.className = 'satus-text__value'; - component_value.innerText = Satus.locale.getMessage(element.value); - - component.appendChild(component_value); - } - - return component; + + +/*-------------------------------------------------------------- +# GET MESSAGE +--------------------------------------------------------------*/ + +Satus.locale.getMessage = function(string) { + return this.messages[string] || string; }; -/*-------------------------------------------------------------- ->>> TEXT FIELD ---------------------------------------------------------------*/ - -Satus.components.textField = function(element) { - var component = element.rows > 1 ? document.createElement('textarea') : document.createElement('input'); - - component.type = 'text'; - - return component; + +/*-------------------------------------------------------------- +# IMPORT LOCALE +--------------------------------------------------------------*/ + +Satus.locale.import = function(src, callback) { + var xhr = new XMLHttpRequest(); + + xhr.onload = function() { + try { + var object = JSON.parse(this.responseText); + + for (var key in object) { + Satus.locale.messages[key] = object[key].message; + } + + callback(); + } catch (err) { + function listener(request) { + if (request !== null && typeof request === 'object') { + if (request.name === 'translation_response') { + var object = JSON.parse(request.value); + + chrome.runtime.onMessage.removeListener(listener); + + for (var key in object) { + Satus.locale.messages[key] = object[key].message; + } + + callback(); + } + } + } + + chrome.runtime.onMessage.addListener(listener); + + chrome.runtime.sendMessage({ + name: 'translation_request', + path: src + }); + } + }; + + xhr.open('GET', src, true); + xhr.send(); +}; +/*-------------------------------------------------------------- +>>> RENDER +--------------------------------------------------------------*/ + +Satus.render = function(element, container, callback) { + function convert(object) { + if (object && object.type) { + var type = Satus.camelize(object.type), + component = Satus.components[type](object), + excluded_properties = ['type', 'label', 'class', 'title', 'storage']; + + function applyProperties(object, target) { + for (var key in object) { + if (Satus.isset(object[key]) && typeof object[key] === 'object' && !object[key].type) { + if (typeof target[key] !== 'object') { + target[key] = {}; + } + + applyProperties(object[key], target[key]); + } else if (excluded_properties.indexOf(key) === -1) { + target[key] = object[key]; + } + } + } + + applyProperties(object, component); + + component.classList.add('satus-' + object.type); + + if (object.class) { + var class_list = object.class.split(' '); + + for (var i = 0, l = class_list.length; i < l; i++) { + component.classList.add(class_list[i]); + } + } + + if (object.before) { + var component_before = document.createElement('span'); + + component_before.innerHTML = object.before; + + for (var i = component_before.children.length - 1; i > -1; i--) { + component.insertBefore(component_before.children[i], component.firstChild); + } + } + + if (object.after) { + var component_after = document.createElement('span'); + + component_after.innerHTML = object.after; + + for (var i = component_after.children.length - 1; i > -1; i--) { + component.appendChild(component_after.children[i]); + } + } + + (container || document.body).appendChild(component); + + if (typeof component.onClickRender === 'object') { + component.addEventListener('click', function() { + Satus.render(component.onClickRender); + }); + } + + if (Satus.isset(Satus.events.render)) { + for (var i = 0, l = Satus.events.render.length; i < l; i++) { + Satus.events.render[i](component, object); + } + } + + if (typeof component.onrender === 'function') { + component.onrender(object); + } + + if (callback) { + callback(); + } + } + } + + if (element.type) { + convert(element); + } else { + for (var key in element) { + convert(element[key]); + } + } +}; +/*-------------------------------------------------------------- +# CLONE NODE STYLES +--------------------------------------------------------------*/ + +Satus.cloneNodeStyles = function(origin, target) { + target.style.cssText = window.getComputedStyle(origin, '').cssText; + + for (var i = 0, l = origin.children.length; i < l; i++) { + Satus.cloneNodeStyles(origin.children[i], target.children[i]); + } +}; +/*----------------------------------------------------------------------------- +>>> «SEARCH» MODULE +-----------------------------------------------------------------------------*/ + +Satus.search = function(query, object, callback) { + var threads = 0, + results = {}; + + function parse(items) { + threads++; + + for (var key in items) { + var item = items[key]; + + + if (['switch', 'select', 'slider'].indexOf(item.type) !== -1 && key.indexOf(query) !== -1) { + results[key] = item; + } + + if (typeof item === 'object') { + parse(item); + } + } + + threads--; + + if (threads === 0) { + callback(results); + } + } + + parse(object); +}; +/*-------------------------------------------------------------- +>>> STORAGE KEYS +--------------------------------------------------------------*/ + +Satus.modules.updateStorageKeys = function(object, callback) { + var threads = 0; + + function parse(items) { + threads++; + + for (var key in items) { + var item = items[key]; + + + if (item.type) { + item.storage_key = key; + } + + if (typeof item === 'object') { + parse(item); + } + } + + threads--; + + if (threads === 0) { + callback(); + } + } + + parse(object); +}; +/*----------------------------------------------------------------------------- +>>> «USER» MODULE +------------------------------------------------------------------------------- +1.0 Variables +2.0 Software + 2.1 OS + 2.2.1 Name + 2.2.2 Type + 2.2 Browser + 2.2.1 Name + 2.2.2 Version + 2.2.3 Platform + 2.2.4 Languages + 2.2.5 Cookies + 2.2.6 Flash + 2.2.8 Video formats + 2.2.9 Audio formats + 2.2.10 WebGL +3.0 Hardware + 3.1 Screen + 3.2 RAM + 3.3 GPU + 3.4 Cores + 3.5 Touch + 3.6 Connection +4.0 Clearing +-----------------------------------------------------------------------------*/ + +Satus.modules.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; +}; +Satus.on('render', function(component, data) { + if (data.perspective === true) { + component.style.willChange = 'transform'; + component.style.transformStyle = 'preserve-3d'; + component.style.transition = '.4s'; + + component.addEventListener('mousemove', function(event) { + var bounding = component.getBoundingClientRect(), + dx = event.clientX - bounding.left - bounding.width / 2, + dy = event.clientY - bounding.top - bounding.height / 2; + + this.style.transform = 'perspective(440px) rotateX(' + dy * -1 + 'deg) rotateY(' + dx + 'deg) translateZ(0)'; + }); + + component.addEventListener('mouseout', function(event) { + this.style.transform = 'perspective(440px) rotateX(0deg) rotateY(0deg) translateZ(0)'; + }); + } +}); +/*-------------------------------------------------------------- +>>> BUTTON +--------------------------------------------------------------*/ + +Satus.components.button = function(element) { + var component = document.createElement('button'); + + if (Satus.isset(element.icon)) { + var component_icon = document.createElement('span'); + + component_icon.className = 'satus-button__icon'; + component_icon.innerHTML = element.icon; + + component.appendChild(component_icon); + } + + if (Satus.isset(element.label)) { + var component_label = document.createElement('span'); + + component_label.className = 'satus-button__label'; + component_label.innerText = Satus.locale.getMessage(element.label); + + component.appendChild(component_label); + } + + return component; +}; +/*-------------------------------------------------------------- +>>> COLOR PICKER +--------------------------------------------------------------*/ + +Satus.components.colorPicker = function(element) { + var component = document.createElement('div'), + component_value = document.createElement('div'); + + element.class = 'satus-button'; + component_value.className = 'satus-color-picker__value'; + component_value.style.backgroundColor = Satus.storage.get(element.storage_key) || element.value || ''; + + if (Satus.isset(element.label)) { + var component_label = document.createElement('span'); + + component_label.className = 'satus-button__label'; + component_label.innerText = Satus.locale.getMessage(element.label); + + component.appendChild(component_label); + } + + component.addEventListener('click', function() { + var component = document.createElement('div'), + component_canvas = document.createElement('canvas'), + close = document.createElement('button'), + ctx = component_canvas.getContext('2d'), + image = new Image(), + dialog = Satus.components.dialog({}); + + close.className = 'satus-button'; + close.innerHTML = ''; + close.onclick = function() { + dialog.querySelector('.satus-dialog__scrim').click(); + }; + + dialog.className = 'satus-dialog satus-dialog--color-picker'; + + component_canvas.width = 200; + component_canvas.height = 200; + + function select(event) { + var coordinates = component_canvas.getBoundingClientRect(), + x = event.clientX - coordinates.left, + y = event.clientY - coordinates.top, + color = ctx.getImageData(x, y, 1, 1).data; + + component_value.style.backgroundColor = 'rgb(' + color[0] + ',' + color[1] + ',' + color[2] + ')'; + + Satus.storage.set(element.storage_key, component_value.style.backgroundColor); + } + + function mouseup(event) { + component_canvas.removeEventListener('mousemove', select); + window.removeEventListener('mouseup', mouseup); + } + + component_canvas.addEventListener('mousedown', function() { + select(event); + this.addEventListener('mousemove', select); + window.addEventListener('mouseup', mouseup); + }); + + image.onload = function() { + ctx.drawImage(image, 0, 0); + + image.remove(); + }; + + image.src = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNzAgMjcwIj48ZGVmcz48cmFkaWFsR3JhZGllbnQgaWQ9ImEiPjxzdG9wIG9mZnNldD0iMCUiIHN0b3AtY29sb3I9IiNmZmYiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmZmYiIHN0b3Atb3BhY2l0eT0iMCIvPjwvcmFkaWFsR3JhZGllbnQ+PC9kZWZzPjxnIGZpbGw9Im5vbmUiIHN0cm9rZS13aWR0aD0iMTMzIiBjbGFzcz0iSXJvV2hlZWxIdWUiPjxwYXRoIHN0cm9rZT0iaHNsKDI0MCwgMTAwJSwgNTAlKSIgZD0iTTIwMS40NzcgMTM2Ljc0YTY2LjUgNjYuNSAwIDAwLjAyMy0xLjc0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjQxLCAxMDAlLCA1MCUpIiBkPSJNMjAxLjQzNyAxMzcuOWE2Ni41IDY2LjUgMCAwMC4wNTMtMS43NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI0MiwgMTAwJSwgNTAlKSIgZD0iTTIwMS4zNzYgMTM5LjA2YTY2LjUgNjYuNSAwIDAwLjA4My0xLjc0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjQzLCAxMDAlLCA1MCUpIiBkPSJNMjAxLjI5NSAxNDAuMjE4YTY2LjUgNjYuNSAwIDAwLjExNC0xLjczOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI0NCwgMTAwJSwgNTAlKSIgZD0iTTIwMS4xOTQgMTQxLjM3NGE2Ni41IDY2LjUgMCAwMC4xNDQtMS43MzUiLz48cGF0aCBzdHJva2U9ImhzbCgyNDUsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuMDczIDE0Mi41MjhhNjYuNSA2Ni41IDAgMDAuMTc0LTEuNzMyIi8+PHBhdGggc3Ryb2tlPSJoc2woMjQ2LCAxMDAlLCA1MCUpIiBkPSJNMjAwLjkzMSAxNDMuNjhhNjYuNSA2Ni41IDAgMDAuMjA1LTEuNzI5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjQ3LCAxMDAlLCA1MCUpIiBkPSJNMjAwLjc3IDE0NC44M2E2Ni41IDY2LjUgMCAwMC4yMzQtMS43MjYiLz48cGF0aCBzdHJva2U9ImhzbCgyNDgsIDEwMCUsIDUwJSkiIGQ9Ik0yMDAuNTg4IDE0NS45NzZhNjYuNSA2Ni41IDAgMDAuMjY1LTEuNzIxIi8+PHBhdGggc3Ryb2tlPSJoc2woMjQ5LCAxMDAlLCA1MCUpIiBkPSJNMjAwLjM4NiAxNDcuMTE5YTY2LjUgNjYuNSAwIDAwLjI5NS0xLjcxNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI1MCwgMTAwJSwgNTAlKSIgZD0iTTIwMC4xNjUgMTQ4LjI1OGE2Ni41IDY2LjUgMCAwMC4zMjUtMS43MSIvPjxwYXRoIHN0cm9rZT0iaHNsKDI1MSwgMTAwJSwgNTAlKSIgZD0iTTE5OS45MjQgMTQ5LjM5M2E2Ni41IDY2LjUgMCAwMC4zNTQtMS43MDQiLz48cGF0aCBzdHJva2U9ImhzbCgyNTIsIDEwMCUsIDUwJSkiIGQ9Ik0xOTkuNjYzIDE1MC41MjRhNjYuNSA2Ni41IDAgMDAuMzg0LTEuNjk4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjUzLCAxMDAlLCA1MCUpIiBkPSJNMTk5LjM4MiAxNTEuNjVhNjYuNSA2Ni41IDAgMDAuNDE0LTEuNjkiLz48cGF0aCBzdHJva2U9ImhzbCgyNTQsIDEwMCUsIDUwJSkiIGQ9Ik0xOTkuMDgxIDE1Mi43NzFhNjYuNSA2Ni41IDAgMDAuNDQ0LTEuNjgzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjU1LCAxMDAlLCA1MCUpIiBkPSJNMTk4Ljc2MiAxNTMuODg3YTY2LjUgNjYuNSAwIDAwLjQ3Mi0xLjY3NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI1NiwgMTAwJSwgNTAlKSIgZD0iTTE5OC40MjIgMTU0Ljk5N2E2Ni41IDY2LjUgMCAwMC41MDItMS42NjciLz48cGF0aCBzdHJva2U9ImhzbCgyNTcsIDEwMCUsIDUwJSkiIGQ9Ik0xOTguMDY0IDE1Ni4xYTY2LjUgNjYuNSAwIDAwLjUzLTEuNjU3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjU4LCAxMDAlLCA1MCUpIiBkPSJNMTk3LjY4NiAxNTcuMTk4YTY2LjUgNjYuNSAwIDAwLjU2LTEuNjQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjU5LCAxMDAlLCA1MCUpIiBkPSJNMTk3LjI4OSAxNTguMjg5YTY2LjUgNjYuNSAwIDAwLjU4OC0xLjYzOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDI2MCwgMTAwJSwgNTAlKSIgZD0iTTE5Ni44NzMgMTU5LjM3MmE2Ni41IDY2LjUgMCAwMC42MTctMS42MjgiLz48cGF0aCBzdHJva2U9ImhzbCgyNjEsIDEwMCUsIDUwJSkiIGQ9Ik0xOTYuNDM4IDE2MC40NDhhNjYuNSA2Ni41IDAgMDAuNjQ1LTEuNjE3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjYyLCAxMDAlLCA1MCUpIiBkPSJNMTk1Ljk4NCAxNjEuNTE3YTY2LjUgNjYuNSAwIDAwLjY3NC0xLjYwNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI2MywgMTAwJSwgNTAlKSIgZD0iTTE5NS41MTIgMTYyLjU3N2E2Ni41IDY2LjUgMCAwMC43MDItMS41OTMiLz48cGF0aCBzdHJva2U9ImhzbCgyNjQsIDEwMCUsIDUwJSkiIGQ9Ik0xOTUuMDIyIDE2My42MjlhNjYuNSA2Ni41IDAgMDAuNzI5LTEuNTgxIi8+PHBhdGggc3Ryb2tlPSJoc2woMjY1LCAxMDAlLCA1MCUpIiBkPSJNMTk0LjUxMyAxNjQuNjcyYTY2LjUgNjYuNSAwIDAwLjc1Ni0xLjU2OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI2NiwgMTAwJSwgNTAlKSIgZD0iTTE5My45ODYgMTY1LjcwNmE2Ni41IDY2LjUgMCAwMC43ODQtMS41NTQiLz48cGF0aCBzdHJva2U9ImhzbCgyNjcsIDEwMCUsIDUwJSkiIGQ9Ik0xOTMuNDQxIDE2Ni43MzFhNjYuNSA2Ni41IDAgMDAuODEtMS41NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI2OCwgMTAwJSwgNTAlKSIgZD0iTTE5Mi44NzkgMTY3Ljc0NmE2Ni41IDY2LjUgMCAwMC44MzctMS41MjYiLz48cGF0aCBzdHJva2U9ImhzbCgyNjksIDEwMCUsIDUwJSkiIGQ9Ik0xOTIuMjk4IDE2OC43NTFhNjYuNSA2Ni41IDAgMDAuODY0LTEuNTExIi8+PHBhdGggc3Ryb2tlPSJoc2woMjcwLCAxMDAlLCA1MCUpIiBkPSJNMTkxLjcgMTY5Ljc0NmE2Ni41IDY2LjUgMCAwMC44OS0xLjQ5NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3MSwgMTAwJSwgNTAlKSIgZD0iTTE5MS4wODYgMTcwLjczYTY2LjUgNjYuNSAwIDAwLjkxNi0xLjQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjcyLCAxMDAlLCA1MCUpIiBkPSJNMTkwLjQ1MyAxNzEuNzA0YTY2LjUgNjYuNSAwIDAwLjk0Mi0xLjQ2NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3MywgMTAwJSwgNTAlKSIgZD0iTTE4OS44MDQgMTcyLjY2NmE2Ni41IDY2LjUgMCAwMC45NjgtMS40NDgiLz48cGF0aCBzdHJva2U9ImhzbCgyNzQsIDEwMCUsIDUwJSkiIGQ9Ik0xODkuMTM5IDE3My42MTdhNjYuNSA2Ni41IDAgMDAuOTkyLTEuNDMiLz48cGF0aCBzdHJva2U9ImhzbCgyNzUsIDEwMCUsIDUwJSkiIGQ9Ik0xODguNDU2IDE3NC41NTZhNjYuNSA2Ni41IDAgMDAxLjAxOC0xLjQxMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3NiwgMTAwJSwgNTAlKSIgZD0iTTE4Ny43NTggMTc1LjQ4M2E2Ni41IDY2LjUgMCAwMDEuMDQyLTEuMzk1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjc3LCAxMDAlLCA1MCUpIiBkPSJNMTg3LjA0MyAxNzYuMzk3YTY2LjUgNjYuNSAwIDAwMS4wNjYtMS4zNzYiLz48cGF0aCBzdHJva2U9ImhzbCgyNzgsIDEwMCUsIDUwJSkiIGQ9Ik0xODYuMzEzIDE3Ny4zYTY2LjUgNjYuNSAwIDAwMS4wOS0xLjM1OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3OSwgMTAwJSwgNTAlKSIgZD0iTTE4NS41NjcgMTc4LjE4OGE2Ni41IDY2LjUgMCAwMDEuMTEzLTEuMzM4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjgwLCAxMDAlLCA1MCUpIiBkPSJNMTg0LjgwNiAxNzkuMDY0YTY2LjUgNjYuNSAwIDAwMS4xMzYtMS4zMTkiLz48cGF0aCBzdHJva2U9ImhzbCgyODEsIDEwMCUsIDUwJSkiIGQ9Ik0xODQuMDI5IDE3OS45MjdhNjYuNSA2Ni41IDAgMDAxLjE2LTEuMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDI4MiwgMTAwJSwgNTAlKSIgZD0iTTE4My4yMzcgMTgwLjc3NmE2Ni41IDY2LjUgMCAwMDEuMTgyLTEuMjc5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjgzLCAxMDAlLCA1MCUpIiBkPSJNMTgyLjQzMSAxODEuNjFhNjYuNSA2Ni41IDAgMDAxLjIwNC0xLjI1NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDI4NCwgMTAwJSwgNTAlKSIgZD0iTTE4MS42MSAxODIuNDMxYTY2LjUgNjYuNSAwIDAwMS4yMjYtMS4yMzYiLz48cGF0aCBzdHJva2U9ImhzbCgyODUsIDEwMCUsIDUwJSkiIGQ9Ik0xODAuNzc2IDE4My4yMzdhNjYuNSA2Ni41IDAgMDAxLjI0Ny0xLjIxNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI4NiwgMTAwJSwgNTAlKSIgZD0iTTE3OS45MjcgMTg0LjAyOWE2Ni41IDY2LjUgMCAwMDEuMjY4LTEuMTkzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjg3LCAxMDAlLCA1MCUpIiBkPSJNMTc5LjA2NCAxODQuODA2YTY2LjUgNjYuNSAwIDAwMS4yODktMS4xNzEiLz48cGF0aCBzdHJva2U9ImhzbCgyODgsIDEwMCUsIDUwJSkiIGQ9Ik0xNzguMTg4IDE4NS41NjdhNjYuNSA2Ni41IDAgMDAxLjMxLTEuMTQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjg5LCAxMDAlLCA1MCUpIiBkPSJNMTc3LjMgMTg2LjMxM2E2Ni41IDY2LjUgMCAwMDEuMzI4LTEuMTI1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjkwLCAxMDAlLCA1MCUpIiBkPSJNMTc2LjM5NyAxODcuMDQzYTY2LjUgNjYuNSAwIDAwMS4zNDgtMS4xMDEiLz48cGF0aCBzdHJva2U9ImhzbCgyOTEsIDEwMCUsIDUwJSkiIGQ9Ik0xNzUuNDgzIDE4Ny43NThhNjYuNSA2Ni41IDAgMDAxLjM2Ny0xLjA3OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDI5MiwgMTAwJSwgNTAlKSIgZD0iTTE3NC41NTYgMTg4LjQ1NmE2Ni41IDY2LjUgMCAwMDEuMzg1LTEuMDUzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjkzLCAxMDAlLCA1MCUpIiBkPSJNMTczLjYxNyAxODkuMTM5YTY2LjUgNjYuNSAwIDAwMS40MDQtMS4wMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDI5NCwgMTAwJSwgNTAlKSIgZD0iTTE3Mi42NjYgMTg5LjgwNGE2Ni41IDY2LjUgMCAwMDEuNDIyLTEuMDA0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjk1LCAxMDAlLCA1MCUpIiBkPSJNMTcxLjcwNCAxOTAuNDUzYTY2LjUgNjYuNSAwIDAwMS40MzktLjk4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjk2LCAxMDAlLCA1MCUpIiBkPSJNMTcwLjczIDE5MS4wODZhNjYuNSA2Ni41IDAgMDAxLjQ1Ni0uOTU1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjk3LCAxMDAlLCA1MCUpIiBkPSJNMTY5Ljc0NiAxOTEuN2E2Ni41IDY2LjUgMCAwMDEuNDcyLS45MjgiLz48cGF0aCBzdHJva2U9ImhzbCgyOTgsIDEwMCUsIDUwJSkiIGQ9Ik0xNjguNzUxIDE5Mi4yOThhNjYuNSA2Ni41IDAgMDAxLjQ4OS0uOTAzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjk5LCAxMDAlLCA1MCUpIiBkPSJNMTY3Ljc0NiAxOTIuODc5YTY2LjUgNjYuNSAwIDAwMS41MDQtLjg3NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwMCwgMTAwJSwgNTAlKSIgZD0iTTE2Ni43MzEgMTkzLjQ0MWE2Ni41IDY2LjUgMCAwMDEuNTE5LS44NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwMSwgMTAwJSwgNTAlKSIgZD0iTTE2NS43MDYgMTkzLjk4NmE2Ni41IDY2LjUgMCAwMDEuNTM0LS44MjQiLz48cGF0aCBzdHJva2U9ImhzbCgzMDIsIDEwMCUsIDUwJSkiIGQ9Ik0xNjQuNjcyIDE5NC41MTNhNjYuNSA2Ni41IDAgMDAxLjU0OC0uNzk3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzAzLCAxMDAlLCA1MCUpIiBkPSJNMTYzLjYyOSAxOTUuMDIyYTY2LjUgNjYuNSAwIDAwMS41NjEtLjc3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzA0LCAxMDAlLCA1MCUpIiBkPSJNMTYyLjU3NyAxOTUuNTEyYTY2LjUgNjYuNSAwIDAwMS41NzUtLjc0MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwNSwgMTAwJSwgNTAlKSIgZD0iTTE2MS41MTcgMTk1Ljk4NGE2Ni41IDY2LjUgMCAwMDEuNTg3LS43MTUiLz48cGF0aCBzdHJva2U9ImhzbCgzMDYsIDEwMCUsIDUwJSkiIGQ9Ik0xNjAuNDQ4IDE5Ni40MzhhNjYuNSA2Ni41IDAgMDAxLjYtLjY4NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwNywgMTAwJSwgNTAlKSIgZD0iTTE1OS4zNzIgMTk2Ljg3M2E2Ni41IDY2LjUgMCAwMDEuNjEyLS42NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDMwOCwgMTAwJSwgNTAlKSIgZD0iTTE1OC4yODkgMTk3LjI4OWE2Ni41IDY2LjUgMCAwMDEuNjIyLS42MzEiLz48cGF0aCBzdHJva2U9ImhzbCgzMDksIDEwMCUsIDUwJSkiIGQ9Ik0xNTcuMTk4IDE5Ny42ODZhNjYuNSA2Ni41IDAgMDAxLjYzMy0uNjAzIi8+PHBhdGggc3Ryb2tlPSJoc2woMzEwLCAxMDAlLCA1MCUpIiBkPSJNMTU2LjEgMTk4LjA2NGE2Ni41IDY2LjUgMCAwMDEuNjQ0LS41NzQiLz48cGF0aCBzdHJva2U9ImhzbCgzMTEsIDEwMCUsIDUwJSkiIGQ9Ik0xNTQuOTk3IDE5OC40MjJhNjYuNSA2Ni41IDAgMDAxLjY1My0uNTQ1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzEyLCAxMDAlLCA1MCUpIiBkPSJNMTUzLjg4NyAxOTguNzYyYTY2LjUgNjYuNSAwIDAwMS42NjMtLjUxNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxMywgMTAwJSwgNTAlKSIgZD0iTTE1Mi43NzEgMTk5LjA4MWE2Ni41IDY2LjUgMCAwMDEuNjcyLS40ODciLz48cGF0aCBzdHJva2U9ImhzbCgzMTQsIDEwMCUsIDUwJSkiIGQ9Ik0xNTEuNjUgMTk5LjM4MmE2Ni41IDY2LjUgMCAwMDEuNjgtLjQ1OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxNSwgMTAwJSwgNTAlKSIgZD0iTTE1MC41MjQgMTk5LjY2M2E2Ni41IDY2LjUgMCAwMDEuNjg3LS40MjkiLz48cGF0aCBzdHJva2U9ImhzbCgzMTYsIDEwMCUsIDUwJSkiIGQ9Ik0xNDkuMzkzIDE5OS45MjRhNjYuNSA2Ni41IDAgMDAxLjY5NS0uNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxNywgMTAwJSwgNTAlKSIgZD0iTTE0OC4yNTggMjAwLjE2NWE2Ni41IDY2LjUgMCAwMDEuNzAxLS4zNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxOCwgMTAwJSwgNTAlKSIgZD0iTTE0Ny4xMTkgMjAwLjM4NmE2Ni41IDY2LjUgMCAwMDEuNzA3LS4zNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDMxOSwgMTAwJSwgNTAlKSIgZD0iTTE0NS45NzYgMjAwLjU4OGE2Ni41IDY2LjUgMCAwMDEuNzEzLS4zMSIvPjxwYXRoIHN0cm9rZT0iaHNsKDMyMCwgMTAwJSwgNTAlKSIgZD0iTTE0NC44MyAyMDAuNzdhNjYuNSA2Ni41IDAgMDAxLjcxOC0uMjgiLz48cGF0aCBzdHJva2U9ImhzbCgzMjEsIDEwMCUsIDUwJSkiIGQ9Ik0xNDMuNjggMjAwLjkzMWE2Ni41IDY2LjUgMCAwMDEuNzIzLS4yNSIvPjxwYXRoIHN0cm9rZT0iaHNsKDMyMiwgMTAwJSwgNTAlKSIgZD0iTTE0Mi41MjggMjAxLjA3M2E2Ni41IDY2LjUgMCAwMDEuNzI3LS4yMiIvPjxwYXRoIHN0cm9rZT0iaHNsKDMyMywgMTAwJSwgNTAlKSIgZD0iTTE0MS4zNzQgMjAxLjE5NGE2Ni41IDY2LjUgMCAwMDEuNzMtLjE5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzI0LCAxMDAlLCA1MCUpIiBkPSJNMTQwLjIxOCAyMDEuMjk1YTY2LjUgNjYuNSAwIDAwMS43MzMtLjE2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzI1LCAxMDAlLCA1MCUpIiBkPSJNMTM5LjA2IDIwMS4zNzZhNjYuNSA2Ni41IDAgMDAxLjczNi0uMTMiLz48cGF0aCBzdHJva2U9ImhzbCgzMjYsIDEwMCUsIDUwJSkiIGQ9Ik0xMzcuOSAyMDEuNDM3YTY2LjUgNjYuNSAwIDAwMS43MzktLjA5OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDMyNywgMTAwJSwgNTAlKSIgZD0iTTEzNi43NCAyMDEuNDc3YTY2LjUgNjYuNSAwIDAwMS43NC0uMDY4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzI4LCAxMDAlLCA1MCUpIiBkPSJNMTM1LjU4IDIwMS40OTdhNjYuNSA2Ni41IDAgMDAxLjc0LS4wMzgiLz48cGF0aCBzdHJva2U9ImhzbCgzMjksIDEwMCUsIDUwJSkiIGQ9Ik0xMzQuNDIgMjAxLjQ5N2E2Ni41IDY2LjUgMCAwMDEuNzQtLjAwNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDMzMCwgMTAwJSwgNTAlKSIgZD0iTTEzMy4yNiAyMDEuNDc3YTY2LjUgNjYuNSAwIDAwMS43NC4wMjMiLz48cGF0aCBzdHJva2U9ImhzbCgzMzEsIDEwMCUsIDUwJSkiIGQ9Ik0xMzIuMSAyMDEuNDM3YTY2LjUgNjYuNSAwIDAwMS43NC4wNTMiLz48cGF0aCBzdHJva2U9ImhzbCgzMzIsIDEwMCUsIDUwJSkiIGQ9Ik0xMzAuOTQgMjAxLjM3NmE2Ni41IDY2LjUgMCAwMDEuNzQuMDgzIi8+PHBhdGggc3Ryb2tlPSJoc2woMzMzLCAxMDAlLCA1MCUpIiBkPSJNMTI5Ljc4MiAyMDEuMjk1YTY2LjUgNjYuNSAwIDAwMS43MzguMTE0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM0LCAxMDAlLCA1MCUpIiBkPSJNMTI4LjYyNiAyMDEuMTk0YTY2LjUgNjYuNSAwIDAwMS43MzUuMTQ0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM1LCAxMDAlLCA1MCUpIiBkPSJNMTI3LjQ3MiAyMDEuMDczYTY2LjUgNjYuNSAwIDAwMS43MzIuMTc0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM2LCAxMDAlLCA1MCUpIiBkPSJNMTI2LjMyIDIwMC45MzFhNjYuNSA2Ni41IDAgMDAxLjcyOS4yMDUiLz48cGF0aCBzdHJva2U9ImhzbCgzMzcsIDEwMCUsIDUwJSkiIGQ9Ik0xMjUuMTcgMjAwLjc3YTY2LjUgNjYuNSAwIDAwMS43MjYuMjM0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM4LCAxMDAlLCA1MCUpIiBkPSJNMTI0LjAyNCAyMDAuNTg4YTY2LjUgNjYuNSAwIDAwMS43MjEuMjY1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzM5LCAxMDAlLCA1MCUpIiBkPSJNMTIyLjg4MSAyMDAuMzg2YTY2LjUgNjYuNSAwIDAwMS43MTYuMjk1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzQwLCAxMDAlLCA1MCUpIiBkPSJNMTIxLjc0MiAyMDAuMTY1YTY2LjUgNjYuNSAwIDAwMS43MS4zMjUiLz48cGF0aCBzdHJva2U9ImhzbCgzNDEsIDEwMCUsIDUwJSkiIGQ9Ik0xMjAuNjA3IDE5OS45MjRhNjYuNSA2Ni41IDAgMDAxLjcwNC4zNTQiLz48cGF0aCBzdHJva2U9ImhzbCgzNDIsIDEwMCUsIDUwJSkiIGQ9Ik0xMTkuNDc2IDE5OS42NjNhNjYuNSA2Ni41IDAgMDAxLjY5OC4zODQiLz48cGF0aCBzdHJva2U9ImhzbCgzNDMsIDEwMCUsIDUwJSkiIGQ9Ik0xMTguMzUgMTk5LjM4MmE2Ni41IDY2LjUgMCAwMDEuNjkuNDE0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzQ0LCAxMDAlLCA1MCUpIiBkPSJNMTE3LjIyOSAxOTkuMDgxYTY2LjUgNjYuNSAwIDAwMS42ODMuNDQ0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzQ1LCAxMDAlLCA1MCUpIiBkPSJNMTE2LjExMyAxOTguNzYyYTY2LjUgNjYuNSAwIDAwMS42NzYuNDcyIi8+PHBhdGggc3Ryb2tlPSJoc2woMzQ2LCAxMDAlLCA1MCUpIiBkPSJNMTE1LjAwMyAxOTguNDIyYTY2LjUgNjYuNSAwIDAwMS42NjcuNTAyIi8+PHBhdGggc3Ryb2tlPSJoc2woMzQ3LCAxMDAlLCA1MCUpIiBkPSJNMTEzLjkgMTk4LjA2NGE2Ni41IDY2LjUgMCAwMDEuNjU3LjUzIi8+PHBhdGggc3Ryb2tlPSJoc2woMzQ4LCAxMDAlLCA1MCUpIiBkPSJNMTEyLjgwMiAxOTcuNjg2YTY2LjUgNjYuNSAwIDAwMS42NDguNTYiLz48cGF0aCBzdHJva2U9ImhzbCgzNDksIDEwMCUsIDUwJSkiIGQ9Ik0xMTEuNzExIDE5Ny4yODlhNjYuNSA2Ni41IDAgMDAxLjYzOS41ODgiLz48cGF0aCBzdHJva2U9ImhzbCgzNTAsIDEwMCUsIDUwJSkiIGQ9Ik0xMTAuNjI4IDE5Ni44NzNhNjYuNSA2Ni41IDAgMDAxLjYyOC42MTciLz48cGF0aCBzdHJva2U9ImhzbCgzNTEsIDEwMCUsIDUwJSkiIGQ9Ik0xMDkuNTUyIDE5Ni40MzhhNjYuNSA2Ni41IDAgMDAxLjYxNy42NDUiLz48cGF0aCBzdHJva2U9ImhzbCgzNTIsIDEwMCUsIDUwJSkiIGQ9Ik0xMDguNDgzIDE5NS45ODRhNjYuNSA2Ni41IDAgMDAxLjYwNi42NzQiLz48cGF0aCBzdHJva2U9ImhzbCgzNTMsIDEwMCUsIDUwJSkiIGQ9Ik0xMDcuNDIzIDE5NS41MTJhNjYuNSA2Ni41IDAgMDAxLjU5My43MDIiLz48cGF0aCBzdHJva2U9ImhzbCgzNTQsIDEwMCUsIDUwJSkiIGQ9Ik0xMDYuMzcxIDE5NS4wMjJhNjYuNSA2Ni41IDAgMDAxLjU4MS43MjkiLz48cGF0aCBzdHJva2U9ImhzbCgzNTUsIDEwMCUsIDUwJSkiIGQ9Ik0xMDUuMzI4IDE5NC41MTNhNjYuNSA2Ni41IDAgMDAxLjU2OC43NTYiLz48cGF0aCBzdHJva2U9ImhzbCgzNTYsIDEwMCUsIDUwJSkiIGQ9Ik0xMDQuMjk0IDE5My45ODZhNjYuNSA2Ni41IDAgMDAxLjU1NC43ODQiLz48cGF0aCBzdHJva2U9ImhzbCgzNTcsIDEwMCUsIDUwJSkiIGQ9Ik0xMDMuMjY5IDE5My40NDFhNjYuNSA2Ni41IDAgMDAxLjU0LjgxIi8+PHBhdGggc3Ryb2tlPSJoc2woMzU4LCAxMDAlLCA1MCUpIiBkPSJNMTAyLjI1NCAxOTIuODc5YTY2LjUgNjYuNSAwIDAwMS41MjYuODM3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzU5LCAxMDAlLCA1MCUpIiBkPSJNMTAxLjI0OSAxOTIuMjk4YTY2LjUgNjYuNSAwIDAwMS41MTEuODY0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMCwgMTAwJSwgNTAlKSIgZD0iTTEwMC4yNTQgMTkxLjdhNjYuNSA2Ni41IDAgMDAxLjQ5Ni44OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDEsIDEwMCUsIDUwJSkiIGQ9Ik05OS4yNyAxOTEuMDg2YTY2LjUgNjYuNSAwIDAwMS40OC45MTYiLz48cGF0aCBzdHJva2U9ImhzbCgyLCAxMDAlLCA1MCUpIiBkPSJNOTguMjk2IDE5MC40NTNhNjYuNSA2Ni41IDAgMDAxLjQ2NC45NDIiLz48cGF0aCBzdHJva2U9ImhzbCgzLCAxMDAlLCA1MCUpIiBkPSJNOTcuMzM0IDE4OS44MDRhNjYuNSA2Ni41IDAgMDAxLjQ0OC45NjgiLz48cGF0aCBzdHJva2U9ImhzbCg0LCAxMDAlLCA1MCUpIiBkPSJNOTYuMzgzIDE4OS4xMzlhNjYuNSA2Ni41IDAgMDAxLjQzLjk5MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDUsIDEwMCUsIDUwJSkiIGQ9Ik05NS40NDQgMTg4LjQ1NmE2Ni41IDY2LjUgMCAwMDEuNDEzIDEuMDE4Ii8+PHBhdGggc3Ryb2tlPSJoc2woNiwgMTAwJSwgNTAlKSIgZD0iTTk0LjUxNyAxODcuNzU4YTY2LjUgNjYuNSAwIDAwMS4zOTUgMS4wNDIiLz48cGF0aCBzdHJva2U9ImhzbCg3LCAxMDAlLCA1MCUpIiBkPSJNOTMuNjAzIDE4Ny4wNDNhNjYuNSA2Ni41IDAgMDAxLjM3NiAxLjA2NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDgsIDEwMCUsIDUwJSkiIGQ9Ik05Mi43IDE4Ni4zMTNhNjYuNSA2Ni41IDAgMDAxLjM1OSAxLjA5Ii8+PHBhdGggc3Ryb2tlPSJoc2woOSwgMTAwJSwgNTAlKSIgZD0iTTkxLjgxMiAxODUuNTY3YTY2LjUgNjYuNSAwIDAwMS4zMzggMS4xMTMiLz48cGF0aCBzdHJva2U9ImhzbCgxMCwgMTAwJSwgNTAlKSIgZD0iTTkwLjkzNiAxODQuODA2YTY2LjUgNjYuNSAwIDAwMS4zMTkgMS4xMzYiLz48cGF0aCBzdHJva2U9ImhzbCgxMSwgMTAwJSwgNTAlKSIgZD0iTTkwLjA3MyAxODQuMDI5YTY2LjUgNjYuNSAwIDAwMS4zIDEuMTYiLz48cGF0aCBzdHJva2U9ImhzbCgxMiwgMTAwJSwgNTAlKSIgZD0iTTg5LjIyNCAxODMuMjM3YTY2LjUgNjYuNSAwIDAwMS4yNzkgMS4xODIiLz48cGF0aCBzdHJva2U9ImhzbCgxMywgMTAwJSwgNTAlKSIgZD0iTTg4LjM5IDE4Mi40MzFhNjYuNSA2Ni41IDAgMDAxLjI1NyAxLjIwNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE0LCAxMDAlLCA1MCUpIiBkPSJNODcuNTY5IDE4MS42MWE2Ni41IDY2LjUgMCAwMDEuMjM2IDEuMjI2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTUsIDEwMCUsIDUwJSkiIGQ9Ik04Ni43NjMgMTgwLjc3NmE2Ni41IDY2LjUgMCAwMDEuMjE0IDEuMjQ3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTYsIDEwMCUsIDUwJSkiIGQ9Ik04NS45NzEgMTc5LjkyN2E2Ni41IDY2LjUgMCAwMDEuMTkzIDEuMjY4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTcsIDEwMCUsIDUwJSkiIGQ9Ik04NS4xOTQgMTc5LjA2NGE2Ni41IDY2LjUgMCAwMDEuMTcxIDEuMjg5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTgsIDEwMCUsIDUwJSkiIGQ9Ik04NC40MzMgMTc4LjE4OGE2Ni41IDY2LjUgMCAwMDEuMTQ4IDEuMzEiLz48cGF0aCBzdHJva2U9ImhzbCgxOSwgMTAwJSwgNTAlKSIgZD0iTTgzLjY4NyAxNzcuM2E2Ni41IDY2LjUgMCAwMDEuMTI1IDEuMzI4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjAsIDEwMCUsIDUwJSkiIGQ9Ik04Mi45NTcgMTc2LjM5N2E2Ni41IDY2LjUgMCAwMDEuMTAxIDEuMzQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjEsIDEwMCUsIDUwJSkiIGQ9Ik04Mi4yNDIgMTc1LjQ4M2E2Ni41IDY2LjUgMCAwMDEuMDc4IDEuMzY3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjIsIDEwMCUsIDUwJSkiIGQ9Ik04MS41NDQgMTc0LjU1NmE2Ni41IDY2LjUgMCAwMDEuMDUzIDEuMzg1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjMsIDEwMCUsIDUwJSkiIGQ9Ik04MC44NjEgMTczLjYxN2E2Ni41IDY2LjUgMCAwMDEuMDMgMS40MDQiLz48cGF0aCBzdHJva2U9ImhzbCgyNCwgMTAwJSwgNTAlKSIgZD0iTTgwLjE5NiAxNzIuNjY2YTY2LjUgNjYuNSAwIDAwMS4wMDQgMS40MjIiLz48cGF0aCBzdHJva2U9ImhzbCgyNSwgMTAwJSwgNTAlKSIgZD0iTTc5LjU0NyAxNzEuNzA0YTY2LjUgNjYuNSAwIDAwLjk4IDEuNDM5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjYsIDEwMCUsIDUwJSkiIGQ9Ik03OC45MTQgMTcwLjczYTY2LjUgNjYuNSAwIDAwLjk1NSAxLjQ1NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI3LCAxMDAlLCA1MCUpIiBkPSJNNzguMyAxNjkuNzQ2YTY2LjUgNjYuNSAwIDAwLjkyOCAxLjQ3MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDI4LCAxMDAlLCA1MCUpIiBkPSJNNzcuNzAyIDE2OC43NTFhNjYuNSA2Ni41IDAgMDAuOTAzIDEuNDg5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjksIDEwMCUsIDUwJSkiIGQ9Ik03Ny4xMjEgMTY3Ljc0NmE2Ni41IDY2LjUgMCAwMC44NzcgMS41MDQiLz48cGF0aCBzdHJva2U9ImhzbCgzMCwgMTAwJSwgNTAlKSIgZD0iTTc2LjU1OSAxNjYuNzMxYTY2LjUgNjYuNSAwIDAwLjg1IDEuNTE5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzEsIDEwMCUsIDUwJSkiIGQ9Ik03Ni4wMTQgMTY1LjcwNmE2Ni41IDY2LjUgMCAwMC44MjQgMS41MzQiLz48cGF0aCBzdHJva2U9ImhzbCgzMiwgMTAwJSwgNTAlKSIgZD0iTTc1LjQ4NyAxNjQuNjcyYTY2LjUgNjYuNSAwIDAwLjc5NyAxLjU0OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDMzLCAxMDAlLCA1MCUpIiBkPSJNNzQuOTc4IDE2My42MjlhNjYuNSA2Ni41IDAgMDAuNzcgMS41NjEiLz48cGF0aCBzdHJva2U9ImhzbCgzNCwgMTAwJSwgNTAlKSIgZD0iTTc0LjQ4OCAxNjIuNTc3YTY2LjUgNjYuNSAwIDAwLjc0MiAxLjU3NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDM1LCAxMDAlLCA1MCUpIiBkPSJNNzQuMDE2IDE2MS41MTdhNjYuNSA2Ni41IDAgMDAuNzE1IDEuNTg3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzYsIDEwMCUsIDUwJSkiIGQ9Ik03My41NjIgMTYwLjQ0OGE2Ni41IDY2LjUgMCAwMC42ODcgMS42Ii8+PHBhdGggc3Ryb2tlPSJoc2woMzcsIDEwMCUsIDUwJSkiIGQ9Ik03My4xMjcgMTU5LjM3MmE2Ni41IDY2LjUgMCAwMC42NiAxLjYxMiIvPjxwYXRoIHN0cm9rZT0iaHNsKDM4LCAxMDAlLCA1MCUpIiBkPSJNNzIuNzExIDE1OC4yODlhNjYuNSA2Ni41IDAgMDAuNjMxIDEuNjIyIi8+PHBhdGggc3Ryb2tlPSJoc2woMzksIDEwMCUsIDUwJSkiIGQ9Ik03Mi4zMTQgMTU3LjE5OGE2Ni41IDY2LjUgMCAwMC42MDMgMS42MzMiLz48cGF0aCBzdHJva2U9ImhzbCg0MCwgMTAwJSwgNTAlKSIgZD0iTTcxLjkzNiAxNTYuMWE2Ni41IDY2LjUgMCAwMC41NzQgMS42NDQiLz48cGF0aCBzdHJva2U9ImhzbCg0MSwgMTAwJSwgNTAlKSIgZD0iTTcxLjU3OCAxNTQuOTk3YTY2LjUgNjYuNSAwIDAwLjU0NSAxLjY1MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDQyLCAxMDAlLCA1MCUpIiBkPSJNNzEuMjM4IDE1My44ODdhNjYuNSA2Ni41IDAgMDAuNTE3IDEuNjYzIi8+PHBhdGggc3Ryb2tlPSJoc2woNDMsIDEwMCUsIDUwJSkiIGQ9Ik03MC45MTkgMTUyLjc3MWE2Ni41IDY2LjUgMCAwMC40ODcgMS42NzIiLz48cGF0aCBzdHJva2U9ImhzbCg0NCwgMTAwJSwgNTAlKSIgZD0iTTcwLjYxOCAxNTEuNjVhNjYuNSA2Ni41IDAgMDAuNDU4IDEuNjgiLz48cGF0aCBzdHJva2U9ImhzbCg0NSwgMTAwJSwgNTAlKSIgZD0iTTcwLjMzNyAxNTAuNTI0YTY2LjUgNjYuNSAwIDAwLjQyOSAxLjY4NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDQ2LCAxMDAlLCA1MCUpIiBkPSJNNzAuMDc2IDE0OS4zOTNhNjYuNSA2Ni41IDAgMDAuNCAxLjY5NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDQ3LCAxMDAlLCA1MCUpIiBkPSJNNjkuODM1IDE0OC4yNThhNjYuNSA2Ni41IDAgMDAuMzcgMS43MDEiLz48cGF0aCBzdHJva2U9ImhzbCg0OCwgMTAwJSwgNTAlKSIgZD0iTTY5LjYxNCAxNDcuMTE5YTY2LjUgNjYuNSAwIDAwLjM0IDEuNzA3Ii8+PHBhdGggc3Ryb2tlPSJoc2woNDksIDEwMCUsIDUwJSkiIGQ9Ik02OS40MTIgMTQ1Ljk3NmE2Ni41IDY2LjUgMCAwMC4zMSAxLjcxMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDUwLCAxMDAlLCA1MCUpIiBkPSJNNjkuMjMgMTQ0LjgzYTY2LjUgNjYuNSAwIDAwLjI4IDEuNzE4Ii8+PHBhdGggc3Ryb2tlPSJoc2woNTEsIDEwMCUsIDUwJSkiIGQ9Ik02OS4wNjkgMTQzLjY4YTY2LjUgNjYuNSAwIDAwLjI1IDEuNzIzIi8+PHBhdGggc3Ryb2tlPSJoc2woNTIsIDEwMCUsIDUwJSkiIGQ9Ik02OC45MjcgMTQyLjUyOGE2Ni41IDY2LjUgMCAwMC4yMiAxLjcyNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDUzLCAxMDAlLCA1MCUpIiBkPSJNNjguODA2IDE0MS4zNzRhNjYuNSA2Ni41IDAgMDAuMTkgMS43MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDU0LCAxMDAlLCA1MCUpIiBkPSJNNjguNzA1IDE0MC4yMThhNjYuNSA2Ni41IDAgMDAuMTYgMS43MzMiLz48cGF0aCBzdHJva2U9ImhzbCg1NSwgMTAwJSwgNTAlKSIgZD0iTTY4LjYyNCAxMzkuMDZhNjYuNSA2Ni41IDAgMDAuMTMgMS43MzYiLz48cGF0aCBzdHJva2U9ImhzbCg1NiwgMTAwJSwgNTAlKSIgZD0iTTY4LjU2MyAxMzcuOWE2Ni41IDY2LjUgMCAwMC4wOTkgMS43MzkiLz48cGF0aCBzdHJva2U9ImhzbCg1NywgMTAwJSwgNTAlKSIgZD0iTTY4LjUyMyAxMzYuNzRhNjYuNSA2Ni41IDAgMDAuMDY4IDEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCg1OCwgMTAwJSwgNTAlKSIgZD0iTTY4LjUwMyAxMzUuNThhNjYuNSA2Ni41IDAgMDAuMDM4IDEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCg1OSwgMTAwJSwgNTAlKSIgZD0iTTY4LjUwMyAxMzQuNDJhNjYuNSA2Ni41IDAgMDAuMDA3IDEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCg2MCwgMTAwJSwgNTAlKSIgZD0iTTY4LjUyMyAxMzMuMjZBNjYuNSA2Ni41IDAgMDA2OC41IDEzNSIvPjxwYXRoIHN0cm9rZT0iaHNsKDYxLCAxMDAlLCA1MCUpIiBkPSJNNjguNTYzIDEzMi4xYTY2LjUgNjYuNSAwIDAwLS4wNTMgMS43NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDYyLCAxMDAlLCA1MCUpIiBkPSJNNjguNjI0IDEzMC45NGE2Ni41IDY2LjUgMCAwMC0uMDgzIDEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCg2MywgMTAwJSwgNTAlKSIgZD0iTTY4LjcwNSAxMjkuNzgyYTY2LjUgNjYuNSAwIDAwLS4xMTQgMS43MzgiLz48cGF0aCBzdHJva2U9ImhzbCg2NCwgMTAwJSwgNTAlKSIgZD0iTTY4LjgwNiAxMjguNjI2YTY2LjUgNjYuNSAwIDAwLS4xNDQgMS43MzUiLz48cGF0aCBzdHJva2U9ImhzbCg2NSwgMTAwJSwgNTAlKSIgZD0iTTY4LjkyNyAxMjcuNDcyYTY2LjUgNjYuNSAwIDAwLS4xNzQgMS43MzIiLz48cGF0aCBzdHJva2U9ImhzbCg2NiwgMTAwJSwgNTAlKSIgZD0iTTY5LjA2OSAxMjYuMzJhNjYuNSA2Ni41IDAgMDAtLjIwNSAxLjcyOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDY3LCAxMDAlLCA1MCUpIiBkPSJNNjkuMjMgMTI1LjE3YTY2LjUgNjYuNSAwIDAwLS4yMzQgMS43MjYiLz48cGF0aCBzdHJva2U9ImhzbCg2OCwgMTAwJSwgNTAlKSIgZD0iTTY5LjQxMiAxMjQuMDI0YTY2LjUgNjYuNSAwIDAwLS4yNjUgMS43MjEiLz48cGF0aCBzdHJva2U9ImhzbCg2OSwgMTAwJSwgNTAlKSIgZD0iTTY5LjYxNCAxMjIuODgxYTY2LjUgNjYuNSAwIDAwLS4yOTUgMS43MTYiLz48cGF0aCBzdHJva2U9ImhzbCg3MCwgMTAwJSwgNTAlKSIgZD0iTTY5LjgzNSAxMjEuNzQyYTY2LjUgNjYuNSAwIDAwLS4zMjUgMS43MSIvPjxwYXRoIHN0cm9rZT0iaHNsKDcxLCAxMDAlLCA1MCUpIiBkPSJNNzAuMDc2IDEyMC42MDdhNjYuNSA2Ni41IDAgMDAtLjM1NCAxLjcwNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDcyLCAxMDAlLCA1MCUpIiBkPSJNNzAuMzM3IDExOS40NzZhNjYuNSA2Ni41IDAgMDAtLjM4NCAxLjY5OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDczLCAxMDAlLCA1MCUpIiBkPSJNNzAuNjE4IDExOC4zNWE2Ni41IDY2LjUgMCAwMC0uNDE0IDEuNjkiLz48cGF0aCBzdHJva2U9ImhzbCg3NCwgMTAwJSwgNTAlKSIgZD0iTTcwLjkxOSAxMTcuMjI5YTY2LjUgNjYuNSAwIDAwLS40NDQgMS42ODMiLz48cGF0aCBzdHJva2U9ImhzbCg3NSwgMTAwJSwgNTAlKSIgZD0iTTcxLjIzOCAxMTYuMTEzYTY2LjUgNjYuNSAwIDAwLS40NzIgMS42NzYiLz48cGF0aCBzdHJva2U9ImhzbCg3NiwgMTAwJSwgNTAlKSIgZD0iTTcxLjU3OCAxMTUuMDAzYTY2LjUgNjYuNSAwIDAwLS41MDIgMS42NjciLz48cGF0aCBzdHJva2U9ImhzbCg3NywgMTAwJSwgNTAlKSIgZD0iTTcxLjkzNiAxMTMuOWE2Ni41IDY2LjUgMCAwMC0uNTMgMS42NTciLz48cGF0aCBzdHJva2U9ImhzbCg3OCwgMTAwJSwgNTAlKSIgZD0iTTcyLjMxNCAxMTIuODAyYTY2LjUgNjYuNSAwIDAwLS41NiAxLjY0OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDc5LCAxMDAlLCA1MCUpIiBkPSJNNzIuNzExIDExMS43MTFhNjYuNSA2Ni41IDAgMDAtLjU4OCAxLjYzOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDgwLCAxMDAlLCA1MCUpIiBkPSJNNzMuMTI3IDExMC42MjhhNjYuNSA2Ni41IDAgMDAtLjYxNyAxLjYyOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDgxLCAxMDAlLCA1MCUpIiBkPSJNNzMuNTYyIDEwOS41NTJhNjYuNSA2Ni41IDAgMDAtLjY0NSAxLjYxNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDgyLCAxMDAlLCA1MCUpIiBkPSJNNzQuMDE2IDEwOC40ODNhNjYuNSA2Ni41IDAgMDAtLjY3NCAxLjYwNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDgzLCAxMDAlLCA1MCUpIiBkPSJNNzQuNDg4IDEwNy40MjNhNjYuNSA2Ni41IDAgMDAtLjcwMiAxLjU5MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDg0LCAxMDAlLCA1MCUpIiBkPSJNNzQuOTc4IDEwNi4zNzFhNjYuNSA2Ni41IDAgMDAtLjcyOSAxLjU4MSIvPjxwYXRoIHN0cm9rZT0iaHNsKDg1LCAxMDAlLCA1MCUpIiBkPSJNNzUuNDg3IDEwNS4zMjhhNjYuNSA2Ni41IDAgMDAtLjc1NiAxLjU2OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDg2LCAxMDAlLCA1MCUpIiBkPSJNNzYuMDE0IDEwNC4yOTRhNjYuNSA2Ni41IDAgMDAtLjc4NCAxLjU1NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDg3LCAxMDAlLCA1MCUpIiBkPSJNNzYuNTU5IDEwMy4yNjlhNjYuNSA2Ni41IDAgMDAtLjgxIDEuNTQiLz48cGF0aCBzdHJva2U9ImhzbCg4OCwgMTAwJSwgNTAlKSIgZD0iTTc3LjEyMSAxMDIuMjU0YTY2LjUgNjYuNSAwIDAwLS44MzcgMS41MjYiLz48cGF0aCBzdHJva2U9ImhzbCg4OSwgMTAwJSwgNTAlKSIgZD0iTTc3LjcwMiAxMDEuMjQ5YTY2LjUgNjYuNSAwIDAwLS44NjQgMS41MTEiLz48cGF0aCBzdHJva2U9ImhzbCg5MCwgMTAwJSwgNTAlKSIgZD0iTTc4LjMgMTAwLjI1NGE2Ni41IDY2LjUgMCAwMC0uODkgMS40OTYiLz48cGF0aCBzdHJva2U9ImhzbCg5MSwgMTAwJSwgNTAlKSIgZD0iTTc4LjkxNCA5OS4yN2E2Ni41IDY2LjUgMCAwMC0uOTE2IDEuNDgiLz48cGF0aCBzdHJva2U9ImhzbCg5MiwgMTAwJSwgNTAlKSIgZD0iTTc5LjU0NyA5OC4yOTZhNjYuNSA2Ni41IDAgMDAtLjk0MiAxLjQ2NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDkzLCAxMDAlLCA1MCUpIiBkPSJNODAuMTk2IDk3LjMzNGE2Ni41IDY2LjUgMCAwMC0uOTY4IDEuNDQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woOTQsIDEwMCUsIDUwJSkiIGQ9Ik04MC44NjEgOTYuMzgzYTY2LjUgNjYuNSAwIDAwLS45OTIgMS40MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDk1LCAxMDAlLCA1MCUpIiBkPSJNODEuNTQ0IDk1LjQ0NGE2Ni41IDY2LjUgMCAwMC0xLjAxOCAxLjQxMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDk2LCAxMDAlLCA1MCUpIiBkPSJNODIuMjQyIDk0LjUxN2E2Ni41IDY2LjUgMCAwMC0xLjA0MiAxLjM5NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDk3LCAxMDAlLCA1MCUpIiBkPSJNODIuOTU3IDkzLjYwM2E2Ni41IDY2LjUgMCAwMC0xLjA2NiAxLjM3NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDk4LCAxMDAlLCA1MCUpIiBkPSJNODMuNjg3IDkyLjdhNjYuNSA2Ni41IDAgMDAtMS4wOSAxLjM1OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDk5LCAxMDAlLCA1MCUpIiBkPSJNODQuNDMzIDkxLjgxMmE2Ni41IDY2LjUgMCAwMC0xLjExMyAxLjMzOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwMCwgMTAwJSwgNTAlKSIgZD0iTTg1LjE5NCA5MC45MzZhNjYuNSA2Ni41IDAgMDAtMS4xMzYgMS4zMTkiLz48cGF0aCBzdHJva2U9ImhzbCgxMDEsIDEwMCUsIDUwJSkiIGQ9Ik04NS45NzEgOTAuMDczYTY2LjUgNjYuNSAwIDAwLTEuMTYgMS4zIi8+PHBhdGggc3Ryb2tlPSJoc2woMTAyLCAxMDAlLCA1MCUpIiBkPSJNODYuNzYzIDg5LjIyNGE2Ni41IDY2LjUgMCAwMC0xLjE4MiAxLjI3OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwMywgMTAwJSwgNTAlKSIgZD0iTTg3LjU2OSA4OC4zOWE2Ni41IDY2LjUgMCAwMC0xLjIwNCAxLjI1NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwNCwgMTAwJSwgNTAlKSIgZD0iTTg4LjM5IDg3LjU2OWE2Ni41IDY2LjUgMCAwMC0xLjIyNiAxLjIzNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwNSwgMTAwJSwgNTAlKSIgZD0iTTg5LjIyNCA4Ni43NjNhNjYuNSA2Ni41IDAgMDAtMS4yNDcgMS4yMTQiLz48cGF0aCBzdHJva2U9ImhzbCgxMDYsIDEwMCUsIDUwJSkiIGQ9Ik05MC4wNzMgODUuOTcxYTY2LjUgNjYuNSAwIDAwLTEuMjY4IDEuMTkzIi8+PHBhdGggc3Ryb2tlPSJoc2woMTA3LCAxMDAlLCA1MCUpIiBkPSJNOTAuOTM2IDg1LjE5NGE2Ni41IDY2LjUgMCAwMC0xLjI4OSAxLjE3MSIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwOCwgMTAwJSwgNTAlKSIgZD0iTTkxLjgxMiA4NC40MzNhNjYuNSA2Ni41IDAgMDAtMS4zMSAxLjE0OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDEwOSwgMTAwJSwgNTAlKSIgZD0iTTkyLjcgODMuNjg3YTY2LjUgNjYuNSAwIDAwLTEuMzI4IDEuMTI1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTEwLCAxMDAlLCA1MCUpIiBkPSJNOTMuNjAzIDgyLjk1N2E2Ni41IDY2LjUgMCAwMC0xLjM0OCAxLjEwMSIvPjxwYXRoIHN0cm9rZT0iaHNsKDExMSwgMTAwJSwgNTAlKSIgZD0iTTk0LjUxNyA4Mi4yNDJhNjYuNSA2Ni41IDAgMDAtMS4zNjcgMS4wNzgiLz48cGF0aCBzdHJva2U9ImhzbCgxMTIsIDEwMCUsIDUwJSkiIGQ9Ik05NS40NDQgODEuNTQ0YTY2LjUgNjYuNSAwIDAwLTEuMzg1IDEuMDUzIi8+PHBhdGggc3Ryb2tlPSJoc2woMTEzLCAxMDAlLCA1MCUpIiBkPSJNOTYuMzgzIDgwLjg2MWE2Ni41IDY2LjUgMCAwMC0xLjQwNCAxLjAzIi8+PHBhdGggc3Ryb2tlPSJoc2woMTE0LCAxMDAlLCA1MCUpIiBkPSJNOTcuMzM0IDgwLjE5NmE2Ni41IDY2LjUgMCAwMC0xLjQyMiAxLjAwNCIvPjxwYXRoIHN0cm9rZT0iaHNsKDExNSwgMTAwJSwgNTAlKSIgZD0iTTk4LjI5NiA3OS41NDdhNjYuNSA2Ni41IDAgMDAtMS40MzkuOTgiLz48cGF0aCBzdHJva2U9ImhzbCgxMTYsIDEwMCUsIDUwJSkiIGQ9Ik05OS4yNyA3OC45MTRhNjYuNSA2Ni41IDAgMDAtMS40NTYuOTU1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTE3LCAxMDAlLCA1MCUpIiBkPSJNMTAwLjI1NCA3OC4zYTY2LjUgNjYuNSAwIDAwLTEuNDcyLjkyOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDExOCwgMTAwJSwgNTAlKSIgZD0iTTEwMS4yNDkgNzcuNzAyYTY2LjUgNjYuNSAwIDAwLTEuNDg5LjkwMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDExOSwgMTAwJSwgNTAlKSIgZD0iTTEwMi4yNTQgNzcuMTIxYTY2LjUgNjYuNSAwIDAwLTEuNTA0Ljg3NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDEyMCwgMTAwJSwgNTAlKSIgZD0iTTEwMy4yNjkgNzYuNTU5YTY2LjUgNjYuNSAwIDAwLTEuNTE5Ljg1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTIxLCAxMDAlLCA1MCUpIiBkPSJNMTA0LjI5NCA3Ni4wMTRhNjYuNSA2Ni41IDAgMDAtMS41MzQuODI0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTIyLCAxMDAlLCA1MCUpIiBkPSJNMTA1LjMyOCA3NS40ODdhNjYuNSA2Ni41IDAgMDAtMS41NDguNzk3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTIzLCAxMDAlLCA1MCUpIiBkPSJNMTA2LjM3MSA3NC45NzhhNjYuNSA2Ni41IDAgMDAtMS41NjEuNzciLz48cGF0aCBzdHJva2U9ImhzbCgxMjQsIDEwMCUsIDUwJSkiIGQ9Ik0xMDcuNDIzIDc0LjQ4OGE2Ni41IDY2LjUgMCAwMC0xLjU3NS43NDIiLz48cGF0aCBzdHJva2U9ImhzbCgxMjUsIDEwMCUsIDUwJSkiIGQ9Ik0xMDguNDgzIDc0LjAxNmE2Ni41IDY2LjUgMCAwMC0xLjU4Ny43MTUiLz48cGF0aCBzdHJva2U9ImhzbCgxMjYsIDEwMCUsIDUwJSkiIGQ9Ik0xMDkuNTUyIDczLjU2MmE2Ni41IDY2LjUgMCAwMC0xLjYuNjg3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTI3LCAxMDAlLCA1MCUpIiBkPSJNMTEwLjYyOCA3My4xMjdhNjYuNSA2Ni41IDAgMDAtMS42MTIuNjYiLz48cGF0aCBzdHJva2U9ImhzbCgxMjgsIDEwMCUsIDUwJSkiIGQ9Ik0xMTEuNzExIDcyLjcxMWE2Ni41IDY2LjUgMCAwMC0xLjYyMi42MzEiLz48cGF0aCBzdHJva2U9ImhzbCgxMjksIDEwMCUsIDUwJSkiIGQ9Ik0xMTIuODAyIDcyLjMxNGE2Ni41IDY2LjUgMCAwMC0xLjYzMy42MDMiLz48cGF0aCBzdHJva2U9ImhzbCgxMzAsIDEwMCUsIDUwJSkiIGQ9Ik0xMTMuOSA3MS45MzZhNjYuNSA2Ni41IDAgMDAtMS42NDQuNTc0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTMxLCAxMDAlLCA1MCUpIiBkPSJNMTE1LjAwMyA3MS41NzhhNjYuNSA2Ni41IDAgMDAtMS42NTMuNTQ1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTMyLCAxMDAlLCA1MCUpIiBkPSJNMTE2LjExMyA3MS4yMzhhNjYuNSA2Ni41IDAgMDAtMS42NjMuNTE3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTMzLCAxMDAlLCA1MCUpIiBkPSJNMTE3LjIyOSA3MC45MTlhNjYuNSA2Ni41IDAgMDAtMS42NzIuNDg3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTM0LCAxMDAlLCA1MCUpIiBkPSJNMTE4LjM1IDcwLjYxOGE2Ni41IDY2LjUgMCAwMC0xLjY4LjQ1OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDEzNSwgMTAwJSwgNTAlKSIgZD0iTTExOS40NzYgNzAuMzM3YTY2LjUgNjYuNSAwIDAwLTEuNjg3LjQyOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDEzNiwgMTAwJSwgNTAlKSIgZD0iTTEyMC42MDcgNzAuMDc2YTY2LjUgNjYuNSAwIDAwLTEuNjk1LjQiLz48cGF0aCBzdHJva2U9ImhzbCgxMzcsIDEwMCUsIDUwJSkiIGQ9Ik0xMjEuNzQyIDY5LjgzNWE2Ni41IDY2LjUgMCAwMC0xLjcwMS4zNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDEzOCwgMTAwJSwgNTAlKSIgZD0iTTEyMi44ODEgNjkuNjE0YTY2LjUgNjYuNSAwIDAwLTEuNzA3LjM0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTM5LCAxMDAlLCA1MCUpIiBkPSJNMTI0LjAyNCA2OS40MTJhNjYuNSA2Ni41IDAgMDAtMS43MTMuMzEiLz48cGF0aCBzdHJva2U9ImhzbCgxNDAsIDEwMCUsIDUwJSkiIGQ9Ik0xMjUuMTcgNjkuMjNhNjYuNSA2Ni41IDAgMDAtMS43MTguMjgiLz48cGF0aCBzdHJva2U9ImhzbCgxNDEsIDEwMCUsIDUwJSkiIGQ9Ik0xMjYuMzIgNjkuMDY5YTY2LjUgNjYuNSAwIDAwLTEuNzIzLjI1Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTQyLCAxMDAlLCA1MCUpIiBkPSJNMTI3LjQ3MiA2OC45MjdhNjYuNSA2Ni41IDAgMDAtMS43MjcuMjIiLz48cGF0aCBzdHJva2U9ImhzbCgxNDMsIDEwMCUsIDUwJSkiIGQ9Ik0xMjguNjI2IDY4LjgwNmE2Ni41IDY2LjUgMCAwMC0xLjczLjE5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTQ0LCAxMDAlLCA1MCUpIiBkPSJNMTI5Ljc4MiA2OC43MDVhNjYuNSA2Ni41IDAgMDAtMS43MzMuMTYiLz48cGF0aCBzdHJva2U9ImhzbCgxNDUsIDEwMCUsIDUwJSkiIGQ9Ik0xMzAuOTQgNjguNjI0YTY2LjUgNjYuNSAwIDAwLTEuNzM2LjEzIi8+PHBhdGggc3Ryb2tlPSJoc2woMTQ2LCAxMDAlLCA1MCUpIiBkPSJNMTMyLjEgNjguNTYzYTY2LjUgNjYuNSAwIDAwLTEuNzM5LjA5OSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE0NywgMTAwJSwgNTAlKSIgZD0iTTEzMy4yNiA2OC41MjNhNjYuNSA2Ni41IDAgMDAtMS43NC4wNjgiLz48cGF0aCBzdHJva2U9ImhzbCgxNDgsIDEwMCUsIDUwJSkiIGQ9Ik0xMzQuNDIgNjguNTAzYTY2LjUgNjYuNSAwIDAwLTEuNzQuMDM4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTQ5LCAxMDAlLCA1MCUpIiBkPSJNMTM1LjU4IDY4LjUwM2E2Ni41IDY2LjUgMCAwMC0xLjc0LjAwNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1MCwgMTAwJSwgNTAlKSIgZD0iTTEzNi43NCA2OC41MjNBNjYuNSA2Ni41IDAgMDAxMzUgNjguNSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1MSwgMTAwJSwgNTAlKSIgZD0iTTEzNy45IDY4LjU2M2E2Ni41IDY2LjUgMCAwMC0xLjc0LS4wNTMiLz48cGF0aCBzdHJva2U9ImhzbCgxNTIsIDEwMCUsIDUwJSkiIGQ9Ik0xMzkuMDYgNjguNjI0YTY2LjUgNjYuNSAwIDAwLTEuNzQtLjA4MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1MywgMTAwJSwgNTAlKSIgZD0iTTE0MC4yMTggNjguNzA1YTY2LjUgNjYuNSAwIDAwLTEuNzM4LS4xMTQiLz48cGF0aCBzdHJva2U9ImhzbCgxNTQsIDEwMCUsIDUwJSkiIGQ9Ik0xNDEuMzc0IDY4LjgwNmE2Ni41IDY2LjUgMCAwMC0xLjczNS0uMTQ0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTU1LCAxMDAlLCA1MCUpIiBkPSJNMTQyLjUyOCA2OC45MjdhNjYuNSA2Ni41IDAgMDAtMS43MzItLjE3NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1NiwgMTAwJSwgNTAlKSIgZD0iTTE0My42OCA2OS4wNjlhNjYuNSA2Ni41IDAgMDAtMS43MjktLjIwNSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1NywgMTAwJSwgNTAlKSIgZD0iTTE0NC44MyA2OS4yM2E2Ni41IDY2LjUgMCAwMC0xLjcyNi0uMjM0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTU4LCAxMDAlLCA1MCUpIiBkPSJNMTQ1Ljk3NiA2OS40MTJhNjYuNSA2Ni41IDAgMDAtMS43MjEtLjI2NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE1OSwgMTAwJSwgNTAlKSIgZD0iTTE0Ny4xMTkgNjkuNjE0YTY2LjUgNjYuNSAwIDAwLTEuNzE2LS4yOTUiLz48cGF0aCBzdHJva2U9ImhzbCgxNjAsIDEwMCUsIDUwJSkiIGQ9Ik0xNDguMjU4IDY5LjgzNWE2Ni41IDY2LjUgMCAwMC0xLjcxLS4zMjUiLz48cGF0aCBzdHJva2U9ImhzbCgxNjEsIDEwMCUsIDUwJSkiIGQ9Ik0xNDkuMzkzIDcwLjA3NmE2Ni41IDY2LjUgMCAwMC0xLjcwNC0uMzU0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTYyLCAxMDAlLCA1MCUpIiBkPSJNMTUwLjUyNCA3MC4zMzdhNjYuNSA2Ni41IDAgMDAtMS42OTgtLjM4NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE2MywgMTAwJSwgNTAlKSIgZD0iTTE1MS42NSA3MC42MThhNjYuNSA2Ni41IDAgMDAtMS42OS0uNDE0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTY0LCAxMDAlLCA1MCUpIiBkPSJNMTUyLjc3MSA3MC45MTlhNjYuNSA2Ni41IDAgMDAtMS42ODMtLjQ0NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE2NSwgMTAwJSwgNTAlKSIgZD0iTTE1My44ODcgNzEuMjM4YTY2LjUgNjYuNSAwIDAwLTEuNjc2LS40NzIiLz48cGF0aCBzdHJva2U9ImhzbCgxNjYsIDEwMCUsIDUwJSkiIGQ9Ik0xNTQuOTk3IDcxLjU3OGE2Ni41IDY2LjUgMCAwMC0xLjY2Ny0uNTAyIi8+PHBhdGggc3Ryb2tlPSJoc2woMTY3LCAxMDAlLCA1MCUpIiBkPSJNMTU2LjEgNzEuOTM2YTY2LjUgNjYuNSAwIDAwLTEuNjU3LS41MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDE2OCwgMTAwJSwgNTAlKSIgZD0iTTE1Ny4xOTggNzIuMzE0YTY2LjUgNjYuNSAwIDAwLTEuNjQ4LS41NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDE2OSwgMTAwJSwgNTAlKSIgZD0iTTE1OC4yODkgNzIuNzExYTY2LjUgNjYuNSAwIDAwLTEuNjM5LS41ODgiLz48cGF0aCBzdHJva2U9ImhzbCgxNzAsIDEwMCUsIDUwJSkiIGQ9Ik0xNTkuMzcyIDczLjEyN2E2Ni41IDY2LjUgMCAwMC0xLjYyOC0uNjE3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTcxLCAxMDAlLCA1MCUpIiBkPSJNMTYwLjQ0OCA3My41NjJhNjYuNSA2Ni41IDAgMDAtMS42MTctLjY0NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE3MiwgMTAwJSwgNTAlKSIgZD0iTTE2MS41MTcgNzQuMDE2YTY2LjUgNjYuNSAwIDAwLTEuNjA2LS42NzQiLz48cGF0aCBzdHJva2U9ImhzbCgxNzMsIDEwMCUsIDUwJSkiIGQ9Ik0xNjIuNTc3IDc0LjQ4OGE2Ni41IDY2LjUgMCAwMC0xLjU5My0uNzAyIi8+PHBhdGggc3Ryb2tlPSJoc2woMTc0LCAxMDAlLCA1MCUpIiBkPSJNMTYzLjYyOSA3NC45NzhhNjYuNSA2Ni41IDAgMDAtMS41ODEtLjcyOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE3NSwgMTAwJSwgNTAlKSIgZD0iTTE2NC42NzIgNzUuNDg3YTY2LjUgNjYuNSAwIDAwLTEuNTY4LS43NTYiLz48cGF0aCBzdHJva2U9ImhzbCgxNzYsIDEwMCUsIDUwJSkiIGQ9Ik0xNjUuNzA2IDc2LjAxNGE2Ni41IDY2LjUgMCAwMC0xLjU1NC0uNzg0Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTc3LCAxMDAlLCA1MCUpIiBkPSJNMTY2LjczMSA3Ni41NTlhNjYuNSA2Ni41IDAgMDAtMS41NC0uODEiLz48cGF0aCBzdHJva2U9ImhzbCgxNzgsIDEwMCUsIDUwJSkiIGQ9Ik0xNjcuNzQ2IDc3LjEyMWE2Ni41IDY2LjUgMCAwMC0xLjUyNi0uODM3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTc5LCAxMDAlLCA1MCUpIiBkPSJNMTY4Ljc1MSA3Ny43MDJhNjYuNSA2Ni41IDAgMDAtMS41MTEtLjg2NCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE4MCwgMTAwJSwgNTAlKSIgZD0iTTE2OS43NDYgNzguM2E2Ni41IDY2LjUgMCAwMC0xLjQ5Ni0uODkiLz48cGF0aCBzdHJva2U9ImhzbCgxODEsIDEwMCUsIDUwJSkiIGQ9Ik0xNzAuNzMgNzguOTE0YTY2LjUgNjYuNSAwIDAwLTEuNDgtLjkxNiIvPjxwYXRoIHN0cm9rZT0iaHNsKDE4MiwgMTAwJSwgNTAlKSIgZD0iTTE3MS43MDQgNzkuNTQ3YTY2LjUgNjYuNSAwIDAwLTEuNDY0LS45NDIiLz48cGF0aCBzdHJva2U9ImhzbCgxODMsIDEwMCUsIDUwJSkiIGQ9Ik0xNzIuNjY2IDgwLjE5NmE2Ni41IDY2LjUgMCAwMC0xLjQ0OC0uOTY4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTg0LCAxMDAlLCA1MCUpIiBkPSJNMTczLjYxNyA4MC44NjFhNjYuNSA2Ni41IDAgMDAtMS40My0uOTkyIi8+PHBhdGggc3Ryb2tlPSJoc2woMTg1LCAxMDAlLCA1MCUpIiBkPSJNMTc0LjU1NiA4MS41NDRhNjYuNSA2Ni41IDAgMDAtMS40MTMtMS4wMTgiLz48cGF0aCBzdHJva2U9ImhzbCgxODYsIDEwMCUsIDUwJSkiIGQ9Ik0xNzUuNDgzIDgyLjI0MmE2Ni41IDY2LjUgMCAwMC0xLjM5NS0xLjA0MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDE4NywgMTAwJSwgNTAlKSIgZD0iTTE3Ni4zOTcgODIuOTU3YTY2LjUgNjYuNSAwIDAwLTEuMzc2LTEuMDY2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTg4LCAxMDAlLCA1MCUpIiBkPSJNMTc3LjMgODMuNjg3YTY2LjUgNjYuNSAwIDAwLTEuMzU5LTEuMDkiLz48cGF0aCBzdHJva2U9ImhzbCgxODksIDEwMCUsIDUwJSkiIGQ9Ik0xNzguMTg4IDg0LjQzM2E2Ni41IDY2LjUgMCAwMC0xLjMzOC0xLjExMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDE5MCwgMTAwJSwgNTAlKSIgZD0iTTE3OS4wNjQgODUuMTk0YTY2LjUgNjYuNSAwIDAwLTEuMzE5LTEuMTM2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTkxLCAxMDAlLCA1MCUpIiBkPSJNMTc5LjkyNyA4NS45NzFhNjYuNSA2Ni41IDAgMDAtMS4zLTEuMTYiLz48cGF0aCBzdHJva2U9ImhzbCgxOTIsIDEwMCUsIDUwJSkiIGQ9Ik0xODAuNzc2IDg2Ljc2M2E2Ni41IDY2LjUgMCAwMC0xLjI3OS0xLjE4MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDE5MywgMTAwJSwgNTAlKSIgZD0iTTE4MS42MSA4Ny41NjlhNjYuNSA2Ni41IDAgMDAtMS4yNTctMS4yMDQiLz48cGF0aCBzdHJva2U9ImhzbCgxOTQsIDEwMCUsIDUwJSkiIGQ9Ik0xODIuNDMxIDg4LjM5YTY2LjUgNjYuNSAwIDAwLTEuMjM2LTEuMjI2Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTk1LCAxMDAlLCA1MCUpIiBkPSJNMTgzLjIzNyA4OS4yMjRhNjYuNSA2Ni41IDAgMDAtMS4yMTQtMS4yNDciLz48cGF0aCBzdHJva2U9ImhzbCgxOTYsIDEwMCUsIDUwJSkiIGQ9Ik0xODQuMDI5IDkwLjA3M2E2Ni41IDY2LjUgMCAwMC0xLjE5My0xLjI2OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDE5NywgMTAwJSwgNTAlKSIgZD0iTTE4NC44MDYgOTAuOTM2YTY2LjUgNjYuNSAwIDAwLTEuMTcxLTEuMjg5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMTk4LCAxMDAlLCA1MCUpIiBkPSJNMTg1LjU2NyA5MS44MTJhNjYuNSA2Ni41IDAgMDAtMS4xNDgtMS4zMSIvPjxwYXRoIHN0cm9rZT0iaHNsKDE5OSwgMTAwJSwgNTAlKSIgZD0iTTE4Ni4zMTMgOTIuN2E2Ni41IDY2LjUgMCAwMC0xLjEyNS0xLjMyOCIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwMCwgMTAwJSwgNTAlKSIgZD0iTTE4Ny4wNDMgOTMuNjAzYTY2LjUgNjYuNSAwIDAwLTEuMTAxLTEuMzQ4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjAxLCAxMDAlLCA1MCUpIiBkPSJNMTg3Ljc1OCA5NC41MTdhNjYuNSA2Ni41IDAgMDAtMS4wNzgtMS4zNjciLz48cGF0aCBzdHJva2U9ImhzbCgyMDIsIDEwMCUsIDUwJSkiIGQ9Ik0xODguNDU2IDk1LjQ0NGE2Ni41IDY2LjUgMCAwMC0xLjA1My0xLjM4NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwMywgMTAwJSwgNTAlKSIgZD0iTTE4OS4xMzkgOTYuMzgzYTY2LjUgNjYuNSAwIDAwLTEuMDMtMS40MDQiLz48cGF0aCBzdHJva2U9ImhzbCgyMDQsIDEwMCUsIDUwJSkiIGQ9Ik0xODkuODA0IDk3LjMzNGE2Ni41IDY2LjUgMCAwMC0xLjAwNC0xLjQyMiIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwNSwgMTAwJSwgNTAlKSIgZD0iTTE5MC40NTMgOTguMjk2YTY2LjUgNjYuNSAwIDAwLS45OC0xLjQzOSIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwNiwgMTAwJSwgNTAlKSIgZD0iTTE5MS4wODYgOTkuMjdhNjYuNSA2Ni41IDAgMDAtLjk1NS0xLjQ1NiIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwNywgMTAwJSwgNTAlKSIgZD0iTTE5MS43IDEwMC4yNTRhNjYuNSA2Ni41IDAgMDAtLjkyOC0xLjQ3MiIvPjxwYXRoIHN0cm9rZT0iaHNsKDIwOCwgMTAwJSwgNTAlKSIgZD0iTTE5Mi4yOTggMTAxLjI0OWE2Ni41IDY2LjUgMCAwMC0uOTAzLTEuNDg5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjA5LCAxMDAlLCA1MCUpIiBkPSJNMTkyLjg3OSAxMDIuMjU0YTY2LjUgNjYuNSAwIDAwLS44NzctMS41MDQiLz48cGF0aCBzdHJva2U9ImhzbCgyMTAsIDEwMCUsIDUwJSkiIGQ9Ik0xOTMuNDQxIDEwMy4yNjlhNjYuNSA2Ni41IDAgMDAtLjg1LTEuNTE5Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjExLCAxMDAlLCA1MCUpIiBkPSJNMTkzLjk4NiAxMDQuMjk0YTY2LjUgNjYuNSAwIDAwLS44MjQtMS41MzQiLz48cGF0aCBzdHJva2U9ImhzbCgyMTIsIDEwMCUsIDUwJSkiIGQ9Ik0xOTQuNTEzIDEwNS4zMjhhNjYuNSA2Ni41IDAgMDAtLjc5Ny0xLjU0OCIvPjxwYXRoIHN0cm9rZT0iaHNsKDIxMywgMTAwJSwgNTAlKSIgZD0iTTE5NS4wMjIgMTA2LjM3MWE2Ni41IDY2LjUgMCAwMC0uNzctMS41NjEiLz48cGF0aCBzdHJva2U9ImhzbCgyMTQsIDEwMCUsIDUwJSkiIGQ9Ik0xOTUuNTEyIDEwNy40MjNhNjYuNSA2Ni41IDAgMDAtLjc0Mi0xLjU3NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDIxNSwgMTAwJSwgNTAlKSIgZD0iTTE5NS45ODQgMTA4LjQ4M2E2Ni41IDY2LjUgMCAwMC0uNzE1LTEuNTg3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjE2LCAxMDAlLCA1MCUpIiBkPSJNMTk2LjQzOCAxMDkuNTUyYTY2LjUgNjYuNSAwIDAwLS42ODctMS42Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjE3LCAxMDAlLCA1MCUpIiBkPSJNMTk2Ljg3MyAxMTAuNjI4YTY2LjUgNjYuNSAwIDAwLS42Ni0xLjYxMiIvPjxwYXRoIHN0cm9rZT0iaHNsKDIxOCwgMTAwJSwgNTAlKSIgZD0iTTE5Ny4yODkgMTExLjcxMWE2Ni41IDY2LjUgMCAwMC0uNjMxLTEuNjIyIi8+PHBhdGggc3Ryb2tlPSJoc2woMjE5LCAxMDAlLCA1MCUpIiBkPSJNMTk3LjY4NiAxMTIuODAyYTY2LjUgNjYuNSAwIDAwLS42MDMtMS42MzMiLz48cGF0aCBzdHJva2U9ImhzbCgyMjAsIDEwMCUsIDUwJSkiIGQ9Ik0xOTguMDY0IDExMy45YTY2LjUgNjYuNSAwIDAwLS41NzQtMS42NDQiLz48cGF0aCBzdHJva2U9ImhzbCgyMjEsIDEwMCUsIDUwJSkiIGQ9Ik0xOTguNDIyIDExNS4wMDNhNjYuNSA2Ni41IDAgMDAtLjU0NS0xLjY1MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIyMiwgMTAwJSwgNTAlKSIgZD0iTTE5OC43NjIgMTE2LjExM2E2Ni41IDY2LjUgMCAwMC0uNTE3LTEuNjYzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjIzLCAxMDAlLCA1MCUpIiBkPSJNMTk5LjA4MSAxMTcuMjI5YTY2LjUgNjYuNSAwIDAwLS40ODctMS42NzIiLz48cGF0aCBzdHJva2U9ImhzbCgyMjQsIDEwMCUsIDUwJSkiIGQ9Ik0xOTkuMzgyIDExOC4zNWE2Ni41IDY2LjUgMCAwMC0uNDU4LTEuNjgiLz48cGF0aCBzdHJva2U9ImhzbCgyMjUsIDEwMCUsIDUwJSkiIGQ9Ik0xOTkuNjYzIDExOS40NzZhNjYuNSA2Ni41IDAgMDAtLjQyOS0xLjY4NyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIyNiwgMTAwJSwgNTAlKSIgZD0iTTE5OS45MjQgMTIwLjYwN2E2Ni41IDY2LjUgMCAwMC0uNC0xLjY5NSIvPjxwYXRoIHN0cm9rZT0iaHNsKDIyNywgMTAwJSwgNTAlKSIgZD0iTTIwMC4xNjUgMTIxLjc0MmE2Ni41IDY2LjUgMCAwMC0uMzctMS43MDEiLz48cGF0aCBzdHJva2U9ImhzbCgyMjgsIDEwMCUsIDUwJSkiIGQ9Ik0yMDAuMzg2IDEyMi44ODFhNjYuNSA2Ni41IDAgMDAtLjM0LTEuNzA3Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjI5LCAxMDAlLCA1MCUpIiBkPSJNMjAwLjU4OCAxMjQuMDI0YTY2LjUgNjYuNSAwIDAwLS4zMS0xLjcxMyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIzMCwgMTAwJSwgNTAlKSIgZD0iTTIwMC43NyAxMjUuMTdhNjYuNSA2Ni41IDAgMDAtLjI4LTEuNzE4Ii8+PHBhdGggc3Ryb2tlPSJoc2woMjMxLCAxMDAlLCA1MCUpIiBkPSJNMjAwLjkzMSAxMjYuMzJhNjYuNSA2Ni41IDAgMDAtLjI1LTEuNzIzIi8+PHBhdGggc3Ryb2tlPSJoc2woMjMyLCAxMDAlLCA1MCUpIiBkPSJNMjAxLjA3MyAxMjcuNDcyYTY2LjUgNjYuNSAwIDAwLS4yMi0xLjcyNyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIzMywgMTAwJSwgNTAlKSIgZD0iTTIwMS4xOTQgMTI4LjYyNmE2Ni41IDY2LjUgMCAwMC0uMTktMS43MyIvPjxwYXRoIHN0cm9rZT0iaHNsKDIzNCwgMTAwJSwgNTAlKSIgZD0iTTIwMS4yOTUgMTI5Ljc4MmE2Ni41IDY2LjUgMCAwMC0uMTYtMS43MzMiLz48cGF0aCBzdHJva2U9ImhzbCgyMzUsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuMzc2IDEzMC45NGE2Ni41IDY2LjUgMCAwMC0uMTMtMS43MzYiLz48cGF0aCBzdHJva2U9ImhzbCgyMzYsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuNDM3IDEzMi4xYTY2LjUgNjYuNSAwIDAwLS4wOTktMS43MzkiLz48cGF0aCBzdHJva2U9ImhzbCgyMzcsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuNDc3IDEzMy4yNmE2Ni41IDY2LjUgMCAwMC0uMDY4LTEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCgyMzgsIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuNDk3IDEzNC40MmE2Ni41IDY2LjUgMCAwMC0uMDM4LTEuNzQiLz48cGF0aCBzdHJva2U9ImhzbCgyMzksIDEwMCUsIDUwJSkiIGQ9Ik0yMDEuNDk3IDEzNS41OGE2Ni41IDY2LjUgMCAwMC0uMDA3LTEuNzQiLz48L2c+PGNpcmNsZSBjeD0iMTM1IiBjeT0iMTM1IiByPSIxMzMiIGZpbGw9InVybCgjYSkiIGNsYXNzPSJJcm9XaGVlbFNhdHVyYXRpb24iLz48Y2lyY2xlIGN4PSIxMzUiIGN5PSIxMzUiIHI9IjEzMyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZmZmIiBzdHJva2Utd2lkdGg9IjIiIGNsYXNzPSJJcm9XaGVlbEJvcmRlciIvPjwvc3ZnPg=='; + + dialog.querySelector('.satus-scrollbar__content').appendChild(close); + dialog.querySelector('.satus-scrollbar__content').appendChild(component_canvas); + + document.body.appendChild(dialog); + }); + + component.appendChild(component_value); + + return component; +}; +/*-------------------------------------------------------------- +>>> DIALOG +--------------------------------------------------------------*/ + +Satus.components.dialog = function(element) { + var component = document.createElement('div'), + component_scrim = document.createElement('div'), + component_surface = document.createElement('div'), + component_scrollbar = Satus.components.scrollbar(component_surface), + options = element.options || {}; + + component_scrim.className = 'satus-dialog__scrim'; + component_surface.className = 'satus-dialog__surface'; + + for (var key in element) { + Satus.render(element[key], component_scrollbar); + } + + function close() { + window.removeEventListener('keydown', keydown); + + component.classList.add('satus-dialog--closing'); + + if (typeof element.onclose === 'function') { + element.onclose(); + } + + setTimeout(function() { + component.remove(); + }, Satus.getAnimationDuration(component_surface)); + } + + function keydown(event) { + if (event.keyCode === 27) { + event.preventDefault(); + close(); + } + + if (event.keyCode === 9) { + var elements = component_surface.querySelectorAll('button, input'), + focused = false; + + event.preventDefault(); + + for (var i = 0, l = elements.length; i < l; i++) { + if (elements[i] === document.activeElement && elements[i + 1]) { + elements[i + 1].focus(); + + focused = true; + + i = l; + } + } + + if (focused === false) { + elements[0].focus(); + } + } + } + + component_scrim.addEventListener('click', close); + window.addEventListener('keydown', keydown); + + component.appendChild(component_scrim); + component.appendChild(component_surface); + + // OPTIONS + + if (options.left) { + component_surface.style.left = options.left + 'px'; + } + + if (options.top) { + component_surface.style.top = options.top + 'px'; + } + + if (options.width) { + component_surface.style.width = options.width + 'px'; + } + + if (options.height) { + component_surface.style.height = options.height + 'px'; + } + + // END OPTIONS + + return component; +}; +/*-------------------------------------------------------------- +>>> FOLDER +--------------------------------------------------------------*/ + +Satus.components.folder = function(object) { + var component = document.createElement('button'); + + component.object = object; + + component.classList.add('satus-button'); + + component.addEventListener('click', function() { + var parent = document.querySelector(component.object.parent) || document.querySelector('.satus-main'); + + if (!component.object.parent || !parent.classList.contains('satus-main')) { + while (!parent.classList.contains('satus-main')) { + parent = parent.parentNode; + } + } + + parent.open(this.object, object.onopen); + }); + + if (Satus.isset(object.label)) { + var component_label = document.createElement('span'); + + component_label.className = 'satus-folder__label'; + component_label.innerText = Satus.locale.getMessage(object.label); + + component.appendChild(component_label); + } + + return component; +}; +/*-------------------------------------------------------------- +>>> HEADER +--------------------------------------------------------------*/ + +Satus.components.header = function(object) { + var component = document.createElement('header'); + + for (var key in object) { + Satus.render(object[key], component); + } + + return component; +}; +/*-------------------------------------------------------------- +>>> LIST +--------------------------------------------------------------*/ + +Satus.components.list = function(object) { + var ul = document.createElement('ul'); + + if (object.compact === true) { + ul.classList.add('satus-list'); + ul.classList.add('satus-list--compact'); + } + + for (var key in object) { + if (Satus.isset(object[key].type)) { + var li = document.createElement('li'); + + if (object.sortable === true) { + function mousedown(event) { + if (event.button === 0) { + var self = this, + dragging = false, + clone = false, + current_index = Array.from(self.parentNode.children).indexOf(self), + bounding = this.getBoundingClientRect(), + offset_x = event.clientX - bounding.left, + offset_y = event.clientY - bounding.top; + + function mousemove(event) { + if (dragging === false) { + clone = self.cloneNode(true); + + Satus.cloneNodeStyles(self, clone); + clone.style.position = 'fixed'; + clone.style.pointerEvents = 'none'; + clone.style.backgroundColor = '#fff'; + self.style.visibility = 'hidden'; + + document.body.appendChild(clone); + + dragging = true; + } + + var x = bounding.left, //event.clientX - offset_x + y = event.clientY - offset_y, + index = Math.floor(y / self.offsetHeight) - 1; + + clone.style.left = x + 'px'; + clone.style.top = y + 'px'; + + if (index !== current_index && self.parentNode.children[index]) { + var new_clone = self.cloneNode(true); + + if (index > 0) { + self.parentNode.insertBefore(new_clone, self.parentNode.children[index].nextSibling); + } else { + self.parentNode.insertBefore(new_clone, self.parentNode.children[index]); + } + + self.remove(); + + self = new_clone; + + self.addEventListener('mousedown', mousedown); + + if (typeof object.onchange === 'function') { + object.onchange(current_index, index); + } + + current_index = index; + } + } + + function mouseup(event) { + if (clone) { + clone.remove(); + self.style.visibility = ''; + } + + window.removeEventListener('mousemove', mousemove); + window.removeEventListener('mouseup', mouseup); + } + + window.addEventListener('mousemove', mousemove); + window.addEventListener('mouseup', mouseup); + } + } + + li.addEventListener('mousedown', mousedown); + } + + Satus.render(object[key], li); + + ul.appendChild(li); + } + } + + return ul; +}; +/*-------------------------------------------------------------- +>>> MAIN +--------------------------------------------------------------*/ + +Satus.components.main = function(object) { + var component = document.createElement('main'), + component_container = document.createElement('div'), + component_scrollbar = Satus.components.scrollbar(component_container, object.scrollbar); + + component.history = [object]; + + component.back = function() { + var container = this.querySelector('.satus-main__container'), + component_container = document.createElement('div'), + component_scrollbar = Satus.components.scrollbar(component_container); + + container.classList.add('satus-main__container--fade-out-right'); + component_container.className = 'satus-main__container satus-main__container--fade-in-left'; + + this.history.pop(); + + for (var key in this.history[this.history.length - 1]) { + Satus.render(this.history[this.history.length - 1][key], component_scrollbar); + } + + this.appendChild(component_container); + + if (this.historyListener) { + this.historyListener(component_container); + } + + if (this.history[this.history.length - 1].onopen) { + component_scrollbar.onopen = this.history[this.history.length - 1].onopen; + + component_scrollbar.onopen(); + } + + setTimeout(function() { + container.remove(); + }, Satus.getAnimationDuration(container)); + }; + + component.open = function(element, callback) { + var container = this.querySelector('.satus-main__container'), + component_container = document.createElement('div'), + component_scrollbar = Satus.components.scrollbar(component_container); + + container.classList.add('satus-main__container--fade-out-left'); + component_container.className = 'satus-main__container satus-main__container--fade-in-right'; + + this.history.push(element); + + for (var key in this.history[this.history.length - 1]) { + Satus.render(this.history[this.history.length - 1][key], component_scrollbar); + } + + this.appendChild(component_container); + + if (this.historyListener) { + this.historyListener(component_container); + } + + if (callback) { + component_scrollbar.onopen = callback; + + component_scrollbar.onopen(); + } + + setTimeout(function() { + container.remove(); + }, Satus.getAnimationDuration(container)); + }; + + component_container.className = 'satus-main__container'; + + if (object.on && object.on.change) { + component.historyListener = object.on.change; + } + + if (component.historyListener) { + component.historyListener(component_container); + } + + for (var key in object) { + Satus.render(object[key], component_scrollbar); + } + + component.appendChild(component_container); + + return component; +}; +/*----------------------------------------------------------------------------- +>>> SCROLL BAR +-----------------------------------------------------------------------------*/ + +Satus.components.scrollbar = function(parent, enabled) { + if (enabled === false) { + return parent; + } + + var component = document.createElement('div'), + component_wrapper = document.createElement('div'), + component_content = document.createElement('div'), + component_thumb = document.createElement('div'); + + component.className = 'satus-scrollbar'; + component_wrapper.className = 'satus-scrollbar__wrapper'; + component_content.className = 'satus-scrollbar__content'; + component_thumb.className = 'satus-scrollbar__thumb'; + + + // RESIZE + + function resize() { + component_content.style.width = component.offsetWidth + 'px'; + component_wrapper.style.height = component.offsetHeight + 'px'; + + if (component_wrapper.scrollHeight > component_wrapper.offsetHeight) { + component_thumb.style.height = component_wrapper.offsetHeight / component_wrapper.scrollHeight * component_wrapper.offsetHeight + 'px'; + } + } + + window.addEventListener('resize', resize); + + new MutationObserver(resize).observe(component_content, { + subtree: true, + childList: true + }); + + + // HOVER + + component.timeout = false; + + function active() { + if (component.timeout) { + clearTimeout(component.timeout); + + component.timeout = false; + } + + component.classList.add('active'); + + component.timeout = setTimeout(function() { + component.classList.remove('active'); + + component.timeout = false; + }, 1000); + } + + component.addEventListener('mousemove', active); + + + // SCROLL + + component_wrapper.addEventListener('scroll', function(event) { + active(); + + component_thumb.style.top = Math.floor(component_wrapper.scrollTop * (component_wrapper.offsetHeight - component_thumb.offsetHeight) / (component_wrapper.scrollHeight - component_wrapper.offsetHeight)) + 'px'; + }); + + component_thumb.addEventListener('mousedown', function(event) { + var offsetY = event.layerY; + + if (event.button !== 0) { + return false; + } + + function mousemove(event) { + var offset = 100 / ((component.offsetHeight - component_thumb.offsetHeight) / (event.clientY - offsetY - component.getBoundingClientRect().top)), + scroll = component_wrapper.scrollHeight - component.offsetHeight; + + component_wrapper.scrollTop = scroll / 100 * offset; + + event.preventDefault(); + + return false; + } + + function mouseup() { + window.removeEventListener('mouseup', mouseup); + window.removeEventListener('mousemove', mousemove); + } + + window.addEventListener('mouseup', mouseup); + window.addEventListener('mousemove', mousemove); + }); + + component_wrapper.appendChild(component_content); + component.appendChild(component_wrapper); + component.appendChild(component_thumb); + + parent.appendChild(component); + + return component_content; +}; +/*-------------------------------------------------------------- +>>> SECTION +--------------------------------------------------------------*/ + +Satus.components.section = function(element) { + var component = document.createElement('section'); + + for (var key in element) { + Satus.render(element[key], component); + } + + return component; +}; +/*-------------------------------------------------------------- +>>> SELECT +--------------------------------------------------------------*/ + +Satus.components.select = function(element) { + var component = document.createElement('button'), + component_label = document.createElement('span'), + component_value = document.createElement('span'), + label = Satus.locale.getMessage(element.label); + + component.classList.add('satus-button'); + + component_label.className = 'satus-select__label'; + component_label.innerText = label; + + component_value.className = 'satus-select__value'; + + if (element.storage_key) { + var value = Satus.storage.get(element.storage_key); + + component.dataset.storageKey = element.storage_key; + + for (var i = 0, l = element.options.length; i < l; i++) { + if (value === element.options[i].value) { + value = element.options[i].label; + } + } + + component_value.innerText = Satus.locale.getMessage(value || element.options[0].label); + } + + component.onclick = function() { + var position = this.getBoundingClientRect(), + dialog = { + type: 'dialog', + class: 'satus-dialog--select-component' + }; + + for (var key in element.options) { + dialog[key] = element.options[key]; + + dialog[key].type = 'button'; + dialog[key].dataset = {}; + dialog[key].dataset.key = element.options[key].label; + dialog[key].dataset.value = element.options[key].value; + dialog[key].onclick = function() { + component_value.innerText = Satus.locale.getMessage(this.dataset.key); + + Satus.storage.set(component.dataset.storageKey, this.dataset.value); + + var parent = this.parentNode; + + while (!parent.classList.contains('satus-dialog')) { + parent = parent.parentNode; + } + + parent.querySelector('.satus-dialog__scrim').click(); + }; + } + + Satus.render(dialog); + }; + + component.appendChild(component_label); + component.appendChild(component_value); + + return component; +}; +/*------------------------------------------------------------------------------ +>>> SHORTCUT +------------------------------------------------------------------------------*/ + +Satus.components.shortcut = function(element) { + var self = this, + value = (Satus.storage.get(element.storage_key) ? JSON.parse(Satus.storage.get(element.storage_key)) : false) || element.value || {}, + component = document.createElement('div'), + component_label = document.createElement('span'), + component_value = document.createElement('span'), + mousewheel_timeout = false, + mousewheel_only = false; + + component_label.className = 'satus-shortcut__label'; + component_value.className = 'satus-shortcut__value'; + + function update(canvas) { + let text_value = [], + keys_value = []; + + if (value.altKey === true) { + text_value.push('Alt'); + keys_value.push('
Alt
'); + } + + if (value.ctrlKey === true) { + text_value.push('Ctrl'); + keys_value.push('
Ctrl
'); + } + + if (value.shiftKey === true) { + text_value.push('Shift'); + keys_value.push('
Shift
'); + } + + if (value.key === ' ') { + text_value.push('Space bar'); + keys_value.push('
Space bar
'); + + } else if (typeof value.key === 'string' && ['Shift', 'Control', 'Alt'].indexOf(value.key) === -1) { + if (value.key === 'ArrowUp') { + text_value.push('↑'); + keys_value.push('
'); + } else if (value.key === 'ArrowRight') { + text_value.push('→'); + keys_value.push('
'); + } else if (value.key === 'ArrowDown') { + text_value.push('↓'); + keys_value.push('
'); + } else if (value.key === 'ArrowLeft') { + text_value.push('←'); + keys_value.push('
'); + } else { + let key = value.key.toUpperCase(); + + text_value.push(key); + keys_value.push('
' + key + '
'); + } + } + + if (value.wheel) { + keys_value.push('
'); + } + + component_value.innerText = text_value.join('+'); + + if (canvas) { + if (keys_value.length > 0) { + canvas.innerHTML = keys_value.join('
'); + } else { + canvas.innerText = Satus.locale.getMessage('pressAnyKeyOrUseMouseWheel'); + } + } + } + + update(); + + component_value.dataset.value = component_value.innerText; + + component_label.innerText = Satus.locale.getMessage(element.label); + + component.addEventListener('click', function() { + let component_dialog = document.createElement('div'), + component_dialog_label = document.createElement('span'), + component_scrim = document.createElement('div'), + component_surface = document.createElement('div'), + component_canvas = document.createElement('div'), + component_section = document.createElement('section'), + component_button_reset = document.createElement('div'), + component_button_cancel = document.createElement('div'), + component_button_save = document.createElement('div'); + + component_dialog.className = 'satus-dialog satus-dialog_open'; + component_dialog_label.className = 'satus-shortcut-dialog-label'; + component_scrim.className = 'satus-dialog__scrim'; + component_surface.className = 'satus-dialog__surface satus-dialog__surface_shortcut'; + component_canvas.className = 'satus-shortcut__canvas'; + component_section.className = 'satus-section satus-section--align-end satus-section_shortcut'; + component_button_reset.className = 'satus-button satus-button_shortcut'; + component_button_cancel.className = 'satus-button satus-button_shortcut'; + component_button_save.className = 'satus-button satus-button_shortcut'; + + component_dialog_label.innerText = component_label.innerText; + component_button_reset.innerText = Satus.locale.getMessage('reset'); + component_button_cancel.innerText = Satus.locale.getMessage('cancel'); + component_button_save.innerText = Satus.locale.getMessage('save'); + + update(component_canvas); + + function keydown(event) { + event.preventDefault(); + event.stopPropagation(); + + mousewheel_only = false; + clearTimeout(mousewheel_timeout); + + value = { + key: event.key, + keyCode: event.keyCode, + shiftKey: event.shiftKey, + ctrlKey: event.ctrlKey, + altKey: event.altKey + }; + + update(component_canvas); + + return false; + } + + function mousewheel(event) { + event.stopPropagation(); + + if (mousewheel_only === true) { + delete value.shiftKey; + delete value.altKey; + delete value.ctrlKey; + delete value.keyCode; + delete value.key; + } + + clearTimeout(mousewheel_timeout); + + mousewheel_timeout = setTimeout(function() { + mousewheel_only = true; + }, 300); + + value.wheel = event.deltaY; + + update(component_canvas); + + return false; + } + + window.addEventListener('keydown', keydown); + window.addEventListener('mousewheel', mousewheel); + + function close(clear = true) { + window.removeEventListener('keydown', keydown); + window.removeEventListener('mousewheel', mousewheel); + + if (clear === true) { + component_value.innerText = component_value.dataset.value; + } + + component_dialog.classList.remove('satus-dialog_open'); + + setTimeout(function() { + component_dialog.remove(); + }, Number(document.defaultView.getComputedStyle(component_dialog, '').getPropertyValue('animation-duration').replace(/[^0-9.]/g, '') * 1000)); + } + + component_scrim.addEventListener('click', close); + component_button_reset.addEventListener('click', function() { + Satus.storage.set(element.storage_key, null); + close(); + value = (Satus.storage.get(element.storage_key) ? JSON.parse(Satus.storage.get(element.storage_key)) : false) || object.value || {}; + update(); + }); + component_button_cancel.addEventListener('click', close); + component_button_save.addEventListener('click', function() { + Satus.storage.set(element.storage_key, JSON.stringify(value)); + close(false); + }); + + component_section.appendChild(component_button_reset); + component_section.appendChild(component_button_cancel); + component_section.appendChild(component_button_save); + + component_surface.appendChild(component_dialog_label); + component_surface.appendChild(component_canvas); + component_surface.appendChild(component_section); + + component_dialog.appendChild(component_scrim); + component_dialog.appendChild(component_surface); + + document.body.appendChild(component_dialog); + }); + + component.appendChild(component_label); + component.appendChild(component_value); + + return component; +}; +/*-------------------------------------------------------------- +>>> SLIDER +--------------------------------------------------------------*/ + +Satus.components.slider = function(element) { + var component = document.createElement('div'); + + // LABEL + if (Satus.isset(element.label)) { + var component_label = document.createElement('span'); + + component_label.className = 'satus-slider__label'; + component_label.innerText = Satus.locale.getMessage(element.label); + + component.appendChild(component_label); + } + + + // RANGE + var component_range = document.createElement('input'); + + component_range.type = 'range'; + component_range.className = 'satus-slider__range'; + component_range.min = element.min || 0; + component_range.max = element.max || 10; + component_range.step = element.step || 1; + + component_range.oninput = function() { + var track = this.parentNode.querySelector('.satus-slider__track'), + thumb = this.parentNode.querySelector('.satus-slider__thumb'), + min = Number(this.min) || 0, + max = Number(this.max) || 1, + step = Number(this.step) || 1, + value = Number(this.value) || 0, + offset = (value - min) / (max - min) * 100; + + track.style.width = 'calc(' + offset + '% - ' + Math.floor(offset * 12 / 100) + 'px)'; + + Satus.storage.set(this.dataset.storageKey, Number(this.value)); + + component_thumb.dataset.value = this.value; + + if (component.onchange) { + component.onchange(Number(this.value)); + } + }; + + component.change = function(value) { + component_range.value = value; + + component_thumb.dataset.value = value; + + component_range.oninput(); + }; + + component.addEventListener('mousedown', function() { + function mousemove() { + component.classList.add('satus-slider--dragging'); + } + + function mouseup() { + component.classList.remove('satus-slider--dragging'); + + window.removeEventListener('mousemove', mousemove); + window.removeEventListener('mouseup', mouseup); + } + + window.addEventListener('mousemove', mousemove); + window.addEventListener('mouseup', mouseup); + }); + + if (element.onchange) { + component.onchange = element.onchange; + } + + component.appendChild(component_range); + + + // CONTAINER + var component_container = document.createElement('div'); + + component_container.className = 'satus-slider__container'; + + component.appendChild(component_container); + + + // TRACK + var component_track_container = document.createElement('div'), + component_track = document.createElement('div'); + + component_track_container.className = 'satus-slider__track-container'; + component_track.className = 'satus-slider__track'; + + component_track_container.appendChild(component_track); + component_container.appendChild(component_track_container); + + + // FOCUS RING + var component_ring = document.createElement('div'); + + component_ring.className = 'satus-slider__ring'; + + component_track.appendChild(component_ring); + + + // THUMB + var component_thumb = document.createElement('div'); + + component_thumb.className = 'satus-slider__thumb'; + + component_track.appendChild(component_thumb); + + if (element.storage_key) { + var value = Satus.storage.get(element.storage_key) || element.value; + + component_range.dataset.storageKey = element.storage_key; + + if (value) { + component_range.value = value; + + if (!Satus.isset(value)) { + value = element.value; + } + + var offset = (Number(component_range.value) - Number(component_range.min)) / (Number(component_range.max) - Number(component_range.min)) * 100; + + component_track.style.width = 'calc(' + offset + '% - ' + Math.floor(offset * 12 / 100) + 'px)'; + component_thumb.dataset.value = value; + } else { + component_range.value = 0; + component_thumb.dataset.value = 0; + } + } + + + return component; +}; +/*-------------------------------------------------------------- +>>> SWITCH +--------------------------------------------------------------*/ + +Satus.components.switch = function(element) { + var component = document.createElement('div'), + value; + + // LABEL + if (Satus.isset(element.label)) { + var component_label = document.createElement('span'); + + component_label.className = 'satus-switch__label'; + component_label.innerText = Satus.locale.getMessage(element.label); + + component.appendChild(component_label); + } + + + // INPUT + var component_input = document.createElement('input'); + + component_input.type = 'checkbox'; + component_input.className = 'satus-switch__input'; + + if (element.storage_key) { + value = Satus.storage.get(element.storage_key); + + component_input.dataset.storageKey = element.storage_key; + } + + if (!Satus.isset(value)) { + value = element.value; + } + + if (value) { + component_input.checked = value; + } + + component_input.addEventListener('change', function() { + Satus.storage.set(this.dataset.storageKey, this.checked); + }); + + component.appendChild(component_input); + + + // TRACK + var component_track = document.createElement('div'); + + component_track.className = 'satus-switch__track'; + + component.appendChild(component_track); + + + // MOUSE MOVE + component_track.addEventListener('mousedown', function(event) { + var prevent = false, + difference = 0; + + function click(event) { + event.preventDefault(); + event.stopPropagation(); + + component.removeEventListener('click', click); + + return false; + } + + function mousemove(event) { + var checkbox = component.querySelector('input'), + movement = event.movementX; + + if (movement * difference < 0) { + difference = 0; + } else { + difference += movement; + + if (prevent === false) { + prevent = true; + component.addEventListener('click', click); + } + } + + if (difference < -5) { + checkbox.checked = false; + } else if (difference > 5) { + checkbox.checked = true; + } + } + + function mouseup(event) { + window.removeEventListener('mousemove', mousemove); + window.removeEventListener('mouseup', mouseup); + } + + window.addEventListener('mousemove', mousemove); + window.addEventListener('mouseup', mouseup); + }); + + + // TOUCH MOVE + component_track.addEventListener('touchstart', function(event) { + var previous_x = 0, + difference = 0; + + function mousemove(event) { + var checkbox = component.querySelector('input'), + movement = event.touches[0].clientX - previous_x; + + previous_x = event.touches[0].clientX; + + if (movement * difference < 0) { + difference = 0; + } else { + difference += movement; + } + + if (difference < -5) { + checkbox.checked = false; + } else if (difference > 5) { + checkbox.checked = true; + } + } + + function mouseup(event) { + window.removeEventListener('touchmove', mousemove); + window.removeEventListener('touchend', mouseup); + } + + window.addEventListener('touchmove', mousemove); + window.addEventListener('touchend', mouseup); + }); + + + return component; +}; +Satus.components.table = function(item) { + var component = document.createElement('div'), + component_head = document.createElement('div'), + component_body = document.createElement('div'), + component_scrollbar = Satus.components.scrollbar(component_body, item.scrollbar), + table = document.createElement('table'), + thead = document.createElement('thead'), + thead_tr = document.createElement('tr'), + tbody = document.createElement('tbody'); + + component_head.className = 'satus-table__head'; + component_body.className = 'satus-table__body'; + + function update(data) { + var pages = Math.ceil(component.data.length / component.paging), + start = Math.max((component.pagingIndex - 1) * component.paging, 0), + end = component.pagingIndex * component.paging; + + if (end > data.length) { + end = data.length; + } else if (end === 0) { + end = component.paging; + } + + tbody.innerHTML = ''; + + if (data) { + for (var i = start, l = end; i < l; i++) { + if (data[i]) { + var tr = document.createElement('tr'); + + for (var j = 0, k = data[i].length; j < k; j++) { + var td = document.createElement('td'), + span = document.createElement('span'); + + span.innerText = data[i][j]; + + td.appendChild(span); + tr.appendChild(td); + } + + tbody.appendChild(tr); + } + } + } + + component.pagingUpdate(); + } + + function sortArray(array, index, mode) { + if (mode === 'asc') { + if (typeof array[0][index] === 'number') { + sorted = array.sort(function(a, b) { + return a[index] - b[index]; + }); + } else { + sorted = array.sort(function(a, b) { + return a[index].localeCompare(b[index]); + }); + } + } else { + if (typeof array[0][index] === 'number') { + sorted = array.sort(function(a, b) { + return b[index] - a[index]; + }); + } else { + sorted = array.sort(function(a, b) { + return b[index].localeCompare(a[index]); + }); + } + } + + return array; + } + + function sort() { + var mode = this.dataset.sorting, + index = Array.prototype.indexOf.call(this.parentElement.children, this), + sorted; + + if (mode === 'none') { + mode = 'asc'; + } else if (mode === 'asc') { + mode = 'desc'; + } else if (mode === 'desc') { + mode = 'asc'; + } + + if (this.parentNode.querySelector('div[data-sorting=asc], div[data-sorting=desc]')) { + this.parentNode.querySelector('div[data-sorting=asc], div[data-sorting=desc]').dataset.sorting = 'none'; + } + + this.dataset.sorting = mode; + + sorted = sortArray(component.data, index, mode); + + update(sorted); + } + + function resize() { + for (var i = 0, l = component_head.children.length; i < l; i++) { + component_head.children[i].style.width = thead.querySelectorAll('th')[i].offsetWidth + 'px'; + } + } + + for (var i = 0, l = item.columns.length; i < l; i++) { + var column = document.createElement('div'), + th = document.createElement('th'); + + column.dataset.sorting = 'none'; + column.addEventListener('click', sort); + column.innerHTML = '' + item.columns[i].title + ''; + th.innerText = item.columns[i].title; + + component_head.appendChild(column); + thead_tr.appendChild(th); + } + + thead.appendChild(thead_tr); + table.appendChild(thead); + table.appendChild(tbody); + component_scrollbar.appendChild(table); + + component.appendChild(component_head); + component.appendChild(component_body); + + component.data = item.data; + component.paging = item.paging; + component.pagingIndex = 0; + + component.update = function(data, index, mode) { + if (Satus.isset(data)) { + this.data = data; + } + + if (Satus.isset(index) && Satus.isset(mode)) { + this.querySelectorAll('.satus-table__head > div')[index].dataset.sorting = mode; + + this.data = sortArray(this.data, index, mode); + } + + update(this.data); + }; + + + // PAGING + + function pagingUpdate() { + if (typeof this.paging === 'number') { + var pages = Math.ceil(this.data.length / this.paging); + + this.querySelector('.satus-table__paging').innerHTML = ''; + + for (var i = 1; i <= pages; i++) { + var button = document.createElement('button'); + + if (i === (this.pagingIndex || 1)) { + button.className = 'active'; + } + + button.innerText = i; + button.parentComponent = this; + button.addEventListener('click', function() { + if (this.parentNode.querySelector('button.active')) { + this.parentNode.querySelector('button.active').classList.remove('active'); + } + + this.classList.add('active'); + + this.parentComponent.pagingIndex = Number(this.innerText); + this.parentComponent.update(this.parentComponent.data); + }); + + this.querySelector('.satus-table__paging').appendChild(button); + } + } + } + + component.pagingUpdate = pagingUpdate; + + component_paging = document.createElement('div'); + + component_paging.className = 'satus-table__paging'; + + component_scrollbar.appendChild(component_paging); + + // END PAGING + + + var sorting; + + for (var i = 0, l = item.columns.length; i < l; i++) { + if (item.columns[i].hasOwnProperty('sorting')) { + component_head.querySelectorAll('div')[i].dataset.sorting = item.columns[i].sorting; + + update(sortArray(item.data, i, item.columns[i].sorting)); + + i = l; + } + } + + setTimeout(resize); + + return component; +}; +/*-------------------------------------------------------------- +>>> TEXT +--------------------------------------------------------------*/ + +Satus.components.text = function(element) { + var component = document.createElement('span'); + + if (Satus.isset(element.label)) { + var component_label = document.createElement('span'); + + component_label.className = 'satus-text__label'; + component_label.innerText = Satus.locale.getMessage(element.label); + + component.appendChild(component_label); + } + + if (Satus.isset(element.value)) { + var component_value = document.createElement('span'); + + component_value.className = 'satus-text__value'; + component_value.innerText = Satus.locale.getMessage(element.value); + + component.appendChild(component_value); + } + + return component; +}; +/*-------------------------------------------------------------- +>>> TEXT FIELD +--------------------------------------------------------------*/ + +Satus.components.textField = function(element) { + var component = element.rows > 1 ? document.createElement('textarea') : document.createElement('input'); + + component.type = 'text'; + + return component; }; \ No newline at end of file diff --git a/src/css/basic.css b/src/css/basic.css index 5253d62..6f59c73 100644 --- a/src/css/basic.css +++ b/src/css/basic.css @@ -3,22 +3,27 @@ ----------------------------------------------------------------- 1.0 Fonts 2.0 Body +3.0 Button ---------------------------------------------------------------*/ /*--------------------------------------------------------------- 1.0 FONTS ---------------------------------------------------------------*/ -@font-face { - font-family: 'Open Sans'; - font-weight: 400; - src: url('assets/fonts/OpenSans-Regular.ttf'); +@font-face +{ + font-family: 'Open Sans'; + font-weight: 400; + + src: url('assets/fonts/OpenSans-Regular.ttf'); } -@font-face { - font-family: 'Open Sans'; - font-weight: 700; - src: url('assets/fonts/OpenSans-SemiBold.ttf'); +@font-face +{ + font-family: 'Open Sans'; + font-weight: 700; + + src: url('assets/fonts/OpenSans-SemiBold.ttf'); } @@ -26,14 +31,80 @@ 2.0 BODY ---------------------------------------------------------------*/ -body { - font-family: 'Open Sans', sans-serif; - font-size: .875rem; - display: flex; - overflow: hidden; - flex-direction: column; - width: 18.75rem; - height: 31.25rem; - margin: 0; - background-color: #2c2b2c; -} \ No newline at end of file +body +{ + font-family: 'Open Sans', sans-serif; + font-size: .875rem; + + width: 300px; + height: 500px; + margin: 0; +} + +.satus +{ + position: absolute; + z-index: 1; + top: -250px; + left: -350px; + + overflow: hidden; + + width: 1000px; + height: 1000px; + + transition: all .5s linear, opacity .4s; + + opacity: 1; + border-radius: 50%; + background-color: var(--satus-theme-main); +} + +.satus__wrapper +{ + position: absolute; + top: 250px; + left: 350px; + + display: flex; + flex-direction: column; + + width: 300px; + height: 500px; + + transition: .5s linear; +} + + + + +.satus.loading +{ + top: 14px; + left: calc(100% - 64px); + + width: 32px; + height: 32px; + + transition: 0s linear; + + opacity: 0; +} + +.satus.loading .satus__wrapper +{ + top: -14px; + left: -236px; + + transition: 0s linear; +} + + +/*--------------------------------------------------------------- +3.0 BUTTON +---------------------------------------------------------------*/ + +button +{ + font-family: 'Open Sans', sans-serif; +} diff --git a/src/css/header.css b/src/css/header.css index a5d8b10..ec7a23b 100644 --- a/src/css/header.css +++ b/src/css/header.css @@ -13,9 +13,11 @@ 1.0 HEADER ---------------------------------------------------------------*/ -.satus-header { - z-index: 1; - box-shadow: 0 2px 4px rgba(0, 0, 0, .1); +.satus-header +{ + z-index: 1; + + box-shadow: 0 2px 4px rgba(0, 0, 0, .1); } @@ -23,14 +25,16 @@ 2.0 BUTTONS ---------------------------------------------------------------*/ -.satus-header .satus-button { - width: 36px; - height: 36px; - padding: 6px; +.satus-header .satus-button +{ + width: 36px; + height: 36px; + padding: 6px; } -.satus-header .satus-button::before { - border-radius: 50%; +.satus-header .satus-button::before +{ + border-radius: 50%; } @@ -38,17 +42,20 @@ 3.0 BACK BUTTON ---------------------------------------------------------------*/ -.satus-button--back { - position: absolute; +.satus-button--back +{ + position: absolute; } -.satus-button--back svg { - fill: none; - stroke: currentColor; +.satus-button--back svg +{ + fill: none; + stroke: currentColor; } -body[data-appearance='home'] .satus-button--back { - visibility: hidden; +body[data-appearance='home'] .satus-button--back +{ + visibility: hidden; } @@ -56,16 +63,15 @@ body[data-appearance='home'] .satus-button--back { 4.0 TITLE ---------------------------------------------------------------*/ -.satus-text--title { - font-size: .9375rem; - font-weight: 600; - position: absolute; - left: 56px; - letter-spacing: .0125em; +.satus-text--title +{ + position: absolute; + left: 56px; } -body[data-appearance='home'] .satus-text--title { - left: 14px; +body[data-appearance='home'] .satus-text--title +{ + left: 14px; } @@ -73,8 +79,9 @@ body[data-appearance='home'] .satus-text--title { 5.0 RIGHT SECTION ---------------------------------------------------------------*/ -.satus-section--align-end { - justify-content: flex-end; +.satus-section--align-end +{ + justify-content: flex-end; } @@ -82,22 +89,27 @@ body[data-appearance='home'] .satus-text--title { 6.0 SWITCH ---------------------------------------------------------------*/ -.satus-switch--night-mode { - padding: 0; +.satus-switch--night-mode +{ + padding: 0; } -.satus-switch--night-mode:hover { - background-color: transparent; +.satus-switch--night-mode:hover +{ + background-color: transparent; } -.satus-switch--night-mode[data-value=false]>svg:last-child { - opacity: .5; +.satus-switch--night-mode[data-value=false] > svg:last-child +{ + opacity: .5; } -.satus-switch--night-mode[data-value=true]>svg:first-child { - opacity: .5; +.satus-switch--night-mode[data-value=true] > svg:first-child +{ + opacity: .5; } -.satus-switch--night-mode .satus-switch__track { - margin: 0 4px; -} \ No newline at end of file +.satus-switch--night-mode .satus-switch__track +{ + margin: 0 4px; +} diff --git a/src/css/main.css b/src/css/main.css index fdf1bc6..eeb7aad 100644 --- a/src/css/main.css +++ b/src/css/main.css @@ -17,13 +17,9 @@ 1.0 MAIN ---------------------------------------------------------------*/ -.satus-main { - flex: 1; -} - -.satus-main, -.satus-main__container { - background-color: #2c2b2c; +.satus-main +{ + flex: 1; } @@ -31,21 +27,23 @@ 2.0 SECTION ---------------------------------------------------------------*/ -.satus-main .satus-section { - display: block; - width: calc(100% - 16px); - max-width: 900px; - margin: 8px auto; - padding: 8px 0; - color: var(--satus-theme-on-surface, #777); - border: 1px solid rgba(0, 0, 0, .1); - border-radius: 8px; - background-color: var(--satus-theme-surface, #fff); +.satus-main .satus-section +{ + display: block; + + width: calc(100% - 16px); + max-width: 900px; + margin: 8px auto; + padding: 8px 0; + + border: 1px solid rgba(0, 0, 0, .1); + border-radius: 8px; } -.satus-main .satus-section--message { - padding-right: 8px; - padding-left: 8px; +.satus-main .satus-section--message +{ + padding-right: 8px; + padding-left: 8px; } @@ -53,11 +51,12 @@ 3.0 BUTTON ---------------------------------------------------------------*/ -.satus-main .satus-button { - width: 100%; - height: 48px; - min-height: 48px; - padding: 0 16px; +.satus-main .satus-button +{ + width: 100%; + height: 48px; + min-height: 48px; + padding: 0 16px; } @@ -65,12 +64,13 @@ 4.0 FOLDER ---------------------------------------------------------------*/ -.satus-main .satus-folder svg { - width: 20px; - height: 20px; - margin: 0 14px 0 0; - stroke: none; - fill: var(--satus-theme-primary); +.satus-main .satus-folder svg +{ + width: 20px; + height: 20px; + margin: 0 14px 0 0; + + stroke: none; } @@ -79,17 +79,20 @@ ---------------------------------------------------------------*/ .satus-switch:hover, -.satus-switch:hover input { - cursor: pointer; +.satus-switch:hover input +{ + cursor: pointer; } -.satus-switch--night-mode { - width: auto; +.satus-switch--night-mode +{ + width: auto; } -.satus-switch__icon { - width: 20px; - height: 20px; +.satus-switch__icon +{ + width: 20px; + height: 20px; } @@ -97,8 +100,9 @@ 6.0 TEXTAREA ---------------------------------------------------------------*/ -.satus-textarea { - width: calc(100% - 32px); +.satus-textarea +{ + width: calc(100% - 32px); } @@ -106,34 +110,43 @@ 7.0 WEBSITES ---------------------------------------------------------------*/ -.satus-main__container[data-appearance=websites] .satus-section>.satus-section { - position: relative; - width: 100%; - margin: 0; - padding: 0; - border: none; - background: transparent; - box-shadow: none; +.satus-main__container[data-appearance=websites] .satus-section > .satus-section +{ + position: relative; + + width: 100%; + margin: 0; + padding: 0; + + border: none; + background: transparent; + box-shadow: none; } -.satus-main__container[data-appearance=websites] .satus-section>.satus-section .satus-switch { - position: absolute; - top: 0; - right: 0; - width: auto; - height: 100%; +.satus-main__container[data-appearance=websites] .satus-section > .satus-section .satus-switch +{ + position: absolute; + top: 0; + right: 0; + + width: auto; + height: 100%; } -.satus[data-path='main/websites'] .satus-main .satus-section { - position: relative; - padding: 0; +.satus[data-path='main/websites'] .satus-main .satus-section +{ + position: relative; + + padding: 0; } -.satus[data-path='main/websites'] .satus-main .satus-section .satus-switch { - position: absolute; - top: 0; - right: 0; - width: auto; +.satus[data-path='main/websites'] .satus-main .satus-section .satus-switch +{ + position: absolute; + top: 0; + right: 0; + + width: auto; } @@ -141,17 +154,20 @@ 8.0 LANGUAGE ---------------------------------------------------------------*/ -.satus-select[data-storage-key=language] { - padding-left: 50px; +.satus-select[data-storage-key=language] +{ + padding-left: 50px; } -.satus-select[data-storage-key=language] svg { - position: absolute; - left: 16px; - width: 20px; - height: 20px; - stroke: none; - fill: var(--satus-theme-primary); +.satus-select[data-storage-key=language] svg +{ + position: absolute; + left: 16px; + + width: 20px; + height: 20px; + + stroke: none; } @@ -159,19 +175,24 @@ 9.0 ABOUT ---------------------------------------------------------------*/ -.satus-main__container[data-appearance='about'] .satus-text { - display: flex; - box-sizing: border-box; - width: 100%; - min-height: 48px; - padding: 0 8px; - justify-content: space-between; - align-items: center; +.satus-main__container[data-appearance='about'] .satus-text +{ + display: flex; + + box-sizing: border-box; + width: 100%; + min-height: 48px; + padding: 0 8px; + + justify-content: space-between; + align-items: center; } -.satus-main__container[data-appearance='about'] .satus-text__value { - text-align: right; - opacity: .7; +.satus-main__container[data-appearance='about'] .satus-text__value +{ + text-align: right; + + opacity: .7; } @@ -179,30 +200,38 @@ 10.0 MADE WITH LOVE ---------------------------------------------------------------*/ -.made-with-love { - font-size: 13px; - position: absolute; - bottom: 16px; - left: 50%; - width: 100%; - height: auto; - min-height: auto; - padding: 0; - cursor: pointer; - transform: translateX(-50%); - text-align: center; - color: var(--satus-theme-on-surface, #d62121); - justify-content: center; -} - -.made-with-love svg { - position: relative; - top: 4px; - width: 16px; - height: 16px; - fill: #d62121; -} - -.made-with-love span { - margin: 0 0 0 4px; -} \ No newline at end of file +.made-with-love +{ + font-size: 13px; + + position: absolute; + bottom: 16px; + left: 50%; + + width: 100%; + height: auto; + min-height: auto; + padding: 0; + + cursor: pointer; + transform: translateX(-50%); + text-align: center; + + justify-content: center; +} + +.made-with-love svg +{ + position: relative; + top: 4px; + + width: 16px; + height: 16px; + + fill: #d62121; +} + +.made-with-love span +{ + margin: 0 0 0 4px; +} diff --git a/src/css/themes.css b/src/css/themes.css index f4dc0fb..306b358 100644 --- a/src/css/themes.css +++ b/src/css/themes.css @@ -9,7 +9,8 @@ 1.0 VARIABLES ---------------------------------------------------------------*/ -html { +/*.satus.dark { + --satus-theme-ripple: rgba(255, 255, 255, .04); --satus-theme-primary: #e8bd70; --background-1: #2c2b2c; --text-1: #b5b5b5; @@ -20,6 +21,29 @@ html { --background-3: #2c2b2c; --text-3: #b5b5b5; --icon-3: #b5b5b5; +}*/ + +.satus.dark +{ + --satus-theme-primary: #f6b465; + + --satus-theme-dialog: #2c2b2c; + --satus-theme-dialog-text: #b5b5b5; + + --satus-theme-header: #343334; + --satus-theme-header-text: #b5b5b5; + + --satus-theme-main: #2c2b2c; + --satus-theme-main-text: #b5b5b5; + + --satus-theme-section: #343334; + + --satus-theme-button: transparent; + + --satus-theme-scrollbar: rgba(255, 255, 255, .2); + --satus-theme-scrollbar-focus: rgba(255, 255, 255, .4); + + --satus-theme-ripple: rgba(255, 255, 255, .04); } diff --git a/src/js/header.js b/src/js/header.js index 5323f0e..75870e2 100644 --- a/src/js/header.js +++ b/src/js/header.js @@ -2,6 +2,8 @@ >>> «HEADER» TEMPLATE -----------------------------------------------------------------------------*/ +var HOSTNAME; + var Menu = { header: { type: 'header', @@ -35,7 +37,33 @@ var Menu = { after: '', value: true, onchange: function() { + var container = document.createElement('div'), + wrapper = document.createElement('div'); + this.dataset.value = this.querySelector('input').checked; + + container.classList.add('satus'); + container.classList.add('loading'); + + wrapper.classList.add('satus__wrapper'); + + if (this.querySelector('input').checked) { + container.classList.add('dark'); + } + + Satus.render(Menu, wrapper); + + container.appendChild(wrapper); + + document.body.appendChild(container); + + setTimeout(function() { + container.classList.remove('loading'); + }); + + setTimeout(function() { + container.previousElementSibling.remove(); + }, 500); }, onrender: function() { this.dataset.value = this.querySelector('input').checked; diff --git a/src/js/index.js b/src/js/index.js index 60c79e8..550a5ca 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -7,13 +7,18 @@ /*--------------------------------------------------------------- 1.0 ---------------------------------------------------------------*/ - + function init(response) { var TAB_URL = response ? new URL(response) : '', - HOSTNAME = TAB_URL.hostname || 'empty', language = Satus.storage.get('language') || 'en'; + HOSTNAME = TAB_URL.hostname || 'empty'; + Satus.storage.import(function() { + if (!Satus.isset(Satus.storage.get('mode')) || Satus.storage.get('mode') === true) { + document.querySelector('.satus').classList.add('dark'); + } + Satus.locale.import('_locales/' + language + '/messages.json', function() { Satus.modules.updateStorageKeys(Menu, function() { Menu.main.section.exclude_this_website.storage_key = 'websites/' + HOSTNAME + '/exclude_this_website'; @@ -26,10 +31,13 @@ function init(response) { Menu.main.section.styles.textfield.storage_key = 'websites/' + HOSTNAME + '/styles'; - var websites = Satus.storage.get('websites') || {}; + var websites = Satus.storage.get('websites') || {}, + count = 0; for (var key in websites) { if (key !== 'empty') { + count++; + Menu.main.section.websites.section[key] = { type: 'section', @@ -119,12 +127,12 @@ function init(response) { storage_key: 'websites/' + key + '/exclude_this_website', onrender: function(obj) { var item = this.querySelector('input'); - + item.checked = item.checked ? false : true; }, onchange: function(obj) { var item = this.querySelector('input'); - + Satus.storage.set(item.dataset.storageKey, item.checked ? false : true); } } @@ -132,7 +140,19 @@ function init(response) { } } - Satus.render(Menu, document.body); + if (count === 0) { + Menu.main.section.websites.section.message = { + type: 'text', + label: 'theListIsEmpty', + style: { + 'display': 'block', + 'text-align': 'center', + 'margin': '32px 0' + } + }; + } + + Satus.render(Menu, document.querySelector('.satus__wrapper')); }); }); }); @@ -147,4 +167,4 @@ chrome.tabs.query({ } else { init(); } -}); +}); \ No newline at end of file diff --git a/src/js/main.js b/src/js/main.js index 7da0a9c..6b2def0 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -12,7 +12,7 @@ Menu.main = { type: 'button', label: 'onlyEnableForThisWebsite', onclick: function() { - var websites = Satus.storage.get('websites'); + var websites = Satus.storage.get('websites') || {}; for (var key in websites) { if (key != HOSTNAME) { @@ -289,9 +289,6 @@ Menu.main = { before: '', label: 'settings', parent: '.satus-main__container', - onclick: function() { - document.querySelector('.satus-dialog__scrim').click(); - }, section: { type: 'section', @@ -453,62 +450,6 @@ Menu.main = { } }); } - }, - delete_youtube_cookies: { - type: 'button', - label: 'deleteYoutubeCookies', - - onclick: function() { - document.querySelector('.satus').appendChild(Satus.components.dialog({ - type: 'dialog', - - message: { - type: 'text', - label: 'thisWillRemoveAllYouTubeCookies', - style: { - 'width': '100%', - 'opacity': '.8' - } - }, - section: { - type: 'section', - class: 'controls', - style: { - 'justify-content': 'flex-end', - 'display': 'flex' - }, - - cancel: { - type: 'button', - label: 'cancel', - onclick: function() { - var scrim = document.querySelectorAll('.satus-dialog__scrim'); - - scrim[scrim.length - 1].click(); - } - }, - accept: { - type: 'button', - label: 'accept', - onclick: function() { - var scrim = document.querySelectorAll('.satus-dialog__scrim'); - - chrome.tabs.query({}, function(tabs) { - for (var i = 0, l = tabs.length; i < l; i++) { - if (tabs[i].hasOwnProperty('url')) { - chrome.tabs.sendMessage(tabs[i].id, { - name: 'delete_youtube_cookies' - }); - } - } - }); - - scrim[scrim.length - 1].click(); - } - } - } - })); - } } } }, @@ -670,4 +611,4 @@ Menu.main = { window.open('https://chrome.google.com/webstore/detail/improve-youtube-open-sour/bnomihfieiccainjcjblhegjgglakjdd'); } } -}; +}; \ No newline at end of file