Compare commits

..

No commits in common. "1353908a765c02e0f089a7fe3dbdf6c7b35c0d9b" and "42e2c79e0817ca6cb8d626de9f53cb4b3b5d934c" have entirely different histories.

4 changed files with 1356 additions and 2467 deletions

View File

@ -1,66 +1,20 @@
# WolfChart v2.3
by Ballantyne de Wolf, Offspring Digital
# WolfChart v1.6
by Ballantyne de Wolf and Offspring Digital
This is professional optometrist/optician/ophthalmologist tool for sight testing. It cannot be used safely by the general public.
This is professional optometrist/optician/ophthalmologist tool for measuring visual acuity. I cannot be used safely by the general public.
If you have any concerns about your vision or eyes, consult a qualified professional.
Now that's out of the way, the objectives are:
1. Clinically relevant, scientifically supported sight testing tools, in the widest possible range of clinical and research settings.
1. Clinically relevant, scientifically supported visual acuity measurement in the widest possible range of clinical settings
2. Open source with GNU licence
3. Can be used on a wide variety of screen hardware
3. Customisable optotypes and alphabets to come eg Arabic, Hebrew, Chinese, Thai, Cyrillic etc
3. Customisable optotypes and alphabets to come eg Hebrew, Chinese, Thai, Cyrillic etc
Ver2.3
- Bug fixes
- guide dots on V charts hide and show behaviour fixed
- shuffle and duochrome disabled in single and column modes
-
- Additions
- Experimental optotypes in Chinese, Arabic and Hebrew
- Removed the Man from Shapes5, leaving 5 shapes in use, and set out alphabet to work better vertically
Ver2.2
- Bug fixes
- moved SVG transforms to css transforms. Safari doesn't implement SVG transform, all browsers implement SVG.css transform. Means have to add units
- fixed badly-written rotate90 function, also not working on Safari
- Rejigged Snellen BS4724 6/6 and 6/5 lines to get rid of an FU
- fixed sidebar controls not responding to nav links
- fixed text-decoration in nav-button-div a
- Additions
- characterClick now cycles through: mask one letter > mask column of letters > show all >
Ver2.1
- Now displays charts in 4 categories, using direction buttons and keys to navigate
- Paging up and down the letter chart now done by showing and hiding fullscreen pages, rather than scrolling a larger-than-fullscreen page
- Right hand sidebar containing controls
- Chart keeps track of your usage, offering your most-used chart on key strokes and nav buttons
- Fixed viewport - now uses document.documentwindow.clientHeight and a trimmed window.innerWidth at all times
- Single charts have spacebar/onclick/button function to eg zoom
- Removed colour pickers, replaced with text, preset buttons and hue-only sliders for filter tests
- Various improvements under bonnet
- Switched off PWA features like manifest and sw.js - will maybe bring them back later.
- Versioned as X.y in localStorage
Ver1.8
- fixed bug of bg colour not stored on first use.
- added coloured dots at 6/4.8(20/16,-0.1,1.1, normal VA) and 6/12(20/40,0.3,0.5, legal VA).
- did some code cleaning
Ver1.7
- added colour picker for background that defaults to white. This is maybe only useful in a research environment.
- added Vanishing Sloan optotype/Vanishing ETDRS alphabet.When selected, body background colour is same as optotype colour but 0.5 opacity. Used jquery.not() to exempt white filled elements from optotype color. Body bg reverts to stored with all other optotypes.
- Added prototype Shapes optotype
- Set color of scoreBox text to be optotype color with opacity 1, so that it will always be the same or more visible than the optotype itself.
- thinking of replacing all the fills in the svg raw materials section with classes and then using jquery to fill. Could be more flexible that way?
- simplified css in .duo to try and eliminate white gaps in duochrome backgrounds.
Ver1.6
- subtense array now to 3 decimal places, enabling
- improved scoring for Actual Numerators - fractional notations are rounded to 0.1m or 0.5ft and the / is replaced by a ! when Actual is selected.
- improved scoring for Actual numerators - rounding previously made the numerator too complex and denominator different if using Actual vs Standard numerator
- cleaned up some superfluous code lines in this area.
- updated help topics
- changed the Snellen R to try and make it more readable - in the field it was proving less readable than the other Snellens. Made the oblique stem more vertical.
Ver1.5

3501
index.htm

File diff suppressed because one or more lines are too long

52
manifest.json Normal file
View File

@ -0,0 +1,52 @@
{
"name": "WolfChart v1.5",
"short_name": "WolfChart",
"theme_color": "#86c7ef",
"background_color": "#86c7ef",
"display": "fullscreen",
"scope": "/",
"start_url": "/test_index.htm",
"icons": [
{
"src": "images/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "images/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "images/icons/icon-128x128.png",
"sizes": "128x128",
"type": "image/png"
},
{
"src": "images/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "images/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "images/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "images/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "images/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"splash_pages": null
}

198
sw.js Normal file
View File

@ -0,0 +1,198 @@
"use strict";
//console.log('WORKER: executing.');
/* A version number is useful when updating the worker logic,
allowing you to remove outdated cache entries during the update.
*/
var version = 'v1::';
/* These resources will be downloaded and cached by the service worker
during the installation process. If any resource fails to be downloaded,
then the service worker won't be installed either.
*/
var offlineFundamentals = [
'test_index.htm',
'manifest.json'
];
/* The install event fires when the service worker is first installed.
You can use this event to prepare the service worker to be able to serve
files while visitors are offline.
*/
self.addEventListener("install", function(event) {
//console.log('WORKER: install event in progress.');
/* Using event.waitUntil(p) blocks the installation process on the provided
promise. If the promise is rejected, the service worker won't be installed.
*/
event.waitUntil(
/* The caches built-in is a promise-based API that helps you cache responses,
as well as finding and deleting them.
*/
caches
/* You can open a cache by name, and this method returns a promise. We use
a versioned cache name here so that we can remove old cache entries in
one fell swoop later, when phasing out an older service worker.
*/
.open(version + 'fundamentals')
.then(function(cache) {
/* After the cache is opened, we can fill it with the offline fundamentals.
The method below will add all resources in `offlineFundamentals` to the
cache, after making requests for them.
*/
return cache.addAll(offlineFundamentals);
})
.then(function() {
//console.log('WORKER: install completed');
})
);
});
/* The fetch event fires whenever a page controlled by this service worker requests
a resource. This isn't limited to `fetch` or even XMLHttpRequest. Instead, it
comprehends even the request for the HTML page on first load, as well as JS and
CSS resources, fonts, any images, etc.
*/
self.addEventListener("fetch", function(event) {
//console.log('WORKER: fetch event in progress.');
/* We should only cache GET requests, and deal with the rest of method in the
client-side, by handling failed POST,PUT,PATCH,etc. requests.
*/
if (event.request.method !== 'GET') {
/* If we don't block the event as shown below, then the request will go to
the network as usual.
*/
//console.log('WORKER: fetch event ignored.', event.request.method, event.request.url);
return;
}
/* Similar to event.waitUntil in that it blocks the fetch event on a promise.
Fulfillment result will be used as the response, and rejection will end in a
HTTP response indicating failure.
*/
event.respondWith(
caches
/* This method returns a promise that resolves to a cache entry matching
the request. Once the promise is settled, we can then provide a response
to the fetch request.
*/
.match(event.request)
.then(function(cached) {
/* Even if the response is in our cache, we go to the network as well.
This pattern is known for producing "eventually fresh" responses,
where we return cached responses immediately, and meanwhile pull
a network response and store that in the cache.
Read more:
https://ponyfoo.com/articles/progressive-networking-serviceworker
*/
var networked = fetch(event.request)
// We handle the network request with success and failure scenarios.
.then(fetchedFromNetwork, unableToResolve)
// We should catch errors on the fetchedFromNetwork handler as well.
.catch(unableToResolve);
/* We return the cached response immediately if there is one, and fall
back to waiting on the network as usual.
*/
//console.log('WORKER: fetch event', cached ? '(cached)' : '(network)', event.request.url);
return cached || networked;
function fetchedFromNetwork(response) {
/* We copy the response before replying to the network request.
This is the response that will be stored on the ServiceWorker cache.
*/
var cacheCopy = response.clone();
//console.log('WORKER: fetch response from network.', event.request.url);
caches
// We open a cache to store the response for this request.
.open(version + 'pages')
.then(function add(cache) {
/* We store the response for this request. It'll later become
available to caches.match(event.request) calls, when looking
for cached responses.
*/
return cache.put(event.request, cacheCopy);
})
.then(function() {
//console.log('WORKER: fetch response stored in cache.', event.request.url);
});
// Return the response so that the promise is settled in fulfillment.
return response;
}
/* When this method is called, it means we were unable to produce a response
from either the cache or the network. This is our opportunity to produce
a meaningful response even when all else fails. It's the last chance, so
you probably want to display a "Service Unavailable" view or a generic
error response.
*/
function unableToResolve () {
/* There's a couple of things we can do here.
- Test the Accept header and then return one of the `offlineFundamentals`
e.g: `return caches.match('/some/cached/image.png')`
- You should also consider the origin. It's easier to decide what
"unavailable" means for requests against your origins than for requests
against a third party, such as an ad provider.
- Generate a Response programmaticaly, as shown below, and return that.
*/
//console.log('WORKER: fetch request failed in both cache and network.');
/* Here we're creating a response programmatically. The first parameter is the
response body, and the second one defines the options for the response.
*/
return new Response('<h1>Service Unavailable</h1>', {
status: 503,
statusText: 'Service Unavailable',
headers: new Headers({
'Content-Type': 'text/html'
})
});
}
})
);
});
/* The activate event fires after a service worker has been successfully installed.
It is most useful when phasing out an older version of a service worker, as at
this point you know that the new worker was installed correctly. In this example,
we delete old caches that don't match the version in the worker we just finished
installing.
*/
self.addEventListener("activate", function(event) {
/* Just like with the install event, event.waitUntil blocks activate on a promise.
Activation will fail unless the promise is fulfilled.
*/
//console.log('WORKER: activate event in progress.');
event.waitUntil(
caches
/* This method returns a promise which will resolve to an array of available
cache keys.
*/
.keys()
.then(function (keys) {
// We return a promise that settles when all outdated caches are deleted.
return Promise.all(
keys
.filter(function (key) {
// Filter by keys that don't start with the latest version prefix.
return !key.startsWith(version);
})
.map(function (key) {
/* Return a promise that's fulfilled
when each outdated cache is deleted.
*/
return caches.delete(key);
})
);
})
.then(function() {
//console.log('WORKER: activate completed.');
})
);
});