Feature/578 prettier.io formatting (#585)

* Reformatted codebase using prettier.io (should not change functional behavior)
* Formatted README.md, added CONTRIBUTING.md, .prettierrc configuration file, and installed pre-commit hook
This commit is contained in:
Chad Bailey
2020-02-08 16:26:10 -06:00
committed by GitHub
parent 4ac2e458f5
commit 55500fc010
14 changed files with 1295 additions and 956 deletions

15
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,15 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- repo: https://github.com/prettier/prettier
rev: 1.19.1 # Use the sha or tag you want to point at
hooks:
- id: prettier

8
.prettierrc Normal file
View File

@@ -0,0 +1,8 @@
{
"trailingComma": "none",
"tabWidth": 2,
"printWidth": 80,
"semi": true,
"endOfLine": "auto",
"proseWrap": "always"
}

85
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,85 @@
# Contributing
Video Speed Controller is an open source project licensed under the MIT license
with many contributers. Contributions are welcome, and greatly appreciated.
If you would like to help, getting started is easy.
## Get Started
1. You must have a github account and be logged in
2. Fork the repo by clicking the "Fork" link on the top-right corner of the page
3. Once the fork is ready, clone to your local PC
```sh
$ git clone https://github.com/<USERNAME>/videospeed.git
Cloning into 'videospeed'...
remote: Enumerating objects: 10, done.
remote: Counting objects: 100% (10/10), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 877 (delta 3), reused 2 (delta 1), pack-reused 867
Receiving objects: 100% (877/877), 317.65 KiB | 2.17 MiB/s, done.
Resolving deltas: 100% (543/543), done.
```
4. Create a branch for your changes
```sh
$ cd videospeed
videospeed$ git checkout -b bugfix/1-fix-double-click
M .github/workflows/chrome-store-upload.yaml
M README.md
M options.js
Switched to a new branch 'bugfix/1-fix-double-click'
videospeed$
```
5. Open the code in your favorite code editor, make your changes
```sh
echo "Awesome changes" > somefile.js
git add .
```
> Important: Your commit must be formatted using
> [prettier](https://prettier.io/). If it is not it may be autoformatted for
> you or your pull request may be rejected.
6. Next, open Chrome/Brave/Chromium and enable developer mode via
`Settings > Extensions > Manage Extensions` and toggle `Developer mode` in
the top-right corner.
7. Click `Load unpacked` and browse to the folder you cloned videospeed to.
8. Try out your changes, make sure they work as expected
9. Commit and push your changes to github
```sh
git commit -m "Awesome description of some awesome changes."
git push
```
10. Open your branch up on the github website then click `New pull request` and
write up a description of your changes.
## Optional
### Run Pre-Commit Checks Locally
Installing [pre-commit](https://pre-commit.com/) is easy to do (click the link
for instructions on your platform). This repo comes with pre-commit already
configured. Doing this will ensure that your project is properly formatted and
runs some very basic tests. Once you have pre-commit installed on your system,
simply enter `pre-commit install` in your terminal in the folder to have these
checks run automatically each time you commit.
Even better, after issueing the install command you can now manually run
pre-commit checks before committing via `pre-commit run --all-files`
### Pull Upstream Changes
You should always be working with the latest version of the tool to make pull
requests easy. If you want to do this easily, just add a second remote to your
local git repo like this
`git push --set-upstream origin feature/578-prettier.io-formatting`
Now any time you like to pull the latest version in to your local branch you can
simply issue the command `git pull upstream master`

View File

@@ -2,48 +2,86 @@
**TL;DR: faster playback translates to better engagement and retention.** **TL;DR: faster playback translates to better engagement and retention.**
Average adult reads prose text at [250 to 300 words per minute](http://www.paperbecause.com/PIOP/files/f7/f7bb6bc5-2c4a-466f-9ae7-b483a2c0dca4.pdf) (wpm). By contrast, the average rate of speech for English speakers is ~150 wpm, with slide presentations often closer to 100 wpm. As a result, when given the choice, many viewers [speed up video playback to ~1.3\~1.5 its recorded rate](http://research.microsoft.com/en-us/um/redmond/groups/coet/compression/chi99/paper.pdf) to compensate for the difference. Average adult reads prose text at
[250 to 300 words per minute](http://www.paperbecause.com/PIOP/files/f7/f7bb6bc5-2c4a-466f-9ae7-b483a2c0dca4.pdf)
Many viewers report that [accelerated viewing keeps their attention longer](http://www.enounce.com/docs/BYUPaper020319.pdf): faster delivery keeps the viewer more engaged with the content. In fact, with a little training many end up watching videos at 2x+ the recorded speed. Some studies report that after being exposed to accelerated playback, [listeners become uncomfortable](http://alumni.media.mit.edu/~barons/html/avios92.html#beasleyalteredspeech) if they are forced to return to normal rate of presentation. (wpm). By contrast, the average rate of speech for English speakers is ~150 wpm,
with slide presentations often closer to 100 wpm. As a result, when given the
choice, many viewers
[speed up video playback to ~1.3\~1.5 its recorded rate](http://research.microsoft.com/en-us/um/redmond/groups/coet/compression/chi99/paper.pdf)
to compensate for the difference.
Many viewers report that
[accelerated viewing keeps their attention longer](http://www.enounce.com/docs/BYUPaper020319.pdf):
faster delivery keeps the viewer more engaged with the content. In fact, with a
little training many end up watching videos at 2x+ the recorded speed. Some
studies report that after being exposed to accelerated playback,
[listeners become uncomfortable](http://alumni.media.mit.edu/~barons/html/avios92.html#beasleyalteredspeech)
if they are forced to return to normal rate of presentation.
## Faster HTML5 Video ## Faster HTML5 Video
HTML5 video provides a native API to accelerate playback of any video. The problem is, many players either hide, or limit this functionality. For best results playback speed adjustments should be easy and frequent to match the pace and content being covered: we don't read at a fixed speed, and similarly, we need an easy way to accelerate the video, slow it down, and quickly rewind the last point to listen to it a few more times. HTML5 video provides a native API to accelerate playback of any video. The
problem is, many players either hide, or limit this functionality. For best
results playback speed adjustments should be easy and frequent to match the pace
and content being covered: we don't read at a fixed speed, and similarly, we
need an easy way to accelerate the video, slow it down, and quickly rewind the
last point to listen to it a few more times.
![Player](https://cloud.githubusercontent.com/assets/2400185/24076745/5723e6ae-0c41-11e7-820c-1d8e814a2888.png) ![Player](https://cloud.githubusercontent.com/assets/2400185/24076745/5723e6ae-0c41-11e7-820c-1d8e814a2888.png)
#### *[Install Chrome Extension](https://chrome.google.com/webstore/detail/video-speed-controller/nffaoalbilbmmfgbnbgppjihopabppdk)* ### _[Install Chrome Extension](https://chrome.google.com/webstore/detail/video-speed-controller/nffaoalbilbmmfgbnbgppjihopabppdk)_
Once the extension is installed simply navigate to any page that offers HTML5 video ([example](http://www.youtube.com/watch?v=E9FxNzv1Tr8)), and you'll see a speed indicator in top left corner. Hover over the indicator to reveal the controls to accelerate, slowdown, and quickly rewind or advance the video. Or, even better, simply use your keyboard: \*\* Once the extension is installed simply navigate to any page that offers
HTML5 video ([example](http://www.youtube.com/watch?v=E9FxNzv1Tr8)), and you'll
see a speed indicator in top left corner. Hover over the indicator to reveal the
controls to accelerate, slowdown, and quickly rewind or advance the video. Or,
even better, simply use your keyboard:
* **S** - decrease playback speed. - **S** - decrease playback speed.
* **D** - increase playback speed. - **D** - increase playback speed.
* **R** - reset playback speed to 1.0x. - **R** - reset playback speed to 1.0x.
* **Z** - rewind video by 10 seconds. - **Z** - rewind video by 10 seconds.
* **X** - advance video by 10 seconds. - **X** - advance video by 10 seconds.
* **G** - toggle between current and user configurable preferred speed. - **G** - toggle between current and user configurable preferred speed.
* **V** - show/hide the controller. - **V** - show/hide the controller.
You can customize and reassign the default shortcut keys in the extensions settings page, as well as add additional shortcut keys to match your preferences. For example, you can assign multiple different "preferred speed" shortcuts with different values, which will allow you to quickly toggle between your most commonly used speeds. To add a new shortcut, open extension settings and click "Add New". You can customize and reassign the default shortcut keys in the extensions
settings page, as well as add additional shortcut keys to match your
preferences. For example, you can assign multiple different "preferred speed"
shortcuts with different values, which will allow you to quickly toggle between
your most commonly used speeds. To add a new shortcut, open extension settings
and click "Add New".
![settings Add New shortcut](https://user-images.githubusercontent.com/121805/50726471-50242200-1172-11e9-902f-0e5958387617.jpg) ![settings Add New shortcut](https://user-images.githubusercontent.com/121805/50726471-50242200-1172-11e9-902f-0e5958387617.jpg)
Some sites may assign other functionality to one of the assigned shortcut keys — these collisions are inevitable, unfortunately. As a workaround, the extension listens both for lower and upper case values (i.e. you can use `Shift-<shortcut>`) if there is other functionality assigned to the lowercase key. This is not a perfect solution, as some sites may listen to both, but works most of the time. Some sites may assign other functionality to one of the assigned shortcut keys —
these collisions are inevitable, unfortunately. As a workaround, the extension
listens both for lower and upper case values (i.e. you can use
`Shift-<shortcut>`) if there is other functionality assigned to the lowercase
key. This is not a perfect solution, as some sites may listen to both, but works
most of the time.
### FAQ ### FAQ
**The video controls are not showing up?** This extension is only compatible with HTML5 video. If you don't see the controls showing up, chances are you are viewing a Flash video. If you want to confirm, try right-clicking on the video and inspect the menu: if it mentions flash, then that's the issue. That said, most sites will fallback to HTML5 if they detect that Flash it not available. You can try manually disabling Flash plugin in Chrome: **The video controls are not showing up?** This extension is only compatible
with HTML5 video. If you don't see the controls showing up, chances are you are
viewing a Flash video. If you want to confirm, try right-clicking on the video
and inspect the menu: if it mentions flash, then that's the issue. That said,
most sites will fallback to HTML5 if they detect that Flash it not available.
You can try manually disabling Flash plugin in Chrome:
* In a new tab, navigate to `chrome://settings/content/flash` - In a new tab, navigate to `chrome://settings/content/flash`
* Disable "Allow sites to run Flash" - Disable "Allow sites to run Flash"
* Restart your browser and try playing your video again - Restart your browser and try playing your video again
**The speed controls are not showing up for local videos?** To enable playback of local media (e.g. File > Open File), you need to grant additional permissions to the extension. **The speed controls are not showing up for local videos?** To enable playback
of local media (e.g. File > Open File), you need to grant additional permissions
to the extension.
* In a new tab, navigate to `chrome://extensions` - In a new tab, navigate to `chrome://extensions`
* Find "Video Speed Controller" extension in the list and enable "Allow access to file URLs" - Find "Video Speed Controller" extension in the list and enable "Allow access
* Open a new tab and try opening a local file, the controls should show up to file URLs"
- Open a new tab and try opening a local file, the controls should show up
### License ### License

View File

@@ -1,8 +1,12 @@
.vsc-nosource { display: none !important; } .vsc-nosource {
.vsc-hidden { display: none !important; } display: none !important;
}
.vsc-hidden {
display: none !important;
}
.vsc-manual { .vsc-manual {
visibility: visible !important; visibility: visible !important;
opacity: 1.0 !important; opacity: 1 !important;
} }
/* Origin specific overrides */ /* Origin specific overrides */
@@ -14,13 +18,13 @@
.ytp-autohide .vsc-controller { .ytp-autohide .vsc-controller {
visibility: hidden; visibility: hidden;
transition: opacity .25s cubic-bezier(0.4,0,0.2,1); transition: opacity 0.25s cubic-bezier(0.4, 0, 0.2, 1);
opacity: 0; opacity: 0;
} }
.ytp-autohide .vcs-show { .ytp-autohide .vcs-show {
visibility: visible; visibility: visible;
opacity: 1.0; opacity: 1;
} }
/* YouTube embedded player */ /* YouTube embedded player */
@@ -32,8 +36,8 @@
/* Facebook player */ /* Facebook player */
#facebook .vsc-controller { #facebook .vsc-controller {
position: relative; position: relative;
top: 40px; top: 40px;
} }
/* Google Photos player */ /* Google Photos player */
@@ -76,7 +80,8 @@ div.video-wrapper + div.target {
} }
/* Fix black overlay on Kickstarter */ /* Fix black overlay on Kickstarter */
div.video-player.has_played.vertically_center:before, div.legacy-video-player.has_played.vertically_center:before { div.video-player.has_played.vertically_center:before,
div.legacy-video-player.has_played.vertically_center:before {
content: none !important; content: none !important;
} }

1188
inject.js

File diff suppressed because it is too large Load Diff

View File

@@ -10,7 +10,7 @@
"48": "icons/icon48.png", "48": "icons/icon48.png",
"128": "icons/icon128.png" "128": "icons/icon128.png"
}, },
"permissions": [ "activeTab", "storage" ], "permissions": ["activeTab", "storage"],
"options_page": "options.html", "options_page": "options.html",
"browser_action": { "browser_action": {
"default_icon": { "default_icon": {
@@ -20,9 +20,10 @@
}, },
"default_popup": "popup.html" "default_popup": "popup.html"
}, },
"content_scripts": [{ "content_scripts": [
{
"all_frames": true, "all_frames": true,
"matches": [ "http://*/*", "https://*/*", "file:///*" ], "matches": ["http://*/*", "https://*/*", "file:///*"],
"match_about_blank": true, "match_about_blank": true,
"exclude_matches": [ "exclude_matches": [
"https://plus.google.com/hangouts/*", "https://plus.google.com/hangouts/*",
@@ -31,11 +32,9 @@
"https://teamtreehouse.com/*", "https://teamtreehouse.com/*",
"http://www.hitbox.tv/*" "http://www.hitbox.tv/*"
], ],
"css": [ "inject.css" ], "css": ["inject.css"],
"js": [ "inject.js" ] "js": ["inject.js"]
} }
], ],
"web_accessible_resources": [ "web_accessible_resources": ["inject.css", "shadow.css"]
"inject.css", "shadow.css"
]
} }

View File

@@ -1,109 +1,112 @@
body { body {
margin: 0; margin: 0;
padding-left: 15px; padding-left: 15px;
padding-top: 53px; padding-top: 53px;
font-family: sans-serif; font-family: sans-serif;
font-size: 12px; font-size: 12px;
color: rgb(48, 57, 66); color: rgb(48, 57, 66);
} }
h1, h2, h3 { h1,
font-weight: normal; h2,
line-height: 1; h3 {
user-select: none; font-weight: normal;
cursor: default; line-height: 1;
user-select: none;
cursor: default;
} }
h1 { h1 {
font-size: 1.5em; font-size: 1.5em;
margin: 21px 0 13px; margin: 21px 0 13px;
} }
h3 { h3 {
font-size: 1.2em; font-size: 1.2em;
margin-bottom: 0.8em; margin-bottom: 0.8em;
color: black; color: black;
} }
p { p {
margin: 0.65em 0; margin: 0.65em 0;
} }
header { header {
position: fixed; position: fixed;
top: 0; top: 0;
left: 15px; left: 15px;
right: 0; right: 0;
border-bottom: 1px solid #EEE; border-bottom: 1px solid #eee;
background: linear-gradient(white, white 40%, rgba(255, 255, 255, 0.92)); background: linear-gradient(white, white 40%, rgba(255, 255, 255, 0.92));
} }
header, section { header,
min-width: 600px; section {
max-width: 738px; min-width: 600px;
max-width: 738px;
} }
section { section {
padding-left: 18px; padding-left: 18px;
margin-top: 8px; margin-top: 8px;
margin-bottom: 24px; margin-bottom: 24px;
} }
section h3 { section h3 {
margin-left: -18px; margin-left: -18px;
} }
button { button {
-webkit-appearance: none; -webkit-appearance: none;
position: relative; position: relative;
margin: 0 1px 0 0; margin: 0 1px 0 0;
padding: 0 10px; padding: 0 10px;
min-width: 4em; min-width: 4em;
min-height: 2em; min-height: 2em;
background-image: linear-gradient(#EDEDED, #EDEDED 38%, #DEDEDE); background-image: linear-gradient(#ededed, #ededed 38%, #dedede);
border: 1px solid rgba(0,0,0,0.25); border: 1px solid rgba(0, 0, 0, 0.25);
border-radius: 2px; border-radius: 2px;
outline: none; outline: none;
box-shadow: 0 1px 0 rgba(0,0,0,0.08), inset 0 1px 2px rgba(255,255,255,0.75); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08),
color: #444; inset 0 1px 2px rgba(255, 255, 255, 0.75);
text-shadow: 0 1px 0 rgb(240,240,240); color: #444;
font: inherit; text-shadow: 0 1px 0 rgb(240, 240, 240);
font: inherit;
user-select: none; user-select: none;
} }
input[type="text"] { input[type="text"] {
width: 75px; width: 75px;
text-align: center; text-align: center;
} }
.row { .row {
margin: 5px 0px; margin: 5px 0px;
} }
label { label {
display: inline-block; display: inline-block;
width: 170px; width: 170px;
vertical-align: top; vertical-align: top;
} }
#status { #status {
color: #9D9D9D; color: #9d9d9d;
display: inline-block; display: inline-block;
margin-left: 50px; margin-left: 50px;
} }
#faq { #faq {
margin-top: 2em; margin-top: 2em;
} }
select { select {
width: 170px; width: 170px;
} }
.customForce { .customForce {
display: none; display: none;
width: 250px; width: 250px;
} }
.customKey { .customKey {
color: transparent; color: transparent;
text-shadow: 0 0 0 #000000; text-shadow: 0 0 0 #000000;
} }

View File

@@ -1,119 +1,170 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Video Speed Controller: Options</title> <title>Video Speed Controller: Options</title>
<link rel="stylesheet" href="options.css" /> <link rel="stylesheet" href="options.css" />
<script src="options.js"></script> <script src="options.js"></script>
</head> </head>
<body> <body>
<header> <header>
<h1>Video Speed Controller</h1> <h1>Video Speed Controller</h1>
</header> </header>
<section id="customs"> <section id="customs">
<h3>Shortcuts</h3> <h3>Shortcuts</h3>
<div class="row customs" id="display"> <div class="row customs" id="display">
<select class="customDo"> <select class="customDo">
<option value="display">Show/hide controller</option> <option value="display">Show/hide controller</option>
</select> </select>
<input class="customKey" type="text" value="" placeholder="press a key"> <input
<input class="customValue" type="text" placeholder="value (0.10)"> class="customKey"
<select class="customForce"> type="text"
<option value="false">Do not disable website key bindings</option> value=""
<option value="true">Disable websites key bindings</option> placeholder="press a key"
</select></div> />
<div class="row customs" id="slower"> <input class="customValue" type="text" placeholder="value (0.10)" />
<select class="customDo"> <select class="customForce">
<option value="slower">Decrease speed</option> <option value="false">Do not disable website key bindings</option>
</select> <option value="true">Disable websites key bindings</option>
<input class="customKey" type="text" value="" placeholder="press a key"> </select>
<input class="customValue" type="text" placeholder="value (0.10)"> </div>
<select class="customForce"> <div class="row customs" id="slower">
<option value="false">Do not disable website key bindings</option> <select class="customDo">
<option value="true">Disable websites key bindings</option> <option value="slower">Decrease speed</option>
</select></div> </select>
<div class="row customs" id="faster"> <input
<select class="customDo"> class="customKey"
<option value="faster">Increase speed</option> type="text"
</select> value=""
<input class="customKey" type="text" value="" placeholder="press a key"> placeholder="press a key"
<input class="customValue" type="text" placeholder="value (0.10)"> />
<select class="customForce"> <input class="customValue" type="text" placeholder="value (0.10)" />
<option value="false">Do not disable website key bindings</option> <select class="customForce">
<option value="true">Disable websites key bindings</option> <option value="false">Do not disable website key bindings</option>
</select></div> <option value="true">Disable websites key bindings</option>
<div class="row customs" id="rewind"> </select>
<select class="customDo"> </div>
<option value="rewind">Rewind</option> <div class="row customs" id="faster">
</select> <select class="customDo">
<input class="customKey" type="text" value="" placeholder="press a key"> <option value="faster">Increase speed</option>
<input class="customValue" type="text" placeholder="value (10)"> </select>
<select class="customForce"> <input
<option value="false">Do not disable website key bindings</option> class="customKey"
<option value="true">Disable websites key bindings</option> type="text"
</select></div> value=""
<div class="row customs" id="advance"> placeholder="press a key"
<select class="customDo"> />
<option value="advance">Advance</option> <input class="customValue" type="text" placeholder="value (0.10)" />
</select> <select class="customForce">
<input class="customKey" type="text" value="" placeholder="press a key"> <option value="false">Do not disable website key bindings</option>
<input class="customValue" type="text" placeholder="value (10)"> <option value="true">Disable websites key bindings</option>
<select class="customForce"> </select>
<option value="false">Do not disable website key bindings</option> </div>
<option value="true">Disable websites key bindings</option> <div class="row customs" id="rewind">
</select></div> <select class="customDo">
<div class="row customs" id="reset"> <option value="rewind">Rewind</option>
<select class="customDo"> </select>
<option value="reset">Reset speed</option> <input
</select> class="customKey"
<input class="customKey" type="text" value="" placeholder="press a key"> type="text"
<input class="customValue" type="text" placeholder="value (1.00)" disabled> value=""
<select class="customForce"> placeholder="press a key"
<option value="false">Do not disable website key bindings</option> />
<option value="true">Disable websites key bindings</option> <input class="customValue" type="text" placeholder="value (10)" />
</select></div> <select class="customForce">
<div class="row customs" id="fast"> <option value="false">Do not disable website key bindings</option>
<select class="customDo"> <option value="true">Disable websites key bindings</option>
<option value="fast">Preferred speed</option> </select>
</select> </div>
<input class="customKey" type="text" value="" placeholder="press a key"> <div class="row customs" id="advance">
<input class="customValue" type="text" placeholder="value (1.80)"> <select class="customDo">
<select class="customForce"> <option value="advance">Advance</option>
<option value="false">Do not disable website key bindings</option> </select>
<option value="true">Disable websites key bindings</option> <input
</select></div> 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> <button id="add">Add New</button>
</section> </section>
<section> <section>
<h3>Other</h3> <h3>Other</h3>
<div class="row"> <div class="row">
<label for="enabled">Enabled</label> <label for="enabled">Enabled</label>
<input id="enabled" type="checkbox"/> <input id="enabled" type="checkbox" />
</div> </div>
<div class="row"> <div class="row">
<label for="startHidden">Hide controller by default</label> <label for="startHidden">Hide controller by default</label>
<input id="startHidden" type="checkbox"/> <input id="startHidden" type="checkbox" />
</div> </div>
<div class="row"> <div class="row">
<label for="rememberSpeed">Remember Playback Speed</label> <label for="rememberSpeed">Remember Playback Speed</label>
<input id="rememberSpeed" type="checkbox"/> <input id="rememberSpeed" type="checkbox" />
</div> </div>
<div class="row"> <div class="row">
<label for="audioBoolean">Work on audio</label> <label for="audioBoolean">Work on audio</label>
<input id="audioBoolean" type="checkbox"/> <input id="audioBoolean" type="checkbox" />
</div> </div>
<div class="row"> <div class="row">
<label for="controllerOpacity">Controller opacity</label> <label for="controllerOpacity">Controller opacity</label>
<input id="controllerOpacity" type="text" value=""> <input id="controllerOpacity" type="text" value="" />
</div> </div>
<div class="row"> <div class="row">
<label for="blacklist">Blacklisted sites on which extension is disabled<br/> <label for="blacklist"
(one per line)<br/> >Blacklisted sites on which extension is disabled<br />
<br/> (one per line)<br />
<em><a href="https://www.regexpal.com/">Regex</a> is supported. Be sure it is in "//g" format.<br/> <br />
ie: /(.+)youtube\.com(\/*)$/gi</em> <em
><a href="https://www.regexpal.com/">Regex</a> is supported. Be sure
it is in "//g" format.<br />
ie: /(.+)youtube\.com(\/*)$/gi</em
>
</label> </label>
<textarea id="blacklist" rows="10" cols="50"></textarea> <textarea id="blacklist" rows="10" cols="50"></textarea>
</div> </div>
@@ -129,21 +180,39 @@
<hr /> <hr />
<h4>The video controls are not showing up?</h4> <h4>The video controls are not showing up?</h4>
<p>This extension is only compatible with HTML5 video. If you don't see the controls showing up, chances are you are viewing a Flash video. If you want to confirm, try right-clicking on the video and inspect the menu: if it mentions flash, then that's the issue. That said, <b>most sites will fallback to HTML5</b> if they detect that Flash it not available. You can try manually disabling Flash plugin in Chrome:</p> <p>
This extension is only compatible with HTML5 video. If you don't see the
controls showing up, chances are you are viewing a Flash video. If you
want to confirm, try right-clicking on the video and inspect the menu:
if it mentions flash, then that's the issue. That said,
<b>most sites will fallback to HTML5</b> if they detect that Flash it
not available. You can try manually disabling Flash plugin in Chrome:
</p>
<ul> <ul>
<li>In a new tab, navigate to <code>chrome://settings/content/flash</code></li> <li>
In a new tab, navigate to <code>chrome://settings/content/flash</code>
</li>
<li>Disable "Allow sites to run Flash"</li> <li>Disable "Allow sites to run Flash"</li>
<li>Restart your browser and try playing your video again</li> <li>Restart your browser and try playing your video again</li>
</ul> </ul>
<h4>The speed controls are not showing up for local videos?</h4> <h4>The speed controls are not showing up for local videos?</h4>
<p>To enable playback of local media (e.g. File &gt; Open File), you need to grant additional permissions to the extension.</p> <p>
To enable playback of local media (e.g. File &gt; Open File), you need
to grant additional permissions to the extension.
</p>
<ul> <ul>
<li>In a new tab, navigate to <code>chrome://extensions</code></li> <li>In a new tab, navigate to <code>chrome://extensions</code></li>
<li>Find "Video Speed Controller" extension in the list and enable "Allow access to file URLs"</li> <li>
<li>Open a new tab and try opening a local file, the controls should show up</li> Find "Video Speed Controller" extension in the list and enable "Allow
access to file URLs"
</li>
<li>
Open a new tab and try opening a local file, the controls should show
up
</li>
</ul> </ul>
</div> </div>
</body> </body>

View File

@@ -1,21 +1,21 @@
var regStrip=/^[\r\t\f\v ]+|[\r\t\f\v ]+$/gm; var regStrip = /^[\r\t\f\v ]+|[\r\t\f\v ]+$/gm;
var tcDefaults = { var tcDefaults = {
speed: 1.0, // default: speed: 1.0, // default:
displayKeyCode: 86, // default: V displayKeyCode: 86, // default: V
rememberSpeed: false, // default: false rememberSpeed: false, // default: false
audioBoolean: false, // default: false audioBoolean: false, // default: false
startHidden: false, // default: false startHidden: false, // default: false
enabled: true, // default enabled enabled: true, // default enabled
controllerOpacity: 0.3, // default: 0.3 controllerOpacity: 0.3, // default: 0.3
keyBindings: [ keyBindings: [
{action: "display", key: 86, value: 0, force: false, predefined: true }, // V { action: "display", key: 86, value: 0, force: false, predefined: true }, // V
{action: "slower", key: 83, value: 0.1, force: false, predefined: true}, // S { 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: "faster", key: 68, value: 0.1, force: false, predefined: true }, // D
{action: "rewind", key: 90, value: 10, force: false, predefined: true}, // Z { action: "rewind", key: 90, value: 10, force: false, predefined: true }, // Z
{action: "advance", key: 88, value: 10, force: false, predefined: true}, // X { action: "advance", key: 88, value: 10, force: false, predefined: true }, // X
{action: "reset", key: 82, value: 1, force: false, predefined: true}, // R { action: "reset", key: 82, value: 1, force: false, predefined: true }, // R
{action: "fast", key: 71, value: 1.8, force: false, predefined: true} // G { action: "fast", key: 71, value: 1.8, force: false, predefined: true } // G
], ],
blacklist: ` blacklist: `
www.instagram.com www.instagram.com
@@ -23,78 +23,81 @@ var tcDefaults = {
vine.co vine.co
imgur.com imgur.com
teams.microsoft.com teams.microsoft.com
`.replace(regStrip, '') `.replace(regStrip, "")
}; };
var keyBindings = []; var keyBindings = [];
var keyCodeAliases = { var keyCodeAliases = {
0: 'null', 0: "null",
null: 'null', null: "null",
undefined: 'null', undefined: "null",
32: 'Space', 32: "Space",
37: 'Left', 37: "Left",
38: 'Up', 38: "Up",
39: 'Right', 39: "Right",
40: 'Down', 40: "Down",
96: 'Num 0', 96: "Num 0",
97: 'Num 1', 97: "Num 1",
98: 'Num 2', 98: "Num 2",
99: 'Num 3', 99: "Num 3",
100: 'Num 4', 100: "Num 4",
101: 'Num 5', 101: "Num 5",
102: 'Num 6', 102: "Num 6",
103: 'Num 7', 103: "Num 7",
104: 'Num 8', 104: "Num 8",
105: 'Num 9', 105: "Num 9",
106: 'Num *', 106: "Num *",
107: 'Num +', 107: "Num +",
109: 'Num -', 109: "Num -",
110: 'Num .', 110: "Num .",
111: 'Num /', 111: "Num /",
112: 'F1', 112: "F1",
113: 'F2', 113: "F2",
114: 'F3', 114: "F3",
115: 'F4', 115: "F4",
116: 'F5', 116: "F5",
117: 'F6', 117: "F6",
118: 'F7', 118: "F7",
119: 'F8', 119: "F8",
120: 'F9', 120: "F9",
121: 'F10', 121: "F10",
122: 'F11', 122: "F11",
123: 'F12', 123: "F12",
186: ';', 186: ";",
188: '<', 188: "<",
189: '-', 189: "-",
187: '+', 187: "+",
190: '>', 190: ">",
191: '/', 191: "/",
192: '~', 192: "~",
219: '[', 219: "[",
220: '\\', 220: "\\",
221: ']', 221: "]",
222: '\'', 222: "'"
} };
function recordKeyPress(e) { function recordKeyPress(e) {
if ( if (
(e.keyCode >= 48 && e.keyCode <= 57) // Numbers 0-9 (e.keyCode >= 48 && e.keyCode <= 57) || // Numbers 0-9
|| (e.keyCode >= 65 && e.keyCode <= 90) // Letters A-Z (e.keyCode >= 65 && e.keyCode <= 90) || // Letters A-Z
|| keyCodeAliases[e.keyCode] // Other character keys keyCodeAliases[e.keyCode] // Other character keys
) { ) {
e.target.value = keyCodeAliases[e.keyCode] || String.fromCharCode(e.keyCode); e.target.value =
keyCodeAliases[e.keyCode] || String.fromCharCode(e.keyCode);
e.target.keyCode = e.keyCode; e.target.keyCode = e.keyCode;
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} else if (e.keyCode === 8) { // Clear input when backspace pressed } else if (e.keyCode === 8) {
e.target.value = ''; // Clear input when backspace pressed
} else if (e.keyCode === 27) { // When esc clicked, clear input e.target.value = "";
e.target.value = 'null'; } else if (e.keyCode === 27) {
// When esc clicked, clear input
e.target.value = "null";
e.target.keyCode = null; e.target.keyCode = null;
} }
}; }
function inputFilterNumbersOnly(e) { function inputFilterNumbersOnly(e) {
var char = String.fromCharCode(e.keyCode); var char = String.fromCharCode(e.keyCode);
@@ -102,18 +105,20 @@ function inputFilterNumbersOnly(e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} }
}; }
function inputFocus(e) { function inputFocus(e) {
e.target.value = ""; e.target.value = "";
}; }
function inputBlur(e) { function inputBlur(e) {
e.target.value = keyCodeAliases[e.target.keyCode] || String.fromCharCode(e.target.keyCode); e.target.value =
}; keyCodeAliases[e.target.keyCode] || String.fromCharCode(e.target.keyCode);
}
function updateShortcutInputText(inputId, keyCode) { function updateShortcutInputText(inputId, keyCode) {
document.getElementById(inputId).value = keyCodeAliases[keyCode] || String.fromCharCode(keyCode); document.getElementById(inputId).value =
keyCodeAliases[keyCode] || String.fromCharCode(keyCode);
document.getElementById(inputId).keyCode = keyCode; document.getElementById(inputId).keyCode = keyCode;
} }
@@ -123,7 +128,7 @@ function updateCustomShortcutInputText(inputItem, keyCode) {
} }
// List of custom actions for which customValue should be disabled // List of custom actions for which customValue should be disabled
var customActionsNoValues=["pause","muted","mark","jump","display"]; var customActionsNoValues = ["pause", "muted", "mark", "jump", "display"];
function add_shortcut() { function add_shortcut() {
var html = `<select class="customDo"> var html = `<select class="customDo">
@@ -146,11 +151,14 @@ function add_shortcut() {
<option value="true">Disable websites key bindings</option> <option value="true">Disable websites key bindings</option>
</select> </select>
<button class="removeParent">X</button>`; <button class="removeParent">X</button>`;
var div = document.createElement('div'); var div = document.createElement("div");
div.setAttribute('class', 'row customs'); div.setAttribute("class", "row customs");
div.innerHTML = html; div.innerHTML = html;
var customs_element = document.getElementById("customs"); var customs_element = document.getElementById("customs");
customs_element.insertBefore(div, customs_element.children[customs_element.childElementCount - 1]); customs_element.insertBefore(
div,
customs_element.children[customs_element.childElementCount - 1]
);
} }
function createKeyBindings(item) { function createKeyBindings(item) {
@@ -158,28 +166,37 @@ function createKeyBindings(item) {
const key = item.querySelector(".customKey").keyCode; const key = item.querySelector(".customKey").keyCode;
const value = Number(item.querySelector(".customValue").value); const value = Number(item.querySelector(".customValue").value);
const force = item.querySelector(".customForce").value; const force = item.querySelector(".customForce").value;
const predefined = !!item.id;//item.id ? true : false; const predefined = !!item.id; //item.id ? true : false;
keyBindings.push({action: action, key: key, value: value, force: force, predefined: predefined}); keyBindings.push({
action: action,
key: key,
value: value,
force: force,
predefined: predefined
});
} }
// Validates settings before saving // Validates settings before saving
function validate() { function validate() {
var valid = true; var valid = true;
var status = document.getElementById('status'); var status = document.getElementById("status");
document.getElementById('blacklist').value.split("\n").forEach(match => { document
match = match.replace(regStrip,'') .getElementById("blacklist")
if (match.startsWith('/')) { .value.split("\n")
try { .forEach(match => {
var regexp = new RegExp(match); match = match.replace(regStrip, "");
} catch(err) { if (match.startsWith("/")) {
status.textContent = 'Error: Invalid Regex: ' + match try {
+ '. Unable to save'; var regexp = new RegExp(match);
valid = false; } catch (err) {
return; status.textContent =
"Error: Invalid Regex: " + match + ". Unable to save";
valid = false;
return;
}
} }
} });
})
return valid; return valid;
} }
@@ -189,47 +206,70 @@ function save_options() {
return; return;
} }
keyBindings = []; keyBindings = [];
Array.from(document.querySelectorAll(".customs")).forEach(item => createKeyBindings(item)); // Remove added shortcuts Array.from(document.querySelectorAll(".customs")).forEach(item =>
createKeyBindings(item)
); // Remove added shortcuts
var rememberSpeed = document.getElementById('rememberSpeed').checked; var rememberSpeed = document.getElementById("rememberSpeed").checked;
var audioBoolean = document.getElementById('audioBoolean').checked; var audioBoolean = document.getElementById("audioBoolean").checked;
var enabled = document.getElementById('enabled').checked; var enabled = document.getElementById("enabled").checked;
var startHidden = document.getElementById('startHidden').checked; var startHidden = document.getElementById("startHidden").checked;
var controllerOpacity = document.getElementById('controllerOpacity').value; var controllerOpacity = document.getElementById("controllerOpacity").value;
var blacklist = document.getElementById('blacklist').value; var blacklist = document.getElementById("blacklist").value;
chrome.storage.sync.remove(["resetSpeed", "speedStep", "fastSpeed", "rewindTime", "advanceTime", "resetKeyCode", "slowerKeyCode", "fasterKeyCode", "rewindKeyCode", "advanceKeyCode", "fastKeyCode"]); chrome.storage.sync.remove([
chrome.storage.sync.set({ "resetSpeed",
rememberSpeed: rememberSpeed, "speedStep",
audioBoolean: audioBoolean, "fastSpeed",
enabled: enabled, "rewindTime",
startHidden: startHidden, "advanceTime",
controllerOpacity: controllerOpacity, "resetKeyCode",
keyBindings: keyBindings, "slowerKeyCode",
blacklist: blacklist.replace(regStrip,'') "fasterKeyCode",
}, function() { "rewindKeyCode",
// Update status to let user know options were saved. "advanceKeyCode",
var status = document.getElementById('status'); "fastKeyCode"
status.textContent = 'Options saved'; ]);
setTimeout(function() { chrome.storage.sync.set(
status.textContent = ''; {
}, 1000); rememberSpeed: rememberSpeed,
}); audioBoolean: audioBoolean,
enabled: enabled,
startHidden: startHidden,
controllerOpacity: controllerOpacity,
keyBindings: keyBindings,
blacklist: blacklist.replace(regStrip, "")
},
function() {
// Update status to let user know options were saved.
var status = document.getElementById("status");
status.textContent = "Options saved";
setTimeout(function() {
status.textContent = "";
}, 1000);
}
);
} }
// 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('rememberSpeed').checked = storage.rememberSpeed; document.getElementById("rememberSpeed").checked = storage.rememberSpeed;
document.getElementById('audioBoolean').checked = storage.audioBoolean; document.getElementById("audioBoolean").checked = storage.audioBoolean;
document.getElementById('enabled').checked = storage.enabled; document.getElementById("enabled").checked = storage.enabled;
document.getElementById('startHidden').checked = storage.startHidden; document.getElementById("startHidden").checked = storage.startHidden;
document.getElementById('controllerOpacity').value = storage.controllerOpacity; document.getElementById("controllerOpacity").value =
document.getElementById('blacklist').value = storage.blacklist; storage.controllerOpacity;
document.getElementById("blacklist").value = storage.blacklist;
// ensure that there is a "display" binding for upgrades from versions that had it as a separate binding // ensure that there is a "display" binding for upgrades from versions that had it as a separate binding
if(storage.keyBindings.filter(x => x.action == "display").length == 0){ if (storage.keyBindings.filter(x => x.action == "display").length == 0) {
storage.keyBindings.push({ action: "display", value: 0, force: false, predefined: true }); storage.keyBindings.push({
action: "display",
value: 0,
force: false,
predefined: true
});
} }
for (let i in storage.keyBindings) { for (let i in storage.keyBindings) {
@@ -237,27 +277,36 @@ function restore_options() {
if (item.predefined) { if (item.predefined) {
//do predefined ones because their value needed for overlay //do predefined ones because their value needed for overlay
// document.querySelector("#" + item["action"] + " .customDo").value = item["action"]; // document.querySelector("#" + item["action"] + " .customDo").value = item["action"];
if (item["action"] == "display" && typeof (item["key"]) === "undefined"){ if (item["action"] == "display" && typeof item["key"] === "undefined") {
item["key"] = storage.displayKeyCode || tcDefaults.displayKeyCode; // V item["key"] = storage.displayKeyCode || tcDefaults.displayKeyCode; // V
} }
if (customActionsNoValues.includes(item["action"])) if (customActionsNoValues.includes(item["action"]))
document.querySelector("#" + item["action"] + " .customValue").disabled = true; document.querySelector(
"#" + item["action"] + " .customValue"
).disabled = true;
updateCustomShortcutInputText(document.querySelector("#" + item["action"] + " .customKey"), item["key"]); updateCustomShortcutInputText(
document.querySelector("#" + item["action"] + " .customValue").value = item["value"]; document.querySelector("#" + item["action"] + " .customKey"),
document.querySelector("#" + item["action"] + " .customForce").value = item["force"]; item["key"]
} );
else { document.querySelector("#" + item["action"] + " .customValue").value =
item["value"];
document.querySelector("#" + item["action"] + " .customForce").value =
item["force"];
} else {
// new ones // new ones
add_shortcut(); add_shortcut();
const dom = document.querySelector(".customs:last-of-type") const dom = document.querySelector(".customs:last-of-type");
dom.querySelector(".customDo").value = item["action"]; dom.querySelector(".customDo").value = item["action"];
if (customActionsNoValues.includes(item["action"])) if (customActionsNoValues.includes(item["action"]))
dom.querySelector(".customValue").disabled = true; dom.querySelector(".customValue").disabled = true;
updateCustomShortcutInputText(dom.querySelector(".customKey"), item["key"]); updateCustomShortcutInputText(
dom.querySelector(".customKey"),
item["key"]
);
dom.querySelector(".customValue").value = item["value"]; dom.querySelector(".customValue").value = item["value"];
dom.querySelector(".customForce").value = item["force"]; dom.querySelector(".customForce").value = item["force"];
} }
@@ -268,60 +317,68 @@ function restore_options() {
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 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";
setTimeout(function() { setTimeout(function() {
status.textContent = ''; status.textContent = "";
}, 1000); }, 1000);
}); });
} }
function show_experimental() { function show_experimental() {
document.querySelectorAll(".customForce").forEach(item => item.style.display = 'inline-block'); document
.querySelectorAll(".customForce")
.forEach(item => (item.style.display = "inline-block"));
} }
document.addEventListener('DOMContentLoaded', function () { 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("add").addEventListener("click", add_shortcut);
document.getElementById('restore').addEventListener('click', restore_defaults); document
document.getElementById('experimental').addEventListener('click', show_experimental); .getElementById("restore")
.addEventListener("click", restore_defaults);
document
.getElementById("experimental")
.addEventListener("click", show_experimental);
function eventCaller(event, className, funcName) { function eventCaller(event, className, funcName) {
if (!event.target.classList.contains(className)) { if (!event.target.classList.contains(className)) {
return return;
} }
funcName(event); funcName(event);
} }
document.addEventListener('keypress', (event) => { document.addEventListener("keypress", event => {
eventCaller(event, "customValue", inputFilterNumbersOnly) eventCaller(event, "customValue", inputFilterNumbersOnly);
}); });
document.addEventListener('focus', (event) => { document.addEventListener("focus", event => {
eventCaller(event, "customKey", inputFocus) eventCaller(event, "customKey", inputFocus);
}); });
document.addEventListener('blur', (event) => { document.addEventListener("blur", event => {
eventCaller(event, "customKey", inputBlur) eventCaller(event, "customKey", inputBlur);
}); });
document.addEventListener('keydown', (event) => { document.addEventListener("keydown", event => {
eventCaller(event, "customKey", recordKeyPress) eventCaller(event, "customKey", recordKeyPress);
}); });
document.addEventListener('click', (event) => { document.addEventListener("click", event => {
eventCaller(event, "removeParent", function () { eventCaller(event, "removeParent", function() {
event.target.parentNode.remove() event.target.parentNode.remove();
}) });
}); });
document.addEventListener('change', (event) => { document.addEventListener("change", event => {
eventCaller(event, "customDo", function () { eventCaller(event, "customDo", function() {
if (customActionsNoValues.includes(event.target.value)) { if (customActionsNoValues.includes(event.target.value)) {
event.target.nextElementSibling.nextElementSibling.disabled = true; event.target.nextElementSibling.nextElementSibling.disabled = true;
event.target.nextElementSibling.nextElementSibling.value = 0; event.target.nextElementSibling.nextElementSibling.value = 0;
} else { } else {
event.target.nextElementSibling.nextElementSibling.disabled = false; event.target.nextElementSibling.nextElementSibling.disabled = false;
} }
}) });
}); });
}) });

View File

@@ -1,5 +1,5 @@
body { body {
min-width: 8em min-width: 8em;
} }
hr { hr {
@@ -12,13 +12,14 @@ hr {
button { button {
width: 100%; width: 100%;
background-image: linear-gradient(#EDEDED, #EDEDED 38%, #DEDEDE); background-image: linear-gradient(#ededed, #ededed 38%, #dedede);
border: 1px solid rgba(0,0,0,0.25); border: 1px solid rgba(0, 0, 0, 0.25);
border-radius: 2px; border-radius: 2px;
outline: none; outline: none;
box-shadow: 0 1px 0 rgba(0,0,0,0.08), inset 0 1px 2px rgba(255,255,255,0.75); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08),
inset 0 1px 2px rgba(255, 255, 255, 0.75);
color: #444; color: #444;
text-shadow: 0 1px 0 rgb(240,240,240); text-shadow: 0 1px 0 rgb(240, 240, 240);
font: inherit; font: inherit;
user-select: none; user-select: none;
} }

View File

@@ -1,4 +1,4 @@
<!doctype html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Video Speed Controller: Popup</title> <title>Video Speed Controller: Popup</title>

View File

@@ -1,44 +1,47 @@
document.addEventListener('DOMContentLoaded', function () { document.addEventListener("DOMContentLoaded", function() {
document.querySelector('#config').addEventListener('click', function() { document.querySelector("#config").addEventListener("click", function() {
window.open(chrome.runtime.getURL("options.html")); window.open(chrome.runtime.getURL("options.html"));
}); });
document.querySelector('#about').addEventListener('click', function() { document.querySelector("#about").addEventListener("click", function() {
window.open("https://github.com/igrigorik/videospeed"); window.open("https://github.com/igrigorik/videospeed");
}); });
document.querySelector('#feedback').addEventListener('click', function() { document.querySelector("#feedback").addEventListener("click", function() {
window.open("https://github.com/igrigorik/videospeed/issues"); window.open("https://github.com/igrigorik/videospeed/issues");
}); });
document.querySelector('#enable').addEventListener('click', function() { document.querySelector("#enable").addEventListener("click", function() {
toggleEnabled(true, settingsSavedReloadMessage); toggleEnabled(true, settingsSavedReloadMessage);
}); });
document.querySelector('#disable').addEventListener('click', function() { document.querySelector("#disable").addEventListener("click", function() {
toggleEnabled(false, settingsSavedReloadMessage); toggleEnabled(false, settingsSavedReloadMessage);
}); });
chrome.storage.sync.get({enabled: true}, function(storage) { chrome.storage.sync.get({ enabled: true }, function(storage) {
toggleEnabledUI(storage.enabled); toggleEnabledUI(storage.enabled);
}); });
function toggleEnabled(enabled, callback){ function toggleEnabled(enabled, callback) {
chrome.storage.sync.set({ chrome.storage.sync.set(
enabled: enabled, {
}, function() { enabled: enabled
toggleEnabledUI(enabled); },
if(callback) callback(enabled); function() {
}); toggleEnabledUI(enabled);
if (callback) callback(enabled);
}
);
} }
function toggleEnabledUI(enabled){ function toggleEnabledUI(enabled) {
document.querySelector('#enable').classList.toggle("hide", enabled); document.querySelector("#enable").classList.toggle("hide", enabled);
document.querySelector('#disable').classList.toggle("hide", !enabled); document.querySelector("#disable").classList.toggle("hide", !enabled);
const suffix = `${(enabled ? "" : "_disabled")}.png` const suffix = `${enabled ? "" : "_disabled"}.png`;
chrome.browserAction.setIcon({ chrome.browserAction.setIcon({
"path": { path: {
"19": "icons/icon19" + suffix, "19": "icons/icon19" + suffix,
"38": "icons/icon38" + suffix, "38": "icons/icon38" + suffix,
"48": "icons/icon48" + suffix "48": "icons/icon48" + suffix
@@ -46,12 +49,14 @@ document.addEventListener('DOMContentLoaded', function () {
}); });
} }
function settingsSavedReloadMessage(enabled){ function settingsSavedReloadMessage(enabled) {
setStatusMessage(`${enabled ? "Enabled" : "Disabled"}. Reload page to see changes`); setStatusMessage(
`${enabled ? "Enabled" : "Disabled"}. Reload page to see changes`
);
} }
function setStatusMessage(str){ function setStatusMessage(str) {
const status_element = document.querySelector('#status') const status_element = document.querySelector("#status");
status_element.classList.toggle("hide", false); status_element.classList.toggle("hide", false);
status_element.innerText = str; status_element.innerText = str;
} }

View File

@@ -72,7 +72,7 @@ button:focus {
} }
button:hover { button:hover {
opacity: 1.0; opacity: 1;
} }
button:active { button:active {