Skip to content

Instantly share code, notes, and snippets.

@dataserver
Last active March 5, 2024 12:08
Show Gist options
  • Save dataserver/7baa96ce14c170e66720c3ec7d57bfdf to your computer and use it in GitHub Desktop.
Save dataserver/7baa96ce14c170e66720c3ec7d57bfdf to your computer and use it in GitHub Desktop.
tampermonkey userscript boilerplate
// ==UserScript==
// @name userscript boilerplate
// @namespace userscriptnamespace
// @version 1
// @description Script description
// @author Author
// @match http://asdf.com/*
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery-popup-overlay/2.1.1/jquery.popupoverlay.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery.serializeJSON/2.9.0/jquery.serializejson.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/jquery.mark.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/alasql/0.4.11/alasql.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/jscolor/2.0.4/jscolor.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/lz-string/1.4.4/lz-string.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_deleteValue
// @grant GM_listValues
// ==/UserScript==
// ####################################################################################################################################
// ABOUT:
// SOURCE CODE: https://greasyfork.org/en/scripts/372121-
// REF:
// - js style guide https://github.com/airbnb/javascript
// - reserved words http://www.javascripter.net/faq/reserved.htm
// - template strings https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Template_literals
// - icons https://fontawesome.com/v4.7.0/cheatsheet/
// - alasql https://github.com/agershun/alasql/wiki/Getting-started
// - moment https://momentjs.com/docs/
// - lz-string http://pieroxy.net/blog/pages/lz-string/
// - underscore https://underscorejs.org/
/* global $:false, jQuery:false, debug:false, alasql:false, toastr:false, jscolor:false, moment:false, LZString:false, _:false */
((() => { // avoid conflicts
const DEBUG_MODE = true;
const SCRIPT_VERSION = 1;
const DEFAULT_CONFIG = {
font: 'Roboto',
color: '00cc00',
param_one: `1 Something here`,
param_text: `2 Text Another thing`,
param_three: `3 Three Third thing\nOhhhh`,
};
const MARKJS_OPTIONS = {
element: "mark",
className: "uscr-text-highlight",
separateWordSearch: true
};
const cssFiles = [
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/fontawesome.min.css",
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.9.0/css/solid.min.css",
"https://fonts.googleapis.com/icon?family=Material+Icons",
"https://cdnjs.cloudflare.com/ajax/libs/toastr.js/2.1.4/toastr.min.css"
];
// ####################################################################################################################################
let dbase;
let highlight_strings = [];
let storage = {
version: 1,
// compress: false,
options: {
prefix: ''
},
// Greasemonkey storage API
read: function (key, defaultValue) {
const raw = GM_getValue(this._prefix(key), defaultValue);
// let str = (this.compress) ? LZString.decompressFromUTF16(raw) : raw;
return this._parse(raw);
},
write: function (key, value) {
const raw = this._stringify(value);
// let str = (this.compress) ? LZString.compressToUTF16(raw) : raw;
return GM_setValue(this._prefix(key), raw);
},
delete: function (key) {
return GM_deleteValue(this._prefix(key));
},
readKeys: function () {
return GM_listValues();
},
// browser localstorage
// read: function (key, defaultValue) {
// const raw = localStorage.getItem(this._prefix(key), defaultValue);
// const val = raw || defaultValue;
// // const str = (this.compress) ? LZString.decompressFromUTF16(val) : val;
// // return this._parse(str);
// return this._parse(val);
// },
// write: function (key, value) {
// const raw = this._stringify(value);
// // let str = (this.compress) ? LZString.compressToUTF16(raw) : raw;
// localStorage.setItem(this._prefix(key), raw);
// return;
// },
// delete: function (key) {
// return localStorage.removeItem(this._prefix(key));
// },
// readKeys: function () {
// let keys = [];
// for(let i=0, l=localStorage.length; i < l; i++){
// keys.push( localStorage.getItem(localStorage.key(i)) );
// }
// return keys;
// },
// “Set” means “add if absent, replace if present.”
set: function (key, value) {
let savedVal = this.read(key);
if (typeof savedVal === 'undefined' || !savedVal) {
// add if absent
return this.add(key, value);
} else {
// replace if present
this.write(key, value);
return true;
}
},
// “Add” means “add if absent, do nothing if present” (if a uniquing collection).
add: function (key, value) {
let savedVal = this.read(key, false);
if (typeof savedVal === 'undefined' || !savedVal) {
this.write(key, value);
return true;
} else {
if (this._isArray(savedVal)) { // is array
let index = savedVal.indexOf(value);
if (index !== -1) {
// do nothing if present
return false;
} else {
// add if absent
savedVal.push(value);
this.write(key, savedVal);
return true;
}
} else if (this._isObject(savedVal)) { // is object
// merge obj value on obj
let result, objToMerge = value;
result = Object.assign(savedVal, objToMerge);
this.write(key, result);
return false;
}
return false;
}
},
// “Replace” means “replace if present, do nothing if absent.”
replace: function (key, itemFind, itemReplacement) {
let savedVal = this.read(key, false);
if (typeof savedVal === 'undefined' || !savedVal) {
// do nothing if absent
return false;
} else {
if (this._isArray(savedVal)) { // is Array
let index = savedVal.indexOf(itemFind);
if (index !== -1) {
// replace if present
savedVal[index] = itemReplacement;
this.write(key, savedVal);
return true;
} else {
// do nothing if absent
return false;
}
} else if (this._isObject(savedVal)) {
// is Object
// replace property's value
savedVal[itemFind] = itemReplacement;
this.write(key, savedVal);
return true;
}
return false;
}
},
// “Remove” means “remove if present, do nothing if absent.”
remove: function (key, value) {
if (typeof value === 'undefined') { // remove key
this.delete(key);
return true;
} else { // value present
let savedVal = this.read(key);
if (typeof savedVal === 'undefined' || !savedVal) {
return true;
} else {
if (this._isArray(savedVal)) { // is Array
let index = savedVal.indexOf(value);
if (index !== -1) {
// remove if present
savedVal.splice(index, 1);
this.write(key, savedVal);
return true;
} else {
// do nothing if absent
return false;
}
} else if (this._isObject(savedVal)) { // is Object
let property = value;
delete savedVal[property];
this.write(key, savedVal);
return true;
}
return false;
}
}
},
get: function (key, defaultValue) {
return this.read(key, defaultValue);
},
getAll: function () {
const keys = this._listKeys();
let obj = {};
for (let i = 0, len = keys.length; i < len; i++) {
obj[keys[i]] = this.read(keys[i]);
}
return obj;
},
getKeys: function () {
return this._listKeys();
},
getPrefix: function () {
return this.options.prefix;
},
empty: function () {
const keys = this._listKeys();
for (let i = 0, len = keys.lenght; i < len; i++) {
this.delete(keys[i]);
}
},
has: function (key) {
return this.get(key) !== null;
},
forEach: function (callbackFunc) {
const allContent = this.getAll();
for (let prop in allContent) {
callbackFunc(prop, allContent[prop]);
}
},
_parse: function (value) {
if (this._isJson(value)) {
return JSON.parse(value);
}
return value;
},
_stringify: function (value) {
if (this._isJson(value)) {
return value;
}
return JSON.stringify(value);
},
_listKeys: function (usePrefix = false) {
const prefixed = this.readKeys();
let unprefixed = [];
if (usePrefix) {
return prefixed;
} else {
for (let i = 0, len = prefixed.length; i < len; i++) {
unprefixed[i] = this._unprefix(prefixed[i]);
}
return unprefixed;
}
},
_prefix: function (key) {
return this.options.prefix + key;
},
_unprefix: function (key) {
return key.substring(this.options.prefix.length);
},
_isJson: function (item) {
try {
JSON.parse(item);
} catch (e) {
return false;
}
return true;
},
_isObject: function (a) {
return (!!a) && (a.constructor === Object);
},
_isArray: function (a) {
return (!!a) && (a.constructor === Array);
}
};
// https://stackoverflow.com/questions/7298364/using-jquery-and-json-to-populate-forms
function populateForm($form, data) {
$.each(data, (key, value) => { // all json fields ordered by name
let $ctrls, $ctrl;
if (value instanceof Array) {
$ctrls = $form.find("[name='" + key + "[]']"); //all form elements for a name. Multiple checkboxes can have the same name, but different values
} else {
$ctrls = $form.find("[name='" + key + "']");
}
if ($ctrls.is("select")) { //special form types
$("option", $ctrls).each(function () {
if (this.value == value) {
this.selected = true;
}
});
} else if ($ctrls.is("textarea")) {
$ctrls.val(value);
} else {
switch ($ctrls.attr("type")) { //input type
case "text":
case "range":
case "hidden":
$ctrls.val(value);
break;
case "radio":
if ($ctrls.length >= 1) {
$.each($ctrls, function (index) { // every individual element
let elemValue = $(this).attr("value");
let singleVal = value;
let elemValueInData = singleVal;
if (elemValue == value) {
$(this).prop("checked", true);
} else {
$(this).prop("checked", false);
}
});
}
break;
case "checkbox":
if ($ctrls.length > 1) {
$.each($ctrls, function (index) { // every individual element
let elemValue = $(this).attr("value");
let elemValueInData;
let singleVal;
for (let i = 0; i < value.length; i++) {
singleVal = value[i];
debug("singleVal", singleVal, "/value[i][1]", value[i][1]);
if (singleVal == elemValue) {
elemValueInData = singleVal;
}
}
if (elemValueInData) {
$(this).prop("checked", true);
} else {
$(this).prop("checked", false);
}
});
} else if ($ctrls.length == 1) {
$ctrl = $ctrls;
if (value) {
$ctrl.prop("checked", true);
} else {
$ctrl.prop("checked", false);
}
}
break;
}
}
});
}
function db_check_version() {
const stored_ver = parseInt(storage.get('version', 0), 10);
let upgrade = false;
if (stored_ver === 0) { // first run
setup_storage();
} else if (stored_ver === 111) {
upgrade_v2();
debug('set new version', SCRIPT_VERSION);
}
}
function setup_storage() {
// storage.set('configs', DEFAULT_CONFIG);
// storage.set('version', SCRIPT_VERSION);
}
function db_init() {
// let users_db = storage.get("users", []);
// let favorites_db = storage.get("favorites", []);
dbase = new alasql.Database("mybase");
// dbase.exec("CREATE TABLE users (id INT, name STRING, highlight INT, icon STRING, icon_color STRING, note STRING)");
// dbase.exec("CREATE TABLE favorites (postid INT, username STRING, note STRING)");
// if (users_db.length >= 1) {
// alasql.databases.mybase.tables.users.data = users_db;
// }
// if (favorites_db.length >= 1) {
// alasql.databases.mybase.tables.favorites.data = favorites_db;
// }
// setup_storage();
// db_clean();
}
function db_clean() {
// dbase.exec("DELETE FROM users");
// dbase.exec("DELETE FROM favorites");
db_save();
}
function db_save() {
// debug( alasql.databases.mybase.tables.users.data);
// storage.set("users", alasql.databases.mybase.tables.users.data);
// debug( alasql.databases.mybase.tables.favorites.data);
// storage.set("favorites", alasql.databases.mybase.tables.favorites.data);
}
function upgrade_v2() {
// storage.set('version', 2);
// do stuff
}
// CONFIG
function get_config() {
let cfg = storage.get('configs', DEFAULT_CONFIG);
debug('cfg', cfg);
return Object.assign({}, DEFAULT_CONFIG, cfg);
}
function set_config(configs) {
debug('props', Object.getOwnPropertyNames(configs).sort());
storage.set('configs', configs);
return configs;
}
// USER
function create_User(user) {
return {
id: parseInt(user.id),
name: (typeof user.name !== 'undefined') ? user.name : "",
flagged: (typeof user.flagged !== 'undefined') ? parseInt(user.flagged) : 0,
note: (typeof user.note !== 'undefined') ? user.note : ""
};
}
function get_user(id = 0) {
id = parseInt(id);
// let result = dbase.exec("SELECT * FROM users WHERE id = ? LIMIT 1", [id]);
// if (result.length > 0) {
// return result[0];
// } else {
// return null;
// }
}
function set_user(user = {}) {
// user.id = parseInt(user.id);
// user.highlight = parseInt(user.highlight);
// dbase.exec("DELETE FROM users WHERE id = ? ", [user.id]);
// dbase.exec("INSERT INTO users (?,?,?,?,?,?)", [user.id, user.name, user.highlight, user.icon, user.icon_color, user.note]);
db_save();
}
function delete_user(id = 0) {
id = parseInt(id);
// dbase.exec("DELETE FROM users WHERE id = ? ", [id]);
db_save();
}
// DEBUG
function set_debug(isDebug = false) {
if (isDebug) {
window.debug = window.console.log.bind(window.console);
} else {
window.debug = function () {};
}
}
function appendFilesToHead(arr = [], forceExt = false) {
for (let i = 0; i < arr.length; i++) {
let urlStr = arr[i];
let ext = (forceExt) ? forceExt : urlStr.slice((Math.max(0, urlStr.lastIndexOf(".")) || Infinity) + 1);
let ele = null;
switch (ext) {
case "js":
ele = document.createElement("script");
ele.type = "text/javascript";
ele.src = urlStr;
break;
case "css":
ele = document.createElement("link");
ele.rel = "stylesheet";
ele.type = "text/css";
ele.href = urlStr;
break;
default:
ele = document.createElement("script");
ele.type = "text/javascript";
ele.src = urlStr;
}
document.getElementsByTagName("head")[0].appendChild(ele);
}
}
function append_styles() {
let styles = ``;
let arrCss = cssFiles;
if (configs.forum_font != "") {
arrCss.push(`https://fonts.googleapis.com/css?family=${configs.font}`);
}
appendFilesToHead(arrCss, 'css');
// http://dev.vast.com/jquery-popup-overlay/
styles += `
<style data-style-id="js-uscr-fixed-style" type="text/css">
/* .mil {font-family: 'Lato', sans-serif;} */
.mil { color: #000000; line-height: 1.5; }
/* TYPOGRAPHY */
.mil h1 {font-size: 2.5rem;}
.mil h2 {font-size: 2rem;}
.mil h3 {font-size: 1.375rem;}
.mil h4 {font-size: 1.125rem;}
.mil h5 {font-size: 1rem;}
.mil h6 {font-size: 0.875rem;}
/* .mil p { font-size: 1.125rem; font-weight: 200; line-height: 1.8;} */
.mil .left {text-align: left;}
.mil .right {text-align: right;}
.mil .center {text-align: center; margin-left: auto; margin-right: auto;}
.mil .justify {text-align: justify;}
/* GRID */
.mil .container { width: 90%; margin-left: auto; margin-right: auto;}
.mil .row { position: relative; width: 100%; }
.mil .row [class^="col"] { float: left; margin: 0.5rem 2%; min-height: 0.125rem; }
.mil .col-1,.mil .col-2,.mil .col-3,.mil .col-4,.mil .col-5,.mil .col-6,.mil .col-7,.mil .col-8,.mil .col-9,.mil .col-10,.mil .col-11,.mil .col-12 { width: 96%; }
.mil .col-1-sm { width: 4.33%; }
.mil .col-2-sm { width: 12.66%; }
.mil .col-3-sm { width: 21%; }
.mil .col-4-sm { width: 29.33%; }
.mil .col-5-sm { width: 37.66%; }
.mil .col-6-sm { width: 46%; }
.mil .col-7-sm { width: 54.33%; }
.mil .col-8-sm { width: 62.66%; }
.mil .col-9-sm { width: 71%; }
.mil .col-10-sm { width: 79.33%; }
.mil .col-11-sm { width: 87.66%; }
.mil .col-12-sm { width: 96%; }
.mil .row::after { content: ""; display: table; clear: both;}
.mil .hidden-sm { display: none;}
@media only screen and (min-width: 33.75em) {/* 540px */
.mil .container { width: 80%; }
}
@media only screen and (min-width: 45em) {/* 720px */
.mil .col-1 { width: 4.33%; }
.mil .col-2 { width: 12.66%; }
.mil .col-3 { width: 21%; }
.mil .col-4 { width: 29.33%; }
.mil .col-5 { width: 37.66%; }
.mil .col-6 { width: 46%; }
.mil .col-7 { width: 54.33%; }
.mil .col-8 { width: 62.66%; }
.mil .col-9 { width: 71%; }
.mil .col-10-sm { width: 79.33%; }
.mil .col-11-sm { width: 87.66%; }
.mil .col-12-sm { width: 96%; }
.mil .hidden-sm { display: block; }
}
@media only screen and (min-width: 60em) {/* 960px */
.mil .container {width: 75%;max-width: 60rem;}
}
/* userscript css */
.css-uscr {color:#000000;}
.css-uscr a:link { color: #0000EE; }
.css-uscr a:visited { color: #551A8B; }
.css-uscr-cursor-pointer { cursor: pointer;}
.css-uscr-cursor-move { cursor: move;}
.css-uscr-hidden { display:none; }
.css-uscr-modal-resizable { overflow: auto; resize: both; }
.css-uscr-modal-draggable { position: absolute;}
.popup_visible .css-uscr-card {
-webkit-transform: scale(1);
-moz-transform: scale(1);
-ms-transform: scale(1);
transform: scale(1);
}
.css-uscr-full-overlay {
position: fixed;
background: #fff;
bottom: 0;
right: 0;
width: 0%;
height: 0%;
opacity: 0.9;
visibility: hidden;
overflow: auto;
z-index: 99998;
}
.css-uscr-card {
-webkit-transform: scale(0.8);
-moz-transform: scale(0.8);
-ms-transform: scale(0.8);
transform: scale(0.8);
z-index: 10000;
min-height:20px;
padding:19px;
margin-bottom:20px;
background-color:#FFFFFF;
border:1px solid #e3e3e3;
border-radius:4px;
-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);
box-shadow:inset 0 1px 1px rgba(0,0,0,.05)
}
.css-uscr-card FIELDSET {
border: 1px solid #000000;
padding: 5px;
margin-top: 10px;
}
.css-uscr-card FIELDSET LEGEND {
color: #000000;
padding: 2px 5px ;
margin-left: 10px;
}
.css-uscr-card BUTTON {
padding: 5px 10px;
text-align: center;
font-weight: bold;
display: inline-block;
border-radius: .5rem;
border: 3px solid transparent;
}
.css-uscr-button-row { text-align:center; margin-top: 20px;}
.css-uscr-card TABLE BUTTON { padding: 0px 10px;}
.css-uscr-card TEXTAREA { min-height: 250px; }
.css-uscr-card TEXTAREA,
.css-uscr-card INPUT[type="text"] { width: 95%; }
.css-uscr-slider {-webkit-appearance: none; appearance: none; width: 100%; background: #e3e3e3; outline: none; opacity: 0.7; -webkit-transition: .2s; transition: opacity .2s; }
.css-uscr-slider:hover { opacity: 1; }
.css-uscr-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 25px; height: 25px; background: #4CAF50; cursor: pointer;}
.css-uscr-slider::-moz-range-thumb { width: 25px; height: 25px; background: #4CAF50; cursor: pointer;}
.css-btn-primary {background-color: blue; cursor:pointer; color:white;}
.css-btn-danger {background-color: red; cursor:pointer; color:white;}
.css-btn-neutral {background-color: grey; cursor:pointer; color:white;}
.css-uscr-help-icon { text-align: right;cursor: pointer;}
.mil dl {
display: block;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0px;
margin-inline-end: 0px;
}
.mil dt {
display: block;
}
.mil dd {
display: block;
margin-inline-start: 40px;
}
.tables-row-hover tr:hover td{
background-color:#CFFFFD;
}
</style>
<style data-style-id="js-uscr-dynamic-style" type="text/css"></style>
`;
$('head').append(styles);
}
function append_modals() {
let cpButton, modals;
modals = `
<!-- USERSCRIPT -->
<!-- TEMPLATE -->
<div id="js-uscr-card-template" class="js-uscr-modal-draggable css-uscr css-uscr-card css-uscr-modal-resizable" style="display:none;">
<div class="mil">
<h2 class="js-uscr-modal-draggable-handler css-uscr-cursor-move">
Help
</h2>
<div class="row">
<div class="col-12">
<h2>Icons</h2>
<dl>
<dt>Top of Page</dt>
<dd><i class="fas fa-cog fa-lg"></i> - Open userscript options</dd>
<dd><i class="fas fa-bookmark fa-lg"></i> - Your Favorites</dd>
<dt>Under User Posts</dt>
<dd><i class="fas fa-sticky-note fa-lg"></i> - Write note about this user</dd>
<dd><i class="fas fa-paint-brush fa-lg"></i> - Highlight the username everywhere</dd>
<dd><i class="fas fa-bookmark fa-lg"></i> - Favorite this post</dd>
</dl>
<p></p>
<p>version: ${SCRIPT_VERSION}</p>
</div>
</div>
<p class="button-row">
<button type="button" class="js-uscr-card-button-close css-btn-neutral">Close</button>
</p>
</div>
</div>
<!-- /TEMPLATE -->
<!-- HELP -->
<div id="js-uscr-card-help" class="js-uscr-modal-draggable css-uscr css-uscr-card css-uscr-modal-resizable" style="min-width:50vh; min-height:40vh; display:none;">
<div class="mil">
<h2 class="js-uscr-modal-draggable-handler css-uscr-cursor-move">
Help
</h2>
<div class="row">
<div class="col-12">
<h2>Icons</h2>
<dl>
<dt>Top of Page</dt>
<dd><i class="fas fa-cog fa-lg"></i> - Open userscript options</dd>
<dd><i class="fas fa-bookmark fa-lg"></i> - Your Favorites</dd>
<dt>Under User Posts</dt>
<dd><i class="fas fa-sticky-note fa-lg"></i> - Write note about this user</dd>
<dd><i class="fas fa-paint-brush fa-lg"></i> - Highlight the username everywhere</dd>
<dd><i class="fas fa-bookmark fa-lg"></i> - Favorite this post</dd>
</dl>
<p></p>
<p>version: ${SCRIPT_VERSION}</p>
</div>
</div>
<p class="button-row">
<button type="button" class="js-uscr-card-button-close css-btn-neutral">Close</button>
</p>
</div>
</div>
<!-- /HELP -->
<!-- CPANEL -->
<div id="js-uscr-card-cpanel" class="js-uscr-modal-draggable css-uscr css-uscr-card css-uscr-modal-resizable" style="min-width:50vh; min-height:40vh; display:none;">
<div class="mil">
<form id="js-uscr-form-cpanel">
<h2 class="js-uscr-modal-draggable-handler css-uscr-cursor-move">Settings</h2>
<fieldset>
<legend>Field Set</legend>
<P>
<label>
<span>Param 1</span>
<br>
<input type="text" name="param_one" value="">
</label>
</p>
<P>
<label>
<span>Param 2</span>
<br>
<input type="text" name="param_text" value="">
</label>
</p>
<p>
<label>
<span>Color</span>
<br>
<input type="text" class="js-uscr-color" data-jscolor="{position:'top', zIndex:100002, width:101, padding:20, borderWidth:3}" data-bind="updateSampleText" name="color" value="" size="6">
</label>
</p>
<p>
<span class="js-uscr-color-sample">Lorem ipsum dolor sit amet, consectetur</span>
</p>
<p>
<label>
<span>Font</span>
<br>
<select name="font">
<option value="">- Use theme default -</option>
<option value="IBM+Plex+Mono">IBM Plex Mono</option>
<option value="Lato">Lato</option>
<option value="Merriweather">Merriweather</option>
<option value="Open+Sans">Opens Sans</option>
<option value="Questrial">Questrial</option>
<option value="Raleway">Raleway</option>
<option value="Roboto">Roboto</option>
<option value="Roboto+Mono">Roboto Mono</option>
<option value="Ubuntu">Ubuntu</option>
</select>
</label>
</p>
<p>
<label>
<span>Note</span>
<br>
<textarea name="param_three" row="3"></textarea>
</label>
</p>
</fieldset>
<!--
<fieldset>
<legend></legend>
<p>
<label>
<span></span>
<br>
</label>
</p>
</fieldset>
-->
<p class="button-row">
<button type="button" class="js-uscr-card-button-close css-btn-neutral">Close</button>
<button type="button" class="js-uscr-card-button-save css-btn-primary">Save</button>
</p>
</form>
<div align="right">
<span class="js-uscr-card-button-help css-uscr-help-icon"><i class="fas fa-question-circle fa-2x"></i></span>
</div>
</div>
</div>
<!-- /CPANEL -->
<!-- /USERSCRIPT -->
`;
cpButton = `
<!-- USERSCRIPT -->
<div>
<span class="js-uscr-card-cpanel-button-open" style="cursor: pointer;"><i class="fas fa-cogs fa-lg"></i> </span>
</div>
<!-- /USERSCRIPT -->
`;
$("BODY").append(modals);
$("BODY").append(cpButton);
}
function do_config_css() {
let css;
css = `.uscr-text-highlight {color:#${configs.hightlight_color}; background-color:#${configs.hightlight_bgcolor};}`;
// if (configs.banned_users_highlight) {
// css += `.uscr-title-banner-member {color:#${configs.banned_users_highlight_color};}`;
// }
if (configs.font != "") {
css += `body { font-family: "${configs.font}"; }`;
}
$("#uscr-dynamic-style").html(css);
$("#navigation.pageWidth").css({ "width": configs.forum_width + "vw" });
$("#content .pageWidth").css({ "width": configs.forum_width + "vw" });
}
// HIGHLIGHT
function do_highlight(arr = []) {
let db_strings;
let result;
let strings_comma = configs.highlight_strings;
let oldArray = strings_comma.split(",");
let trimedArr = oldArray.map(str => str.trim());
debug("do_highlight", result);
// result = mybase.exec("SELECT * FROM configs");
// if (result.length > 0) {
// db_strings = result.map(item => item.name);
// debug("db_strings", db_strings);
// }
// $("elementName").mark(strs, MARKJS_OPTIONS);
$("BODY").mark(trimedArr, MARKJS_OPTIONS);
}
function undo_highlight() {
$("BODY").unmark(MARKJS_OPTIONS);
}
function main() {
debug('main()', '');
// CARD > DRAG
$(document).on('mousedown', '.js-uscr-modal-draggable-handler', function (event) {
let move = $(this).closest('.js-uscr-modal-draggable');
let lastOffset = move.data('lastTransform');
let lastOffsetX = lastOffset ? lastOffset.dx : 0;
let lastOffsetY = lastOffset ? lastOffset.dy : 0;
let startX = event.pageX - lastOffsetX;
let startY = event.pageY - lastOffsetY;
$(document).on('mousemove', function (event) {
let newDx = event.pageX - startX;
let newDy = event.pageY - startY;
move.css('transform', 'translate(' + newDx + 'px, ' + newDy + 'px)');
move.data('lastTransform', {
dx: newDx,
dy: newDy
});
window.getSelection().removeAllRanges();
});
});
$(document).on('mouseup', function () {
$(this).off('mousemove');
});
// CARD > CPANEL > OPEN
$(document).on('click', '.js-uscr-card-cpanel-button-open', function (event) {
event.preventDefault();
$("BODY").addClass("css-uscr-noscroll");
$("#js-uscr-card-cpanel").popup({ blur: false, autoopen: true });
populateForm($("#js-uscr-card-cpanel FORM"), configs);
jscolor.installByClassName('js-uscr-color');
return false;
});
// CARD > BUTTON CLOSE
$(".js-uscr-card-button-close").click(function () {
event.preventDefault();
let card_id = $(this).closest('.css-uscr-card').attr("id");
$("BODY").removeClass("css-uscr-noscroll");
$(`#${card_id}`).popup('hide');
return false;
});
// CARD > BUTTON SAVE
$(".js-uscr-card-button-save").click(function () {
event.preventDefault();
let card_id = $(this).closest(".css-uscr-card").attr("id");
let formData = $(this).closest("form").serializeJSON();
console.log(formData);
switch (card_id) { //input type
case "js-uscr-card-":
break;
case "js-uscr-card-cpanel":
set_config(formData);
configs = get_config();
do_config_css();
break;
default:
}
$("BODY").removeClass("css-uscr-noscroll");
$(`#${card_id}`).popup('hide');
toastr.success('Saved');
return false;
});
// CARD > BUTTON DELETE
$(".js-uscr-card-button-delete").click(function () {
event.preventDefault();
let id;
let card_id = $(this).closest(".css-uscr-card").attr("id");
switch (card_id) {
case "js-uscr-card-":
id = $(this).closest("form[data-id]").attr("data-id");
break;
case "js-uscr-card-cpanel":
//id = '2';
//delete_xyz(card_id);
break;
default:
//something
}
$("BODY").removeClass("css-uscr-noscroll");
$(`#${card_id}`).popup('hide');
toastr.success('Deleted');
return false;
});
// CARD > BUTTON HELP
$('.js-uscr-card-button-help').click(function () {
event.preventDefault();
let card_id = $(this).closest(".css-uscr-card").attr("id");
$("BODY").addClass("css-uscr-noscroll");
$(`#${card_id}`).popup('hide');
$("#js-uscr-card-help").popup({ blur: false, autoopen: true });
return false;
});
// ====================================================================
$("#js-uscr-card-cpanel INPUT[data-bind='updateSampleText']").on('change', function () {
let color = $(this).val();
$(this).css("background-color", '#' + color);
$(".js-uscr-color-sample").css({ color: "#" + color });
return false;
});
} //main
// ========================================================================
set_debug(DEBUG_MODE);
db_check_version();
let configs = get_config();
toastr.options = {
toastClass: 'toastr',
positionClass: 'toast-top-full-width',
showDuration: 300,
hideDuration: 1000,
timeOut: 3000
};
$(document).ready(function () {
db_init();
append_styles();
append_modals();
main();
do_config_css();
});
}))();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment