download flashcards

This commit is contained in:
Nicky Case 2018-09-30 12:54:38 -04:00
parent 44a7ba4116
commit 9c772e3c1d
6 changed files with 12096 additions and 0 deletions

View File

@ -48,6 +48,10 @@
<sim x=80 y=0 w=440 h=300 src="sims/singlecard/?card=test&refresh=yes"></sim>
</panel>
<panel w=600 h=400 bg="#fff">
<sim x=0 y=0 w=600 h=400 src="sims/downloads/all.html"></sim>
</panel>
<!-- - - - - - - - - - -->
@ -69,6 +73,61 @@
</div>
</span>
<!--
TO TEST DOWNLOADING OF ALL THE CARDS
-->
<span id="flashcard_sci_a_front">
<div class="fcard_center" style="height:2.5em">
여보세요
Здравствуйте
</div>
</span>
<span id="flashcard_sci_a_back">
<div class="fcard_bg" src="pics/fcards0.png" sx=400 sy=0></div>
<div style="position: absolute; width: 250px; top: 60px; right: 0; line-height: 1.1em;">
你好
こんにちは
</div>
</span>
<span id="flashcard_mitochondria_7_front">
<div class="fcard_bg" src="pics/fcards_ch2.png" sx=400 sy=960 style="top:40px"></div>
<div class="fcard_center" style="font-size: 35px; height: 220px;">
According to Endosymbiotic Theory, mitochondria arose around
<span class="underline">____</span> years ago
</div>
</span>
<span id="flashcard_mitochondria_7_back">
<div class="fcard_center" style="height:1.5em">
~1.5 billion years ago
</div>
</span>
<span id="flashcard_mitochondria_8_front">
<div class="fcard_bg" src="pics/fcards_ch2.png" sx=400 sy=960 style="top:40px"></div>
<div class="fcard_center" style="font-size: 37px; height: 220px;">
According to Endosymbiotic Theory, mitochondria first arose when...
</div>
</span>
<span id="flashcard_mitochondria_8_back">
<div class="fcard_bg" src="pics/fcards_ch2.png" sx=0 sy=1440></div>
<div class="fcard_center" style="height:230px">
when a prokaryote was eaten by another cell
</div>
</span>
<span id="flashcard_sci_c_front">
<div class="fcard_center" style="height:3.4em">
The Forgetting Curve (<i>with</i> optimally-spaced recalls) looks like...
</div>
</span>
<span id="flashcard_sci_c_back">
<div class="fcard_bg" src="pics/fcards0.png" sx=400 sy=240></div>
<div style="position: absolute; width: 360px; top: 120px; left: 20px; font-size:20px; line-height: 1.1em;">
(note: the gaps between recalls <i>increase</i> in length)
</div>
</span>
</div>

247
sims/downloads/FileSaver.js Normal file
View File

@ -0,0 +1,247 @@
/*! FileSaver.js
* A saveAs() FileSaver implementation.
* 2014-01-24
*
* By Eli Grey, http://eligrey.com
* License: X11/MIT
* See LICENSE.md
*/
/*global self */
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
var saveAs = saveAs
// IE 10+ (native saveAs)
|| (typeof navigator !== "undefined" &&
navigator.msSaveOrOpenBlob && navigator.msSaveOrOpenBlob.bind(navigator))
// Everyone else
|| (function(view) {
"use strict";
// IE <10 is explicitly unsupported
if (typeof navigator !== "undefined" &&
/MSIE [1-9]\./.test(navigator.userAgent)) {
return;
}
var
doc = view.document
// only get URL when necessary in case BlobBuilder.js hasn't overridden it yet
, get_URL = function() {
return view.URL || view.webkitURL || view;
}
, URL = view.URL || view.webkitURL || view
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
, can_use_save_link = !view.externalHost && "download" in save_link
, click = function(node) {
var event = doc.createEvent("MouseEvents");
event.initMouseEvent(
"click", true, false, view, 0, 0, 0, 0, 0
, false, false, false, false, 0, null
);
node.dispatchEvent(event);
}
, webkit_req_fs = view.webkitRequestFileSystem
, req_fs = view.requestFileSystem || webkit_req_fs || view.mozRequestFileSystem
, throw_outside = function(ex) {
(view.setImmediate || view.setTimeout)(function() {
throw ex;
}, 0);
}
, force_saveable_type = "application/octet-stream"
, fs_min_size = 0
, deletion_queue = []
, process_deletion_queue = function() {
var i = deletion_queue.length;
while (i--) {
var file = deletion_queue[i];
if (typeof file === "string") { // file is an object URL
URL.revokeObjectURL(file);
} else { // file is a File
file.remove();
}
}
deletion_queue.length = 0; // clear queue
}
, dispatch = function(filesaver, event_types, event) {
event_types = [].concat(event_types);
var i = event_types.length;
while (i--) {
var listener = filesaver["on" + event_types[i]];
if (typeof listener === "function") {
try {
listener.call(filesaver, event || filesaver);
} catch (ex) {
throw_outside(ex);
}
}
}
}
, FileSaver = function(blob, name) {
// First try a.download, then web filesystem, then object URLs
var
filesaver = this
, type = blob.type
, blob_changed = false
, object_url
, target_view
, get_object_url = function() {
var object_url = get_URL().createObjectURL(blob);
deletion_queue.push(object_url);
return object_url;
}
, dispatch_all = function() {
dispatch(filesaver, "writestart progress write writeend".split(" "));
}
// on any filesys errors revert to saving with object URLs
, fs_error = function() {
// don't create more object URLs than needed
if (blob_changed || !object_url) {
object_url = get_object_url(blob);
}
if (target_view) {
target_view.location.href = object_url;
} else {
window.open(object_url, "_blank");
}
filesaver.readyState = filesaver.DONE;
dispatch_all();
}
, abortable = function(func) {
return function() {
if (filesaver.readyState !== filesaver.DONE) {
return func.apply(this, arguments);
}
};
}
, create_if_not_found = {create: true, exclusive: false}
, slice
;
filesaver.readyState = filesaver.INIT;
if (!name) {
name = "download";
}
if (can_use_save_link) {
object_url = get_object_url(blob);
// FF for Android has a nasty garbage collection mechanism
// that turns all objects that are not pure javascript into 'deadObject'
// this means `doc` and `save_link` are unusable and need to be recreated
// `view` is usable though:
doc = view.document;
save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a");
save_link.href = object_url;
save_link.download = name;
var event = doc.createEvent("MouseEvents");
event.initMouseEvent(
"click", true, false, view, 0, 0, 0, 0, 0
, false, false, false, false, 0, null
);
save_link.dispatchEvent(event);
filesaver.readyState = filesaver.DONE;
dispatch_all();
return;
}
// Object and web filesystem URLs have a problem saving in Google Chrome when
// viewed in a tab, so I force save with application/octet-stream
// http://code.google.com/p/chromium/issues/detail?id=91158
if (view.chrome && type && type !== force_saveable_type) {
slice = blob.slice || blob.webkitSlice;
blob = slice.call(blob, 0, blob.size, force_saveable_type);
blob_changed = true;
}
// Since I can't be sure that the guessed media type will trigger a download
// in WebKit, I append .download to the filename.
// https://bugs.webkit.org/show_bug.cgi?id=65440
if (webkit_req_fs && name !== "download") {
name += ".download";
}
if (type === force_saveable_type || webkit_req_fs) {
target_view = view;
}
if (!req_fs) {
fs_error();
return;
}
fs_min_size += blob.size;
req_fs(view.TEMPORARY, fs_min_size, abortable(function(fs) {
fs.root.getDirectory("saved", create_if_not_found, abortable(function(dir) {
var save = function() {
dir.getFile(name, create_if_not_found, abortable(function(file) {
file.createWriter(abortable(function(writer) {
writer.onwriteend = function(event) {
target_view.location.href = file.toURL();
deletion_queue.push(file);
filesaver.readyState = filesaver.DONE;
dispatch(filesaver, "writeend", event);
};
writer.onerror = function() {
var error = writer.error;
if (error.code !== error.ABORT_ERR) {
fs_error();
}
};
"writestart progress write abort".split(" ").forEach(function(event) {
writer["on" + event] = filesaver["on" + event];
});
writer.write(blob);
filesaver.abort = function() {
writer.abort();
filesaver.readyState = filesaver.DONE;
};
filesaver.readyState = filesaver.WRITING;
}), fs_error);
}), fs_error);
};
dir.getFile(name, {create: false}, abortable(function(file) {
// delete file if it already exists
file.remove();
save();
}), abortable(function(ex) {
if (ex.code === ex.NOT_FOUND_ERR) {
save();
} else {
fs_error();
}
}));
}), fs_error);
}), fs_error);
}
, FS_proto = FileSaver.prototype
, saveAs = function(blob, name) {
return new FileSaver(blob, name);
}
;
FS_proto.abort = function() {
var filesaver = this;
filesaver.readyState = filesaver.DONE;
dispatch(filesaver, "abort");
};
FS_proto.readyState = FS_proto.INIT = 0;
FS_proto.WRITING = 1;
FS_proto.DONE = 2;
FS_proto.error =
FS_proto.onwritestart =
FS_proto.onprogress =
FS_proto.onwrite =
FS_proto.onabort =
FS_proto.onerror =
FS_proto.onwriteend =
null;
view.addEventListener("unload", process_deletion_queue, false);
saveAs.unload = function() {
process_deletion_queue();
view.removeEventListener("unload", process_deletion_queue, false);
};
return saveAs;
}(
typeof self !== "undefined" && self
|| typeof window !== "undefined" && window
|| this.content
));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the window
if (typeof module !== "undefined") module.exports = saveAs;

15
sims/downloads/all.css Normal file
View File

@ -0,0 +1,15 @@
/* FONT FACE */
@font-face {
font-family: "PatrickHand";
font-style: normal;
font-weight: 400;
src: url(../../css/PatrickHand-Regular.ttf) format('truetype');
}
body{
background:#bada55;
}
canvas{
width:150px;
margin: 5px;
}

26
sims/downloads/all.html Normal file
View File

@ -0,0 +1,26 @@
<!--
The Process:
1. ONLY when you press the button, does it take labels & pics & such...
2. Loads 'em all...
3. Draws them to canvasses!
4. Lets you download all of 'em, as a .zip!
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Download all o' them</title>
<link rel="stylesheet" type="text/css" href="all.css">
</head>
<body>
<button id="download">DOWNLOAD</button>
</body>
</html>
<script src="FileSaver.js"></script>
<script src="jszip.js"></script>
<script src="../helpers.js"></script>
<script src="download_all.js"></script>

View File

@ -0,0 +1,144 @@
/**********************************
1. ONLY when you press the button, does it take labels & pics & such... @done
2. Loads 'em all...
3. Draws html to canvasses!
- draw SOMETHING @done
- draw background image (if any) @done
- draw text box in correct position & text align with word wrap
4. Lets you download all of 'em, as a .zip! @done
**********************************/
// CARDS TO LOAD
var CARDNAMES = [
"sci_a",
"mitochondria_7",
"mitochondria_8",
"sci_c"
];
var download_btn = $("#download");
download_btn.onclick = function(){
// disable while we wait...
download_btn.disabled = true;
// Loads
var CARD_HTMLS = [];
for(var i=0; i<CARDNAMES.length; i++){
var cardname = CARDNAMES[i];
var front = document.createElement("div");
front.innerHTML = _getLabel("flashcard_"+cardname+"_front");
var back = document.createElement("div");
back.innerHTML = _getLabel("flashcard_"+cardname+"_back");
var htmls = { front:front, back:back };
CARD_HTMLS.push(htmls);
}
// DRAW TO CANVASSES (with Promises, coz loading)
var canvasPromises = [];
for(var i=0; i<CARD_HTMLS.length; i++){
var html = CARD_HTMLS[i];
var cardname = CARDNAMES[i];
canvasPromises.push( _drawToCanvas(cardname+"_front", html.front) );
canvasPromises.push( _drawToCanvas(cardname+"_back", html.back) );
}
// When all Promises fulfilled...
Promise.all(canvasPromises).then(function(canvasses){
// ZIP
var zip = new JSZip();
// Canvasses
canvasses.forEach(function(results){
var filename = results[0];
var canvas = results[1];
zip.file(filename+".png", canvas.toDataURL().substr(22), {base64: true});
});
// Download...
zip.generateAsync({type:"blob"})
.then(function(content) {
saveAs(content, "flashcards.zip");
});
});
};
function _drawToCanvas(filename, dom){
return new Promise(function(resolveCanvas){
// Canvas & Context
var canvas = document.createElement("canvas");
canvas.width = 400*2;
canvas.height = 240*2;
var ctx = canvas.getContext("2d");
ctx.scale(2,2);
// White background
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw background (with offset, if any)
var drawBG = new Promise(function(resolveBG){
// Any BG?
var bg = dom.querySelector(".fcard_bg");
if(bg){
var bgSrc = "../../" + bg.getAttribute("src");
var bgImage = new Image();
bgImage.onload = function(){
var sx = parseInt( bg.getAttribute("sx") ) || 0;
var sy = parseInt( bg.getAttribute("sy") ) || 0;
var dx = parseInt( bg.style.left ) || 0;
var dy = parseInt( bg.style.top ) || 0;
var width = 400;
var height = 240;
ctx.drawImage(bgImage,
sx*2, sy*2, width*2, height*2,
dx, dy, width, height);
resolveBG(); // donzeo
};
bgImage.src = bgSrc;
}else{
resolveBG(); // donzeo
}
});
// Draw text
drawBG.then(function(){
// Draw the innerText, w/e
ctx.fillStyle = "#000";
ctx.font = "20px PatrickHand";
ctx.fillText(dom.innerText, 10, 50);
// Return it!
resolveCanvas([filename, canvas]);
});
});
}

11605
sims/downloads/jszip.js Executable file

File diff suppressed because it is too large Load Diff