diff --git a/START_SCOREBOARD.html b/START_SCOREBOARD.html
deleted file mode 100644
index 4018f09..0000000
--- a/START_SCOREBOARD.html
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
- LADD Roller Derby Scoreboard
-
-
-
-
- LADD Scoreboard
-
-
- Having problems? Try something other than Internet Explorer!
- Chrome and Firefox have both been tested extensively.
-
-
-
-
- Documentation
-
-
-
- Neale Pickett <neale@woozle.org >
-
-
-
-
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..2c7c29a
--- /dev/null
+++ b/TODO
@@ -0,0 +1,2 @@
+* chrome.fileSystem.retainEntry?
+* use chrome.power to keep the display on
diff --git a/_locales/en/messages.json b/_locales/en/messages.json
new file mode 100644
index 0000000..5fb1bc7
--- /dev/null
+++ b/_locales/en/messages.json
@@ -0,0 +1,48 @@
+{
+ "appName": {
+ "message": "Woozle Roller Derby Scoreboard",
+ "description": "Application name"
+ },
+ "appShortName": {
+ "message": "Woozle Scoreboard",
+ "description": "Short application name"
+ },
+ "appDesc": {
+ "message": "Roller Derby Scoreboard for WFTDA, USARS, RDCL, MADE, and JRDA",
+ "description": "Application description for app store listing"
+ },
+
+ "period1": {
+ "message": "Period 1",
+ "description": "Name of first period"
+ },
+ "period2": {
+ "message": "Period 2",
+ "description": "Name of second period"
+ },
+ "halftime": {
+ "message": "Halftime",
+ "description": "The name of the break between periods"
+ },
+ "timeToGame": {
+ "message": "To Derby",
+ "description": "Text shown after countdown to start of game"
+ },
+
+ "jam": {
+ "message": "Jam",
+ "description": "Time during the game when skaters are actively playing"
+ },
+ "lineup": {
+ "message": "Lineup",
+ "description": "Time between active play, when skaters are positioning themselves"
+ },
+ "timeout": {
+ "message": "Timeout",
+ "description": "Time when game is suspended: period clock stops counting down"
+ },
+ "setup": {
+ "message": "Setup",
+ "description": "Software state allowing logos and times to be adjusted"
+ }
+}
diff --git a/classic.html b/classic.html
deleted file mode 100644
index 9362253..0000000
--- a/classic.html
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-
-
- LADD Scoreboard
-
-
-
-
-
-
-
-
-
-
- Home
-
- 0
- ★
- -
-
-
-
- --:--
-
- -:--.-
-
- 0
-
-
-
- Vis
-
- 0
- ★
- -
-
-
-
-
-
Power Jam
-
Grand Slam
-
Ouch
-
OMG
-
-
-
diff --git a/crg-nologo.html b/crg-nologo.html
deleted file mode 100644
index c53813d..0000000
--- a/crg-nologo.html
+++ /dev/null
@@ -1,192 +0,0 @@
-
-
-
-
- LADD Scoreboard
-
-
-
-
-
-
-
-
-
-
diff --git a/crg.html b/crg.html
deleted file mode 100644
index 89b8710..0000000
--- a/crg.html
+++ /dev/null
@@ -1,199 +0,0 @@
-
-
-
-
- LADD Scoreboard
-
-
-
-
-
-
-
-
-
-
-
Home
-
-
-
-
-
-
-
-
-
Home
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/flag-ca.html b/flag-ca.html
deleted file mode 100644
index 1cd69b3..0000000
--- a/flag-ca.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-flag
-
-
diff --git a/flag-mx.html b/flag-mx.html
deleted file mode 100644
index e76fd9a..0000000
--- a/flag-mx.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-flag
-
-
diff --git a/flag-us.html b/flag-us.html
deleted file mode 100644
index 59eb521..0000000
--- a/flag-us.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-flag
-
-
diff --git a/highvis.html b/highvis.html
deleted file mode 100644
index 90fa242..0000000
--- a/highvis.html
+++ /dev/null
@@ -1,99 +0,0 @@
-
-
-
-
- LADD Scoreboard
-
-
-
-
-
-
-
-
-
- --:--
-
-
- -
- ★
- -
- ★
- -
-
-
- -:--.-
-
-
-
Power Jam
-
Grand Slam
-
Ouch!
-
OMG
-
-
-
-
diff --git a/index.html b/index.html
deleted file mode 100644
index 2ea9a3a..0000000
--- a/index.html
+++ /dev/null
@@ -1,152 +0,0 @@
-
-
-
-
- LADD Roller Derby Scoreboard
-
-
-
-
- LADD Roller Derby Scoreboard
-
-
- This is a free WFTDA-rules scoreboard, created with ease-of-use
- in mind. It is known to work on PC, Mac, Android, iOS, or Linux, using any
- common web browser.
-
-
-
-
-
- Try it right now : click on things
- to make them change.
-
-
- Features
-
-
-
- Free to use, share, and change (GPLv3)
-
-
- No Internet connection required
-
-
- Easy mouse-driven (with hotkeys) setup and operation
-
-
- No complicated installation procedure: just open a web page
-
-
- Looks good , with colors tuned for high-visibility
- on projectors
-
-
- Appearance can be customized in HTML and CSS; comes with
- several pre-written themes
-
-
- Runs on practically anything, including older computers,
- smartphones, and tablets
-
-
- Ships with an ever-expanding set of
- team logos
-
-
- The only scoreboard conforming to 9.1.5.4, requiring
- penalty tracking .
-
-
-
- Themes
-
-
- Documentation
-
- Watch a 5-minute video
- tutorial or read the
- Full documentation which comes bundled with the
- download.
-
-
-
- Download
-
- Download
- version 5.2 to your hard drive to run a scoreboard
- without Internet access (recommended :
- watch how ). This
- includes the documentation.
-
-
-
- If your scoreboard computer has an Internet connection, you don't
- need to download anything at all. Just load up
- the full-screen version from this
- page and you're all set.
-
-
-
- You can
- also browse
- the source tree or clone it with git:
-
git clone http://woozle.org/~neale/projects/scoreboard
-
-
- Other Derby Stuff By Me
-
-
-
- Contact Me
-
-
- If you'd like me to add your team logo, have an idea for improvement,
- or just want to say hi, please send me an email. I especially
- like hearing from people who are using the software: I love knowing
- I'm able to help people out.
-
-
-
- Neale Pickett <neale@woozle.org >
-
-
-
-
diff --git a/logos/4crg.png b/logos/4crg.png
deleted file mode 100644
index aeac4dc..0000000
Binary files a/logos/4crg.png and /dev/null differ
diff --git a/logos/animas.png b/logos/animas.png
deleted file mode 100644
index 1bf1519..0000000
Binary files a/logos/animas.png and /dev/null differ
diff --git a/logos/aurora.png b/logos/aurora.png
deleted file mode 100644
index dd3d8cf..0000000
Binary files a/logos/aurora.png and /dev/null differ
diff --git a/logos/bbdd.png b/logos/bbdd.png
deleted file mode 100644
index f77386c..0000000
Binary files a/logos/bbdd.png and /dev/null differ
diff --git a/logos/bd-betties.png b/logos/bd-betties.png
deleted file mode 100644
index 9e3ff1e..0000000
Binary files a/logos/bd-betties.png and /dev/null differ
diff --git a/logos/black.png b/logos/black.png
deleted file mode 100644
index 0cd754c..0000000
Binary files a/logos/black.png and /dev/null differ
diff --git a/logos/blue.png b/logos/blue.png
deleted file mode 100644
index 248aeb1..0000000
Binary files a/logos/blue.png and /dev/null differ
diff --git a/logos/bombs.png b/logos/bombs.png
deleted file mode 100644
index 7713709..0000000
Binary files a/logos/bombs.png and /dev/null differ
diff --git a/logos/brawlers.png b/logos/brawlers.png
deleted file mode 100644
index ca47daa..0000000
Binary files a/logos/brawlers.png and /dev/null differ
diff --git a/logos/cherries.png b/logos/cherries.png
deleted file mode 100644
index 45e1648..0000000
Binary files a/logos/cherries.png and /dev/null differ
diff --git a/logos/choicecity.png b/logos/choicecity.png
deleted file mode 100644
index f9e205f..0000000
Binary files a/logos/choicecity.png and /dev/null differ
diff --git a/logos/chupas.png b/logos/chupas.png
deleted file mode 100644
index 54f32b1..0000000
Binary files a/logos/chupas.png and /dev/null differ
diff --git a/logos/dcd.png b/logos/dcd.png
deleted file mode 100644
index a3506de..0000000
Binary files a/logos/dcd.png and /dev/null differ
diff --git a/logos/dia.png b/logos/dia.png
deleted file mode 100644
index d574084..0000000
Binary files a/logos/dia.png and /dev/null differ
diff --git a/logos/doomsdames.png b/logos/doomsdames.png
deleted file mode 100644
index d5eddb3..0000000
Binary files a/logos/doomsdames.png and /dev/null differ
diff --git a/logos/doubledown.png b/logos/doubledown.png
deleted file mode 100644
index 810df49..0000000
Binary files a/logos/doubledown.png and /dev/null differ
diff --git a/logos/durango.png b/logos/durango.png
deleted file mode 100644
index 8504179..0000000
Binary files a/logos/durango.png and /dev/null differ
diff --git a/logos/fdd.png b/logos/fdd.png
deleted file mode 100644
index cfcd9d0..0000000
Binary files a/logos/fdd.png and /dev/null differ
diff --git a/logos/green.png b/logos/green.png
deleted file mode 100644
index ac41253..0000000
Binary files a/logos/green.png and /dev/null differ
diff --git a/logos/hobots.png b/logos/hobots.png
deleted file mode 100644
index b2b203c..0000000
Binary files a/logos/hobots.png and /dev/null differ
diff --git a/logos/hustlen.png b/logos/hustlen.png
deleted file mode 100644
index 6c15e05..0000000
Binary files a/logos/hustlen.png and /dev/null differ
diff --git a/logos/logos.html b/logos/logos.html
deleted file mode 100644
index 9fd8344..0000000
--- a/logos/logos.html
+++ /dev/null
@@ -1,74 +0,0 @@
-
-
-
- Roller Derby Logos
-
-
-
-
-
-
- Roller Derby Logo Gallery
-
-
- Here are the logos currently shipping with the
- free LADD Scoreboard . If you'd like
- yours added, email your team name, preferred short name, and logo
- to neale@woozle.org .
-
-
-
-
diff --git a/logos/logos.js b/logos/logos.js
deleted file mode 100644
index bfb6e36..0000000
--- a/logos/logos.js
+++ /dev/null
@@ -1,52 +0,0 @@
-teams = [
- ["LA", "bombs.png", "Los Alamos M'Atom Bombs"],
- ["ARG", "animas.png", "Animas Valley Roller Girls"],
- ["Taos", "taos.png", "Taos Whiplashes"],
- ["RIP", "rip.png", "Rollergirls In Pagosa"],
- ["4CRG", "4crg.png", "4 Corners Roller Girls"],
- ["DRG", "durango.png", "Durango Roller Girls"],
- ["SFe", "brawlers.png", "Disco Brawlers"],
- ["HCRD", "aurora.png", "High City Derby Divas"],
- ["Moab", "moab.png", "Moab Roller Derby"],
- ["Bots", "hobots.png", "Albuquerque Ho-Bots"],
- ["HNR", "hustlen.png", "HCDD Hustle N' Rollers"],
- ["DD", "doubledown.png", "HCDD Double Down"],
- ["DCD", "dcd.png", "Duke City Derby"],
- ["RMRG", "rmrg.png", "Rocky Mountain Roller Girls"],
- ["DD", "doomsdames.png", "Albuquerque Doomsdames"],
- ["TEX", "texpistols.png", "El Paso Tex Pistols"],
- ["PWH", "pistol.png", "El Paso Pistol Whip-Hers"],
- ["MT", "minorthreat.png", "Minor Threat"],
- ["CCR", "choicecity.png", "Choice City Rebels"],
- ["DIA", "dia.png", "Derby Intelligence Agency"],
- ["TRD", "tucson.png", "Tucson Roller Derby"],
- ["TST", "saddletramps.jpg","Tucson Saddle Tramps"],
- ["TC", "tallcity.png", "Tall City Roller Betties"],
- ["SS", "ssdd.png", "South Side Derby Dames"],
- ["WTRD", "wtrd.png", "West Texas Roller Dollz"],
- ["FDD", "fdd.png", "Faultline Derby Devilz"],
- ["CHPA", "chupas.png", "New Mexico Chupacabras"],
- ["TKRD", "tulare-kings.png", "Tulare Kings Roller Derby"],
- ["CHRY", "cherries.png", "Los Alamos Cherry Bombs"],
- ["PLG", "plague.png", "Zombie Plague"],
- ["BDB", "bd-betties.png", "Black Diamond Betties"],
- ["SKS", "sirens.png", "Sea to Sky Sirens"],
- ["BBDD", "bbdd.png", "Battle Born Derby Demons"],
- ["OKVD", "okvd.png", "Oklahoma Victory Dolls"],
- ["MM", "munecas.png", "Muñecas Muertas"],
- ["MARI", "marionettes.png", "Albuquerque Marionettes"],
- ["QSDD", "qsdd.png", "Quad Skate Derby Dames"],
- ["BWBS", "bwbs.png", "Backwoods Bombshells"]
- ["CRH", "redhots.png", "Chicago Red Hots"],
- ["HCRG", "campers.png", "Happy Camper Rollergirls"]
-];
-teams.sort();
-
-// Add special teams at the beginning
-teams.splice(0, 0,
- ["Blk", "black.png", "Black Team"],
- ["Wht", "white.png", "White Team"],
- ["Grn", "green.png", "Green Team"],
- ["Rng", "orange.png", "Orange Team"],
- ["Blu", "blue.png", "Blue Team"]
-);
diff --git a/logos/marionettes.png b/logos/marionettes.png
deleted file mode 100644
index 635dfb9..0000000
Binary files a/logos/marionettes.png and /dev/null differ
diff --git a/logos/minorthreat.png b/logos/minorthreat.png
deleted file mode 100644
index aac503c..0000000
Binary files a/logos/minorthreat.png and /dev/null differ
diff --git a/logos/moab.png b/logos/moab.png
deleted file mode 100644
index 9c71bb0..0000000
Binary files a/logos/moab.png and /dev/null differ
diff --git a/logos/munecas.png b/logos/munecas.png
deleted file mode 100644
index 30dae0a..0000000
Binary files a/logos/munecas.png and /dev/null differ
diff --git a/logos/okvd.png b/logos/okvd.png
deleted file mode 100644
index 161fe01..0000000
Binary files a/logos/okvd.png and /dev/null differ
diff --git a/logos/orange.png b/logos/orange.png
deleted file mode 100644
index 4136338..0000000
Binary files a/logos/orange.png and /dev/null differ
diff --git a/logos/pistol.png b/logos/pistol.png
deleted file mode 100644
index 4fdc843..0000000
Binary files a/logos/pistol.png and /dev/null differ
diff --git a/logos/plague.png b/logos/plague.png
deleted file mode 100644
index 4f7b10e..0000000
Binary files a/logos/plague.png and /dev/null differ
diff --git a/logos/rip.png b/logos/rip.png
deleted file mode 100644
index 6d98c6b..0000000
Binary files a/logos/rip.png and /dev/null differ
diff --git a/logos/rmrg.png b/logos/rmrg.png
deleted file mode 100644
index 2f93072..0000000
Binary files a/logos/rmrg.png and /dev/null differ
diff --git a/logos/saddletramps.jpg b/logos/saddletramps.jpg
deleted file mode 100644
index ecaf098..0000000
Binary files a/logos/saddletramps.jpg and /dev/null differ
diff --git a/logos/sirens.png b/logos/sirens.png
deleted file mode 100644
index 51c5374..0000000
Binary files a/logos/sirens.png and /dev/null differ
diff --git a/logos/skate.png b/logos/skate.png
deleted file mode 100644
index 8a63311..0000000
Binary files a/logos/skate.png and /dev/null differ
diff --git a/logos/ssdd.png b/logos/ssdd.png
deleted file mode 100644
index e7841f4..0000000
Binary files a/logos/ssdd.png and /dev/null differ
diff --git a/logos/tallcity.png b/logos/tallcity.png
deleted file mode 100644
index b846a15..0000000
Binary files a/logos/tallcity.png and /dev/null differ
diff --git a/logos/taos.png b/logos/taos.png
deleted file mode 100644
index b00f3d6..0000000
Binary files a/logos/taos.png and /dev/null differ
diff --git a/logos/texpistols.png b/logos/texpistols.png
deleted file mode 100644
index 4c6c474..0000000
Binary files a/logos/texpistols.png and /dev/null differ
diff --git a/logos/tucson.png b/logos/tucson.png
deleted file mode 100644
index 064b73c..0000000
Binary files a/logos/tucson.png and /dev/null differ
diff --git a/logos/tulare-kings.png b/logos/tulare-kings.png
deleted file mode 100644
index 1baddb1..0000000
Binary files a/logos/tulare-kings.png and /dev/null differ
diff --git a/logos/wftda.png b/logos/wftda.png
deleted file mode 100644
index b55f3ce..0000000
Binary files a/logos/wftda.png and /dev/null differ
diff --git a/logos/white.png b/logos/white.png
deleted file mode 100644
index 2c9edaf..0000000
Binary files a/logos/white.png and /dev/null differ
diff --git a/logos/wtrd.png b/logos/wtrd.png
deleted file mode 100644
index 155ff19..0000000
Binary files a/logos/wtrd.png and /dev/null differ
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..bd54566
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,27 @@
+{
+ "manifest_version": 2,
+
+ "name": "BETA Woozle Scoreboard",
+ "short_name": "BETA Scoreboard",
+ "icons": {"128": "res/icon-plaid.png"},
+
+ "_name": "__MSG_appName__",
+ "_short_name": "__MSG_appShortName__",
+ "_icons": {"128": "res/icon.png"},
+
+ "description": "__MSG_appDesc__",
+ "author": "Neale Pickett ",
+ "version": "7.0.2",
+ "app": {
+ "background": {
+ "scripts": ["res/background.js"]
+ }
+ },
+ "permissions": [
+ "storage",
+ "fileSystem",
+ "fullscreen"
+ ],
+ "default_locale": "en",
+ "offline_enabled": true
+}
diff --git a/micro.html b/micro.html
deleted file mode 100644
index b9c3155..0000000
--- a/micro.html
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
- LADD Scoreboard
-
-
-
-
-
-
-
-
-
- --:--
-
-
- S
- -:--
-
-
-
-
diff --git a/penalties.html b/penalties.html
deleted file mode 100644
index 93fca7d..0000000
--- a/penalties.html
+++ /dev/null
@@ -1,140 +0,0 @@
-
-
-
-
- LADD Scoreboard
-
-
-
-
-
-
-
-
-
-
-
-
- 0
- ★
- -
-
-
-
- --:--
- -:--.-
-
- 0
-
-
-
-
- 0
- ★
- -
-
-
-
-
-
-
-
Power Jam
-
Grand Slam
-
Ouch
-
OMG
-
-
-
diff --git a/res/BadGirl.swf b/res/BadGirl.swf
deleted file mode 100644
index 029f84a..0000000
Binary files a/res/BadGirl.swf and /dev/null differ
diff --git a/res/FasterFaster.swf b/res/FasterFaster.swf
deleted file mode 100644
index 53f9ebc..0000000
Binary files a/res/FasterFaster.swf and /dev/null differ
diff --git a/res/Flag_of_Canada.svg b/res/Flag_of_Canada.svg
deleted file mode 100644
index 137eced..0000000
--- a/res/Flag_of_Canada.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/res/Flag_of_Mexico.svg b/res/Flag_of_Mexico.svg
deleted file mode 100644
index 7ed18fa..0000000
--- a/res/Flag_of_Mexico.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/res/Flag_of_the_United_States.svg b/res/Flag_of_the_United_States.svg
deleted file mode 100644
index f02c7a8..0000000
--- a/res/Flag_of_the_United_States.svg
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/HolyShot.swf b/res/HolyShot.swf
deleted file mode 100644
index 8b91385..0000000
Binary files a/res/HolyShot.swf and /dev/null differ
diff --git a/res/Magenta.woff b/res/Magenta.woff
deleted file mode 100644
index f03433c..0000000
Binary files a/res/Magenta.woff and /dev/null differ
diff --git a/res/Ouch.swf b/res/Ouch.swf
deleted file mode 100644
index 2e543d2..0000000
Binary files a/res/Ouch.swf and /dev/null differ
diff --git a/res/PermanentMarker.woff b/res/PermanentMarker.woff
deleted file mode 100644
index 756566a..0000000
Binary files a/res/PermanentMarker.woff and /dev/null differ
diff --git a/res/Pow.swf b/res/Pow.swf
deleted file mode 100644
index 5415073..0000000
Binary files a/res/Pow.swf and /dev/null differ
diff --git a/res/Ubuntu-Bold.ttf b/res/Ubuntu-Bold.ttf
new file mode 100644
index 0000000..c0142fe
Binary files /dev/null and b/res/Ubuntu-Bold.ttf differ
diff --git a/res/Ubuntu-Medium.ttf b/res/Ubuntu-Medium.ttf
new file mode 100644
index 0000000..443ec8b
Binary files /dev/null and b/res/Ubuntu-Medium.ttf differ
diff --git a/res/Zounds.swf b/res/Zounds.swf
deleted file mode 100644
index 8df8f9c..0000000
Binary files a/res/Zounds.swf and /dev/null differ
diff --git a/res/adverts.js b/res/adverts.js
deleted file mode 100644
index 64110e0..0000000
--- a/res/adverts.js
+++ /dev/null
@@ -1,30 +0,0 @@
-var advert_num = 100
-var advert_itimer
-
-function adverterror() {
- if (advert_num > 1) {
- advert_num = 1
- rotate_advert()
- } else {
- var e = document.getElementById("advert")
- clearInterval(advert_itimer)
- e.style.visibility = "hidden"
- }
-}
-
-function rotate_advert() {
- var e = document.getElementById("advert")
- var sn
-
- if (advert_num < 10) {
- sn = "0" + advert_num
- } else {
- sn = advert_num
- }
-
- e.src = "ads/ad" + sn + ".jpg"
-
- advert_num = advert_num + 1
-}
-
-advert_itimer = setInterval(rotate_advert, 15000)
diff --git a/res/background.js b/res/background.js
new file mode 100644
index 0000000..549f4e2
--- /dev/null
+++ b/res/background.js
@@ -0,0 +1,5 @@
+chrome.app.runtime.onLaunched.addListener(function() {
+ chrome.app.window.create('res/scoreboard.html', {
+ 'state': 'fullscreen'
+ })
+})
diff --git a/res/checkerboard.png b/res/checkerboard.png
deleted file mode 100644
index a2746af..0000000
Binary files a/res/checkerboard.png and /dev/null differ
diff --git a/res/close-icon-white.png b/res/close-icon-white.png
new file mode 100644
index 0000000..cd78df5
Binary files /dev/null and b/res/close-icon-white.png differ
diff --git a/res/hellokitty.svg b/res/hellokitty.svg
deleted file mode 100644
index 75b6569..0000000
--- a/res/hellokitty.svg
+++ /dev/null
@@ -1,160 +0,0 @@
-
-
-
-
-
-
-
- image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/ic_picture.png b/res/ic_picture.png
new file mode 100644
index 0000000..2bfaaa7
Binary files /dev/null and b/res/ic_picture.png differ
diff --git a/res/icon-plaid.png b/res/icon-plaid.png
new file mode 100644
index 0000000..3aba628
Binary files /dev/null and b/res/icon-plaid.png differ
diff --git a/res/icon.png b/res/icon.png
new file mode 100644
index 0000000..248a381
Binary files /dev/null and b/res/icon.png differ
diff --git a/res/jammer.svg b/res/jammer.svg
deleted file mode 100644
index 63a2fd2..0000000
--- a/res/jammer.svg
+++ /dev/null
@@ -1,98 +0,0 @@
-
-
-
-
-
-
-
-
-
- image/svg+xml
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/kitty.html b/res/kitty.html
new file mode 100644
index 0000000..ecf7dcd
--- /dev/null
+++ b/res/kitty.html
@@ -0,0 +1,19 @@
+
+
+
+ Kitty Explorer
+
+
+
+
+ (meow)
+
+
diff --git a/res/kitty.js b/res/kitty.js
new file mode 100644
index 0000000..ea3b7bd
--- /dev/null
+++ b/res/kitty.js
@@ -0,0 +1,355 @@
+// This is kludged together from the output of http://www.professorcloud.com/svg-to-canvas/
+// I saved as a 100×68.83 pixel SVG, then twiddled around with the prelude of the JS output.
+// If you are reading this, there's probably a nicer converter out now.
+// But this seems to work okay so it may not be worth the effort.
+
+function kitty(ctx, kittyColor) {
+
+ var scaleBase = 0.1098503139616503
+ var scaleX = scaleBase * ctx.canvas.width / 100
+ var scaleY = scaleBase * ctx.canvas.height / 68.83
+ var scale = Math.min(scaleX, scaleY)
+
+
+ctx.save();
+ctx.scale(scale, scale);
+ctx.translate(187.81991,187.81991);
+ctx.strokeStyle = 'rgba(0,0,0,0)';
+ctx.lineCap = 'butt';
+ctx.lineJoin = 'miter';
+ctx.miterLimit = 4;
+ctx.save();
+ctx.translate(0.22995231,-396.76901);
+ctx.save();
+ctx.fillStyle = kittyColor;
+ctx.strokeStyle = "#000000";
+ctx.lineWidth = 20.37454605102539;
+ctx.lineCap = "butt";
+ctx.lineJoin = "round";
+ctx.miterLimit = 4;
+ctx.beginPath();
+ctx.moveTo(263.23037,219.17781);
+ctx.bezierCurveTo(209.09715,219.95058,155.19615,230.72191999999998,105.64392999999998,251.41147);
+ctx.bezierCurveTo(105.57612999999998,251.43927000000002,105.47314999999999,251.38257000000002,105.40514999999998,251.41147);
+ctx.bezierCurveTo(74.58948199999998,237.52258,40.50337099999997,225.86925000000002,15.867370999999977,229.44481000000002);
+ctx.bezierCurveTo(-2.982406800000021,254.52492,-9.558406700000024,291.54425000000003,-10.397073000000024,327.57825);
+ctx.bezierCurveTo(-68.96529500000003,384.63103,-109.75229000000002,464.09403000000003,-118.55874000000001,566.34569);
+ctx.lineTo(-93.72685000000001,566.34569);
+ctx.bezierCurveTo(-99.55329500000002,829.8689099999999,218.71792,826.24936,262.99159,825.16958);
+ctx.bezierCurveTo(271.39515,824.9648,290.07180999999997,824.88991,314.80415,823.02069);
+ctx.bezierCurveTo(331.29237,821.77436,350.61791999999997,819.6868,371.15326,816.3351399999999);
+ctx.bezierCurveTo(376.28715,815.49736,381.38669999999996,814.48214,386.67314999999996,813.4700199999999);
+ctx.bezierCurveTo(497.68913999999995,792.2149099999999,637.94381,730.7707999999999,621.6202499999999,549.8706899999999);
+ctx.lineTo(660.7781399999999,549.8706899999999);
+ctx.bezierCurveTo(649.6126999999999,467.2469199999999,617.1321399999999,400.28402999999986,571.4791399999999,348.58980999999983);
+ctx.bezierCurveTo(572.5872599999999,307.2829199999998,567.21926,261.8263599999998,545.2146999999999,232.54880999999983);
+ctx.bezierCurveTo(518.6728099999999,228.69657999999984,481.3090299999999,242.58857999999984,448.7526999999999,257.8581399999998);
+ctx.bezierCurveTo(448.68599999999986,257.82703999999984,448.5803699999999,257.8892399999998,448.51391999999987,257.8581399999998);
+ctx.bezierCurveTo(390.90069999999986,231.21335999999982,326.91391999999985,218.26880999999983,263.2303699999999,219.17780999999982);
+ctx.closePath();
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.restore();
+ctx.save();
+ctx.translate(0.22995231,-396.76901);
+ctx.save();
+ctx.fillStyle = "rgba(45, 45, 45, 0.6745098039215687)";
+ctx.strokeStyle = "#000000";
+ctx.lineWidth = 20.37454605102539;
+ctx.lineCap = "butt";
+ctx.lineJoin = "round";
+ctx.miterLimit = 4;
+ctx.beginPath();
+ctx.moveTo(263.23037,219.17781);
+ctx.bezierCurveTo(209.02281,219.9517,155.01337,230.66592,105.40514999999999,251.41147);
+ctx.bezierCurveTo(124.77393,260.14114,142.75193,269.80447000000004,156.26259,277.19836);
+ctx.bezierCurveTo(101.54814999999999,287.66580999999996,23.972259999999977,334.24057999999997,-9.20318450000002,369.84013999999996);
+ctx.bezierCurveTo(-10.36285100000002,356.41981,-10.73551800000002,342.11868999999996,-10.39707300000002,327.57824999999997);
+ctx.bezierCurveTo(-68.96529500000003,384.63102999999995,-109.75229000000002,464.09403,-118.55874000000001,566.34569);
+ctx.lineTo(-41.675629000000015,566.34569);
+ctx.lineTo(-41.675629000000015,439.32147);
+ctx.bezierCurveTo(96.42092599999998,476.58558,501.82402999999994,478.74613999999997,577.4483700000001,446.96202999999997);
+ctx.lineTo(579.5972600000001,549.87069);
+ctx.lineTo(660.7781400000001,549.87069);
+ctx.bezierCurveTo(649.6127000000001,467.24692,617.1321400000002,400.28403,571.4791400000001,348.58980999999994);
+ctx.bezierCurveTo(571.2552600000001,356.94624999999996,570.9641400000002,365.08991999999995,570.2852600000001,372.94402999999994);
+ctx.bezierCurveTo(537.1098100000002,337.34457999999995,459.5339200000001,290.76980999999995,404.8194800000001,280.3023599999999);
+ctx.bezierCurveTo(416.6672600000001,273.81846999999993,432.09703000000013,265.6700299999999,448.7527000000001,257.85813999999993);
+ctx.bezierCurveTo(391.08781,231.15081,326.98737,218.2677,263.23037,219.17781);
+ctx.closePath();
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "rgba(0, 0, 0, 0)";
+ctx.strokeStyle = "#000000";
+ctx.lineWidth = 20.37454605102539;
+ctx.lineCap = "butt";
+ctx.lineJoin = "round";
+ctx.miterLimit = 4;
+ctx.beginPath();
+ctx.moveTo(-41.675629,439.32136);
+ctx.lineTo(-41.675629,566.34569);
+ctx.lineTo(-93.72685,566.34569);
+ctx.bezierCurveTo(-99.55329499999999,829.8689099999999,218.71792,826.24936,262.9917,825.16958);
+ctx.bezierCurveTo(307.81048,824.07647,646.49437,825.52791,621.62037,549.87069);
+ctx.lineTo(579.59726,549.87069);
+ctx.lineTo(577.44837,446.96191999999996);
+ctx.bezierCurveTo(501.82413999999994,478.74602999999996,96.42092599999995,476.58547,-41.67562900000007,439.32135999999997);
+ctx.closePath();
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "rgba(0, 0, 0, 0)";
+ctx.transform(0.1017341,0,0,0.1017341,-189.21074,758.53069);
+ctx.save();
+ctx.fillStyle = "rgba(0, 0, 0, 0)";
+ctx.strokeStyle = "#000000";
+ctx.lineWidth = 200.2725372314453;
+ctx.lineCap = "round";
+ctx.lineJoin = "round";
+ctx.miterLimit = 4;
+ctx.beginPath();
+ctx.moveTo(5838.2978,-4701.1388);
+ctx.bezierCurveTo(6376.116,-4598.2485,7139.0243,-4139.491099999999,7465.124900000001,-3789.5636999999997);
+ctx.bezierCurveTo(7504.7714000000005,-4248.3897,7479.873700000001,-4823.4601,7219.823,-5169.4639);
+ctx.bezierCurveTo(6825.455400000001,-5226.701,6182.3921,-4889.4492,5838.2978,-4701.1388);
+ctx.closePath();
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "rgba(0, 0, 0, 0)";
+ctx.strokeStyle = "#000000";
+ctx.lineWidth = 200.2725372314453;
+ctx.lineCap = "round";
+ctx.lineJoin = "round";
+ctx.miterLimit = 4;
+ctx.beginPath();
+ctx.moveTo(3397.0185,-4731.6101);
+ctx.bezierCurveTo(2859.2003,-4628.7198,2096.2920000000004,-4169.9624,1770.1914000000002,-3820.035);
+ctx.bezierCurveTo(1730.5449,-4278.861,1755.4426,-4853.9313,2015.4933,-5199.9351);
+ctx.bezierCurveTo(2409.8609,-5257.172299999999,3052.9242000000004,-4919.9205,3397.0185,-4731.6101);
+ctx.closePath();
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "#000000";
+ctx.strokeStyle = "rgba(0, 0, 0, 0)";
+ctx.beginPath();
+ctx.moveTo(52.032037,620.50691);
+ctx.bezierCurveTo(52.032037,620.50691,55.796148,645.0247999999999,71.66670400000001,650.0097999999999);
+ctx.bezierCurveTo(71.66670400000001,650.0097999999999,79.093259,652.2479099999999,86.621593,649.2976899999999);
+ctx.bezierCurveTo(86.621593,649.2976899999999,93.946481,646.4491399999998,98.727926,639.8363599999999);
+ctx.bezierCurveTo(98.727926,639.8363599999999,103.30604,633.4271399999999,104.22158999999999,623.76236);
+ctx.bezierCurveTo(104.22158999999999,623.76236,104.93369999999999,617.0479099999999,103.91636999999999,606.1623599999999);
+ctx.bezierCurveTo(103.91636999999999,606.1623599999999,102.39036999999999,598.6340299999999,98.42281499999999,592.5300299999999);
+ctx.bezierCurveTo(98.42281499999999,592.5300299999999,93.94648099999999,585.61214,87.63892599999998,582.7635799999999);
+ctx.bezierCurveTo(87.63892599999998,582.7635799999999,39.91114799999998,566.1871399999999,35.457925999999986,571.0994699999999);
+ctx.bezierCurveTo(31.004703999999986,576.0117999999999,65.93703699999999,585.0342499999999,61.053814999999986,587.5775799999999);
+ctx.bezierCurveTo(61.053814999999986,587.5775799999999,49.38692599999999,596.3959099999998,52.03203699999999,620.50691);
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "#000000";
+ctx.strokeStyle = "rgba(0, 0, 0, 0)";
+ctx.beginPath();
+ctx.moveTo(297.48526,699.49191);
+ctx.bezierCurveTo(297.48526,699.49191,285.37881,707.63058,268.38926,707.0202499999999);
+ctx.bezierCurveTo(268.38926,707.0202499999999,253.23091999999997,706.5115799999999,239.08980999999997,699.5936899999999);
+ctx.bezierCurveTo(239.08980999999997,699.5936899999999,231.76503999999997,695.93125,228.40780999999998,688.5045799999999);
+ctx.bezierCurveTo(228.40780999999998,688.5045799999999,225.15225999999998,681.3832499999999,226.27137,672.5323599999999);
+ctx.bezierCurveTo(226.27137,672.5323599999999,227.18692,665.8179099999999,230.54415,660.3242499999999);
+ctx.bezierCurveTo(230.54415,660.3242499999999,234.41004,654.3219099999999,240.3107,651.37169);
+ctx.bezierCurveTo(240.3107,651.37169,251.70492,643.84336,267.77881,644.1485799999999);
+ctx.bezierCurveTo(267.77881,644.1485799999999,283.44592,644.4537999999999,295.55226000000005,651.6769099999999);
+ctx.bezierCurveTo(295.55226000000005,651.6769099999999,301.24937000000006,654.3219099999999,305.11526000000003,659.9173599999999);
+ctx.bezierCurveTo(305.11526000000003,659.9173599999999,308.87948000000006,665.4110299999999,309.69337,671.9219099999999);
+ctx.bezierCurveTo(309.69337,671.9219099999999,310.71070000000003,680.3659099999999,307.45515,687.5890299999999);
+ctx.bezierCurveTo(307.45515,687.5890299999999,304.30137,694.8121399999999,297.48526,699.4919099999998);
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "#d35f5f";
+ctx.strokeStyle = "rgba(0, 0, 0, 0)";
+ctx.beginPath();
+ctx.moveTo(271.03437,661.23991);
+ctx.bezierCurveTo(271.03437,661.23991,281.51292,662.0538,287.10837000000004,668.66647);
+ctx.bezierCurveTo(287.10837000000004,668.66647,289.14304000000004,670.19247,289.95692,672.93925);
+ctx.lineTo(290.97426,678.02603);
+ctx.bezierCurveTo(290.97426,678.02603,290.87204,681.07803,288.63437,683.72314);
+ctx.bezierCurveTo(288.63437,683.72314,286.5997,686.16469,283.64937,687.4872499999999);
+ctx.bezierCurveTo(283.64937,687.4872499999999,275.81581,691.4549099999999,265.84592,690.9462499999998);
+ctx.bezierCurveTo(265.84592,690.9462499999998,255.57080999999997,690.5393599999999,248.65281,685.4525799999999);
+ctx.bezierCurveTo(248.65281,685.4525799999999,242.65059,679.75547,244.78691999999998,674.2617999999999);
+ctx.bezierCurveTo(244.78691999999998,674.2617999999999,245.49915,671.3115799999999,247.83903999999998,668.3612499999999);
+ctx.bezierCurveTo(247.83903999999998,668.3612499999999,250.07715,665.5126899999999,252.82392,663.98669);
+ctx.bezierCurveTo(252.82392,663.98669,261.98004,660.42603,271.03436999999997,661.23991);
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "#000000";
+ctx.strokeStyle = "rgba(0, 0, 0, 0)";
+ctx.beginPath();
+ctx.moveTo(472.46781,621.05491);
+ctx.bezierCurveTo(472.46781,621.05491,468.70369999999997,645.5727999999999,452.83315,650.5577999999999);
+ctx.bezierCurveTo(452.83315,650.5577999999999,445.40659,652.7959099999999,437.87826,649.8456899999999);
+ctx.bezierCurveTo(437.87826,649.8456899999999,430.55337000000003,646.9971399999998,425.77192,640.3843599999999);
+ctx.bezierCurveTo(425.77192,640.3843599999999,421.19392000000005,633.9751399999999,420.27826000000005,624.31036);
+ctx.bezierCurveTo(420.27826000000005,624.31036,419.56615000000005,617.5959099999999,420.58348000000007,606.7103599999999);
+ctx.bezierCurveTo(420.58348000000007,606.7103599999999,422.1094800000001,599.1820299999999,426.0771500000001,593.0780299999999);
+ctx.bezierCurveTo(426.0771500000001,593.0780299999999,430.5533700000001,586.16014,436.8609200000001,583.3115799999999);
+ctx.bezierCurveTo(436.8609200000001,583.3115799999999,484.5887000000001,566.7351399999999,489.04192000000006,571.6474699999999);
+ctx.bezierCurveTo(493.49514000000005,576.5597999999999,458.56281000000007,585.5822499999999,463.44603000000006,588.1255799999999);
+ctx.bezierCurveTo(463.44603000000006,588.1255799999999,475.1129200000001,596.9439099999998,472.46781000000004,621.05491);
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "rgba(0, 0, 0, 0)";
+ctx.strokeStyle = "#000000";
+ctx.lineWidth = 20.37454605102539;
+ctx.lineCap = "round";
+ctx.lineJoin = "round";
+ctx.miterLimit = 4;
+ctx.beginPath();
+ctx.moveTo(581.84259,635.47703);
+ctx.bezierCurveTo(605.9547,636.57303,667.3308099999999,646.43714,687.05892,651.91714);
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "rgba(0, 0, 0, 0)";
+ctx.strokeStyle = "#000000";
+ctx.lineWidth = 20.37454605102539;
+ctx.lineCap = "round";
+ctx.lineJoin = "round";
+ctx.miterLimit = 4;
+ctx.beginPath();
+ctx.moveTo(550.05848,705.62125);
+ctx.bezierCurveTo(573.0745900000001,706.71725,635.54681,734.1173600000001,662.94681,749.4614700000001);
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "rgba(0, 0, 0, 0)";
+ctx.strokeStyle = "#000000";
+ctx.lineWidth = 20.37454605102539;
+ctx.lineCap = "round";
+ctx.lineJoin = "round";
+ctx.miterLimit = 4;
+ctx.beginPath();
+ctx.moveTo(569.78648,573.0048);
+ctx.bezierCurveTo(601.5707,563.1408,692.53892,559.8528,712.26703,563.1408);
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "rgba(0, 0, 0, 0)";
+ctx.strokeStyle = "#000000";
+ctx.lineWidth = 20.37454605102539;
+ctx.lineCap = "round";
+ctx.lineJoin = "round";
+ctx.miterLimit = 4;
+ctx.beginPath();
+ctx.moveTo(3.1525932,710.00536);
+ctx.bezierCurveTo(-22.055518,715.48536,-79.047739,745.07747,-109.73585,772.47758);
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "rgba(0, 0, 0, 0)";
+ctx.strokeStyle = "#000000";
+ctx.lineWidth = 20.37454605102539;
+ctx.lineCap = "round";
+ctx.lineJoin = "round";
+ctx.miterLimit = 4;
+ctx.beginPath();
+ctx.moveTo(-34.111629,654.10914);
+ctx.bezierCurveTo(-62.607629,656.30114,-114.11985000000001,663.9731400000001,-137.13596,674.93325);
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "rgba(0, 0, 0, 0)";
+ctx.strokeStyle = "#000000";
+ctx.lineWidth = 20.37454605102539;
+ctx.lineCap = "round";
+ctx.lineJoin = "round";
+ctx.miterLimit = 4;
+ctx.beginPath();
+ctx.moveTo(-38.495629,586.15692);
+ctx.bezierCurveTo(-76.85574,575.1968,-157.95996,580.6768,-177.68807,589.44491);
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "rgba(0, 0, 0, 0)";
+ctx.strokeStyle = "#000000";
+ctx.lineWidth = 20.37454605102539;
+ctx.lineCap = "butt";
+ctx.lineJoin = "round";
+ctx.miterLimit = 4;
+ctx.beginPath();
+ctx.moveTo(-41.675629,439.32136);
+ctx.lineTo(-41.675629,566.34569);
+ctx.lineTo(-93.72685,566.34569);
+ctx.bezierCurveTo(-99.55329499999999,829.8689099999999,218.71792,826.24936,262.9917,825.16958);
+ctx.bezierCurveTo(307.81048,824.07647,646.49437,825.52791,621.62037,549.87069);
+ctx.lineTo(579.59726,549.87069);
+ctx.lineTo(577.44837,446.96191999999996);
+ctx.bezierCurveTo(501.82413999999994,478.74602999999996,96.42092599999995,476.58547,-41.67562900000007,439.32135999999997);
+ctx.closePath();
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "#d7d7d7";
+ctx.strokeStyle = "rgba(0, 0, 0, 0)";
+ctx.beginPath();
+ctx.moveTo(194.05837,466.43958);
+ctx.bezierCurveTo(194.05837,430.27146999999997,215.66548,237.52380999999997,227.72147999999999,221.08369999999996);
+ctx.lineTo(351.55826,226.78069999999997);
+ctx.bezierCurveTo(340.59815000000003,257.46880999999996,319.89015,411.05714,325.37015,469.14536);
+ctx.closePath();
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.save();
+ctx.fillStyle = "rgba(0, 0, 0, 0)";
+ctx.strokeStyle = "#000000";
+ctx.lineWidth = 20.37454605102539;
+ctx.lineCap = "butt";
+ctx.lineJoin = "round";
+ctx.miterLimit = 4;
+ctx.beginPath();
+ctx.moveTo(263.23037,219.17781);
+ctx.bezierCurveTo(209.02281,219.9517,155.01337,230.66592,105.40514999999999,251.41147);
+ctx.bezierCurveTo(124.77393,260.14114,142.75193,269.80447000000004,156.26259,277.19836);
+ctx.bezierCurveTo(101.54814999999999,287.66580999999996,23.972259999999977,334.24057999999997,-9.20318450000002,369.84013999999996);
+ctx.bezierCurveTo(-10.36285100000002,356.41981,-10.73551800000002,342.11868999999996,-10.39707300000002,327.57824999999997);
+ctx.bezierCurveTo(-68.96529500000003,384.63102999999995,-109.75229000000002,464.09403,-118.55874000000001,566.34569);
+ctx.lineTo(-41.675629000000015,566.34569);
+ctx.lineTo(-41.675629000000015,439.32147);
+ctx.bezierCurveTo(96.42092599999998,476.58558,501.82402999999994,478.74613999999997,577.4483700000001,446.96202999999997);
+ctx.lineTo(579.5972600000001,549.87069);
+ctx.lineTo(660.7781400000001,549.87069);
+ctx.bezierCurveTo(649.6127000000001,467.24692,617.1321400000002,400.28403,571.4791400000001,348.58980999999994);
+ctx.bezierCurveTo(571.2552600000001,356.94624999999996,570.9641400000002,365.08991999999995,570.2852600000001,372.94402999999994);
+ctx.bezierCurveTo(537.1098100000002,337.34457999999995,459.5339200000001,290.76980999999995,404.8194800000001,280.3023599999999);
+ctx.bezierCurveTo(416.6672600000001,273.81846999999993,432.09703000000013,265.6700299999999,448.7527000000001,257.85813999999993);
+ctx.bezierCurveTo(391.08781,231.15081,326.98737,218.2677,263.23037,219.17781);
+ctx.closePath();
+ctx.fill();
+ctx.stroke();
+ctx.restore();
+ctx.restore();
+ctx.restore();
+};
\ No newline at end of file
diff --git a/res/kitty.png b/res/kitty.png
new file mode 100644
index 0000000..369f1dd
Binary files /dev/null and b/res/kitty.png differ
diff --git a/res/kitty.svg b/res/kitty.svg
new file mode 100644
index 0000000..e0061d1
--- /dev/null
+++ b/res/kitty.svg
@@ -0,0 +1,184 @@
+
+
+
+
+
+
+
+ image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/others.html b/res/others.html
deleted file mode 100644
index 5882d1e..0000000
--- a/res/others.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
-
-
- Free Derby Scoreboard Software
-
-
-
-
-
- Free Derby Scoreboard Software
-
-
- This is a list of no-cost roller derby scoreboard software I have
- found. Mine is at the top, because I think it's the best. I might
- be wrong, though! Try the rest out and see for yourself.
-
-
-
-
- Name
- Source?
- Platform
- Windows
- Notes
-
-
-
- LADD Scoreboard
- YES
- JavaScript (web browser)
- 1
- Easy to operate, easy to read; also, I wrote it :)
-
-
-
- POÄNG (formerly QCRG Scoreboard )
- YES
- Adobe AIR
- 2
- Nice clean layout
-
-
-
- CRD Scoreboard
- YES
- Java
- 2
- Interesting cli/srv model allowing multiple operators on a LAN
-
-
-
- Derby Score
- YES
- Java
- 2
- Could use some visual polish, but I like the author's attitude
-
-
-
- Thor's Hammer
- no
- Windows
- 2
-
-
-
-
- JamTracker
- no
- Adobe AIR
- 2
- Busy layout
-
-
-
- Rinxter
- no?
- Windows
- 2
- If Oracle made a scoreboard, this would be it. It's massive : generates reports!
-
-
-
- DerbyBoard
- no
- Windows
- 2
- What an incredible waste of screen real estate! I hope you play somewhere very dark.
-
-
-
- Scoreboard Pro
- no
- Windows
- 2
- The author does not appear to have read WFTDA's rules.
-
-
-
- Source?
-
- Whether you can download and modify the source code. Important to
- many nerds like myself.
-
-
- Platform
-
- What you need to buy/install before you can run it.
-
-
- Windows
-
-
- 1
-
- Operator interacts directly with the image on the projector.
- What you see is what the audience sees.
-
- 2
-
- Separate interface for operator and audience, like an old-school
- 7-panel display scoreboard. What you see is a control panel;
- the audience sees something different.
-
-
-
-
-
-
-
- Neale Pickett <neale@woozle.org >
-
-
-
-
-
diff --git a/res/penalties.js b/res/penalties.js
deleted file mode 100644
index 19cef61..0000000
--- a/res/penalties.js
+++ /dev/null
@@ -1,161 +0,0 @@
-/***********************************
- * Penalties
- */
-function penalties (team) {
- var table = document.getElementById("penalties-" + team);
-
- var majors = table.getElementsByClassName("majors")[0];
- var sk8ers = table.getElementsByClassName("sk8ers")[0];
-
- var majdiv = majors.getElementsByTagName("div");
- var sk8div = sk8ers.getElementsByTagName("div");
-
- var ret = [];
-
- for (var i = 0; i < 20; i += 1) {
- ret.push([sk8div[i].text,
- majdiv[i].value || 0]);
- }
-
- return ret;
-}
-
-function penalties_save () {
- var ls = localStorage || {};
-
- var name_a = document.getElementById("name-a").innerHTML;
- var name_b = document.getElementById("name-b").innerHTML;
-
- var pen_a = JSON.stringify(penalties("a"));
- var pen_b = JSON.stringify(penalties("b"));
-
- ls["rdsb_penalties_a"] = pen_a;
- ls["rdsb_penalties_b"] = pen_b;
-
- ls["rdsb_roster " + name_a] = pen_a;
- ls["rdsb_roster " + name_b] = pen_b;
-}
-
-function penalties_setdiv (div, value) {
- if (div.text == undefined) {
- div.value = value;
- div.style.height = (value||0) + "em";
- div.innerHTML = value?value:"";
- } else {
- div.text = value;
- div.innerHTML = value?"":"•";
- for (var i in value) {
- var c = value[i];
- // XXX: use CSS "text-wrap: unrestricted" when supported
- div.innerHTML += c + " ";
- }
- }
-}
-
-function penalties_load (team, values) {
- var table = document.getElementById("penalties-" + team);
-
- var majors = table.getElementsByClassName("majors")[0];
- var sk8ers = table.getElementsByClassName("sk8ers")[0];
-
- var majdiv = majors.getElementsByTagName("div");
- var sk8div = sk8ers.getElementsByTagName("div");
-
- for (var i = 0; i < values.length; i += 1) {
- penalties_setdiv(sk8div[i], values[i][0]);
- penalties_setdiv(majdiv[i], values[i][2]);
- }
-}
-
-function penalties_setTeamName (team, name) {
- var ls = localStorage || {};
- var roster_in = ls["rdsb_roster " + name];
- var roster_out = [];
-
- if (roster_in) {
- roster_in = JSON.parse(roster_in);
- }
-
- for (var i = 0; i < 20; i += 1) {
- if (! roster_in) {
- roster_out.push(["", 0, 0]);
- } else {
- roster_out.push([roster_in[i][0], 0, 0])
- }
- }
- penalties_load(team, roster_out);
-}
-
-function penalties_click (event) {
- var element = event.currentTarget;
- var pops = element.parentNode;
- var div = element.getElementsByTagName("div")[0];
- var inc = event.shiftKey?-1:1;
- var val;
-
- if (pops.className == "majors") {
- val = ((div.value || 0) + inc + 9) % 9;
- } else if (state == SETUP) {
- val = prompt("Enter skater number", div.text);
- }
-
- if (val != undefined) {
- penalties_setdiv(div, val);
- penalties_save();
- }
-}
-
-// Remove penalties area if there are no players set
-function penalties_duck () {
- var pen = document.getElementById("penalties");
- var a = penalties("a");
- var b = penalties("b");
-
- for (var i = 0; i < 20; i += 1) {
- if (a[i][0] || b[i][0]) {
- return;
- }
- }
-
- pen.style.display = "none";
-}
-
-function penalties_init () {
- var ls = localStorage || {};
-
- // Populate ALL ROWS AT ONCE because I'm crazy like that.
- for (var j = 0; j < 2; j += 1) {
- var team = (j==0)?"a":"b";
-
- var table = document.getElementById("penalties-" + team);
- var majors = table.getElementsByClassName("majors")[0];
- var sk8ers = table.getElementsByClassName("sk8ers")[0];
-
- for (var i = 0; i < 20; i += 1) {
- var td;
- var div;
-
- var majdiv = document.createElement("div");
- td = document.createElement("td");
- td.onclick = penalties_click;
- td.appendChild(majdiv);
- majors.appendChild(td);
-
-
- div = document.createElement("div");
- div.text = "";
- div.appendChild(document.createTextNode("•"));
- td = document.createElement("td");
- td.onclick = penalties_click;
- td.appendChild(div);
- sk8ers.appendChild(td);
- }
- }
-
- if (ls.rdsb_penalties_a) {
- penalties_load("a", JSON.parse(ls.rdsb_penalties_a));
- }
- if (ls.rdsb_penalties_b) {
- penalties_load("b", JSON.parse(ls.rdsb_penalties_b));
- }
-}
diff --git a/res/scoreboard-explained.png b/res/scoreboard-explained.png
deleted file mode 100644
index 1c7a94a..0000000
Binary files a/res/scoreboard-explained.png and /dev/null differ
diff --git a/res/scoreboard.css b/res/scoreboard.css
index cfb63f7..7f327bb 100644
--- a/res/scoreboard.css
+++ b/res/scoreboard.css
@@ -1,53 +1,60 @@
@font-face {
- font-family: 'Magenta';
- src: url('Magenta.woff') format('woff');
- font-weight: normal;
- font-style: normal;
+ font-family: 'Ubuntu';
+ src: url('Ubuntu-Medium.ttf');
+ font-weight: normal;
+ font-style: normal;
}
@font-face {
- font-family: 'PermanentMarker';
- src: url('PermanentMarker.woff') format('woff');
- font-weight: normal;
- font-style: normal;
+ font-family: 'Ubuntu';
+ src: url('Ubuntu-Bold.ttf');
+ font-weight: bold;
+ font-style: normal;
}
body {
- background: url(bg.jpg) #222;
- background-size: 100% auto;
- font-size: 160px;
- color: #eee;
- margin: 0;
+ background: url(bg.jpg) #222;
+ background-size: 100% auto;
+ font-size: 160px;
+ color: #eee;
+ margin: 0;
+}
+
+input {
+ font: inherit;
+}
+
+input[readonly] {
+ color: inherit;
+ background: inherit;
+ border: inherit;
}
#scoreboard {
- cursor: default;
- font-family: sans-serif;
- font-weight: bold;
+ cursor: default;
+ font-family: Ubuntu, sans-serif;
}
#scoreboard p {
- margin: 0;
+ margin: 0;
}
#scoreboard *[id] {
- cursor: pointer;
- -moz-user-select: none;
- -khtml-user-select: none;
- user-select: none;
+ cursor: pointer;
+ user-select: none;
}
.left, .right {
- width: 2em;
- height: 100%;
- text-align: center;
- position: absolute;
- top: 0;
+ width: 2em;
+ height: 100%;
+ text-align: center;
+ position: absolute;
+ top: 0;
}
.left {
- left: 0;
+ left: 0;
}
.right {
- right: 0;
+ right: 0;
}
.center {
@@ -55,79 +62,103 @@ body {
}
.logo {
- max-width: 1.8em;
- max-height: 2em;
+ text-align: center;
}
+.logo img {
+ max-width: 1.8em;
+ max-height: 2em;
+ display: none;
+}
+
+.logo input {
+ top: 30%;
+ font-size: 10pt;
+ vertical-align: top;
+ max-height: 15pt;
+ border: none;
+}
+
+.setup {
+ background: rgba(0, 255,0, 0.3);
+}
+
+
.timeouts {
- position: absolute;
- font-size: 50%;
- bottom: 1em;
- color: #0f0;
+ position: absolute;
+ font-size: 50%;
+ bottom: 1em;
+ color: #0f0;
}
#timeouts-a {
- left: 0em;
+ left: 0em;
}
#timeouts-b {
- right: 0em;
+ right: 0em;
}
/* Jammer indicators */
#jammer-a, #jammer-b {
- font-family: monospace;
- position: absolute;
- bottom: 0em;
- color: #444;
+ font-family: monospace;
+ position: absolute;
+ bottom: 0em;
+ color: #444;
}
#jammer-a.lead, #jammer-b.lead, #jamtext, #periodtext {
- color: yellow;
+ color: yellow;
}
#jammer-a {
- left: 0.5em;
+ left: 0.5em;
}
#jammer-b {
- right: 0.5em;
+ right: 0.5em;
}
#jam, #period {
- text-align: center;
- background: #000;
- border-radius: 15px;
+ text-align: center;
+ font-weight: bold;
+ background: #000;
+ border-radius: 15px;
}
#period {
- position: absolute;
- top: 0;
- left: 50%;
- width: 3.4em;
- margin-left: -1.7em;
+ position: absolute;
+ top: 0;
+ left: 50%;
+ width: 3.4em;
+ margin-left: -1.7em;
}
#jam {
- position: absolute;
- bottom: 0em;
- left: 50%;
- width: 4em;
- margin-left: -2em;
+ position: absolute;
+ bottom: 0em;
+ left: 50%;
+ width: 3.5em;
+ margin-left: -1.75em;
}
-#jamtext, #periodtext {
- text-align: center;
- font-family: PermanentMarker, sans-serif;
- font-weight: normal;
- font-size: 75%;
+#jamtext, #periodtext, #preset {
+ text-align: center;
+ font-family: Ubuntu, sans-serif;
+ font-size: 75%;
- position: absolute;
- left: 50%;
- width: 5em;
- margin-left: -2.5em;
+ padding: 0.2em;
+ position: absolute;
+ left: 50%;
+ width: 5em;
+ margin-left: -2.7em;
+ z-index: -1;
}
#periodtext {
- top: 1.4em;
+ top: 1.4em;
+}
+
+#preset {
+ top: 40%;
}
#jamtext {
- bottom: 1.4em;
+ bottom: 1.4em;
}
#advert {
@@ -137,24 +168,24 @@ body {
}
.score {
- position: absolute;
- font-size: 1.2em;
- top: 50%;
- margin-top: -0.6em;
+ position: absolute;
+ font-size: 1.2em;
+ top: 50%;
+ margin-top: -0.6em;
}
#score-a {
- left: 0em;
+ left: 0em;
}
#score-b {
- right: 0em;
+ right: 0em;
}
#jamno {
- color: #0f0;
- position: absolute;
- font-size: 50%;
- bottom: 2.2em;
- right: 25%;
+ color: #0f0;
+ position: absolute;
+ font-size: 50%;
+ bottom: 2.2em;
+ right: 25%;
}
@@ -162,34 +193,46 @@ body {
* States timers can be in
*/
#jam.paused, #period.paused {
- color: #aaf;
+ color: #aaf;
}
#jam.lowtime, #period.lowtime {
- background: #f24;
+ background: #f24;
}
#jam.timeout {
- background: #044;
+ background: #044;
}
#jam.lineup {
- background: #060;
+ background: #060;
}
+#close, #prefs {
+ position: absolute;
+ top: 0;
+ right: 0;
+ height: 16px;
+ width: 16px;
+ opacity: 0.5;
+}
+
+#prefs {
+ top: inherit;
+ bottom: 0;
+}
/*
* Notices
*/
#notice {
- display: none;
- position: absolute;
- bottom: 1.3em;
- left: 50%;
- width: 4em;
+ display: none;
+ position: absolute;
+ bottom: 1.3em;
+ left: 50%;
+ width: 4em;
height: 3em;
- margin-left: -2em;
+ margin-left: -2em;
+ text-align: center;
}
-#notice embed {
- width: 100%;
+#notice img {
height: 100%;
-}
-
+}
\ No newline at end of file
diff --git a/res/scoreboard.html b/res/scoreboard.html
new file mode 100644
index 0000000..9fad9df
--- /dev/null
+++ b/res/scoreboard.html
@@ -0,0 +1,68 @@
+
+
+
+
+ Woozle Scoreboard
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/scoreboard.js b/res/scoreboard.js
index 0378de9..120a072 100644
--- a/res/scoreboard.js
+++ b/res/scoreboard.js
@@ -1,19 +1,19 @@
/*
- * LADD Roller Derby Scoreboard
- * Copyright © 2011 Neale Pickett
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
+ Woozle Roller Derby Scoreboard
+ Copyright © 2014 Neale Pickett
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
*/
/* You can only have one scoreboard per page. This limitation is mostly
@@ -24,17 +24,37 @@
* change in this file.
*/
-longnames = false;
-tenths = true;
+/* Times for various rulesets */
+var presets = [
+ ["WFTDA", 30 * 60 * 1000, 120 * 1000, 30 * 1000, 3],
+ ["USARS", 30 * 60 * 1000, 90 * 1000, 30 * 1000, 3],
+ ["RDCL", 15 * 60 * 1000, 60 * 1000, 30 * 1000, 3],
+ ["MADE", 15 * 60 * 1000, 90 * 1000, 30 * 1000, 1],
+ ["JRDA", 30 * 60 * 1000, 120 * 1000, 30 * 1000, 2]
+];
+var period_time;
+var jam_time;
+var lineup_time;
+var timeouts;
/* State names */
-var SETUP = 0; // !P 30:00 !J 2:00
-var JAM = 1; // P J 2:00
-var LINEUP = 2; // P J 1:00
-var TIMEOUT = 3; // !P J 1:00
+var SETUP = 0;
+var JAM = 1;
+var LINEUP = 2;
+var TIMEOUT = 3;
-var periodtext = ["Period 1", "Halftime", "Period 2", "Break"];
-var jamtext = ["Jam", "Lineup", "Timeout", "Setup"];
+var periodtext = [
+ chrome.i18n.getMessage("period1"),
+ chrome.i18n.getMessage("halftime"),
+ chrome.i18n.getMessage("period2"),
+ chrome.i18n.getMessage("timeToGame")
+];
+var jamtext = [
+ chrome.i18n.getMessage("jam"),
+ chrome.i18n.getMessage("lineup"),
+ chrome.i18n.getMessage("timeout"),
+ chrome.i18n.getMessage("setup")
+];
var period = 0;
var jamno = 0;
@@ -42,148 +62,180 @@ var state = SETUP;
var timer_updates = [];
function update() {
- for (i in timer_updates) {
- var u = timer_updates[i];
+ for (var i in timer_updates) {
+ var u = timer_updates[i];
- u();
- }
+ u();
+ }
+}
+
+function e(id) {
+ ret = document.getElementById(id);
+ if (! ret) {
+ return Array();
+ }
+ return ret;
}
// Create a timer on [element].
-// If [tenths] is true, show tenths of a second.
-// If [callback] is defined, call it when time runs out.
-function startTimer(element, tenths, callback) {
- var startTime;
- var running = false;
- var set_duration = 0;
- var duration = 0;
- var className;
+function startTimer(element) {
+ var startTime;
+ var running = false;
+ var set_duration = 0;
+ var duration = 0;
+ var className;
- // Re-calculate and update displayed time
- function refresh () {
- var remain = element.remaining();
- var min = Math.floor(Math.abs(remain / 60000));
- var sec = (Math.floor(Math.abs(remain / 100)) / 10) % 60;
+ // Heartbeat
+ function pulse() {
+ if (! running) {
+ element.className = className + " paused";
+ return;
+ }
+
+ refresh();
+ }
+
+ // Re-calculate and update displayed time
+ function refresh() {
+ var remain = Math.ceil(element.remaining() / 1000);
+ var min = Math.floor(Math.abs(remain) / 60);
+ var sec = Math.abs(remain) % 60;
+
+ // Set classes
+ if ((! className) && (remain <= 20)) {
+ element.className = "lowtime";
+ } else {
+ element.className = className;
+ }
- // Set classes
- element.className = className;
- if ((! className) && (remain <= 20000)) {
- element.className += " lowtime";
- }
- if (! running) {
- element.className += " paused";
- }
+ // Has the timer run out?
+ if ((set_duration > 0) && (remain <= 0)) {
+ duration = 0;
+ sec = 0;
+ element.stop();
+ }
- // Has the timer run out?
- if ((set_duration > 0) && (remain <= 0)) {
- duration = 0;
- sec = 0;
- running = false;
- if (callback) {
- callback();
- }
- }
+ sec = Math.ceil(sec);
+ // Zero-pad
+ if (sec < 10) {
+ sec = "0" + sec;
+ }
- // .toFixed() rounds, we want to truncate
- if (! tenths) {
- sec = Math.floor(sec);
- } else {
- sec = sec.toFixed(1);
- }
- // Zero-pad
- if (sec < 10) {
- sec = "0" + sec;
- }
+ var t = min + ":" + sec;
+ if (t != element.value) {
+ element.value = t;
+ }
+ }
+
+ function inputHandler() {
+ var t = element.value.split(":");
+ var sec = (Number(t[0]) * 60) + Number(t[1]);
+
+ if (isNaN(sec) || (sec <= 0) || (sec > (59 * 60))) {
+ // Ignore goofy values
+ return;
+ }
+
+ element.set(sec * 1000, className, true);
+ }
- var t = min + ":" + sec;
- if (t != element.innerHTML) {
- element.innerHTML = t;
- }
- }
+ // Return remaining time in milliseconds
+ element.remaining = function() {
+ if (running) {
+ var now = (new Date()).getTime();
+ return duration - (now - startTime);
+ } else {
+ return duration;
+ }
+ }
- // Return remaining time in milliseconds
- element.remaining = function() {
- if (running) {
- var now = (new Date()).getTime();
- return duration - (now - startTime);
- } else {
- return duration;
- }
- }
+ // Set timer to [d] milliseconds.
+ // Put element into class [cn], if set.
+ // If [stealth] is set, don't refresh
+ element.set = function(t, cn, stealth) {
+ startTime = (new Date()).getTime();
+ set_duration = t;
+ duration = t;
+ className = cn;
+
+ if (! stealth) {
+ refresh();
+ }
+ }
- // Set timer to [d] milliseconds.
- // Put element into class [cn], if set.
- element.set = function(t, cn) {
- startTime = (new Date()).getTime();
- set_duration = t;
- duration = t;
- className = cn;
- refresh();
- }
+ // Start timer
+ element.start = function() {
+ if (! running) {
+ startTime = (new Date()).getTime();
+ running = true;
+ }
+ refresh();
+ }
- // Start timer
- element.start = function() {
- if (! running) {
- startTime = (new Date()).getTime();
- running = true;
- }
- refresh();
- }
+ // Stop timer
+ element.stop = function() {
+ if (running) {
+ duration = element.remaining();
+ running = false;
+ }
+ }
- // Stop timer
- element.stop = function() {
- if (running) {
- duration = element.remaining();
- running = false;
- }
- refresh();
- }
+ element.readOnly = true;
+ element.addEventListener("input", inputHandler);
- timer_updates.push(refresh);
+ timer_updates.push(pulse);
}
// Transition state machine based on state
function transition(newstate) {
- var jt = e("jam");
- var pt = e("period");
- var jtext = e("jamtext");
- var jno = e("jamno");
+ var jt = e("jam");
+ var pt = e("period");
+ var jtext = e("jamtext");
+ var jno = e("jamno");
- if ((newstate == undefined) || (newstate == state)) {
- return;
- }
+ if ((newstate === undefined) || (newstate == state)) {
+ return;
+ }
- if ((state == SETUP) && window.penalties) {
- penalties_duck();
- }
+ state = newstate;
- state = newstate;
+ if (state == JAM) {
+ pt.start();
+ jt.set(jam_time);
+ jt.start();
+ jtext.innerHTML = jamtext[0];
+ jamno += 1;
+ jno.innerHTML = jamno;
+ pt.readOnly = true;
+ } else if (state == LINEUP) {
+ pt.start();
+ jt.set(lineup_time, "lineup");
+ jt.start();
+ jtext.innerHTML = jamtext[1];
+ pt.readOnly = true;
+ } else if (state == TIMEOUT) {
+ pt.stop();
+ if (pt.remaining() <= 0) {
+ pt.set(period_time);
+ }
+ jt.set(0, "timeout");
+ jt.start();
+ jtext.innerHTML = jamtext[2];
+ pt.readOnly = false;
+ }
- if (state == JAM) {
- pt.start();
- jt.set(120000);
- jt.start();
- jtext.innerHTML = jamtext[0];
- jamno += 1;
- jno.innerHTML = jamno;
- } else if (state == LINEUP) {
- pt.start();
- jt.set(30000, "lineup");
- jt.start();
- jtext.innerHTML = jamtext[1];
- } else if (state == TIMEOUT) {
- pt.stop();
- if (pt.remaining() <= 0) {
- pt.set(1800000);
- }
- jt.set(0, "timeout");
- jt.start();
- jtext.innerHTML = jamtext[2];
- }
-
- // Reset lead jammer indicators
- e("jammer-a").className = "";
- e("jammer-b").className = "";
+ // Reset lead jammer indicators
+ e("jammer-a").className = "";
+ e("jammer-b").className = "";
+
+ var setupElements = document.getElementsByClassName("setup")
+ for (var i = 0; i < setupElements.length; i += 1) {
+ var el = setupElements[i]
+
+ el.style.display = "none"
+ }
+
+ save();
}
@@ -192,387 +244,415 @@ function transition(newstate) {
* Notices
*/
-var notices = [
- false,
- '',
- '',
- '',
- '',
- '',
- '',
- '',
-];
+var notices = {
+ "banana": ' '
+};
var notice_timer;
function notice_expire() {
- var c = document.getElementById("notice");
+ var c = e("notice");
c.innerHTML = "";
c.style.display = "none";
}
function notice(n) {
- var c = document.getElementById("notice");
+ var c = e("notice");
- c.style.display = "block";
- if (notices[n]) {
- c.innerHTML = notices[n];
- clearTimeout(notice_timer);
- notice_timer = setTimeout(function() {notice_expire()}, 8000);
- } else {
- notice_expire();
- }
+ if (notices[n]) {
+ if (c.innerHTML != notices[n]) {
+ c.innerHTML = notices[n];
+ c.style.display = "block";
+ }
+ clearTimeout(notice_timer);
+ notice_timer = setTimeout(function() {notice_expire()}, 8000);
+ } else {
+ notice_expire();
+ }
}
-function e(id) {
- ret = document.getElementById(id);
- if (! ret) {
- return Array();
- }
- return ret;
-}
function score(team, points) {
- var te = document.getElementById("score-" + team);
- var ts = Number(te.innerHTML);
+ var te = e("score-" + team);
+ var ts = Number(te.innerHTML);
- ts += points;
- te.innerHTML = ts;
+ ts = Math.max(ts + points, 0);
+ te.innerHTML = ts;
}
/***********************************
* Event handlers
*/
-var logo = {a:-1, b:-1};
-
function leadJammer(team) {
- tgt = e("jammer-" + team);
- var on = ! tgt.className;
+ tgt = e("jammer-" + team);
+ var on = ! tgt.className;
- e("jammer-a").className = "";
- e("jammer-b").className = "";
- if (on) tgt.className = "lead";
+ e("jammer-a").className = "";
+ e("jammer-b").className = "";
+ if (on) tgt.className = "lead";
+}
+
+function changeLogo(team) {
+ // Holy cow, asynchronous events galore here
+ var element = e("img-" + team)
+
+ function setURL(file) {
+ element.src = URL.createObjectURL(file);
+ }
+
+ function loaded(entry) {
+ entry.file(setURL);
+ e("kitty-" + team).style.display = "none"
+ element.style.display = "inline"
+ }
+
+ chrome.fileSystem.chooseEntry(
+ {
+ "accepts": [{
+ "mimeTypes": ["image/*"]
+ }],
+ "acceptsAllTypes": false
+ },
+ loaded);
}
function handle(event) {
- var tgt = event.target || window.event.srcElement;
- var team = tgt.id.substr(tgt.id.length - 1);
- var adj = event.shiftKey?-1:1;
- var mod = (event.ctrlKey || event.altKey);
- var newstate;
+ var tgt = event.target || window.event.srcElement;
+ var team = tgt.id.substr(tgt.id.length - 1);
+ var adj = event.shiftKey?-1:1;
+ var mod = (event.ctrlKey || event.altKey);
+ var newstate;
- switch (tgt.id) {
- case "name-a":
- case "name-b":
- if (state == SETUP) {
- var tn = prompt("Enter team " + team + " name", tgt.innerHTML);
+ switch (tgt.id) {
+ case "load-a":
+ case "load-b":
+ changeLogo(team)
+ break
+ case "img-a":
+ case "img-b":
+ case "kitty-a":
+ case "kitty-b":
+ score(team, -adj);
+ break;
+ case "jammer-a":
+ case "jammer-b":
+ leadJammer(team);
+ break;
+ case "timeouts-a":
+ case "timeouts-b":
+ // Allow for timeouts > 3
+ var v = Number(tgt.innerHTML);
- if (tn) {
- tgt.innerHTML = tn;
- }
- if (window.penalties) {
- penalties_setTeamName(team, tn);
- }
- }
- break;
- case "logo-a":
- case "logo-b":
- if (state == SETUP) {
- if (mod) {
- var u = prompt("Enter URL to team " + team + " logo");
+ v -= adj;
+ if (v == -1) {
+ v = timeouts;
+ }
+ tgt.innerHTML = v;
+ break;
+ case "period":
+ if ((state == SETUP) || (state == TIMEOUT)) {
+ // Nothin'
+ } else {
+ newstate = TIMEOUT;
+ }
+ break;
+ case "periodtext":
+ var pt;
+ var ptl = periodtext.length;
- if (u) {
- tgt.src = u;
- }
- } else {
- var t, name;
-
- logo[team] = (teams.length + logo[team] + adj) % teams.length;
- t = teams[logo[team]];
-
- if (longnames) {
- name = t[2];
- } else {
- name = t[0];
- }
-
- e("name-" + team).innerHTML = name;
- tgt.src = "logos/" + t[1];
-
- if (window.penalties) {
- penalties_setTeamName(team, t[0]);
- }
- }
- } else {
- score(team, -adj);
- }
- break;
- case "jammer-a":
- case "jammer-b":
- leadJammer(team);
- break;
- case "timeouts-a":
- case "timeouts-b":
- // Allow for timeouts > 3
- var v = Number(tgt.innerHTML);
-
- v -= adj;
- if (v == -1) v = 3;
- tgt.innerHTML = v;
- break;
- case "period":
- if ((state == SETUP) || (state == TIMEOUT)) {
- var r = prompt("Enter new time for period clock", tgt.innerHTML);
- if (! r) return;
-
- var t = r.split(":");
- var sec = 0;
-
- if (t.length > 3) {
- tgt.innerHTML = "What?";
- return;
- }
-
- for (var i in t) {
- var v = t[i];
- sec = (sec * 60) + Number(v);
- }
-
- tgt.set(sec*1000);
- } else {
- newstate = TIMEOUT;
- }
- break;
- case "periodtext":
- var pt;
-
- if (mod) {
- pt = prompt("Enter new period indicator text", tgt.innerHTML);
- } else {
- var ptl = periodtext.length;
-
- period = (period + ptl + adj) % ptl;
- pt = periodtext[period];
- }
- if (pt) {
- tgt.innerHTML = pt;
- if (state == TIMEOUT) {
- jamno = 0;
- e("jamno").innerHTML = jamno;
- }
- }
- break;
- case "jam":
- if (state == JAM) {
- newstate = LINEUP;
- } else {
- newstate = JAM;
- }
- break;
- case "jamno":
- jamno -= adj;
- tgt.innerHTML = jamno;
- break;
- case "score-a":
- case "score-b":
- if (state == SETUP) {
- var s = prompt("Enter score for team " + team, tgt.innerHTML);
- if (s) {
- tgt.innerHTML = s;
- }
- } else {
- score(team, adj);
- }
- break;
- }
- transition(newstate);
+ period = (period + ptl + adj) % ptl;
+ pt = periodtext[period];
+ if (pt) {
+ tgt.innerHTML = pt;
+ if (state == TIMEOUT) {
+ jamno = 0;
+ e("jamno").innerHTML = jamno;
+ }
+ }
+ break;
+ case "jam":
+ if (state == JAM) {
+ newstate = LINEUP;
+ } else {
+ newstate = JAM;
+ }
+ break;
+ case "jamno":
+ jamno -= adj;
+ tgt.innerHTML = jamno;
+ break;
+ case "score-a":
+ case "score-b":
+ if (state == SETUP) {
+ e(tgt.id).innerHTML = 0;
+ } else {
+ score(team, adj);
+ }
+ break;
+ case "preset":
+ load_preset(+1);
+ break;
+ case "close":
+ window.close();
+ break;
+ }
+ transition(newstate);
}
function key(event) {
- var e = event || window.event;
- var c = String.fromCharCode(e.which || e.keyCode || 0);
- var newstate;
+ var e = event || window.event;
+ var k = e.which || e.keyCode || 0;
+ var c;
+ var newstate;
- switch (c) {
- case " ":
- if (state == JAM) {
- newstate = LINEUP;
- } else {
- newstate = JAM;
- }
- break;
- case "t":
- newstate = TIMEOUT;
- break;
- case "a":
- case "[":
- score('a', 1);
- break;
- case "b":
- case "]":
- score('b', 1);
- break;
- case "A":
- case "{":
- score('a', -1);
- break;
- case "B":
- case "}":
- score('b', -1);
- break;
- case ",":
- leadJammer('a');
- break;
- case ".":
- leadJammer('b');
- break;
- case "1":
- case "2":
- case "3":
- case "4":
- case "5":
- case "6":
- case "7":
- case "8":
- case "9":
- case "0":
- var n = Number(c);
+ switch (k) {
+ case 32:
+ c = " ";
+ break;
+ case 38:
+ c = "up";
+ break;
+ case 40:
+ c = "down";
+ break;
+ case 188:
+ c = ",";
+ break;
+ case 190:
+ c = ".";
+ break;
+ case 191:
+ c = "/";
+ break;
+ case 219:
+ c = e.shiftKey ? "{" : "[";
+ break;
+ case 221:
+ c = e.shiftKey ? "}" : "]";
+ break;
+ case 222:
+ c = e.shiftKey ? "\"" : "'";
+ break;
+ default:
+ if ((k >= 48) && (k <= 90)) {
+ c = String.fromCharCode(k);
+ if (! e.shiftKey) {
+ c = c.toLowerCase();
+ }
+ } else {
+ c = null;
+ }
+ break;
+ }
- window.notice(n);
- }
+ bige = e;
- transition(newstate);
+ switch (c) {
+ case "up":
+ if ((state == TIMEOUT) || (state == SETUP)) {
+ var pt = e("period");
+ var rem = pt.remaining();
+ pt.set(rem + 1000);
+ }
+ break;
+ case "down":
+ if ((state == TIMEOUT) || (state == SETUP)) {
+ var pt = e("period");
+ var rem = pt.remaining();
+ pt.set(rem - 1000);
+ }
+ break;
+ case " ":
+ if (state == JAM) {
+ newstate = LINEUP;
+ } else {
+ newstate = JAM;
+ }
+ break;
+ case "t":
+ newstate = TIMEOUT;
+ break;
+ case "a":
+ case "[":
+ score('a', 1);
+ break;
+ case "'":
+ case "]":
+ score('b', 1);
+ break;
+ case "z":
+ case "{":
+ score('a', -1);
+ break;
+ case "/":
+ case "}":
+ score('b', -1);
+ break;
+ case ",":
+ leadJammer('a');
+ break;
+ case ".":
+ leadJammer('b');
+ break;
+ case "g":
+ window.notice("banana");
+ break;
+ }
+
+ transition(newstate);
}
-function get(k, d) {
- if (! window.localStorage) {
- return d;
- } else {
- var v = window.localStorage["rdsb_" + k];
- if (v == undefined) {
- return d;
- }
- return v;
- }
-}
-
-function store(k, v) {
- if ((v == undefined) || ! window.localStorage) {
- return;
- } else {
- localStorage["rdsb_" + k] = v;
- }
-}
function save() {
- if (window.penalties_save) {
- penalties_save();
- }
- store("period_clock", e("period").remaining());
- store("name_a", e("name-a").innerHTML);
- store("name_b", e("name-b").innerHTML);
- store("logo_a", e("logo-a").src);
- store("logo_b", e("logo-b").src);
- store("score_a", e("score-a").innerHTML);
- store("score_b", e("score-b").innerHTML);
- store("timeout_a", e("timeouts-a").innerHTML);
- store("timeout_b", e("timeouts-b").innerHTML);
- store("jamno", jamno);
- store("period", period);
+ chrome.storage.local.set(
+ {
+ "preset": e("preset").innerHTML,
+ "score_a": e("score-a").innerHTML,
+ "score_b": e("score-b").innerHTML,
+ "timeouts_a": e("timeouts-a").innerHTML,
+ "timeouts_b": e("timeouts-b").innerHTML,
+ "period_clock": e("period").remaining(),
+ }
+ );
}
-
-function iecheck() {
- // If it's IE, it's got to be at least 7
- var ua = navigator.userAgent;
- var ie = ua.indexOf("MSIE ");
- if (ie == -1) {
- // Not IE
- return;
- } else {
- var n = parseFloat(ua.substring(ie + 5, ua.indexOf(";", ie)));
- if (n < 7) {
- alert("Your browser is too old to run the Woozle scoreboard.\nYou can use Firefox, Chrome, Opera, or Internet Explorer 7 and up.");
- }
- }
+function load_preset(preset_name) {
+ var inc = false;
+ var pn = 0;
+
+ if (preset_name == +1) {
+ preset_name = e("preset").innerHTML;
+ inc = true;
+ }
+
+ for (var i in presets) {
+ if (presets[i][0] == preset_name) {
+ pn = Number(i);
+ break;
+ }
+ }
+ if (inc) {
+ pn = (pn + 1) % presets.length;
+ }
+ preset_name = presets[pn][0];
+ period_time = presets[pn][1];
+ jam_time = presets[pn][2];
+ lineup_time = presets[pn][3];
+ timeouts = presets[pn][4];
+
+ e("preset").innerHTML = preset_name;
+ e("jam").set(jam_time);
+ e("period").set(period_time);
+ e("timeouts-a").innerHTML = timeouts;
+ e("timeouts-b").innerHTML = timeouts;
+ e("score-a").innerHTML = 0;
+ e("score-b").innerHTML = 0;
+}
+
+function load() {
+ function load_cb(state) {
+ load_preset(state.preset);
+
+ e("period").set((state.period_clock >= 0) ? state.period_clock : period_time);
+
+ e("score-a").innerHTML = state.score_a;
+ e("score-b").innerHTML = state.score_b;
+
+ e("timeouts-a").innerHTML = (state.timeouts_a >= 0) ? state.timeouts_a : timeouts;
+ e("timeouts-b").innerHTML = (state.timeouts_b >= 0) ? state.timeouts_b : timeouts;
+
+ }
+
+ chrome.storage.local.get({
+ "preset": presets[0][0],
+ "period_clock": -1,
+ "score_a": 0,
+ "score_b": 0,
+ "timeouts_a": -1,
+ "timeouts_b": -1
+ }, load_cb);
+}
+
+
+function ei(name) {
+ el = e(name);
+ if (el.addEventListener) {
+ el.addEventListener("click", handle, false);
+ }
+ return el;
}
function start() {
- resize();
- iecheck();
+ resize();
+ load();
- var p = document.getElementById("period");
- var j = document.getElementById("jam");
- var c;
+ ei("logo-a");
+ ei("logo-b");
+ ei("score-a");
+ ei("score-b")
+ ei("jammer-a");
+ ei("jammer-b");
+ ei("timeouts-a");
+ ei("timeouts-b");
+ ei("period");
+ ei("jam");
+ ei("prefs");
+ ei("close");
+ ei("preset");
+
+ e("color-a").addEventListener("change", function() {rekitty("a")}, false);
+ e("color-b").addEventListener("change", function() {rekitty("b")}, false);
+ ei("periodtext").innerHTML = periodtext[period];
+ ei("jamtext").innerHTML = jamtext[3];
+ transition();
- // IE8 doesn't have localStorage for file:// URLs :<
- e("name-a").innerHTML = get("name_a", "Home");
- e("name-b").innerHTML = get("name_b", "Vis");
- e("logo-a").src = get("logo_a", "logos/black.png");
- e("logo-b").src = get("logo_b", "logos/white.png");
- e("score-a").innerHTML = get("score_a", 0);
- e("score-b").innerHTML = get("score_b", 0);
- e("timeouts-a").innerHTML = get("timeout_a", 3);
- e("timeouts-b").innerHTML = get("timeout_b", 3);
- period = Number(get("period", 0));
- jamno = Number(get("jamno", 0));
+
- if (window.localStorage) {
- save_itimer = setInterval(save, 1000);
- }
-
- if (window.penalties) {
- penalties_init();
- }
+ var p = e("period");
+ startTimer(p);
+ p.readOnly = false;
- e("periodtext").innerHTML = periodtext[period];
- e("jamtext").innerHTML = jamtext[3];
- transition();
+ var j = e("jam");
+ startTimer(j);
- c = Number(get("period_clock", 1800000));
- startTimer(p);
- p.set(c);
+ update_itimer = setInterval(update, 200); // 5 times a second
- var j = document.getElementById("jam");
- startTimer(j, window.tenths);
- j.set(120000);
-
- save_timer = setInterval(save, 1000);
- update_itimer = setInterval(update, 33);
+}
+function rekitty(team) {
+ var i = e("img-" + team)
+ var k = e("kitty-" + team)
+ var color = e("color-" + team).value
+
+ i.style.display = "none"
+ k.style.display = "inline"
+ kitty(k.getContext("2d"), color)
}
function resize() {
- var b = document.getElementsByTagName("body")[0];
- var w, h;
-
- // Internet Explorer makes everything a pain in the ass
- if (window.innerWidth) {
- w = window.innerWidth;
- h = window.innerHeight;
- } else if (document.documentElement && document.documentElement.clientWidth) {
- w = document.documentElement.clientWidth;
- h = document.documentElement.clientHeight;
- } else if (document.body) {
- w = document.body.clientWidth;
- h = document.body.clientHeight;
- } else {
- // Punt
- w = 800;
- h = 600;
- }
-
- w /= 7;
- h /= 5;
+ var w = window.innerWidth / 7
+ var h = window.innerHeight / 5
+ var fs = Math.min(w, h)
- var fs = Math.min(w, h);
-
- b.style.fontSize = fs + 'px';
+ document.body.style.fontSize = Math.min(w, h) + 'px'
+
+ // Now do kitty canvases
+ var kw = fs * 1.8
+ var kh = kw * 0.6883
+
+ var kitties = document.getElementsByClassName("kitty")
+ for (var i = 0; i < kitties.length; i += 1) {
+ k = kitties[i]
+ k.width = kw
+ k.height = kh
+ }
+ rekitty("a")
+ rekitty("b")
}
window.onload = start;
-document.onkeypress = key; // IE requires document, not window
+document.onkeydown = key; // IE requires document, not window
window.onresize = resize;
diff --git a/res/screenshot.png b/res/screenshot.png
deleted file mode 100644
index b79867e..0000000
Binary files a/res/screenshot.png and /dev/null differ
diff --git a/res/style.css b/res/style.css
deleted file mode 100644
index 424b563..0000000
--- a/res/style.css
+++ /dev/null
@@ -1,41 +0,0 @@
-@font-face {
- font-family: 'PermanentMarker';
- src: url('PermanentMarker.woff') format('woff');
- font-weight: normal;
- font-style: normal;
-}
-
-body {
- background: #222 url(bg.jpg);
- background-size: 100% auto;
- color: #eee;
- max-width: 40em;
- margin: auto auto;
-}
-h1 {
- color: #fd8;
- font-family: PermanentMarker, fantasy, sans-serif;
- font-size-adjust: 1.0;
-}
-h2 {
- font-family: sans-serif;
-}
-dt {
- font-size: 120%;
- font-weight: bold;
-}
-a {
- color: yellow;
-}
-caption {
- font-size: 33%;
- font-family: default;
-}
-
-#screenshot {
- text-align: center;
-}
-
-#screenshot img {
- border: solid black 4px;
-}
diff --git a/res/todo.txt b/res/todo.txt
deleted file mode 100644
index 9241dd3..0000000
--- a/res/todo.txt
+++ /dev/null
@@ -1,2 +0,0 @@
-* When period ends and jam timer is toggled, period clock should not count up
-* Auto-scale (3-digit score wrapped in Taos)
diff --git a/res/usage.html b/res/usage.html
deleted file mode 100644
index c467782..0000000
--- a/res/usage.html
+++ /dev/null
@@ -1,223 +0,0 @@
-
-
-
-
- Using the LADD Roller Derby Scoreboard
-
-
-
-
- Using the LADD Roller Derby Scoreboard
-
-
-
-
- If you don't like reading manuals, just start clicking on things;
- it's supposed to be easy to figure out.
-
-
-
- Space Bar
- Switch between Jam and Rotation
-
- T
- Enter timeout
-
- A / Shift-A
- Add / subtract a point on the left
-
- B / Shift-B
- Add / subtract a point on the right
-
- F5
- Enter Setup mode
-
-
- Setup
-
-
-
- When the state indicator says "Setup", you can click on almost
- anything to change it.
-
-
- Set the logo before you change the team name.
-
-
- If your team's logo and name isn't in the
- list , please email them to me so I can add them.
-
- Reload the page (click "Reload" or type F5) to get back to Setup
- mode. Scores, timeouts, and period clock time are all saved.
-
-
- Type Space Bar or click the jam clock to begin the first jam.
-
-
-
-
- Running Jams
-
-
-
- Press Space Bar or click the jam clock to switch between 2:00
- jams and 0:30 rotations.
-
-
- Type "A" or "B" to add points to a team's score. You can also
- click a score to add a point.
-
-
- Type "Shift+A" or "Shift+B" to remove points from a team's
- score. You can also click a team logo to remove a point.
-
-
-
-
- Timeouts
-
-
-
- Type "T" or click the period clock to enter into a timeout.
-
-
-
- Click a team's timeout count to remove one from it. If it's at
- 0, click it to reset it to 3.
-
-
-
- Click the period clock during a timeout to change the time left
- in the period.
-
-
-
- Type Space Bar or click the jam clock to exit timeout mode and
- start the next jam.
-
-
-
-
- Periods
-
-
-
- Go into Timeout mode to re-set the period clock to 30:00. Click
- it to change it to a different time.
-
-
- Click the period indicator to cycle between "Period 1",
- "Halftime", "Period 2", and "Break".
-
-
-
-
- Other cases
-
-
- Halftime / Double-header break
-
-
- Type "T" to enter timeout mode.
- Click the period indicator until it says "Halftime" or
- "Break"
- Click the period clock.
- Enter the duration of the break.
- Type Space Bar to start counting down.
- It's okay to let the jam clock reach 0:00.
-
-
-
- 20-minute periods
-
-
- During Setup or Timeout, click the period clock.
- Enter "20:00" for the new time.
- Click the period indicator until it displays the
- right period.
-
-
-
-
-
- Advanced Tips
-
-
-
- Hold down the "Shift" key to make counters, logos, etc. go the
- other direction.
-
-
- Hold down the "Ctrl" or "Alt" key while clicking a team logo in
- Setup mode to provide a URL.
-
-
- Hold down the "Ctrl" or "Alt" key while clicking the period
- indicator to change it to any text.
-
-
- Timeouts can exceed three by clicking them while holding the
- "Shift" key.
-
-
- You can leave off minutes or seconds if they're zero: "30:" is
- the same as "30:00", and "19" is the same as "0:19".
-
-
- If part of the scoreboard changes background color, click
- (without shift) somewhere on the background to get it back to
- normal. It changed color because your browser was selecting
- that part of the page for copy and paste!
-
-
-
-
- Customizing
-
- If you use this, I want to add your logo and the logos of the
- teams you play to the included set of
- logos .
-
-
-
- The scoreboard is written in HTML5, CSS, and JavaScript, so a web
- designer should be able to season to taste. Send me what you come
- up with, I want to see it!
-
-
-
- If you have problems
-
- If something goes wrong, please email me (link below) with as much
- detail as you can remember, and I'll try to fix it for you and
- everybody else. For example:
-
-
-
- I clicked the period timer during a timeout and the Team A logo
- turned into a photo of a burrito.
-
-
-
- Enjoy!
- Neale Pickett <neale@woozle.org>
-
-
-
diff --git a/scoreboard.html b/scoreboard.html
deleted file mode 100644
index 649b30f..0000000
--- a/scoreboard.html
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
-
- LADD Scoreboard
-
-
-
-
-
-
-
-
-
-
- 0
- ★
- -
-
-
-
- --:--
-
- -:--.-
-
-
-
-
-
- 0
- ★
- -
-
-
-
-
-
-
-