Add Rescroller chromium
@ -0,0 +1,5 @@
|
|||||||
|
## About Rescroller
|
||||||
|
|
||||||
|
Rescroller allows you to customize the look and feel of scrollbars on webpages within Google Chrome. Using the included settings, set the color, shadows, borders, etc. of each scrollbar element, or write custom CSS to style the scrollbars manually.
|
||||||
|
|
||||||
|
[](https://chrome.google.com/webstore/detail/rescroller/ddehdnnhjimbggeeenghijehnpakijod)
|
@ -0,0 +1 @@
|
|||||||
|
[{"description":"treehash per file","signed_content":{"payload":"eyJjb250ZW50X2hhc2hlcyI6W3siYmxvY2tfc2l6ZSI6NDA5NiwiZGlnZXN0Ijoic2hhMjU2IiwiZmlsZXMiOlt7InBhdGgiOiJSRUFETUUubWQiLCJyb290X2hhc2giOiJ3VldaRHo5OUsza2F3SlhDZlY4ZXNFYTV6OEgwcVkzTFlFOTd2NFAwbXRzIn0seyJwYXRoIjoiUmlnaHRlb3VzLVJlZ3VsYXIudHRmIiwicm9vdF9oYXNoIjoiUGpPaTc1UFNlNFVzY21uM2R0bmFlcnhITjdsb2FfZHNYb2F2MktWdG1jZyJ9LHsicGF0aCI6ImFwcGljb25zL2ljb24xMjgucG5nIiwicm9vdF9oYXNoIjoiWFpnN3NFdk9SQkxrd2Zqd2JPUGdYUGNrZ1dwbk9TOWZvb3BIS19TRDVxUSJ9LHsicGF0aCI6ImFwcGljb25zL2ljb24xNi5wbmciLCJyb290X2hhc2giOiJFdzRsdVNzZkp4UEJUbjZ6N205U2xKNkJBa2E2Q2UxMUFOS0lxb21pTVVRIn0seyJwYXRoIjoiYXBwaWNvbnMvaWNvbjE5LnBuZyIsInJvb3RfaGFzaCI6ImhzZV9kbGJVZTdTanZORGd1SklBdG1QOUNPY19RSC13bzNfVFYxLWlVd1kifSx7InBhdGgiOiJhcHBpY29ucy9pY29uMzgucG5nIiwicm9vdF9oYXNoIjoiTzAzRUlfQUpuREgyUHozMUNjMmFlYVhMbXhWemZ6dXlTcEZCUXE4WkVzOCJ9LHsicGF0aCI6ImFwcGljb25zL2ljb240OC5wbmciLCJyb290X2hhc2giOiJFb3IxcFZ5Y3FwSzdlVzc1TjgwQkZtVVcxc1R1RUlYNnItblRJekw1QktVIn0seyJwYXRoIjoiaW1hZ2VzL2JnLnBuZyIsInJvb3RfaGFzaCI6IlZ6YU5pMjBxNmFHb2hmcEJ3RHpzMjR3NnozX1ltVzd6UjQwRzhIa1NiXzQifSx7InBhdGgiOiJpbWFnZXMvY2xvc2UtYnV0dG9uLnBuZyIsInJvb3RfaGFzaCI6Im02VkNCSUFCRm90Q0I5Z1VNN2RobVdja2xUZkJjTGN0TklYSzNLQnVycUkifSx7InBhdGgiOiJpbWFnZXMvZGVmYXVsdHMvZG93bi5wbmciLCJyb290X2hhc2giOiJpQmY2MVBoeTY1dm4wbzI2ZXlJVXFDUHoxaGttUnVmU2ZNYmFNaTB5RTJRIn0seyJwYXRoIjoiaW1hZ2VzL2RlZmF1bHRzL2xlZnQucG5nIiwicm9vdF9oYXNoIjoibUJscW5PQV84RldocXB6LUVINXpQVEpCbHdFcl9YOTFibEZ5RzF4V3RIZyJ9LHsicGF0aCI6ImltYWdlcy9kZWZhdWx0cy9yaWdodC5wbmciLCJyb290X2hhc2giOiJ5ZExHQTZSQ1plbkFaYmVzT0VRSmJjS3ZVbU5xSVBkMm1pTEtFWGcyb2NzIn0seyJwYXRoIjoiaW1hZ2VzL2RlZmF1bHRzL3VwLnBuZyIsInJvb3RfaGFzaCI6IkN1cm1yaUY4SG5ubEZyazdyRWlJYkFxSU4zVlJLUFVxS29iTUZDbTZkU3cifSx7InBhdGgiOiJpbWFnZXMvbG9nby1ob3Zlci5wbmciLCJyb290X2hhc2giOiJOUGsweU5zZEVNbXVSY2xvdV9fcFo2c1F2cWo2U2tld3FKN1M3YVljdnBzIn0seyJwYXRoIjoiaW1hZ2VzL2xvZ28ucG5nIiwicm9vdF9oYXNoIjoiV05Pbk5zdFN6QmpKbmZUWG5FZ2VnT1JUSjdwdFZQR0ZQSWRMNUppWXZRQSJ9LHsicGF0aCI6ImpzL2JhY2tncm91bmQuanMiLCJyb290X2hhc2giOiJoTDY1aGFOMjJxWTFsMC1nal9URzJvRjk5VXMxU1ZyeE9MMU9NOGd1SjhzIn0seyJwYXRoIjoianMvY3NzanNvbi5qcyIsInJvb3RfaGFzaCI6ImNVLWllQUExMER5MTJpcEhrajdpV2FZVTFJRXBUc3Q2X2JISW5WN0RMWUUifSx7InBhdGgiOiJqcy9qcXVlcnktbWluaWNvbG9ycy9pbWFnZXMvY29sb3JzLnBuZyIsInJvb3RfaGFzaCI6InZwbU1Ha29qbnVhYkQ3UG1LTC1aeW5lOFJTVDQtSXIwbHlrZ25QSVA0THMifSx7InBhdGgiOiJqcy9qcXVlcnktbWluaWNvbG9ycy9qcXVlcnkubWluaUNvbG9ycy5jc3MiLCJyb290X2hhc2giOiJ4Q3U4ZDYyakFtODJxdmJPOWZoMUVqblV1ZTVlM1hxTF83WWZCZHdDZFNjIn0seyJwYXRoIjoianMvanF1ZXJ5LW1pbmljb2xvcnMvanF1ZXJ5Lm1pbmlDb2xvcnMuanMiLCJyb290X2hhc2giOiJmRVpSbTF6aDVPVkxZWlhOc0JsZGxRX0pqQ0pwU3lzcjJzWmNoNHJRRzFjIn0seyJwYXRoIjoianMvanF1ZXJ5LXVpLmpzIiwicm9vdF9oYXNoIjoibWtuQ0cwSFFDS08tUTdKanczWXotckpiS2dldUlXZ3BlcVVaZXJZVDltcyJ9LHsicGF0aCI6ImpzL2pxdWVyeS5qcyIsInJvb3RfaGFzaCI6Im96UGZtWmtkYjRiS2d4WXdtaGptRXcxZE1nSXlfaC1jODhvTHZuM1dUV2sifSx7InBhdGgiOiJqcy9vcHRpb25zLmpzIiwicm9vdF9oYXNoIjoiRXhHS3luRmFvR1hvYXhXT0hpdnA4WFR3SEJHdlNTR2YwSzNhVEJJUHU3WSJ9LHsicGF0aCI6ImpzL3Jlc2Nyb2xsZXIuanMiLCJyb290X2hhc2giOiJudVdneDZZY25Yd01LZzh6anpDZFB0UEN5Q2RHZVJaT1dudVpCM1FKclpRIn0seyJwYXRoIjoibWFuaWZlc3QuanNvbiIsInJvb3RfaGFzaCI6IjVSUmJoUWhvSjRLVGtCTURiZTJYV25faXFSWmZPMS12ekRqQ1NsdjFpYmcifSx7InBhdGgiOiJub2h1cC5vdXQiLCJyb290X2hhc2giOiJNT0F1dXNrVkIyX29ra01LVDF1MjZqVGR4TUVFLU5OX2ZoYjhNMlVHS0xJIn0seyJwYXRoIjoib3B0aW9ucy5odG1sIiwicm9vdF9oYXNoIjoiRTlNRTZXaXZsOUVfaEdZM2Y0YWZ3Y25SRGRMLTNQcU82UkV5c0c1QWZ3OCJ9LHsicGF0aCI6InN0eWxlLmNzcyIsInJvb3RfaGFzaCI6InZySFNEOTh2M21HZkhScFZjdG9aYUk2RFlkeFZCbmN4MXRpMVVYd0RIdXcifV0sImZvcm1hdCI6InRyZWVoYXNoIiwiaGFzaF9ibG9ja19zaXplIjo0MDk2fV0sIml0ZW1faWQiOiJkZGVoZG5uaGppbWJnZ2VlZW5naGlqZWhucGFraWpvZCIsIml0ZW1fdmVyc2lvbiI6IjEuMyIsInByb3RvY29sX3ZlcnNpb24iOjF9","signatures":[{"header":{"kid":"publisher"},"protected":"eyJhbGciOiJSUzI1NiJ9","signature":"ghkBssOwtjM_sZKKAbrl3ezjK-TKYwfrMfWa1uFHs5kQ9K_Gyrv4f23ydLBS1DYU3Vb2jfLXVU9ng-byD0SNEzQshupx1lAg9YTjKxw3ngktdzHWSewEANmpljVinNwqqEp_oviMcc29rr_HVr5PFoucYWvuJ1Oec21YDIKuM9E"},{"header":{"kid":"webstore"},"protected":"eyJhbGciOiJSUzI1NiJ9","signature":"TzaONt0eUFC1D9jt2Rs-mWeZa0zAG8Ahig0kBBELA-fkT4vXLR3H4kAEy__RNqw6QgkwgoeZdJSdZP2VDYrDcDKE41axv1WyWFFNeyFuAkR8Gbn9Plu7Y6lsPMkQCG80M4H0tQWTT8ABd_vjBAlsZ0aL_5xRSJvZb23dZy2bBfQDsZp-PkHzuRJoK_vu9h1xnu0SOPjVI9E7Tz6MosaNP330RtnD3qmMU8zqeO48O0AzTJUeMcP-J_4t1VeBURo2bmc1F63Z2UjPpE36-XZI9ixyE0JXoApX1p9r3AvCIAYptz3JLGcOjb03rn0o4S7E5jZriMjGHzec9Xh6Q8dqpQ"}]}}]
|
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 638 B |
After Width: | Height: | Size: 744 B |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 662 B |
After Width: | Height: | Size: 339 B |
After Width: | Height: | Size: 334 B |
After Width: | Height: | Size: 344 B |
After Width: | Height: | Size: 258 B |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 5.4 KiB |
@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* Background Event page: this handles events for the extension between pages and performs the following:
|
||||||
|
*
|
||||||
|
* - Handles browser action button click (opening of options.html)
|
||||||
|
* - Handles first-time install by setting install_time in local storage and opening options.html
|
||||||
|
* - Hanldes changes to chrome.sync and syncs down CSS updated remotely
|
||||||
|
* - Hands generated CSS over to tabs when requested
|
||||||
|
*
|
||||||
|
* Note: because this is a non-persistent ('event') background page, this script will only load to run
|
||||||
|
* event callbacks. Do not put any code outside of listeners!
|
||||||
|
*
|
||||||
|
* Note: Unfortunately, we need to load jquery.js and cssjson.js here, since they are needed when the CSS
|
||||||
|
* hasn't been precomputed or needs to be regenerated.
|
||||||
|
*/
|
||||||
|
|
||||||
|
chrome.runtime.onInstalled.addListener(function(details) { // when extension installed/updated and chrome updated
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this is the first time running the extension, open options page
|
||||||
|
* and Download latest Chrome Storage to Local Storage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (details.reason != 'install') { // no need to sync down if updating.
|
||||||
|
Rescroller.performMigrations();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rescroller.syncDown(function() {
|
||||||
|
if (localStorage['install_time']) { return; } // only open options.html if this is the first install on any of the users' Chromes
|
||||||
|
|
||||||
|
localStorage['install_time'] = new Date().getTime();
|
||||||
|
chrome.tabs.create({ url: 'options.html' });
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listen for page states to change and set our custom CSS when tabs are loading
|
||||||
|
*/
|
||||||
|
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
|
||||||
|
if (changeInfo.status != 'loading') { return; }
|
||||||
|
|
||||||
|
// Check to make sure this url isn't blacklisted. Exit early if so
|
||||||
|
var restrictedSites = Rescroller.getListOfDisabledSites();
|
||||||
|
for (var restricted in restrictedSites) {
|
||||||
|
var restricted = restrictedSites[restricted];
|
||||||
|
|
||||||
|
if (!restricted) { continue; }
|
||||||
|
if (tab.url.indexOf(restricted) >= 0) { return; } // @todo this could probably be more accurate
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aaaand, inject our customized CSS into the webpage!
|
||||||
|
chrome.tabs.insertCSS(tabId, { // unfortunately, this requires the <all_urls> permission :/
|
||||||
|
code: localStorage['generated-css'],
|
||||||
|
allFrames: true,
|
||||||
|
runAt: 'document_start'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle action button in Chrome toolbar
|
||||||
|
*/
|
||||||
|
chrome.browserAction.onClicked.addListener(function(tab) {
|
||||||
|
chrome.tabs.create({ url: "options.html" });
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect changes to Chrome Storage, and import them into Local Storage
|
||||||
|
*/
|
||||||
|
chrome.storage.onChanged.addListener(function(changes, namespace) {
|
||||||
|
|
||||||
|
// Convert these 'changes' into a key-val object, parallel to how localStorage is formatted (no need for change[].oldValue)
|
||||||
|
var changesCleaned = {};
|
||||||
|
for (var key in changes) {
|
||||||
|
changesCleaned[key] = changes[key].newValue
|
||||||
|
}
|
||||||
|
|
||||||
|
Rescroller.mergeSyncWithLocalStorage(changesCleaned);
|
||||||
|
});
|
@ -0,0 +1,297 @@
|
|||||||
|
/**
|
||||||
|
* CSS-JSON Converter for JavaScript
|
||||||
|
* Converts CSS to JSON and back.
|
||||||
|
* Version 2.1
|
||||||
|
*
|
||||||
|
* Released under the MIT license.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Aram Kocharyan, http://aramk.com/
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
|
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
||||||
|
to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions
|
||||||
|
of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||||
|
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var CSSJSON = new function () {
|
||||||
|
|
||||||
|
var base = this;
|
||||||
|
|
||||||
|
base.init = function () {
|
||||||
|
// String functions
|
||||||
|
String.prototype.trim = function () {
|
||||||
|
return this.replace(/^\s+|\s+$/g, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
String.prototype.repeat = function (n) {
|
||||||
|
return new Array(1 + n).join(this);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
base.init();
|
||||||
|
|
||||||
|
var selX = /([^\s\;\{\}][^\;\{\}]*)\{/g;
|
||||||
|
var endX = /\}/g;
|
||||||
|
var lineX = /([^\;\{\}]*)\;/g;
|
||||||
|
var commentX = /\/\*[\s\S]*?\*\//g;
|
||||||
|
var lineAttrX = /([^\:]+):([^\;]*);/;
|
||||||
|
|
||||||
|
// This is used, a concatenation of all above. We use alternation to
|
||||||
|
// capture.
|
||||||
|
var altX = /(\/\*[\s\S]*?\*\/)|([^\s\;\{\}][^\;\{\}]*(?=\{))|(\})|([^\;\{\}]+\;(?!\s*\*\/))/gmi;
|
||||||
|
|
||||||
|
// Capture groups
|
||||||
|
var capComment = 1;
|
||||||
|
var capSelector = 2;
|
||||||
|
var capEnd = 3;
|
||||||
|
var capAttr = 4;
|
||||||
|
|
||||||
|
var isEmpty = function (x) {
|
||||||
|
return typeof x == 'undefined' || x.length == 0 || x == null;
|
||||||
|
};
|
||||||
|
|
||||||
|
var isCssJson = function (node) {
|
||||||
|
return !isEmpty(node) ? (node.attributes && node.children) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input is css string and current pos, returns JSON object
|
||||||
|
*
|
||||||
|
* @param cssString
|
||||||
|
* The CSS string.
|
||||||
|
* @param args
|
||||||
|
* An optional argument object. ordered: Whether order of
|
||||||
|
* comments and other nodes should be kept in the output. This
|
||||||
|
* will return an object where all the keys are numbers and the
|
||||||
|
* values are objects containing "name" and "value" keys for each
|
||||||
|
* node. comments: Whether to capture comments. split: Whether to
|
||||||
|
* split each comma separated list of selectors.
|
||||||
|
*/
|
||||||
|
base.toJSON = function (cssString, args) {
|
||||||
|
var node = {
|
||||||
|
children: {},
|
||||||
|
attributes: {}
|
||||||
|
};
|
||||||
|
var match = null;
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
|
if (typeof args == 'undefined') {
|
||||||
|
var args = {
|
||||||
|
ordered: false,
|
||||||
|
comments: false,
|
||||||
|
stripComments: false,
|
||||||
|
split: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (args.stripComments) {
|
||||||
|
args.comments = false;
|
||||||
|
cssString = cssString.replace(commentX, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((match = altX.exec(cssString)) != null) {
|
||||||
|
if (!isEmpty(match[capComment]) && args.comments) {
|
||||||
|
// Comment
|
||||||
|
var add = match[capComment].trim();
|
||||||
|
node[count++] = add;
|
||||||
|
} else if (!isEmpty(match[capSelector])) {
|
||||||
|
// New node, we recurse
|
||||||
|
var name = match[capSelector].trim();
|
||||||
|
// This will return when we encounter a closing brace
|
||||||
|
var newNode = base.toJSON(cssString, args);
|
||||||
|
if (args.ordered) {
|
||||||
|
var obj = {};
|
||||||
|
obj['name'] = name;
|
||||||
|
obj['value'] = newNode;
|
||||||
|
// Since we must use key as index to keep order and not
|
||||||
|
// name, this will differentiate between a Rule Node and an
|
||||||
|
// Attribute, since both contain a name and value pair.
|
||||||
|
obj['type'] = 'rule';
|
||||||
|
node[count++] = obj;
|
||||||
|
} else {
|
||||||
|
if (args.split) {
|
||||||
|
var bits = name.split(',');
|
||||||
|
} else {
|
||||||
|
var bits = [name];
|
||||||
|
}
|
||||||
|
for (i in bits) {
|
||||||
|
var sel = bits[i].trim();
|
||||||
|
if (sel in node.children) {
|
||||||
|
for (var att in newNode.attributes) {
|
||||||
|
node.children[sel].attributes[att] = newNode.attributes[att];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
node.children[sel] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!isEmpty(match[capEnd])) {
|
||||||
|
// Node has finished
|
||||||
|
return node;
|
||||||
|
} else if (!isEmpty(match[capAttr])) {
|
||||||
|
var line = match[capAttr].trim();
|
||||||
|
var attr = lineAttrX.exec(line);
|
||||||
|
if (attr) {
|
||||||
|
// Attribute
|
||||||
|
var name = attr[1].trim();
|
||||||
|
var value = attr[2].trim();
|
||||||
|
if (args.ordered) {
|
||||||
|
var obj = {};
|
||||||
|
obj['name'] = name;
|
||||||
|
obj['value'] = value;
|
||||||
|
obj['type'] = 'attr';
|
||||||
|
node[count++] = obj;
|
||||||
|
} else {
|
||||||
|
if (name in node.attributes) {
|
||||||
|
var currVal = node.attributes[name];
|
||||||
|
if (!(currVal instanceof Array)) {
|
||||||
|
node.attributes[name] = [currVal];
|
||||||
|
}
|
||||||
|
node.attributes[name].push(value);
|
||||||
|
} else {
|
||||||
|
node.attributes[name] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Semicolon terminated line
|
||||||
|
node[count++] = line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param node
|
||||||
|
* A JSON node.
|
||||||
|
* @param depth
|
||||||
|
* The depth of the current node; used for indentation and
|
||||||
|
* optional.
|
||||||
|
* @param breaks
|
||||||
|
* Whether to add line breaks in the output.
|
||||||
|
*/
|
||||||
|
base.toCSS = function (node, depth, breaks) {
|
||||||
|
var cssString = '';
|
||||||
|
if (typeof depth == 'undefined') {
|
||||||
|
depth = 0;
|
||||||
|
}
|
||||||
|
if (typeof breaks == 'undefined') {
|
||||||
|
breaks = false;
|
||||||
|
}
|
||||||
|
if (node.attributes) {
|
||||||
|
for (i in node.attributes) {
|
||||||
|
var att = node.attributes[i];
|
||||||
|
if (att instanceof Array) {
|
||||||
|
for (var j = 0; j < att.length; j++) {
|
||||||
|
cssString += strAttr(i, att[j], depth);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cssString += strAttr(i, att, depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.children) {
|
||||||
|
var first = true;
|
||||||
|
for (i in node.children) {
|
||||||
|
if (breaks && !first) {
|
||||||
|
cssString += '\n';
|
||||||
|
} else {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
cssString += strNode(i, node.children[i], depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cssString;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param data
|
||||||
|
* You can pass css string or the CSSJS.toJSON return value.
|
||||||
|
* @param id (Optional)
|
||||||
|
* To identify and easy removable of the style element
|
||||||
|
* @param replace (Optional. defaults to TRUE)
|
||||||
|
* Whether to remove or simply do nothing
|
||||||
|
* @return HTMLLinkElement
|
||||||
|
*/
|
||||||
|
base.toHEAD = function (data, id, replace) {
|
||||||
|
var head = document.getElementsByTagName('head')[0];
|
||||||
|
var xnode = document.getElementById(id);
|
||||||
|
var _xnodeTest = (xnode !== null && xnode instanceof HTMLStyleElement);
|
||||||
|
|
||||||
|
if (isEmpty(data) || !(head instanceof HTMLHeadElement)) return;
|
||||||
|
if (_xnodeTest) {
|
||||||
|
if (replace === true || isEmpty(replace)) {
|
||||||
|
xnode.removeAttribute('id');
|
||||||
|
} else return;
|
||||||
|
}
|
||||||
|
if (isCssJson(data)) {
|
||||||
|
data = base.toCSS(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
var node = document.createElement('style');
|
||||||
|
node.type = 'text/css';
|
||||||
|
|
||||||
|
if (!isEmpty(id)) {
|
||||||
|
node.id = id;
|
||||||
|
} else {
|
||||||
|
node.id = 'cssjson_' + timestamp();
|
||||||
|
}
|
||||||
|
if (node.styleSheet) {
|
||||||
|
node.styleSheet.cssText = data;
|
||||||
|
} else {
|
||||||
|
node.appendChild(document.createTextNode(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
head.appendChild(node);
|
||||||
|
|
||||||
|
if (isValidStyleNode(node)) {
|
||||||
|
if (_xnodeTest) {
|
||||||
|
xnode.parentNode.removeChild(xnode);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
node.parentNode.removeChild(node);
|
||||||
|
if (_xnodeTest) {
|
||||||
|
xnode.setAttribute('id', id);
|
||||||
|
node = xnode;
|
||||||
|
} else return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Alias
|
||||||
|
|
||||||
|
if (typeof window != 'undefined') {
|
||||||
|
window.createCSS = base.toHEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
|
||||||
|
var isValidStyleNode = function (node) {
|
||||||
|
return (node instanceof HTMLStyleElement) && node.sheet.cssRules.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var timestamp = function () {
|
||||||
|
return Date.now() || +new Date();
|
||||||
|
};
|
||||||
|
|
||||||
|
var strAttr = function (name, value, depth) {
|
||||||
|
return '\t'.repeat(depth) + name + ': ' + value + ';\n';
|
||||||
|
};
|
||||||
|
|
||||||
|
var strNode = function (name, value, depth) {
|
||||||
|
var cssString = '\t'.repeat(depth) + name + ' {\n';
|
||||||
|
cssString += base.toCSS(value, depth + 1);
|
||||||
|
cssString += '\t'.repeat(depth) + '}\n';
|
||||||
|
return cssString;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
After Width: | Height: | Size: 12 KiB |
@ -0,0 +1,81 @@
|
|||||||
|
.miniColors-trigger {
|
||||||
|
height: 22px;
|
||||||
|
width: 22px;
|
||||||
|
background: url(images/trigger.png) center no-repeat;
|
||||||
|
vertical-align: middle;
|
||||||
|
margin: 0 .25em;
|
||||||
|
display: inline-block;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniColors-selector {
|
||||||
|
position: absolute;
|
||||||
|
width: 175px;
|
||||||
|
height: 150px;
|
||||||
|
background: #FFF;
|
||||||
|
border: solid 1px #BBB;
|
||||||
|
-moz-box-shadow: 0 0 6px rgba(0, 0, 0, .25);
|
||||||
|
-webkit-box-shadow: 0 0 6px rgba(0, 0, 0, .25);
|
||||||
|
box-shadow: 0 0 6px rgba(0, 0, 0, .25);
|
||||||
|
-moz-border-radius: 5px;
|
||||||
|
-webkit-border-radius: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
z-index: 999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniColors-selector.black {
|
||||||
|
background: #000;
|
||||||
|
border-color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniColors-colors {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
left: 5px;
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
background: url(images/colors.png) right no-repeat;
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniColors-hues {
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
left: 160px;
|
||||||
|
width: 20px;
|
||||||
|
height: 150px;
|
||||||
|
background: url(images/colors.png) left no-repeat;
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniColors-colorPicker {
|
||||||
|
position: absolute;
|
||||||
|
width: 9px;
|
||||||
|
height: 9px;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
-moz-border-radius: 11px;
|
||||||
|
-webkit-border-radius: 11px;
|
||||||
|
border-radius: 11px;
|
||||||
|
}
|
||||||
|
.miniColors-colorPicker-inner {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 7px;
|
||||||
|
height: 7px;
|
||||||
|
border: 1px solid #000;
|
||||||
|
-moz-border-radius: 9px;
|
||||||
|
-webkit-border-radius: 9px;
|
||||||
|
border-radius: 9px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniColors-huePicker {
|
||||||
|
position: absolute;
|
||||||
|
left: -3px;
|
||||||
|
width: 24px;
|
||||||
|
height: 1px;
|
||||||
|
border: 1px solid #fff;
|
||||||
|
border-radius: 2px;
|
||||||
|
background: #000;
|
||||||
|
}
|
@ -0,0 +1,592 @@
|
|||||||
|
/*
|
||||||
|
* jQuery miniColors: A small color selector
|
||||||
|
*
|
||||||
|
* Copyright 2011 Cory LaViska for A Beautiful Site, LLC. (http://abeautifulsite.net/)
|
||||||
|
*
|
||||||
|
* Dual licensed under the MIT or GPL Version 2 licenses
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(jQuery) (function($) {
|
||||||
|
|
||||||
|
$.extend($.fn, {
|
||||||
|
|
||||||
|
miniColors: function(o, data) {
|
||||||
|
|
||||||
|
var create = function(input, o, data) {
|
||||||
|
//
|
||||||
|
// Creates a new instance of the miniColors selector
|
||||||
|
//
|
||||||
|
|
||||||
|
// Determine initial color (defaults to white)
|
||||||
|
var color = expandHex(input.val());
|
||||||
|
if( !color ) color = 'ffffff';
|
||||||
|
var hsb = hex2hsb(color);
|
||||||
|
|
||||||
|
// Create trigger
|
||||||
|
var trigger = $('<a class="miniColors-trigger" style="background-color: #' + color + '" href="#"></a>');
|
||||||
|
trigger.insertAfter(input);
|
||||||
|
|
||||||
|
// Set input data and update attributes
|
||||||
|
input
|
||||||
|
.addClass('miniColors')
|
||||||
|
.data('original-maxlength', input.attr('maxlength') || null)
|
||||||
|
.data('original-autocomplete', input.attr('autocomplete') || null)
|
||||||
|
.data('letterCase', 'uppercase')
|
||||||
|
.data('trigger', trigger)
|
||||||
|
.data('hsb', hsb)
|
||||||
|
.data('change', o.change ? o.change : null)
|
||||||
|
.data('close', o.close ? o.close : null)
|
||||||
|
.data('open', o.open ? o.open : null)
|
||||||
|
.attr('maxlength', 7)
|
||||||
|
.attr('autocomplete', 'off')
|
||||||
|
.val('#' + convertCase(color, o.letterCase));
|
||||||
|
|
||||||
|
// Handle options
|
||||||
|
if( o.readonly ) input.prop('readonly', true);
|
||||||
|
if( o.disabled ) disable(input);
|
||||||
|
|
||||||
|
// Show selector when trigger is clicked
|
||||||
|
trigger.bind('click.miniColors', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
if( input.val() === '' ) input.val('#');
|
||||||
|
show(input);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show selector when input receives focus
|
||||||
|
input.bind('focus.miniColors', function(event) {
|
||||||
|
if( input.val() === '' ) input.val('#');
|
||||||
|
show(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hide on blur
|
||||||
|
input.bind('blur.miniColors', function(event) {
|
||||||
|
var hex = expandHex( hsb2hex(input.data('hsb')) );
|
||||||
|
input.val( hex ? '#' + convertCase(hex, input.data('letterCase')) : '' );
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hide when tabbing out of the input
|
||||||
|
input.bind('keydown.miniColors', function(event) {
|
||||||
|
if( event.keyCode === 9 ) hide(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update when color is typed in
|
||||||
|
input.bind('keyup.miniColors', function(event) {
|
||||||
|
setColorFromInput(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle pasting
|
||||||
|
input.bind('paste.miniColors', function(event) {
|
||||||
|
// Short pause to wait for paste to complete
|
||||||
|
setTimeout( function() {
|
||||||
|
setColorFromInput(input);
|
||||||
|
}, 5);
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var destroy = function(input) {
|
||||||
|
//
|
||||||
|
// Destroys an active instance of the miniColors selector
|
||||||
|
//
|
||||||
|
|
||||||
|
hide();
|
||||||
|
input = $(input);
|
||||||
|
|
||||||
|
// Restore to original state
|
||||||
|
input.data('trigger').remove();
|
||||||
|
input
|
||||||
|
.attr('autocomplete', input.data('original-autocomplete'))
|
||||||
|
.attr('maxlength', input.data('original-maxlength'))
|
||||||
|
.removeData()
|
||||||
|
.removeClass('miniColors')
|
||||||
|
.unbind('.miniColors');
|
||||||
|
$(document).unbind('.miniColors');
|
||||||
|
};
|
||||||
|
|
||||||
|
var enable = function(input) {
|
||||||
|
//
|
||||||
|
// Enables the input control and the selector
|
||||||
|
//
|
||||||
|
input
|
||||||
|
.prop('disabled', false)
|
||||||
|
.data('trigger')
|
||||||
|
.css('opacity', 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
var disable = function(input) {
|
||||||
|
//
|
||||||
|
// Disables the input control and the selector
|
||||||
|
//
|
||||||
|
hide(input);
|
||||||
|
input
|
||||||
|
.prop('disabled', true)
|
||||||
|
.data('trigger')
|
||||||
|
.css('opacity', 0.5);
|
||||||
|
};
|
||||||
|
|
||||||
|
var show = function(input) {
|
||||||
|
//
|
||||||
|
// Shows the miniColors selector
|
||||||
|
//
|
||||||
|
if( input.prop('disabled') ) return false;
|
||||||
|
|
||||||
|
// Hide all other instances
|
||||||
|
hide();
|
||||||
|
|
||||||
|
//Lines 145 and 146 and 147 were modified below by dwat to display color picker to the right of the "trigger" and the "apply" button
|
||||||
|
|
||||||
|
// Generate the selector
|
||||||
|
var selector = $('<div class="miniColors-selector"></div>');
|
||||||
|
selector
|
||||||
|
.append('<div class="miniColors-colors" style="background-color: #FFF;"><div class="miniColors-colorPicker"><div class="miniColors-colorPicker-inner"></div></div>')
|
||||||
|
.append('<div class="miniColors-hues"><div class="miniColors-huePicker"></div></div>')
|
||||||
|
.append('<div class="miniColors-apply"><a href="#">Apply</a></div>') //Added by dwat
|
||||||
|
.css({
|
||||||
|
top: input.is(':visible') ? input.offset().top + input.outerHeight() : input.data('trigger').offset().top + input.data('trigger').outerHeight() - ($(".miniColors-trigger").outerHeight() * 2.5),
|
||||||
|
left: input.is(':visible') ? input.offset().left : input.data('trigger').offset().left + $(".miniColors-trigger").outerWidth() + 3,
|
||||||
|
display: 'none'
|
||||||
|
})
|
||||||
|
.addClass( input.attr('class') );
|
||||||
|
|
||||||
|
// Set background for colors
|
||||||
|
var hsb = input.data('hsb');
|
||||||
|
selector
|
||||||
|
.find('.miniColors-colors')
|
||||||
|
.css('backgroundColor', '#' + hsb2hex({ h: hsb.h, s: 100, b: 100 }));
|
||||||
|
|
||||||
|
// Set colorPicker position
|
||||||
|
var colorPosition = input.data('colorPosition');
|
||||||
|
if( !colorPosition ) colorPosition = getColorPositionFromHSB(hsb);
|
||||||
|
selector.find('.miniColors-colorPicker')
|
||||||
|
.css('top', colorPosition.y + 'px')
|
||||||
|
.css('left', colorPosition.x + 'px');
|
||||||
|
|
||||||
|
// Set huePicker position
|
||||||
|
var huePosition = input.data('huePosition');
|
||||||
|
if( !huePosition ) huePosition = getHuePositionFromHSB(hsb);
|
||||||
|
selector.find('.miniColors-huePicker').css('top', huePosition.y + 'px');
|
||||||
|
|
||||||
|
// Set input data
|
||||||
|
input
|
||||||
|
.data('selector', selector)
|
||||||
|
.data('huePicker', selector.find('.miniColors-huePicker'))
|
||||||
|
.data('colorPicker', selector.find('.miniColors-colorPicker'))
|
||||||
|
.data('mousebutton', 0);
|
||||||
|
|
||||||
|
$('BODY').append(selector);
|
||||||
|
selector.fadeIn(100);
|
||||||
|
|
||||||
|
// Prevent text selection in IE
|
||||||
|
selector.bind('selectstart', function() { return false; });
|
||||||
|
|
||||||
|
$(document).bind('mousedown.miniColors touchstart.miniColors', function(event) {
|
||||||
|
|
||||||
|
input.data('mousebutton', 1);
|
||||||
|
var testSubject = $(event.target).parents().andSelf();
|
||||||
|
|
||||||
|
if( testSubject.hasClass('miniColors-colors') ) {
|
||||||
|
event.preventDefault();
|
||||||
|
input.data('moving', 'colors');
|
||||||
|
moveColor(input, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( testSubject.hasClass('miniColors-hues') ) {
|
||||||
|
event.preventDefault();
|
||||||
|
input.data('moving', 'hues');
|
||||||
|
moveHue(input, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( testSubject.hasClass('miniColors-selector') ) {
|
||||||
|
event.preventDefault();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( testSubject.hasClass('miniColors') ) return;
|
||||||
|
|
||||||
|
hide(input);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document)
|
||||||
|
.bind('mouseup.miniColors touchend.miniColors', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
input.data('mousebutton', 0).removeData('moving');
|
||||||
|
})
|
||||||
|
.bind('mousemove.miniColors touchmove.miniColors', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
if( input.data('mousebutton') === 1 ) {
|
||||||
|
if( input.data('moving') === 'colors' ) moveColor(input, event);
|
||||||
|
if( input.data('moving') === 'hues' ) moveHue(input, event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fire open callback
|
||||||
|
if( input.data('open') ) {
|
||||||
|
input.data('open').call(input.get(0), '#' + hsb2hex(hsb), hsb2rgb(hsb));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var hide = function(input) {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Hides one or more miniColors selectors
|
||||||
|
//
|
||||||
|
|
||||||
|
// Hide all other instances if input isn't specified
|
||||||
|
if( !input ) input = '.miniColors';
|
||||||
|
|
||||||
|
$(input).each( function() {
|
||||||
|
var selector = $(this).data('selector');
|
||||||
|
$(this).removeData('selector');
|
||||||
|
$(selector).fadeOut(100, function() {
|
||||||
|
// Fire close callback
|
||||||
|
if( input.data('close') ) {
|
||||||
|
var hsb = input.data('hsb'), hex = hsb2hex(hsb);
|
||||||
|
input.data('close').call(input.get(0), '#' + hex, hsb2rgb(hsb));
|
||||||
|
}
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).unbind('.miniColors');
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var moveColor = function(input, event) {
|
||||||
|
|
||||||
|
var colorPicker = input.data('colorPicker');
|
||||||
|
|
||||||
|
colorPicker.hide();
|
||||||
|
|
||||||
|
var position = {
|
||||||
|
x: event.pageX,
|
||||||
|
y: event.pageY
|
||||||
|
};
|
||||||
|
|
||||||
|
// Touch support
|
||||||
|
if( event.originalEvent.changedTouches ) {
|
||||||
|
position.x = event.originalEvent.changedTouches[0].pageX;
|
||||||
|
position.y = event.originalEvent.changedTouches[0].pageY;
|
||||||
|
}
|
||||||
|
position.x = position.x - input.data('selector').find('.miniColors-colors').offset().left - 5;
|
||||||
|
position.y = position.y - input.data('selector').find('.miniColors-colors').offset().top - 5;
|
||||||
|
if( position.x <= -5 ) position.x = -5;
|
||||||
|
if( position.x >= 144 ) position.x = 144;
|
||||||
|
if( position.y <= -5 ) position.y = -5;
|
||||||
|
if( position.y >= 144 ) position.y = 144;
|
||||||
|
|
||||||
|
input.data('colorPosition', position);
|
||||||
|
colorPicker.css('left', position.x).css('top', position.y).show();
|
||||||
|
|
||||||
|
// Calculate saturation
|
||||||
|
var s = Math.round((position.x + 5) * 0.67);
|
||||||
|
if( s < 0 ) s = 0;
|
||||||
|
if( s > 100 ) s = 100;
|
||||||
|
|
||||||
|
// Calculate brightness
|
||||||
|
var b = 100 - Math.round((position.y + 5) * 0.67);
|
||||||
|
if( b < 0 ) b = 0;
|
||||||
|
if( b > 100 ) b = 100;
|
||||||
|
|
||||||
|
// Update HSB values
|
||||||
|
var hsb = input.data('hsb');
|
||||||
|
hsb.s = s;
|
||||||
|
hsb.b = b;
|
||||||
|
|
||||||
|
// Set color
|
||||||
|
setColor(input, hsb, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
var moveHue = function(input, event) {
|
||||||
|
|
||||||
|
var huePicker = input.data('huePicker');
|
||||||
|
|
||||||
|
huePicker.hide();
|
||||||
|
|
||||||
|
var position = {
|
||||||
|
y: event.pageY
|
||||||
|
};
|
||||||
|
|
||||||
|
// Touch support
|
||||||
|
if( event.originalEvent.changedTouches ) {
|
||||||
|
position.y = event.originalEvent.changedTouches[0].pageY;
|
||||||
|
}
|
||||||
|
|
||||||
|
position.y = position.y - input.data('selector').find('.miniColors-colors').offset().top - 1;
|
||||||
|
if( position.y <= -1 ) position.y = -1;
|
||||||
|
if( position.y >= 149 ) position.y = 149;
|
||||||
|
input.data('huePosition', position);
|
||||||
|
huePicker.css('top', position.y).show();
|
||||||
|
|
||||||
|
// Calculate hue
|
||||||
|
var h = Math.round((150 - position.y - 1) * 2.4);
|
||||||
|
if( h < 0 ) h = 0;
|
||||||
|
if( h > 360 ) h = 360;
|
||||||
|
|
||||||
|
// Update HSB values
|
||||||
|
var hsb = input.data('hsb');
|
||||||
|
hsb.h = h;
|
||||||
|
|
||||||
|
// Set color
|
||||||
|
setColor(input, hsb, true);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var setColor = function(input, hsb, updateInput) {
|
||||||
|
input.data('hsb', hsb);
|
||||||
|
var hex = hsb2hex(hsb);
|
||||||
|
if( updateInput ) input.val( '#' + convertCase(hex, input.data('letterCase')) );
|
||||||
|
input.data('trigger').css('backgroundColor', '#' + hex);
|
||||||
|
if( input.data('selector') ) input.data('selector').find('.miniColors-colors').css('backgroundColor', '#' + hsb2hex({ h: hsb.h, s: 100, b: 100 }));
|
||||||
|
|
||||||
|
// Fire change callback
|
||||||
|
if( input.data('change') ) {
|
||||||
|
if( hex === input.data('lastChange') ) return;
|
||||||
|
input.data('change').call(input.get(0), '#' + hex, hsb2rgb(hsb));
|
||||||
|
input.data('lastChange', hex);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var setColorFromInput = function(input) {
|
||||||
|
|
||||||
|
input.val('#' + cleanHex(input.val()));
|
||||||
|
var hex = expandHex(input.val());
|
||||||
|
if( !hex ) return false;
|
||||||
|
|
||||||
|
// Get HSB equivalent
|
||||||
|
var hsb = hex2hsb(hex);
|
||||||
|
|
||||||
|
// If color is the same, no change required
|
||||||
|
var currentHSB = input.data('hsb');
|
||||||
|
if( hsb.h === currentHSB.h && hsb.s === currentHSB.s && hsb.b === currentHSB.b ) return true;
|
||||||
|
|
||||||
|
// Set colorPicker position
|
||||||
|
var colorPosition = getColorPositionFromHSB(hsb);
|
||||||
|
var colorPicker = $(input.data('colorPicker'));
|
||||||
|
colorPicker.css('top', colorPosition.y + 'px').css('left', colorPosition.x + 'px');
|
||||||
|
input.data('colorPosition', colorPosition);
|
||||||
|
|
||||||
|
// Set huePosition position
|
||||||
|
var huePosition = getHuePositionFromHSB(hsb);
|
||||||
|
var huePicker = $(input.data('huePicker'));
|
||||||
|
huePicker.css('top', huePosition.y + 'px');
|
||||||
|
input.data('huePosition', huePosition);
|
||||||
|
|
||||||
|
setColor(input, hsb);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var convertCase = function(string, letterCase) {
|
||||||
|
if( letterCase === 'lowercase' ) return string.toLowerCase();
|
||||||
|
if( letterCase === 'uppercase' ) return string.toUpperCase();
|
||||||
|
return string;
|
||||||
|
};
|
||||||
|
|
||||||
|
var getColorPositionFromHSB = function(hsb) {
|
||||||
|
var x = Math.ceil(hsb.s / 0.67);
|
||||||
|
if( x < 0 ) x = 0;
|
||||||
|
if( x > 150 ) x = 150;
|
||||||
|
var y = 150 - Math.ceil(hsb.b / 0.67);
|
||||||
|
if( y < 0 ) y = 0;
|
||||||
|
if( y > 150 ) y = 150;
|
||||||
|
return { x: x - 5, y: y - 5 };
|
||||||
|
};
|
||||||
|
|
||||||
|
var getHuePositionFromHSB = function(hsb) {
|
||||||
|
var y = 150 - (hsb.h / 2.4);
|
||||||
|
if( y < 0 ) h = 0;
|
||||||
|
if( y > 150 ) h = 150;
|
||||||
|
return { y: y - 1 };
|
||||||
|
};
|
||||||
|
|
||||||
|
var cleanHex = function(hex) {
|
||||||
|
return hex.replace(/[^A-F0-9]/ig, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
var expandHex = function(hex) {
|
||||||
|
hex = cleanHex(hex);
|
||||||
|
if( !hex ) return null;
|
||||||
|
if( hex.length === 3 ) hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
||||||
|
return hex.length === 6 ? hex : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
var hsb2rgb = function(hsb) {
|
||||||
|
var rgb = {};
|
||||||
|
var h = Math.round(hsb.h);
|
||||||
|
var s = Math.round(hsb.s*255/100);
|
||||||
|
var v = Math.round(hsb.b*255/100);
|
||||||
|
if(s === 0) {
|
||||||
|
rgb.r = rgb.g = rgb.b = v;
|
||||||
|
} else {
|
||||||
|
var t1 = v;
|
||||||
|
var t2 = (255 - s) * v / 255;
|
||||||
|
var t3 = (t1 - t2) * (h % 60) / 60;
|
||||||
|
if( h === 360 ) h = 0;
|
||||||
|
if( h < 60 ) { rgb.r = t1; rgb.b = t2; rgb.g = t2 + t3; }
|
||||||
|
else if( h < 120 ) {rgb.g = t1; rgb.b = t2; rgb.r = t1 - t3; }
|
||||||
|
else if( h < 180 ) {rgb.g = t1; rgb.r = t2; rgb.b = t2 + t3; }
|
||||||
|
else if( h < 240 ) {rgb.b = t1; rgb.r = t2; rgb.g = t1 - t3; }
|
||||||
|
else if( h < 300 ) {rgb.b = t1; rgb.g = t2; rgb.r = t2 + t3; }
|
||||||
|
else if( h < 360 ) {rgb.r = t1; rgb.g = t2; rgb.b = t1 - t3; }
|
||||||
|
else { rgb.r = 0; rgb.g = 0; rgb.b = 0; }
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
r: Math.round(rgb.r),
|
||||||
|
g: Math.round(rgb.g),
|
||||||
|
b: Math.round(rgb.b)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var rgb2hex = function(rgb) {
|
||||||
|
var hex = [
|
||||||
|
rgb.r.toString(16),
|
||||||
|
rgb.g.toString(16),
|
||||||
|
rgb.b.toString(16)
|
||||||
|
];
|
||||||
|
$.each(hex, function(nr, val) {
|
||||||
|
if (val.length === 1) hex[nr] = '0' + val;
|
||||||
|
});
|
||||||
|
return hex.join('');
|
||||||
|
};
|
||||||
|
|
||||||
|
var hex2rgb = function(hex) {
|
||||||
|
hex = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
|
||||||
|
|
||||||
|
return {
|
||||||
|
r: hex >> 16,
|
||||||
|
g: (hex & 0x00FF00) >> 8,
|
||||||
|
b: (hex & 0x0000FF)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var rgb2hsb = function(rgb) {
|
||||||
|
var hsb = { h: 0, s: 0, b: 0 };
|
||||||
|
var min = Math.min(rgb.r, rgb.g, rgb.b);
|
||||||
|
var max = Math.max(rgb.r, rgb.g, rgb.b);
|
||||||
|
var delta = max - min;
|
||||||
|
hsb.b = max;
|
||||||
|
hsb.s = max !== 0 ? 255 * delta / max : 0;
|
||||||
|
if( hsb.s !== 0 ) {
|
||||||
|
if( rgb.r === max ) {
|
||||||
|
hsb.h = (rgb.g - rgb.b) / delta;
|
||||||
|
} else if( rgb.g === max ) {
|
||||||
|
hsb.h = 2 + (rgb.b - rgb.r) / delta;
|
||||||
|
} else {
|
||||||
|
hsb.h = 4 + (rgb.r - rgb.g) / delta;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hsb.h = -1;
|
||||||
|
}
|
||||||
|
hsb.h *= 60;
|
||||||
|
if( hsb.h < 0 ) {
|
||||||
|
hsb.h += 360;
|
||||||
|
}
|
||||||
|
hsb.s *= 100/255;
|
||||||
|
hsb.b *= 100/255;
|
||||||
|
return hsb;
|
||||||
|
};
|
||||||
|
|
||||||
|
var hex2hsb = function(hex) {
|
||||||
|
var hsb = rgb2hsb(hex2rgb(hex));
|
||||||
|
// Zero out hue marker for black, white, and grays (saturation === 0)
|
||||||
|
if( hsb.s === 0 ) hsb.h = 360;
|
||||||
|
return hsb;
|
||||||
|
};
|
||||||
|
|
||||||
|
var hsb2hex = function(hsb) {
|
||||||
|
return rgb2hex(hsb2rgb(hsb));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Handle calls to $([selector]).miniColors()
|
||||||
|
switch(o) {
|
||||||
|
|
||||||
|
//Added by dwat (this case: hide...):
|
||||||
|
case 'hide':
|
||||||
|
$(this).each(function() {
|
||||||
|
if( !$(this).hasClass('miniColors') ) return;
|
||||||
|
hide($(this));
|
||||||
|
});
|
||||||
|
return $(this);
|
||||||
|
|
||||||
|
case 'readonly':
|
||||||
|
|
||||||
|
$(this).each( function() {
|
||||||
|
if( !$(this).hasClass('miniColors') ) return;
|
||||||
|
$(this).prop('readonly', data);
|
||||||
|
});
|
||||||
|
|
||||||
|
return $(this);
|
||||||
|
|
||||||
|
case 'disabled':
|
||||||
|
|
||||||
|
$(this).each( function() {
|
||||||
|
if( !$(this).hasClass('miniColors') ) return;
|
||||||
|
if( data ) {
|
||||||
|
disable($(this));
|
||||||
|
} else {
|
||||||
|
enable($(this));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return $(this);
|
||||||
|
|
||||||
|
case 'value':
|
||||||
|
|
||||||
|
// Getter
|
||||||
|
if( data === undefined ) {
|
||||||
|
if( !$(this).hasClass('miniColors') ) return;
|
||||||
|
var input = $(this),
|
||||||
|
hex = expandHex(input.val());
|
||||||
|
return hex ? '#' + convertCase(hex, input.data('letterCase')) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setter
|
||||||
|
$(this).each( function() {
|
||||||
|
if( !$(this).hasClass('miniColors') ) return;
|
||||||
|
$(this).val(data);
|
||||||
|
setColorFromInput($(this));
|
||||||
|
});
|
||||||
|
|
||||||
|
return $(this);
|
||||||
|
|
||||||
|
case 'destroy':
|
||||||
|
|
||||||
|
$(this).each( function() {
|
||||||
|
if( !$(this).hasClass('miniColors') ) return;
|
||||||
|
destroy($(this));
|
||||||
|
});
|
||||||
|
|
||||||
|
return $(this);
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
if( !o ) o = {};
|
||||||
|
|
||||||
|
$(this).each( function() {
|
||||||
|
|
||||||
|
// Must be called on an input element
|
||||||
|
if( $(this)[0].tagName.toLowerCase() !== 'input' ) return;
|
||||||
|
|
||||||
|
// If a trigger is present, the control was already created
|
||||||
|
if( $(this).data('trigger') ) return;
|
||||||
|
|
||||||
|
// Create the control
|
||||||
|
create($(this), o, data);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
return $(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
})(jQuery);
|
@ -0,0 +1,565 @@
|
|||||||
|
/**
|
||||||
|
* Javascript used to control the settings page, options.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
var LOAD_START = new Date().getTime(); // keep track of when the page loads so we know to show the save settings dialog
|
||||||
|
var showSaveConfirmation;
|
||||||
|
var showSaveConfirmTime = 4000;
|
||||||
|
var saveconfirmationTimeout;
|
||||||
|
var lastClickedColorPickerPropertyID;
|
||||||
|
|
||||||
|
Rescroller.onSettingsUpdated = function() {
|
||||||
|
if (!Rescroller.settings.get('showSaveConfirmation') || (new Date().getTime() - 500) <= LOAD_START) { return; }
|
||||||
|
|
||||||
|
// Show "saved" confirmation box
|
||||||
|
clearTimeout(saveconfirmationTimeout);
|
||||||
|
$("#save-confirm").fadeIn("slow");
|
||||||
|
saveconfirmationTimeout = setTimeout(function() {
|
||||||
|
$("#save-confirm").fadeOut("slow");
|
||||||
|
}, showSaveConfirmTime)
|
||||||
|
};
|
||||||
|
|
||||||
|
//Enable functionality of Confirm Box "Never Show Again" button
|
||||||
|
$(document).ready(function() {
|
||||||
|
$("#save-confirm #hide-saved-confirm").click(function() {
|
||||||
|
Rescroller.settings.set('showSaveConfirmation', false);
|
||||||
|
$("#save-confirm").fadeOut("slow");
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function refreshScrollbars() {
|
||||||
|
$("#rescroller").html(Rescroller.getCSSString());
|
||||||
|
var originalOverflow = $("body").css("overflow");
|
||||||
|
$("body").css("overflow", "hidden");
|
||||||
|
setTimeout(function() { $("body").css("overflow", originalOverflow) }, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Following "plugin" function found here: http://stackoverflow.com/a/10310815/477632
|
||||||
|
$.fn.draghover = function(options) {
|
||||||
|
return this.each(function() {
|
||||||
|
|
||||||
|
var collection = $(),
|
||||||
|
self = $(this);
|
||||||
|
|
||||||
|
//Note: "dragenter", "dragleave", and "dragover" need to be e.preventDefault()-ed
|
||||||
|
//in order for the webpage not to redirect to the dragged-in image:
|
||||||
|
//See explanation here: http://stackoverflow.com/a/8938581/477632
|
||||||
|
|
||||||
|
self.on('dragenter', function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (collection.size() === 0) {
|
||||||
|
self.trigger('draghoverstart');
|
||||||
|
}
|
||||||
|
collection = collection.add(e.target);
|
||||||
|
});
|
||||||
|
|
||||||
|
self.on('dragleave', function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
// timeout is needed because Firefox 3.6 fires the dragleave event on
|
||||||
|
// the previous element before firing dragenter on the next one
|
||||||
|
setTimeout( function() {
|
||||||
|
collection = collection.not(e.target);
|
||||||
|
if (collection.size() === 0) {
|
||||||
|
self.trigger('draghoverend');
|
||||||
|
}
|
||||||
|
}, 1);
|
||||||
|
|
||||||
|
self.on('dragover', function(e) {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function showErrorMessage(msg) {
|
||||||
|
|
||||||
|
var errorBox = $("#errorbox");
|
||||||
|
errorBox.html(msg);
|
||||||
|
errorBox.slideDown("fast", function() {
|
||||||
|
setTimeout(function() {
|
||||||
|
//Hide the error message in 5 seconds
|
||||||
|
hideErrorMessage();
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideErrorMessage() {
|
||||||
|
$("#errorbox").slideUp("fast");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Convert the styling stored in local storage into CSS:
|
||||||
|
var newCSS = Rescroller.getCSSString();
|
||||||
|
|
||||||
|
//Write the newly formatted CSS (from local storage) to the (beginning of the) page:
|
||||||
|
document.write('<style id="rescroller">' + newCSS + "</style>");
|
||||||
|
|
||||||
|
//When the page has loaded:
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
refreshScrollbars();
|
||||||
|
|
||||||
|
//show generated css in css div:
|
||||||
|
$("#generatedcss").html(newCSS);
|
||||||
|
|
||||||
|
//Fill the excludedsites textarea with the list of excluded sites:
|
||||||
|
$("#excludedsites").val(Rescroller.settings.get('excludedsites'));
|
||||||
|
$("#excludedsites").change(function() {
|
||||||
|
Rescroller.settings.set('excludedsites', $(this).val());
|
||||||
|
});
|
||||||
|
|
||||||
|
//Fill the custom CSS form with the custom CSS
|
||||||
|
$("#customcss").val(Rescroller.properties.get("customcss"));
|
||||||
|
$("#customcss").change(function() {
|
||||||
|
Rescroller.properties.set("customcss", $(this).val());
|
||||||
|
refreshScrollbars();
|
||||||
|
});
|
||||||
|
|
||||||
|
//Fill the form elements with data from local storage:
|
||||||
|
$("input").each(function(index, element) {
|
||||||
|
|
||||||
|
if ($(this).attr("type") != "submit") { //Make sure we're not talking about the submit button here
|
||||||
|
|
||||||
|
if ($(this).attr("type") == "checkbox") { //If it's a check box...
|
||||||
|
|
||||||
|
//If local storage says this option should be checked, check it
|
||||||
|
if (Rescroller.properties.get($(this).attr("id")) == "checked") {
|
||||||
|
$(this).attr("checked", Rescroller.properties.get($(this).attr("id")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//If it's an ordinary input, just fill the input with the corresponding value from local storage
|
||||||
|
else {
|
||||||
|
$(this).val(Rescroller.properties.get($(this).attr("id")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function resetDragHoveringEventTriggering() {
|
||||||
|
|
||||||
|
var originalBackground;
|
||||||
|
var originalText;
|
||||||
|
|
||||||
|
//Following is a pain using "dragenter" and "dragleave" events. draghover() plugin (above) makes it easy!
|
||||||
|
$(window).draghover().on({
|
||||||
|
"draghoverstart" : function() {
|
||||||
|
originalBackground = $(".selector-button").css("background");
|
||||||
|
originalText = $(".selector-button").html();
|
||||||
|
$(".selector-button").animate({ "background-color" : "#C91313" }, "slow");
|
||||||
|
$(".selector-button").html("Drop Here");
|
||||||
|
},
|
||||||
|
"draghoverend" : function() {
|
||||||
|
$(".selector-button").html(originalText);
|
||||||
|
$(".selector-button").animate({ "background-color" : originalBackground }, "slow");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
$("#expandcss").click(function() {
|
||||||
|
$("#generatedcss").slideToggle("fast");
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
//Reset formatting button
|
||||||
|
$("#resetformatting").click(function() {
|
||||||
|
if (!confirm("Are you sure you would like to reset your scrollbars to default? This cannot be undone.")) { return false; }
|
||||||
|
Rescroller.restoreDefaults();
|
||||||
|
|
||||||
|
// full refresh instead of refreshScrollbars() so all our settings bars are reset as well.
|
||||||
|
// An actual JS view framework will fix this later on.
|
||||||
|
location.reload(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
//Expand/collapse all non-custom css areas when that checkbox is checked
|
||||||
|
if (Rescroller.properties.get("usecustomcss") == "checked") {
|
||||||
|
$(".section").not("#misc").not($("#general")).hide();
|
||||||
|
$(".customcss-collapsible").hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#usecustomcss").change(function() {
|
||||||
|
if ($(this).is(":checked")) {
|
||||||
|
$(".section").not("#misc").not($("#general")).slideUp("slow");
|
||||||
|
$(".customcss-collapsible").slideUp("slow");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$(".section").slideDown("slow");
|
||||||
|
$(".customcss-collapsible").slideDown("slow");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//Clear picture buttons
|
||||||
|
$(".clearimage").click(function() {
|
||||||
|
var key = $(this).parent().parent().attr("id");
|
||||||
|
Rescroller.properties.remove(key);
|
||||||
|
$(this).siblings(".thumbframe .thumbcontainer").html("No Image Loaded");
|
||||||
|
$(this).parents(".imagepicker-container").children("input[type=file].selector").val("");
|
||||||
|
|
||||||
|
//Hide the thumbframe and restore it with the "Select Image" button
|
||||||
|
$("#" + key).children(".thumbframe").hide();
|
||||||
|
$("#" + key).children(".selector-button").css("display", "block");
|
||||||
|
|
||||||
|
refreshScrollbars();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
//Set correct value for <select>s
|
||||||
|
$("select").each(function() {
|
||||||
|
var thisProperty = $(this).attr('id');
|
||||||
|
var thisPropertyValue = Rescroller.properties.get(thisProperty);
|
||||||
|
$(this).children().each(function() {
|
||||||
|
if($(this).val() == thisPropertyValue) {
|
||||||
|
$(this).attr("selected", "selected");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
//When <select> is changed, save it to local storage
|
||||||
|
$("select").change(function() {
|
||||||
|
var thisProperty = $(this).attr('id');
|
||||||
|
var currentValue = $(this).val();
|
||||||
|
Rescroller.properties.set(thisProperty, currentValue);
|
||||||
|
refreshScrollbars();
|
||||||
|
});
|
||||||
|
|
||||||
|
/***********Set up Sliders************/
|
||||||
|
|
||||||
|
//Main slider (scrollbar size)
|
||||||
|
$("#size .slider").slider({
|
||||||
|
animate: true,
|
||||||
|
min: 0,
|
||||||
|
max: 30
|
||||||
|
});
|
||||||
|
|
||||||
|
//All sliders
|
||||||
|
$(".slider").not("#size .slider").slider({
|
||||||
|
animate: true,
|
||||||
|
min: 0,
|
||||||
|
max: 100
|
||||||
|
});
|
||||||
|
|
||||||
|
//Loop through all "property" classes and set up their inner sliders, etc.
|
||||||
|
$(".slider-property").each(function() {
|
||||||
|
|
||||||
|
var propertyName = $(this).attr('id');
|
||||||
|
var theOrientation;
|
||||||
|
if ($(this).children(".slider").hasClass("slider-v")) { theOrientation = "vertical"; }
|
||||||
|
else { theOrientation = "horizontal"; }
|
||||||
|
|
||||||
|
//If this is one of the few scrollbars that uses px instead of %, set the "units" to px
|
||||||
|
var units;
|
||||||
|
if (propertyName == "size" || propertyName == "buttons-size") { units = "px"; }
|
||||||
|
else { units = "%"; }
|
||||||
|
|
||||||
|
//Fill slider value with value from local storage
|
||||||
|
$("#" + propertyName + " .slider-value").html(Rescroller.properties.get(propertyName) + units);
|
||||||
|
|
||||||
|
//Set up slider for this property
|
||||||
|
$("#" + propertyName + " .slider").slider({
|
||||||
|
value: Rescroller.properties.get(propertyName),
|
||||||
|
orientation: theOrientation,
|
||||||
|
slide: function(event, ui) {
|
||||||
|
$(this).siblings(".slider-value").html(ui.value + units);
|
||||||
|
},
|
||||||
|
change: function(event, ui) {
|
||||||
|
//Update value in local storage
|
||||||
|
Rescroller.properties.set(propertyName, ui.value);
|
||||||
|
refreshScrollbars();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
/***********Set up Color Pickers************/
|
||||||
|
|
||||||
|
$(".colorselection").each(function() {
|
||||||
|
|
||||||
|
var localStorageKey = $(this).parent().attr("id");
|
||||||
|
var self = $(this);
|
||||||
|
|
||||||
|
$(this).miniColors({
|
||||||
|
change: function(hex, rgb) {
|
||||||
|
self.siblings(".colorvalue").val(hex);
|
||||||
|
},
|
||||||
|
close: function(hex, rgb) {
|
||||||
|
Rescroller.properties.set(localStorageKey, hex);
|
||||||
|
refreshScrollbars();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set default color to whatever it's been saved to
|
||||||
|
$(this).miniColors("value", Rescroller.properties.get($(this).parent().attr("id")));
|
||||||
|
|
||||||
|
// Add "apply" button
|
||||||
|
$(".miniColors-selector").append('<p><a href="#">Apply</a></p>');
|
||||||
|
});
|
||||||
|
|
||||||
|
// save the last-clicked color picker
|
||||||
|
$("a.miniColors-trigger").click(function() {
|
||||||
|
lastClickedColorPickerPropertyID = $(this).parent().attr("id");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set functionality of "apply" button
|
||||||
|
$("body").on("click", ".miniColors-apply a", function() { //applies listener to the <a> that hasn't been created yet
|
||||||
|
var colorSelectorInput = $("#" + lastClickedColorPickerPropertyID).children("input.colorselection");
|
||||||
|
colorSelectorInput.miniColors("hide");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Loop through all image frames and fill them:
|
||||||
|
var keys = [
|
||||||
|
"slider-background-image-vertical",
|
||||||
|
"slider-background-image-horizontal",
|
||||||
|
"slider-background-image-vertical-hover",
|
||||||
|
"slider-background-image-horizontal-hover",
|
||||||
|
"slider-background-image-vertical-active",
|
||||||
|
"slider-background-image-horizontal-active",
|
||||||
|
|
||||||
|
"background-background-image-vertical",
|
||||||
|
"background-background-image-horizontal",
|
||||||
|
"background-background-image-vertical-hover",
|
||||||
|
"background-background-image-horizontal-hover",
|
||||||
|
"background-background-image-vertical-active",
|
||||||
|
"background-background-image-horizontal-active",
|
||||||
|
|
||||||
|
"buttons-background-image-up",
|
||||||
|
"buttons-background-image-down",
|
||||||
|
"buttons-background-image-left",
|
||||||
|
"buttons-background-image-right",
|
||||||
|
"buttons-background-image-up-hover",
|
||||||
|
"buttons-background-image-down-hover",
|
||||||
|
"buttons-background-image-left-hover",
|
||||||
|
"buttons-background-image-right-hover",
|
||||||
|
"buttons-background-image-up-active",
|
||||||
|
"buttons-background-image-down-active",
|
||||||
|
"buttons-background-image-left-active",
|
||||||
|
"buttons-background-image-right-active"
|
||||||
|
]
|
||||||
|
|
||||||
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
|
||||||
|
if (Rescroller.properties.get(keys[i]) && Rescroller.properties.get(keys[i]) != 0) {
|
||||||
|
$("#" + keys[i] + " .thumbframe div.thumbcontainer").html('<img src="' + Rescroller.properties.get(keys[i]) + '" />');
|
||||||
|
$("#" + keys[i] + " .thumbframe").css("display", "inline-block"); //show the image frame for this image
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//otherwise, show the "upload image" button (instead of the thumbframe)
|
||||||
|
$("#" + keys[i] + " .selector-button").css("display", "inline-block");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//draghover() "plugin" stops working after being utilized once, so needed to be in function that can be recalled
|
||||||
|
resetDragHoveringEventTriggering();
|
||||||
|
|
||||||
|
//Fill "colorvalue" inputs with color values
|
||||||
|
$(".colorvalue").each(function() {
|
||||||
|
$(this).val(Rescroller.properties.get($(this).parent().attr("id")));
|
||||||
|
});
|
||||||
|
|
||||||
|
//Automatically select text when clicking a color value
|
||||||
|
$(".colorvalue").focus(function() {
|
||||||
|
var self = $(this);
|
||||||
|
$(this).select(); //Select the value of the input form
|
||||||
|
$(this).mouseup(function(e) { //Prevent the text from being unselected when you stop the click
|
||||||
|
e.preventDefault();
|
||||||
|
self.off("mouseup"); //Remove the mouseup function to restore normal functionality
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(".colorvalue").change(function() {
|
||||||
|
var val = $(this).val();
|
||||||
|
//If the value is a hex value, save it
|
||||||
|
if (val.indexOf("#") == 0 && (val.length == 4 || val.length == 7)) {
|
||||||
|
$(this).siblings(".colorselection").miniColors("value", val);
|
||||||
|
Rescroller.properties.set($(this).parent().attr("id"), val);
|
||||||
|
refreshScrollbars();
|
||||||
|
}
|
||||||
|
//If the user just forgot the #, add it automatically and save
|
||||||
|
else if (val.indexOf("#") != 0 && (val.length == 3 || val.length == 6)) {
|
||||||
|
$(this).siblings(".colorselection").miniColors("value", "#" + val);
|
||||||
|
$(this).val("#" + val);
|
||||||
|
Rescroller.properties.set($(this).parent().attr("id"), val);
|
||||||
|
refreshScrollbars();
|
||||||
|
}
|
||||||
|
//If it's just a bad value, restore original
|
||||||
|
else {
|
||||||
|
$(this).val(Rescroller.properties.get($(this).parent().attr("id")));
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
/********** Collapsable Checkboxes *********************/
|
||||||
|
|
||||||
|
//Scroll buttons
|
||||||
|
var showButtons = $("#showbuttons");
|
||||||
|
|
||||||
|
//Make sure wrapper is correctly expanded on load
|
||||||
|
if (showButtons.is(":checked")) { $("#buttons-toggleable").show(); }
|
||||||
|
else { $("#buttons-toggleable").hide(); }
|
||||||
|
|
||||||
|
//When checkbox is changed:
|
||||||
|
showButtons.change(function() {
|
||||||
|
|
||||||
|
// Expand/collapse wrapper & save value to local storage
|
||||||
|
if ($(this).is(":checked")) {
|
||||||
|
Rescroller.properties.set($(this).attr("id"), "checked");
|
||||||
|
$("#buttons-toggleable").slideDown("fast", function() { refreshScrollbars(); });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Rescroller.properties.set($(this).attr("id"), "unchecked");
|
||||||
|
$("#buttons-toggleable").slideUp("fast", function() { refreshScrollbars(); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/************* Slider Hover/Active Checkboxes **************/
|
||||||
|
|
||||||
|
//Make sure wrappers are correctly expanded/collapsed on load
|
||||||
|
$(".toggle-hover-active").each(function() {
|
||||||
|
|
||||||
|
var targetWrapper = $("#" + $(this).attr("data-wrapperid"));
|
||||||
|
|
||||||
|
if ($(this).is(":checked")) { targetWrapper.show(); }
|
||||||
|
else { targetWrapper.hide(); }
|
||||||
|
});
|
||||||
|
|
||||||
|
//Expand/collapse and write to local Storage
|
||||||
|
$(".toggle-hover-active").change(function() {
|
||||||
|
|
||||||
|
if ($(this).is(":checked")) {
|
||||||
|
//alert("Checked!");
|
||||||
|
Rescroller.properties.set($(this).attr("id"), "checked");
|
||||||
|
$("#" + $(this).attr("data-wrapperid")).slideDown("slow", function() { refreshScrollbars(); });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//alert("Unchecked!");
|
||||||
|
Rescroller.properties.set($(this).attr("id"), "unchecked");
|
||||||
|
$("#" + $(this).attr("data-wrapperid")).slideUp("slow", function() { refreshScrollbars(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshScrollbars();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
/** Set functionality of "restore default buttons" link (for scrollbar buttons) **/
|
||||||
|
setRestoreArrowsDefaultImages("restore-arrow-defaults", "buttons-background-image-", "");
|
||||||
|
setRestoreArrowsDefaultImages("restore-arrow-defaults-hover", "buttons-background-image-", "-hover");
|
||||||
|
setRestoreArrowsDefaultImages("restore-arrow-defaults-active", "buttons-background-image-", "-active");
|
||||||
|
|
||||||
|
function setRestoreArrowsDefaultImages(triggerID, propertyPrefix, propertySuffix) {
|
||||||
|
$("#" + triggerID).click(function() {
|
||||||
|
|
||||||
|
var up = propertyPrefix + "up" + propertySuffix;
|
||||||
|
var down = propertyPrefix + "down" + propertySuffix;
|
||||||
|
var left = propertyPrefix + "left" + propertySuffix;
|
||||||
|
var right = propertyPrefix + "right" + propertySuffix;
|
||||||
|
|
||||||
|
Rescroller.properties.set(down, chrome.extension.getURL("images/defaults/down.png"));
|
||||||
|
Rescroller.properties.set(up, chrome.extension.getURL("images/defaults/up.png"));
|
||||||
|
Rescroller.properties.set(left, chrome.extension.getURL("images/defaults/left.png"));
|
||||||
|
Rescroller.properties.set(right, chrome.extension.getURL("images/defaults/right.png"));
|
||||||
|
|
||||||
|
$("#" + down + ", #" + up + ", #" + left + ", #" + right).each(function() {
|
||||||
|
|
||||||
|
$(this).children(".thumbframe").children(".thumbcontainer").html('<img src="' + Rescroller.properties.get($(this).attr("id")) + '" />');
|
||||||
|
$(this).children(".selector-button").hide();
|
||||||
|
$(this).children(".thumbframe").show();
|
||||||
|
});
|
||||||
|
|
||||||
|
refreshScrollbars();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
/***********Image selector functionality*****************/
|
||||||
|
|
||||||
|
function handleFiles(files, frame, key) {
|
||||||
|
|
||||||
|
var file = files[0];
|
||||||
|
var imageType = /image.*/;
|
||||||
|
|
||||||
|
if (!file.type.match(imageType)) {
|
||||||
|
showErrorMessage("Sorry, you must select an image file. Please try again.")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For now, restrict the user from using large images that won't sync. In the future, we could allow it,
|
||||||
|
// but we'll have to warn the user that it will not be synced and make sure our raw value (the reference to
|
||||||
|
// the actual data image localStorage item) doesn't overwrite any remote ones.
|
||||||
|
if (file.size >= chrome.storage.sync.QUOTA_BYTES_PER_ITEM) {
|
||||||
|
showErrorMessage('Sorry, only very small images are allowed. Please choose one under 8 KB.')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//hide any error messages
|
||||||
|
hideErrorMessage();
|
||||||
|
|
||||||
|
var img = document.createElement("img");
|
||||||
|
img.classList.add("obj");
|
||||||
|
img.file = file;
|
||||||
|
|
||||||
|
frame.innerHTML = ""; //clear frame before putting new image in
|
||||||
|
frame.appendChild(img);
|
||||||
|
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = (function(aImg) {
|
||||||
|
return function(e) {
|
||||||
|
aImg.src = e.target.result;
|
||||||
|
|
||||||
|
//Save to local storage
|
||||||
|
Rescroller.properties.set(key, aImg.src);
|
||||||
|
|
||||||
|
//Change the "Select Image" button to an image frame
|
||||||
|
var container = $(frame).parents(".imagepicker-container");
|
||||||
|
container.children(".selector-button").hide();
|
||||||
|
container.children(".thumbframe").show();
|
||||||
|
|
||||||
|
//Redraw scrollbars
|
||||||
|
refreshScrollbars();
|
||||||
|
};
|
||||||
|
})(img);
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
//Whenever selectors (hidden <input type="file">s) are changed, save their valuese to local storage
|
||||||
|
$(".selector").change(function() {
|
||||||
|
handleFiles(this.files, $(this).siblings(".thumbframe").children("div.thumbcontainer").get()[0], $(this).parent().attr("id"))
|
||||||
|
});
|
||||||
|
|
||||||
|
//Whenever selector buttons are clicked, invoke their related selector's click function (i.e., save their contents to local storage)
|
||||||
|
$(".selector-button").click(function() {
|
||||||
|
$(this).siblings(".selector").get()[0].click();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
//Whenever a file is dropped on a dropbox, save the file to local storage with the associated value
|
||||||
|
$(".selector-button").bind("drop", function(eventObj) {
|
||||||
|
e = eventObj.originalEvent;
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
var dt = e.dataTransfer;
|
||||||
|
var files = dt.files;
|
||||||
|
|
||||||
|
handleFiles(files, $(this).siblings(".thumbframe").children("div.thumbcontainer").get()[0], $(this).parent().attr("id"));
|
||||||
|
|
||||||
|
//Hide the dropbox
|
||||||
|
$(".selector-button").html("Select Image");
|
||||||
|
$(".selector-button").animate({ "background-color" : "#333" }, "slow");
|
||||||
|
resetDragHoveringEventTriggering();
|
||||||
|
return false;
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,850 @@
|
|||||||
|
/**
|
||||||
|
* The Rescroller API and other utility methods.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!String.prototype.fmt) {
|
||||||
|
String.prototype.fmt = function() {
|
||||||
|
var args = arguments;
|
||||||
|
var i = 0;
|
||||||
|
return this.replace(/%((%)|s)/g, function(match) {
|
||||||
|
return_val = typeof args[i] != 'undefined' ? args[i] : match;
|
||||||
|
i++;
|
||||||
|
return return_val;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Superficial class creator. It may be better to use something like Backbone in the future.
|
||||||
|
*/
|
||||||
|
var createClass = function(proto) {
|
||||||
|
proto || (proto = {});
|
||||||
|
proto.constructor || (proto.constructor = function() {});
|
||||||
|
var obj = function() {
|
||||||
|
proto.constructor.apply(this, arguments)
|
||||||
|
};
|
||||||
|
obj.prototype = proto;
|
||||||
|
return obj;
|
||||||
|
};
|
||||||
|
|
||||||
|
window.Rescroller = {
|
||||||
|
version: chrome.app.getDetails().version,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object that understands our image {} format and can handle image data values to and from localStorage
|
||||||
|
*/
|
||||||
|
Image: createClass({
|
||||||
|
data: {
|
||||||
|
localStorageKey: null
|
||||||
|
},
|
||||||
|
|
||||||
|
constructor: function(data) {
|
||||||
|
if (!data) { return; }
|
||||||
|
|
||||||
|
this.data = data;
|
||||||
|
},
|
||||||
|
|
||||||
|
getDataValue: function() {
|
||||||
|
var dataValue = localStorage[this.data.localStorageKey];
|
||||||
|
if (!dataValue) { return ''; }
|
||||||
|
return dataValue;
|
||||||
|
},
|
||||||
|
|
||||||
|
setImageData: function(imageData) {
|
||||||
|
var imageKey = 'image-' + new Date().getTime() + Math.random().toString().split('.')[1];
|
||||||
|
|
||||||
|
this.data.localStorageKey = imageKey;
|
||||||
|
localStorage[imageKey] = imageData;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
removeImage: function() {
|
||||||
|
localStorage.removeItem(this.data.localStorageKey);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When we are converted to string, let's show our value string instead of [object Object]. This way,
|
||||||
|
* we don't need to handle this class vs other string values in getCSSString()
|
||||||
|
*/
|
||||||
|
toString: function() {
|
||||||
|
return this.getDataValue();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is needed for JSON.stringify() and localStorage's stringify
|
||||||
|
*/
|
||||||
|
toJSON: function() {
|
||||||
|
return this.data;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
|
settings: {
|
||||||
|
_settings: null, // a cached JSON version of our settings from localStorage.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform setup of our settins struture for a new installation.
|
||||||
|
*/
|
||||||
|
_initializeFirstTimeSettings: function() {
|
||||||
|
localStorage['rescroller-settings'] = JSON.stringify({
|
||||||
|
showSaveConfirmation: true,
|
||||||
|
excludedsites: '',
|
||||||
|
scrollbarStyle: {
|
||||||
|
metadata: {}, // unused now, but will use it in the future if/when we allow saving/sharing/exporting of styles
|
||||||
|
data: {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Rescroller.restoreDefaults(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sometimes after localStorage has changed, we need to wipe our JS cache
|
||||||
|
* so the next time get()/getAll() is called, we return accurate results.
|
||||||
|
*/
|
||||||
|
resetJSCache: function() {
|
||||||
|
this._settings = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get our settings object.
|
||||||
|
* @param {boolean} force If true, will get the setting from localStorage instead of our in-memory object
|
||||||
|
*/
|
||||||
|
getAll: function(force) {
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
if (!localStorage['rescroller-settings']) { // no matter what, we need a default for this
|
||||||
|
this._initializeFirstTimeSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force === true || !this._settings) {
|
||||||
|
this._settings = JSON.parse(localStorage.getItem('rescroller-settings'));
|
||||||
|
|
||||||
|
// Convert all image {}'s into proper Image classes
|
||||||
|
Object.keys(this._settings.scrollbarStyle.data).forEach(function(key) {
|
||||||
|
var val = that._settings.scrollbarStyle.data[key];
|
||||||
|
if (!(val instanceof Object) && !val.localStorageKey) { return true; }
|
||||||
|
that._settings.scrollbarStyle.data[key] = new Rescroller.Image(val);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._settings;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a single setting value.
|
||||||
|
* @param {string} key The setting to get
|
||||||
|
* @param {boolean} force If true, will get the setting from localStorage instead of our in-memory object
|
||||||
|
*/
|
||||||
|
get: function(key, force) {
|
||||||
|
try { return this.getAll(force)[key]; }
|
||||||
|
catch(e) { return null; }
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function(key, value, noSync) {
|
||||||
|
var settings = this.getAll();
|
||||||
|
settings[key] = value;
|
||||||
|
localStorage['rescroller-settings'] = JSON.stringify(settings);
|
||||||
|
localStorage['date-settings-last-updated'] = new Date().getTime();
|
||||||
|
Rescroller.onSettingsUpdated();
|
||||||
|
|
||||||
|
if (noSync) { return; }
|
||||||
|
Rescroller.syncUp();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
|
||||||
|
getAll: function(force) {
|
||||||
|
var props = null;
|
||||||
|
try { props = Rescroller.settings.get('scrollbarStyle', force); }
|
||||||
|
catch(e) { }
|
||||||
|
|
||||||
|
if (!props || !props.data) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return props.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
get: function(key, force) {
|
||||||
|
try {
|
||||||
|
var val = this.getAll(force)[key];
|
||||||
|
return val ? val : ''; // return empty string so we don't have 'null's in our CSS
|
||||||
|
} catch(e) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
set: function(key, value, noSync) {
|
||||||
|
var props = this.getAll();
|
||||||
|
|
||||||
|
// if previous value was image, we need to remove the old image before overwriting it
|
||||||
|
if (this.get(key) instanceof Rescroller.Image) {
|
||||||
|
this.get(key).removeImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value == 'string' && value.indexOf('data') == 0) { // save images in separate localStorage key to avoid chrome.sync item size limits
|
||||||
|
props[key] = new Rescroller.Image().setImageData(value);
|
||||||
|
} else {
|
||||||
|
props[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setMultiple(props, noSync);
|
||||||
|
Rescroller.generateScrollbarCSS(); // update our generated CSS for browser tabs
|
||||||
|
},
|
||||||
|
|
||||||
|
setMultiple: function(newProps, noSync) {
|
||||||
|
var props = this.getAll();
|
||||||
|
|
||||||
|
for (key in newProps) {
|
||||||
|
var newVal = newProps[key];
|
||||||
|
|
||||||
|
if (typeof newVal == 'string' && newVal.indexOf('data') == 0) {
|
||||||
|
newVal = new Rescroller.Image().setImageData(newVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
props[key] = newVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rescroller.settings.set('scrollbarStyle', {
|
||||||
|
metadata: Rescroller.settings.get('scrollbarStyle').metadata,
|
||||||
|
data: props
|
||||||
|
}, noSync);
|
||||||
|
|
||||||
|
Rescroller.generateScrollbarCSS(); // update our generated CSS for browser tabs
|
||||||
|
},
|
||||||
|
|
||||||
|
remove: function(key) {
|
||||||
|
if (this.get(key) instanceof Rescroller.Image) {
|
||||||
|
this.get(key).removeImage();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.set(key, '');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
performMigrations: function() {
|
||||||
|
|
||||||
|
if (!this._migrateDataToSingleKey() && !this._migrateImageNullValues()) {
|
||||||
|
return; // none of the migrations needed to run; we're done!
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since localStorage has change, we need to invalide our JS cache so we get accurate results
|
||||||
|
this.settings.resetJSCache();
|
||||||
|
|
||||||
|
// we need to regenerate our CSS so it's in localStorage['generated-css'] for our background page to find it
|
||||||
|
this.generateScrollbarCSS();
|
||||||
|
|
||||||
|
// After switching to the new version, the new settings should be synced up.
|
||||||
|
localStorage['date-settings-last-updated'] = new Date().getTime(); // copied from set()
|
||||||
|
this.syncUp(); // sync migrated structures up
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migration from 1.2 --> 1.3. Migrate all our "sb-*" keys in localStorage to a single key.
|
||||||
|
*
|
||||||
|
* @returns {boolean} true if migration ran, false if it didn't (need to)
|
||||||
|
*/
|
||||||
|
_migrateDataToSingleKey: function() {
|
||||||
|
if (!localStorage['sb-size']) { return false; } // already migrated
|
||||||
|
|
||||||
|
var json = {
|
||||||
|
scrollbarStyle: {
|
||||||
|
metadata: {},
|
||||||
|
data: {}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.keys(localStorage).forEach(function(key) {
|
||||||
|
if (key == 'install_time') { return true; } // continue
|
||||||
|
|
||||||
|
if (key == 'sb-excludedsites') {
|
||||||
|
json['excludedsites'] = localStorage['sb-excludedsites']
|
||||||
|
} else if (key == 'showSaveConfirmation') { // change showSaveConfirmation form a '1'/'0' to true/false
|
||||||
|
json[key] = localStorage[key] !== '0';
|
||||||
|
} else if (key.indexOf('sb-') == 0) { // put scrollbar CSS settings in our scrollbar settings, without the 'sb-' prefix
|
||||||
|
json.scrollbarStyle.data[key.substr(3, key.length -1)] = (isNaN(parseInt(localStorage[key]))) ? localStorage[key] : parseInt(localStorage[key]) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the old key/val
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
});
|
||||||
|
|
||||||
|
this._settings = json;
|
||||||
|
localStorage['rescroller-settings'] = JSON.stringify(json)
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For whatever reason, we were setting default values for images as 0. They should be empty strings.
|
||||||
|
* Also, this migrates datea values (data-url strings) to their own key in local storage so that
|
||||||
|
* chrome.sync will handle them separately.
|
||||||
|
*
|
||||||
|
* @return {boolean} true if migration ran, false if it didn't (need to)
|
||||||
|
*/
|
||||||
|
_migrateImageNullValues: function() {
|
||||||
|
|
||||||
|
var i = 0;
|
||||||
|
var props = this.properties.getAll();
|
||||||
|
for (key in props) {
|
||||||
|
if (key.indexOf('background-image') <= -1) { continue; }
|
||||||
|
|
||||||
|
// Convert any data strings to Image classes
|
||||||
|
if (typeof key == 'string' && key.indexOf('data') === 0) {
|
||||||
|
props[key] = new Rescroller.Image().setImageData(props[key]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parseInt(props[key]) !== 0) { continue; }
|
||||||
|
props[key] = '';
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't set anything if no changes were made; this prevents a recursive loop with
|
||||||
|
// chrome.sync since this is run every every sync down
|
||||||
|
if (i == 0) { return false; }
|
||||||
|
|
||||||
|
this.properties.setMultiple(props, true)
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple callback method that callers can set to act when the settings have been updated.
|
||||||
|
*/
|
||||||
|
onSettingsUpdated: function() {},
|
||||||
|
|
||||||
|
getListOfDisabledSites: function() {
|
||||||
|
var rawString = this.settings.get('excludedsites');
|
||||||
|
if (!rawString) { return []; }
|
||||||
|
|
||||||
|
//Remove all spaces from the string, etc.
|
||||||
|
rawString = this._replaceAll(rawString, " ", "");
|
||||||
|
rawString = this._replaceAll(rawString, "https://", "");
|
||||||
|
rawString = this._replaceAll(rawString, "http://", "");
|
||||||
|
rawString = this._replaceAll(rawString, "www.", "");
|
||||||
|
rawString = this._replaceAll(rawString, "*/", "");
|
||||||
|
rawString = this._replaceAll(rawString, "*.", "");
|
||||||
|
rawString = this._replaceAll(rawString, "*", "");
|
||||||
|
|
||||||
|
if (!rawString) { return []; }
|
||||||
|
return rawString.split(",");
|
||||||
|
},
|
||||||
|
|
||||||
|
_replaceAll: function(theString, toReplace, replaceWith) {
|
||||||
|
|
||||||
|
while (theString.indexOf(toReplace) >= 0) {
|
||||||
|
theString = theString.replace(toReplace, replaceWith);
|
||||||
|
}
|
||||||
|
return theString;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get number of pixels from percentage
|
||||||
|
*/
|
||||||
|
_precentageToPixels: function(percentage, doNotReduceByHalf) {
|
||||||
|
if (!doNotReduceByHalf) {
|
||||||
|
return ((percentage / 100) * this.properties.get("size")) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (percentage / 100) * this.properties.get("size");
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for first-time install refresh from Chrome Storage -> Local Storage (or old localStorage -> Chrome Storage)
|
||||||
|
*/
|
||||||
|
syncDown: function(callback, force) {
|
||||||
|
callback || (callback = function() {});
|
||||||
|
var that = this;
|
||||||
|
|
||||||
|
chrome.storage.sync.get(function(items) {
|
||||||
|
that.mergeSyncWithLocalStorage(items, force);
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge items from Chrome Sync into LocalStorage.
|
||||||
|
* Note: if a 'date-settings-last-updated' item exists in the synced items and localStorage,
|
||||||
|
* the update will only occur if a remote timestamp is newer than local.
|
||||||
|
*
|
||||||
|
* @param {object} items An object of key-value items to set in local storage.
|
||||||
|
* @param {boolean} force If true, we will force the merge - otherwise we will only sync if 'date-settings-last-updated' comparisons match
|
||||||
|
* @return {[type]} [description]
|
||||||
|
*/
|
||||||
|
mergeSyncWithLocalStorage: function(items, force) {
|
||||||
|
var lastUpdatedRemote = items['date-settings-last-updated'];
|
||||||
|
var lastUpdatedLocal = localStorage['date-settings-last-updated'];
|
||||||
|
|
||||||
|
// Do not proceed if remote data is older than local data
|
||||||
|
if (!force && lastUpdatedRemote && lastUpdatedLocal && parseInt(lastUpdatedLocal) >= parseInt(lastUpdatedRemote)) {
|
||||||
|
console.warn('[Rescroller] Warning: ignoring sync down; remote data is out of date.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var key in items) {
|
||||||
|
var val = items[key];
|
||||||
|
if (!val) { continue; }
|
||||||
|
|
||||||
|
localStorage[key] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// force refresh of this.settings._settings
|
||||||
|
this.settings.resetJSCache();
|
||||||
|
|
||||||
|
// migrate incoming data
|
||||||
|
this.performMigrations();
|
||||||
|
this.generateScrollbarCSS();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sync our settings up to Chrome Storage.
|
||||||
|
*
|
||||||
|
* @note we used to throttle this ourselves with a queueSyncUp() method, but it seemed like overkill since the limit was upped from 10/min to 120/min:
|
||||||
|
* https://bugs.chromium.org/p/chromium/issues/detail?id=270665#c19 (@see MAX_WRITE_OPERATIONS_PER_MINUTE)
|
||||||
|
*/
|
||||||
|
syncUp: function() {
|
||||||
|
|
||||||
|
var ls = {};
|
||||||
|
for (var key in localStorage) {
|
||||||
|
if (key == 'generated-css') { continue; } // waste of time to sync this
|
||||||
|
if (!localStorage[key]) { continue; }
|
||||||
|
|
||||||
|
// For legacy, ignore any images that are too big to sync
|
||||||
|
if ((encodeURI(localStorage[key]).split(/%..|./).length - 1) > chrome.storage.sync.QUOTA_BYTES_PER_ITEM) {
|
||||||
|
console.warn('[Rescroller] Ignoring sync up of image > 8 KB.')
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ls[key] = localStorage[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
chrome.storage.sync.set(ls);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore the default settings for the scrollbars.
|
||||||
|
*
|
||||||
|
* Slider/background theme are shades of Material's Blue Grey colors:
|
||||||
|
* https://material.google.com/style/color.html#color-color-palette
|
||||||
|
*/
|
||||||
|
restoreDefaults: function(noSync) {
|
||||||
|
|
||||||
|
this.properties.setMultiple({
|
||||||
|
|
||||||
|
// General
|
||||||
|
"size" : 8,
|
||||||
|
"subbackground-color" : "#000000",
|
||||||
|
"corner-background" : "#B0BEC5",
|
||||||
|
// "resizer-background" : "#FFC31F",
|
||||||
|
|
||||||
|
// Background
|
||||||
|
"background-color" : "#B0BEC5",
|
||||||
|
"background-shadow-color" : "#000000",
|
||||||
|
"background-shadow-size" : 0,
|
||||||
|
"background-border-size" : 0,
|
||||||
|
"background-border-color" : "#000000",
|
||||||
|
"background-border-style" : "solid",
|
||||||
|
"background-radius" : 0,
|
||||||
|
// hovering
|
||||||
|
"background-color-hover" : "#D9D9D9",
|
||||||
|
"background-shadow-color-hover" : "#000000",
|
||||||
|
"background-shadow-size-hover" : 0,
|
||||||
|
// active
|
||||||
|
"background-color-active" : "#D9D9D9",
|
||||||
|
"background-shadow-color-active" : "#000000",
|
||||||
|
"background-shadow-size-active" : 0,
|
||||||
|
|
||||||
|
// Scrollbar piece/slider
|
||||||
|
"slider-color" : "#455A64",
|
||||||
|
"slider-shadow-color" : "#000000",
|
||||||
|
"slider-shadow-size" : 0,
|
||||||
|
"slider-radius" : 0,
|
||||||
|
"slider-border-size" : 0,
|
||||||
|
"slider-border-color" : "#000000",
|
||||||
|
"slider-border-style" : "solid",
|
||||||
|
// hovering
|
||||||
|
"slider-color-hover" : "#666",
|
||||||
|
"slider-shadow-color-hover" : "#000000",
|
||||||
|
"slider-shadow-size-hover" : 0,
|
||||||
|
// active
|
||||||
|
"slider-color-active" : "#666",
|
||||||
|
"slider-shadow-color-active" : "#000000",
|
||||||
|
"slider-shadow-size-active" : 0,
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
"showbuttons" : "off",
|
||||||
|
"buttons-size" : 20,
|
||||||
|
"buttons-color" : "#666666",
|
||||||
|
"buttons-shadow-color" : "#000000",
|
||||||
|
"buttons-shadow-size" : 0,
|
||||||
|
"buttons-radius" : 0,
|
||||||
|
"buttons-border-size" : 0,
|
||||||
|
"buttons-border-color" : "#666",
|
||||||
|
"buttons-border-style" : "solid",
|
||||||
|
"buttons-background-image-up" : chrome.extension.getURL("images/defaults/up.png"),
|
||||||
|
"buttons-background-image-down" : chrome.extension.getURL("images/defaults/down.png"),
|
||||||
|
"buttons-background-image-left" : chrome.extension.getURL("images/defaults/left.png"),
|
||||||
|
"buttons-background-image-right" : chrome.extension.getURL("images/defaults/right.png"),
|
||||||
|
// hovering
|
||||||
|
"buttons-color-hover" : "#666666",
|
||||||
|
"buttons-shadow-color-hover" : "#000000",
|
||||||
|
"buttons-shadow-size-hover" : 0,
|
||||||
|
"buttons-background-image-up-hover" : chrome.extension.getURL("images/defaults/up.png"),
|
||||||
|
"buttons-background-image-down-hover" : chrome.extension.getURL("images/defaults/down.png"),
|
||||||
|
"buttons-background-image-left-hover" : chrome.extension.getURL("images/defaults/left.png"),
|
||||||
|
"buttons-background-image-right-hover" : chrome.extension.getURL("images/defaults/right.png"),
|
||||||
|
// active
|
||||||
|
"buttons-color-active" : "#666666",
|
||||||
|
"buttons-shadow-color-active" : "#000000",
|
||||||
|
"buttons-shadow-size-active" : 0,
|
||||||
|
"buttons-background-image-up-active" : chrome.extension.getURL("images/defaults/up.png"),
|
||||||
|
"buttons-background-image-down-active" : chrome.extension.getURL("images/defaults/down.png"),
|
||||||
|
"buttons-background-image-left-active" : chrome.extension.getURL("images/defaults/left.png"),
|
||||||
|
"buttons-background-image-right-active" : chrome.extension.getURL("images/defaults/right.png"),
|
||||||
|
|
||||||
|
// Reset all non-button images
|
||||||
|
"slider-background-image-vertical" : '',
|
||||||
|
"slider-background-image-horizontal" : '',
|
||||||
|
"slider-background-image-vertical-hover" : '',
|
||||||
|
"slider-background-image-horizontal-hover" : '',
|
||||||
|
"slider-background-image-vertical-active" : '',
|
||||||
|
"slider-background-image-horizontal-active" : '',
|
||||||
|
|
||||||
|
"background-background-image-vertical" : '',
|
||||||
|
"background-background-image-horizontal" : '',
|
||||||
|
"background-background-image-vertical-hover" : '',
|
||||||
|
"background-background-image-horizontal-hover" : '',
|
||||||
|
"background-background-image-vertical-active" : '',
|
||||||
|
"background-background-image-horizontal-active" : '',
|
||||||
|
|
||||||
|
// Custom CSS
|
||||||
|
// @note potential improvement: maybe, if the the user enters this, it should be used in addition to the generated CSS?
|
||||||
|
// This way people can override just some parts of the styling, or everything.
|
||||||
|
"customcss" : "::-webkit-scrollbar {\
|
||||||
|
\n\n\
|
||||||
|
}\n\
|
||||||
|
::-webkit-scrollbar-button {\
|
||||||
|
\n\n\
|
||||||
|
}\n\
|
||||||
|
::-webkit-scrollbar-track {\
|
||||||
|
\n\n\
|
||||||
|
}\n\
|
||||||
|
::-webkit-scrollbar-track-piece {\
|
||||||
|
\n\n\
|
||||||
|
}\n\
|
||||||
|
::-webkit-scrollbar-thumb {\
|
||||||
|
\n\n\
|
||||||
|
}\n\
|
||||||
|
::-webkit-scrollbar-corner {\
|
||||||
|
\n\n\
|
||||||
|
}\n\
|
||||||
|
::-webkit-resizer {\
|
||||||
|
\n\n\
|
||||||
|
}"
|
||||||
|
}, noSync);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gnerate a CSS string from our scrollbar settings and save it to local storage for browser tabs to use.
|
||||||
|
*/
|
||||||
|
generateScrollbarCSS: function() {
|
||||||
|
localStorage['generated-css'] = this.getCSSString();
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grab data from local storage and convert it into a CSS string
|
||||||
|
*/
|
||||||
|
getCSSString: function() {
|
||||||
|
|
||||||
|
// If user has chosen to specify his own CSS, just return that
|
||||||
|
if (this.properties.get("usecustomcss") == "checked") { return this.properties.get("customcss"); }
|
||||||
|
|
||||||
|
// Build our CSS structure as JSON for readability and maintainability. Then, we'll convert it to CSS!
|
||||||
|
var json = {
|
||||||
|
children: {
|
||||||
|
|
||||||
|
// Base
|
||||||
|
"::-webkit-scrollbar, ::-webkit-scrollbar:horizontal, ::-webkit-scrollbar:vertical": {
|
||||||
|
"attributes": {
|
||||||
|
"width": "%spx".fmt(this.properties.get('size')),
|
||||||
|
"height": "%spx".fmt(this.properties.get('size')),
|
||||||
|
"background-color": "%s".fmt(this.properties.get('subbackground-color'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"::-webkit-scrollbar-track-piece": {
|
||||||
|
"attributes": {
|
||||||
|
"background-color": this.properties.get('background-color'),
|
||||||
|
"box-shadow": "inset 0 0 %spx %s".fmt(this._precentageToPixels(this.properties.get('background-shadow-size'), true), this.properties.get('background-shadow-color')),
|
||||||
|
"border": "%spx %s %s".fmt(this._precentageToPixels(this.properties.get('background-border-size')), this.properties.get('background-border-style'), this.properties.get('background-border-color')),
|
||||||
|
"border-radius": "%spx".fmt(this._precentageToPixels(this.properties.get('background-radius')))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-track-piece:vertical": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('background-background-image-vertical'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-track-piece:horizontal": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('background-background-image-horizontal'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"::-webkit-scrollbar-thumb": {
|
||||||
|
"attributes": {
|
||||||
|
"background-color": this.properties.get('slider-color'),
|
||||||
|
"box-shadow": "inset 0 0 %spx %s".fmt(this._precentageToPixels(this.properties.get('slider-shadow-size'), true), this.properties.get('slider-shadow-color')),
|
||||||
|
"border-radius": "%spx".fmt(this._precentageToPixels(this.properties.get('slider-radius'))),
|
||||||
|
"border": "%spx %s %s".fmt(this._precentageToPixels(this.properties.get('slider-border-size')), this.properties.get('slider-border-style'), this.properties.get('slider-border-color'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-thumb:vertical": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('slider-background-image-vertical'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-thumb:horizontal": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('slider-background-image-horizontal'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"::-webkit-scrollbar-corner": {
|
||||||
|
"attributes": {
|
||||||
|
"background-color": this.properties.get('corner-background')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// "::-webkit-resizer": {
|
||||||
|
// "attributes": {
|
||||||
|
// "background-color": this.properties.get('resizer-background')
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Conditionals:
|
||||||
|
|
||||||
|
if (this.properties.get('showbuttons') == 'checked') {
|
||||||
|
$.extend(json.children, {
|
||||||
|
"::-webkit-scrollbar-button": {
|
||||||
|
"attributes": {
|
||||||
|
"background-color": this.properties.get('buttons-color'),
|
||||||
|
"border-radius": "%spx".fmt(this._precentageToPixels(this.properties.get('buttons-radius'))),
|
||||||
|
"box-shadow": "inset 0 0 %spx %s".fmt(this._precentageToPixels(this.properties.get('buttons-shadow-size'), true), this.properties.get('buttons-shadow-color')),
|
||||||
|
"border": "%spx %s %s".fmt(this._precentageToPixels(this.properties.get('buttons-border-size')), this.properties.get('buttons-border-style'), this.properties.get('buttons-border-color')),
|
||||||
|
"display": "block"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:vertical": {
|
||||||
|
"attributes": {
|
||||||
|
"height": "%spx".fmt(this.properties.get('buttons-size'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:horizontal": {
|
||||||
|
"attributes": {
|
||||||
|
"width": "%spx".fmt(this.properties.get('buttons-size'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:vertical:decrement": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('buttons-background-image-up'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:vertical:increment": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('buttons-background-image-down'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:horizontal:increment": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('buttons-background-image-right'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:horizontal:decrement": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('buttons-background-image-left'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.properties.get('buttons-use-hover') == 'checked') {
|
||||||
|
$.extend(json.children, {
|
||||||
|
"::-webkit-scrollbar-button:vertical:decrement:hover": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('buttons-background-image-up-hover'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:vertical:increment:hover": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('buttons-background-image-down-hover'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:horizontal:increment:hover": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('buttons-background-image-right-hover'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:horizontal:decrement:hover": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('buttons-background-image-left-hover'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:hover": {
|
||||||
|
"attributes": {
|
||||||
|
"background-color": this.properties.get('buttons-color-hover'),
|
||||||
|
"box-shadow": "inset 0 0 %spx %s".fmt(this._precentageToPixels(this.properties.get('buttons-shadow-size-hover'), true), this.properties.get('buttons-shadow-color-hover'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.properties.get('buttons-use-active') == 'checked') {
|
||||||
|
$.extend(json.children, {
|
||||||
|
"::-webkit-scrollbar-button:vertical:decrement:active": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('buttons-background-image-up-active'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:vertical:increment:active": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('buttons-background-image-down-active'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:horizontal:increment:active": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('buttons-background-image-right-active'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:horizontal:decrement:active": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('buttons-background-image-left-active'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-button:active": {
|
||||||
|
"attributes": {
|
||||||
|
"background-color": this.properties.get('buttons-color-active'),
|
||||||
|
"box-shadow": "inset 0 0 %spx %s')".fmt(this._precentageToPixels(this.properties.get('buttons-shadow-size-active'), true), this.properties.get('buttons-shadow-color-active'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use single buttons (hide the doubles):
|
||||||
|
$.extend(json.children, {
|
||||||
|
"::-webkit-scrollbar-button:vertical:start:increment, ::-webkit-scrollbar-button:vertical:end:decrement, ::-webkit-scrollbar-button:horizontal:start:increment, ::-webkit-scrollbar-button:horizontal:end:decrement": {
|
||||||
|
"attributes": {
|
||||||
|
"display": "none"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.properties.get("background-use-hover") == "checked") {
|
||||||
|
$.extend(json.children, {
|
||||||
|
"::-webkit-scrollbar-track-piece:vertical:hover": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('background-background-image-vertical-hover'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-track-piece:horizontal:hover": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('background-background-image-horizontal-hover'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-track-piece:hover ": {
|
||||||
|
"attributes": {
|
||||||
|
"background-color": this.properties.get('background-color-hover'),
|
||||||
|
"box-shadow": "inset 0 0 %spx %s".fmt(this._precentageToPixels(this.properties.get('background-shadow-size-hover'), true), this.properties.get('background-shadow-color-hover'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.properties.get("background-use-active") == "checked") {
|
||||||
|
$.extend(json.children, {
|
||||||
|
"::-webkit-scrollbar-track-piece:vertical:active": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('background-background-image-vertical-active'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-track-piece:horizontal:active": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('background-background-image-horizontal-active'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-track-piece:active": {
|
||||||
|
"attributes": {
|
||||||
|
"background-color": this.properties.get('background-color-active'),
|
||||||
|
"box-shadow": "inset 0 0 %spx %s".fmt(this._precentageToPixels(this.properties.get('background-shadow-size-active'), true), this.properties.get('background-shadow-color-active'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.properties.get("slider-use-hover") == "checked") {
|
||||||
|
$.extend(json.children, {
|
||||||
|
"::-webkit-scrollbar-thumb:hover": {
|
||||||
|
"attributes": {
|
||||||
|
"background-color": this.properties.get('slider-color-hover'),
|
||||||
|
"box-shadow": "inset 0 0 %spx %s".fmt(this._precentageToPixels(this.properties.get('slider-shadow-size-hover'), true), this.properties.get('slider-shadow-color-hover'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-thumb:vertical:hover": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('slider-background-image-vertical-hover'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-thumb:horizontal:hover": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('slider-background-image-horizontal-hover'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.properties.get("slider-use-active") == "checked") {
|
||||||
|
$.extend(json.children, {
|
||||||
|
"::-webkit-scrollbar-thumb:active": {
|
||||||
|
"attributes": {
|
||||||
|
"background-color": this.properties.get('slider-color-active'),
|
||||||
|
"box-shadow": "inset 0 0 %spx %s".fmt(this._precentageToPixels(this.properties.get('slider-shadow-size-active'), true), this.properties.get('slider-shadow-color-active'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-thumb:vertical:active": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('slider-background-image-vertical-active'))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"::-webkit-scrollbar-thumb:horizontal:active": {
|
||||||
|
"attributes": {
|
||||||
|
"background-image": "url('%s')".fmt(this.properties.get('slider-background-image-horizontal-active'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some cleanup before we send it off!
|
||||||
|
$.each(json.children, function(selector, children) {
|
||||||
|
var attrs = children.attributes
|
||||||
|
$.each(attrs, function(attr_name, attr_val) { // assume we never go deeper than one level
|
||||||
|
|
||||||
|
if (!attr_val) { return true; } // continue
|
||||||
|
|
||||||
|
// Clear out any empty image values to avoid erronius server calls
|
||||||
|
if (attr_val == "url('')") {
|
||||||
|
attrs[attr_name] = '""';
|
||||||
|
return true; // continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure every attribute is marked '!important'
|
||||||
|
attrs[attr_name] = attr_val + ' !important';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return CSSJSON.toCSS(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"background": {
|
||||||
|
"persistant": false,
|
||||||
|
"scripts": [ "js/jquery.js", "js/cssjson.js", "js/rescroller.js", "js/background.js" ]
|
||||||
|
},
|
||||||
|
"browser_action": {
|
||||||
|
"default_icon": "appicons/icon19.png",
|
||||||
|
"default_title": "Rescroller Settings"
|
||||||
|
},
|
||||||
|
"description": "Decorate your scrollbars.",
|
||||||
|
"icons": {
|
||||||
|
"128": "appicons/icon128.png",
|
||||||
|
"16": "appicons/icon16.png",
|
||||||
|
"19": "appicons/icon19.png",
|
||||||
|
"48": "appicons/icon48.png"
|
||||||
|
},
|
||||||
|
"key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDf7Pb6m0Y9FUeE/I1KlD8Tv7E7K1AZY8MIdLm9Cknitwldt+SpwROOnI30pPyCh66kZVtvtAcAqp1lP+BGorm5wEdf5pAaXFccXFSxQtN861hnwYY+/s+FseGmGZWVCpaRZd4mowojAesS1cI1siTULWoz0u9c8pQ2t0L3vA3VxwIDAQAB",
|
||||||
|
"manifest_version": 2,
|
||||||
|
"name": "Rescroller",
|
||||||
|
"options_page": "options.html",
|
||||||
|
"permissions": [ "\u003Call_urls>", "storage", "tabs" ],
|
||||||
|
"update_url": "https://clients2.google.com/service/update2/crx",
|
||||||
|
"version": "1.3",
|
||||||
|
"version_name": "1.3",
|
||||||
|
"web_accessible_resources": [ "images/defaults/up.png", "images/defaults/down.png", "images/defaults/left.png", "images/defaults/right.png" ]
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
[06:45:51] Using gulpfile /vagrant/gulpfile.js
|
||||||
|
[06:45:51] Starting 'watch'...
|
||||||
|
[06:45:51] Finished 'watch' after 82 ms
|
||||||
|
[06:46:05] Using gulpfile /vagrant/gulpfile.js
|
||||||
|
[06:46:05] Starting 'watch'...
|
||||||
|
[06:46:05] Finished 'watch' after 80 ms
|
||||||
|
[06:47:30] Using gulpfile /vagrant/gulpfile.js
|
||||||
|
[06:47:30] Starting 'watch'...
|
||||||
|
[06:47:30] Finished 'watch' after 82 ms
|
@ -0,0 +1,696 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Rescroller</title>
|
||||||
|
<link type="text/css" rel="stylesheet" href="style.css"></link>
|
||||||
|
<script type="text/javascript" src="js/jquery.js"></script>
|
||||||
|
<script type="text/javascript" src="js/jquery-ui.js"></script>
|
||||||
|
<script type="text/javascript" src="js/rescroller.js"></script>
|
||||||
|
<script type="text/javascript" src="js/cssjson.js"></script>
|
||||||
|
<script type="text/javascript" src="js/options.js"></script>
|
||||||
|
<script type="text/javascript" src="js/jquery-minicolors/jquery.miniColors.js"></script>
|
||||||
|
<link type="text/css" rel="stylesheet" href="js/jquery-minicolors/jquery.miniColors.css" />
|
||||||
|
<!-- @todo:david put "fork on github" note in -->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="errorbox">Error!</div>
|
||||||
|
<div id="save-confirm">
|
||||||
|
<p><b>Settings Saved</b></p>
|
||||||
|
<p>Your scrollbar settings are saved automatically. If you are signed into Chrome with sync, your scrollbars will follow you across computers.</p>
|
||||||
|
<p><a href="#" id="hide-saved-confirm">Don't show again</a></p>
|
||||||
|
</div>
|
||||||
|
<div id="settings">
|
||||||
|
<div id="logo-wrapper">
|
||||||
|
<img src="images/logo-hover.png" id="logo-hover" />
|
||||||
|
<img src="images/logo.png" id="logo" />
|
||||||
|
</div>
|
||||||
|
<form id="theform">
|
||||||
|
<div id="welcomemsg">
|
||||||
|
<p>Welcome to Rescroller! Using the tools below, you can customize the look and feel of scrollbars across your Chrome browser. Please take a moment to style each scrollbar element and their properties, including the sizes and colors of shadows and borders. This extension will override scrollbars on all websites, including those that have their own customized scrollbars, unless you specify them in the blacklist below.</p>
|
||||||
|
|
||||||
|
<p><small>(Please note that, due to general restrictions for Chrome extensions, your scrollbars will not appear on the Chrome Webstore, or URLS that begin with "<code>chrome://</code>". However, you can enable Rescroller for local webpages and incognito browsing in Chrome's extension manager.)</small></p>
|
||||||
|
</div>
|
||||||
|
<div class="section" id="general">
|
||||||
|
<h1 class="sectionheader">General</h1>
|
||||||
|
<div id="size" class="slider-property customcss-collapsible" style="display: block;">
|
||||||
|
<div class="property-title">Scrollbar Size</div>
|
||||||
|
<div class="slider slider-h"></div>
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="resetformatting" class="button">Restore Default Formatting</div>
|
||||||
|
<p style="margin: 20px auto 10px"><b>Blacklist:</b></p>
|
||||||
|
<p class="small-description">Enter any sites for which you would not like to override scrollbar styling, below (separated by commas):</p>
|
||||||
|
<textarea id="excludedsites" placeholder="Example: mail.google.com, facebook.com"></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" id="scrollbar-slider">
|
||||||
|
<h1 class="sectionheader">Slider Handle</h1>
|
||||||
|
<div id="slider-color" class="colorpicker-container" style="display: block">
|
||||||
|
<b>Color:</b>
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td><p class="imagepicker-label">Vertical Image:</p></td>
|
||||||
|
<td><p class="imagepicker-label">Horizontal Image:</p></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div id="slider-background-image-vertical" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div id="slider-background-image-horizontal" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="subsection">
|
||||||
|
<p class="sectionsubheader">Shadows</p>
|
||||||
|
<div id="slider-shadow-size" class="slider-property">
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div class="slider slider-v"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="slider-shadow-color" class="colorpicker-container">
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div class="subsection">
|
||||||
|
<p class="sectionsubheader">Borders</p>
|
||||||
|
<div id="slider-border-size" class="slider-property">
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div class="slider slider-v"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="slider-border-color" class="colorpicker-container">
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
Style:
|
||||||
|
<!--<input type="text" id="slider-border-style" />-->
|
||||||
|
<select id="slider-border-style">
|
||||||
|
<option value="solid">Solid</option>
|
||||||
|
<option value="dashed">Dashed</option>
|
||||||
|
<option value="dotted">Dotted</option>
|
||||||
|
<option value="double">Double</option>
|
||||||
|
<option value="groove">Groove</option>
|
||||||
|
<option value="inset">Inset</option>
|
||||||
|
<option value="outset">Outset</option>
|
||||||
|
<option value="ridge">Ridge</option>
|
||||||
|
</select>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p class="sectionsubheader">Rounded Corners</p>
|
||||||
|
<div id="slider-radius" class="slider-property">
|
||||||
|
<div class="slider slider-h"></div>
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="custom-hover-active-label">Customize Style When Hovering: <input type="checkbox" id="slider-use-hover" class="toggle-hover-active" data-wrapperid="slider-hover-wrapper" /></p>
|
||||||
|
<div id="slider-hover-wrapper">
|
||||||
|
<p class="sectionsubheader">Hovering State</p>
|
||||||
|
<div class="subsection">
|
||||||
|
<div id="slider-color-hover" class="colorpicker-container">
|
||||||
|
<b>Color:</b>
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Vertical Image:</p>
|
||||||
|
<div id="slider-background-image-vertical-hover" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Horizontal Image:</p>
|
||||||
|
<div id="slider-background-image-horizontal-hover" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="subsection">
|
||||||
|
<p class="property-title">Shadows</p>
|
||||||
|
<div id="slider-shadow-size-hover" class="slider-property">
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div class="slider slider-v"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="slider-shadow-color-hover" class="colorpicker-container">
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="custom-hover-active-label">Customize Style When Clicking: <input type="checkbox" id="slider-use-active" class="toggle-hover-active" data-wrapperid="slider-active-wrapper" /></p>
|
||||||
|
<div id="slider-active-wrapper">
|
||||||
|
<p class="sectionsubheader">Active State</p>
|
||||||
|
<div class="subsection">
|
||||||
|
<div id="slider-color-active" class="colorpicker-container">
|
||||||
|
<b>Color:</b>
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Vertical Image:</p>
|
||||||
|
<div id="slider-background-image-vertical-active" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Horizontal Image:</p>
|
||||||
|
<div id="slider-background-image-horizontal-active" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="subsection">
|
||||||
|
<p class="property-title">Shadows</p>
|
||||||
|
<div id="slider-shadow-size-active" class="slider-property">
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div class="slider slider-v"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="slider-shadow-color-active" class="colorpicker-container">
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- **************** Scrollbar Background ********************** -->
|
||||||
|
|
||||||
|
<div class="section" id="scrollbar-bg">
|
||||||
|
<h1 class="sectionheader">Background</h1>
|
||||||
|
<div id="background-color" class="colorpicker-container" style="display: block;">
|
||||||
|
<b>Color:</b>
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td><p class="imagepicker-label">Vertical Image:</p></td>
|
||||||
|
<td><p class="imagepicker-label">Horizontal Image:</p></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div id="background-background-image-vertical" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div id="background-background-image-horizontal" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div class="subsection">
|
||||||
|
<p class="sectionsubheader">Shadows</p>
|
||||||
|
<div id="background-shadow-size" class="slider-property">
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div class="slider slider-v"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="background-shadow-color" class="colorpicker-container">
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="subsection">
|
||||||
|
<p class="sectionsubheader">Borders</p>
|
||||||
|
<div id="background-border-size" class="slider-property">
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div class="slider slider-v"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="background-border-color" class="colorpicker-container">
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
Style:
|
||||||
|
<select id="background-border-style">
|
||||||
|
<option value="solid">Solid</option>
|
||||||
|
<option value="dashed">Dashed</option>
|
||||||
|
<option value="dotted">Dotted</option>
|
||||||
|
<option value="double">Double</option>
|
||||||
|
<option value="groove">Groove</option>
|
||||||
|
<option value="inset">Inset</option>
|
||||||
|
<option value="outset">Outset</option>
|
||||||
|
<option value="ridge">Ridge</option>
|
||||||
|
</select>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="sectionsubheader">Rounded Corners</p>
|
||||||
|
<div id="background-radius" class="slider-property">
|
||||||
|
<div class="slider slider-h"></div>
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="custom-hover-active-label">Customize Style When Hovering: <input type="checkbox" id="background-use-hover" class="toggle-hover-active" data-wrapperid="background-hover-wrapper" /></p>
|
||||||
|
<div id="background-hover-wrapper">
|
||||||
|
<p class="sectionsubheader">Hovering State</p>
|
||||||
|
<div class="subsection">
|
||||||
|
<div id="background-color-hover" class="colorpicker-container" style="display: block;">
|
||||||
|
<b>Color:</b>
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Vertical Image:</p>
|
||||||
|
<div id="background-background-image-vertical-hover" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Horizontal Image:</p>
|
||||||
|
<div id="background-background-image-horizontal-hover" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="subsection">
|
||||||
|
<p class="property-title">Shadows:</p>
|
||||||
|
<div id="background-shadow-size-hover" class="slider-property">
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div class="slider slider-v"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="background-shadow-color-hover" class="colorpicker-container">
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="custom-hover-active-label">Customize Style When Clicking: <input type="checkbox" id="background-use-active" class="toggle-hover-active" data-wrapperid="background-active-wrapper" /></p>
|
||||||
|
<div id="background-active-wrapper">
|
||||||
|
<p class="sectionsubheader">Active State</p>
|
||||||
|
<div class="subsection">
|
||||||
|
<div id="background-color-active" class="colorpicker-container" style="display: block;">
|
||||||
|
<b>Color:</b>
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Vertical Image:</p>
|
||||||
|
<div id="background-background-image-vertical-active" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Horizontal Image:</p>
|
||||||
|
<div id="background-background-image-horizontal-active" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="subsection">
|
||||||
|
<p class="property-title">Shadows:</p>
|
||||||
|
<div id="background-shadow-size-active" class="slider-property">
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div class="slider slider-v"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="background-shadow-color-active" class="colorpicker-container">
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ********************** Scrollbar Buttons ************************ -->
|
||||||
|
|
||||||
|
<div class="section" id="scrollbar-buttons">
|
||||||
|
<h1 class="sectionheader">Buttons</h1>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>Show scroll buttons:</td>
|
||||||
|
<td><input type="checkbox" id="showbuttons" /></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div id="buttons-toggleable">
|
||||||
|
<div id="buttons-color" class="colorpicker-container" style="display: block;">
|
||||||
|
<b>Color:</b>
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<div id="buttons-size" class="slider-property" style="display: block;">
|
||||||
|
<div class="slider slider-h"></div>
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td><p class="imagepicker-label">Up</p></td>
|
||||||
|
<td><p class="imagepicker-label">Down</p></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div id="buttons-background-image-up" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div id="buttons-background-image-down" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><p class="imagepicker-label">Left</p></td>
|
||||||
|
<td><p class="imagepicker-label">Right</p></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div id="buttons-background-image-left" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div id="buttons-background-image-right" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p><a href="#" id="restore-arrow-defaults">Restore Default Arrows</a></p>
|
||||||
|
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
|
||||||
|
<div class="subsection">
|
||||||
|
<p class="sectionsubheader">Shadows</p>
|
||||||
|
<div id="buttons-shadow-size" class="slider-property">
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div class="slider slider-v"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="buttons-shadow-color" class="colorpicker-container">
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="subsection">
|
||||||
|
<p class="sectionsubheader">Borders</p>
|
||||||
|
<div id="buttons-border-size" class="slider-property">
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div class="slider slider-v"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="buttons-border-color" class="colorpicker-container">
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
Style:
|
||||||
|
<select id="buttons-border-style">
|
||||||
|
<option value="solid">Solid</option>
|
||||||
|
<option value="dashed">Dashed</option>
|
||||||
|
<option value="dotted">Dotted</option>
|
||||||
|
<option value="double">Double</option>
|
||||||
|
<option value="groove">Groove</option>
|
||||||
|
<option value="inset">Inset</option>
|
||||||
|
<option value="outset">Outset</option>
|
||||||
|
<option value="ridge">Ridge</option>
|
||||||
|
</select>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="sectionsubheader">Rounded Corners</p>
|
||||||
|
<div id="buttons-radius" class="slider-property">
|
||||||
|
<div class="slider slider-h"></div>
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="custom-hover-active-label">Customize Style When Hovering: <input type="checkbox" id="buttons-use-hover" class="toggle-hover-active" data-wrapperid="buttons-hover-wrapper" /></p>
|
||||||
|
<div id="buttons-hover-wrapper">
|
||||||
|
<p class="sectionsubheader">Hovering State</p>
|
||||||
|
<div class="subsection">
|
||||||
|
<div id="buttons-color-hover" class="colorpicker-container" style="display: block;">
|
||||||
|
<b>Color:</b>
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Up Image:</p>
|
||||||
|
<div id="buttons-background-image-up-hover" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Down Image:</p>
|
||||||
|
<div id="buttons-background-image-down-hover" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Left Image:</p>
|
||||||
|
<div id="buttons-background-image-left-hover" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Right Image:</p>
|
||||||
|
<div id="buttons-background-image-right-hover" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p><a href="#" id="restore-arrow-defaults-hover">Restore Default Arrows</a></p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="subsection">
|
||||||
|
<p class="property-title">Shadows:</p>
|
||||||
|
<div id="buttons-shadow-size-hover" class="slider-property">
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div class="slider slider-v"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="buttons-shadow-color-hover" class="colorpicker-container">
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="custom-hover-active-label">Customize Style When Clicking: <input type="checkbox" id="buttons-use-active" class="toggle-hover-active" data-wrapperid="buttons-active-wrapper" /></p>
|
||||||
|
<div id="buttons-active-wrapper">
|
||||||
|
<p class="sectionsubheader">Active State</p>
|
||||||
|
<div class="subsection">
|
||||||
|
<div id="buttons-color-active" class="colorpicker-container" style="display: block;">
|
||||||
|
<b>Color:</b>
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Up Image:</p>
|
||||||
|
<div id="buttons-background-image-up-active" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Down Image:</p>
|
||||||
|
<div id="buttons-background-image-down-active" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Left Image:</p>
|
||||||
|
<div id="buttons-background-image-left-active" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<p class="imagepicker-label">Right Image:</p>
|
||||||
|
<div id="buttons-background-image-right-active" class="imagepicker-container">
|
||||||
|
<input type="file" class="selector" />
|
||||||
|
<a href="#" class="selector-button">Select Image</a>
|
||||||
|
<div class="thumbframe">
|
||||||
|
<div class="thumbcontainer">No Image Loaded</div>
|
||||||
|
<img src="images/close-button.png" class="clearimage"></img>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p><a href="#" id="restore-arrow-defaults-active">Restore Default Arrows</a></p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="subsection">
|
||||||
|
<p class="property-title">Shadows:</p>
|
||||||
|
<div id="buttons-shadow-size-active" class="slider-property">
|
||||||
|
<div class="slider-value"></div>
|
||||||
|
<div class="slider slider-v"></div>
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
</div>
|
||||||
|
<div id="buttons-shadow-color-active" class="colorpicker-container">
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="section" id="misc">
|
||||||
|
<h1 class="sectionheader">Miscellaneous</h1>
|
||||||
|
<div id="subbackground-color" class="colorpicker-container customcss-collapsible" style="display: block;">
|
||||||
|
<b>Sub-Background Color:</b>
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<div id="corner-background" class="colorpicker-container customcss-collapsible" style="display: block;">
|
||||||
|
<b>Corner Color:</b>
|
||||||
|
<input type="hidden" id="colortext" class="colorselection" />
|
||||||
|
<input type="text" class="colorvalue" />
|
||||||
|
</div>
|
||||||
|
<p>Use Custom CSS (Advanced Users Only): <input type="checkbox" id="usecustomcss" class="toggle-hover-active" data-wrapperid="customcss-wrapper" /></p>
|
||||||
|
<div id="customcss-wrapper">
|
||||||
|
<p class="small-description">While the tools above are useful in designing a unique scrollbar, they do not allow for complete customization of scrollbars within Google Chrome. If you are a web developer or are familiar with CSS styling, <a href="http://css-tricks.com/custom-scrollbars-in-webkit/" target="_blank">you may enter custom CSS</a> to override the above tools, below:</p>
|
||||||
|
<textarea id="customcss" placeholder="Enter CSS here"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
<!--<input type="submit" value="Update" />-->
|
||||||
|
</form>
|
||||||
|
<p style="display: none;"><a href="#" id="expandcss" >Click here to expand/collapse generated CSS</a></p>
|
||||||
|
<div id="generatedcss">Error</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,442 @@
|
|||||||
|
body {
|
||||||
|
text-align: center;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
background: url("images/bg.png"); /* http://subtlepatterns.com/patterns/dark_wall.png */
|
||||||
|
color: white;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 40px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #007ED3;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #09F;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
display: inline-block;
|
||||||
|
background: #666;
|
||||||
|
color: white;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-weight: bold;
|
||||||
|
-webkit-transition: background-color 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: #333;
|
||||||
|
-webkit-transition: background-color 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colorvalue {
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
font-size: 11px;
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#welcomemsg {
|
||||||
|
width: 515px;
|
||||||
|
margin: 0 auto 20px auto;
|
||||||
|
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
|
||||||
|
font-size: 15px;
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div#logo-wrapper {
|
||||||
|
width: 500px;
|
||||||
|
height: 173px;
|
||||||
|
margin: 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
img#logo, img#logo-hover {
|
||||||
|
position: absolute;
|
||||||
|
margin: 0;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img#logo {
|
||||||
|
-webkit-transition: opacity 3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
img#logo:hover {
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transition: opacity 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: "Righteous-Regular";
|
||||||
|
src: url("Righteous-Regular.ttf");
|
||||||
|
}
|
||||||
|
|
||||||
|
.section h1 {
|
||||||
|
font-size: 25px;
|
||||||
|
font-family: "Righteous-Regular";
|
||||||
|
}
|
||||||
|
|
||||||
|
div#errorbox {
|
||||||
|
background: pink;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
color: #900;
|
||||||
|
width: 88%;
|
||||||
|
margin: 0 5%;
|
||||||
|
padding: 10px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
border: 1px solid #900;
|
||||||
|
border-top: 0px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
z-index: 500;
|
||||||
|
display: none;
|
||||||
|
box-shadow: 0 0 20px #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small-description {
|
||||||
|
font-size: 11px;
|
||||||
|
margin: 20px auto 5px;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
width: 90%;
|
||||||
|
padding: 10px;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
font-size: 13px;
|
||||||
|
border: 2px solid gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea#customcss {
|
||||||
|
font-family: "Consolas", "Courier New", Courier, monospacel;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea:focus {
|
||||||
|
border: 2px solid #009600;
|
||||||
|
box-shadow: inset 0 0 5px gray;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#settings {
|
||||||
|
width: 500px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.section {
|
||||||
|
background: rgba(204, 204, 204, 0.8);
|
||||||
|
padding: 0px 10px 20px;
|
||||||
|
border-radius: 3px;
|
||||||
|
width: 500px;
|
||||||
|
margin: 20px auto;
|
||||||
|
color: black;
|
||||||
|
box-shadow: 0 0 25px black;
|
||||||
|
}
|
||||||
|
.section:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
.section .subsection {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 20px 20px 0px;
|
||||||
|
width: 185px; /*135*/
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section .custom-hover-active-label {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.section h1.sectionheader {
|
||||||
|
margin: 10px;
|
||||||
|
background: #333;
|
||||||
|
color: white;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 0 5px 20px;
|
||||||
|
border-bottom-left-radius: 3px;
|
||||||
|
border-bottom-right-radius: 3px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
div.section .sectionsubheader {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 15px;
|
||||||
|
background: #6D6D6D;
|
||||||
|
color: white;
|
||||||
|
padding: 2px;
|
||||||
|
border-bottom: 2px solid #009600;
|
||||||
|
border-top-left-radius: 3px;
|
||||||
|
border-top-right-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.section table {
|
||||||
|
margin: 10px auto;
|
||||||
|
}
|
||||||
|
div.section table p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
div.section table tr, div.section table td {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearimage {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
margin-right: -6px;
|
||||||
|
margin-top: -4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
div#generatedcss {
|
||||||
|
width: 500px;
|
||||||
|
background: lightgray;
|
||||||
|
font-family: consolas, 'Courier New', Courier, monospace;
|
||||||
|
margin: 20px auto;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: left;
|
||||||
|
color: black;
|
||||||
|
box-shadow: inset 0 0 10px black;
|
||||||
|
word-wrap: break-word;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Checkboxes */
|
||||||
|
input[type=checkbox] {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selector { display: none; }
|
||||||
|
.selector-button {
|
||||||
|
display: none;
|
||||||
|
background: #333;
|
||||||
|
border: 3px dashed #333;
|
||||||
|
color: white;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 3px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
.selector-button:hover {
|
||||||
|
background: #2D2D2D;
|
||||||
|
box-shadow: 0 0 5px black;
|
||||||
|
}
|
||||||
|
.thumbframe {
|
||||||
|
width: 100px;
|
||||||
|
background: #666;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 3px;
|
||||||
|
vertical-align: middle;
|
||||||
|
position: relative;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.thumbframe img {
|
||||||
|
max-width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imagepicker-container {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imagepicker-label {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 5px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.property-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.slider {
|
||||||
|
background: gray;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 5px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.slider-h {
|
||||||
|
width: 150px;
|
||||||
|
height: 7px;
|
||||||
|
padding: 0 10px;
|
||||||
|
margin: 7px auto 10px;
|
||||||
|
}
|
||||||
|
.slider-v {
|
||||||
|
height: 100px;
|
||||||
|
width: 7px;
|
||||||
|
padding: 10px 0;
|
||||||
|
margin: 15px auto 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All sliders */
|
||||||
|
.slider .ui-slider-handle {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
position: absolute;
|
||||||
|
x-index: 200;
|
||||||
|
background: #06C;
|
||||||
|
border-radius: 10px;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.slider-h .ui-slider-handle {
|
||||||
|
top: -2.5px;
|
||||||
|
margin-left: -6px;
|
||||||
|
}
|
||||||
|
.slider-v .ui-slider-handle {
|
||||||
|
left: -2.5px !important;
|
||||||
|
margin-bottom: -6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-slider-handle:active {
|
||||||
|
background: #353535;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider-value {
|
||||||
|
font-size: 11px;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 7px 5px 10px;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Color pickers */
|
||||||
|
.colorpicker-container {
|
||||||
|
margin: 10px auto;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colorpicker-container, .slider-property {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Modify color picker default styling */
|
||||||
|
.miniColors-trigger {
|
||||||
|
width: 45px !important;
|
||||||
|
height: 30px !important;
|
||||||
|
background-image: none !important;
|
||||||
|
border: 1px solid #455A64;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniColors-selector {
|
||||||
|
-webkit-border-radius: 0px !important;
|
||||||
|
border-radius: 0px !important;
|
||||||
|
border: none !important;
|
||||||
|
padding: 3px 4px !important;
|
||||||
|
height: 167px !important;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniColors-selector:before {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
left: -14px;
|
||||||
|
top: 35%;
|
||||||
|
border: 7px solid;
|
||||||
|
border-color: transparent white transparent transparent;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniColors-colors {
|
||||||
|
top: 3px !important;
|
||||||
|
left: 3px !important;
|
||||||
|
}
|
||||||
|
.miniColors-hues {
|
||||||
|
top: 3px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.miniColors-apply {
|
||||||
|
left: 7px;
|
||||||
|
font-size: 11px;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#save-confirm {
|
||||||
|
position: fixed;
|
||||||
|
top: 50px;
|
||||||
|
right: 20px;
|
||||||
|
width: 225px;
|
||||||
|
background: rgb(245, 245, 164);
|
||||||
|
color: black;
|
||||||
|
box-shadow: 0 0 20px black;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
display: none;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
#save-confirm:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
right: -20px;
|
||||||
|
top: 15px;
|
||||||
|
border: 10px solid;
|
||||||
|
border-color: transparent transparent transparent rgb(245, 245, 164);
|
||||||
|
}
|
||||||
|
|
||||||
|
#save-confirm a#hide-saved-confirm {
|
||||||
|
color: #003A91;
|
||||||
|
}
|
||||||
|
|
||||||
|
#save-confirm a#hide-saved-confirm:hover {
|
||||||
|
color: #005CE7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************
|
||||||
|
* WEBKIT SCROLLBARS *
|
||||||
|
********************/
|
||||||
|
|
||||||
|
/* The scrollbars themselves (height/width, mostly)
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The up/down/left/right buttons that move the "thumb"
|
||||||
|
::-webkit-scrollbar-button {
|
||||||
|
background-color: blue;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The entire scrollable area (including the track-piece and the scrollbar thumb)
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The scollbar area that is not being covered by the scrollbar
|
||||||
|
::-webkit-scrollbar-track-piece {
|
||||||
|
background-color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The scrollbar piece
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The corner space between horizontal and verticle scrollbars
|
||||||
|
::-webkit-scrollbar-corner {
|
||||||
|
background: purple;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The resizer piece that covers the scrollbar-corner (sometimes)
|
||||||
|
::-webkit-resizer {
|
||||||
|
background: orange;
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
MANIFEST-000001
|
@ -0,0 +1,2 @@
|
|||||||
|
2022/11/02-16:37:20.208 3 Creating DB /home/toto/.config/chromium/Default/Local Storage/leveldb since it was missing.
|
||||||
|
2022/11/02-16:37:20.209 3 Reusing MANIFEST /home/toto/.config/chromium/Default/Local Storage/leveldb/MANIFEST-000001
|
@ -311,6 +311,89 @@
|
|||||||
"was_installed_by_default": false,
|
"was_installed_by_default": false,
|
||||||
"was_installed_by_oem": false,
|
"was_installed_by_oem": false,
|
||||||
"withholding_permissions": false
|
"withholding_permissions": false
|
||||||
|
},
|
||||||
|
"ddehdnnhjimbggeeenghijehnpakijod": {
|
||||||
|
"active_bit": false,
|
||||||
|
"active_permissions": {
|
||||||
|
"api": [
|
||||||
|
"storage",
|
||||||
|
"tabs"
|
||||||
|
],
|
||||||
|
"explicit_host": [
|
||||||
|
"<all_urls>",
|
||||||
|
"chrome://favicon/*"
|
||||||
|
],
|
||||||
|
"manifest_permissions": []
|
||||||
|
},
|
||||||
|
"allowlist": 1,
|
||||||
|
"commands": {},
|
||||||
|
"content_settings": [],
|
||||||
|
"creation_flags": 9,
|
||||||
|
"events": [],
|
||||||
|
"from_webstore": true,
|
||||||
|
"granted_permissions": {
|
||||||
|
"api": [
|
||||||
|
"storage",
|
||||||
|
"tabs"
|
||||||
|
],
|
||||||
|
"explicit_host": [
|
||||||
|
"<all_urls>",
|
||||||
|
"chrome://favicon/*"
|
||||||
|
],
|
||||||
|
"manifest_permissions": []
|
||||||
|
},
|
||||||
|
"incognito_content_settings": [],
|
||||||
|
"incognito_preferences": {},
|
||||||
|
"install_time": "13311875435035454",
|
||||||
|
"location": 1,
|
||||||
|
"manifest": {
|
||||||
|
"background": {
|
||||||
|
"persistant": false,
|
||||||
|
"scripts": [
|
||||||
|
"js/jquery.js",
|
||||||
|
"js/cssjson.js",
|
||||||
|
"js/rescroller.js",
|
||||||
|
"js/background.js"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"browser_action": {
|
||||||
|
"default_icon": "appicons/icon19.png",
|
||||||
|
"default_title": "Rescroller Settings"
|
||||||
|
},
|
||||||
|
"description": "Decorate your scrollbars.",
|
||||||
|
"icons": {
|
||||||
|
"128": "appicons/icon128.png",
|
||||||
|
"16": "appicons/icon16.png",
|
||||||
|
"19": "appicons/icon19.png",
|
||||||
|
"48": "appicons/icon48.png"
|
||||||
|
},
|
||||||
|
"key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDf7Pb6m0Y9FUeE/I1KlD8Tv7E7K1AZY8MIdLm9Cknitwldt+SpwROOnI30pPyCh66kZVtvtAcAqp1lP+BGorm5wEdf5pAaXFccXFSxQtN861hnwYY+/s+FseGmGZWVCpaRZd4mowojAesS1cI1siTULWoz0u9c8pQ2t0L3vA3VxwIDAQAB",
|
||||||
|
"manifest_version": 2,
|
||||||
|
"name": "Rescroller",
|
||||||
|
"options_page": "options.html",
|
||||||
|
"permissions": [
|
||||||
|
"<all_urls>",
|
||||||
|
"storage",
|
||||||
|
"tabs"
|
||||||
|
],
|
||||||
|
"update_url": "https://clients2.google.com/service/update2/crx",
|
||||||
|
"version": "1.3",
|
||||||
|
"version_name": "1.3",
|
||||||
|
"web_accessible_resources": [
|
||||||
|
"images/defaults/up.png",
|
||||||
|
"images/defaults/down.png",
|
||||||
|
"images/defaults/left.png",
|
||||||
|
"images/defaults/right.png"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"needs_sync": true,
|
||||||
|
"path": "ddehdnnhjimbggeeenghijehnpakijod/1.3_0",
|
||||||
|
"preferences": {},
|
||||||
|
"regular_only_preferences": {},
|
||||||
|
"state": 1,
|
||||||
|
"was_installed_by_default": false,
|
||||||
|
"was_installed_by_oem": false,
|
||||||
|
"withholding_permissions": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|