WaniKani Open Framework Html Test Set

Testing Set for the WaniKani Open Framework Html Type

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==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);