2016-04-04 03:05:22 +00:00
/ *
2017-08-15 04:43:09 +00:00
* Copyright ( C ) 2016 - 2017 Alex Yatskov < alex @ foosoft . net >
2016-04-04 03:05:22 +00:00
* Author : Alex Yatskov < alex @ foosoft . net >
*
* 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 < http : //www.gnu.org/licenses/>.
* /
2017-07-17 02:29:43 +00:00
async function formRead ( ) {
const optionsOld = await optionsLoad ( ) ;
const optionsNew = $ . extend ( true , { } , optionsOld ) ;
optionsNew . general . showGuide = $ ( '#show-usage-guide' ) . prop ( 'checked' ) ;
2017-09-29 02:41:29 +00:00
optionsNew . general . resultOutputMode = $ ( '#result-output-mode' ) . val ( ) ;
2017-07-17 02:29:43 +00:00
optionsNew . general . audioSource = $ ( '#audio-playback-source' ) . val ( ) ;
optionsNew . general . audioVolume = parseFloat ( $ ( '#audio-playback-volume' ) . val ( ) ) ;
optionsNew . general . debugInfo = $ ( '#show-debug-info' ) . prop ( 'checked' ) ;
optionsNew . general . showAdvanced = $ ( '#show-advanced-options' ) . prop ( 'checked' ) ;
optionsNew . general . maxResults = parseInt ( $ ( '#max-displayed-results' ) . val ( ) , 10 ) ;
optionsNew . general . popupWidth = parseInt ( $ ( '#popup-width' ) . val ( ) , 10 ) ;
optionsNew . general . popupHeight = parseInt ( $ ( '#popup-height' ) . val ( ) , 10 ) ;
optionsNew . general . popupOffset = parseInt ( $ ( '#popup-offset' ) . val ( ) , 10 ) ;
optionsNew . scanning . middleMouse = $ ( '#middle-mouse-button-scan' ) . prop ( 'checked' ) ;
optionsNew . scanning . selectText = $ ( '#select-matched-text' ) . prop ( 'checked' ) ;
optionsNew . scanning . alphanumeric = $ ( '#search-alphanumeric' ) . prop ( 'checked' ) ;
2017-09-17 06:08:43 +00:00
optionsNew . scanning . autoHideResults = $ ( '#auto-hide-results' ) . prop ( 'checked' ) ;
2017-07-17 02:29:43 +00:00
optionsNew . scanning . delay = parseInt ( $ ( '#scan-delay' ) . val ( ) , 10 ) ;
optionsNew . scanning . length = parseInt ( $ ( '#scan-length' ) . val ( ) , 10 ) ;
optionsNew . scanning . modifier = $ ( '#scan-modifier-key' ) . val ( ) ;
optionsNew . anki . enable = $ ( '#anki-enable' ) . prop ( 'checked' ) ;
optionsNew . anki . tags = $ ( '#card-tags' ) . val ( ) . split ( /[,; ]+/ ) ;
optionsNew . anki . sentenceExt = parseInt ( $ ( '#sentence-detection-extent' ) . val ( ) , 10 ) ;
optionsNew . anki . server = $ ( '#interface-server' ) . val ( ) ;
2017-09-06 20:18:06 +00:00
optionsNew . anki . fieldTemplates = $ ( '#field-templates' ) . val ( ) ;
2017-07-17 02:29:43 +00:00
2017-07-17 02:55:33 +00:00
if ( optionsOld . anki . enable && ! ankiErrorShown ( ) ) {
2017-07-17 02:29:43 +00:00
optionsNew . anki . terms . deck = $ ( '#anki-terms-deck' ) . val ( ) ;
optionsNew . anki . terms . model = $ ( '#anki-terms-model' ) . val ( ) ;
optionsNew . anki . terms . fields = ankiFieldsToDict ( $ ( '#terms .anki-field-value' ) ) ;
optionsNew . anki . kanji . deck = $ ( '#anki-kanji-deck' ) . val ( ) ;
optionsNew . anki . kanji . model = $ ( '#anki-kanji-model' ) . val ( ) ;
optionsNew . anki . kanji . fields = ankiFieldsToDict ( $ ( '#kanji .anki-field-value' ) ) ;
}
2017-03-03 05:01:49 +00:00
2017-07-17 02:29:43 +00:00
$ ( '.dict-group' ) . each ( ( index , element ) => {
const dictionary = $ ( element ) ;
const title = dictionary . data ( 'title' ) ;
const priority = parseInt ( dictionary . find ( '.dict-priority' ) . val ( ) , 10 ) ;
const enabled = dictionary . find ( '.dict-enabled' ) . prop ( 'checked' ) ;
2017-10-05 02:21:07 +00:00
const main = dictionary . find ( '.dict-main' ) . prop ( 'checked' ) ;
optionsNew . dictionaries [ title ] = { priority , enabled , main } ;
2017-03-03 05:01:49 +00:00
} ) ;
2017-07-17 02:29:43 +00:00
return { optionsNew , optionsOld } ;
2017-03-03 05:01:49 +00:00
}
2017-07-17 02:55:33 +00:00
function formUpdateVisibility ( options ) {
2017-03-03 05:01:49 +00:00
const general = $ ( '#anki-general' ) ;
if ( options . anki . enable ) {
general . show ( ) ;
} else {
general . hide ( ) ;
}
const advanced = $ ( '.options-advanced' ) ;
if ( options . general . showAdvanced ) {
advanced . show ( ) ;
} else {
advanced . hide ( ) ;
}
2017-05-25 02:13:56 +00:00
const debug = $ ( '#debug' ) ;
if ( options . general . debugInfo ) {
2017-09-13 03:20:03 +00:00
const temp = utilIsolate ( options ) ;
temp . anki . fieldTemplates = '...' ;
const text = JSON . stringify ( temp , null , 4 ) ;
2017-05-25 02:13:56 +00:00
debug . html ( handlebarsEscape ( text ) ) ;
debug . show ( ) ;
} else {
debug . hide ( ) ;
}
2017-03-03 05:01:49 +00:00
}
2017-08-15 04:43:09 +00:00
async function onFormOptionsChanged ( e ) {
2017-07-17 02:29:43 +00:00
try {
2017-08-15 04:43:09 +00:00
if ( ! e . originalEvent && ! e . isTrigger ) {
return ;
}
2017-07-17 02:29:43 +00:00
const { optionsNew , optionsOld } = await formRead ( ) ;
await optionsSave ( optionsNew ) ;
2017-03-05 23:54:03 +00:00
2017-07-17 02:55:33 +00:00
formUpdateVisibility ( optionsNew ) ;
2017-03-05 23:54:03 +00:00
2017-07-17 02:29:43 +00:00
const ankiUpdated =
optionsNew . anki . enable !== optionsOld . anki . enable ||
optionsNew . anki . server !== optionsOld . anki . server ;
if ( ankiUpdated ) {
2017-08-16 03:58:50 +00:00
ankiSpinnerShow ( true ) ;
2017-07-17 02:29:43 +00:00
await ankiDeckAndModelPopulate ( optionsNew ) ;
2017-08-16 03:58:50 +00:00
ankiErrorShow ( ) ;
2017-07-17 02:29:43 +00:00
}
} catch ( e ) {
ankiErrorShow ( e ) ;
} finally {
ankiSpinnerShow ( false ) ;
}
2017-08-15 04:43:09 +00:00
}
2017-07-17 02:29:43 +00:00
2017-08-15 04:43:09 +00:00
async function onReady ( ) {
2017-07-17 02:29:43 +00:00
const options = await optionsLoad ( ) ;
$ ( '#show-usage-guide' ) . prop ( 'checked' , options . general . showGuide ) ;
2017-09-29 02:41:29 +00:00
$ ( '#result-output-mode' ) . val ( options . general . resultOutputMode ) ;
2017-07-17 02:29:43 +00:00
$ ( '#audio-playback-source' ) . val ( options . general . audioSource ) ;
$ ( '#audio-playback-volume' ) . val ( options . general . audioVolume ) ;
$ ( '#show-debug-info' ) . prop ( 'checked' , options . general . debugInfo ) ;
$ ( '#show-advanced-options' ) . prop ( 'checked' , options . general . showAdvanced ) ;
$ ( '#max-displayed-results' ) . val ( options . general . maxResults ) ;
$ ( '#popup-width' ) . val ( options . general . popupWidth ) ;
$ ( '#popup-height' ) . val ( options . general . popupHeight ) ;
$ ( '#popup-offset' ) . val ( options . general . popupOffset ) ;
$ ( '#middle-mouse-button-scan' ) . prop ( 'checked' , options . scanning . middleMouse ) ;
$ ( '#select-matched-text' ) . prop ( 'checked' , options . scanning . selectText ) ;
$ ( '#search-alphanumeric' ) . prop ( 'checked' , options . scanning . alphanumeric ) ;
2017-09-17 06:08:43 +00:00
$ ( '#auto-hide-results' ) . prop ( 'checked' , options . scanning . autoHideResults ) ;
2017-07-17 02:29:43 +00:00
$ ( '#scan-delay' ) . val ( options . scanning . delay ) ;
$ ( '#scan-length' ) . val ( options . scanning . length ) ;
$ ( '#scan-modifier-key' ) . val ( options . scanning . modifier ) ;
2017-09-23 02:39:05 +00:00
$ ( '#dict-purge-link' ) . click ( utilAsync ( onDictionaryPurge ) ) ;
2017-08-15 04:43:09 +00:00
$ ( '#dict-file' ) . change ( utilAsync ( onDictionaryImport ) ) ;
2017-07-17 02:29:43 +00:00
$ ( '#anki-enable' ) . prop ( 'checked' , options . anki . enable ) ;
$ ( '#card-tags' ) . val ( options . anki . tags . join ( ' ' ) ) ;
$ ( '#sentence-detection-extent' ) . val ( options . anki . sentenceExt ) ;
$ ( '#interface-server' ) . val ( options . anki . server ) ;
2017-09-06 20:18:06 +00:00
$ ( '#field-templates' ) . val ( options . anki . fieldTemplates ) ;
$ ( '#field-templates-reset' ) . click ( utilAsync ( onAnkiFieldTemplatesReset ) ) ;
$ ( 'input, select, textarea' ) . not ( '.anki-model' ) . change ( utilAsync ( onFormOptionsChanged ) ) ;
2017-08-15 04:43:09 +00:00
$ ( '.anki-model' ) . change ( utilAsync ( onAnkiModelChanged ) ) ;
2017-07-17 02:29:43 +00:00
try {
await dictionaryGroupsPopulate ( options ) ;
} catch ( e ) {
dictionaryErrorShow ( e ) ;
}
try {
await ankiDeckAndModelPopulate ( options ) ;
} catch ( e ) {
ankiErrorShow ( e ) ;
}
2017-07-17 02:55:33 +00:00
formUpdateVisibility ( options ) ;
2017-08-15 04:43:09 +00:00
}
2017-07-17 02:29:43 +00:00
2017-08-15 04:43:09 +00:00
$ ( document ) . ready ( utilAsync ( onReady ) ) ;
2017-03-03 05:01:49 +00:00
/ *
* Dictionary
* /
2017-03-05 23:54:03 +00:00
function dictionaryErrorShow ( error ) {
2017-03-03 05:01:49 +00:00
const dialog = $ ( '#dict-error' ) ;
if ( error ) {
2017-09-23 03:38:23 +00:00
const overrides = [
[
'A mutation operation was attempted on a database that did not allow mutations.' ,
2017-09-23 15:55:53 +00:00
'Access to IndexedDB appears to be restricted. Firefox seems to require that the history preference is set to "Remember history" before IndexedDB use of any kind is allowed.'
2017-09-23 03:38:23 +00:00
] ,
[
'The operation failed for reasons unrelated to the database itself and not covered by any other error code.' ,
2017-09-23 15:55:53 +00:00
'Unable to access IndexedDB due to a possibly corrupt user profile. Try using the "Refresh Firefox" feature to reset your user profile.'
2017-09-23 03:38:23 +00:00
] ,
[
'BulkError' ,
2017-09-23 15:55:53 +00:00
'Unable to finish importing dictionary data into IndexedDB. This may indicate that you do not have sufficient disk space available to complete this operation.'
2017-09-23 03:38:23 +00:00
]
] ;
if ( error . toString ) {
error = error . toString ( ) ;
}
for ( const [ match , subst ] of overrides ) {
if ( error . includes ( match ) ) {
error = subst ;
break ;
}
}
2017-09-23 02:39:05 +00:00
dialog . show ( ) . text ( error ) ;
2017-03-03 05:01:49 +00:00
} else {
dialog . hide ( ) ;
}
}
2017-03-05 23:54:03 +00:00
function dictionarySpinnerShow ( show ) {
2017-03-03 05:01:49 +00:00
const spinner = $ ( '#dict-spinner' ) ;
if ( show ) {
spinner . show ( ) ;
} else {
spinner . hide ( ) ;
}
}
2017-03-05 23:54:03 +00:00
function dictionaryGroupsSort ( ) {
const dictGroups = $ ( '#dict-groups' ) ;
const dictGroupChildren = dictGroups . children ( '.dict-group' ) . sort ( ( ca , cb ) => {
const pa = parseInt ( $ ( ca ) . find ( '.dict-priority' ) . val ( ) , 10 ) ;
const pb = parseInt ( $ ( cb ) . find ( '.dict-priority' ) . val ( ) , 10 ) ;
if ( pa < pb ) {
return 1 ;
} else if ( pa > pb ) {
return - 1 ;
} else {
return 0 ;
}
} ) ;
dictGroups . append ( dictGroupChildren ) ;
}
2017-10-05 02:21:07 +00:00
function dictionarySetMain ( e ) {
const mainDictionary = $ ( e . target ) . closest ( '.dict-group' ) ;
const mainDictionaryTitle = mainDictionary . data ( 'title' ) ;
$ ( '.dict-group' ) . each ( ( index , element ) => {
const dictionary = $ ( element ) ;
if ( dictionary . data ( 'title' ) !== mainDictionaryTitle ) {
dictionary . find ( '.dict-main' ) . prop ( 'checked' , false ) ;
}
} ) ;
}
2017-07-17 02:29:43 +00:00
async function dictionaryGroupsPopulate ( options ) {
2017-03-03 05:01:49 +00:00
const dictGroups = $ ( '#dict-groups' ) . empty ( ) ;
const dictWarning = $ ( '#dict-warning' ) . hide ( ) ;
2017-09-14 00:30:45 +00:00
const dictRows = await utilDatabaseGetTitles ( ) ;
2017-07-17 02:29:43 +00:00
if ( dictRows . length === 0 ) {
dictWarning . show ( ) ;
}
2017-03-05 23:54:03 +00:00
2017-07-17 02:29:43 +00:00
for ( const dictRow of dictRowsSort ( dictRows , options ) ) {
2017-10-05 02:21:07 +00:00
const dictOptions = options . dictionaries [ dictRow . title ] || { enabled : false , priority : 0 , main : false } ;
2017-09-09 19:59:49 +00:00
const dictHtml = await apiTemplateRender ( 'dictionary.html' , {
2017-07-17 02:29:43 +00:00
title : dictRow . title ,
version : dictRow . version ,
revision : dictRow . revision ,
priority : dictOptions . priority ,
2017-10-05 02:21:07 +00:00
enabled : dictOptions . enabled ,
main : dictOptions . main
2017-07-17 02:29:43 +00:00
} ) ;
2017-03-03 05:01:49 +00:00
2017-07-17 02:29:43 +00:00
dictGroups . append ( $ ( dictHtml ) ) ;
}
2017-03-03 05:01:49 +00:00
2017-07-17 02:55:33 +00:00
formUpdateVisibility ( options ) ;
2017-07-17 02:29:43 +00:00
$ ( '.dict-enabled, .dict-priority' ) . change ( e => {
dictionaryGroupsSort ( ) ;
2017-07-17 02:55:33 +00:00
onFormOptionsChanged ( e ) ;
2017-07-17 02:29:43 +00:00
} ) ;
2017-10-05 02:21:07 +00:00
$ ( '.dict-main' ) . change ( e => {
dictionarySetMain ( e ) ;
onFormOptionsChanged ( e ) ;
} ) ;
2017-03-03 05:01:49 +00:00
}
2017-08-15 04:43:09 +00:00
async function onDictionaryPurge ( e ) {
2017-03-03 05:01:49 +00:00
e . preventDefault ( ) ;
const dictControls = $ ( '#dict-importer, #dict-groups' ) . hide ( ) ;
2017-09-23 02:39:05 +00:00
const dictProgress = $ ( '#dict-purge' ) . show ( ) ;
2017-03-03 05:01:49 +00:00
2017-07-17 02:29:43 +00:00
try {
dictionaryErrorShow ( ) ;
dictionarySpinnerShow ( true ) ;
2017-07-28 04:42:14 +00:00
await utilDatabasePurge ( ) ;
2017-07-17 02:29:43 +00:00
const options = await optionsLoad ( ) ;
options . dictionaries = { } ;
await optionsSave ( options ) ;
await dictionaryGroupsPopulate ( options ) ;
} catch ( e ) {
dictionaryErrorShow ( e ) ;
} finally {
2017-03-05 23:54:03 +00:00
dictionarySpinnerShow ( false ) ;
2017-07-17 02:29:43 +00:00
2017-03-03 05:01:49 +00:00
dictControls . show ( ) ;
dictProgress . hide ( ) ;
2017-07-17 02:29:43 +00:00
}
2017-08-15 04:43:09 +00:00
}
2017-06-25 22:36:28 +00:00
2017-08-15 04:43:09 +00:00
async function onDictionaryImport ( e ) {
2017-06-25 22:43:29 +00:00
const dictFile = $ ( '#dict-file' ) ;
2017-07-17 02:29:43 +00:00
const dictControls = $ ( '#dict-importer' ) . hide ( ) ;
2017-06-25 22:36:28 +00:00
const dictProgress = $ ( '#dict-import-progress' ) . show ( ) ;
2017-07-17 02:29:43 +00:00
try {
dictionaryErrorShow ( ) ;
dictionarySpinnerShow ( true ) ;
2017-06-25 22:36:28 +00:00
2017-07-17 02:29:43 +00:00
const setProgress = percent => dictProgress . find ( '.progress-bar' ) . css ( 'width' , ` ${ percent } % ` ) ;
const updateProgress = ( total , current ) => setProgress ( current / total * 100.0 ) ;
setProgress ( 0.0 ) ;
const options = await optionsLoad ( ) ;
2017-07-28 04:42:14 +00:00
const summary = await utilDatabaseImport ( e . target . files [ 0 ] , updateProgress ) ;
2017-10-05 02:21:07 +00:00
options . dictionaries [ summary . title ] = { enabled : true , priority : 0 , main : false } ;
2017-07-17 02:29:43 +00:00
await optionsSave ( options ) ;
await dictionaryGroupsPopulate ( options ) ;
} catch ( e ) {
dictionaryErrorShow ( e ) ;
} finally {
2017-06-25 22:36:28 +00:00
dictionarySpinnerShow ( false ) ;
2017-07-17 02:29:43 +00:00
dictFile . val ( '' ) ;
dictControls . show ( ) ;
2017-06-25 22:36:28 +00:00
dictProgress . hide ( ) ;
2017-07-17 02:29:43 +00:00
}
2017-08-15 04:43:09 +00:00
}
2017-03-03 05:01:49 +00:00
2017-07-17 06:56:36 +00:00
2017-03-03 05:01:49 +00:00
/ *
* Anki
* /
2017-03-05 23:54:03 +00:00
function ankiSpinnerShow ( show ) {
2017-03-03 05:01:49 +00:00
const spinner = $ ( '#anki-spinner' ) ;
if ( show ) {
spinner . show ( ) ;
} else {
spinner . hide ( ) ;
}
}
2017-03-05 23:54:03 +00:00
function ankiErrorShow ( error ) {
2017-03-03 05:01:49 +00:00
const dialog = $ ( '#anki-error' ) ;
if ( error ) {
2017-09-23 02:39:05 +00:00
dialog . show ( ) . text ( error ) ;
2017-03-03 05:01:49 +00:00
}
else {
dialog . hide ( ) ;
2016-04-04 03:05:22 +00:00
}
2017-03-03 05:01:49 +00:00
}
2017-07-17 02:55:33 +00:00
function ankiErrorShown ( ) {
return $ ( '#anki-error' ) . is ( ':visible' ) ;
}
2017-03-03 05:01:49 +00:00
function ankiFieldsToDict ( selection ) {
const result = { } ;
selection . each ( ( index , element ) => {
result [ $ ( element ) . data ( 'field' ) ] = $ ( element ) . val ( ) ;
} ) ;
2016-04-04 03:05:22 +00:00
2017-03-03 05:01:49 +00:00
return result ;
2016-04-04 03:05:22 +00:00
}
2017-07-17 02:29:43 +00:00
async function ankiDeckAndModelPopulate ( options ) {
2017-03-03 05:01:49 +00:00
const ankiFormat = $ ( '#anki-format' ) . hide ( ) ;
2017-07-28 04:42:14 +00:00
const deckNames = await utilAnkiGetDeckNames ( ) ;
2017-07-17 02:29:43 +00:00
const ankiDeck = $ ( '.anki-deck' ) ;
ankiDeck . find ( 'option' ) . remove ( ) ;
deckNames . sort ( ) . forEach ( name => ankiDeck . append ( $ ( '<option/>' , { value : name , text : name } ) ) ) ;
2017-07-28 04:42:14 +00:00
const modelNames = await utilAnkiGetModelNames ( ) ;
2017-07-17 02:29:43 +00:00
const ankiModel = $ ( '.anki-model' ) ;
ankiModel . find ( 'option' ) . remove ( ) ;
modelNames . sort ( ) . forEach ( name => ankiModel . append ( $ ( '<option/>' , { value : name , text : name } ) ) ) ;
2017-03-03 05:01:49 +00:00
2017-08-19 18:23:19 +00:00
$ ( '#anki-terms-deck' ) . val ( options . anki . terms . deck ) ;
await ankiFieldsPopulate ( $ ( '#anki-terms-model' ) . val ( options . anki . terms . model ) , options ) ;
$ ( '#anki-kanji-deck' ) . val ( options . anki . kanji . deck ) ;
await ankiFieldsPopulate ( $ ( '#anki-kanji-model' ) . val ( options . anki . kanji . model ) , options ) ;
2017-07-17 02:29:43 +00:00
ankiFormat . show ( ) ;
}
async function ankiFieldsPopulate ( element , options ) {
2017-03-03 05:01:49 +00:00
const modelName = element . val ( ) ;
2017-07-09 22:23:11 +00:00
if ( ! modelName ) {
2017-07-17 02:29:43 +00:00
return ;
2017-03-03 05:01:49 +00:00
}
2017-07-17 02:29:43 +00:00
const tab = element . closest ( '.tab-pane' ) ;
const tabId = tab . attr ( 'id' ) ;
const container = tab . find ( 'tbody' ) . empty ( ) ;
2017-03-03 05:01:49 +00:00
const markers = {
2017-03-29 03:49:26 +00:00
'terms' : [
'audio' ,
'cloze-body' ,
'cloze-prefix' ,
'cloze-suffix' ,
'dictionary' ,
'expression' ,
'furigana' ,
2017-08-26 19:18:35 +00:00
'furigana-plain' ,
2017-03-29 03:49:26 +00:00
'glossary' ,
2017-07-16 08:05:23 +00:00
'glossary-brief' ,
2017-03-29 03:49:26 +00:00
'reading' ,
'sentence' ,
'tags' ,
'url'
] ,
'kanji' : [
'character' ,
'dictionary' ,
'glossary' ,
'kunyomi' ,
'onyomi' ,
'sentence' ,
'tags' ,
'url'
]
2017-03-03 05:01:49 +00:00
} [ tabId ] || { } ;
2017-07-28 04:42:14 +00:00
for ( const name of await utilAnkiGetModelFieldNames ( modelName ) ) {
2017-07-17 02:29:43 +00:00
const value = options . anki [ tabId ] . fields [ name ] || '' ;
const html = Handlebars . templates [ 'model.html' ] ( { name , markers , value } ) ;
container . append ( $ ( html ) ) ;
}
2017-03-03 05:01:49 +00:00
2017-08-15 04:43:09 +00:00
tab . find ( '.anki-field-value' ) . change ( utilAsync ( onFormOptionsChanged ) ) ;
2017-07-17 02:55:33 +00:00
tab . find ( '.marker-link' ) . click ( onAnkiMarkerClicked ) ;
}
function onAnkiMarkerClicked ( e ) {
e . preventDefault ( ) ;
const link = e . target ;
$ ( link ) . closest ( '.input-group' ) . find ( '.anki-field-value' ) . val ( ` { ${ link . text } } ` ) . trigger ( 'change' ) ;
2016-04-04 03:05:22 +00:00
}
2017-08-15 04:43:09 +00:00
async function onAnkiModelChanged ( e ) {
2017-07-17 02:29:43 +00:00
try {
2017-08-15 04:43:09 +00:00
if ( ! e . originalEvent ) {
return ;
}
2017-07-17 02:29:43 +00:00
const element = $ ( this ) ;
2017-03-03 05:01:49 +00:00
const tab = element . closest ( '.tab-pane' ) ;
const tabId = tab . attr ( 'id' ) ;
2017-07-17 02:29:43 +00:00
const { optionsNew , optionsOld } = await formRead ( ) ;
2017-03-03 05:01:49 +00:00
optionsNew . anki [ tabId ] . fields = { } ;
2017-07-17 02:29:43 +00:00
await optionsSave ( optionsNew ) ;
2017-08-16 03:58:50 +00:00
ankiSpinnerShow ( true ) ;
2017-07-17 02:29:43 +00:00
await ankiFieldsPopulate ( element , optionsNew ) ;
2017-08-16 03:58:50 +00:00
ankiErrorShow ( ) ;
2017-07-17 02:29:43 +00:00
} catch ( e ) {
ankiErrorShow ( e ) ;
} finally {
ankiSpinnerShow ( false ) ;
}
2017-08-15 04:43:09 +00:00
}
2017-09-06 20:18:06 +00:00
async function onAnkiFieldTemplatesReset ( e ) {
try {
e . preventDefault ( ) ;
const options = await optionsLoad ( ) ;
$ ( '#field-templates' ) . val ( options . anki . fieldTemplates = optionsFieldTemplates ( ) ) ;
await optionsSave ( options ) ;
} catch ( e ) {
ankiErrorShow ( e ) ;
}
}