Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Created the AnkiMediaQueue for JavaScript media support
This adds the global `ankimedia` javascript object to every card. By default, it does not do anything unless the user explicitly calls for `ankimedia.setup()` inside a script tag. For example: ![image](https://user-images.githubusercontent.com/5332158/80847514-5bf8ea80-8be6-11ea-93f0-7fccfcd4bc72.png) **front** ```html What is the <b>past participle</b> of the verb to <b>{{Verb}}</b>?</span><br> <span style="display: flex; align-items: center;"> <input type="button" value="x1.2" onclick="setAnkiMedia( media => { media.playbackRate = 1.2; } )" /> <input type="button" value="x1.0" onclick="setAnkiMedia( media => { media.playbackRate = 1.0; } )" /> <input type="button" value="x0.6" onclick="setAnkiMedia( media => { media.playbackRate = 0.6; } )" /> <audio data-file="{{VerbAudio}}" controlsList="nodownload" controls></audio> </span> {{type:PastParticiple}} <script type="text/javascript"> ankimedia.setup(); ankimedia.add("front", "{{VerbAudio}}", 1.2); ☺</script> ``` **style** ```css audio { width: 100%; } ``` **style** ```html {{FrontSide}} <hr id=answer> <span style="display: flex; align-items: center;"> <input type="button" value="x1.2" onclick="setAnkiMedia( media => { media.playbackRate = 1.2; } )" /> <input type="button" value="x1.0" onclick="setAnkiMedia( media => { media.playbackRate = 1.0; } )" /> <input type="button" value="x0.6" onclick="setAnkiMedia( media => { media.playbackRate = 0.6; } )" /> <audio data-file="{{PastParticipleAudio}}" controlsList="nodownload" controls></audio> </span> {{PastParticiplePhonetic}} <script type="text/javascript"> ankimedia.add( "back", "{{PastParticipleAudio}}", 1.2); </script> ``` This will require the usage of the argument `fileonly` to the sound tag (#540 - Added arguments as [sound:argument1 argument2]). **fields** ```java Verb: bumb VerbPhonetic: /bumb/ VerbAudio: [sound:bumb.mp3|fileonly] PastParticiple: bamb PastParticiplePhonetic: /bamb/ PastParticipleAudio: [sound:bamb.mp3|fileonly] ``` Instead of calling `ankimedia.add("front", "{{VerbAudio}}", 1.2)` / `ankimedia.add( "back", "{{PastParticipleAudio}}", 1.2)` you can just call `ankimedia.autoadd( "front" )` / `ankimedia.autoadd( "back" )` which automatically detect all HTML5 media elements and plays them sequentially. These is the documentation for all public methods of the `ankimedia` global object: ```sql /** * Find all audio and video tags and run them through the callback parameter. * @param {Function} callback - to be called on each media. * @param {Array} initial - an additional list of items to be iterated over. */ function setAnkiMedia(callback, initial = undefined) /** * Automatically add all media elements found and start playing them sequentially. * @param {string} where - pass "front" if this is being called on the card-front, * otherwise, pass "back" if it is being called on the card-back. * @param {number} speed - the speed to play the audio, where 1.0 is the default speed. * Each media element can also have an attribute as `data-speed="1.0"` indicating * the speed it should play. The `data-speed` value has precedence over this parameter. */ ankimedia.addall(where, speed = 1.0) /** * Add an audio file to the playing queue and immediately starts playing, if not playing already. * @param {string} filename - an audio filename for playing * @param {string} where - pass "front" if this is being called on the card-front, * otherwise, pass "back" as it is being called on the card-back. * @param {number} speed - the speed to play the audio, where 1.0 is the default speed. * Each media element can also have an attribute as `data-speed="1.0"` indicating * the speed it should play. The `data-speed` value has precedence over this parameter. */ ankimedia.add(where, filename, speed = 1.0) /** * Call this on your front-card before adding new medias to the playing queue. * You can call this function as `setup({delay: 5, wait: false})`. * * @param {number} delay - how many seconds to time to wait before playing the next audio. * @param {boolean} wait - if true (default), wait the question audio to play * when the answer was showed before it had finished playing. * @param {function} extra - a function(media) to be run on each media of the page. * @param {array} medias - an array of initial values to be passed to setAnkiMedia() calls. */ ankimedia.setup(parameters: any = {}) ``` You can see the audio tests running if you go do the directory `anki/qt`, run `export PUPPETEER_HEADLESS=false` and run `make check`: ![keepinput](https://user-images.githubusercontent.com/5332158/80896475-faf41400-8cc4-11ea-9dcc-553569eb567b.gif) ```java (pyenv) F:\anki\qt\ts>set PUPPETEER_HEADLESS=false (pyenv) F:\anki\qt\ts>cmd /c "cd .. && make .build/testjs" (cd ts && npm run build) > anki-dtop-js@1.0.0 build F:\anki\qt\ts > tsc --build (cd ts && npm run gulp) > anki-dtop-js@1.0.0 gulp F:\anki\qt\ts > gulp reviewer [19:13:06] Using gulpfile F:\anki\qt\ts\gulpfile.js [19:13:06] Starting 'reviewer'... [19:13:17] Finished 'reviewer' after 11 s (cd ts && npm run test) > anki-dtop-js@1.0.0 test F:\anki\qt\ts > jest --verbose --runInBand Determining test suites to run... Running static file server on 'http://127.0.0.1:58254'... Environment 'slowMo=undefined' 'headless=true' 'args=--window-position=960,10' DevTools listening on ws://127.0.0.1:58255/devtools/browser/2b4a8e8c-7d76-4ce8-a01c-61754b7231e0 PASS src/reviewer.test.ts (15.415s) Test question and answer audios √ Showing a question should play its audio file automatically: front silence1.mp3 'ankimedia.setup(); ankimedia.addall( "front" );'... (870ms) √ Showing a question should play its audio file automatically: front silence1.mp3 'ankimedia.setup({delay: 0, wait: false, medias: []}); ankimedia.addall( "front" );'... (590ms) √ Showing a question should play its audio file automatically: front silence2.mp3 'ankimedia.setup(); ankimedia.add( "front", "silence2.mp3" );'... (574ms) √ Showing a question should play its audio file automatically: front silence2.mp3 'ankimedia.setup({delay: 0, wait: false, medias: []}); ankimedia.add( "front", "silence2.mp3" );'... (560ms) √ Showing a question should play its audio file automatically: front silence2.mp3 'ankimedia.setup({delay: 0, wait: false, medias: []}); ankimedia.add( "front", "silence2.mp3" );'... (320ms) √ Showing a new question should play its audio automatically: front silence1.mp3 'ankimedia.setup(); ankimedia.addall( "front" );', refront silence2.mp3 'ankimedia.setup(); ankimedia.addall( "front" );'... (1083ms) √ Showing a new question should play its audio automatically: front silence1.mp3 'ankimedia.setup(); ankimedia.add( "front", "silence1.mp3" );', refront silence2.mp3 'ankimedia.setup(); ankimedia.add( "front", "silence2.mp3" );'... (1097ms) √ Showing an answer with the same id as the question should only play the answer audio: front silence1.mp3 'ankimedia.setup(); ankimedia.addall( "front" );', back silence1.mp3 'ankimedia.setup(); ankimedia.addall( "back" );'... (1263ms) √ Showing an answer with the same id as the question should only play the answer audio: front silence1.mp3 'ankimedia.setup(); ankimedia.addall( "front" );', back silence2.mp3 'ankimedia.setup(); ankimedia.addall( "back" );'... (1268ms) √ Showing an answer with the same id as the question should only play the answer audio: front silence1.mp3 'ankimedia.setup(); ankimedia.add( "front", "silence1.mp3" );', back silence1.mp3 'ankimedia.setup(); ankimedia.add( "back", "silence1.mp3" );'... (1294ms) √ Showing an answer with the same id as the question should only play the answer audio: front silence1.mp3 'ankimedia.setup(); ankimedia.add( "front", "silence1.mp3" );', back silence2.mp3 'ankimedia.setup(); ankimedia.add( "back", "silence2.mp3" );'... (1303ms) PASS src/reviewer-exceptions.test.ts Test question and answer exception handling √ ankimedia.setup() with invalid parameters (24ms) √ ankimedia.setup() with bad parameters (20ms) √ do not call setup() before other methods (3ms) √ do not pass the correct value of where (4ms) √ do not add media files with the correct speed or file name (10ms) √ Calling functions with invalid arguments count (6ms) √ setAnkiMedia() with invalid callback parameters (4ms) Test Suites: 2 passed, 2 total Tests: 18 passed, 18 total Snapshots: 0 total Time: 17.026s, estimated 18s Ran all test suites. (pyenv) F:\anki\qt\ts> ```
- Loading branch information