// ==UserScript==
// @name WaniKani Open Framework Html Test Set
// @namespace https://www.wanikani.com
// @description Testing Set for the WaniKani Open Framework Html Type
// @author prouleau
// @version 0.0.1
// @include https://www.wanikani.com/*
// @grant none
// ==/UserScript==
(function(wkof) {
'use strict';
var wkofMinimumVersion = '1.0.52';
if (!wkof) {
var response = confirm('WaniKani Open Framework Date Filters requires WaniKani Open Framework.\n Click "OK" to be forwarded to installation instructions.');
if (response) {
window.location.href = 'https://community.wanikani.com/t/instructions-installing-wanikani-open-framework/28549';
}
return;
}
var htmlTestSetDialog = false;
var htmlTestSetScriptId = 'htmlTestSet';
var htmlTestSetTitle = 'Html Test Set';
var needToRegisterFilters = true;
var filterNamePrefix = 'htmlTestSet_';
var baseTestsFilterName = filterNamePrefix + 'baseTests';
var pathTestsFilterName = filterNamePrefix + 'pathTests';
var defaultTestsFilterName = filterNamePrefix + 'defaultTests';
var callbackTestsFilterName = filterNamePrefix + 'callbackTests';
var filterTestsFilterName = filterNamePrefix + 'filterTests';
var filterTestsBFilterName = filterNamePrefix + 'filterTestsB';
var filterItemListFilterName = filterNamePrefix + 'filterItemList';
var supportedFilters = [baseTestsFilterName, pathTestsFilterName, defaultTestsFilterName, callbackTestsFilterName, filterTestsFilterName, filterTestsBFilterName,
filterItemListFilterName, ];
function updateFiltersWhenReady() {
needToRegisterFilters = true;
waitForItemDataRegistry().then(registerFilters);
}
function waitForItemDataRegistry() {
return wkof.wait_state('wkof.ItemData.registry', 'ready');
}
function registerFilters() {
if (!needToRegisterFilters) {
return;
}
supportedFilters.forEach(function(filterName) {
delete wkof.ItemData.registry.sources.wk_items.filters[filterName];
});
registerBaseTestsFilter();
registerPathTestsFilter();
registerDefaultTestsFilter();
registerCallbackTestsFilter();
registerFilterTestsFilter();
registerFilterTestsBFilter();
registerItemListFilter();
needToRegisterFilters = false;
}
function promise(){var a,b,c=new Promise(function(d,e){a=d;b=e;});c.resolve=a;c.reject=b;return c;};
var htmlTestSetLoadedPromise = promise();
wkof.include('Menu, Settings');
wkof.ready('Menu').then(installMenu);
function installMenu() {
loadDialog().then(function() {
addMenuItem();
});
}
function addMenuItem() {
wkof.Menu.insert_script_link({
script_id: htmlTestSetScriptId,
name: htmlTestSetScriptId,
submenu: 'Open',
title: htmlTestSetTitle,
on_click: function() { htmlTestSetDialog.open(); }
});
}
function installdialog() {
wkof.ItemData.pause_ready_event(true);
loadDialog().then(function() {
wkof.ItemData.pause_ready_event(false);
});
}
let defaultValue = JSON.stringify({});
//=========================================
// HTML for the html and css tests
//=========================================
let htmlBaseTest = '<p class="html_spaced">This is testing the integration of html element into the dialog. The goal is to verify the html '+
'inserts well without breaking the overall layout.</p></br>'+
'<p class="html_spaced">There are generic classes '+
'for styling the html element in the general look and feel of the settings dialog. They handle the most common '+
'situations. The programmer is free to add more styling classes or use a completely different styling should the need arises.</p><br>'+
'<p class="html_spaced">You may verify that everything resizes well and that narrow mode is properly handled.</p><br>'+
'<p class="html_spaced">There is no tagging of the settings. Trying to change them and storing the data will have no effect. '+
'This is purely a html and css test.</p><br>'+
'<p class="html_spaced">This test is available as a filter. In this case there is no filtering done. The goal is to verify there '+
'is no conflict with the particular css used in the context of a filter.</p><br>'+
'<p class="html_spaced"><b>Classes for styling full width elements</b></p><br>'+
'<p class="html_spaced">We can place items in a class <code>html_tigth</code> to have little spacing vertically.</p>'+
'<p class="html_spaced">We can place items in a div with class <code>html_spaced</code> to have more spacing vertically.</p>'+
'<p class="html_spaced">Both classes cause the element to occupy the full width of the enclosing div.</p><br>'+
'<p class="html_spaced">If a <code>html_tight</code> element is immediately followed by a <code>html_spaced</code> element the two are '+
'visually grouped by spacing.</p>'+
'<label class="html_tight">Text input</label>'+
'<input class="html_spaced" type="text">'+
'<label class="html_tight">Number input</label>'+
'<input class="html_spaced" type="number">'+
'<label class="html_tight">Color</label>'+
'<input class="html_spaced" type="color">'+
'<label class="html_tight">Dropdown</label>'+
'<select class="html_spaced">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'</select>'+
'<label class="html_tight">List</label>'+
'<select class="html_spaced" size="3">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'<option>option 4</option>'+
'<option>option 5</option>'+
'</select>'+
'<label class="html_tight">Multi</label>'+
'<select class="html_spaced" multiple size="4">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'<option>option 4</option>'+
'<option>option 5</option>'+
'<option>option 6</option>'+
'<option>option 7</option>'+
'</select>'+
'<label class="html_tight">Textarea.</label>'+
'<textarea class="html_spaced" rows="7"></textarea>'+
'<label class="html_tight">HTML5 date picker.</label>'+
'<input class="html_spaced" type="date">'+
'<label class="html_tight">HTML5 datetime picker.</label>'+
'<input class="html_spaced" type="datetime-local">'+
'<label class="html_tight">HTML5 time picker.</label>'+
'<input class="html_spaced" type="time">'+
'<br><p class="html_spaced"><b>Classes for styling left-right combo</b></p><br>'+
'<p class="html_spaced">We can use a pair of div element to create a left-rigth combination. The left element'+
'must have class <code>html_left</code> and the right element must have class <code>html_right</code>. The whole combo must be wrapped in '+
'a div with class <code>html_row</code>.</p>'+
'<div class="html_row">'+
'<div class="html_left"><label>Checkbox</label></div>'+
'<div class="html_right"><input type="checkbox"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Text Input</label></div>'+
'<div class="html_right"><input type="text"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Numeric Input</label></div>'+
'<div class="html_right"><input type="number"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Color</label></div>'+
'<div class="html_right"><input type="color"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Dropdown</label></div>'+
'<div class="html_right">'+
'<select>'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'</select>'+
'</div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Multi</label></div>'+
'<div class="html_right">'+
'<select multiple size="4">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'<option>option 4</option>'+
'<option>option 5</option>'+
'<option>option 6</option>'+
'<option>option 7</option>'+
'</select>'+
'</div>'+
'</div>'+
'<br><p class="html_spaced"><b>Columns</b></p><br>'+
'<p class="html_spaced">If two div are given the classes <code>html_column_left</code> and <code>html_column_right</code> a two '+
'columns layout is created. Headers are styled with <code>html_header</code></p><br>'+
'<div class="html_column_left">'+
'<label class="html_header">Left Column Header</label>'+
'<label class="html_tight">Text input</label>'+
'<input class="html_spaced" type="text">'+
'<label class="html_tight">Number input</label>'+
'<input class="html_spaced" type="number">'+
'<label class="html_tight">Color</label>'+
'<input class="html_spaced" type="color">'+
'<div class="html_row">'+
'<div class="html_left"><label>Dropdown</label></div>'+
'<div class="html_right">'+
'<select>'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'</select>'+
'</div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Multi</label></div>'+
'<div class="html_right">'+
'<select multiple size="4">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'<option>option 4</option>'+
'<option>option 5</option>'+
'<option>option 6</option>'+
'<option>option 7</option>'+
'</select>'+
'</div>'+
'</div>'+
'</div>'+
'<div class="html_column_right">'+
'<label class="html_header">Right Column Header</label>'+
'<div class="html_row">'+
'<div class="html_left"><label>Checkbox</label></div>'+
'<div class="html_right"><input type="checkbox"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Text Input</label></div>'+
'<div class="html_right"><input type="text"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Numeric Input</label></div>'+
'<div class="html_right"><input type="number"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Color</label></div>'+
'<div class="html_right"><input type="color"></div>'+
'</div>'+
'<label class="html_tight">Dropdown</label>'+
'<select class="html_spaced">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'</select>'+
'<label class="html_tight">Multi</label>'+
'<select class="html_spaced" multiple size="4">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'<option>option 4</option>'+
'<option>option 5</option>'+
'<option>option 6</option>'+
'<option>option 7</option>'+
'</select>'+
'</div>'+
'<br><p class="html_spaced"><b>Grouping</b></p><br>'+
'<p class="html_spaced">If elements are inserted in a div of class <code>html_shaded</code> '+
'a box is created that visually group them together.</p><br>'+
'<div class="html_row">'+
'<div class="html_left"><label>Text Input</label></div>'+
'<div class="html_right"><input type="text"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Numeric Input</label></div>'+
'<div class="html_right"><input type="number"></div>'+
'</div>'+
'<div class="html_shaded">'+
'<label class="html_tight">Text input</label>'+
'<input class="html_spaced" type="text">'+
'<label class="html_tight">Number input</label>'+
'<input class="html_spaced" type="number">'+
'<div class="html_row">'+
'<div class="html_left"><label>Dropdown</label></div>'+
'<div class="html_right">'+
'<select>'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'</select>'+
'</div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Multi</label></div>'+
'<div class="html_right">'+
'<select multiple size="4">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'<option>option 4</option>'+
'<option>option 5</option>'+
'<option>option 6</option>'+
'<option>option 7</option>'+
'</select>'+
'</div>'+
'</div>'+
'</div>'+
'<br><br><p class="html_spaced">This works within columns too.</p><br>'+
'<div class="html_column_left">'+
'<label class="html_header">Left Column Header</label>'+
'<div class="html_shaded">'+
'<label class="html_tight">Text input</label>'+
'<input class="html_spaced" type="text">'+
'<label class="html_tight">Number input</label>'+
'<input class="html_spaced" type="number">'+
'<label class="html_tight">Color</label>'+
'<input class="html_spaced" type="color">'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Multi</label></div>'+
'<div class="html_right">'+
'<select multiple size="4">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'<option>option 4</option>'+
'<option>option 5</option>'+
'<option>option 6</option>'+
'<option>option 7</option>'+
'</select>'+
'</div>'+
'</div>'+
'</div>'+
'<div class="html_column_right">'+
'<label class="html_header">Right Column Header</label>'+
'<div class="html_row">'+
'<div class="html_left"><label>Checkbox</label></div>'+
'<div class="html_right"><input type="checkbox"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Text Input</label></div>'+
'<div class="html_right"><input type="text"></div>'+
'</div>'+
'<div class="html_shaded">'+
'<div class="html_row">'+
'<div class="html_left"><label>Numeric Input</label></div>'+
'<div class="html_right"><input type="number"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Color</label></div>'+
'<div class="html_right"><input type="color"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Dropdown</label></div>'+
'<div class="html_right">'+
'<select>'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'</select>'+
'</div>'+
'</div>'+
'</div>'+
'<label class="html_tight">Dropdown</label>'+
'<select class="html_spaced">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'</select>'+
'<label class="html_tight" title="You need to hold control\nfor multiple selections.">Multi</label>'+
'<select class="html_spaced" multiple size="4">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'<option>option 4</option>'+
'<option>option 5</option>'+
'<option>option 6</option>'+
'<option>option 7</option>'+
'</select>'+
'</div>'+
'<br><p class="html_spaced">If <code>html_shaded</code> is applied to a column the whole column gets shaded.</p><br>'+
'<div class="html_column_left html_shaded">'+
'<label class="html_header">Left Column Header</label>'+
'<label class="html_tight">Text input</label>'+
'<input class="html_spaced" type="text">'+
'<label class="html_tight">Number input</label>'+
'<input class="html_spaced" type="number">'+
'<label class="html_tight">Color</label>'+
'<input class="html_spaced" type="color">'+
'<div class="html_row">'+
'<div class="html_left"><label>Color</label></div>'+
'<div class="html_right"><input type="color"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Dropdown</label></div>'+
'<div class="html_right">'+
'<select>'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'</select>'+
'</div>'+
'</div>'+
'</div>'+
'<div class="html_column_right html_shaded">'+
'<label class="html_header">Right Column Header</label>'+
'<div class="html_row">'+
'<div class="html_left"><label>Checkbox</label></div>'+
'<div class="html_right"><input type="checkbox"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Text Input</label></div>'+
'<div class="html_right"><input type="text"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Numeric Input</label></div>'+
'<div class="html_right"><input type="number"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label>Multi</label></div>'+
'<div class="html_right">'+
'<select multiple size="4">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'<option>option 4</option>'+
'<option>option 5</option>'+
'<option>option 6</option>'+
'<option>option 7</option>'+
'</select>'+
'</div>'+
'</div>'+
'<label class="html_tight">Dropdown</label>'+
'<select class="html_spaced">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'</select>'+
'<label class="html_tight" title="You need to hold control\nfor multiple selections.">Multi</label>'+
'<select class="html_spaced" multiple size="4">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'<option>option 4</option>'+
'<option>option 5</option>'+
'<option>option 6</option>'+
'<option>option 7</option>'+
'</select>'+
'</div>';
//=========================================
// HTML for the visual test
//=========================================
let htmlVisualTestPreamble = ''+
'<p class="html_spaced">This is a test for verifying how the inserted html blends visually with the framework built-in elements '+
'when both are used in the same dialog. The goal is to make sure everything looks pretty and clean when using the styling '+
'classes discussed in the HTML and CSS test.<p><br>'+
'The configuration for the html element allows a <code>shade</code> flag. When set to true the html will be styled to '+
'set it apart from individual settings. The test cover both cases where this flag is used and not used. '+
'There is also one instance where there is no label for the inserted html.</p><br>';
let htmlVisualTestHtmlA = ''+
'<label class="html_tight">HTML Inserted Textarea - shade flag not used</label>'+
'<textarea class="html_spaced" rows="7"></textarea>';
let htmlVisualTestHtmlA1 = ''+
'<label class="html_tight">HTML Inserted Textarea - shade flag and label not used</label>'+
'<textarea class="html_spaced" rows="7"></textarea>';
let htmlVisualTestHtmlB = ''+
'<div class="html_column_left">'+
'<label class="html_tight">Dropdown</label>'+
'<select class="html_spaced">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'</select>'+
'<label class="html_tight">List</label>'+
'<select class="html_spaced" size="3">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'<option>option 4</option>'+
'<option>option 5</option>'+
'</select>'+
'</div>'+
'<div class="html_column_right">'+
'<div class="html_row">'+
'<label class="html_left">Text input</label>'+
'<input class="html_right" type="text">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left">Number input</label>'+
'<input class="html_right" type="number">'+
'</div>'+
'</div>';
let htmlVisualTestHtmlC = ''+
'<div class="html_column_left html_shaded">'+
'<label class="html_tight">Dropdown</label>'+
'<select class="html_spaced">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'</select>'+
'<label class="html_tight">List</label>'+
'<select class="html_spaced" size="3">'+
'<option>option 1</option>'+
'<option>option 2</option>'+
'<option>option 3</option>'+
'<option>option 4</option>'+
'<option>option 5</option>'+
'</select>'+
'</div>'+
'<div class="html_column_right html_shaded">'+
'<div class="html_row">'+
'<label class="html_left">Text input</label>'+
'<input class="html_right" type="text">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left">Number input</label>'+
'<input class="html_right" type="number">'+
'</div>'+
'</div>';
//=========================================
// HTML for the tag test
//=========================================
let htmlTagTestPreamble = ''+
'<p class="html_spaced">This is a test for the tagging of html elements to cause the settings to be stored at the proper location '+
'in <code>wkof.settings[script_id]</code>. There is a mix and match of html elements and other '+
'framework elements to validate they don\'t interfere with each other. You may verify that you can change settings, '+
'save them and get them back when you reopen the dialog.</p><br>';
let htmlTagTestHtml = ''+
'<p class="html_spaced">Testing all the input types.</p>'+
'<div class="html_row">'+
'<div class="html_left"><label for="htmlTestSet_no0">Checkbox input no 0</label></div>'+
'<div class="html_right"><input id="htmlTestSet_no0" class="setting" name="no0" type="checkbox"></div>'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_no1">Text input no 1</label>'+
'<input id="htmlTestSet_no1" class="html_right setting" name="no1" type="text">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_no2">Number input no 2</label>'+
'<input id="htmlTestSet_no2" class="html_right setting" name="no2" type="number">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_no3">Color no 3</label>'+
'<input id="htmlTestSet_no3" class="html_right setting" name="no3" type="color">'+
'</div>'+
'<label class="html_tight" for="htmlTestSet_no4">Dropdown no 4</label>'+
'<select id="htmlTestSet_no4" class="html_spaced setting" name="no4">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_no5">List no 5</label>'+
'<select id="htmlTestSet_no5" class="html_spaced setting" name="no5" size="3">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'<option name="option4">option 4</option>'+
'<option name="option5">option 5</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_no6">Multi no 6</label>'+
'<select id="htmlTestSet_no6" class="html_spaced setting" name="no6" multiple size="4">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'<option name="option4">option 4</option>'+
'<option name="option5">option 5</option>'+
'<option name="option6">option 6</option>'+
'<option name="option7">option 7</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_no7">Textarea no 7</label>'+
'<textarea id="htmlTestSet_no7" class="html_spaced setting" name="no7" rows="7"></textarea>'+
'<div class="html_shaded">'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_no8">HTML5 date picker no 8.</label>'+
'<input id="htmlTestSet_no8" class="html_spaced setting" name="no8" type="date">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_no9">HTML5 datetime picker no9.</label>'+
'<input id="htmlTestSet_no9" class="html_spaced setting" name="no9" type="datetime-local">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_no10">HTML5 time picker.</label>'+
'<input id="htmlTestSet_no10" class="html_spaced setting" name="no10" type="time">'+
'</div>'+
'</div>';
//=========================================
// HTML for the path test
//=========================================
let htmlPathTest = ''+
'<p class="html_spaced">This is a test for the tagging of html elements to cause the settings to be stored at the proper location '+
'in <code>wkof.settings[script_id]</code>. This test is meant to be called from a filter. In this case the settings must be '+
'stored in the proper preset '+
'of Item Inspector and Self Study Quiz as indicated by the path location. You may verify this is done correctly. No filtering '+
'is done because this is not the purpose of the test.</p><br>'+
'<p class="html_spaced">Testing all the input types.</p>'+
'<div class="html_row">'+
'<div class="html_left"><label for="htmlTestSet_htmlTestSet_pathTests_no0">Checkbox</label></div>'+
'<div class="html_right"><input id="htmlTestSet_htmlTestSet_pathTests_no0" class="setting" name="htmlTestSet_pathTests_no0" type="checkbox"></div>'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_pathTests_no1">Text</label>'+
'<input id="htmlTestSet_htmlTestSet_pathTests_no1" class="html_right setting" name="htmlTestSet_pathTests_no1" type="text">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_pathTests_no2">Number</label>'+
'<input id="htmlTestSet_htmlTestSet_pathTests_no2" class="html_right setting" name="htmlTestSet_pathTests_no2" type="number">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_pathTests_no3">Color</label>'+
'<input id="htmlTestSet_htmlTestSet_pathTests_no3" class="html_right setting" name="htmlTestSet_pathTests_no3" type="color">'+
'</div>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_pathTests_no4">Dropdown</label>'+
'<select id="htmlTestSet_htmlTestSet_pathTests_no4" class="html_spaced setting" name="htmlTestSet_pathTests_no4">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_pathTests_no5">List</label>'+
'<select id="htmlTestSet_htmlTestSet_pathTests_no5" class="html_spaced setting" name="htmlTestSet_pathTests_no5" size="3">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'<option name="option4">option 4</option>'+
'<option name="option5">option 5</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_pathTests_no6">Multi</label>'+
'<select id="htmlTestSet_htmlTestSet_pathTests_no6" class="html_spaced setting" name="htmlTestSet_pathTests_no6" multiple size="4">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'<option name="option4">option 4</option>'+
'<option name="option5">option 5</option>'+
'<option name="option6">option 6</option>'+
'<option name="option7">option 7</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_pathTests_no7">Textarea</label>'+
'<textarea id="htmlTestSet_htmlTestSet_pathTests_no7" class="html_spaced setting" name="htmlTestSet_pathTests_no7" rows="7"></textarea>'+
'<div class="html_shaded">'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_pathTests_no8">HTML5 date picker</label>'+
'<input id="htmlTestSet_htmlTestSet_pathTests_no8" class="html_spaced setting" name="htmlTestSet_pathTests_no8" type="date">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_pathTests_no9">HTML5 datetime picker</label>'+
'<input id="htmlTestSet_htmlTestSet_pathTests_no9" class="html_spaced setting" name="htmlTestSet_pathTests_no9" type="datetime-local">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_pathTests_no10">HTML5 time picker</label>'+
'<input id="htmlTestSet_htmlTestSet_pathTests_no10" class="html_spaced setting" name="htmlTestSet_pathTests_no10" type="time">'+
'</div>'+
'</div>';
//=========================================
// HTML for the default values test
//=========================================
let htmlDefaultTest = ''+
'<p class="html_spaced">This test verifies that the initialization of default values work. If the test is successful you will see '+
'the input elements populated with their default values. All data types are tested. For comparison purposes an element '+
'without a default valut is provided.</p><br>'+
'<p class="html_spaced">Testing all the input types. The labels indicate how it should be. In case of a mismatch there is a bug.</p>'+
'<div class="html_row">'+
'<div class="html_left"><label for="htmlTestSet_htmlTestSet_defaultno0">Checkbox default is checked</label></div>'+
'<div class="html_right"><input id="htmlTestSet_htmlTestSet_defaultno0" class="setting" name="htmlTestSet_defaultno0" type="checkbox"></div>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label for="htmlTestSet_htmlTestSet_defaultno1">Checkbox no default unchecked</label></div>'+
'<div class="html_right"><input id="htmlTestSet_htmlTestSet_defaultno1" class="setting" name="htmlTestSet_defaultno1" type="checkbox"></div>'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_defaultno2">Text default abc</label>'+
'<input id="htmlTestSet_htmlTestSet_defaultno2" class="html_right setting" name="htmlTestSet_defaultno2" type="text">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_defaultno3">Text no default empty</label>'+
'<input id="htmlTestSet_htmlTestSet_defaultno3" class="html_right setting" name="htmlTestSet_defaultno3" type="text">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_defaultno4">Number default 100</label>'+
'<input id="htmlTestSet_htmlTestSet_defaultno4" class="html_right setting" name="htmlTestSet_defaultno4" type="number">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_defaultno5">Number no default empty</label>'+
'<input id="htmlTestSet_htmlTestSet_defaultno5" class="html_right setting" name="htmlTestSet_defaultno5" type="number">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_defaultno6">Color default red</label>'+
'<input id="htmlTestSet_htmlTestSet_defaultno6" class="html_right setting" name="htmlTestSet_defaultno6" type="color">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_defaultno7">Color no default black</label>'+
'<input id="htmlTestSet_htmlTestSet_defaultno7" class="html_right setting" name="htmlTestSet_defaultno7" type="color">'+
'</div>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno8">Dropdown default option 3</label>'+
'<select id="htmlTestSet_htmlTestSet_defaultno8" class="html_spaced setting" name="htmlTestSet_defaultno8">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno9">Dropdown no default option 1</label>'+
'<select id="htmlTestSet_htmlTestSet_defaultno9" class="html_spaced setting" name="htmlTestSet_defaultno9">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno10">List default option 3</label>'+
'<select id="htmlTestSet_htmlTestSet_defaultno10" class="html_spaced setting" name="htmlTestSet_defaultno10" size="3">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'<option name="option4">option 4</option>'+
'<option name="option5">option 5</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno11">List no default option 1</label>'+
'<select id="htmlTestSet_htmlTestSet_defaultno11" class="html_spaced setting" name="htmlTestSet_defaultno11" size="3">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'<option name="option4">option 4</option>'+
'<option name="option5">option 5</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno12">Multi default all selected</label>'+
'<select id="htmlTestSet_htmlTestSet_defaultno12" class="html_spaced setting" name="htmlTestSet_defaultno12" multiple size="4">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'<option name="option4">option 4</option>'+
'<option name="option5">option 5</option>'+
'<option name="option6">option 6</option>'+
'<option name="option7">option 7</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno13">Multi no default none selected</label>'+
'<select id="htmlTestSet_htmlTestSet_defaultno13" class="html_spaced setting" name="htmlTestSet_defaultno13" multiple size="4">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'<option name="option4">option 4</option>'+
'<option name="option5">option 5</option>'+
'<option name="option6">option 6</option>'+
'<option name="option7">option 7</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno14">Textarea default abcd</label>'+
'<textarea id="htmlTestSet_htmlTestSet_defaultno14" class="html_spaced setting" name="htmlTestSet_defaultno14" rows="7"></textarea>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno15">Textarea no default empty</label>'+
'<textarea id="htmlTestSet_htmlTestSet_defaultno15" class="html_spaced setting" name="htmlTestSet_defaultno15" rows="7"></textarea>'+
'<div class="html_shaded">'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno16">HTML5 date picker default 2010-01-01</label>'+
'<input id="htmlTestSet_htmlTestSet_defaultno16" class="html_spaced setting" name="htmlTestSet_defaultno16" type="date">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno17">HTML5 date picker no default format placeholder</label>'+
'<input id="htmlTestSet_htmlTestSet_defaultno17" class="html_spaced setting" name="htmlTestSet_defaultno17" type="date">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno18">HTML5 datetime picker default 2010-01-01 01:00</label>'+
'<input id="htmlTestSet_htmlTestSet_defaultno18" class="html_spaced setting" name="htmlTestSet_defaultno18" type="datetime-local">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno19">HTML5 datetime picker no default format placeholder</label>'+
'<input id="htmlTestSet_htmlTestSet_defaultno19" class="html_spaced setting" name="htmlTestSet_defaultno19" type="datetime-local">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno20">HTML5 time picker default 01:00</label>'+
'<input id="htmlTestSet_htmlTestSet_defaultno20" class="html_spaced setting" name="htmlTestSet_defaultno20" type="time">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_defaultno21">HTML5 time picker no default format placeholder</label>'+
'<input id="htmlTestSet_htmlTestSet_defaultno21" class="html_spaced setting" name="htmlTestSet_defaultno21" type="time">'+
'</div>'+
'</div>';
//=========================================
// HTML for the validation/callback test
//=========================================
let htmlCallbackTestCore = ''+
'<p class="html_spaced">This is testing the validation and callbacks in embedded html. Validation and callbacks are defined in '+
'the content subobject of the html element subobject. All the standard wkof features are availble through this mechanism.</p><br>'+
'<p class="html_spaced">This is availble for filters as well. In its filter incanation this test doesn\'t filter anything '+
'because this is not the purpose of the test.</p><br>'+
'<br><p class="html_spaced">This dropdown triggers an alert with an <code>on_change</code> callback.</p>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_callbackTests_no3">Dropdown with callback</label>'+
'<select id="htmlTestSet_htmlTestSet_callbackTests_no3" class="html_spaced setting" name="htmlTestSet_callbackTests_no3">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'</select>'+
'<br><p class="html_spaced">This button triggers an alert with an <code>on_click</code> callback.</p>'+
'<button class="html_spaced setting" name="htmlTestSet_callbackTests_no4" type="button">Click for an alert</button>'+
'<p class="html_spaced">This numerical input takes a min max built-in validation.</p>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_callbackTests_no0">Number between 5 and 10</label>'+
'<div class="html_right msg"><input id="htmlTestSet_htmlTestSet_callbackTests_no0" class="setting" name="htmlTestSet_callbackTests_no0" type="number"></div>'+
'</div>'+
'<br><p class="html_spaced">This text input accepts only charactes [a-z] with a built-in regex validation.</p>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_callbackTests_no1">Text with lowercase letters only</label>'+
'<div class="msg html_right"><input id="htmlTestSet_htmlTestSet_callbackTests_no1" class="setting" name="htmlTestSet_callbackTests_no1" type="text"></div>'+
'</div>'+
'<br><p class="html_spaced">This text input accepts a YYYY-MM-DD date with a <code>validate</code> callback.</p>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_callbackTests_no2">YYY-MM-DD only</label>'+
'<div class="msg html_right"><input id="htmlTestSet_htmlTestSet_callbackTests_no2" class="setting" name="htmlTestSet_callbackTests_no2" type="text"></div>'+
'</div>'+
'<br><p class="html_spaced">This text area accepts a comma separated list of words with spaces around the commas with a <code>validate</code> '+
'callback.</p>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_callbackTests_no6">Textarea</label>'+
'<div class="msg"><textarea id="htmlTestSet_htmlTestSet_callbackTests_no6" class="html_spaced setting" name="htmlTestSet_callbackTests_no6" rows="7"></textarea></div>';
let htmlCallbackTest = htmlCallbackTestCore+
'<p class="html_spaced">The validated element must be included in a div with class <code>msg</code> to receive the message at the proper '+
'location. Without such an enclosing the message will show up below the entire embedded htlm. This required to change '+
'the validation code to locate a <code>$(elem).parent(\'.msg\')</code> instead of a <code>$(elem).parent(\'.right\')</code>' +
'as was done before.</p><br>'+
'<p class="html_spaced">This tests what happens when you request a validation without enclosing it in a div with class <code>msg</code>. '+
'Watch for the message at the bottom of the embedded html.</p><br>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_callbackTests_no5">Number between 50 and 60</label>'+
'<input id="htmlTestSet_htmlTestSet_callbackTests_no5" class="html_right setting" name="htmlTestSet_callbackTests_no5" type="number">'+
'</div>'+
'<p class="html_spaced">There are below some non html elements that shows the change doesn\'t break validation for these elements.</p><br>';
//=========================================
// HTML for the refresh_on_change test
//=========================================
let htmlRefreshTest = ''+
'<p class="html_spaced">This tests the <code>refresh_on_change</code> flag on html elements. '+
'The procedure goes as follows. You change the value of the control numeric field to a value other than zero. '+
'Then you click on the "Reset to Zero" button. It will reset to zero the setting for the control field ' +
'but it will not refresh the dialog. You can then change the value of some other fields. If a '+
'refresh on change occurs the control field will return to zero. If it does not return to zero there is no refresh. '+
'You may test all data types in this manner.</p><br>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_refreshTests_no0">Control</label>'+
'<input id="htmlTestSet_htmlTestSet_refreshTests_no0" class="html_right setting" name="htmlTestSet_refreshTests_no0" type="number">'+
'</div>'+
'<div class="html_row">'+
'<p class="html_left"> </p>'+
'<button class="html_right setting" name="htmlTestSet_refreshTests_no1" type="button">Reset to zero</button>'+
'</div>'+
'<div class="html_row">'+
'<div class="html_left"><label for="htmlTestSet_htmlTestSet_refreshTests_no2">Checkbox</label></div>'+
'<div class="html_right"><input id="htmlTestSet_htmlTestSet_refreshTests_no2" class="setting" name="htmlTestSet_refreshTests_no2" type="checkbox"></div>'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_refreshTests_no3">Text</label>'+
'<input id="htmlTestSet_htmlTestSet_refreshTests_no3" class="html_right setting" name="htmlTestSet_refreshTests_no3" type="text">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_refreshTests_no4">Number</label>'+
'<input id="htmlTestSet_htmlTestSet_refreshTests_no4" class="html_right setting" name="htmlTestSet_refreshTests_no4" type="number">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_refreshTests_no5">Color</label>'+
'<input id="htmlTestSet_htmlTestSet_refreshTests_no5" class="html_right setting" name="htmlTestSet_refreshTests_no5" type="color">'+
'</div>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_refreshTests_no6">Dropdown</label>'+
'<select id="htmlTestSet_htmlTestSet_refreshTests_no6" class="html_spaced setting" name="htmlTestSet_refreshTests_no6">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_refreshTests_no7">List</label>'+
'<select id="htmlTestSet_htmlTestSet_refreshTests_no7" class="html_spaced setting" name="htmlTestSet_refreshTests_no7" size="3">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'<option name="option4">option 4</option>'+
'<option name="option5">option 5</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_refreshTests_no8">Multi</label>'+
'<select id="htmlTestSet_htmlTestSet_refreshTests_no8" class="html_spaced setting" name="htmlTestSet_refreshTests_no8" multiple size="4">'+
'<option name="option1">option 1</option>'+
'<option name="option2">option 2</option>'+
'<option name="option3">option 3</option>'+
'<option name="option4">option 4</option>'+
'<option name="option5">option 5</option>'+
'<option name="option6">option 6</option>'+
'<option name="option7">option 7</option>'+
'</select>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_refreshTests_no9">Textarea</label>'+
'<textarea id="htmlTestSet_htmlTestSet_refreshTests_no9" class="html_spaced setting" name="htmlTestSet_refreshTests_no9" rows="7"></textarea>'+
'<div class="html_shaded">'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_refreshTests_no10">HTML5 date picker</label>'+
'<input id="htmlTestSet_htmlTestSet_refreshTests_no10" class="html_spaced setting" name="htmlTestSet_refreshTests_no10" type="date">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_refreshTests_no11">HTML5 datetime picker</label>'+
'<input id="htmlTestSet_htmlTestSet_refreshTests_no11" class="html_spaced setting" name="htmlTestSet_refreshTests_no11" type="datetime-local">'+
'</div>'+
'<div class="html_row">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_refreshTests_no12">HTML5 time picker</label>'+
'<input id="htmlTestSet_htmlTestSet_refreshTests_no12" class="html_spaced setting" name="htmlTestSet_refreshTests_no12" type="time">'+
'</div>'+
'</div>';
//=========================================
// HTML for the first filter test
//=========================================
let htmlFilterTestA = ''+
'<p class="html_spaced">This tests a working filter. The intent is to verify that the multiple settings in a html type filter '+
'are successfully passed in a configuration object to <code>wkof.ItemData.get_items()</code> and eventually '+
'find their way to the filter. This particular filter uses <code>filter_value_map</code> to process dates ' +
'beforehand. A separate filter will use a direct access. (without <code>filter_value_map</code>)</p><br>'+
'<p class="html_spaced">This filter selects items based on a combination of item type and a date range for when lessons for '+
'the items were taken.</p></br>'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_filterTests_no0">Item Type</label>'+
'<select id="htmlTestSet_htmlTestSet_filterTests_no0" class="html_spaced setting" name="htmlTestSet_filterTests_no0" multiple size="3">'+
'<option name="radical">radical</option>'+
'<option name="kanji">kanji</option>'+
'<option name="vocabulary">vocabulary</option>'+
'</select>'+
'<div class="html_row msg">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_filterTests_no1">Burned Items Start Date</label>'+
'<input id="htmlTestSet_htmlTestSet_filterTests_no1" class="html_right setting" name="htmlTestSet_filterTests_no1" type="text">'+
'</div>'+
'<div class="html_row msg">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_filterTests_no2">Burned Items End Date</label>'+
'<input id="htmlTestSet_htmlTestSet_filterTests_no2" class="html_right setting" name="htmlTestSet_filterTests_no2" type="text">'+
'</div>';
//=========================================
// HTML for the second filter test
//=========================================
let htmlFilterTestB = ''+
'<p class="html_spaced">This tests a working filter. The intent is to verify that the multiple settings in a html type filter '+
'are successfully passed in a configuration object to <code>wkof.ItemData.get_items()</code> and eventually '+
'find their way to the filter. This particular filter does <b>not</b> use <code>filter_value_map</code> to process the ' +
'filter value beforehand.</p><br>'+
'<p class="html_spaced">This filter selects items based on a range of % of total correct answers.</p></br>'+
'<div class="html_row msg">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_filterTestsB_no1">Low % of correct answers</label>'+
'<input id="htmlTestSet_htmlTestSet_filterTestsB_no1" class="html_right setting" name="htmlTestSet_filterTestsB_no1" type="number">'+
'</div>'+
'<div class="html_row msg">'+
'<label class="html_left" for="htmlTestSet_htmlTestSet_filterTestsB_no2">High % of correct answers.</label>'+
'<input id="htmlTestSet_htmlTestSet_filterTestsB_no2" class="html_right setting" name="htmlTestSet_filterTestsB_no2" type="number">'+
'</div>';
//=============================================
// HTML for the filter with dialog button test
//=============================================
let hoverTipRadical = 'List radicals in a list separated with commas.';
let placeholderRadical = 'big, small';
let hoverTipKanji = 'List kanji in a list separated with commas.';
let placeholderKanji = '大, 小';
let hoverTipVocabulary = 'List vocabulary in a list separated with commas.';
let placeholderVocabulary = '大きい, 小さい';
let hoverTipUpload = 'Bring in your filter items from a file\nyou have previously downloaded.\nYou must select the file first.';
let hoverTipDownload = 'Save your filter items into a file\nyou may upload in the future.';
let htmlFilterTestC = ''+
'<p class="html_spaced">This tests a working filter. This is an example of a filter I am interested to write. '+
'One objective is to verify that I can do what I want with an html type filter.</p><br>'+
'<p class="html_spaced">This is a version of the item list filter with a better user interface. It accepts a comma separated list '+
'of items for each item type.</p><br> '+
'<div title="'+hoverTipRadical+'">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_itemList_radical">Radicals</label>'+
'<div class="msg"><textarea id="htmlTestSet_htmlTestSet_itemList_radical" class="html_spaced setting" name="htmlTestSet_itemList_radical" '+
'placeholder="'+placeholderRadical+'" rows="6"></textarea></div>'+
'</div>'+
'<div title="'+hoverTipKanji+'">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_itemList_kanji">Kanji</label>'+
'<div class="msg"><textarea id="htmlTestSet_htmlTestSet_itemList_kanji" class="html_spaced setting" name="htmlTestSet_itemList_kanji" '+
'placeholder="'+placeholderKanji+'" rows="6"></textarea></div>'+
'</div>'+
'<div title="'+hoverTipVocabulary+'">'+
'<label class="html_tight" for="htmlTestSet_htmlTestSet_itemList_vocabulary">Vocabulary</label>'+
'<div class="msg"><textarea id="htmlTestSet_htmlTestSet_itemList_vocabulary" class="html_spaced setting" name="htmlTestSet_itemList_vocabulary" '+
'placeholder="'+placeholderVocabulary+'" rows="6"></textarea></div>'+
'</div>'+
'<div><input type="file" id="htmlTestSet_htmlTestSet_itemList_file" class="html_spaced" name="htmlTestSet_itemList_file"></div>'+
'<div class="msg files">'+
'<button class="html_spaced setting" id="htmlTestSet_htmlTestSet_itemList_upload" name="htmlTestSet_itemList_upload" '+
'title="'+hoverTipUpload+'" type="button">Set items according to selected file</button>'+
'<button class="html_spaced" id="htmlTestSet_htmlTestSet_itemList_download" '+
'title="'+hoverTipDownload+'" type="button" style="margin-left: 0.4em;">'+
'<a download="Filter Item List.txt" name="htmlTestSet_itemList_link" style="text-decoration:none;color:#000000;">Download items</a>'+
'</button>'+
'</div>';
function loadDialog() {
wkof.ready('Settings').then(function() {
// ===========================================
// Configuration for HTML and CSS tests
// ===========================================
let basicTestConfig = {type: 'page', label: 'HTML and CSS Test',
content: {basicTests: {type: 'html', label: 'HTML and CSS Test', html: htmlBaseTest, },
},
};
let visualTestConfig = {type: 'page', label: 'Visual Test',
content: {visualTestPreamble: {type: 'html', label: 'Visual Test', html: htmlVisualTestPreamble, },
checkboxVisualTestA: {type: 'checkbox', label: 'Not HTML checkbox', },
numberVisualTestB: {type: 'number', label: 'Not HTML number', },
textVisualTestC: {type: 'text', label: 'Not HTML text', },
visualTestHtmlD: {type: 'html', label: 'Html For The Test', html: htmlVisualTestHtmlA, },
numberVisualTestBA: {type: 'number', label: 'Not HTML number', },
textVisualTestBB: {type: 'text', label: 'Not HTML text', },
visualTestHtmlBC: {type: 'html', html: htmlVisualTestHtmlA1, },
checkboxVisualTestE: {type: 'checkbox', label: 'Not HTML checkbox', },
numberVisualTestF: {type: 'number', label: 'Not HTML number', },
numberVisualTestDA: {type: 'number', label: 'Not HTML number', },
textVisualTestDB: {type: 'text', label: 'Not HTML text', },
visualTestHtmlDC: {type: 'html', label: 'Html In Columns Not Shaded', html: htmlVisualTestHtmlB, },
checkboxVisualTestDE: {type: 'checkbox', label: 'Not HTML checkbox', },
numberVisualTestDF: {type: 'number', label: 'Not HTML number', },
textVisualTestG: {type: 'text', label: 'Not HTML text', },
groupVisualTestH: {type: 'group', label: 'Group',
content: {
numberVisualTestI: {type: 'number', label: 'Not HTML number', },
textVisualTestJ: {type: 'text', label: 'Not HTML text', },
visualTestHtmlK: {type: 'html', label: 'Html In a Group Not Shaded', html: htmlVisualTestHtmlB, },
checkboxVisualTestL: {type: 'checkbox', label: 'Not HTML checkbox', },
numberVisualTestM: {type: 'number', label: 'Not HTML number', },
},
},
checkboxVisualTestCA: {type: 'checkbox', label: 'Not HTML checkbox', },
numberVisualTestCB: {type: 'number', label: 'Not HTML number', },
textVisualTestCC: {type: 'text', label: 'Not HTML text', },
groupVisualTestCD: {type: 'group', label: 'Group',
content: {
numberVisualTestCE: {type: 'number', label: 'Not HTML number', },
textVisualTestCF: {type: 'text', label: 'Not HTML text', },
visualTestHtmlCG: {type: 'html', label: 'Html Shaded In a Group', shade: true, html: htmlVisualTestHtmlB, },
checkboxVisualTestCH: {type: 'checkbox', label: 'Not HTML checkbox', },
numberVisualTestCI: {type: 'number', label: 'Not HTML number', },
},
},
numberVisualTestN: {type: 'number', label: 'Not HTML number', },
numberVisualTestO: {type: 'number', label: 'Not HTML number', },
textVisualTestP: {type: 'text', label: 'Not HTML text', },
textVisualTestQ: {type: 'text', label: 'Not HTML text', },
groupVisualTestR: {type: 'group', label: 'Group',
content: {
numberVisualTestS: {type: 'number', label: 'Not HTML number', },
textVisualTestT: {type: 'text', label: 'Not HTML text', },
visualTestHtmlU: {type: 'html', label: 'Html Shaded In a Group With Inner Shading', shade: true, html: htmlVisualTestHtmlC, },
checkboxVisualTestV: {type: 'checkbox', label: 'Not HTML checkbox', },
numberVisualTestW: {type: 'number', label: 'Not HTML number', },
},
},
numberVisualTestX: {type: 'number', label: 'Not HTML number', },
numberVisualTestY: {type: 'number', label: 'Not HTML number', },
textVisualTestZ: {type: 'text', label: 'Not HTML text', },
textVisualTestAA: {type: 'text', label: 'Not HTML text', },
visualTestHtmlAB: {type: 'html', label: 'Html Shaded Not In A Group', shade: true, html: htmlVisualTestHtmlB, },
checkboxVisualTestAC: {type: 'checkbox', label: 'Not HTML checkbox', },
numberVisualTestAD: {type: 'number', label: 'Not HTML number', },
},
};
// ===========================================
// Configuration for tag tests
// ===========================================
let htmlTagConfig = {no0:{type: "checkbox"}, no1:{type: "text"}, no2:{type: "number"}, no3:{type: "color"},
no4:{type: "dropdown", content: {option1: "option 1", option2: "option 2", option3: "option 3", },},
no5:{type: "list", content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4", option5: "option 5", },},
no6:{type: "list", multi: true, content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4",
option5: "option 5", option6: "option 6", option7: "option 7", },
},
no7:{type: "other"}, no8:{type: "input", subtype: "date"}, no9:{type: "input", subtype: "datetime-local"},
no10:{type: "input", subtype: "time"}, };
let htmlTagTestConfig = {type: 'page', label: 'Tag Test',
content: {tagTestPreamble: {type: 'html', label: 'Preamble', html: htmlTagTestPreamble, },
checkboxTest: {type: 'checkbox', label: 'Not HTML checkbox', },
numberTest: {type: 'number', label: 'Not HTML number', },
textTest: {type: 'text', label: 'Not HTML text', },
tagTestHtml: {type: 'html', label: 'Html For The Test', shade: true, html: htmlTagTestHtml,
content: htmlTagConfig},
dropdownTest: {type: 'dropdown', label: 'Not HTM dropdown', content:{option1: 'Option 1',
option2: 'Option 2',
option3: 'Option 4',
option4: 'Option 4',
option5: 'Option 5',
}
},
dropdownTest: {type: 'list', label: 'Not HTM list', content:{option1: 'Option 1',
option2: 'Option 2',
option3: 'Option 4',
option4: 'Option 4',
option5: 'Option 5',
}
},
dateTest: {type: 'input', label: 'Not HTM date', subtype: "date", },
},
};
// ===========================================
// Configuration for default tests
// ===========================================
let htmlDefaultConfig = {htmlTestSet_defaultno0:{type: "checkbox", default: true}, htmlTestSet_defaultno1:{type: "checkbox",},
htmlTestSet_defaultno2:{type: "text", default: 'abc'}, htmlTestSet_defaultno3:{type: "text",},
htmlTestSet_defaultno4:{type: "number", default: 100}, htmlTestSet_defaultno5:{type: "number",},
htmlTestSet_defaultno6:{type: "color", default: '#de1717'}, htmlTestSet_defaultno7:{type: "color",},
htmlTestSet_defaultno8:{type: "dropdown", default: 'option3', content: {option1: "option 1", option2: "option 2", option3: "option 3", },},
htmlTestSet_defaultno9:{type: "dropdown",content: {option1: "option 1", option2: "option 2", option3: "option 3", },},
htmlTestSet_defaultno10:{type: "list", default: 'option3',
content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4", option5: "option 5", },},
htmlTestSet_defaultno11:{type: "list",
content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4", option5: "option 5", },},
htmlTestSet_defaultno12:{type: "list", multi: true,
default: {option1: true, option2: true, option3: true, option4: true, option5: true, option6: true, option7: true, },
content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4", option5: "option 5", option6: "option 6", option7: "option 7", },
},
htmlTestSet_defaultno13:{type: "list", multi: true,
content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4", option5: "option 5", option6: "option 6", option7: "option 7", },
},
htmlTestSet_defaultno14:{type: "textarea", default: 'abcd'}, htmlTestSet_defaultno15:{type: "textarea",},
htmlTestSet_defaultno16:{type: "input", subtype: "date", default:"2010-01-01"}, htmlTestSet_defaultno17:{type: "input", subtype: "date",},
htmlTestSet_defaultno18:{type: "input", subtype: "datetime-local", default:"2010-01-01T01:00"}, htmlTestSet_defaultno19:{type: "input", subtype: "datetime-local",},
htmlTestSet_defaultno20:{type: "input", subtype: "time", default: "01:00"}, htmlTestSet_defaultno21:{type: "input", subtype: "time"}
};
let htmdefaultTestConfig = {type: 'page', label: 'Default Test',
content: {defaultTestHtml: {type: 'html', label: 'Html For The Test', html: htmlDefaultTest,
content: htmlDefaultConfig},
},
};
// ===========================================
// Configuration for callback tests
// ===========================================
let htmCallbackConfig = {htmlTestSet_callbackTests_no0:{type: "number", default: 6, min: 5, max: 10,},
htmlTestSet_callbackTests_no1:{type: "text", default: 'abcd', match: '^[a-z]*$'},
htmlTestSet_callbackTests_no2:{type: "text", default: '2010-01-01', validate: validateDate},
htmlTestSet_callbackTests_no3:{type: "dropdown", default: 'option1', on_change: sendAlertOnChange,
content: {option1: "option 1", option2: "option 2", option3: "option 3", },},
htmlTestSet_callbackTests_no4:{type: "button", on_click: sendAlertOnClick},
htmlTestSet_callbackTests_no5:{type: "number", default: 55, min: 50, max: 60,},
htmlTestSet_callbackTests_no6:{type: 'other', validate: validateTextArea},
};
let htmlCallbackTestConfig = {type: 'page', label: 'Callback Test',
content: {callbackTestHtml: {type: 'html', html: htmlCallbackTest, shade: true, content: htmCallbackConfig},
callbackTestNumber: {type: 'number', label: 'Between 100 and 150', default:106, min:100, max: 150},
callbackTestText: {type: 'text', label: 'Uppercase only', default: 'ABCD', match: '^[A-Z]*$'},
callbackTestDate: {type: "text", label: 'YYYY-MM-DD hh:mm', default: '2010-01-01', validate: validateDateTime},
},
};
// ===========================================
// Configuration for refresh tests
// ===========================================
let htmlRefreshConfig = {htmlTestSet_refreshTests_no0: {type: 'number',},
htmlTestSet_refreshTests_no1: {type: 'button', on_click: resetToZero},
htmlTestSet_refreshTests_no2:{type: "checkbox", refresh_on_change:true},
htmlTestSet_refreshTests_no3:{type: "text", refresh_on_change:true},
htmlTestSet_refreshTests_no4:{type: "number", refresh_on_change:true},
htmlTestSet_refreshTests_no5:{type: "color", refresh_on_change:true},
htmlTestSet_refreshTests_no6:{type: "dropdown", refresh_on_change:true, content: {option1: "option 1", option2: "option 2", option3: "option 3", },},
htmlTestSet_refreshTests_no7:{type: "list", refresh_on_change:true, content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4", option5: "option 5", },},
htmlTestSet_refreshTests_no8:{type: "list", refresh_on_change:true, multi: true, content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4",
option5: "option 5", option6: "option 6", option7: "option 7", },
},
htmlTestSet_refreshTests_no9:{type: "other", refresh_on_change:true},
htmlTestSet_refreshTests_no10:{type: "input", subtype: "date", refresh_on_change:true},
htmlTestSet_refreshTests_no11:{type: "input", subtype: "datetime-local", refresh_on_change:true},
htmlTestSet_refreshTests_no12:{type: "input", subtype: "time", refresh_on_change:true}, };
let htmlRefreshTestConfig = {type: 'page', label: 'Refresh Test',
content: {refreshTestHtml: {type: 'html', label: 'Html For The Test', shade: true, html: htmlRefreshTest,
content: htmlRefreshConfig},
},
};
// ===========================================
// Construction of the dialog and load
// ===========================================
htmlTestSetDialog = new wkof.Settings({
script_id: htmlTestSetScriptId,
title: htmlTestSetTitle,
content: {htmlTestsSet: {type:'tabset', content: {tabBasicTests: basicTestConfig, tabVisualTest: visualTestConfig, tabTagTest: htmlTagTestConfig,
tabDefaultTest: htmdefaultTestConfig, tabCallbackTest: htmlCallbackTestConfig,
tabRefreshTest: htmlRefreshTestConfig}},
}
});
htmlTestSetDialog.load().then(function() {
updateFiltersWhenReady();
htmlTestSetLoadedPromise.resolve();
});
});
return htmlTestSetLoadedPromise;
}
// BEGIN HTML and CSS Tests
let htmlTestHover_tip = 'HTML and CSS tests For data types and classes for styling the layout';
function registerBaseTestsFilter() {
wkof.ItemData.registry.sources.wk_items.filters[baseTestsFilterName] = {
type: 'html',
html: htmlBaseTest,
label: 'HTML and CSS Test',
filter_func: nullFilter,
set_options: function(options) { return; },
hover_tip: htmlTestHover_tip,
};
}
function nullFilter(filterValue, item) {
return true;
}
// END HTML and CSS tests
// BEGIN Path Test
let pathTestHover_tip = 'Tests whether settings are stored in the right path';
let htmPathConfig = {htmlTestSet_pathTests_no0:{type: "checkbox", default: false}, htmlTestSet_pathTests_no1:{type: "text", default: 'Default'},
htmlTestSet_pathTests_no2:{type: "number", default: 999}, htmlTestSet_pathTests_no3:{type: "color", default: '#000000'},
htmlTestSet_pathTests_no4:{type: "dropdown", default: 'option3', content: {option1: "option 1", option2: "option 2", option3: "option 3", },},
htmlTestSet_pathTests_no5:{type: "list", default: 'option4', content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4", option5: "option 5", },},
htmlTestSet_pathTests_no6:{type: "list", multi: true, default: {option1: false, option2: true, option3: true, option4: false,
option5: false, option6: false, option7: false, },
content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4",
option5: "option 5", option6: "option 6", option7: "option 7", },
},
htmlTestSet_pathTests_no7:{type: "other"}, htmlTestSet_pathTests_no8:{type: "input", subtype: "date", default: '2020-01-01'},
htmlTestSet_pathTests_no9:{type: "input", subtype: "datetime-local", default: '2020-01-01T00:00'},
htmlTestSet_pathTests_no10:{type: "input", subtype: "time", default: '00:00'}, };
function registerPathTestsFilter() {
wkof.ItemData.registry.sources.wk_items.filters[pathTestsFilterName] = {
type: 'html',
html: htmlPathTest,
label: 'Path Test',
default: {},
filter_func: nullFilter,
set_options: function(options) { return; },
hover_tip: pathTestHover_tip,
content: htmPathConfig,
};
}
// END Path tests
// BEGIN Default Test
let defaultTestHover_tip = 'Tests whether the defaults are properly processed';
let htmlDefaultConfig = {htmlTestSet_defaultno0:{type: "checkbox", default: true}, htmlTestSet_defaultno1:{type: "checkbox",},
htmlTestSet_defaultno2:{type: "text", default: 'abc'}, htmlTestSet_defaultno3:{type: "text",},
htmlTestSet_defaultno4:{type: "number", default: 100}, htmlTestSet_defaultno5:{type: "number",},
htmlTestSet_defaultno6:{type: "color", default: '#de1717'}, htmlTestSet_defaultno7:{type: "color",},
htmlTestSet_defaultno8:{type: "dropdown", default: 'option3', content: {option1: "option 1", option2: "option 2", option3: "option 3", },},
htmlTestSet_defaultno9:{type: "dropdown",content: {option1: "option 1", option2: "option 2", option3: "option 3", },},
htmlTestSet_defaultno10:{type: "list", default: 'option3',
content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4", option5: "option 5", },},
htmlTestSet_defaultno11:{type: "list",
content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4", option5: "option 5", },},
htmlTestSet_defaultno12:{type: "list", multi: true,
default: {option1: true, option2: true, option3: true, option4: true, option5: true, option6: true, option7: true, },
content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4", option5: "option 5", option6: "option 6", option7: "option 7", },
},
htmlTestSet_defaultno13:{type: "list", multi: true,
content: {option1: "option 1", option2: "option 2", option3: "option 3", option4: "option 4", option5: "option 5", option6: "option 6", option7: "option 7", },
},
htmlTestSet_defaultno14:{type: "textarea", default: 'abcd'}, htmlTestSet_defaultno15:{type: "textarea",},
htmlTestSet_defaultno16:{type: "input", subtype: "date", default:"2010-01-01"}, htmlTestSet_defaultno17:{type: "input", subtype: "date",},
htmlTestSet_defaultno18:{type: "input", subtype: "datetime-local", default:"2010-01-01T01:00"}, htmlTestSet_defaultno19:{type: "input", subtype: "datetime-local",},
htmlTestSet_defaultno20:{type: "input", subtype: "time", default: "01:00"}, htmlTestSet_defaultno21:{type: "input", subtype: "time"}
};
function registerDefaultTestsFilter() {
wkof.ItemData.registry.sources.wk_items.filters[defaultTestsFilterName] = {
type: 'html',
html: htmlDefaultTest,
label: 'Default Test',
default: {},
filter_func: nullFilter,
set_options: function(options) { return; },
hover_tip: defaultTestHover_tip,
content: htmlDefaultConfig,
};
}
// END Default tests
// BEGIN Callback Test
let callbackTestHover_tip = 'Whether validation and callbacks work in filters';
let htmCallbackConfig = {htmlTestSet_callbackTests_no0:{type: "number", default: 6, min: 5, max: 10,},
htmlTestSet_callbackTests_no1:{type: "text", default: 'abcd', match: '^[a-z]*$'},
htmlTestSet_callbackTests_no2:{type: "text", default: '2010-01-01', validate: validateDate},
htmlTestSet_callbackTests_no3:{type: "dropdown", default: 'option1', on_change: sendAlertOnChange,
content: {option1: "option 1", option2: "option 2", option3: "option 3", },},
htmlTestSet_callbackTests_no4:{type: "button", on_click: sendAlertOnClick},
htmlTestSet_callbackTests_no6:{type: 'other', validate: validateTextArea},
};
function registerCallbackTestsFilter() {
wkof.ItemData.registry.sources.wk_items.filters[callbackTestsFilterName] = {
type: 'html',
html: htmlCallbackTestCore,
label: 'Callback and Validation Test',
default: {},
filter_func: nullFilter,
set_options: function(options) { return; },
hover_tip: callbackTestHover_tip,
content: htmCallbackConfig,
};
}
// END Callback test
// BEGIN First Filter Test
let filterTestHover_tip = 'Whether filters with filter_value_map work';
let htmFilterConfig = {htmlTestSet_filterTests_no0:{type: "list", multi: true, default:{radical: false, kanji: false, vocabulary: false, },
content: {radical: "radical", kanji: "kanji", vocabulary: "vocabulary", },},
htmlTestSet_filterTests_no1:{type: "text", default: '2010-01-01', validate: validateDate},
htmlTestSet_filterTests_no2:{type: "text", default: '2020-12-31', validate: validateDate},
};
function registerFilterTestsFilter() {
wkof.ItemData.registry.sources.wk_items.filters[filterTestsFilterName] = {
type: 'html',
html: htmlFilterTestA,
label: 'Filter Test With <code>filter_value_map</code>',
default: {},
filter_func: combinedlFilter,
filter_value_map: filter_value_map_wrapper.bind(null, parseDateTime),
set_options: function(options) { options.assignments = true; },
hover_tip: filterTestHover_tip,
content: htmFilterConfig,
};
}
function combinedlFilter(filterValue, item) {
if (!filterValue.htmlTestSet_filterTests_no0[item.object]) return false;
if (item.assignments === undefined) return false;
if (item.assignments.started_at === undefined) return false;
let date = Date.parse(item.assignments.started_at);
if (date < filterValue.afterDate) return false;
return date <= filterValue.beforeDate;
};
function filter_value_map_wrapper(funct, param){
param.afterDate = funct(param.htmlTestSet_filterTests_no1).getTime();
param.beforeDate = funct(param.htmlTestSet_filterTests_no2).getTime();
return param;
};
// BEGIN Second Filter Test
let filterTestBHover_tip = 'Whether filters without filter_value_map work';
let htmFilterBConfig = {htmlTestSet_filterTestsB_no1:{type: "number", },
htmlTestSet_filterTestsB_no2:{type: "number", },
};
function registerFilterTestsBFilter() {
wkof.ItemData.registry.sources.wk_items.filters[filterTestsBFilterName] = {
type: 'html',
html: htmlFilterTestB,
label: 'Filter Test Without <code>filter_value_map</code>',
default: {},
filter_func: combinedlFilterB,
set_options: function(options) { options.review_statistics = true; },
hover_tip: filterTestBHover_tip,
content: htmFilterBConfig,
};
}
function combinedlFilterB(filterValue, item) {
if (item.review_statistics === undefined) return false;
let percent = item.review_statistics.percentage_correct;
if (percent === undefined) return false;
if (percent < filterValue.htmlTestSet_filterTestsB_no1) return false;
return percent <= filterValue.htmlTestSet_filterTestsB_no2;
};
// END Second Filter test
// BEGIN Item List Test
let filterItemListBHover_tip = 'Specify lists of items to be accepted.';
let htmItemListConfig = {htmlTestSet_itemList_radical:{type: "textarea", default: '', on_change: setDownloadLink},
htmlTestSet_itemList_kanji:{type: "textarea", default: '', on_change: setDownloadLink},
htmlTestSet_itemList_vocabulary:{type: "textarea", default: '', on_change: setDownloadLink},
htmlTestSet_itemList_upload:{type: "button", on_click: uploadFile},
htmlTestSet_itemList_download:{type: "button", on_click: onClickDownload},
};
function registerItemListFilter() {
wkof.ItemData.registry.sources.wk_items.filters[filterItemListFilterName] = {
type: 'html',
html: htmlFilterTestC,
label: 'Item List',
default: {},
filter_func: itemListFilter,
filter_value_map: prepareFilter,
pre_open: initializeDownloadLink,
set_options: function(options) { return; },
hover_tip: filterItemListBHover_tip,
content: htmItemListConfig,
};
}
//-------------------------------------------------------------------
function split_list(str) {return str.replace(/、/g,',').replace(/[\r\n\s ]+/g,' ').trim().replace(/ *, */g, ',').split(',').filter(function(name) {return (name.length > 0);});}
function itemListFilter(filterValue, item) {
let type = item.object;
if (type === 'radical') if (item.data.characters !== null) if (filterValue.radical.indexOf(item.data.characters) >= 0) return true;
return filterValue[type].indexOf(item.data.slug) >= 0;
};
function prepareFilter(filterValue){
let renamed = {};
renamed.radical = split_list(filterValue.htmlTestSet_itemList_radical);
renamed.kanji = split_list(filterValue.htmlTestSet_itemList_kanji);
renamed.vocabulary = split_list(filterValue.htmlTestSet_itemList_vocabulary);
return renamed;
}
function onClickDownload(name, config, on_change){
let root = this.closest('.html_type');
var buttons = $(root).find(".files");
buttons.find('.note').remove();
}
function initializeDownloadLink(elem, path){
let radicals = eval(path+'.htmlTestSet_itemList_radical');
let kanji = eval(path+'.htmlTestSet_itemList_kanji');
let vocabulary = eval(path+'.htmlTestSet_itemList_vocabulary');
let encoded = makeEncode(radicals, kanji, vocabulary);
let downloadElem = $(elem).find("a[name='htmlTestSet_itemList_link']");
downloadElem.attr("href", "data:text/plain; charset=utf-8,"+encoded);
}
function setDownloadLink(name, value, config){
let root = this.closest('.html_type');
var buttons = $(root).find(".files");
buttons.find('.note').remove();
let radicalElem = $(root).find(".setting[name='htmlTestSet_itemList_radical']");
let kanjiElem = $(root).find(".setting[name='htmlTestSet_itemList_kanji']");
let vocabularyElem = $(root).find(".setting[name='htmlTestSet_itemList_vocabulary']");
let radicals = radicalElem.val();
let kanji = kanjiElem.val();
let vocabulary = vocabularyElem.val();
let encoded = makeEncode(radicals, kanji, vocabulary);
let downloadElem = $(root).find("a[name='htmlTestSet_itemList_link']");
downloadElem.attr("href", "data:text/plain; charset=utf-8,"+encoded);
}
function makeEncode(radicals, kanji, vocabulary){
let list = [];
list.push('radicals');
list.push(radicals);
list.push('kanji');
list.push(kanji);
list.push('vocabulary');
list.push(vocabulary);
let text = list.join('\n');
return encodeURI("\uFEFF"+text);
}
function uploadFile(name, config, on_change){
let root = this.target.closest('.html_type');
var buttons = $(root).find(".files");
buttons.find('.note').remove();
let fileElem = $(root).find("input[name='htmlTestSet_itemList_file']");
let filenames = fileElem.prop('files');
if (filenames.length === 0){
buttons.append('<div class="note error">'+'Plese select a file'+'</div>');
return;
}
let filename = filenames[0];
let reader = new FileReader();
reader.onload = validateReception;
reader.readAsText(filename);
function validateReception(event){
let result = receiveText(event);
if (typeof result === 'string'){
var buttons = $(root).find(".files");
buttons.find('.note').remove();
buttons.append('<div class="note error">'+result+'</div>');
};
}
function receiveText(event){
let text = event.target.result;
let radicals, kanji, vocabulary;
let errorMsg = 'Invalid file content';
text = text.replaceAll('\n','');
let start = text.indexOf('radicals');
if (start !== 0) return errorMsg;
start = start + 'radicals'.length;
let end = text.indexOf('kanji');
if (end <= start) return errorMsg;
radicals = text.slice(start, end);
start = end + 'kanji'.length;
end = text.indexOf('vocabulary');
if (end <= start) return errorMsg;
kanji = text.slice(start, end);
start = end + 'vocabulary'.length;
vocabulary = text.slice(start);
let elem = $(root).find(".setting[name='htmlTestSet_itemList_radical']");
elem.val(radicals);
elem.change();
elem = $(root).find(".setting[name='htmlTestSet_itemList_kanji']");
elem.val(kanji);
elem.change();
elem = $(root).find(".setting[name='htmlTestSet_itemList_vocabulary']");
elem.val(vocabulary);
elem.change();
return true;
}
}
// END Item List Filter test
function sendAlertOnChange(){
alert('The dropdown selection has been changed.');
}
function sendAlertOnClick(e){
alert('The button has been clicked.');
}
function resetToZero(e){
wkof.settings[htmlTestSetScriptId].htmlTestSet_refreshTests_no0 = 0;
alert('Control has been resetted to zero');
}
function validateTextArea(value, config){
console.log('validateTextArea is called');
let match = /^\s*[a-zA_Z]+(?:\s*,\s*[a-zA-Z]+)*\s*$/.test(value);
if (match) return true;
return 'Invalid list of words';
}
function validateTextAreaKanji(value, config){
let list = split_list(value);
let result = true;
list.forEach(item=>{result = result && item.match(/^[-a-zA-Z0-9\u3040-\u309f\u30a0-\u30ff\uff00-\uffef\u4e00-\u9faf\u3400-\u4dbf\u3005]+$/) !== null})
// Hiragana: [\u3040-\u309f]
// Katakana: [\u30a0-\u30ff]
// Roman characters + half-width katakana: [\uff00-\uffef]
// Kanji: [\u4e00-\u9faf]|[\u3400-\u4dbf]
// Repeater: \u3005
// see http://www.rikai.com/library/kanjitables/kanji_codes.unicode.shtml
if (result === true) return true;
return 'Invalid list of words';
}
//=======================================
// Date Validation and Parsing Functions
//=======================================
//=======================================
// All time validation functions and the parsing function accept
// YYYY-MM-DD 24:00 to mean next day at 00:00
// According to wikipedia this is part of the 24 hours time comvention
//=======================================
//=======================================
// This group of functions nails the format to YYYY-MM-DD something
//=======================================
// Error messages
const errorWrongDateTimeFormat = 'Use YYYY-MM-DD HH:MM [24h, 12h]';
const errorWrongDateTimeRelativeFormat = 'Use YYYY-MM-DD HH:MM [24h, 12h]<br>Or +10d3h45m or -4h12h30m<br>+- needed, rest may be omitted';
const errorWrongDateTimeFullFormat = 'Use YYYY-MM-DD HH:MM:SS.mmm<br>Seconds and milliseconds optional';
const errorWrongDateTimeFullRelativeFormat = 'Use YYYY-MM-DD HH:MM:SS.mmm<br>Seconds and milliseconds optional<br>Or +10d3h45m12s -4h12h30m10s<br>+- needed, rest may be omitted';
const errorWrongDateFormat = 'Invalid date - Use YYYY-MM-DD';
const errorWrongDateRelativeFormat = 'Invalid date - Use YYYY-MM-DD<br>Or +10d or -2d';
const errorOutOfRange = 'Number out of range';
//=======================================
// Validates datetime in YYYY-MM-DD HH:MM format
// Accepts both 24h and 12h formats (am pm)
// Accepts YYYY-MM-DD (HH:MM omitted)
// Bissextile years are properly processed
// Suitable for use as validate callback in a text component of a setting
function validateDateTime(dateString, config){
dateString = dateString.trim();
if (dateString.length > 18){
return errorWrongDateTimeFormat;
} else {
let result = validateDate(dateString.slice(0,10), config);
if (result === errorOutOfRange) return errorOutOfRange;
if (result !== true) return errorWrongDateTimeFormat;
if (dateString.length === 10) return true; //Valid YYY-MM-DD and nothing else
result = validateTime(dateString.slice(0,16));
if (result === errorOutOfRange) return errorOutOfRange;
if (result !== true) return errorWrongDateTimeFormat;
if (dateString.length === 16){
return true
} else {
if (dateString.length === 18){
let suffix = dateString.slice(16)
if (suffix === 'am' || suffix === 'pm'){
let hh = Number(dateString.slice(11, 13))
if (hh < 1 || hh > 12){return errorOutOfRange}
return true
} else {
return errorWrongDateTimeFormat;
}
}
return errorWrongDateTimeFormat;
};
};
return errorWrongDateTimeFormat;
};
//=======================================
// Validates datetime in YYYY-MM-DD HH:MM format or relative time format
// Accepts both 24h and 12h formats (am pm)
// Accepts YYYY-MM-DD (HH:MM omitted)
// Bissextile years are properly processed
// Suitable for use as validate callback in a text component of a setting
function validateDateTimeRelative(dateString, config){
dateString = dateString.trim();
if (dateString.match(/^([+-])(?:(\d+)[dD])?(?:(\d+)[hH])?(?:(\d+)[mM])?$/) !== null){
if (dateString === '+' || dateString === '-') return errorWrongDateTimeRelativeFormat
return true;
} else {
let result = validateDateTime(dateString, config)
if (result === true || result === errorOutOfRange) return result;
return errorWrongDateTimeRelativeFormat;
}
};
//=======================================
// Validate datetime in YYYY-MM-DD HH:MM:SS.mmm format
// Seconds and milliseconds are optional
// Bissextile years are properly processed
// Suitable for use as validate callback in a text component of a setting
function validateDateTimeFull(dateString, config){
dateString = dateString.trim();
let result = validateDateTime(dateString.slice(0, 16), config);
if (result === errorOutOfRange){
return errorOutOfRange;
} else if (result !== true){
return errorWrongDateTimeFullFormat;
} else if (dateString.length <= 16){
return true // seconds and milliseconds omitted
} else {
var regEx = /^:(\d{2}|\d{2}\.\d{3})$/;
if(!dateString.slice(16).match(regEx)) return errorWrongDateTimeFullFormat; // Invalid format
let d = new Date(dateString);
let dNum = d.getTime();
if(!dNum && dNum !== 0) return errorOutOfRange; // NaN value, Invalid date
return true
}
}
//=======================================
// Validate datetime in YYYY-MM-DD HH:MM:SS.mmm format or relative format
// Seconds and milliseconds are optional
// Bissextile years are properly processed
// Suitable for use as validate callback in a text component of a setting
function validateDateTimeFullRelative(dateString, config){
dateString = dateString.trim();
if (dateString.match(/^([+-])(?:(\d+)[dD])?(?:(\d+)[hH])?(?:(\d+)[mM])?(?:(\d+)[sS])?$/) !== null){
if (dateString === '+' || dateString === '-') return errorWrongDateTimeFullRelativeFormat
return true;
} else {
let result = validateDateTimeFull(dateString, config)
if (result === true || result === errorOutOfRange) return result;
return errorWrongDateTimeFullRelativeFormat;
}
};
//=======================================
// Validates dates in YYYY-MM-DD format
// Bissextile years are properly processed
// Suitable for use as validate callback in a text component of a setting
function validateDate(dateString, config, keyword) {
dateString = dateString.trim();
let regEx = /^\d{4}-\d{2}-\d{2}$/;
if(!dateString.match(regEx)) return errorWrongDateFormat; // Invalid format
let d = new Date(dateString);
let dNum = d.getTime();
if(!dNum && dNum !== 0) return errorOutOfRange; // NaN value, Invalid date
let r = d.toISOString().slice(0,10) === dateString;
if (r) {
return true
} else {
return errorOutOfRange
};
}
//=======================================
// Validates dates in YYYY-MM-DD format or relative format
// Bissextile years are properly processed
// Suitable for use as validate callback in a text component of a setting
function validateDateRelative(dateString, config){
dateString = dateString.trim();
if (dateString.match(/^([+-])(?:(\d+)[dD])?$/) !== null){
if (dateString === '+' || dateString === '-') return errorWrongDateRelativeFormat
return true;
} else {
let result = validateDate(dateString, config)
if (result === true || result === errorOutOfRange) return result;
return errorWrongDateRelativeFormat;
}
};
//=======================================
// Helper function to validate time in HH:MM format
// It should not be publicly exposed
function validateTime(timeString) {
let regEx = /^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}$/;
if(!timeString.match(regEx)) return 'No match'; // Invalid format
let d = new Date(timeString);
let dNum = d.getTime();
if(!dNum && dNum !== 0) return errorOutOfRange; // NaN value, Invalid date
return true
}
//=======================================
// Parses a validated date in YYYY-MM-DD format
// Also parse a validated datetime in YYYY-MM-DD HH:MM format
// Parses datetime in both 12h and 24h formats
// Parses optional seconds and milliseconds
// Returns the corresponding date object for this date/datetime in the local time zone
// May return an invalid date if presented with empty or invalid data - but not always
// If there is doubt about the quality of the data, validate first
// Suitable to parse a validated date from a text component in a setting
function parseDateTime(dateString) {
dateString = dateString.trim(); // validation allows leading and trailing blanks
try {
if (dateString === '') return new Date('###'); // returns an invalid date
let match = dateString.match(/^([+-])(?:(\d+)[dD])?(?:(\d+)[hH])?(?:(\d+)[mM])?(?:(\d+)[sS])?$/);
if (match !== null){
if (dateString === '+' || dateString === '-') return new Date('###'); // returns an invalid date
let date = Date.now();
let sign = (match[1] === '+' ? 1 : -1);
let days = (match[2] || 0) * 86400000;
let hrs = (match[3] || 0) * 3600000;
let min = (match[4] || 0) * 60000;
let sec = (match[5] || 0) * 1000;
return new Date(date + sign * (days + hrs + min + sec));
}
// new Date() uses local time zone when the parameters are separated
let YY = Number(dateString.substring(0, 4));
let MM = Number(dateString.substring(5, 7))-1;
let DD = Number(dateString.substring(8, 10));
let hh = (dateString.length >= 13) ? Number(dateString.substring(11, 13)) : 0;
let mm = (dateString.length >= 16) ? Number(dateString.substring(14, 16)) : 0;
let ss = (dateString.length >= 19) ? Number(dateString.substring(17, 19)) : 0;
let ml = (dateString.length === 23) ? Number(dateString.substring(20, 23)) : 0;
let suffix = (dateString.length === 18) ? dateString.substring(16, 18) : ''
if (suffix === 'am' || suffix === 'pm'){ // if 12 hours format, convert to 24 hours
if (hh === 12) hh = 0;
if (suffix === 'pm') hh += 12;
}
return new Date(YY, MM, DD, hh, mm, ss, ml);
} catch (e) {
return new Date('###'); // returns an invalid date in case of error
}
}
})(window.wkof);