mirror of
https://github.com/SoPat712/videospeed.git
synced 2025-08-22 02:18:45 -04:00
- Over-all working structure changed - tc.settings.keyBindings array added - Options page changed Clean up of #350
This commit is contained in:

committed by
Ilya Grigorik

parent
ecca27f0c0
commit
e24b95dd84
196
inject.js
196
inject.js
@@ -2,20 +2,31 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
var tc = {
|
var tc = {
|
||||||
settings: {
|
settings: {
|
||||||
speed: 1.0, // default 1x
|
speed: 1.0, // default 1x
|
||||||
resetSpeed: 1.0, // default 1x
|
|
||||||
speedStep: 0.1, // default 0.1x
|
/**
|
||||||
fastSpeed: 1.8, // default 1.8x
|
* these are not used and deprecated, will be removed in next update
|
||||||
rewindTime: 10, // default 10s
|
* but should be stay there because chrome.storage.sync.get needs them
|
||||||
advanceTime: 10, // default 10s
|
*/
|
||||||
resetKeyCode: 82, // default: R
|
resetSpeed: 1.0, // default 1.0
|
||||||
slowerKeyCode: 83, // default: S
|
speedStep: null, // default 0.1x just for buttons
|
||||||
fasterKeyCode: 68, // default: D
|
fastSpeed: null, // default 1.8x
|
||||||
rewindKeyCode: 90, // default: Z
|
rewindTime: null, // default 10s just for buttons
|
||||||
advanceKeyCode: 88, // default: X
|
advanceTime: null, // default 10s just for buttons
|
||||||
|
resetKeyCode: null, // default: R
|
||||||
|
slowerKeyCode: null, // default: S
|
||||||
|
fasterKeyCode: null, // default: D
|
||||||
|
rewindKeyCode: null, // default: Z
|
||||||
|
advanceKeyCode: null, // default: X
|
||||||
|
fastKeyCode: null, // default: G
|
||||||
|
/**
|
||||||
|
* these(above) are not used and deprecated, will be removed in next update
|
||||||
|
* but should be stay there because chrome.storage.sync.get needs them.
|
||||||
|
*/
|
||||||
|
|
||||||
displayKeyCode: 86, // default: V
|
displayKeyCode: 86, // default: V
|
||||||
fastKeyCode: 71, // default: G
|
|
||||||
rememberSpeed: false, // default: false
|
rememberSpeed: false, // default: false
|
||||||
startHidden: false, // default: false
|
startHidden: false, // default: false
|
||||||
|
keyBindings: [],
|
||||||
blacklist: `
|
blacklist: `
|
||||||
www.instagram.com
|
www.instagram.com
|
||||||
twitter.com
|
twitter.com
|
||||||
@@ -25,20 +36,66 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
chrome.storage.sync.get(tc.settings, function(storage) {
|
chrome.storage.sync.get(tc.settings, function (storage) {
|
||||||
|
tc.settings.keyBindings = storage.keyBindings; // Array
|
||||||
|
if (storage.keyBindings.length == 0) // if first initialization of 0.5.3
|
||||||
|
{
|
||||||
|
// UPDATE
|
||||||
|
tc.settings.keyBindings.push({
|
||||||
|
action: "slower",
|
||||||
|
key: Number(storage.slowerKeyCode) || 83,
|
||||||
|
value: Number(storage.speedStep) || 0.1,
|
||||||
|
force: false,
|
||||||
|
predefined: true
|
||||||
|
}); // default S
|
||||||
|
tc.settings.keyBindings.push({
|
||||||
|
action: "faster",
|
||||||
|
key: Number(storage.fasterKeyCode) || 68,
|
||||||
|
value: Number(storage.speedStep) || 0.1,
|
||||||
|
force: false,
|
||||||
|
predefined: true
|
||||||
|
}); // default: D
|
||||||
|
tc.settings.keyBindings.push({
|
||||||
|
action: "rewind",
|
||||||
|
key: Number(storage.rewindKeyCode) || 90,
|
||||||
|
value: Number(storage.rewindTime) || 10,
|
||||||
|
force: false,
|
||||||
|
predefined: true
|
||||||
|
}); // default: Z
|
||||||
|
tc.settings.keyBindings.push({
|
||||||
|
action: "advance",
|
||||||
|
key: Number(storage.advanceKeyCode) || 88,
|
||||||
|
value: Number(storage.advanceTime) || 10,
|
||||||
|
force: false,
|
||||||
|
predefined: true
|
||||||
|
}); // default: X
|
||||||
|
tc.settings.keyBindings.push({
|
||||||
|
action: "reset",
|
||||||
|
key: Number(storage.resetKeyCode) || 82,
|
||||||
|
value: 1.0,
|
||||||
|
force: false,
|
||||||
|
predefined: true
|
||||||
|
}); // default: R
|
||||||
|
tc.settings.keyBindings.push({
|
||||||
|
action: "fast",
|
||||||
|
key: Number(storage.fastKeyCode) || 71,
|
||||||
|
value: Number(storage.fastSpeed) || 1.8,
|
||||||
|
force: false,
|
||||||
|
predefined: true
|
||||||
|
}); // default: G
|
||||||
|
tc.settings.version = "0.5.3";
|
||||||
|
|
||||||
|
chrome.storage.sync.set({
|
||||||
|
keyBindings: tc.settings.keyBindings,
|
||||||
|
version: tc.settings.version,
|
||||||
|
displayKeyCode: tc.settings.displayKeyCode,
|
||||||
|
rememberSpeed: tc.settings.rememberSpeed,
|
||||||
|
startHidden: tc.settings.startHidden,
|
||||||
|
blacklist: tc.settings.blacklist.replace(/^\s+|\s+$/gm, '')
|
||||||
|
});
|
||||||
|
}
|
||||||
tc.settings.speed = Number(storage.speed);
|
tc.settings.speed = Number(storage.speed);
|
||||||
tc.settings.resetSpeed = Number(storage.resetSpeed);
|
|
||||||
tc.settings.speedStep = Number(storage.speedStep);
|
|
||||||
tc.settings.fastSpeed = Number(storage.fastSpeed);
|
|
||||||
tc.settings.rewindTime = Number(storage.rewindTime);
|
|
||||||
tc.settings.advanceTime = Number(storage.advanceTime);
|
|
||||||
tc.settings.resetKeyCode = Number(storage.resetKeyCode);
|
|
||||||
tc.settings.rewindKeyCode = Number(storage.rewindKeyCode);
|
|
||||||
tc.settings.slowerKeyCode = Number(storage.slowerKeyCode);
|
|
||||||
tc.settings.fasterKeyCode = Number(storage.fasterKeyCode);
|
|
||||||
tc.settings.fastKeyCode = Number(storage.fastKeyCode);
|
|
||||||
tc.settings.displayKeyCode = Number(storage.displayKeyCode);
|
tc.settings.displayKeyCode = Number(storage.displayKeyCode);
|
||||||
tc.settings.advanceKeyCode = Number(storage.advanceKeyCode);
|
|
||||||
tc.settings.rememberSpeed = Boolean(storage.rememberSpeed);
|
tc.settings.rememberSpeed = Boolean(storage.rememberSpeed);
|
||||||
tc.settings.startHidden = Boolean(storage.startHidden);
|
tc.settings.startHidden = Boolean(storage.startHidden);
|
||||||
tc.settings.blacklist = String(storage.blacklist);
|
tc.settings.blacklist = String(storage.blacklist);
|
||||||
@@ -48,6 +105,18 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
|
|
||||||
var forEach = Array.prototype.forEach;
|
var forEach = Array.prototype.forEach;
|
||||||
|
|
||||||
|
function getKeyBindings(action, what = "value") {
|
||||||
|
try {
|
||||||
|
return tc.settings.keyBindings.find(item => item.action === action)[what];
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setKeyBindings(action, value) {
|
||||||
|
tc.settings.keyBindings.find(item => item.action === action)["value"] = value;
|
||||||
|
}
|
||||||
|
|
||||||
function defineVideoController() {
|
function defineVideoController() {
|
||||||
tc.videoController = function(target, parent) {
|
tc.videoController = function(target, parent) {
|
||||||
if (target.dataset['vscid']) {
|
if (target.dataset['vscid']) {
|
||||||
@@ -60,7 +129,7 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
this.id = Math.random().toString(36).substr(2, 9);
|
this.id = Math.random().toString(36).substr(2, 9);
|
||||||
if (!tc.settings.rememberSpeed) {
|
if (!tc.settings.rememberSpeed) {
|
||||||
tc.settings.speed = 1.0;
|
tc.settings.speed = 1.0;
|
||||||
tc.settings.resetSpeed = tc.settings.fastSpeed;
|
setKeyBindings("reset", getKeyBindings("fast")); // resetSpeed = fastSpeed
|
||||||
}
|
}
|
||||||
this.initializeControls();
|
this.initializeControls();
|
||||||
|
|
||||||
@@ -130,7 +199,7 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
|
|
||||||
forEach.call(shadow.querySelectorAll('button'), function(button) {
|
forEach.call(shadow.querySelectorAll('button'), function(button) {
|
||||||
button.onclick = (e) => {
|
button.onclick = (e) => {
|
||||||
runAction(e.target.dataset['action'], document, false, e);
|
runAction(e.target.dataset['action'], document, getKeyBindings(e.target.dataset['action']), e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -242,27 +311,22 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ignore keydown event if typing in an input box
|
// Ignore keydown event if typing in an input box
|
||||||
if ((document.activeElement.nodeName === 'INPUT'
|
if (document.activeElement.nodeName === 'INPUT'
|
||||||
&& document.activeElement.getAttribute('type') === 'text')
|
|
||||||
|| document.activeElement.nodeName === 'TEXTAREA'
|
|| document.activeElement.nodeName === 'TEXTAREA'
|
||||||
|| document.activeElement.isContentEditable) {
|
|| document.activeElement.isContentEditable) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyCode == tc.settings.rewindKeyCode) {
|
if (keyCode == tc.settings.displayKeyCode) {
|
||||||
runAction('rewind', document, true)
|
|
||||||
} else if (keyCode == tc.settings.advanceKeyCode) {
|
|
||||||
runAction('advance', document, true)
|
|
||||||
} else if (keyCode == tc.settings.fasterKeyCode) {
|
|
||||||
runAction('faster', document, true)
|
|
||||||
} else if (keyCode == tc.settings.slowerKeyCode) {
|
|
||||||
runAction('slower', document, true)
|
|
||||||
} else if (keyCode == tc.settings.resetKeyCode) {
|
|
||||||
runAction('reset', document, true)
|
|
||||||
} else if (keyCode == tc.settings.displayKeyCode) {
|
|
||||||
runAction('display', document, true)
|
runAction('display', document, true)
|
||||||
} else if (keyCode == tc.settings.fastKeyCode) {
|
}
|
||||||
runAction('fast', document, true);
|
var item = tc.settings.keyBindings.find(item => item.key === keyCode);
|
||||||
|
if (item) {
|
||||||
|
runAction(item.action, document, item.value);
|
||||||
|
if (item.force === "true") {// disable websites key bindings
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -324,7 +388,7 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function runAction(action, document, keyboard, e) {
|
function runAction(action, document, value, e) {
|
||||||
var videoTags = document.getElementsByTagName('video');
|
var videoTags = document.getElementsByTagName('video');
|
||||||
videoTags.forEach = Array.prototype.forEach;
|
videoTags.forEach = Array.prototype.forEach;
|
||||||
|
|
||||||
@@ -336,18 +400,18 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
|
|
||||||
if (!v.classList.contains('vsc-cancelled')) {
|
if (!v.classList.contains('vsc-cancelled')) {
|
||||||
if (action === 'rewind') {
|
if (action === 'rewind') {
|
||||||
v.currentTime -= tc.settings.rewindTime;
|
v.currentTime -= value;
|
||||||
} else if (action === 'advance') {
|
} else if (action === 'advance') {
|
||||||
v.currentTime += tc.settings.advanceTime;
|
v.currentTime += value;
|
||||||
} else if (action === 'faster') {
|
} else if (action === 'faster') {
|
||||||
// Maximum playback speed in Chrome is set to 16:
|
// Maximum playback speed in Chrome is set to 16:
|
||||||
// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp?l=168
|
// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp?l=168
|
||||||
var s = Math.min( (v.playbackRate < 0.1 ? 0.0 : v.playbackRate) + tc.settings.speedStep, 16);
|
var s = Math.min((v.playbackRate < 0.1 ? 0.0 : v.playbackRate) + value, 16);
|
||||||
v.playbackRate = Number(s.toFixed(2));
|
v.playbackRate = Number(s.toFixed(2));
|
||||||
} else if (action === 'slower') {
|
} else if (action === 'slower') {
|
||||||
// Video min rate is 0.0625:
|
// Video min rate is 0.0625:
|
||||||
// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp?l=167
|
// https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp?l=167
|
||||||
var s = Math.max(v.playbackRate - tc.settings.speedStep, 0.07);
|
var s = Math.max(v.playbackRate - value, 0.07);
|
||||||
v.playbackRate = Number(s.toFixed(2));
|
v.playbackRate = Number(s.toFixed(2));
|
||||||
} else if (action === 'reset') {
|
} else if (action === 'reset') {
|
||||||
resetSpeed(v, 1.0);
|
resetSpeed(v, 1.0);
|
||||||
@@ -357,33 +421,61 @@ chrome.runtime.sendMessage({}, function(response) {
|
|||||||
} else if (action === 'drag') {
|
} else if (action === 'drag') {
|
||||||
handleDrag(v, controller, e);
|
handleDrag(v, controller, e);
|
||||||
} else if (action === 'fast') {
|
} else if (action === 'fast') {
|
||||||
resetSpeed(v, tc.settings.fastSpeed);
|
resetSpeed(v, value);
|
||||||
|
} else if (action === 'pause') {
|
||||||
|
pauseSpeed(v, value);
|
||||||
|
} else if (action === 'muted') {
|
||||||
|
muted(v, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pauseSpeed(v, target) {
|
||||||
|
// not working as expected in youtube for now
|
||||||
|
if (v.playbackRate === target) {
|
||||||
|
v.play()
|
||||||
|
}
|
||||||
|
resetSpeed(v, target)
|
||||||
|
}
|
||||||
|
|
||||||
function resetSpeed(v, target) {
|
function resetSpeed(v, target) {
|
||||||
if (v.playbackRate === target) {
|
if (v.playbackRate === target) {
|
||||||
if(v.playbackRate === tc.settings.resetSpeed)
|
if (v.playbackRate === getKeyBindings("reset")) { // resetSpeed
|
||||||
{
|
|
||||||
if (target !== 1.0) {
|
if (target !== 1.0) {
|
||||||
v.playbackRate = 1.0;
|
v.playbackRate = 1.0;
|
||||||
} else {
|
} else {
|
||||||
v.playbackRate = tc.settings.fastSpeed;
|
v.playbackRate = getKeyBindings("fast"); // fastSpeed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v.playbackRate = tc.settings.resetSpeed;
|
v.playbackRate = getKeyBindings("reset"); // resetSpeed
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tc.settings.resetSpeed = v.playbackRate;
|
setKeyBindings("reset", v.playbackRate);// resetSpeed
|
||||||
chrome.storage.sync.set({'resetSpeed': v.playbackRate});
|
// chrome.storage.sync.set({'resetSpeed': v.playbackRate});
|
||||||
v.playbackRate = target;
|
v.playbackRate = target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function muted(v, value) {
|
||||||
|
v.muted = v.muted !== true; //reverse muted status
|
||||||
|
/* this can be used if someone wants just mute button
|
||||||
|
switch (value) {
|
||||||
|
case 2:
|
||||||
|
v.muted = false;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
v.muted = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
v.muted = v.muted !== true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
function handleDrag(video, controller, e) {
|
function handleDrag(video, controller, e) {
|
||||||
const shadowController = controller.shadowRoot.querySelector('#controller');
|
const shadowController = controller.shadowRoot.querySelector('#controller');
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Video Speed Controller",
|
"name": "Video Speed Controller",
|
||||||
"short_name": "videospeed",
|
"short_name": "videospeed",
|
||||||
"version": "0.5.2",
|
"version": "0.5.3",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"description": "Speed up, slow down, advance and rewind any HTML5 video with quick shortcuts.",
|
"description": "Speed up, slow down, advance and rewind any HTML5 video with quick shortcuts.",
|
||||||
"homepage_url": "https://github.com/igrigorik/videospeed",
|
"homepage_url": "https://github.com/igrigorik/videospeed",
|
||||||
|
12
options.css
12
options.css
@@ -84,10 +84,6 @@ label {
|
|||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
label[for=rememberSpeed] {
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#status {
|
#status {
|
||||||
color: #9D9D9D;
|
color: #9D9D9D;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -97,3 +93,11 @@ label[for=rememberSpeed] {
|
|||||||
#faq {
|
#faq {
|
||||||
margin-top: 2em;
|
margin-top: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
width: 170px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.customForce {
|
||||||
|
display: none;
|
||||||
|
}
|
109
options.html
109
options.html
@@ -10,59 +10,81 @@
|
|||||||
<h1>Video Speed Controller</h1>
|
<h1>Video Speed Controller</h1>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section>
|
<section id="customs">
|
||||||
<h3>Shortcuts</h3>
|
<h3>Shortcuts</h3>
|
||||||
<div class="row">
|
|
||||||
<label for="rewindKeyInput">Rewind</label>
|
|
||||||
<input id="rewindKeyInput" placeholder="press a key" type="text" value=""/>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<label for="advanceKeyInput">Advance</label>
|
|
||||||
<input id="advanceKeyInput" placeholder="press a key" type="text" value=""/>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<label for="resetKeyInput">Reset speed</label>
|
|
||||||
<input id="resetKeyInput" placeholder="press a key" type="text" value=""/>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<label for="slowerKeyInput">Decrease speed</label>
|
|
||||||
<input id="slowerKeyInput" placeholder="press a key" type="text" value=""/>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<label for="fasterKeyInput">Increase speed</label>
|
|
||||||
<input id="fasterKeyInput" placeholder="press a key" type="text" value=""/>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<label for="fastKeyInput">Preferred speed</label>
|
|
||||||
<input id="fastKeyInput" placeholder="press a key" type="text" value=""/>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label for="displayKeyInput">Show/hide controller</label>
|
<label for="displayKeyInput">Show/hide controller</label>
|
||||||
<input id="displayKeyInput" placeholder="press a key" type="text" value=""/>
|
<input id="displayKeyInput" placeholder="press a key" type="text" value=""/>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row customs" id="slower">
|
||||||
<label for="startHidden">Hide controller by default</label>
|
<select class="customDo">
|
||||||
<input id="startHidden" type="checkbox"/>
|
<option value="slower">Decrease speed</option>
|
||||||
</div>
|
</select>
|
||||||
|
<input class="customKey" type="text" value="" placeholder="press a key">
|
||||||
|
<input class="customValue" type="text" placeholder="value (0.10)">
|
||||||
|
<select class="customForce">
|
||||||
|
<option value="false">Do not disable website key bindings</option>
|
||||||
|
<option value="true">Disable websites key bindings</option>
|
||||||
|
</select></div>
|
||||||
|
<div class="row customs" id="faster">
|
||||||
|
<select class="customDo">
|
||||||
|
<option value="faster">Increase speed</option>
|
||||||
|
</select>
|
||||||
|
<input class="customKey" type="text" value="" placeholder="press a key">
|
||||||
|
<input class="customValue" type="text" placeholder="value (0.10)">
|
||||||
|
<select class="customForce">
|
||||||
|
<option value="false">Do not disable website key bindings</option>
|
||||||
|
<option value="true">Disable websites key bindings</option>
|
||||||
|
</select></div>
|
||||||
|
<div class="row customs" id="rewind">
|
||||||
|
<select class="customDo">
|
||||||
|
<option value="rewind">Rewind</option>
|
||||||
|
</select>
|
||||||
|
<input class="customKey" type="text" value="" placeholder="press a key">
|
||||||
|
<input class="customValue" type="text" placeholder="value (10)">
|
||||||
|
<select class="customForce">
|
||||||
|
<option value="false">Do not disable website key bindings</option>
|
||||||
|
<option value="true">Disable websites key bindings</option>
|
||||||
|
</select></div>
|
||||||
|
<div class="row customs" id="advance">
|
||||||
|
<select class="customDo">
|
||||||
|
<option value="advance">Advance</option>
|
||||||
|
</select>
|
||||||
|
<input class="customKey" type="text" value="" placeholder="press a key">
|
||||||
|
<input class="customValue" type="text" placeholder="value (10)">
|
||||||
|
<select class="customForce">
|
||||||
|
<option value="false">Do not disable website key bindings</option>
|
||||||
|
<option value="true">Disable websites key bindings</option>
|
||||||
|
</select></div>
|
||||||
|
<div class="row customs" id="reset">
|
||||||
|
<select class="customDo">
|
||||||
|
<option value="reset">Reset speed</option>
|
||||||
|
</select>
|
||||||
|
<input class="customKey" type="text" value="" placeholder="press a key">
|
||||||
|
<input class="customValue" type="text" placeholder="value (1.00)" disabled>
|
||||||
|
<select class="customForce">
|
||||||
|
<option value="false">Do not disable website key bindings</option>
|
||||||
|
<option value="true">Disable websites key bindings</option>
|
||||||
|
</select></div>
|
||||||
|
<div class="row customs" id="fast">
|
||||||
|
<select class="customDo">
|
||||||
|
<option value="fast">Preferred speed</option>
|
||||||
|
</select>
|
||||||
|
<input class="customKey" type="text" value="" placeholder="press a key">
|
||||||
|
<input class="customValue" type="text" placeholder="value (1.80)">
|
||||||
|
<select class="customForce">
|
||||||
|
<option value="false">Do not disable website key bindings</option>
|
||||||
|
<option value="true">Disable websites key bindings</option>
|
||||||
|
</select></div>
|
||||||
|
|
||||||
|
<button id="add">Add New</button>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<h3>Other</h3>
|
<h3>Other</h3>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label for="rewindTime">Rewind Time (s)</label>
|
<label for="startHidden">Hide controller by default</label>
|
||||||
<input id="rewindTime" type="text" value=""/>
|
<input id="startHidden" type="checkbox"/>
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<label for="advanceTime">Advance Time (s)</label>
|
|
||||||
<input id="advanceTime" type="text" value=""/>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<label for="speedStep">Speed Change Step</label>
|
|
||||||
<input id="speedStep" type="text" value=""/>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<label for="fastSpeed">Preferred Speed (x)</label>
|
|
||||||
<input id="fastSpeed" type="text" value=""/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label for="rememberSpeed">Remember Playback Speed</label>
|
<label for="rememberSpeed">Remember Playback Speed</label>
|
||||||
@@ -76,6 +98,7 @@
|
|||||||
|
|
||||||
<button id="save">Save</button>
|
<button id="save">Save</button>
|
||||||
<button id="restore">Restore Defaults</button>
|
<button id="restore">Restore Defaults</button>
|
||||||
|
<button id="experimental">Show experimental features</button>
|
||||||
|
|
||||||
<div id="status"></div>
|
<div id="status"></div>
|
||||||
|
|
||||||
|
192
options.js
192
options.js
@@ -1,27 +1,30 @@
|
|||||||
var tcDefaults = {
|
var tcDefaults = {
|
||||||
speed: 1.0, // default 1x
|
speed: 1.0, // default:
|
||||||
speedStep: 0.1, // default 0.1x
|
|
||||||
rewindTime: 10, // default 10s
|
|
||||||
advanceTime: 10, // default 10s
|
|
||||||
fastSpeed: 1.8, // default 1.8x
|
|
||||||
resetKeyCode: 82, // default: R
|
|
||||||
slowerKeyCode: 83, // default: S
|
|
||||||
fasterKeyCode: 68, // default: D
|
|
||||||
fastKeyCode: 71, // default: G
|
|
||||||
rewindKeyCode: 90, // default: Z
|
|
||||||
advanceKeyCode: 88, // default: X
|
|
||||||
displayKeyCode: 86, // default: V
|
displayKeyCode: 86, // default: V
|
||||||
rememberSpeed: false, // default: false
|
rememberSpeed: false, // default: false
|
||||||
startHidden: false, // default: false
|
startHidden: false, // default: false
|
||||||
|
keyBindings: [
|
||||||
|
{action: "slower", key: 83, value: 0.1, force: false, predefined: true}, // S
|
||||||
|
{action: "faster", key: 68, value: 0.1, force: false, predefined: true}, // D
|
||||||
|
{action: "rewind", key: 90, value: 10, force: false, predefined: true}, // Z
|
||||||
|
{action: "advance", key: 88, value: 10, force: false, predefined: true}, // X
|
||||||
|
{action: "reset", key: 82, value: 1, force: false, predefined: true}, // R
|
||||||
|
{action: "fast", key: 71, value: 1.8, force: false, predefined: true} // G
|
||||||
|
],
|
||||||
blacklist: `
|
blacklist: `
|
||||||
www.instagram.com
|
www.instagram.com
|
||||||
twitter.com
|
twitter.com
|
||||||
vine.co
|
vine.co
|
||||||
imgur.com
|
imgur.com
|
||||||
`.replace(/^\s+|\s+$/gm,'')
|
`.replace(/^\s+|\s+$/gm, '')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var keyBindings = [];
|
||||||
|
|
||||||
var keyCodeAliases = {
|
var keyCodeAliases = {
|
||||||
|
0: 'null',
|
||||||
|
null: 'null',
|
||||||
|
undefined: 'null',
|
||||||
32: 'Space',
|
32: 'Space',
|
||||||
96: 'Num 0',
|
96: 'Num 0',
|
||||||
97: 'Num 1',
|
97: 'Num 1',
|
||||||
@@ -64,6 +67,9 @@ function recordKeyPress(e) {
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
} else if (e.keyCode === 8) { // Clear input when backspace pressed
|
} else if (e.keyCode === 8) { // Clear input when backspace pressed
|
||||||
e.target.value = '';
|
e.target.value = '';
|
||||||
|
} else if (e.keyCode === 27) { // When esc clicked, clear input
|
||||||
|
e.target.value = 'null';
|
||||||
|
e.target.keyCode = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -88,50 +94,64 @@ function updateShortcutInputText(inputId, keyCode) {
|
|||||||
document.getElementById(inputId).keyCode = keyCode;
|
document.getElementById(inputId).keyCode = keyCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateCustomShortcutInputText(inputItem, keyCode) {
|
||||||
|
inputItem.value = keyCodeAliases[keyCode] || String.fromCharCode(keyCode);
|
||||||
|
inputItem.keyCode = keyCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_shortcut() {
|
||||||
|
var html = `<select class="customDo">
|
||||||
|
<option value="slower">Decrease speed</option>
|
||||||
|
<option value="faster">Increase speed</option>
|
||||||
|
<option value="rewind">Rewind</option>
|
||||||
|
<option value="advance">Advance</option>
|
||||||
|
<option value="reset">Reset speed</option>
|
||||||
|
<option value="fast">Preferred speed</option>
|
||||||
|
<option value="muted">Mute</option>
|
||||||
|
<option value="pause">Pause</option>
|
||||||
|
</select>
|
||||||
|
<input class="customKey" type="text" placeholder="press a key"/>
|
||||||
|
<input class="customValue" type="text" placeholder="value (0.10)"/>
|
||||||
|
<select class="customForce">
|
||||||
|
<option value="false">Do not disable website key bindings</option>
|
||||||
|
<option value="true">Disable websites key bindings</option>
|
||||||
|
</select>
|
||||||
|
<button class="removeParent">X</button>`;
|
||||||
|
var div = document.createElement('div');
|
||||||
|
div.setAttribute('class', 'row customs');
|
||||||
|
div.innerHTML = html;
|
||||||
|
var customs_element = document.getElementById("customs");
|
||||||
|
customs_element.insertBefore(div, customs_element.children[customs_element.childElementCount - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function createKeyBindings(item) {
|
||||||
|
const action = item.querySelector(".customDo").value;
|
||||||
|
const key = item.querySelector(".customKey").keyCode;
|
||||||
|
const value = Number(item.querySelector(".customValue").value);
|
||||||
|
const force = item.querySelector(".customForce").value;
|
||||||
|
const predefined = !!item.id;//item.id ? true : false;
|
||||||
|
|
||||||
|
keyBindings.push({action: action, key: key, value: value, force: force, predefined: predefined});
|
||||||
|
}
|
||||||
|
|
||||||
// Saves options to chrome.storage
|
// Saves options to chrome.storage
|
||||||
function save_options() {
|
function save_options() {
|
||||||
|
keyBindings = [];
|
||||||
|
Array.from(document.querySelectorAll(".customs")).forEach(item => createKeyBindings(item)); // Remove added shortcuts
|
||||||
|
|
||||||
var speedStep = document.getElementById('speedStep').value;
|
|
||||||
var rewindTime = document.getElementById('rewindTime').value;
|
|
||||||
var advanceTime = document.getElementById('advanceTime').value;
|
|
||||||
var fastSpeed = document.getElementById('fastSpeed').value;
|
|
||||||
var resetKeyCode = document.getElementById('resetKeyInput').keyCode;
|
|
||||||
var rewindKeyCode = document.getElementById('rewindKeyInput').keyCode;
|
|
||||||
var advanceKeyCode = document.getElementById('advanceKeyInput').keyCode;
|
|
||||||
var slowerKeyCode = document.getElementById('slowerKeyInput').keyCode;
|
|
||||||
var fasterKeyCode = document.getElementById('fasterKeyInput').keyCode;
|
|
||||||
var fastKeyCode = document.getElementById('fastKeyInput').keyCode;
|
|
||||||
var displayKeyCode = document.getElementById('displayKeyInput').keyCode;
|
var displayKeyCode = document.getElementById('displayKeyInput').keyCode;
|
||||||
var rememberSpeed = document.getElementById('rememberSpeed').checked;
|
var rememberSpeed = document.getElementById('rememberSpeed').checked;
|
||||||
var startHidden = document.getElementById('startHidden').checked;
|
var startHidden = document.getElementById('startHidden').checked;
|
||||||
var blacklist = document.getElementById('blacklist').value;
|
var blacklist = document.getElementById('blacklist').value;
|
||||||
|
|
||||||
speedStep = isNaN(speedStep) ? tcDefaults.speedStep : Number(speedStep);
|
|
||||||
rewindTime = isNaN(rewindTime) ? tcDefaults.rewindTime : Number(rewindTime);
|
|
||||||
advanceTime = isNaN(advanceTime) ? tcDefaults.advanceTime : Number(advanceTime);
|
|
||||||
fastSpeed = isNaN(fastSpeed) ? tcDefaults.fastSpeed : Number(fastSpeed);
|
|
||||||
resetKeyCode = isNaN(resetKeyCode) ? tcDefaults.resetKeyCode : resetKeyCode;
|
|
||||||
rewindKeyCode = isNaN(rewindKeyCode) ? tcDefaults.rewindKeyCode : rewindKeyCode;
|
|
||||||
advanceKeyCode = isNaN(advanceKeyCode) ? tcDefaults.advanceKeyCode : advanceKeyCode;
|
|
||||||
slowerKeyCode = isNaN(slowerKeyCode) ? tcDefaults.slowerKeyCode : slowerKeyCode;
|
|
||||||
fasterKeyCode = isNaN(fasterKeyCode) ? tcDefaults.fasterKeyCode : fasterKeyCode;
|
|
||||||
fastKeyCode = isNaN(fastKeyCode) ? tcDefaults.fastKeyCode : fastKeyCode;
|
|
||||||
displayKeyCode = isNaN(displayKeyCode) ? tcDefaults.displayKeyCode : displayKeyCode;
|
displayKeyCode = isNaN(displayKeyCode) ? tcDefaults.displayKeyCode : displayKeyCode;
|
||||||
|
|
||||||
|
chrome.storage.sync.remove(["resetSpeed", "speedStep", "fastSpeed", "rewindTime", "advanceTime", "resetKeyCode", "slowerKeyCode", "fasterKeyCode", "rewindKeyCode", "advanceKeyCode", "fastKeyCode"]);
|
||||||
chrome.storage.sync.set({
|
chrome.storage.sync.set({
|
||||||
speedStep: speedStep,
|
|
||||||
rewindTime: rewindTime,
|
|
||||||
advanceTime: advanceTime,
|
|
||||||
fastSpeed: fastSpeed,
|
|
||||||
resetKeyCode: resetKeyCode,
|
|
||||||
rewindKeyCode: rewindKeyCode,
|
|
||||||
advanceKeyCode: advanceKeyCode,
|
|
||||||
slowerKeyCode: slowerKeyCode,
|
|
||||||
fasterKeyCode: fasterKeyCode,
|
|
||||||
fastKeyCode: fastKeyCode,
|
|
||||||
displayKeyCode: displayKeyCode,
|
displayKeyCode: displayKeyCode,
|
||||||
rememberSpeed: rememberSpeed,
|
rememberSpeed: rememberSpeed,
|
||||||
startHidden: startHidden,
|
startHidden: startHidden,
|
||||||
|
keyBindings: keyBindings,
|
||||||
blacklist: blacklist.replace(/^\s+|\s+$/gm,'')
|
blacklist: blacklist.replace(/^\s+|\s+$/gm,'')
|
||||||
}, function() {
|
}, function() {
|
||||||
// Update status to let user know options were saved.
|
// Update status to let user know options were saved.
|
||||||
@@ -146,26 +166,41 @@ function save_options() {
|
|||||||
// Restores options from chrome.storage
|
// Restores options from chrome.storage
|
||||||
function restore_options() {
|
function restore_options() {
|
||||||
chrome.storage.sync.get(tcDefaults, function(storage) {
|
chrome.storage.sync.get(tcDefaults, function(storage) {
|
||||||
document.getElementById('speedStep').value = storage.speedStep.toFixed(2);
|
|
||||||
document.getElementById('rewindTime').value = storage.rewindTime;
|
|
||||||
document.getElementById('advanceTime').value = storage.advanceTime;
|
|
||||||
document.getElementById('fastSpeed').value = storage.fastSpeed;
|
|
||||||
updateShortcutInputText('resetKeyInput', storage.resetKeyCode);
|
|
||||||
updateShortcutInputText('rewindKeyInput', storage.rewindKeyCode);
|
|
||||||
updateShortcutInputText('advanceKeyInput', storage.advanceKeyCode);
|
|
||||||
updateShortcutInputText('slowerKeyInput', storage.slowerKeyCode);
|
|
||||||
updateShortcutInputText('fasterKeyInput', storage.fasterKeyCode);
|
|
||||||
updateShortcutInputText('fastKeyInput', storage.fastKeyCode);
|
|
||||||
updateShortcutInputText('displayKeyInput', storage.displayKeyCode);
|
updateShortcutInputText('displayKeyInput', storage.displayKeyCode);
|
||||||
document.getElementById('rememberSpeed').checked = storage.rememberSpeed;
|
document.getElementById('rememberSpeed').checked = storage.rememberSpeed;
|
||||||
document.getElementById('startHidden').checked = storage.startHidden;
|
document.getElementById('startHidden').checked = storage.startHidden;
|
||||||
document.getElementById('blacklist').value = storage.blacklist;
|
document.getElementById('blacklist').value = storage.blacklist;
|
||||||
|
|
||||||
|
for (let i in storage.keyBindings) {
|
||||||
|
var item = storage.keyBindings[i];
|
||||||
|
if (item.predefined) {
|
||||||
|
//do predefined ones because their value needed for overlay
|
||||||
|
// document.querySelector("#" + item["action"] + " .customDo").value = item["action"];
|
||||||
|
updateCustomShortcutInputText(document.querySelector("#" + item["action"] + " .customKey"), item["key"]);
|
||||||
|
document.querySelector("#" + item["action"] + " .customValue").value = item["value"];
|
||||||
|
document.querySelector("#" + item["action"] + " .customForce").value = item["force"];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// new ones
|
||||||
|
add_shortcut();
|
||||||
|
const dom = document.querySelector(".customs:last-of-type")
|
||||||
|
dom.querySelector(".customDo").value = item["action"];
|
||||||
|
|
||||||
|
if (item["action"] === "pause" || item["action"] === "muted")
|
||||||
|
dom.querySelector(".customValue").disabled = true;
|
||||||
|
|
||||||
|
updateCustomShortcutInputText(dom.querySelector(".customKey"), item["key"]);
|
||||||
|
dom.querySelector(".customValue").value = item["value"];
|
||||||
|
dom.querySelector(".customForce").value = item["force"];
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function restore_defaults() {
|
function restore_defaults() {
|
||||||
chrome.storage.sync.set(tcDefaults, function() {
|
chrome.storage.sync.set(tcDefaults, function() {
|
||||||
restore_options();
|
restore_options();
|
||||||
|
document.querySelectorAll(".removeParent").forEach(button => button.click()); // Remove added shortcuts
|
||||||
// Update status to let user know options were saved.
|
// Update status to let user know options were saved.
|
||||||
var status = document.getElementById('status');
|
var status = document.getElementById('status');
|
||||||
status.textContent = 'Default options restored';
|
status.textContent = 'Default options restored';
|
||||||
@@ -175,6 +210,10 @@ function restore_defaults() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function show_experimental() {
|
||||||
|
document.querySelectorAll(".customForce").forEach(item => item.style.display = 'inline-block');
|
||||||
|
}
|
||||||
|
|
||||||
function initShortcutInput(inputId) {
|
function initShortcutInput(inputId) {
|
||||||
document.getElementById(inputId).addEventListener('focus', inputFocus);
|
document.getElementById(inputId).addEventListener('focus', inputFocus);
|
||||||
document.getElementById(inputId).addEventListener('blur', inputBlur);
|
document.getElementById(inputId).addEventListener('blur', inputBlur);
|
||||||
@@ -185,18 +224,47 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||||||
restore_options();
|
restore_options();
|
||||||
|
|
||||||
document.getElementById('save').addEventListener('click', save_options);
|
document.getElementById('save').addEventListener('click', save_options);
|
||||||
|
document.getElementById('add').addEventListener('click', add_shortcut);
|
||||||
document.getElementById('restore').addEventListener('click', restore_defaults);
|
document.getElementById('restore').addEventListener('click', restore_defaults);
|
||||||
|
document.getElementById('experimental').addEventListener('click', show_experimental);
|
||||||
|
|
||||||
initShortcutInput('resetKeyInput');
|
|
||||||
initShortcutInput('rewindKeyInput');
|
|
||||||
initShortcutInput('advanceKeyInput');
|
|
||||||
initShortcutInput('slowerKeyInput');
|
|
||||||
initShortcutInput('fasterKeyInput');
|
|
||||||
initShortcutInput('fastKeyInput');
|
|
||||||
initShortcutInput('displayKeyInput');
|
initShortcutInput('displayKeyInput');
|
||||||
|
|
||||||
document.getElementById('rewindTime').addEventListener('keypress', inputFilterNumbersOnly);
|
function eventCaller(event, className, funcName) {
|
||||||
document.getElementById('advanceTime').addEventListener('keypress', inputFilterNumbersOnly);
|
if (!event.target.classList.contains(className)) {
|
||||||
document.getElementById('speedStep').addEventListener('keypress', inputFilterNumbersOnly);
|
return
|
||||||
document.getElementById('fastSpeed').addEventListener('keypress', inputFilterNumbersOnly);
|
}
|
||||||
|
funcName(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('keypress', (event) => {
|
||||||
|
eventCaller(event, "customValue", inputFilterNumbersOnly)
|
||||||
|
});
|
||||||
|
document.addEventListener('focus', (event) => {
|
||||||
|
eventCaller(event, "customKey", inputFocus)
|
||||||
|
});
|
||||||
|
document.addEventListener('blur', (event) => {
|
||||||
|
eventCaller(event, "customKey", inputBlur)
|
||||||
|
});
|
||||||
|
document.addEventListener('keydown', (event) => {
|
||||||
|
eventCaller(event, "customKey", recordKeyPress)
|
||||||
|
});
|
||||||
|
document.addEventListener('click', (event) => {
|
||||||
|
eventCaller(event, "removeParent", function () {
|
||||||
|
event.target.parentNode.remove()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
document.addEventListener('change', (event) => {
|
||||||
|
eventCaller(event, "customDo", function () {
|
||||||
|
switch (event.target.value) {
|
||||||
|
case "muted":
|
||||||
|
case "pause":
|
||||||
|
event.target.nextElementSibling.nextElementSibling.disabled = true;
|
||||||
|
event.target.nextElementSibling.nextElementSibling.value = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
event.target.nextElementSibling.nextElementSibling.disabled = false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user