Add files via upload
@@ -0,0 +1,222 @@
|
||||
function ReloadSEQTAPages() {
|
||||
chrome.tabs.query({}, function (tabs) {
|
||||
for (let tab of tabs) {
|
||||
if (tab.title.includes("SEQTA Learn")) {
|
||||
chrome.tabs.reload(tab.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
chrome.runtime.onMessage.addListener(function (request, sender) {
|
||||
if (request.type == "reloadTabs") {
|
||||
ReloadSEQTAPages();
|
||||
}
|
||||
else if (request.type == "githubTab") {
|
||||
chrome.tabs.create({ url: "github.com/OG-RandomTechChannel/BestSEQTA" });
|
||||
}
|
||||
else if (request.type == "setDefaultStorage") {
|
||||
console.log('setting default values')
|
||||
SetStorageValue(DefaultValues);
|
||||
}
|
||||
else if (request.type == "addPermissions") {
|
||||
if (typeof (chrome.declarativeContent) != 'undefined') {
|
||||
chrome.declarativeContent.onPageChanged.removeRules(undefined, function () {
|
||||
});
|
||||
}
|
||||
chrome.permissions.request({ permissions: ["declarativeContent"], origins: ["*://*/*"] }, function (granted) {
|
||||
if (granted) {
|
||||
rules = [
|
||||
{
|
||||
conditions: [
|
||||
new chrome.declarativeContent.PageStateMatcher({
|
||||
pageUrl: { urlContains: 'site.seqta.com.au', schemes: ['https'] },
|
||||
})
|
||||
],
|
||||
actions: [new chrome.declarativeContent.RequestContentScript({ js: ["SEQTA.js"] })]
|
||||
},
|
||||
{
|
||||
conditions: [
|
||||
new chrome.declarativeContent.PageStateMatcher({
|
||||
pageUrl: { urlContains: 'learn.', schemes: ['https'] },
|
||||
})
|
||||
],
|
||||
actions: [new chrome.declarativeContent.RequestContentScript({ js: ["SEQTA.js"] })]
|
||||
},
|
||||
|
||||
]
|
||||
for (let i = 0; i < rules.length; i++) {
|
||||
chrome.declarativeContent.onPageChanged.addRules([rules[i]]);
|
||||
}
|
||||
alert("Permissions granted. Reload SEQTA pages to see changes. If this workaround doesn't work, please contact the developer.");
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
var NewsJSON = {};
|
||||
|
||||
|
||||
|
||||
chrome.runtime.onMessage.addListener(
|
||||
function (request, sender, sendResponse) {
|
||||
if (request.type === "sendNews") {
|
||||
|
||||
// Gets the current date
|
||||
const date = new Date();
|
||||
// Formats the current date used send a request for timetable and notices later
|
||||
var TodayFormatted =
|
||||
date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
||||
|
||||
var from = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + (date.getDate() - 1);
|
||||
console.log(TodayFormatted)
|
||||
console.log(from)
|
||||
|
||||
// var url = `https://newsapi.org/v2/everything?sources=abc-news&from=${TodayFormatted}&sortBy=popularity&apiKey=17c0da766ba347c89d094449504e3080`;
|
||||
var url = `https://newsapi.org/v2/everything?domains=abc.net.au&from=${from}&apiKey=17c0da766ba347c89d094449504e3080`
|
||||
|
||||
function GetNews() {
|
||||
fetch(url)
|
||||
.then((result) => result.json())
|
||||
.then((response) => {
|
||||
if (response.code == 'rateLimited') {
|
||||
url += '%00';
|
||||
GetNews();
|
||||
}
|
||||
else {
|
||||
sendResponse({ news: response })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
GetNews();
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const DefaultValues = {
|
||||
onoff: true,
|
||||
animatedbk: true,
|
||||
lessonalert: true,
|
||||
notificationcollector: true,
|
||||
defaultmenuorder: [],
|
||||
menuitems: {},
|
||||
menuorder: [],
|
||||
subjectfilters: {},
|
||||
selectedColor: '#1a1a1a',
|
||||
DarkMode: true,
|
||||
shortcuts: [
|
||||
{
|
||||
name: "YouTube",
|
||||
enabled: false
|
||||
},
|
||||
{
|
||||
name: "Outlook",
|
||||
enabled: true
|
||||
},
|
||||
{
|
||||
name: "Office",
|
||||
enabled: true
|
||||
},
|
||||
{
|
||||
name: "Spotify",
|
||||
enabled: false
|
||||
},
|
||||
{
|
||||
name: "Google",
|
||||
enabled: true
|
||||
},
|
||||
{
|
||||
name: "DuckDuckGo",
|
||||
enabled: false
|
||||
},
|
||||
{
|
||||
name: "Cool Math Games",
|
||||
enabled: false
|
||||
},
|
||||
{
|
||||
name: "SACE",
|
||||
enabled: false
|
||||
},
|
||||
{
|
||||
name: "Google Scholar",
|
||||
enabled: false
|
||||
},
|
||||
{
|
||||
name: "Gmail",
|
||||
enabled: false
|
||||
},
|
||||
{
|
||||
name: "Netflix",
|
||||
enabled: false
|
||||
},
|
||||
{
|
||||
Name: "educationperfect",
|
||||
enabled: false
|
||||
}
|
||||
],
|
||||
customshortcuts: []
|
||||
}
|
||||
|
||||
function SetStorageValue(object) {
|
||||
for (var i in object) {
|
||||
chrome.storage.local.set({ [i]: object[i] })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function UpdateCurrentValues(details) {
|
||||
console.log(details)
|
||||
|
||||
chrome.storage.local.get(null, function (items) {
|
||||
var CurrentValues = items;
|
||||
|
||||
const NewValue = Object.assign({}, DefaultValues, CurrentValues)
|
||||
|
||||
function CheckInnerElement(element) {
|
||||
for (let i in element) {
|
||||
if (typeof element[i] === 'object') {
|
||||
if (typeof DefaultValues[i].length == 'undefined') {
|
||||
NewValue[i] = Object.assign({}, DefaultValues[i], CurrentValues[i])
|
||||
}
|
||||
else { // If the object is an array, turn it back after
|
||||
length = DefaultValues[i].length;
|
||||
NewValue[i] = Object.assign({}, DefaultValues[i], CurrentValues[i])
|
||||
NewArray = [];
|
||||
for (let j = 0; j < length; j++) {
|
||||
NewArray.push(NewValue[i][j]);
|
||||
|
||||
}
|
||||
NewValue[i] = NewArray;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
CheckInnerElement(DefaultValues);
|
||||
|
||||
if (items["customshortcuts"]) {
|
||||
NewValue["customshortcuts"] = items["customshortcuts"];
|
||||
}
|
||||
|
||||
SetStorageValue(NewValue);
|
||||
})
|
||||
}
|
||||
|
||||
chrome.runtime.onInstalled.addListener(function (event) {
|
||||
chrome.storage.local.remove(["justupdated"]);
|
||||
UpdateCurrentValues();
|
||||
if (/*chrome.runtime.getManifest().version > event.previousVersion || */ event.reason == 'install') {
|
||||
chrome.storage.local.set({ justupdated: true });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 926 B |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,18 @@
|
||||
/* // This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
html {
|
||||
background: #161616 !important;
|
||||
background-color: #161616;
|
||||
font-family: Rubik, Roboto !important;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/* // This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
html, p, div, span {
|
||||
color: white !important;
|
||||
text-shadow: 1px 1px 2px #161616, 0 0 1em #161616;
|
||||
}
|
||||
|
||||
blockquote.forward > .preamble {
|
||||
color: rgba(255, 255, 255, 0.7) !important;
|
||||
}
|
||||
|
||||
blockquote.forward > .preamble > .date > .value,
|
||||
blockquote.forward > .preamble > .sender > .value {
|
||||
color: rgba(255, 255, 255, 0.7) !important;
|
||||
}
|
||||
blockquote.forward > .preamble > .date > .label,
|
||||
blockquote.forward > .preamble > .sender > .label {
|
||||
color: rgba(255, 255, 255, 0.7) !important;
|
||||
}
|
||||
table th {
|
||||
background-color: #161616;
|
||||
}
|
||||
|
After Width: | Height: | Size: 273 KiB |
|
After Width: | Height: | Size: 141 KiB |
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "BestSEQTA",
|
||||
"version": "3.0.2",
|
||||
"description": "Making SEQTA Learn better.",
|
||||
"icons": {
|
||||
"48": "icons/icon-48.png"
|
||||
},
|
||||
"browser_action": {
|
||||
"browser_style": true,
|
||||
"default_popup": "popup/info.html",
|
||||
"default_icon": {
|
||||
"32": "icons/icon-32.png",
|
||||
"64": "icons/icon-64.png"
|
||||
}
|
||||
},
|
||||
"permissions": [
|
||||
"tabs",
|
||||
"notifications",
|
||||
"storage",
|
||||
"https://newsapi.org/"
|
||||
],
|
||||
"background": {
|
||||
"scripts": [
|
||||
"background.js"
|
||||
]
|
||||
},
|
||||
"optional_permissions": [
|
||||
"*://*/*",
|
||||
"declarativeContent"
|
||||
],
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": [
|
||||
"https://*.edu.au/*"
|
||||
],
|
||||
"js": [
|
||||
"SEQTA.js"
|
||||
],
|
||||
"run_at": "document_start"
|
||||
}
|
||||
],
|
||||
"web_accessible_resources": [
|
||||
"icons/*",
|
||||
"images/*",
|
||||
"inject/*",
|
||||
"popup/*"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,504 @@
|
||||
.clr-picker {
|
||||
display: none;
|
||||
flex-wrap: wrap;
|
||||
position: absolute;
|
||||
width: 200px;
|
||||
z-index: 1000;
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
justify-content: space-between;
|
||||
box-shadow: 0 0 5px rgba(0,0,0,.05), 0 5px 20px rgba(0,0,0,.1);
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.clr-picker.clr-open {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.clr-gradient {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
margin-bottom: 15px;
|
||||
border-radius: 3px 3px 0 0;
|
||||
background-image: linear-gradient(rgba(0,0,0,0), #000), linear-gradient(90deg, #fff, currentColor);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.clr-marker {
|
||||
position: absolute;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin: -6px 0 0 -6px;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 50%;
|
||||
background-color: currentColor;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.clr-picker input[type="range"]::-webkit-slider-runnable-track {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.clr-picker input[type="range"]::-webkit-slider-thumb {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.clr-picker input[type="range"]::-moz-range-track {
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.clr-picker input[type="range"]::-moz-range-thumb {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.clr-hue {
|
||||
background-image: linear-gradient(to right, #f00 0%, #ff0 16.66%, #0f0 33.33%, #0ff 50%, #00f 66.66%, #f0f 83.33%, #f00 100%);
|
||||
}
|
||||
|
||||
.clr-hue,
|
||||
.clr-alpha {
|
||||
position: relative;
|
||||
width: calc(100% - 40px);
|
||||
height: 8px;
|
||||
margin: 5px 20px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.clr-alpha span {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: inherit;
|
||||
background-image: linear-gradient(90deg, rgba(0,0,0,0), currentColor);
|
||||
}
|
||||
|
||||
.clr-hue input,
|
||||
.clr-alpha input {
|
||||
position: absolute;
|
||||
width: calc(100% + 16px);
|
||||
height: 16px;
|
||||
left: -8px;
|
||||
top: -4px;
|
||||
margin: 0;
|
||||
background-color: transparent;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
.clr-hue div,
|
||||
.clr-alpha div {
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
margin-left: -8px;
|
||||
transform: translateY(-50%);
|
||||
border: 2px solid #fff;
|
||||
border-radius: 50%;
|
||||
background-color: currentColor;
|
||||
box-shadow: 0 0 1px #888;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.clr-alpha div:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: 50%;
|
||||
background-color: currentColor;
|
||||
}
|
||||
|
||||
.clr-format {
|
||||
display: none;
|
||||
order: 1;
|
||||
width: calc(100% - 40px);
|
||||
margin: 0 20px 20px;
|
||||
}
|
||||
|
||||
.clr-segmented {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 15px;
|
||||
box-sizing: border-box;
|
||||
color: #999;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.clr-segmented input,
|
||||
.clr-segmented legend {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.clr-segmented label {
|
||||
flex-grow: 1;
|
||||
padding: 4px 0;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.clr-segmented label:first-of-type {
|
||||
border-radius: 10px 0 0 10px;
|
||||
}
|
||||
|
||||
.clr-segmented label:last-of-type {
|
||||
border-radius: 0 10px 10px 0;
|
||||
}
|
||||
|
||||
.clr-segmented input:checked + label {
|
||||
color: #fff;
|
||||
background-color: #666;
|
||||
}
|
||||
|
||||
.clr-swatches {
|
||||
order: 2;
|
||||
width: calc(100% - 32px);
|
||||
margin: 0 16px;
|
||||
}
|
||||
|
||||
.clr-swatches div {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding-bottom: 12px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.clr-swatches button {
|
||||
position: relative;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin: 0 4px 6px 4px;
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
color: inherit;
|
||||
text-indent: -1000px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.clr-swatches button:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: inherit;
|
||||
background-color: currentColor;
|
||||
box-shadow: inset 0 0 0 1px rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
input.clr-color {
|
||||
order: 1;
|
||||
width: calc(100% - 80px);
|
||||
height: 32px;
|
||||
margin: 15px 20px 20px 0;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 16px;
|
||||
color: #444;
|
||||
background-color: #fff;
|
||||
font-family: sans-serif;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
input.clr-color:focus {
|
||||
outline: none;
|
||||
border: 1px solid #1e90ff;
|
||||
}
|
||||
|
||||
.clr-clear {
|
||||
display: none;
|
||||
order: 2;
|
||||
height: 24px;
|
||||
margin: 0 20px 20px auto;
|
||||
padding: 0 20px;
|
||||
border: 0;
|
||||
border-radius: 12px;
|
||||
color: #fff;
|
||||
background-color: #666;
|
||||
font-family: inherit;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.clr-preview {
|
||||
position: relative;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
margin: 15px 0 20px 20px;
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.clr-preview:before,
|
||||
.clr-preview:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border: 1px solid #fff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.clr-preview:after {
|
||||
border: 0;
|
||||
background-color: currentColor;
|
||||
box-shadow: inset 0 0 0 1px rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
.clr-marker,
|
||||
.clr-hue div,
|
||||
.clr-alpha div,
|
||||
.clr-color {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.clr-field {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.clr-field button {
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
height: 100%;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
border: 0;
|
||||
color: inherit;
|
||||
text-indent: -1000px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.clr-field button:after {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
border-radius: inherit;
|
||||
background-color: currentColor;
|
||||
box-shadow: inset 0 0 1px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
.clr-alpha,
|
||||
.clr-alpha div,
|
||||
.clr-swatches button,
|
||||
.clr-preview:before,
|
||||
.clr-field button {
|
||||
background-image: repeating-linear-gradient(45deg, #aaa 25%, transparent 25%, transparent 75%, #aaa 75%, #aaa), repeating-linear-gradient(45deg, #aaa 25%, #fff 25%, #fff 75%, #aaa 75%, #aaa);
|
||||
background-position: 0 0, 4px 4px;
|
||||
background-size: 8px 8px;
|
||||
}
|
||||
|
||||
.clr-marker:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.clr-keyboard-nav .clr-marker:focus,
|
||||
.clr-keyboard-nav .clr-hue input:focus + div,
|
||||
.clr-keyboard-nav .clr-alpha input:focus + div,
|
||||
.clr-keyboard-nav .clr-segmented input:focus + label {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px #1e90ff, 0 0 2px 2px #fff;
|
||||
}
|
||||
|
||||
.clr-picker[data-alpha="false"] .clr-alpha {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.clr-picker[data-minimal="true"] {
|
||||
padding-top: 16px;
|
||||
}
|
||||
|
||||
.clr-picker[data-minimal="true"] .clr-gradient,
|
||||
.clr-picker[data-minimal="true"] .clr-hue,
|
||||
.clr-picker[data-minimal="true"] .clr-alpha,
|
||||
.clr-picker[data-minimal="true"] .clr-color,
|
||||
.clr-picker[data-minimal="true"] .clr-preview {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/** Dark theme **/
|
||||
|
||||
.clr-dark {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
.clr-dark .clr-segmented {
|
||||
border-color: #777;
|
||||
}
|
||||
|
||||
.clr-dark .clr-swatches button:after {
|
||||
box-shadow: inset 0 0 0 1px rgba(255,255,255,.3);
|
||||
}
|
||||
|
||||
.clr-dark input.clr-color {
|
||||
color: #fff;
|
||||
border-color: #777;
|
||||
background-color: #555;
|
||||
}
|
||||
|
||||
.clr-dark input.clr-color:focus {
|
||||
border-color: #1e90ff;
|
||||
}
|
||||
|
||||
.clr-dark .clr-preview:after {
|
||||
box-shadow: inset 0 0 0 1px rgba(255,255,255,.5);
|
||||
}
|
||||
|
||||
.clr-dark .clr-alpha,
|
||||
.clr-dark .clr-alpha div,
|
||||
.clr-dark .clr-swatches button,
|
||||
.clr-dark .clr-preview:before {
|
||||
background-image: repeating-linear-gradient(45deg, #666 25%, transparent 25%, transparent 75%, #888 75%, #888), repeating-linear-gradient(45deg, #888 25%, #444 25%, #444 75%, #888 75%, #888);
|
||||
}
|
||||
|
||||
/** Polaroid theme **/
|
||||
|
||||
.clr-picker.clr-polaroid {
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 0 5px rgba(0,0,0,.1), 0 5px 30px rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
.clr-picker.clr-polaroid:before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 10px;
|
||||
left: 20px;
|
||||
top: -10px;
|
||||
border: solid transparent;
|
||||
border-width: 0 8px 10px 8px;
|
||||
border-bottom-color: currentColor;
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
filter: drop-shadow(0 -4px 3px rgba(0,0,0,.1));
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.clr-picker.clr-polaroid.clr-dark:before {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.clr-picker.clr-polaroid.clr-left:before {
|
||||
left: auto;
|
||||
right: 20px;
|
||||
}
|
||||
|
||||
.clr-picker.clr-polaroid.clr-top:before {
|
||||
top: auto;
|
||||
bottom: -10px;
|
||||
transform: rotateZ(180deg);
|
||||
}
|
||||
|
||||
.clr-polaroid .clr-gradient {
|
||||
width: calc(100% - 20px);
|
||||
height: 120px;
|
||||
margin: 10px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.clr-polaroid .clr-hue,
|
||||
.clr-polaroid .clr-alpha {
|
||||
width: calc(100% - 30px);
|
||||
height: 10px;
|
||||
margin: 6px 15px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.clr-polaroid .clr-hue div,
|
||||
.clr-polaroid .clr-alpha div {
|
||||
box-shadow: 0 0 5px rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
.clr-polaroid .clr-format {
|
||||
width: calc(100% - 20px);
|
||||
margin: 0 10px 15px;
|
||||
}
|
||||
|
||||
.clr-polaroid .clr-swatches {
|
||||
width: calc(100% - 12px);
|
||||
margin: 0 6px;
|
||||
}
|
||||
.clr-polaroid .clr-swatches div {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.clr-polaroid .clr-swatches button {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.clr-polaroid input.clr-color {
|
||||
width: calc(100% - 60px);
|
||||
margin: 10px 10px 15px 0;
|
||||
}
|
||||
|
||||
.clr-polaroid .clr-clear {
|
||||
margin: 0 10px 15px auto;
|
||||
}
|
||||
|
||||
.clr-polaroid .clr-preview {
|
||||
margin: 10px 0 15px 10px;
|
||||
}
|
||||
|
||||
/** Large theme **/
|
||||
|
||||
.clr-picker.clr-large {
|
||||
width: 275px;
|
||||
}
|
||||
|
||||
.clr-large .clr-gradient {
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.clr-large .clr-swatches button {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
}
|
||||
@@ -0,0 +1,961 @@
|
||||
/*!
|
||||
* Copyright (c) 2021 Momo Bassit.
|
||||
* Licensed under the MIT License (MIT)
|
||||
* https://github.com/mdbassit/Coloris
|
||||
*/
|
||||
|
||||
((window, document, Math) => {
|
||||
const ctx = document.createElement('canvas').getContext('2d');
|
||||
const currentColor = { r: 0, g: 0, b: 0, h: 0, s: 0, v: 0, a: 1 };
|
||||
let picker, colorArea, colorAreaDims, colorMarker, colorPreview, colorValue, clearButton,
|
||||
hueSlider, hueMarker, alphaSlider, alphaMarker, currentEl, currentFormat, oldColor;
|
||||
|
||||
// Default settings
|
||||
const settings = {
|
||||
el: '.coloris',
|
||||
parent: null,
|
||||
theme: 'default',
|
||||
themeMode: 'light',
|
||||
wrap: true,
|
||||
margin: 2,
|
||||
format: 'hex',
|
||||
formatToggle: false,
|
||||
swatches: [],
|
||||
swatchesOnly: false,
|
||||
alpha: true,
|
||||
focusInput: true,
|
||||
autoClose: false,
|
||||
clearButton: {
|
||||
show: false,
|
||||
label: 'Clear'
|
||||
},
|
||||
a11y: {
|
||||
open: 'Open color picker',
|
||||
close: 'Close color picker',
|
||||
marker: 'Saturation: {s}. Brightness: {v}.',
|
||||
hueSlider: 'Hue slider',
|
||||
alphaSlider: 'Opacity slider',
|
||||
input: 'Color value field',
|
||||
format: 'Color format',
|
||||
swatch: 'Color swatch',
|
||||
instruction: 'Saturation and brightness selector. Use up, down, left and right arrow keys to select.'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Configure the color picker.
|
||||
* @param {object} options Configuration options.
|
||||
*/
|
||||
function configure(options) {
|
||||
if (typeof options !== 'object') {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const key in options) {
|
||||
switch (key) {
|
||||
case 'el':
|
||||
bindFields(options.el);
|
||||
if (options.wrap !== false) {
|
||||
wrapFields(options.el);
|
||||
}
|
||||
break;
|
||||
case 'parent':
|
||||
settings.parent = document.querySelector(options.parent);
|
||||
if (settings.parent) {
|
||||
settings.parent.appendChild(picker);
|
||||
}
|
||||
break;
|
||||
case 'themeMode':
|
||||
settings.themeMode = options.themeMode;
|
||||
if (options.themeMode === 'auto' && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
settings.themeMode = 'dark';
|
||||
}
|
||||
// The lack of a break statement is intentional
|
||||
case 'theme':
|
||||
if (options.theme) {
|
||||
settings.theme = options.theme;
|
||||
}
|
||||
picker.className = `clr-picker clr-${settings.theme} clr-${settings.themeMode}`;
|
||||
break;
|
||||
case 'margin':
|
||||
options.margin *= 1;
|
||||
settings.margin = !isNaN(options.margin) ? options.margin : settings.margin;
|
||||
break;
|
||||
case 'wrap':
|
||||
if (options.el && options.wrap) {
|
||||
wrapFields(options.el);
|
||||
}
|
||||
break;
|
||||
case 'formatToggle':
|
||||
getEl('clr-format').style.display = options.formatToggle ? 'block' : 'none';
|
||||
if (options.formatToggle) {
|
||||
settings.format = 'auto';
|
||||
}
|
||||
break;
|
||||
case 'swatches':
|
||||
if (Array.isArray(options.swatches)) {
|
||||
const swatches = [];
|
||||
|
||||
options.swatches.forEach((swatch, i) => {
|
||||
swatches.push(`<button id="clr-swatch-${i}" aria-labelledby="clr-swatch-label clr-swatch-${i}" style="color: ${swatch};">${swatch}</button>`);
|
||||
});
|
||||
|
||||
if (swatches.length) {
|
||||
getEl('clr-swatches').innerHTML = `<div>${swatches.join('')}</div>`;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'swatchesOnly':
|
||||
settings.swatchesOnly = !!options.swatchesOnly;
|
||||
picker.setAttribute('data-minimal', settings.swatchesOnly);
|
||||
|
||||
if (settings.swatchesOnly) {
|
||||
settings.autoClose = true;
|
||||
}
|
||||
break;
|
||||
case 'alpha':
|
||||
settings.alpha = !!options.alpha;
|
||||
picker.setAttribute('data-alpha', settings.alpha);
|
||||
break;
|
||||
case 'clearButton':
|
||||
let display = 'none';
|
||||
|
||||
if (options.clearButton.show) {
|
||||
display = 'block';
|
||||
}
|
||||
|
||||
if (options.clearButton.label) {
|
||||
clearButton.innerHTML = options.clearButton.label;
|
||||
}
|
||||
|
||||
clearButton.style.display = display;
|
||||
break;
|
||||
case 'a11y':
|
||||
const labels = options.a11y;
|
||||
let update = false;
|
||||
|
||||
if (typeof labels === 'object') {
|
||||
for (const label in labels) {
|
||||
if (labels[label] && settings.a11y[label]) {
|
||||
settings.a11y[label] = labels[label];
|
||||
update = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (update) {
|
||||
const openLabel = getEl('clr-open-label');
|
||||
const swatchLabel = getEl('clr-swatch-label');
|
||||
|
||||
openLabel.innerHTML = settings.a11y.open;
|
||||
swatchLabel.innerHTML = settings.a11y.swatch;
|
||||
colorPreview.setAttribute('aria-label', settings.a11y.close);
|
||||
hueSlider.setAttribute('aria-label', settings.a11y.hueSlider);
|
||||
alphaSlider.setAttribute('aria-label', settings.a11y.alphaSlider);
|
||||
colorValue.setAttribute('aria-label', settings.a11y.input);
|
||||
colorArea.setAttribute('aria-label', settings.a11y.instruction);
|
||||
}
|
||||
default:
|
||||
settings[key] = options[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind the color picker to input fields that match the selector.
|
||||
* @param {string} selector One or more selectors pointing to input fields.
|
||||
*/
|
||||
function bindFields(selector) {
|
||||
// Show the color picker on click on the input fields that match the selector
|
||||
addListener(document, 'click', selector, event => {
|
||||
const parent = settings.parent;
|
||||
const coords = event.target.getBoundingClientRect();
|
||||
const scrollY = window.scrollY;
|
||||
let reposition = { left: false, top: false };
|
||||
let offset = { x: 0, y: 0 };
|
||||
let left = coords.x;
|
||||
let top = scrollY + coords.y + coords.height + settings.margin;
|
||||
|
||||
currentEl = event.target;
|
||||
oldColor = currentEl.value;
|
||||
currentFormat = getColorFormatFromStr(oldColor);
|
||||
picker.classList.add('clr-open');
|
||||
|
||||
const pickerWidth = picker.offsetWidth;
|
||||
const pickerHeight = picker.offsetHeight;
|
||||
|
||||
// If the color picker is inside a custom container
|
||||
// set the position relative to it
|
||||
if (parent) {
|
||||
const style = window.getComputedStyle(parent);
|
||||
const marginTop = parseFloat(style.marginTop);
|
||||
const borderTop = parseFloat(style.borderTopWidth);
|
||||
|
||||
offset = parent.getBoundingClientRect();
|
||||
offset.y += borderTop + scrollY;
|
||||
left -= offset.x;
|
||||
top -= offset.y;
|
||||
|
||||
if (left + pickerWidth > parent.clientWidth) {
|
||||
left += coords.width - pickerWidth;
|
||||
reposition.left = true;
|
||||
}
|
||||
|
||||
if (top + pickerHeight > parent.clientHeight - marginTop) {
|
||||
top -= coords.height + pickerHeight + settings.margin * 2;
|
||||
reposition.top = true;
|
||||
}
|
||||
|
||||
top += parent.scrollTop;
|
||||
|
||||
// Otherwise set the position relative to the whole document
|
||||
} else {
|
||||
if (left + pickerWidth > document.documentElement.clientWidth) {
|
||||
left += coords.width - pickerWidth;
|
||||
reposition.left = true;
|
||||
}
|
||||
|
||||
if (top + pickerHeight - scrollY > document.documentElement.clientHeight) {
|
||||
top = scrollY + coords.y - pickerHeight - settings.margin;
|
||||
reposition.top = true;
|
||||
}
|
||||
}
|
||||
|
||||
picker.classList.toggle('clr-left', reposition.left);
|
||||
picker.classList.toggle('clr-top', reposition.top);
|
||||
picker.style.left = `${left}px`;
|
||||
picker.style.top = `${top}px`;
|
||||
colorAreaDims = {
|
||||
width: colorArea.offsetWidth,
|
||||
height: colorArea.offsetHeight,
|
||||
x: picker.offsetLeft + colorArea.offsetLeft + offset.x,
|
||||
y: picker.offsetTop + colorArea.offsetTop + offset.y
|
||||
};
|
||||
|
||||
setColorFromStr(oldColor);
|
||||
|
||||
if (settings.focusInput) {
|
||||
colorValue.focus({ preventScroll: true });
|
||||
}
|
||||
});
|
||||
|
||||
// Update the color preview of the input fields that match the selector
|
||||
addListener(document, 'input', selector, event => {
|
||||
const parent = event.target.parentNode;
|
||||
|
||||
// Only update the preview if the field has been previously wrapped
|
||||
if (parent.classList.contains('clr-field')) {
|
||||
parent.style.color = event.target.value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the linked input fields in a div that adds a color preview.
|
||||
* @param {string} selector One or more selectors pointing to input fields.
|
||||
*/
|
||||
function wrapFields(selector) {
|
||||
document.querySelectorAll(selector).forEach(field => {
|
||||
const parentNode = field.parentNode;
|
||||
|
||||
if (!parentNode.classList.contains('clr-field')) {
|
||||
const wrapper = document.createElement('div');
|
||||
|
||||
wrapper.innerHTML = `<button aria-labelledby="clr-open-label"></button>`;
|
||||
parentNode.insertBefore(wrapper, field);
|
||||
wrapper.setAttribute('class', 'clr-field');
|
||||
wrapper.style.color = field.value;
|
||||
wrapper.appendChild(field);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the color picker.
|
||||
* @param {boolean} [revert] If true, revert the color to the original value.
|
||||
*/
|
||||
function closePicker(revert) {
|
||||
if (currentEl) {
|
||||
// Revert the color to the original value if needed
|
||||
if (revert && oldColor !== currentEl.value) {
|
||||
currentEl.value = oldColor;
|
||||
|
||||
// Trigger an "input" event to force update the thumbnail next to the input field
|
||||
currentEl.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
}
|
||||
|
||||
if (oldColor !== currentEl.value) {
|
||||
currentEl.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
}
|
||||
|
||||
picker.classList.remove('clr-open');
|
||||
|
||||
if (settings.focusInput) {
|
||||
currentEl.focus({ preventScroll: true });
|
||||
}
|
||||
|
||||
currentEl = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the active color from a string.
|
||||
* @param {string} str String representing a color.
|
||||
*/
|
||||
function setColorFromStr(str) {
|
||||
const rgba = strToRGBA(str);
|
||||
const hsva = RGBAtoHSVA(rgba);
|
||||
|
||||
updateMarkerA11yLabel(hsva.s, hsva.v);
|
||||
updateColor(rgba, hsva);
|
||||
|
||||
// Update the UI
|
||||
hueSlider.value = hsva.h;
|
||||
picker.style.color = `hsl(${hsva.h}, 100%, 50%)`;
|
||||
hueMarker.style.left = `${hsva.h / 360 * 100}%`;
|
||||
|
||||
colorMarker.style.left = `${colorAreaDims.width * hsva.s / 100}px`;
|
||||
colorMarker.style.top = `${colorAreaDims.height - (colorAreaDims.height * hsva.v / 100)}px`;
|
||||
|
||||
alphaSlider.value = hsva.a * 100;
|
||||
alphaMarker.style.left = `${hsva.a * 100}%`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Guess the color format from a string.
|
||||
* @param {string} str String representing a color.
|
||||
* @return {string} The color format.
|
||||
*/
|
||||
function getColorFormatFromStr(str) {
|
||||
const format = str.substring(0, 3).toLowerCase();
|
||||
|
||||
if (format === 'rgb' || format === 'hsl') {
|
||||
return format;
|
||||
}
|
||||
|
||||
return 'hex';
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the active color to the linked input field.
|
||||
* @param {number} [color] Color value to override the active color.
|
||||
*/
|
||||
function pickColor(color) {
|
||||
if (currentEl) {
|
||||
currentEl.value = color !== undefined ? color : colorValue.value;
|
||||
currentEl.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the active color based on a specific point in the color gradient.
|
||||
* @param {number} x Left position.
|
||||
* @param {number} y Top position.
|
||||
*/
|
||||
function setColorAtPosition(x, y) {
|
||||
const hsva = {
|
||||
h: hueSlider.value * 1,
|
||||
s: x / colorAreaDims.width * 100,
|
||||
v: 100 - (y / colorAreaDims.height * 100),
|
||||
a: alphaSlider.value / 100
|
||||
};
|
||||
const rgba = HSVAtoRGBA(hsva);
|
||||
|
||||
updateMarkerA11yLabel(hsva.s, hsva.v);
|
||||
updateColor(rgba, hsva);
|
||||
pickColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the color marker's accessibility label.
|
||||
* @param {number} saturation
|
||||
* @param {number} value
|
||||
*/
|
||||
function updateMarkerA11yLabel(saturation, value) {
|
||||
let label = settings.a11y.marker;
|
||||
|
||||
saturation = saturation.toFixed(1) * 1;
|
||||
value = value.toFixed(1) * 1;
|
||||
label = label.replace('{s}', saturation);
|
||||
label = label.replace('{v}', value);
|
||||
colorMarker.setAttribute('aria-label', label);
|
||||
}
|
||||
|
||||
//
|
||||
/**
|
||||
* Get the pageX and pageY positions of the pointer.
|
||||
* @param {object} event The MouseEvent or TouchEvent object.
|
||||
* @return {object} The pageX and pageY positions.
|
||||
*/
|
||||
function getPointerPosition(event) {
|
||||
return {
|
||||
pageX: event.changedTouches ? event.changedTouches[0].pageX : event.pageX,
|
||||
pageY: event.changedTouches ? event.changedTouches[0].pageY : event.pageY
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the color marker when dragged.
|
||||
* @param {object} event The MouseEvent object.
|
||||
*/
|
||||
function moveMarker(event) {
|
||||
const pointer = getPointerPosition(event);
|
||||
let x = pointer.pageX - colorAreaDims.x;
|
||||
let y = pointer.pageY - colorAreaDims.y;
|
||||
|
||||
if (settings.parent) {
|
||||
y += settings.parent.scrollTop;
|
||||
}
|
||||
|
||||
x = (x < 0) ? 0 : (x > colorAreaDims.width) ? colorAreaDims.width : x;
|
||||
y = (y < 0) ? 0 : (y > colorAreaDims.height) ? colorAreaDims.height : y;
|
||||
|
||||
colorMarker.style.left = `${x}px`;
|
||||
colorMarker.style.top = `${y}px`;
|
||||
|
||||
setColorAtPosition(x, y);
|
||||
|
||||
// Prevent scrolling while dragging the marker
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the color marker when the arrow keys are pressed.
|
||||
* @param {number} offsetX The horizontal amount to move.
|
||||
* * @param {number} offsetY The vertical amount to move.
|
||||
*/
|
||||
function moveMarkerOnKeydown(offsetX, offsetY) {
|
||||
const x = colorMarker.style.left.replace('px', '') * 1 + offsetX;
|
||||
const y = colorMarker.style.top.replace('px', '') * 1 + offsetY;
|
||||
|
||||
colorMarker.style.left = `${x}px`;
|
||||
colorMarker.style.top = `${y}px`;
|
||||
|
||||
setColorAtPosition(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the color picker's input field and preview thumb.
|
||||
* @param {Object} rgba Red, green, blue and alpha values.
|
||||
* @param {Object} [hsva] Hue, saturation, value and alpha values.
|
||||
*/
|
||||
function updateColor(rgba = {}, hsva = {}) {
|
||||
let format = settings.format;
|
||||
|
||||
for (const key in rgba) {
|
||||
currentColor[key] = rgba[key];
|
||||
}
|
||||
|
||||
for (const key in hsva) {
|
||||
currentColor[key] = hsva[key];
|
||||
}
|
||||
|
||||
const hex = RGBAToHex(currentColor);
|
||||
const opaqueHex = hex.substring(0, 7);
|
||||
|
||||
colorMarker.style.color = opaqueHex;
|
||||
alphaMarker.parentNode.style.color = opaqueHex;
|
||||
alphaMarker.style.color = hex;
|
||||
colorPreview.style.color = hex;
|
||||
|
||||
// Force repaint the color and alpha gradients as a workaround for a Google Chrome bug
|
||||
colorArea.style.display = 'none';
|
||||
colorArea.offsetHeight;
|
||||
colorArea.style.display = '';
|
||||
alphaMarker.nextElementSibling.style.display = 'none';
|
||||
alphaMarker.nextElementSibling.offsetHeight;
|
||||
alphaMarker.nextElementSibling.style.display = '';
|
||||
|
||||
if (format === 'mixed') {
|
||||
format = currentColor.a === 1 ? 'hex' : 'rgb';
|
||||
} else if (format === 'auto') {
|
||||
format = currentFormat;
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case 'hex':
|
||||
colorValue.value = hex;
|
||||
break;
|
||||
case 'rgb':
|
||||
colorValue.value = RGBAToStr(currentColor);
|
||||
break;
|
||||
case 'hsl':
|
||||
colorValue.value = HSLAToStr(HSVAtoHSLA(currentColor));
|
||||
break;
|
||||
}
|
||||
|
||||
// Select the current format in the format switcher
|
||||
document.querySelector(`.clr-format [value="${format}"]`).checked = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the hue when its slider is moved.
|
||||
*/
|
||||
function setHue() {
|
||||
const hue = hueSlider.value * 1;
|
||||
const x = colorMarker.style.left.replace('px', '') * 1;
|
||||
const y = colorMarker.style.top.replace('px', '') * 1;
|
||||
|
||||
picker.style.color = `hsl(${hue}, 100%, 50%)`;
|
||||
hueMarker.style.left = `${hue / 360 * 100}%`;
|
||||
|
||||
setColorAtPosition(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the alpha when its slider is moved.
|
||||
*/
|
||||
function setAlpha() {
|
||||
const alpha = alphaSlider.value / 100;
|
||||
|
||||
alphaMarker.style.left = `${alpha * 100}%`;
|
||||
updateColor({ a: alpha });
|
||||
pickColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert HSVA to RGBA.
|
||||
* @param {object} hsva Hue, saturation, value and alpha values.
|
||||
* @return {object} Red, green, blue and alpha values.
|
||||
*/
|
||||
function HSVAtoRGBA(hsva) {
|
||||
const saturation = hsva.s / 100;
|
||||
const value = hsva.v / 100;
|
||||
let chroma = saturation * value;
|
||||
let hueBy60 = hsva.h / 60;
|
||||
let x = chroma * (1 - Math.abs(hueBy60 % 2 - 1));
|
||||
let m = value - chroma;
|
||||
|
||||
chroma = (chroma + m);
|
||||
x = (x + m);
|
||||
|
||||
const index = Math.floor(hueBy60) % 6;
|
||||
const red = [chroma, x, m, m, x, chroma][index];
|
||||
const green = [x, chroma, chroma, x, m, m][index];
|
||||
const blue = [m, m, x, chroma, chroma, x][index];
|
||||
|
||||
return {
|
||||
r: Math.round(red * 255),
|
||||
g: Math.round(green * 255),
|
||||
b: Math.round(blue * 255),
|
||||
a: hsva.a
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert HSVA to HSLA.
|
||||
* @param {object} hsva Hue, saturation, value and alpha values.
|
||||
* @return {object} Hue, saturation, lightness and alpha values.
|
||||
*/
|
||||
function HSVAtoHSLA(hsva) {
|
||||
const value = hsva.v / 100;
|
||||
const lightness = value * (1 - (hsva.s / 100) / 2);
|
||||
let saturation;
|
||||
|
||||
if (lightness > 0 && lightness < 1) {
|
||||
saturation = Math.round((value - lightness) / Math.min(lightness, 1 - lightness) * 100);
|
||||
}
|
||||
|
||||
return {
|
||||
h: hsva.h,
|
||||
s: saturation || 0,
|
||||
l: Math.round(lightness * 100),
|
||||
a: hsva.a
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert RGBA to HSVA.
|
||||
* @param {object} rgba Red, green, blue and alpha values.
|
||||
* @return {object} Hue, saturation, value and alpha values.
|
||||
*/
|
||||
function RGBAtoHSVA(rgba) {
|
||||
const red = rgba.r / 255;
|
||||
const green = rgba.g / 255;
|
||||
const blue = rgba.b / 255;
|
||||
const xmax = Math.max(red, green, blue);
|
||||
const xmin = Math.min(red, green, blue);
|
||||
const chroma = xmax - xmin;
|
||||
const value = xmax;
|
||||
let hue = 0;
|
||||
let saturation = 0;
|
||||
|
||||
if (chroma) {
|
||||
if (xmax === red) { hue = ((green - blue) / chroma); }
|
||||
if (xmax === green) { hue = 2 + (blue - red) / chroma; }
|
||||
if (xmax === blue) { hue = 4 + (red - green) / chroma; }
|
||||
if (xmax) { saturation = chroma / xmax; }
|
||||
}
|
||||
|
||||
hue = Math.floor(hue * 60);
|
||||
|
||||
return {
|
||||
h: hue < 0 ? hue + 360 : hue,
|
||||
s: Math.round(saturation * 100),
|
||||
v: Math.round(value * 100),
|
||||
a: rgba.a
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a string to RGBA.
|
||||
* @param {string} str String representing a color.
|
||||
* @return {object} Red, green, blue and alpha values.
|
||||
*/
|
||||
function strToRGBA(str) {
|
||||
const regex = /^((rgba)|rgb)[\D]+([\d.]+)[\D]+([\d.]+)[\D]+([\d.]+)[\D]*?([\d.]+|$)/i;
|
||||
let match, rgba;
|
||||
|
||||
// Default to black for invalid color strings
|
||||
ctx.fillStyle = '#000';
|
||||
|
||||
// Use canvas to convert the string to a valid color string
|
||||
ctx.fillStyle = str;
|
||||
match = regex.exec(ctx.fillStyle);
|
||||
|
||||
if (match) {
|
||||
rgba = {
|
||||
r: match[3] * 1,
|
||||
g: match[4] * 1,
|
||||
b: match[5] * 1,
|
||||
a: match[6] * 1
|
||||
};
|
||||
|
||||
} else {
|
||||
match = ctx.fillStyle.replace('#', '').match(/.{2}/g).map(h => parseInt(h, 16));
|
||||
rgba = {
|
||||
r: match[0],
|
||||
g: match[1],
|
||||
b: match[2],
|
||||
a: 1
|
||||
};
|
||||
}
|
||||
|
||||
return rgba;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert RGBA to Hex.
|
||||
* @param {object} rgba Red, green, blue and alpha values.
|
||||
* @return {string} Hex color string.
|
||||
*/
|
||||
function RGBAToHex(rgba) {
|
||||
let R = rgba.r.toString(16);
|
||||
let G = rgba.g.toString(16);
|
||||
let B = rgba.b.toString(16);
|
||||
let A = '';
|
||||
|
||||
if (rgba.r < 16) {
|
||||
R = '0' + R;
|
||||
}
|
||||
|
||||
if (rgba.g < 16) {
|
||||
G = '0' + G;
|
||||
}
|
||||
|
||||
if (rgba.b < 16) {
|
||||
B = '0' + B;
|
||||
}
|
||||
|
||||
if (settings.alpha && rgba.a < 1) {
|
||||
const alpha = rgba.a * 255 | 0;
|
||||
A = alpha.toString(16);
|
||||
|
||||
if (alpha < 16) {
|
||||
A = '0' + A;
|
||||
}
|
||||
}
|
||||
|
||||
return '#' + R + G + B + A;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert RGBA values to a CSS rgb/rgba string.
|
||||
* @param {object} rgba Red, green, blue and alpha values.
|
||||
* @return {string} CSS color string.
|
||||
*/
|
||||
function RGBAToStr(rgba) {
|
||||
if (!settings.alpha || rgba.a === 1) {
|
||||
return `rgb(${rgba.r}, ${rgba.g}, ${rgba.b})`;
|
||||
} else {
|
||||
return `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert HSLA values to a CSS hsl/hsla string.
|
||||
* @param {object} hsla Hue, saturation, lightness and alpha values.
|
||||
* @return {string} CSS color string.
|
||||
*/
|
||||
function HSLAToStr(hsla) {
|
||||
if (!settings.alpha || hsla.a === 1) {
|
||||
return `hsl(${hsla.h}, ${hsla.s}%, ${hsla.l}%)`;
|
||||
} else {
|
||||
return `hsla(${hsla.h}, ${hsla.s}%, ${hsla.l}%, ${hsla.a})`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init the color picker.
|
||||
*/
|
||||
function init() {
|
||||
// Render the UI
|
||||
picker = document.createElement('div');
|
||||
picker.setAttribute('id', 'clr-picker');
|
||||
picker.className = 'clr-picker';
|
||||
picker.innerHTML =
|
||||
`<input id="clr-color-value" class="clr-color" type="text" value="" aria-label="${settings.a11y.input}">` +
|
||||
`<div id="clr-color-area" class="clr-gradient" role="application" aria-label="${settings.a11y.instruction}">` +
|
||||
'<div id="clr-color-marker" class="clr-marker" tabindex="0"></div>' +
|
||||
'</div>' +
|
||||
'<div class="clr-hue">' +
|
||||
`<input id="clr-hue-slider" type="range" min="0" max="360" step="1" aria-label="${settings.a11y.hueSlider}">` +
|
||||
'<div id="clr-hue-marker"></div>' +
|
||||
'</div>' +
|
||||
'<div class="clr-alpha">' +
|
||||
`<input id="clr-alpha-slider" type="range" min="0" max="100" step="1" aria-label="${settings.a11y.alphaSlider}">` +
|
||||
'<div id="clr-alpha-marker"></div>' +
|
||||
'<span></span>' +
|
||||
'</div>' +
|
||||
'<div id="clr-format" class="clr-format">' +
|
||||
'<fieldset class="clr-segmented">' +
|
||||
`<legend>${settings.a11y.format}</legend>` +
|
||||
'<input id="clr-f1" type="radio" name="clr-format" value="hex">' +
|
||||
'<label for="clr-f1">Hex</label>' +
|
||||
'<input id="clr-f2" type="radio" name="clr-format" value="rgb">' +
|
||||
'<label for="clr-f2">RGB</label>' +
|
||||
'<input id="clr-f3" type="radio" name="clr-format" value="hsl">' +
|
||||
'<label for="clr-f3">HSL</label>' +
|
||||
'<span></span>' +
|
||||
'</fieldset>' +
|
||||
'</div>' +
|
||||
'<div id="clr-swatches" class="clr-swatches"></div>' +
|
||||
`<button id="clr-clear" class="clr-clear">${settings.clearButton.label}</button>` +
|
||||
`<button id="clr-color-preview" class="clr-preview" aria-label="${settings.a11y.close}"></button>` +
|
||||
`<span id="clr-open-label" hidden>${settings.a11y.open}</span>` +
|
||||
`<span id="clr-swatch-label" hidden>${settings.a11y.swatch}</span>`;
|
||||
|
||||
// Append the color picker to the DOM
|
||||
document.body.appendChild(picker);
|
||||
|
||||
// Reference the UI elements
|
||||
colorArea = getEl('clr-color-area');
|
||||
colorMarker = getEl('clr-color-marker');
|
||||
clearButton = getEl('clr-clear');
|
||||
colorPreview = getEl('clr-color-preview');
|
||||
colorValue = getEl('clr-color-value');
|
||||
hueSlider = getEl('clr-hue-slider');
|
||||
hueMarker = getEl('clr-hue-marker');
|
||||
alphaSlider = getEl('clr-alpha-slider');
|
||||
alphaMarker = getEl('clr-alpha-marker');
|
||||
|
||||
// Bind the picker to the default selector
|
||||
bindFields(settings.el);
|
||||
wrapFields(settings.el);
|
||||
|
||||
addListener(picker, 'mousedown', event => {
|
||||
picker.classList.remove('clr-keyboard-nav');
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
addListener(colorArea, 'mousedown', event => {
|
||||
addListener(document, 'mousemove', moveMarker);
|
||||
});
|
||||
|
||||
addListener(colorArea, 'touchstart', event => {
|
||||
document.addEventListener('touchmove', moveMarker, { passive: false });
|
||||
});
|
||||
|
||||
addListener(colorMarker, 'mousedown', event => {
|
||||
addListener(document, 'mousemove', moveMarker);
|
||||
});
|
||||
|
||||
addListener(colorMarker, 'touchstart', event => {
|
||||
document.addEventListener('touchmove', moveMarker, { passive: false });
|
||||
});
|
||||
|
||||
addListener(colorValue, 'change', event => {
|
||||
setColorFromStr(colorValue.value);
|
||||
pickColor();
|
||||
});
|
||||
|
||||
addListener(clearButton, 'click', event => {
|
||||
pickColor('');
|
||||
closePicker();
|
||||
});
|
||||
|
||||
addListener(colorPreview, 'click', event => {
|
||||
pickColor();
|
||||
closePicker();
|
||||
});
|
||||
|
||||
addListener(document, 'click', '.clr-format input', event => {
|
||||
currentFormat = event.target.value;
|
||||
updateColor();
|
||||
pickColor();
|
||||
});
|
||||
|
||||
addListener(picker, 'click', '.clr-swatches button', event => {
|
||||
setColorFromStr(event.target.textContent);
|
||||
pickColor();
|
||||
|
||||
if (settings.autoClose) {
|
||||
closePicker();
|
||||
}
|
||||
});
|
||||
|
||||
addListener(document, 'mouseup', event => {
|
||||
document.removeEventListener('mousemove', moveMarker);
|
||||
});
|
||||
|
||||
addListener(document, 'touchend', event => {
|
||||
document.removeEventListener('touchmove', moveMarker);
|
||||
});
|
||||
|
||||
addListener(document, 'mousedown', event => {
|
||||
picker.classList.remove('clr-keyboard-nav');
|
||||
closePicker();
|
||||
});
|
||||
|
||||
addListener(document, 'keydown', event => {
|
||||
if (event.key === 'Escape') {
|
||||
closePicker(true);
|
||||
} else if (event.key === 'Tab') {
|
||||
picker.classList.add('clr-keyboard-nav');
|
||||
}
|
||||
});
|
||||
|
||||
addListener(document, 'click', '.clr-field button', event => {
|
||||
event.target.nextElementSibling.dispatchEvent(new Event('click', { bubbles: true }));
|
||||
});
|
||||
|
||||
addListener(colorMarker, 'keydown', event => {
|
||||
const movements = {
|
||||
ArrowUp: [0, -1],
|
||||
ArrowDown: [0, 1],
|
||||
ArrowLeft: [-1, 0],
|
||||
ArrowRight: [1, 0]
|
||||
};
|
||||
|
||||
if (Object.keys(movements).indexOf(event.key) !== -1) {
|
||||
moveMarkerOnKeydown(...movements[event.key]);
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
addListener(colorArea, 'click', moveMarker);
|
||||
addListener(hueSlider, 'input', setHue);
|
||||
addListener(alphaSlider, 'input', setAlpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for getElementById to optimize the minified JS.
|
||||
* @param {string} id The element id.
|
||||
* @return {object} The DOM element with the provided id.
|
||||
*/
|
||||
function getEl(id) {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortcut for addEventListener to optimize the minified JS.
|
||||
* @param {object} context The context to which the listener is attached.
|
||||
* @param {string} type Event type.
|
||||
* @param {(string|function)} selector Event target if delegation is used, event handler if not.
|
||||
* @param {function} [fn] Event handler if delegation is used.
|
||||
*/
|
||||
function addListener(context, type, selector, fn) {
|
||||
const matches = Element.prototype.matches || Element.prototype.msMatchesSelector;
|
||||
|
||||
// Delegate event to the target of the selector
|
||||
if (typeof selector === 'string') {
|
||||
context.addEventListener(type, event => {
|
||||
if (matches.call(event.target, selector)) {
|
||||
fn.call(event.target, event);
|
||||
}
|
||||
});
|
||||
|
||||
// If the selector is not a string then it's a function
|
||||
// in which case we need regular event listener
|
||||
} else {
|
||||
fn = selector;
|
||||
context.addEventListener(type, fn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call a function only when the DOM is ready.
|
||||
* @param {function} fn The function to call.
|
||||
* @param {array} [args] Arguments to pass to the function.
|
||||
*/
|
||||
function DOMReady(fn, args) {
|
||||
args = args !== undefined ? args : [];
|
||||
|
||||
if (document.readyState !== 'loading') {
|
||||
fn(...args);
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
fn(...args);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Polyfill for Nodelist.forEach
|
||||
if (NodeList !== undefined && NodeList.prototype && !NodeList.prototype.forEach) {
|
||||
NodeList.prototype.forEach = Array.prototype.forEach;
|
||||
}
|
||||
|
||||
// Expose the color picker to the global scope
|
||||
window.Coloris = (() => {
|
||||
const methods = {
|
||||
set: configure,
|
||||
wrap: wrapFields,
|
||||
close: closePicker
|
||||
};
|
||||
|
||||
function Coloris(options) {
|
||||
DOMReady(() => {
|
||||
if (options) {
|
||||
if (typeof options === 'string') {
|
||||
bindFields(options);
|
||||
} else {
|
||||
configure(options);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
for (const key in methods) {
|
||||
Coloris[key] = (...args) => {
|
||||
DOMReady(methods[key], args);
|
||||
};
|
||||
}
|
||||
|
||||
return Coloris;
|
||||
})();
|
||||
|
||||
// Init the color picker when the DOM is ready
|
||||
DOMReady(init);
|
||||
|
||||
})(window, document, Math);
|
||||
|
||||
Coloris({
|
||||
el: '.coloris',
|
||||
theme: 'large',
|
||||
themeMode: 'dark',
|
||||
format: 'hex',
|
||||
alpha: false,
|
||||
swatches: [
|
||||
'#471616',
|
||||
'#1e4716',
|
||||
'#16473f',
|
||||
'#161c47',
|
||||
'#371647',
|
||||
'#47163f',
|
||||
'#471627',
|
||||
'#3a3a3a',
|
||||
'#ffffff',
|
||||
'#1a1a1a'
|
||||
]
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="256px" height="250px" viewBox="0 0 256 250" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMidYMid">
|
||||
<g>
|
||||
<path d="M128.00106,0 C57.3172926,0 0,57.3066942 0,128.00106 C0,184.555281 36.6761997,232.535542 87.534937,249.460899 C93.9320223,250.645779 96.280588,246.684165 96.280588,243.303333 C96.280588,240.251045 96.1618878,230.167899 96.106777,219.472176 C60.4967585,227.215235 52.9826207,204.369712 52.9826207,204.369712 C47.1599584,189.574598 38.770408,185.640538 38.770408,185.640538 C27.1568785,177.696113 39.6458206,177.859325 39.6458206,177.859325 C52.4993419,178.762293 59.267365,191.04987 59.267365,191.04987 C70.6837675,210.618423 89.2115753,204.961093 96.5158685,201.690482 C97.6647155,193.417512 100.981959,187.77078 104.642583,184.574357 C76.211799,181.33766 46.324819,170.362144 46.324819,121.315702 C46.324819,107.340889 51.3250588,95.9223682 59.5132437,86.9583937 C58.1842268,83.7344152 53.8029229,70.715562 60.7532354,53.0843636 C60.7532354,53.0843636 71.5019501,49.6441813 95.9626412,66.2049595 C106.172967,63.368876 117.123047,61.9465949 128.00106,61.8978432 C138.879073,61.9465949 149.837632,63.368876 160.067033,66.2049595 C184.49805,49.6441813 195.231926,53.0843636 195.231926,53.0843636 C202.199197,70.715562 197.815773,83.7344152 196.486756,86.9583937 C204.694018,95.9223682 209.660343,107.340889 209.660343,121.315702 C209.660343,170.478725 179.716133,181.303747 151.213281,184.472614 C155.80443,188.444828 159.895342,196.234518 159.895342,208.176593 C159.895342,225.303317 159.746968,239.087361 159.746968,243.303333 C159.746968,246.709601 162.05102,250.70089 168.53925,249.443941 C219.370432,232.499507 256,184.536204 256,128.00106 C256,57.3066942 198.691187,0 128.00106,0 Z M47.9405593,182.340212 C47.6586465,182.976105 46.6581745,183.166873 45.7467277,182.730227 C44.8183235,182.312656 44.2968914,181.445722 44.5978808,180.80771 C44.8734344,180.152739 45.876026,179.97045 46.8023103,180.409216 C47.7328342,180.826786 48.2627451,181.702199 47.9405593,182.340212 Z M54.2367892,187.958254 C53.6263318,188.524199 52.4329723,188.261363 51.6232682,187.366874 C50.7860088,186.474504 50.6291553,185.281144 51.2480912,184.70672 C51.8776254,184.140775 53.0349512,184.405731 53.8743302,185.298101 C54.7115892,186.201069 54.8748019,187.38595 54.2367892,187.958254 Z M58.5562413,195.146347 C57.7719732,195.691096 56.4895886,195.180261 55.6968417,194.042013 C54.9125733,192.903764 54.9125733,191.538713 55.713799,190.991845 C56.5086651,190.444977 57.7719732,190.936735 58.5753181,192.066505 C59.3574669,193.22383 59.3574669,194.58888 58.5562413,195.146347 Z M65.8613592,203.471174 C65.1597571,204.244846 63.6654083,204.03712 62.5716717,202.981538 C61.4524999,201.94927 61.1409122,200.484596 61.8446341,199.710926 C62.5547146,198.935137 64.0575422,199.15346 65.1597571,200.200564 C66.2704506,201.230712 66.6095936,202.705984 65.8613592,203.471174 Z M75.3025151,206.281542 C74.9930474,207.284134 73.553809,207.739857 72.1039724,207.313809 C70.6562556,206.875043 69.7087748,205.700761 70.0012857,204.687571 C70.302275,203.678621 71.7478721,203.20382 73.2083069,203.659543 C74.6539041,204.09619 75.6035048,205.261994 75.3025151,206.281542 Z M86.046947,207.473627 C86.0829806,208.529209 84.8535871,209.404622 83.3316829,209.4237 C81.8013,209.457614 80.563428,208.603398 80.5464708,207.564772 C80.5464708,206.498591 81.7483088,205.631657 83.2786917,205.606221 C84.8005962,205.576546 86.046947,206.424403 86.046947,207.473627 Z M96.6021471,207.069023 C96.7844366,208.099171 95.7267341,209.156872 94.215428,209.438785 C92.7295577,209.710099 91.3539086,209.074206 91.1652603,208.052538 C90.9808515,206.996955 92.0576306,205.939253 93.5413813,205.66582 C95.054807,205.402984 96.4092596,206.021919 96.6021471,207.069023 Z" fill="#161614"></path>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1,491 @@
|
||||
/* // This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
/* cyrillic-ext */
|
||||
@import url('https://fonts.googleapis.com/css?family=Rubik:300,400,500,600');
|
||||
|
||||
.outside-container {
|
||||
width: 350px;
|
||||
margin: 0;
|
||||
background-color: #131313;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 80px;
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.selector-container {
|
||||
font-family: Rubik, sans-serif;
|
||||
background-color: #131313;
|
||||
color: white;
|
||||
padding: 4px;
|
||||
font-size: 1.5em !important;
|
||||
text-align: center;
|
||||
width: 90%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0px auto;
|
||||
}
|
||||
.main-page {
|
||||
position: relative;
|
||||
left: 0px;
|
||||
transition: 0.4s;
|
||||
}
|
||||
.menu-page {
|
||||
transition: 0.4s;
|
||||
width: 100%;
|
||||
height: 26em;
|
||||
}
|
||||
.menu-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
height: 2em !important;
|
||||
}
|
||||
.apply-changes {
|
||||
margin-top: 10px;
|
||||
margin-left: 5px;
|
||||
padding: 8px;
|
||||
background-color: #4cd964;
|
||||
width: 40%;
|
||||
font-size: 14px !important;
|
||||
justify-self: right;
|
||||
cursor: pointer;
|
||||
height: fit-content;
|
||||
text-align: center;
|
||||
text-shadow: 0px 0px 15px rgb(22, 22, 22);
|
||||
}
|
||||
.apply-changes h3, h5 {
|
||||
margin: 0;
|
||||
}
|
||||
.apply-changes h3 {
|
||||
font-size: 10px;
|
||||
}
|
||||
.apply-changes h5 {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.logo-container {
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
height: 6em;
|
||||
text-align: center;
|
||||
}
|
||||
.checkbox-container {
|
||||
width: 30%;
|
||||
justify-content: end;
|
||||
display: flex;
|
||||
}
|
||||
.logo-container img {
|
||||
width: 70%;
|
||||
}
|
||||
.addonitem {
|
||||
font-size: 14px !important;
|
||||
margin: 0;
|
||||
/* margin-left: 5px; */
|
||||
font-weight: 700;
|
||||
}
|
||||
p {
|
||||
margin: 0 0 1ex;
|
||||
}
|
||||
.main {
|
||||
font-size: 20px !important;
|
||||
margin-left: 5px;
|
||||
width: 70%;
|
||||
font-weight: 700;
|
||||
}
|
||||
.menumain {
|
||||
width: 100%;
|
||||
margin-left: 0;
|
||||
font-weight: 700;
|
||||
font-size: 20px !important;
|
||||
}
|
||||
.menu-item-selection {
|
||||
max-height: 17em;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.subitem {
|
||||
font-size: 12px !important;
|
||||
font-weight: 300;
|
||||
}
|
||||
.bottom-container {
|
||||
padding: 10px;
|
||||
background-color: #0d0d0d;
|
||||
color: rgb(209, 209, 209);
|
||||
z-index: 3;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
margin-top: 10px;
|
||||
font-size: 13px !important;
|
||||
position:relative;
|
||||
}
|
||||
.clr-field input:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
.text-container {
|
||||
width: 70%;
|
||||
}
|
||||
.item-container {
|
||||
justify-content: space-between;
|
||||
width: 96%;
|
||||
margin: 0px auto;
|
||||
height: 3em;
|
||||
margin-top: 5px;
|
||||
border-bottom: 1px solid rgb(90, 90, 90);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
text-align: left;
|
||||
align-items: center;
|
||||
}
|
||||
.aboutcontainer {
|
||||
justify-content: space-between;
|
||||
width: 96%;
|
||||
margin: 0px auto;
|
||||
margin-top: 0px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
text-align: left;
|
||||
align-items: center;
|
||||
}
|
||||
.aboutlinks {
|
||||
display: flex;
|
||||
margin: 6px 0 !important;
|
||||
padding: 5px 18px !important;
|
||||
font-size: 12px;
|
||||
background: #3d3d3d !important;
|
||||
align-items: center;
|
||||
border-radius: 20px !important;
|
||||
color: white !important;
|
||||
border: none !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
.aboutlinks svg {
|
||||
margin: 0 !important;
|
||||
margin-right: 5px !important;
|
||||
}
|
||||
|
||||
.onoffswitch {
|
||||
margin: 0 0 1ex;
|
||||
position: relative; width: 42px;
|
||||
}
|
||||
.onoffswitch-checkbox {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#github {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
filter: invert(99%) sepia(0%) saturate(627%) hue-rotate(255deg)
|
||||
brightness(122%) contrast(100%);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.onoffswitch-label {
|
||||
display: block; overflow: hidden; cursor: pointer;
|
||||
height: 16px; padding: 0; line-height: 16px;
|
||||
border: 0px solid #FFFFFF; border-radius: 24px;
|
||||
background-color: #9E9E9E;
|
||||
}
|
||||
.onoffswitch-label:before {
|
||||
content: "";
|
||||
display: block; width: 24px; margin: -4px; height: 24px;
|
||||
background: #FFFFFF;
|
||||
position: absolute; top: 0; bottom: 0;
|
||||
right: 22px;
|
||||
border-radius: 24px;
|
||||
transition: 0.3s;
|
||||
}
|
||||
.onoffswitch-checkbox:checked + .onoffswitch-label {
|
||||
background-color: #20E060;
|
||||
}
|
||||
.onoffswitch-checkbox:checked + .onoffswitch-label, .onoffswitch-checkbox:checked + .onoffswitch-label:before {
|
||||
border-color: #20E060;
|
||||
}
|
||||
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-inner {
|
||||
margin-left: 0;
|
||||
}
|
||||
.onoffswitch-checkbox:checked + .onoffswitch-label:before {
|
||||
transition: 0.3s;
|
||||
right: 0px;
|
||||
background-color: #86F078;
|
||||
box-shadow: 3px 6px 18px 0px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.notification {
|
||||
width: 50px;
|
||||
height: 20px;
|
||||
}
|
||||
.notification::before {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
font: 10px/16px Helvetica;
|
||||
word-spacing: 26px;
|
||||
}
|
||||
.notification:checked:before {
|
||||
left: 32px;
|
||||
}
|
||||
.next-page {
|
||||
position: absolute;
|
||||
top: 280px;
|
||||
left: 270px;
|
||||
color: white;
|
||||
font-size: 15px;
|
||||
font-family: Rubik, sans-serif;
|
||||
}
|
||||
.item-container img {
|
||||
opacity: 0.6;
|
||||
}
|
||||
.clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
.back-button {
|
||||
width: 30%;
|
||||
font-size: 20px !important;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
padding: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.back-button img {
|
||||
transform: scaleX(-1);
|
||||
margin: 5px;
|
||||
margin-left: 0;
|
||||
}
|
||||
.menushortcuts {
|
||||
height: 2em;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
transition: 1.0s;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(127, 127, 127, 0.6);
|
||||
background-clip: padding-box;
|
||||
border: 2px solid transparent;
|
||||
transition: 1.0s;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:vertical:hover,
|
||||
::-webkit-scrollbar-thumb:horizontal:hover {
|
||||
background-color: rgb(110, 110, 110);
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
::-webkit-scrollbar-thumb:vertical:active,
|
||||
::-webkit-scrollbar-thumb:horizontal:active {
|
||||
background: rgba(95, 91, 91, 1);
|
||||
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-corner {
|
||||
background: none;
|
||||
}
|
||||
:root, html, body, div, ol {
|
||||
scrollbar-width: thin !important;
|
||||
scrollbar-color: #5e5e5f #161616 !important;
|
||||
}
|
||||
|
||||
|
||||
.topmenu {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
color: white;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
}
|
||||
.navitem {
|
||||
width: 33.34%;
|
||||
padding: 15px 0;
|
||||
position: relative;
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
text-transform: uppercase;
|
||||
overflow: hidden;
|
||||
border-bottom: 2px solid #a5a5a5;
|
||||
color: #a5a5a5;
|
||||
transition: 0.3s;
|
||||
|
||||
}
|
||||
.activenav {
|
||||
border-bottom: 2px solid #ff5f5f;
|
||||
color: #ff5f5f;
|
||||
}
|
||||
.hiddenmenu {
|
||||
display: none;
|
||||
}
|
||||
.applychanges {
|
||||
color: #fcdfb5;
|
||||
border: 2px solid #ffb64c;
|
||||
background-color: #131313;
|
||||
width: 35%;
|
||||
position: absolute;
|
||||
padding: 6px;
|
||||
cursor: pointer;
|
||||
bottom: 4px;
|
||||
left: -150px;
|
||||
z-index: 2;
|
||||
transition: 0.6s;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.applychanges:hover {
|
||||
background-color: #202020;
|
||||
}
|
||||
#applychanges {
|
||||
margin-top: 0px;
|
||||
}
|
||||
.applychanges h5, h6 {
|
||||
margin: 0;
|
||||
font-weight: 400;
|
||||
}
|
||||
.draggable {
|
||||
list-style: none;
|
||||
position: relative;
|
||||
margin-left: 10px;
|
||||
cursor:grab;
|
||||
}
|
||||
.draggable:active {
|
||||
cursor:-moz-grabbing;
|
||||
cursor: -webkit-grabbing;
|
||||
}
|
||||
.draggable::before {
|
||||
position: absolute;
|
||||
z-index: 20;
|
||||
left: -14px;
|
||||
top: 10px;
|
||||
content: url('data:image/svg+xml;charset=UTF-8, <svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="30" width="15"><path fill="white" d="M9,3H11V5H9V3M13,3H15V5H13V3M9,7H11V9H9V7M13,7H15V9H13V7M9,11H11V13H9V11M13,11H15V13H13V11M9,15H11V17H9V15M13,15H15V17H13V15M9,19H11V21H9V19M13,19H15V21H13V19Z" /></svg>');
|
||||
}
|
||||
.custom-shortcuts-button {
|
||||
width: 60%;
|
||||
height: 2em;
|
||||
background: #1a1a1a;
|
||||
color: white;
|
||||
font-size: 15px;
|
||||
padding: 0.4em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: 300ms;
|
||||
}
|
||||
.custom-shortcuts-buttons:hover {
|
||||
background: #161616;
|
||||
transition: 300ms;
|
||||
cursor: pointer;
|
||||
}
|
||||
.custom-shortcuts-buttons:active {
|
||||
background: #191919;
|
||||
transition: 300ms;
|
||||
}
|
||||
|
||||
.customshortcut-submit-valid {
|
||||
background: #20de5f !important;
|
||||
transition: 300ms;
|
||||
}
|
||||
|
||||
.customshortcut-submit-valid:hover {
|
||||
background: #1cc956 !important;
|
||||
transition: 300ms;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.customshortcut-submit-valid:active {
|
||||
background: #17aa48 !important;
|
||||
transition: 300ms;
|
||||
}
|
||||
|
||||
.custom-shortcuts-container {
|
||||
width: 93%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #1a1a1a;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
transition: 250ms;
|
||||
}
|
||||
.custom-shortcuts-container-shown {
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
height: auto;
|
||||
transition: 250ms;
|
||||
}
|
||||
|
||||
.custom-shortcuts-label {
|
||||
padding: 5px;
|
||||
text-align: initial;
|
||||
font-size: 15px;
|
||||
}
|
||||
.custom-shortcuts-field {
|
||||
background: #161616 !important;
|
||||
color: #b9b9b9 !important;
|
||||
font-size: 16px !important;
|
||||
padding: 10px !important;
|
||||
border-radius: 10px !important;
|
||||
border: 0 !important;
|
||||
box-shadow: 0 0 15px 4px rgb(0 0 0 / 6%) !important;
|
||||
transition: 100ms;
|
||||
}
|
||||
.custom-shortcuts-submit {
|
||||
width: 30%;
|
||||
font-size: 15px;
|
||||
margin-top: 0.5em;
|
||||
background: #161616;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.custom-shortcuts-field:focus {
|
||||
outline: none;
|
||||
outline: 1px solid rgb(60, 60, 60);
|
||||
transition: 100ms;
|
||||
}
|
||||
.domain-container {
|
||||
font-size: 9px;
|
||||
margin-top: 2px;
|
||||
color: white;
|
||||
margin-left: 10px;
|
||||
text-align: initial;
|
||||
}
|
||||
.domain-container-button {
|
||||
margin-top: 2px;
|
||||
font-size: 11px;
|
||||
padding: 5px 2px;
|
||||
width: 70%;
|
||||
border-radius: 10px;
|
||||
background: #1cc956;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
margin-left: 0;
|
||||
}
|
||||
.domain-container-button:hover {
|
||||
background: #1ed25a;
|
||||
}
|
||||
.domain-container-button:active {
|
||||
background: #19b34d;
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- // This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>. -->
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="coloris.css" />
|
||||
<script src="coloris.js"></script>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="info.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<style>
|
||||
body {
|
||||
width: 350px;
|
||||
margin: 0;
|
||||
background-color: #131313;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="logo-container"><img src="/icons/betterseqta-light-full.png"></div>
|
||||
<div class="main-page" id="mainpage">
|
||||
<div class="topmenu">
|
||||
<div class="navitem activenav" id="miscsection">Settings</div>
|
||||
<div class="navitem" id="shortcutsection">Shortcuts</div>
|
||||
<div class="navitem" id="aboutsection">About</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="menu-page hiddenmenu" id="menupage">
|
||||
<div class="selector-container" style="margin-bottom: 0;">
|
||||
|
||||
<div class="menu-item-selection">
|
||||
|
||||
<div class="aboutcontainer">
|
||||
<div>
|
||||
<h1 class="addonitem">About</h1>
|
||||
<p class="item subitem">Created and developed and maintained by RTC</p>
|
||||
<p class="item subitem">BestSEQTA is a fork or BestSEQTA
|
||||
which is no longer maintained.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="aboutcontainer">
|
||||
<div>
|
||||
<a class="aboutlinks"
|
||||
href="https://chrome.google.com/webstore/detail/betterseqta/boikofabjaholheekefimfojfncpjfib"
|
||||
target="_blank">
|
||||
<svg style="width:24px;height:24px" viewBox="0 0 24 24">
|
||||
<path fill="currentColor"
|
||||
d="M12,20L15.46,14H15.45C15.79,13.4 16,12.73 16,12C16,10.8 15.46,9.73 14.62,9H19.41C19.79,9.93 20,10.94 20,12A8,8 0 0,1 12,20M4,12C4,10.54 4.39,9.18 5.07,8L8.54,14H8.55C9.24,15.19 10.5,16 12,16C12.45,16 12.88,15.91 13.29,15.77L10.89,19.91C7,19.37 4,16.04 4,12M15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9A3,3 0 0,1 15,12M12,4C14.96,4 17.54,5.61 18.92,8H12C10.06,8 8.45,9.38 8.08,11.21L5.7,7.08C7.16,5.21 9.44,4 12,4M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z" />
|
||||
</svg>
|
||||
Chrome Webstore
|
||||
</a>
|
||||
<a class="aboutlinks" href="https://addons.mozilla.org/en-US/firefox/addon/betterseqta/" target="_blank">
|
||||
<svg style="width:24px;height:24px" viewBox="0 0 24 24">
|
||||
<path fill="currentColor"
|
||||
d="M9.27 7.94C9.27 7.94 9.27 7.94 9.27 7.94M6.85 6.74C6.86 6.74 6.86 6.74 6.85 6.74M21.28 8.6C20.85 7.55 19.96 6.42 19.27 6.06C19.83 7.17 20.16 8.28 20.29 9.1L20.29 9.12C19.16 6.3 17.24 5.16 15.67 2.68C15.59 2.56 15.5 2.43 15.43 2.3C15.39 2.23 15.36 2.16 15.32 2.09C15.26 1.96 15.2 1.83 15.17 1.69C15.17 1.68 15.16 1.67 15.15 1.67H15.13L15.12 1.67L15.12 1.67L15.12 1.67C12.9 2.97 11.97 5.26 11.74 6.71C11.05 6.75 10.37 6.92 9.75 7.22C9.63 7.27 9.58 7.41 9.62 7.53C9.67 7.67 9.83 7.74 9.96 7.68C10.5 7.42 11.1 7.27 11.7 7.23L11.75 7.23C11.83 7.22 11.92 7.22 12 7.22C12.5 7.21 12.97 7.28 13.44 7.42L13.5 7.44C13.6 7.46 13.67 7.5 13.75 7.5C13.8 7.54 13.86 7.56 13.91 7.58L14.05 7.64C14.12 7.67 14.19 7.7 14.25 7.73C14.28 7.75 14.31 7.76 14.34 7.78C14.41 7.82 14.5 7.85 14.54 7.89C14.58 7.91 14.62 7.94 14.66 7.96C15.39 8.41 16 9.03 16.41 9.77C15.88 9.4 14.92 9.03 14 9.19C17.6 11 16.63 17.19 11.64 16.95C11.2 16.94 10.76 16.85 10.34 16.7C10.24 16.67 10.14 16.63 10.05 16.58C10 16.56 9.93 16.53 9.88 16.5C8.65 15.87 7.64 14.68 7.5 13.23C7.5 13.23 8 11.5 10.83 11.5C11.14 11.5 12 10.64 12.03 10.4C12.03 10.31 10.29 9.62 9.61 8.95C9.24 8.59 9.07 8.42 8.92 8.29C8.84 8.22 8.75 8.16 8.66 8.1C8.43 7.3 8.42 6.45 8.63 5.65C7.6 6.12 6.8 6.86 6.22 7.5H6.22C5.82 7 5.85 5.35 5.87 5C5.86 5 5.57 5.16 5.54 5.18C5.19 5.43 4.86 5.71 4.56 6C4.21 6.37 3.9 6.74 3.62 7.14C3 8.05 2.5 9.09 2.28 10.18C2.28 10.19 2.18 10.59 2.11 11.1L2.08 11.33C2.06 11.5 2.04 11.65 2 11.91L2 11.94L2 12.27L2 12.32C2 17.85 6.5 22.33 12 22.33C16.97 22.33 21.08 18.74 21.88 14C21.9 13.89 21.91 13.76 21.93 13.63C22.13 11.91 21.91 10.11 21.28 8.6Z" />
|
||||
</svg>
|
||||
Firefox Add-ons
|
||||
</a>
|
||||
</svg>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="aboutcontainer" style="color: rgb(155, 155, 155); font-size: 14px; margin-top: 7px;">
|
||||
<p>Contact: cacakaca@outlook.com</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="menu-page hiddenmenu" id="shortcutpage">
|
||||
<div class="selector-container" style="margin-bottom: 0; max-height: 17em; overflow-y:hidden;">
|
||||
<div>
|
||||
<div class="custom-shortcuts-button custom-shortcuts-buttons">Create Custom Shortcut</div>
|
||||
<div class="custom-shortcuts-container">
|
||||
<label for="shortcutname" class="custom-shortcuts-label">Shortcut Name:</label>
|
||||
<input type="text" id="shortcutname" name="shortcutname" class="custom-shortcuts-field" placeholder="e.g. Google" maxlength="20">
|
||||
<label for="shortcuturl" class="custom-shortcuts-label">URL:</label>
|
||||
<input type="text" id="shortcuturl" name="shortcuturl" class="custom-shortcuts-field" placeholder="e.g. https://www.google.com">
|
||||
<div class="custom-shortcuts-submit custom-shortcuts-buttons">Create</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-item-selection menushortcut">
|
||||
<div class="item-container menushortcuts">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">YouTube</h1>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification shortcutitem" type="checkbox"
|
||||
id="youtube">
|
||||
<label for="youtube" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-container menushortcuts">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">Outlook</h1>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification shortcutitem" type="checkbox"
|
||||
id="outlook">
|
||||
<label for="outlook" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-container menushortcuts">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">Office</h1>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification shortcutitem" type="checkbox"
|
||||
id="office">
|
||||
<label for="office" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-container menushortcuts">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">Spotify</h1>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification shortcutitem" type="checkbox"
|
||||
id="spotify">
|
||||
<label for="spotify" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-container menushortcuts">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">Google</h1>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification shortcutitem" type="checkbox"
|
||||
id="google">
|
||||
<label for="google" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-container menushortcuts">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">DuckDuckGo</h1>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification shortcutitem" type="checkbox"
|
||||
id="duckduckgo">
|
||||
<label for="duckduckgo" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-container menushortcuts">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">Cool Math Games</h1>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification shortcutitem" type="checkbox"
|
||||
id="coolmathgames">
|
||||
<label for="coolmathgames" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-container menushortcuts">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">SACE</h1>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification shortcutitem" type="checkbox"
|
||||
id="sace">
|
||||
<label for="sace" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-container menushortcuts">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">Google Scholar</h1>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification shortcutitem" type="checkbox"
|
||||
id="googlescholar">
|
||||
<label for="googlescholar" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-container menushortcuts">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">Gmail</h1>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification shortcutitem" type="checkbox"
|
||||
id="gmail">
|
||||
<label for="gmail" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-container menushortcuts">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">Netflix</h1>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification shortcutitem" type="checkbox"
|
||||
id="netflix">
|
||||
<label for="netflix" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-container menushortcuts">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">Education Perfect</h1>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification shortcutitem" type="checkbox"
|
||||
id="netflix">
|
||||
<label for="educationperfect" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="menu-page" id="miscpage">
|
||||
<div class="selector-container" style="margin-bottom: 0;">
|
||||
<div class="menu-item-selection">
|
||||
|
||||
<div class="item-container">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">Notification Collector</h1>
|
||||
<p class="item subitem">Shows the real number of notifications</p>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification" type="checkbox" id="notification">
|
||||
<label for="notification" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-container">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">Lesson Alerts</h1>
|
||||
<p class="item subitem">Sends a native browser notification ~5 minutes prior to lessons.</p>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification" type="checkbox" id="lessonalert">
|
||||
<label for="lessonalert" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-container">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">Animated Background</h1>
|
||||
<p class="item subitem">Adds an animated background to BestSEQTA.</p>
|
||||
</div>
|
||||
<div class="onoffswitch"><input class="onoffswitch-checkbox notification" type="checkbox" id="animatedbk">
|
||||
<label for="animatedbk" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item-container">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">Custom Theme Colour</h1>
|
||||
<p class="item subitem">Customise the overall theme colour of SEQTA Learn.</p>
|
||||
</div>
|
||||
<div class="clr-field" style="justify-content: end; display: flex; margin: 5px;">
|
||||
<button aria-labelledby="clr-open-label"
|
||||
style="width: 51px; right: 0px; border: 1px solid white; border-radius: 3px;"></button>
|
||||
<input type="text" id="colorpicker" class="coloris"
|
||||
style="width: 48px; border-radius: 3px; padding: 6px 0;" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="item-container" style="height: 2em; margin-top: 0px;">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem">BestSEQTA</h1>
|
||||
</div>
|
||||
<div class="onoffswitch" style="margin-bottom: 0px;"><input class="onoffswitch-checkbox notification"
|
||||
type="checkbox" id="onoff">
|
||||
<label for="onoff" class="onoffswitch-label"></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="domain-container">Not working on your SEQTA?<div class="domain-container-button" id="domain-button">Add Permissions for Newer Domains</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="bottom-container">
|
||||
<div class="applychanges" id="applychanges">
|
||||
<div>
|
||||
<h5>Unsaved Changes</h5>
|
||||
<h6>Click to apply.</h6>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div></div>
|
||||
|
||||
<div style="position: absolute; bottom: 15px; right: 50px; color: rgb(177, 177, 177); display: flex;">
|
||||
<p style="margin: 0; margin-right: 5px; color: white;">Created by RTC </p>
|
||||
<p style="margin: 0; margin-right: 5px;" id="version"></p>
|
||||
</div><img src="/popup/github.svg" alt="" id="github">
|
||||
</div>
|
||||
<script src="info.js"></script>
|
||||
|
||||
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,342 @@
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const onoffselection = document.querySelector("#onoff");
|
||||
const notificationcollector = document.querySelector("#notification");
|
||||
const lessonalert = document.querySelector("#lessonalert");
|
||||
const aboutsection = document.querySelector("#aboutsection");
|
||||
const shortcutsection = document.querySelector("#shortcutsection");
|
||||
const miscsection = document.querySelector('#miscsection');
|
||||
const mainpage = document.querySelector("#mainpage");
|
||||
const colorpicker = document.querySelector("#colorpicker");
|
||||
const animatedbk = document.querySelector('#animatedbk');
|
||||
const customshortcutbutton = document.getElementsByClassName('custom-shortcuts-button')[0];
|
||||
const customshortcutdiv = document.getElementsByClassName('custom-shortcuts-container')[0];
|
||||
const customshortcutsubmit = document.getElementsByClassName('custom-shortcuts-submit')[0];
|
||||
const customshortcutinputname = document.querySelector('#shortcutname');
|
||||
const customshortcutinputurl = document.querySelector('#shortcuturl');
|
||||
|
||||
const shortcutmenuitemselection = document.getElementsByClassName('menushortcut')[0];
|
||||
|
||||
const applybutton = document.querySelector('#applychanges')
|
||||
|
||||
const navbuttons = document.getElementsByClassName("navitem");
|
||||
const menupages = document.getElementsByClassName("menu-page")
|
||||
|
||||
const allinputs = document.getElementsByTagName('input');
|
||||
|
||||
const menupage = document.querySelector("#menupage");
|
||||
|
||||
const shortcutpage = document.querySelector("#shortcutpage");
|
||||
|
||||
const miscpage = document.querySelector('#miscpage');
|
||||
|
||||
var shortcutbuttons = document.getElementsByClassName("shortcutitem");
|
||||
|
||||
const github = document.getElementById("github");
|
||||
|
||||
const version = document.getElementById('version');
|
||||
const domainbutton = document.getElementById('domain-button');
|
||||
|
||||
var validURL = false;
|
||||
var validName = false;
|
||||
|
||||
function openGithub() {
|
||||
chrome.tabs.create({ url: "https://github.com/OG-RandomTechChannel/BestSEQTA" });
|
||||
}
|
||||
|
||||
|
||||
function openPage(page) {
|
||||
mainpage.style.left = "-350px";
|
||||
page.style.right = '0px';
|
||||
}
|
||||
|
||||
function backToMainMenu() {
|
||||
mainpage.style.left = "0px";
|
||||
|
||||
menupage.style.right = "-350px";
|
||||
shortcutpage.style.right = "-350px";
|
||||
miscpage.style.right = "-350px";
|
||||
}
|
||||
|
||||
function resetActive() {
|
||||
for (let i = 0; i < navbuttons.length; i++) {
|
||||
navbuttons[i].classList.remove('activenav');
|
||||
}
|
||||
for (let i = 0; i < menupages.length; i++) {
|
||||
menupages[i].classList.add('hiddenmenu');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function FindSEQTATab() {
|
||||
chrome.tabs.query({}, function (tabs) {
|
||||
for (let tab of tabs) {
|
||||
if (tab.title.includes("SEQTA Learn")) {
|
||||
chrome.tabs.reload(tab.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
/*
|
||||
Store the currently selected settings using chrome.storage.local.
|
||||
*/
|
||||
function storeSettings() {
|
||||
chrome.storage.local.set({ onoff: onoffselection.checked }, function () {
|
||||
FindSEQTATab();
|
||||
});
|
||||
}
|
||||
|
||||
function storeNotificationSettings() {
|
||||
chrome.storage.local.set(
|
||||
{ notificationcollector: notificationcollector.checked });
|
||||
chrome.storage.local.set({ lessonalert: lessonalert.checked });
|
||||
chrome.storage.local.set({ animatedbk: animatedbk.checked });
|
||||
}
|
||||
|
||||
|
||||
function StoreAllSettings() {
|
||||
chrome.storage.local.get(["shortcuts"], function (result) {
|
||||
var shortcuts = Object.values(result)[0];
|
||||
for (var i = 0; i < shortcutbuttons.length; i++) {
|
||||
shortcuts[i].enabled = shortcutbuttons[i].checked;
|
||||
}
|
||||
chrome.storage.local.set({ shortcuts: shortcuts });
|
||||
});
|
||||
|
||||
FindSEQTATab();
|
||||
}
|
||||
/*
|
||||
Update the options UI with the settings values retrieved from storage,
|
||||
or the default settings if the stored settings are empty.
|
||||
*/
|
||||
function updateUI(restoredSettings) {
|
||||
if (typeof restoredSettings.onoff == 'undefined') {
|
||||
chrome.runtime.sendMessage({ type: "setDefaultStorage" });
|
||||
|
||||
chrome.storage.local.get(null, function (result) {
|
||||
updateUI(result);
|
||||
});
|
||||
} else {
|
||||
onoffselection.checked = restoredSettings.onoff;
|
||||
notificationcollector.checked = restoredSettings.notificationcollector;
|
||||
lessonalert.checked = restoredSettings.lessonalert;
|
||||
animatedbk.checked = restoredSettings.animatedbk;
|
||||
chrome.storage.local.get(["shortcuts"], function (result) {
|
||||
var shortcuts = Object.values(result)[0];
|
||||
for (var i = 0; i < shortcutbuttons.length; i++) {
|
||||
shortcutbuttons[i].checked = shortcuts[i].enabled;
|
||||
}
|
||||
chrome.storage.local.set({ shortcuts: shortcuts });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var stringtoHTML = function (str) {
|
||||
var parser = new DOMParser();
|
||||
var doc = parser.parseFromString(str, "text/html");
|
||||
return doc.body;
|
||||
};
|
||||
|
||||
function CreateShortcutDiv(name) {
|
||||
|
||||
div = stringtoHTML(`
|
||||
<div class="item-container menushortcuts" data-customshortcut="${name}">
|
||||
<div class="text-container">
|
||||
<h1 class="addonitem" style="font-size: 8px !important;font-weight: 300;">Custom</h1>
|
||||
<h1 class="addonitem">${name}</h1>
|
||||
</div>
|
||||
<svg id="delete-${name}" style="width:24px;height:24px;margin: 9px;cursor:pointer;" viewBox="0 0 24 24">
|
||||
<path fill="#ffffff" d="M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2C6.47,2 2,6.47 2,12C2,17.53 6.47,22 12,22C17.53,22 22,17.53 22,12C22,6.47 17.53,2 12,2M14.59,8L12,10.59L9.41,8L8,9.41L10.59,12L8,14.59L9.41,16L12,13.41L14.59,16L16,14.59L13.41,12L16,9.41L14.59,8Z"></path></svg>
|
||||
</div>`).firstChild;
|
||||
|
||||
shortcutmenuitemselection.append(div);
|
||||
|
||||
const deletebutton = document.getElementById(`delete-${name}`);
|
||||
deletebutton.addEventListener('click', function () {
|
||||
DeleteCustomShortcut(name);
|
||||
applybutton.style.left = "4px";
|
||||
});
|
||||
}
|
||||
|
||||
function AddCustomShortcuts() {
|
||||
chrome.storage.local.get(["customshortcuts"], function (result) {
|
||||
var customshortcuts = Object.values(result)[0];
|
||||
for (let i = 0; i < customshortcuts.length; i++) {
|
||||
const element = customshortcuts[i];
|
||||
CreateShortcutDiv(
|
||||
element.name,
|
||||
)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function DeleteCustomShortcut(name) {
|
||||
item = document.querySelector(`[data-customshortcut="${name}"]`);
|
||||
item.remove();
|
||||
chrome.storage.local.get(["customshortcuts"], function (result) {
|
||||
var customshortcuts = Object.values(result)[0];
|
||||
for (let i = 0; i < customshortcuts.length; i++) {
|
||||
if (customshortcuts[i].name == name) {
|
||||
customshortcuts.splice(i, 1);
|
||||
}
|
||||
}
|
||||
chrome.storage.local.set({ customshortcuts: customshortcuts });
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function CustomShortcutMenu() {
|
||||
customshortcutinputname.value = '';
|
||||
customshortcutinputurl.value = '';
|
||||
validURL = false;
|
||||
validName = false;
|
||||
customshortcutsubmit.classList.remove("customshortcut-submit-valid");
|
||||
if (customshortcutdiv.classList.contains('custom-shortcuts-container-shown')) {
|
||||
customshortcutdiv.classList.remove('custom-shortcuts-container-shown')
|
||||
} else {
|
||||
customshortcutdiv.classList.add('custom-shortcuts-container-shown')
|
||||
};
|
||||
}
|
||||
|
||||
function CreateCustomShortcut() {
|
||||
const shortcutname = customshortcutinputname.value;
|
||||
var shortcuturl = customshortcutinputurl.value;
|
||||
|
||||
if (!(shortcuturl.includes('http'))) {
|
||||
shortcuturl = "https://" + shortcuturl;
|
||||
}
|
||||
|
||||
chrome.storage.local.get(["customshortcuts"], function (result) {
|
||||
var customshortcuts = Object.values(result)[0];
|
||||
customshortcuts.push({ name: shortcutname, url: shortcuturl, icon: (shortcutname[0]).toUpperCase() });
|
||||
chrome.storage.local.set({ customshortcuts: customshortcuts });
|
||||
});
|
||||
|
||||
CreateShortcutDiv(
|
||||
shortcutname
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function onError(e) {
|
||||
console.error(e);
|
||||
}
|
||||
/*
|
||||
On opening the options page, fetch stored settings and update the UI with them.
|
||||
*/
|
||||
chrome.storage.local.get(null, function (result) {
|
||||
document.getElementsByClassName('clr-field')[0].style.color = result.selectedColor;
|
||||
colorpicker.value = result.selectedColor;
|
||||
console.log(result);
|
||||
updateUI(result);
|
||||
});
|
||||
|
||||
/*
|
||||
On blur, save the currently selected settings.
|
||||
*/
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
version.innerHTML = `v${chrome.runtime.getManifest().version}`;
|
||||
github.addEventListener("click", openGithub);
|
||||
|
||||
domainbutton.addEventListener('click', function (event) {
|
||||
chrome.runtime.sendMessage({ type: "addPermissions" });
|
||||
})
|
||||
|
||||
aboutsection.addEventListener("click", () => { resetActive(); aboutsection.classList.add('activenav'); menupage.classList.remove('hiddenmenu') });
|
||||
|
||||
shortcutsection.addEventListener("click", () => { resetActive(); shortcutsection.classList.add('activenav'); shortcutpage.classList.remove('hiddenmenu') });
|
||||
|
||||
miscsection.addEventListener("click", () => { resetActive(); miscsection.classList.add('activenav'); miscpage.classList.remove('hiddenmenu') });
|
||||
|
||||
customshortcutbutton.addEventListener("click", () => { CustomShortcutMenu(); })
|
||||
customshortcutsubmit.addEventListener("click", () => { if (validName && validURL) { CreateCustomShortcut(); CustomShortcutMenu() } });
|
||||
|
||||
var sameName = false;
|
||||
customshortcutinputname.addEventListener("input", function () {
|
||||
sameName = false;
|
||||
chrome.storage.local.get(["customshortcuts"], function (result) {
|
||||
var customshortcuts = Object.values(result)[0];
|
||||
for (let i = 0; i < customshortcuts.length; i++) {
|
||||
if (customshortcuts[i].name == customshortcutinputname.value) {
|
||||
sameName = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (customshortcutinputname.value.length > 0 && customshortcutinputname.value.length < 22 && !sameName) {
|
||||
validName = true;
|
||||
} else {
|
||||
validName = false;
|
||||
}
|
||||
|
||||
if (validName && validURL) {
|
||||
customshortcutsubmit.classList.add("customshortcut-submit-valid");
|
||||
}
|
||||
else {
|
||||
customshortcutsubmit.classList.remove("customshortcut-submit-valid");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
customshortcutinputurl.addEventListener("input", function () {
|
||||
if (customshortcutinputurl.value.length > 0 && customshortcutinputurl.value.includes('.')) {
|
||||
validURL = true;
|
||||
} else {
|
||||
validURL = false;
|
||||
}
|
||||
|
||||
if (validName && validURL) {
|
||||
customshortcutsubmit.classList.add("customshortcut-submit-valid");
|
||||
}
|
||||
else {
|
||||
customshortcutsubmit.classList.remove("customshortcut-submit-valid");
|
||||
}
|
||||
})
|
||||
|
||||
AddCustomShortcuts();
|
||||
});
|
||||
|
||||
onoffselection.addEventListener("change", storeSettings);
|
||||
notificationcollector.addEventListener(
|
||||
"change",
|
||||
storeNotificationSettings
|
||||
);
|
||||
lessonalert.addEventListener("change", storeNotificationSettings)
|
||||
|
||||
animatedbk.addEventListener("change", storeNotificationSettings)
|
||||
|
||||
for (let i = 0; i < allinputs.length; i++) {
|
||||
if (allinputs[i].id != 'colorpicker' && allinputs[i].id != "shortcuturl" && allinputs[i].id != "shortcutname") {
|
||||
allinputs[i].addEventListener("change", () => { applybutton.style.left = "4px" })
|
||||
}
|
||||
}
|
||||
|
||||
applybutton.addEventListener('click', () => { StoreAllSettings(); applybutton.style.left = "-150px" })
|
||||
|
||||
|
||||
colorpicker.addEventListener("input", function () {
|
||||
var colorPreview = document.querySelector('#clr-color-preview')
|
||||
if (colorPreview.style.color) {
|
||||
var hex = colorPreview.style.color.split("(")[1].split(")")[0];
|
||||
hex = hex.split(",");
|
||||
var b = hex.map(function (x) { //For each array element
|
||||
x = parseInt(x).toString(16); //Convert to a base16 string
|
||||
return (x.length == 1) ? "0" + x : x; //Add zero if we get only one character
|
||||
})
|
||||
b = "#" + b.join("");
|
||||
|
||||
chrome.storage.local.set({ selectedColor: b })
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
|
After Width: | Height: | Size: 1.5 KiB |