WaniKani Item Inspector

Inspect Items in Tabular Format

当前为 2020-10-10 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

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

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name          WaniKani Item Inspector
// @namespace     wk-dashboard-item-inspector
// @description   Inspect Items in Tabular Format
// @author        prouleau
// @version       1.10.1
// @include       https://www.wanikani.com/dashboard
// @include       https://www.wanikani.com/
// @grant         none
// ==/UserScript==

// @require       https://greasyfork.org/scripts/40692-wanikani-open-framework-additional-filters/code/WaniKani%20Open%20Framework%20Additional%20Filters.user.js
// @require       https://greasyfork.org/scripts/377971-wanikani-open-framework-visually-similar-kanji-filter/code/Wanikani%20Open%20Framework:%20Visually%20similar%20kanji%20filter.user.js
// @require       https://greasyfork.org/scripts/377613-wanikani-open-framework-jlpt-joyo-and-frequency-filters/code/Wanikani%20Open%20Framework%20JLPT,%20Joyo,%20and%20Frequency%20filters.user.js


(function() {
    'use strict';
    //------------------------------
    // Wanikani Framework
    //------------------------------
    if (!window.wkof) {
        var script_name = 'Wanikani Item Inspector';
        var response = confirm(script_name + ' 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 scriptId = 'Item_Inspector';
    var scriptTitle = 'Item Inspector';

    var quiz_setup_state = 'init';
    function open_settings_dialog() {
        wkof.Settings.load(scriptId)
            .then(function(){
            quiz_setup_state = 'ready';
            init_settings();
        })
        open_quiz_settings();
    }


    //------------------------------
    // Styling
    //------------------------------
    var fontColor;
    var secondaryFontColor;
    function table_css(){
        let is_dark = is_dark_theme();
        fontColor = (is_dark ? '#000000' : '#ffffff');
        secondaryFontColor = (is_dark ? '#212020' : 'gainsboro');
        var leechTableCss = `
            /* Control Bar */

           .WkitControlBar {
                  position: relative;
                  margin: 7px 0.6% 7px 2.6%;
            }

            /* to prevent rendering problems */
            #WkitTopBar {
                  position: relative;
                  display: inline-block;
                  width: 103.2%;
                  margin-left: -27px;
                  margin-bottom: 30px;
                  padding-top: 3px;
                  padding-bottom: 3px;
                  padding-right: 3px;
                  padding-left: 3px;
             }


            #WkitTopBar .WkitSmallCaps {
                  font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
                  margin: 0px;
                  padding: 7.5px 30px;
                  background-color: #d5d5d5;
                  text-align: center;
                  border-radius: 5px 5px 0 0;
                  font-size: 11px;
                  font-weight: bold;
                  letter-spacing: 0;
                  line-height: 20px;
                  color: #555;
                  text-transform: uppercase;
                  text-shadow: 0 1px 0 #fff;
                  ${is_dark ? 'align-items: center;' : ''}
                  ${is_dark ? 'background-color: #1c1e21;' : ''}
                  ${is_dark ? 'box-shadow: 0 1px 1px rgba(0, 0, 0, 0.7), 0 2px 2px rgba(0, 0, 0, 0.7);' : ''}
                  ${is_dark ? 'color: #bcbcbc;' : ''}
                  ${is_dark ? 'display: flex;' : ''}
                  ${is_dark ? 'margin-bottom:;' : ''}
                  ${is_dark ? 'max-height: 60px;' : ''}
                  ${is_dark ? 'padding-bottom: 3px;' : ''}
                  ${is_dark ? 'padding-top: 3px;' : ''}
                  ${is_dark ? 'text-align: left;' : ''}
            }

            #WkitTopBar .WkitTableList {
                  position: relative;
                  margin: 0 0 30px;
            }

            #WkitTopBar .WkitTableList table{
                  width: 100%;
                  max-width: 100%;
                  background-color: transparent;
                  border-collapse: collapse;
                  border-spacing: 0;
            }

            #WkitTopBar .WkitTableList table,
            #WkitTopBar .right table{
                  width: 100%;
                  line-height: 1em;
                  color: ${is_dark ? '#bcbcbc' : '#fff'};
                  /*color: inherit;*/
            }

            #WkitTopBar .WkitTableList table a {
                  text-decoration: none;
            }

            #WkitTopBar .WkitTableList .WkitMainElement {
                  display: block;
                  padding: 0.7em 1em;
                  margin: 0px;
                  color: #fff;
                  text-decoration: none;
                  -webkit-transition: text-shadow ease-out 0.3s;
                  -moz-transition: text-shadow ease-out 0.3s;
                  -o-transition: text-shadow ease-out 0.3s;
                  transition: text-shadow ease-out 0.3s;
            }

            #WkitTopBar .WkitTableList table tr{
                  border-top: 0;
                  border-bottom: 0;
                  border-left: 0;
                  text-shadow: 0 1px 0 rgba(0,0,0,0.2);
            }

            #WkitTopBar .WkitTableList table td{
                  -webkit-box-sizing: border-box;
                  -moz-box-sizing: border-box;
                  box-sizing: border-box;
            }

           #WkitTopBar .WkitTableList table tr[class=vocabulary]{
                  background-color: #a100f1;
                  background-image: -moz-linear-gradient(top, #a0f, #9300dd);
                  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#a0f), to(#9300dd));
                  background-image: -webkit-linear-gradient(top, #a0f, #9300dd);
                  background-image: -o-linear-gradient(top, #a0f, #9300dd);
                  background-image: linear-gradient(to bottom, #a0f, #9300dd);
                  background-repeat: repeat-x;
                  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFAA00FF', endColorstr='#FF9300DD', GradientType=0);
                  border-top: 1px solid #c655ff;
                  border-bottom: 1px solid #8800cc;
                  border-left: 1px solid #c655ff;        }

            #WkitTopBar .WkitTableList table tr[class=kanji]{
                  background-color: #f100a1;
                  background-image: -moz-linear-gradient(top, #f0a, #dd0093);
                  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f0a), to(#dd0093));
                  background-image: -webkit-linear-gradient(top, #f0a, #dd0093);
                  background-image: -o-linear-gradient(top, #f0a, #dd0093);
                  background-image: linear-gradient(to bottom, #f0a, #dd0093);
                  background-repeat: repeat-x;
                  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFF00AA', endColorstr='#FFDD0093', GradientType=0);
                  border-top: 1px solid #f6c;
                  border-bottom: 1px solid #cc0088;
                  border-left: 1px solid #f6c;
            }

            #WkitTopBar .WkitTableList table tr[class=radical]{
                  background-color: #00a1f1;
                  background-image: -moz-linear-gradient(top, #0af, #0093dd);
                  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0af), to(#0093dd));
                  background-image: -webkit-linear-gradient(top, #0af, #0093dd);
                  background-image: -o-linear-gradient(top, #0af, #0093dd);
                  background-image: linear-gradient(to bottom, #0af, #0093dd);
                  background-repeat: repeat-x;
                  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FF00AAFF', endColorstr='#FF0093DD', GradientType=0);
                  border-top: 1px solid #88d7ff;
                  border-bottom: 1px solid #069;
                  border-left: 1px solid #88d7ff;
            }

            #WkitTopBar .WkitItemList {
                  visibility: visible;
                  position: relative;
                  background-color: #0000001a;
                  display: -webkit-flex;
                  display: flex;
                  flex-direction: row;
                  flex-wrap: wrap;
                  line-height: 1;
                  width: 96.1%;
                  margin-left: 29px;
                  margin-right: 4px;
                  padding-top: 3px;
                  padding-bottom: 3px;
                  padding-right: 3px;
                  padding-left: 3px;
                  border-radius: 5px;
            }

            #WkitTopBar .WkitItemList.WkitFlexJustified {
                  justify-content: space-between;
            }

            #WkitTopBar .WkitItemList.WkitFlexLeft {
                  justify-content: flex-start;
            }

            #WkitTopBar .WkitSmallCapsList {
                  font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
                  background-color: #cccccc;
                  text-align: center;
                  width: max-content;
                  font-weight: bold;
                  letter-spacing: 0;
                  color: #241f42;
                  text-transform: uppercase;
                  border-radius: 5px;
                  border-color: #000000;
                  border-width: 1px;
                  border-style: solid;
                  ${is_dark ? 'align-items: center;' : ''}
${is_dark ? 'background-color: #1c1e21;' : ''}
${is_dark ? 'box-shadow: 0 1px 1px rgba(0, 0, 0, 0.7), 0 2px 2px rgba(0, 0, 0, 0.7);' : ''}
${is_dark ? 'color: #bcbcbc;' : ''}
${is_dark ? 'display: flex;' : ''}
${is_dark ? 'margin-bottom:;' : ''}
${is_dark ? 'max-height: 60px;' : ''}
${is_dark ? 'padding-bottom: 3px;' : ''}
${is_dark ? 'padding-top: 3px;' : ''}
${is_dark ? 'text-align: left;' : ''}
}

            #WkitTopBar .WkitSmallCapsList.WkitReading {
                  margin-top: 2px;
                  margin-bottom: 2px;
                  margin-left: 5px;
                  margin-right: 5px;
                  line-height: 1em;
                  padding: 15px 20px;
                  font-size: 14px;
             }

            #WkitTopBar .WkitSmallCapsList.WkitMeaning {
                  margin-top: 2px;
                  margin-bottom: 2px;
                  margin-left: 5px;
                  margin-right: 5px;
                  padding: 8px 20px;
                  font-size: 12px;
             }

            #WkitTopBar .WkitItemListed {
                display: inline-block;
                margin: 10px 5px;
                text-decoration-line: none;
            }

           #WkitTopBar .WkitItemList .WkitTooltipContent {
                padding: -4px;
            }

            #WkitTopBar .WkitItemListed span {
                border-radius: 5px;
                /*border-color: #000000;
                border-width: 1px;
                border-style: solid;*/
                color: #ffffff;
                line-height: 1em;
                padding: 6px;
                margin: 0;
                box-shadow: inset 0 -2px 0 rgba(0,0,0,0.2);
            }

            #WkitTopBar .WkitItemListed a {
                text-decoration-line: none;
            }

            #WkitTopBar .WkitMarker span {
                border-radius: 5px;
                font-size: 14px;
                line-height: 1em;
                padding: 14px 8px;
                margin: 0;
                box-shadow: inset 0 -2px 0 rgba(0,0,0,0.2);
                background-image: linear-gradient(0deg, #c1cdc5, #b0bfb5);
                background-color: #c1cdc5;
            }

            #WkitTopBar .WkitMarkerMeaning span {
                border-radius: 5px;
                font-size: 14px;
                line-height: 1em;
                padding: 6px 6px;
                margin: 0;
                text-decoration-line: none;
                box-shadow: inset 0 -2px 0 rgba(0,0,0,0.2);
                background-image: linear-gradient(0deg, #c1cdc5, #b0bfb5);
                background-color: #c1cdc5;
            }

            #WkitTopBar .left a {
                font-size: 74px;
                line-height: 73px;
                display: block;
                border-radius: 3px;
                margin: 3px 10px 0 3px;
            }

            #WkitTopBar .item.vocabulary .left a {
                margin-right: 3px;
                text-align: center;
            }

            #WkitTopBar .items .radical img {
                height: 14px;
                ${is_dark ? '' : 'filter: invert(1);'}
}

            #WkitTopBar .WkitItemListed img{
                 width: 30px;
                 height: 30px;
                ${is_dark ? '' : 'filter: invert(1);'}
}


            #WkitTopBar .WkitHeader {
                  background-color: ${is_dark ? '#232629' : '#5c6c705c'};
                  display: -webkit-flex;
                  display: flex;
                  justify-content: space-between;
                  padding: 3px;
                  width: calc(100% - 8px);
                  border-radius: 5px;
                  margin-left: -2px;
             }

            #WkitTopBar .WkitControlLeft {
                  display: block;
                  vertical-align: middle;
                  height: 100%;
                  padding-left: 2px;
            }

            #WkitTopBar .WkitControlRight {
                  display: block;
                  vertical-align: middle;
                  height: 100%;
                  padding-right: 3px;
            }

            #WkitTopBar #WkitRandomSelection {
                  margin-left: 15px;
            }

            #WkitTopBar .WkitDialogContainer {
                  display: none; /* Hidden by default */
                  position: absolute;
                  z-index: 1;
                  right: 12px;
                  top: 63px;
                  width: 156px;
                  height: auto;
                  padding: 5px;
                  overflow: auto;
                  background-color: rgb(0,0,0);
                  border-radius: 5px;
                  border-width: 1px;
            }

            #WkitTopBar .WkitFilterContainer {
                  display: none; /* Hidden by default */
                  position: absolute;
                  z-index: 1;
                  right: 60%;
                  top: 63px;
                  width: 156px;
                  height: auto;
                  padding: 5px;
                  overflow: auto;
                  background-color: rgb(0,0,0);
                  border-radius: 5px;
                  border-width: 1px;
            }

            #WkitTopBar .WkitExportButton{
                   z-index: 1; /* Sit on top */
                   border-width: 1px;
                   border-radius: 3px;
                   text-align: center;
                   min-width: 150px;
                   width: max-content;
                   height: 30px;
                   margin: 3px;
                   color: #000000;
                   background-color: #efefef;
                   text-decoration: none;
            }

            #WkitTopBar .WkitTitle {
                   vertical-align: middle;
                   font-size: 150%;
                   text-align: center;
                   margin-top: 3px;
                   margin-bottom: 3px;
                   width: 28%;
            }

           #WkitTopBar .WkitButton {
                   display: inline;
                   float: left;
                   vertical-align: middle;
                   border-width: 1px;
                   border-radius: 3px;
                   text-align: center;
                   min-width: 30px;
                   width: max-content;
                   height: 30px;
                   margin: 2px;
                   margin-top: 5px;
                   margin-bottom: 5px;
                   font-family: FontAwesome;
            }

           #WkitTopBar .WkitButton:not(.WkitActive) {
                   background-color: #efefef;
           }

           #WkitTopBar .WkitButton.WkitActive {
                   background-color: ${is_dark ? 'green' : '#00b300'} ! important;
           }

            #WkitTopBar .WkitTooltipContent .WkitMiniButton {
                   padding-right: 3px;
                   padding-left: 3px;
                   padding-top: 3px;
                   padding-bottom: 2px;
                   margin-top: 3px;
                   font-size: 12px;
                   line-height: 1em;
            }

            #WkitTopBar .WkitButton a {
                  color: rgb(0, 0, 0);
            }

            #WkitTopBar button a {
                  color: #000000;
                  text-decoration: none;
            }

           #WkitTopBar .WkitButtonLeft {
                   float: left;
            }

            #WkitTopBar .WkitButtonRight {
                   float: right;
            }

            #WkitTopBar .WkitEnglishButton {
                   font-size: 18px;
                   font-weight: bold;
            }

            #WkitTopBar .WkitSelector {
                   display: inline;
                   float: left;
                   vertical-align: middle;
                   margin-right: 3px;
                   margin-left: 3px;
                   margin-top: 5px;
                   margin-bottom: 5px;
                   border-width: 1px;
                   border-color: Black;
                   color: Black;
                   background-color: #efefef;
            }

            #WkitTopBar .WkitClipBoard {
                  display: inline-block;
                  width: 96%;
                  height: 420px;
                  margin-left: 29px;
             }

            #WkitTopBar .emptyMessage {
                  margin: 7px 0.6% 7px 2.6%;
                  padding: 5px;
                  padding-left: 15px;
                  padding-top: 10px;
                  background-color: Azure;
                  border-radius: 8px;
             }

            /* Pop ups, aka TOOL TIPS */

            #WkitTopBar .WkitTooltip {
                  display: inline-block;
                  position: relative;
                  padding: 0px;
            }

            #WkitTopBar .WkitTooltip .WkitTooltipContent {
                  display: inline-block;
                  visibility: hidden;
                  background-color: black;
                  color: ${is_dark ? '#bcbcbc' : '#fff'};
                  /*color: inherit;*/
                  font-size: 100%;
                  width: max-content;
                  max-width: 445px;
                  text-align: left;
                  margin: 5px;
                  padding: 2px;
                  border-radius: 3px;
                  position: absolute;
                  z-index: 1;
                  transition-delay: 0.1s;
            }

            #WkitTopBar .WkitTableList .WkitTooltip.WkitFirstItem .WkitTooltipContent {
                  top: 30px;
                  left: 0%;
                  transition-delay: 0.1s;
            }


            #WkitTopBar .WkitTableList .WkitTooltip.WkitLaterItem .WkitTooltipContent {
                  bottom: 30px;
                  left: 0%;
                  transition-delay: 0.1s;
            }


            #WkitTopBar .WkitItemList .WkitTooltipIcon.WkitFirstItem .WkitTooltipContent {
                  top: 55px;
                  left: 50%;
                  max-width: 250px;
                  transition-delay: 0.1s;
            }


            #WkitTopBar .WkitItemList .WkitTooltipIcon.WkitLaterItem .WkitTooltipContent {
                  bottom: 55px;
                  left: 50%;
                  max-width: 250px;
                  transition-delay: 0.1s;
            }


            #WkitTopBar .WkitItemList .WkitTooltipIconMeaning.WkitFirstItem .WkitTooltipContent {
                  top: 35px;
                  left: 50%;
                  max-width: 250px;
            }


            #WkitTopBar .WkitItemList .WkitTooltipIconMeaning.WkitLaterItem .WkitTooltipContent {
                  bottom: 35px;
                  left: 50%;
                  max-width: 250px;
            }


            #WkitTopBar .WkitTableList .WkitTooltip:hover div.WkitTooltipContent {
                  visibility: visible;
                  display: inline-block;
                  z-index: 50;
            }

            #WkitTopBar .WkitItemList .WkitTooltip:hover div.WkitTooltipContent {
                  visibility: visible;
                  display: inline-block;
                  z-index: 50;
                  transition-delay: 0.5s;
                  transform: translateX(-50%);
            }

            #WkitTopBar .WkitTableList .WkitTooltip.WkitFirstItem .WkitTooltipContent::after {
                  content: " ";
                  position: absolute;
                  bottom: 100%; /* At the top of the tooltip */
                  left: 1em;
                  border-width: 5px;
                  border-style: solid;
                  border-color: transparent transparent black transparent;
            }

            #WkitTopBar .WkitTableList .WkitTooltip.WkitLaterItem .WkitTooltipContent::after {
                  content: " ";
                  position: absolute;
                  top: 100%; /* At the bottom of the tooltip */
                  left: 1em;
                  border-width: 5px;
                  border-style: solid;
                  border-color: black transparent transparent transparent;
            }

            #WkitTopBar .WkitItemList .WkitTooltip.WkitFirstItem  .WkitTooltipContent::after {
                  content: " ";
                  position: absolute;
                  bottom: 100%; /* At the top of the tooltip */
                  left: 50%;
                  border-width: 5px;
                  border-style: solid;
                  border-color: transparent transparent black transparent;
            }

            #WkitTopBar .WkitItemList .WkitTooltip.WkitLaterItem .WkitTooltipContent::after {
                  content: " ";
                  position: absolute;
                  top: 100%; /* At the bottom of the tooltip */
                  left: 50%;
                  border-width: 5px;
                  border-style: solid;
                  border-color: black transparent transparent transparent;
            }

             #WkitTopBar .WkitTooltip2 {
                  position: relative;
                  display: inline-block;
                  width: 30px;
            }

            #WkitTopBar .WkitTooltip2 .WkitEnlargedTooltip {
                  display: none;
                  visibility: hidden;
                  background-color: black;
                  color: #fff;
                  font-size: 100%;
                  width: max-content;
                  border-radius: 3px;
                  position: absolute;
                  bottom: 30px;
                  left: 0%;
                  padding: 2px;
                  z-index: 1;
            }

            #WkitTopBar .WkitTooltip2:hover div.WkitEnlargedTooltip {
                  visibility: visible;
                  display: inline-block;
                  z-index: 50;
            }

            #WkitTopBar .WkitTooltip2 .WkitEnlargedTooltip::after {
                  content: " ";
                  position: absolute;
                  top: 100%; /* At the bottom of the tooltip */
                  left: 1em;
                  border-width: 5px;
                  border-style: solid;
                  border-color: black transparent transparent transparent;
            }

            #WkitTopBar .WkitTooltip .radical {
                  background: #00a1f1;
            }

            #WkitTopBar .WkitTooltip .kanji {
                  background: #ff00aa;
            }

            #WkitTopBar .WkitTooltip .vocabulary {
                  background: #9800e8;
            }

            #WkitTopBar .WkitTooltip2 .radical {
                  padding: 5px;
                  background: #00a1f1;
             }

            #WkitTopBar .WkitTooltip2 .kanji {
                  padding: 5px;
                  background: #ff00aa;
            }

            #WkitTopBar .WkitTooltip2 .vocabulary {
                  padding: 5px;
                  background: #9800e8;
            }


            #WkitTopBar .WkitTooltipIcon span.radical {
                  font-size: 30px;
                  background-image: linear-gradient(0deg, #0af, #0093dd);
                  background-color: #00a1f1;
            }

            #WkitTopBar .WkitTooltipIcon span.kanji {
                  font-size: 30px;
                  background-image: linear-gradient(0deg, #f0a, #dd0093);
                  background-color: #ff00aa;
            }

            #WkitTopBar .WkitTooltipIcon span.vocabulary {
                  font-size: 30px;
                  background-image: linear-gradient(0deg, #9800e89e, #7e00c2);
                  background-color: #9800e8;
            }

            #WkitTopBar .WkitTooltipIcon .WkitMarker {
                  margin: 5px;
                  padding: 13px 3px;
            }

            #WkitTopBar .WkitTooltipIcon .WkitMarkerMeaning {
                  margin: 10px 5px;
            }

            #WkitTopBar .WkitTooltipContent img{
                 width: 40px;
                 height: 40px;
                 align-items: center;
             }

            #WkitTopBar .WkitTooltip2 img{
                 width: 80px;
                 height: 80px;
                 align-items: center;
             }

           #WkitTopBar .radical img {
                ${is_dark ? '' : 'filter: invert(1);'}
}

           #WkitTopBar .left span {
                  font-size: 35px;
                  line-height: 40px;
                  display: block;
                  align-items: center;
                  text-align: center;
                  border-radius: 3px;
                  margin: 5px;
                  padding: 5px;
           }

           #WkitTopBar .WkitEnlargedTooltip span {
                  font-size: 60px;
                  line-height: 58px;
                  display: block;
                  border-radius: 3px;
                  margin: 5px;
           }

           #WkitTopBar .right  {
                  padding-left: 7px;
                  padding-right: 7px;
                  padding-bottom: 7px;
           }

           #WkitTopBar .right table td:first-child {
                  padding-right: 10px;
                  font-weight: bold;
           }

          #WkitTopBar .WkitMiniContainer {
                  display: -webkit-flex;
                  display: flex;
                  flex-direction: row;
                  flex-wrap: wrap;
                  justify-content: flex-start;
                  position: relative;
          }

          #WkitTopBar .WkitMiniIcon {
                  position: relative;
                  display: block;
                  font-size: 14px;
                  vertical-align: middle;
                  text-align:center;
                  margin: 2px;
                  height: fit-content;
                  width: max-content;
                  padding: 3px;
                  border-radius: 3px;
                  -webkit-text-size-adjust: none;
                  text-size-adjust: none;
          }

           #WkitTopBar .WkitMiniIcon .WkitMiniTooltipContent {
                  display: inline-block;
                  visibility: hidden;
                  background-color: black;
                  color: #fff;
                  font-size: 100%;
                  width: max-content;
                  max-width: 445px;
                  text-align: left;
                  margin: 5px;
                  padding: 2px;
                  border-radius: 3px;
                  position: absolute;
                  z-index: 1;
            }

            #WkitTopBar .WkitMiniIcon:hover div.WkitMiniTooltipContent {
                  position: absolute;
                  visibility: visible;
                  display: inline-block;
                  z-index: 50;
                  transition-delay: 0.5s;
                  bottom: 28px;
                  transform: translateX(-65%);
            }

            #WkitTopBar .WkitMiniIcon .WkitMiniTooltipContent::after {
                  content: " ";
                  position: absolute;
                  top: 100%; /* At the bottom of the tooltip */
                  left: 65%;
                  border-width: 5px;
                  border-style: solid;
                  border-color: black transparent transparent transparent;
            }


          #WkitTopBar .WkitMiniIcon .radical {
                  background: #00a1f1;
          }

          #WkitTopBar .WkitMiniIcon .kanji {
                  background: #ff00aa;
          }

          #WkitTopBar .WkitMiniIcon .vocabulary {
                  background: #9800e8;
          }

         #WkitTopBar .WkitMiniIcon img{
                 width: 14px;
                 height: 14px;
                 margin: 0px;
                 align-items: center;
          }

          #WkitTopBar .WkitIconWarning {
                 margin: auto;
                 font-weight: bold;
          }

           #WkitTopBar .right table td {
                  padding-top: 3px;
           }

           #WkitTopBar .WkitLabel, {
                  padding: 4px;
           }`

        var leechStyling = document.createElement('style');
        leechStyling.type='text/css';
        if(leechStyling.styleSheet){
            leechStyling.styleSheet.cssText = leechTableCss;
        }else{
            leechStyling.appendChild(document.createTextNode(leechTableCss));
        }
        document.getElementsByTagName('head')[0].appendChild(leechStyling);
    };

    //------------------------------
    // Menu
    //------------------------------
    var settings_dialog;

    function install_menu() {
        wkof.Menu.insert_script_link({
            script_id: scriptId,
            name: scriptId,
            submenu:   'Settings',
            title:     'Item Inspector',
            on_click:  open_settings_dialog
        });
    }


    //------------------------------
    // Settings - new version
    //------------------------------

    //########################################################################
    // QUIZ DATA
    //########################################################################

    var quiz = {
        // Dialogs
        dialog: null,
        settings_dialog: null,

        // Item Lists
        items: [],
        group_list: [],
        serial_list: [],
        index: null,

        // Status
        showing_help: false,
        mode: 'loading',

        // Question Info
        qinfo: {
            load: null,
            prep: null,
            cache: {},
        },

        // Stats
        stats: {
            round: 1,
            total: 0,
            correct: 0,
            incorrect: 0,
        },

        // Functions
        start: null,
        shuffle: null,
        requiz: null,
        ask: null,
        submit: null,
        prev: null,
        next: null,
        close: null,
    };


    //########################################################################
    // QUIZ SETTINGS DIALOG
    //########################################################################

    //========================================================================
    // setup_quiz_settings()
    //------------------------------------------------------------------------
    var quiz_settings_state = 'init';
    var standardInfo = ['table_data', 'sort1', 'sort2', 'tooltip1', 'tooltip2', 'tooltip3', 'tooltip4', 'tooltip5', 'tooltip6', 'tooltip7', 'tooltip8',];
    var exportedInfo = ['export1','export2','export3','export4','export5','export6','export7','export8','export9','export10',
                        'export11','export12','export13','export14','export15','export16','export17','export18','export19','export20',
                        'export21','export22','export23','export24','export25','export26','export27','export28','export29','export30',
                        'export31','export32','export33','export34','export35','export36','export37','export38',];
    var needSubjectId = {'Vis_Sim_Kanji':true, 'Used_In': true, 'Components': true,}
    var wideElements = {'Review_Date':true, 'Passed_Date':true, 'Burned_Date':true, 'Resurrected_Date':true, 'Lesson_Date':true, 'Unlock_Date':true, };
    function setup_quiz_settings() {
        if (quiz_settings_state === 'init') {
            quiz_settings_state = 'loading';
            return wkof.ready('Settings')
                .then(function(){
                quiz_settings_state = 'setup';
                setup_quiz_settings();
            });
        }

        if (quiz_settings_state !== 'setup') return;

        let tableElementContents = {'Meaning_Brief':'Meaning Brief',
                                    'Reading_Brief':'Reading Brief', 'Reading_Full':'Reading Full', 'Leech':'Leech Value',
                                    'Meaning_Correct_Answers': 'Meaning Correct Answers', 'Meaning_Incorrect_Answers': 'Meaning Incorrect Answers',
                                    'Reading_Correct_Answers': 'Reading Correct Answers', 'Reading_Incorrect_Answers': 'Reading Incorrect Answers',
                                    'Total_Correct_Answers': 'Total Correct Answers','Total_Incorrect_Answers': 'Total Incorrect Answers',
                                    'Percentage_Correct': 'Percentage Correct Total','Meaning_Correct': 'Percentage Correct Meaning','Reading_Correct': 'Percentage Correct Reading',
                                    'Meaning_Current_Streak' : 'Meaning Current Streak', 'Reading_Current_Streak': 'Reading Current Streak',
                                    'Meaning_Max_Streak' : 'Meaning Maximum Streak', 'Reading_Max_Streak': 'Reading Maximum Streak',
                                    'Level':'Level',
                                    'Srs':'SRS Stage', 'Review_Date':'Review Date', 'Review_Wait':'Review Wait Time',
                                    'Passed_Date':'Passed Guru Date', 'Burned_Date':'Burned Date', 'Resurrected_Date': 'Resurrected Date',
                                    'Lesson_Date':'Lesson Date', 'Unlock_Date': 'Unlock Date'};

        let dataElementContents = {'None':'None', 'Meaning_Brief':'Meaning Brief', 'Meaning_Full':'Meaning Full',
                                   'Reading_Brief':'Reading Brief', 'Reading_Full':'Reading Full', 'Reading_by_Type': 'Reading by Type (on kun)', 'Leech':'Leech Value',
                                   'Meaning_Correct_Answers': 'Meaning Correct Answers', 'Reading_Correct_Answers': 'Reading Correct Answers',
                                   'Meaning_Incorrect_Answers': 'Meaning Incorrect Answers', 'Reading_Incorrect_Answers': 'Reading Incorrect Answers',
                                   'Total_Correct_Answers': 'Total Correct Answers','Total_Incorrect_Answers': 'Total Incorrect Answers',
                                   'Percentage_Correct': 'Percentage Correct Total','Meaning_Correct': 'Percentage Correct Meaning','Reading_Correct': 'Percentage Correct Reading',
                                   'Meaning_Current_Streak' : 'Meaning Current Streak', 'Reading_Current_Streak': 'Reading Current Streak',
                                   'Meaning_Max_Streak' : 'Meaning Maximum Streak', 'Reading_Max_Streak': 'Reading Maximum Streak',
                                   'Level':'Level',
                                   'Srs':'SRS Stage', 'Review_Date':'Review Date', 'Review_Wait':'Review Wait Time',
                                   'Passed_Date':'Passed Guru Date', 'Burned_Date':'Burned Date', 'Resurrected_Date': 'Resurrected Date',
                                   'Lesson_Date':'Lesson Date', 'Unlock_Date': 'Unlock Date',
                                   'Allow_List': 'Allow List', 'Block_List': 'Block List',
                                   'Part_Of_Speech': 'Part of Speech', 'Vis_Sim_Kanji': 'Visually Similar Kanji',
                                   'Components': 'Components of Item', 'Used_In': 'Items Where Used',
                                  };

        let sortElementContents = {'Default':'Default', 'Type':'Item Type (Rad, Kan, Voc)', 'Meaning_Brief':'Meaning Brief', 'Meaning_Full':'Meaning Full',
                                   'Reading_Brief':'Reading Brief', 'Reading_Full':'Reading Full', 'Leech':'Leech Value',
                                   'Meaning_Correct_Answers': 'Meaning Correct Answers', 'Reading_Correct_Answers': 'Reading Correct Answers',
                                   'Meaning_Incorrect_Answers': 'Meaning Incorrect Answers', 'Reading_Incorrect_Answers': 'Reading Incorrect Answers',
                                   'Total_Correct_Answers': 'Total Correct Answers','Total_Incorrect_Answers': 'Total Incorrect Answers',
                                   'Percentage_Correct': 'Percentage Correct Total','Meaning_Correct': 'Percentage Correct Meaning','Reading_Correct': 'Percentage Correct Reading',
                                   'Meaning_Current_Streak' : 'Meaning Current Streak', 'Reading_Current_Streak': 'Reading Current Streak',
                                   'Meaning_Max_Streak' : 'Meaning Maximum Streak', 'Reading_Max_Streak': 'Reading Maximum Streak',
                                   'Level':'Level',
                                   'Srs':'SRS Stage', 'Review_Date':'Review Date', 'Review_Wait':'Review Wait Time',
                                   'Passed_Date':'Passed Guru Date', 'Burned_Date':'Burned Date', 'Resurrected_Date': 'Resurrected Date',
                                   'Lesson_Date':'Lesson Date', 'Unlock_Date': 'Unlock Date'};

        let wordCloudContents = {'No Repeat': 'Don\'t Repeat', 'Leech':'Leech Value',
                                 'Meaning_Correct_Answers': 'Meaning Correct Answers', 'Reading_Correct_Answers': 'Reading Correct Answers',
                                 'Meaning_Incorrect_Answers': 'Meaning Incorrect Answers', 'Reading_Incorrect_Answers': 'Reading Incorrect Answers',
                                 'Total_Correct_Answers': 'Total Correct Answers','Total_Incorrect_Answers': 'Total Incorrect Answers',
                                 'Percentage_Correct': 'Percentage Correct Total','Meaning_Correct': 'Percentage Correct Meaning','Reading_Correct': 'Percentage Correct Reading',
                                 'Meaning_Current_Streak' : 'Meaning Current Streak', 'Reading_Current_Streak': 'Reading Current Streak',
                                 'Meaning_Max_Streak' : 'Meaning Maximum Streak', 'Reading_Max_Streak': 'Reading Maximum Streak',
                                };

        let exportElementContents = {'None': 'Not Exported', 'Item':'Item', 'Type':'Item Type (Rad, Kan, Voc)', 'Export_Date': 'Export Date',
                                     'Meaning_Brief':'Meaning Brief', 'Meaning_Full':'Meaning Full',
                                     'Reading_Brief':'Reading Brief', 'Reading_Full':'Reading Full', 'Reading_by_Type': 'Reading by Type (on kun)', 'Leech':'Leech Value',
                                     'Meaning_Correct_Answers': 'Meaning Correct Answers', 'Meaning_Incorrect_Answers': 'Meaning Incorrect Answers',
                                     'Reading_Correct_Answers': 'Reading Correct Answers', 'Reading_Incorrect_Answers': 'Reading Incorrect Answers',
                                     'Total_Correct_Answers': 'Total Correct Answers','Total_Incorrect_Answers': 'Total Incorrect Answers',
                                     'Percentage_Correct': 'Percentage Correct Total','Meaning_Correct': 'Percentage Correct Meaning','Reading_Correct': 'Percentage Correct Reading',
                                     'Meaning_Current_Streak' : 'Meaning Current Streak', 'Reading_Current_Streak': 'Reading Current Streak',
                                     'Meaning_Max_Streak' : 'Meaning Maximum Streak', 'Reading_Max_Streak': 'Reading Maximum Streak',
                                     'Level':'Level',
                                     'Srs':'SRS Stage', 'Review_Date':'Review Date',
                                     'Passed_Date':'Passed Guru Date', 'Burned_Date':'Burned Date', 'Resurrected_Date': 'Resurrected Date',
                                     'Lesson_Date':'Lesson Date', 'Unlock_Date': 'Unlock Date',
                                     'Allow_List': 'Allow List', 'Block_List': 'Block List',
                                     'Part_Of_Speech': 'Part of Speech', 'Vis_Sim_Kanji': 'Visually Similar Kanji',
                                     'Components': 'Components of Item', 'Used_In': 'Items Where Used', 'Item_Page': 'URL of Item Page',
                                    };

        var exportTabConfig = {type:'page',label:'Export',hover_tip:'Define the exported items of your table',
                               content:{
                                   sect_tbl_xformat:{type:'section',label:'Export Format'},
                                   separator: {type:'dropdown',label:'Cell Separator',hover_tip:'The characters that separates the cells in a row', default:'\t',
                                               path:'@tablePresets[@active_ipreset].separator', content:{',' : 'Comma', ';': 'Semicolon', '\t': 'Horizontal Tab'},
                                              },
                                   quotes: {type:'dropdown',label:'Use of Quotes',hover_tip:'Whether cells are included in quotes', default:'Never',
                                            path:'@tablePresets[@active_ipreset].quotes', content:{'As_Needed' : 'Only When Needed', 'Never': 'Never Use Quotes', 'Always': 'Always Use Quotes'},
                                           },
                                   sect_tbl_format:{type:'section',label:'Data Format'},
                                   includeTitle: {type: 'checkbox', label:'Include a Title Line', default: false, hover_tip: 'Adds a title line before the exported items',
                                                  path:'@tablePresets[@active_ipreset].includeTitle', },
                                   includeLabels: {type: 'checkbox', label:'Include a Label in Cells', default: false, hover_tip: 'Adds in each cell a label to describe the data.\nLabels are not added to Meanings, Readings, Item, Item Type and URL columns',
                                                   path:'@tablePresets[@active_ipreset].includeLabels', },
                                   URLclickable: {type: 'dropdown', label:'URL Clickable', default: 'Plain', hover_tip: 'Makes URL automatically clickable in spreadsheet, Kitsun and Anki',
                                                  path:'@tablePresets[@active_ipreset].URLclickable',content:{'Plain': 'Plain URL, Non Clickable', 'Spreadsheet': 'Spreadsheet Format', 'html': 'HTML for Kitsun and Anki'}, },
                                   missingData: {type: 'dropdown', label:'Missing Data', default: 'Code_Word', hover_tip: 'How to export missing data',
                                                 path:'@tablePresets[@active_ipreset].missingData', content:{'Code_Word' : 'Mark as Unavailable', 'Empty_Cell': 'Leave the Cell Empty',}},
                                   hoursInDate: {type: 'list', multi: true, size: 4, label:'Adding Hours in Dates', default: {'Review_Date': true}, hover_tip: 'Adding hours and minutes to selected dates.\nUnselected means just the date will be exported.',
                                                 path:'@tablePresets[@active_ipreset].hoursInDate', content:{'Review_Date':'Review Date', 'Passed_Date':'Passed Guru Date', 'Burned_Date':'Burned Date',
                                                                                                             'Resurrected_Date': 'Resurrected Date', 'Lesson_Date':'Lesson Date', 'Unlock_Date': 'Unlock Date',
                                                                                                             'Export_Date': 'Export Date',}},
                                   sect_tbl_export:{type:'section',label:'Exported Columns'},
                                   export1: {type:'dropdown',label:'Exported Column no 1',hover_tip:'The 1st column of exported information', default:'None',
                                             path:'@tablePresets[@active_ipreset].export1', content:exportElementContents,
                                            },
                                   export2: {type:'dropdown',label:'Exported Column no 2',hover_tip:'The 2nd column of exported information', default:'None',
                                             path:'@tablePresets[@active_ipreset].export2', content:exportElementContents,
                                            },
                                   export3: {type:'dropdown',label:'Exported Column no 3',hover_tip:'The 3rd column of exported information', default:'None',
                                             path:'@tablePresets[@active_ipreset].export3', content:exportElementContents,
                                            },
                                   export4: {type:'dropdown',label:'Exported Column no 4',hover_tip:'The 4th column of exported information', default:'None',
                                             path:'@tablePresets[@active_ipreset].export4', content:exportElementContents,
                                            },
                                   export5: {type:'dropdown',label:'Exported Column no 5',hover_tip:'The 5th column of exported information', default:'None',
                                             path:'@tablePresets[@active_ipreset].export5', content:exportElementContents,
                                            },
                                   export6: {type:'dropdown',label:'Exported Column no 6',hover_tip:'The 6th column of exported information', default:'None',
                                             path:'@tablePresets[@active_ipreset].export6', content:exportElementContents,
                                            },
                                   export7: {type:'dropdown',label:'Exported Column no 7',hover_tip:'The 7th column of exported information', default:'None',
                                             path:'@tablePresets[@active_ipreset].export7', content:exportElementContents,
                                            },
                                   export8: {type:'dropdown',label:'Exported Column no 8',hover_tip:'The 8th column of exported information', default:'None',
                                             path:'@tablePresets[@active_ipreset].export8', content:exportElementContents,
                                            },
                                   export9: {type:'dropdown',label:'Exported Column no 9',hover_tip:'The 9th column of exported information', default:'None',
                                             path:'@tablePresets[@active_ipreset].export9', content:exportElementContents,
                                            },
                                   export10: {type:'dropdown',label:'Exported Column no 10',hover_tip:'The 10th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export10', content:exportElementContents,
                                             },
                                   export11: {type:'dropdown',label:'Exported Column no 11',hover_tip:'The 11th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export11', content:exportElementContents,
                                             },
                                   export12: {type:'dropdown',label:'Exported Column no 12',hover_tip:'The 12th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export12', content:exportElementContents,
                                             },
                                   export13: {type:'dropdown',label:'Exported Column no 13',hover_tip:'The 13th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export13', content:exportElementContents,
                                             },
                                   export14: {type:'dropdown',label:'Exported Column no 14',hover_tip:'The 14th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export14', content:exportElementContents,
                                             },
                                   export15: {type:'dropdown',label:'Exported Column no 15',hover_tip:'The 15th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export15', content:exportElementContents,
                                             },
                                   export16: {type:'dropdown',label:'Exported Column no 16',hover_tip:'The 16th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export16', content:exportElementContents,
                                             },
                                   export17: {type:'dropdown',label:'Exported Column no 17',hover_tip:'The 17th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export17', content:exportElementContents,
                                             },
                                   export18: {type:'dropdown',label:'Exported Column no 18',hover_tip:'The 18th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export18', content:exportElementContents,
                                             },
                                   export19: {type:'dropdown',label:'Exported Column no 19',hover_tip:'The 19th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export19', content:exportElementContents,
                                             },
                                   export20: {type:'dropdown',label:'Exported Column no 20',hover_tip:'The 20th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export20', content:exportElementContents,
                                             },
                                   export21: {type:'dropdown',label:'Exported Column no 21',hover_tip:'The 21th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export21', content:exportElementContents,
                                             },
                                   export22: {type:'dropdown',label:'Exported Column no 22',hover_tip:'The 22th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export22', content:exportElementContents,
                                             },
                                   export23: {type:'dropdown',label:'Exported Column no 23',hover_tip:'The 23th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export23', content:exportElementContents,
                                             },
                                   export24: {type:'dropdown',label:'Exported Column no 24',hover_tip:'The 24th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export24', content:exportElementContents,
                                             },
                                   export25: {type:'dropdown',label:'Exported Column no 25',hover_tip:'The 25th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export25', content:exportElementContents,
                                             },
                                   export26: {type:'dropdown',label:'Exported Column no 26',hover_tip:'The 26th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export26', content:exportElementContents,
                                             },
                                   export27: {type:'dropdown',label:'Exported Column no 27',hover_tip:'The 27th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export27', content:exportElementContents,
                                             },
                                   export28: {type:'dropdown',label:'Exported Column no 28',hover_tip:'The 28th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export28', content:exportElementContents,
                                             },
                                   export29: {type:'dropdown',label:'Exported Column no 29',hover_tip:'The 29th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export29', content:exportElementContents,
                                             },
                                   export30: {type:'dropdown',label:'Exported Column no 30',hover_tip:'The 30th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export30', content:exportElementContents,
                                             },
                                   export31: {type:'dropdown',label:'Exported Column no 31',hover_tip:'The 31th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export31', content:exportElementContents,
                                             },
                                   export32: {type:'dropdown',label:'Exported Column no 32',hover_tip:'The 32th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export32', content:exportElementContents,
                                             },
                                   export33: {type:'dropdown',label:'Exported Column no 33',hover_tip:'The 33th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export33', content:exportElementContents,
                                             },
                                   export34: {type:'dropdown',label:'Exported Column no 34',hover_tip:'The 34th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export34', content:exportElementContents,
                                             },
                                   export35: {type:'dropdown',label:'Exported Column no 35',hover_tip:'The 35th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export35', content:exportElementContents,
                                             },
                                   export36: {type:'dropdown',label:'Exported Column no 36',hover_tip:'The 36th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export36', content:exportElementContents,
                                             },
                                   export37: {type:'dropdown',label:'Exported Column no 37',hover_tip:'The 37th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export37', content:exportElementContents,
                                             },
                                   export38: {type:'dropdown',label:'Exported Column no 38',hover_tip:'The 38th column of exported information', default:'None',
                                              path:'@tablePresets[@active_ipreset].export38', content:exportElementContents,
                                             },
                               },
                              }

        var exportDefaultTabConfig = {type:'page',label:'Export',hover_tip:'Define the default exported items of your newly created tables.',
                                      content:{
                                          sect_tbl_defxformat:{type:'section',label:'Export Format'},
                                          defseparator: {type:'dropdown',label:'Cell Separator',hover_tip:'The characters that separates the cells in a row', default:'\t',
                                                         path:'@defaults.separator', content:{',' : 'Comma', ';': 'Semicolon', '\t': 'Horizontal Tab'},
                                                        },
                                          defquotes: {type:'dropdown',label:'Use of Quotes',hover_tip:'Whether cells are included in quotes', default:'Never',
                                                      path:'@defaults.quotes', content:{'As_Needed' : 'Only When Needed', 'Never': 'Never Use Quotes', 'Always': 'Always Use Quotes'},
                                                     },
                                          sect_tbl_defformat:{type:'section',label:'Data Format'},
                                          defincludeTitle: {type: 'checkbox', label:'Include a Title Line', default: false, hover_tip: 'Adds a title line before the exported items',
                                                            path:'@defaults.includeTitle', },
                                          defincludeLabels: {type: 'checkbox', label:'Include a Label in Cells', default: false, hover_tip: 'Adds in each cell a label to describe the data.\nLabels are not added to Meanings, Readings, Item, Item Type and URL columns',
                                                             path:'@defaults.includeLabels', },
                                          defURLclickable: {type: 'dropdown', label:'URL Clickable', default: 'Plain', hover_tip: 'Makes URL automatically clickable in spreadsheet, Kitsun and Anki.',
                                                            path:'@defaults.URLclickable',content:{'Plain': 'Plain URL, Non Clickable', 'Spreadsheet': 'Spreadsheet Format', 'html': 'HTML for Kitsun and Anki'}, },
                                          defmissingData: {type: 'dropdown', label:'Missing Data', default: 'Code_Word', hover_tip: 'How to export missing data',
                                                           path:'@defaults.missingData', content:{'Code_Word' : 'Mark as Unavailable', 'Empty_Cell': 'Leave the Cell Empty',}},
                                          defhoursInDate: {type: 'list', multi: true, size: 4, label:'Adding Hours in Dates', default: {'Review_Date': true}, hover_tip: 'Adding hours and minutes to selected dates.\nUnselected means just the date will be exported.',
                                                           path:'@defaults.hoursInDate', content:{'Review_Date':'Review Date', 'Passed_Date':'Passed Guru Date', 'Burned_Date':'Burned Date',
                                                                                                  'Resurrected_Date': 'Resurrected Date', 'Lesson_Date':'Lesson Date', 'Unlock_Date': 'Unlock Date',
                                                                                                  'Export_Date': 'Export Date',}},
                                          sect_tbl_defexport:{type:'section',label:'Exported Columns'},
                                          defexport1: {type:'dropdown',label:'Exported Column no 1',hover_tip:'The 1st column of exported information', default:'None',
                                                       path:'@defaults.export1', content:exportElementContents,
                                                      },
                                          defexport2: {type:'dropdown',label:'Exported Column no 2',hover_tip:'The 2nd column of exported information', default:'None',
                                                       path:'@defaults.export2', content:exportElementContents,
                                                      },
                                          defexport3: {type:'dropdown',label:'Exported Column no 3',hover_tip:'The 3rd column of exported information', default:'None',
                                                       path:'@defaults.export3', content:exportElementContents,
                                                      },
                                          defexport4: {type:'dropdown',label:'Exported Column no 4',hover_tip:'The 4th column of exported information', default:'None',
                                                       path:'@defaults.export4', content:exportElementContents,
                                                      },
                                          defexport5: {type:'dropdown',label:'Exported Column no 5',hover_tip:'The 5th column of exported information', default:'None',
                                                       path:'@defaults.export5', content:exportElementContents,
                                                      },
                                          defexport6: {type:'dropdown',label:'Exported Column no 6',hover_tip:'The 6th column of exported information', default:'None',
                                                       path:'@defaults.export6', content:exportElementContents,
                                                      },
                                          defexport7: {type:'dropdown',label:'Exported Column no 7',hover_tip:'The 7th column of exported information', default:'None',
                                                       path:'@defaults.export7', content:exportElementContents,
                                                      },
                                          defexport8: {type:'dropdown',label:'Exported Column no 8',hover_tip:'The 8th column of exported information', default:'None',
                                                       path:'@defaults.export8', content:exportElementContents,
                                                      },
                                          defexport9: {type:'dropdown',label:'Exported Column no 9',hover_tip:'The 9th column of exported information', default:'None',
                                                       path:'@defaults.export9', content:exportElementContents,
                                                      },
                                          defexport10: {type:'dropdown',label:'Exported Column no 10',hover_tip:'The 10th column of exported information', default:'None',
                                                        path:'@defaults.export10', content:exportElementContents,
                                                       },
                                          defexport11: {type:'dropdown',label:'Exported Column no 11',hover_tip:'The 11th column of exported information', default:'None',
                                                        path:'@defaults.export11', content:exportElementContents,
                                                       },
                                          defexport12: {type:'dropdown',label:'Exported Column no 12',hover_tip:'The 12th column of exported information', default:'None',
                                                        path:'@defaults.export12', content:exportElementContents,
                                                       },
                                          defexport13: {type:'dropdown',label:'Exported Column no 13',hover_tip:'The 13th column of exported information', default:'None',
                                                        path:'@defaults.export13', content:exportElementContents,
                                                       },
                                          defexport14: {type:'dropdown',label:'Exported Column no 14',hover_tip:'The 14th column of exported information', default:'None',
                                                        path:'@defaults.export14', content:exportElementContents,
                                                       },
                                          defexport15: {type:'dropdown',label:'Exported Column no 15',hover_tip:'The 15th column of exported information', default:'None',
                                                        path:'@defaults.export15', content:exportElementContents,
                                                       },
                                          defexport16: {type:'dropdown',label:'Exported Column no 16',hover_tip:'The 16th column of exported information', default:'None',
                                                        path:'@defaults.export16', content:exportElementContents,
                                                       },
                                          defexport17: {type:'dropdown',label:'Exported Column no 17',hover_tip:'The 17th column of exported information', default:'None',
                                                        path:'@defaults.export17', content:exportElementContents,
                                                       },
                                          defexport18: {type:'dropdown',label:'Exported Column no 18',hover_tip:'The 18th column of exported information', default:'None',
                                                        path:'@defaults.export18', content:exportElementContents,
                                                       },
                                          defexport19: {type:'dropdown',label:'Exported Column no 19',hover_tip:'The 19th column of exported information', default:'None',
                                                        path:'@defaults.export19', content:exportElementContents,
                                                       },
                                          defexport20: {type:'dropdown',label:'Exported Column no 20',hover_tip:'The 20th column of exported information', default:'None',
                                                        path:'@defaults.export20', content:exportElementContents,
                                                       },
                                          defexport21: {type:'dropdown',label:'Exported Column no 21',hover_tip:'The 21th column of exported information', default:'None',
                                                        path:'@defaults.export21', content:exportElementContents,
                                                       },
                                          defexport22: {type:'dropdown',label:'Exported Column no 22',hover_tip:'The 22th column of exported information', default:'None',
                                                        path:'@defaults.export22', content:exportElementContents,
                                                       },
                                          defexport23: {type:'dropdown',label:'Exported Column no 23',hover_tip:'The 23th column of exported information', default:'None',
                                                        path:'@defaults.export23', content:exportElementContents,
                                                       },
                                          defexport24: {type:'dropdown',label:'Exported Column no 24',hover_tip:'The 24th column of exported information', default:'None',
                                                        path:'@defaults.export24', content:exportElementContents,
                                                       },
                                          defexport25: {type:'dropdown',label:'Exported Column no 25',hover_tip:'The 25th column of exported information', default:'None',
                                                        path:'@defaults.export25', content:exportElementContents,
                                                       },
                                          defexport26: {type:'dropdown',label:'Exported Column no 26',hover_tip:'The 26th column of exported information', default:'None',
                                                        path:'@defaults.export26', content:exportElementContents,
                                                       },
                                          defexport27: {type:'dropdown',label:'Exported Column no 27',hover_tip:'The 27th column of exported information', default:'None',
                                                        path:'@defaults.export27', content:exportElementContents,
                                                       },
                                          defexport28: {type:'dropdown',label:'Exported Column no 28',hover_tip:'The 28th column of exported information', default:'None',
                                                        path:'@defaults.export28', content:exportElementContents,
                                                       },
                                          defexport29: {type:'dropdown',label:'Exported Column no 29',hover_tip:'The 29th column of exported information', default:'None',
                                                        path:'@defaults.export29', content:exportElementContents,
                                                       },
                                          defexport30: {type:'dropdown',label:'Exported Column no 30',hover_tip:'The 30th column of exported information', default:'None',
                                                        path:'@defaults.export30', content:exportElementContents,
                                                       },
                                          defexport31: {type:'dropdown',label:'Exported Column no 31',hover_tip:'The 31th column of exported information', default:'None',
                                                        path:'@defaults.export31', content:exportElementContents,
                                                       },
                                          defexport32: {type:'dropdown',label:'Exported Column no 32',hover_tip:'The 32th column of exported information', default:'None',
                                                        path:'@defaults.export32', content:exportElementContents,
                                                       },
                                          defexport33: {type:'dropdown',label:'Exported Column no 33',hover_tip:'The 33th column of exported information', default:'None',
                                                        path:'@defaults.export33', content:exportElementContents,
                                                       },
                                          defexport34: {type:'dropdown',label:'Exported Column no 34',hover_tip:'The 34th column of exported information', default:'None',
                                                        path:'@defaults.export34', content:exportElementContents,
                                                       },
                                          defexport35: {type:'dropdown',label:'Exported Column no 35',hover_tip:'The 35th column of exported information', default:'None',
                                                        path:'@defaults.export35', content:exportElementContents,
                                                       },
                                          defexport36: {type:'dropdown',label:'Exported Column no 36',hover_tip:'The 36th column of exported information', default:'None',
                                                        path:'@defaults.export36', content:exportElementContents,
                                                       },
                                          defexport37: {type:'dropdown',label:'Exported Column no 37',hover_tip:'The 37th column of exported information', default:'None',
                                                        path:'@defaults.export37', content:exportElementContents,
                                                       },
                                          defexport38: {type:'dropdown',label:'Exported Column no 38',hover_tip:'The 38th column of exported information', default:'None',
                                                        path:'@defaults.export38', content:exportElementContents,
                                                       },
                                      },
                                     }

        var contentsTabConfig = {type:'page',label:'Contents',hover_tip:'Define the contents of your table',
                                 content:{
                                     sect_tbl_cnts:{type:'section',label:'Table Entry'},
                                     table_data: {type:'dropdown',label:'Table Data Element',hover_tip:'The data that will be displayed on the table.',
                                                  path:'@tablePresets[@active_ipreset].table_data',
                                                  content:tableElementContents,
                                                 },
                                     sort1: {type:'dropdown',label:'Primary Sort Criterion',hover_tip:'Items will be sorted by this criterion.',
                                             path:'@tablePresets[@active_ipreset].sort1',
                                             content:sortElementContents,
                                            },
                                     sortOrder1: {type:'dropdown',label:'Primary Sort Order',hover_tip:'Items will be sorted in this order.',
                                                  path:'@tablePresets[@active_ipreset].sortOrder1',
                                                  content:{'Default': 'Default', 'Ascending': 'Ascending', 'Descending': 'Descending',},
                                                 },
                                     sort2: {type:'dropdown',label:'Secondary Sort Criterion',hover_tip:'Items will be sorted by this criterion when the primary criterion is of equal values.',
                                             path:'@tablePresets[@active_ipreset].sort2',
                                             content:sortElementContents,
                                            },
                                     sortOrder2: {type:'dropdown',label:'Secondary Sort Order',hover_tip:'Items will be sorted in this order when the primary criterion is of equal values.',
                                                  path:'@tablePresets[@active_ipreset].sortOrder2',
                                                  content:{'Default': 'Default', 'Ascending': 'Ascending', 'Descending': 'Descending',},
                                                 },
                                     displayMeaning: {type: 'checkbox', label:'Show Items by Their Meanings', hover_tip:'Display the items by their English meanings',
                                                      path:'@tablePresets[@active_ipreset].displayMeaning', default: false, },
                                     sect_tbl_tooltips:{type:'section',label:'Table Popups'},
                                     tooltip1: {type:'dropdown',label:'First Popup Element',hover_tip:'The first line of data that will be displayed on the popup.',
                                                path:'@tablePresets[@active_ipreset].tooltip1', default:'None',
                                                content:dataElementContents,
                                               },
                                     tooltip2: {type:'dropdown',label:'Second Popup Element',hover_tip:'The second line of data that will be displayed on the popup.',
                                                path:'@tablePresets[@active_ipreset].tooltip2', default:'None',
                                                content:dataElementContents,
                                               },
                                     tooltip3: {type:'dropdown',label:'Third Popup Element',hover_tip:'The third line of  data that will be displayed on the popup.',
                                                path:'@tablePresets[@active_ipreset].tooltip3', default:'None',
                                                content:dataElementContents,
                                               },
                                     tooltip4: {type:'dropdown',label:'Fourth Popup Element',hover_tip:'The fourth line of  data that will be displayed on the popup.',
                                                path:'@tablePresets[@active_ipreset].tooltip4', default:'None',
                                                content:dataElementContents,
                                               },
                                     tooltip5: {type:'dropdown',label:'Fifth Popup Element',hover_tip:'The fifth line of  data that will be displayed on the popup.',
                                                path:'@tablePresets[@active_ipreset].tooltip5', default:'None',
                                                content:dataElementContents,
                                               },
                                     tooltip6: {type:'dropdown',label:'Sixth Popup Element',hover_tip:'The sixth line of  data that will be displayed on the popup.',
                                                path:'@tablePresets[@active_ipreset].tooltip6', default:'None',
                                                content:dataElementContents,
                                               },
                                     tooltip7: {type:'dropdown',label:'Seventh Popup Element',hover_tip:'The seventh line of  data that will be displayed on the popup.',
                                                path:'@tablePresets[@active_ipreset].tooltip7', default:'None',
                                                content:dataElementContents,
                                               },
                                     tooltip8: {type:'dropdown',label:'Eight Popup Element',hover_tip:'The eight line of  data that will be displayed on the popup.',
                                                path:'@tablePresets[@active_ipreset].tooltip8', default:'None',
                                                content:dataElementContents,
                                               },
                                     sect_tbl_settings:{type:'section',label:'Other Settings'},
                                     enlargingTooltip: {type: 'checkbox', label:'Popup for Enlarged Items', hover_tip:'Adds a popup in tables at the right of the item to show an enlarged version of the item',
                                                        path:'@tablePresets[@active_ipreset].enlargingTooltip', default: false, },
                                     showMarkers: {type: 'checkbox', label:'Show Markers', hover_tip:'Show the markers for the table data in list of icons.',
                                                   path:'@tablePresets[@active_ipreset].showMarkers', default: true, },
                                     showMarkersDate: {type: 'checkbox', label:'Show Markers in Date Selection', hover_tip:'Show the markers for the table data in list of icons when ordered by date.',
                                                   path:'@tablePresets[@active_ipreset].showMarkersDate', default: false, },
                                     showHours: {type: 'checkbox', label:'Show Hours in Markers', hover_tip:'Show the hours and minutes for dates in list of icons markers',
                                                 path:'@tablePresets[@active_ipreset].showHours', default: false, },
                                     leechStreakLimit: {type:'number',label:'Leech Streak Limit',hover_tip:'Do not display an item when current streak for both meaning and reading is equal or greater to this limit.\nA value of 0 disable this feature',
                                                        path:'@tablePresets[@active_ipreset].leechStreakLimit', default:0
                                                       },
                                     sect_tbl_selections:{type:'section',label:'Selection Options Settings'},
                                     randomSelection: {type:'number',label:'Random Selection',hover_tip:'The size of a random selection of items.\n0 means to fill the screen.',
                                                       path:'@tablePresets[@active_ipreset].randomSelection', default:0,},
                                     navigationDate: {type:'dropdown',label:'Date for Date Navigation',hover_tip:'The date used as a reference when the mode ordering by date is on.',
                                                      path:'@tablePresets[@active_ipreset].navigationDate', default:'Lesson_Date',
                                                      content:{'Review_Date':'Review Date', 'Lesson_Date':'Lesson Date', 'Passed_Date':'Passed Guru Date',
                                                               'Burned_Date':'Burned Date', 'Resurrected_Date': 'Resurrected Date', 'Unlock_Date': 'Unlock Date',},
                                               },
                                 },
                                };

        var contentsDefaultTabConfig = {type:'page',label:'Contents',hover_tip:'Define the default contents for your newly created tables',
                                        content:{
                                            sect_tbl_defcnts:{type:'section',label:'Table Entry'},
                                            deftable_data: {type:'dropdown',label:'Table Data Element',hover_tip:'The data that will be displayed on the table.',
                                                            path:'@defaults.table_data', default: 'Level',
                                                            content:tableElementContents,
                                                           },
                                            defsort1: {type:'dropdown',label:'Primary Sort Criterion',hover_tip:'Items will be sorted by this criterion.',
                                                       path:'@defaults.sort1', default: 'Type',
                                                       content:sortElementContents,
                                                      },
                                            defsortOrder1: {type:'dropdown',label:'Primary Sort Order',hover_tip:'Items will be sorted in this order.',
                                                            path:'@defaults.sortOrder1',
                                                            content:{'Default': 'Default', 'Ascending': 'Ascending', 'Descending': 'Descending',},
                                                           },
                                            defsort2: {type:'dropdown',label:'Secondary Sort Criterion',hover_tip:'Items will be sorted by this criterion when the primary criterion is of equal values.',
                                                       path:'@defaults.sort2',
                                                       content:sortElementContents,
                                                      },
                                            defsortOrder2: {type:'dropdown',label:'Secondary Sort Order',hover_tip:'Items will be sorted in this order when the primary criterion is of equal values.',
                                                            path:'@defaults.sortOrder2',
                                                            content:{'Default': 'Default', 'Ascending': 'Ascending', 'Descending': 'Descending',},
                                                           },
                                            defdisplayMeaning: {type: 'checkbox', label:'Show Items by Their Meanings', hover_tip:'Display the items by their English meanings',
                                                                path:'@defaults.displayMeaning', default: false, },
                                            sect_tbl_deftooltips:{type:'section',label:'Table Popups'},
                                            deftooltip1: {type:'dropdown',label:'First Popup Element',hover_tip:'The first line of data that will be displayed on the popup.',
                                                          path:'@defaults.tooltip1', default:'Meaning_Full',
                                                          content:dataElementContents,
                                                         },
                                            deftooltip2: {type:'dropdown',label:'Second Popup Element',hover_tip:'The second line of data that will be displayed on the popup.',
                                                          path:'@defaults.tooltip2', default:'Reading_Full',
                                                          content:dataElementContents,
                                                         },
                                            deftooltip3: {type:'dropdown',label:'Third Popup Element',hover_tip:'The third line of  data that will be displayed on the popup.',
                                                          path:'@defaults.tooltip3', default:'Srs',
                                                          content:dataElementContents,
                                                         },
                                            deftooltip4: {type:'dropdown',label:'Fourth Popup Element',hover_tip:'The fourth line of  data that will be displayed on the popup.',
                                                          path:'@defaults.tooltip4', default:'Unlock_Date',
                                                          content:dataElementContents,
                                                         },
                                            deftooltip5: {type:'dropdown',label:'Fifth Popup Element',hover_tip:'The fifth line of  data that will be displayed on the popup.',
                                                          path:'@defaults.tooltip5', default:'Lesson_Date',
                                                          content:dataElementContents,
                                                         },
                                            deftooltip6: {type:'dropdown',label:'Sixth Popup Element',hover_tip:'The sixth line of  data that will be displayed on the popup.',
                                                          path:'@defaults.tooltip6', default:'Passed_Date',
                                                          content:dataElementContents,
                                                         },
                                            deftooltip7: {type:'dropdown',label:'Seventh Popup Element',hover_tip:'The seventh line of  data that will be displayed on the popup.',
                                                          path:'@defaults.tooltip7', default:'Burned_Date',
                                                          content:dataElementContents,
                                                         },
                                            deftooltip8: {type:'dropdown',label:'Eight Popup Element',hover_tip:'The eight line of  data that will be displayed on the popup.',
                                                          path:'@defaults.tooltip8', default:'Leech',
                                                          content:dataElementContents,
                                                         },
                                            sect_tbl_defsettings:{type:'section',label:'Other Settings'},
                                            defenlargingTooltip: {type: 'checkbox', label:'Popup for Enlarged Items', hover_tip:'Adds a popup in tables at the right of the item to show an enlarged version of the item.',
                                                                  path:'@defaults.enlargingTooltip', default: false, },
                                            defshowMarkers: {type: 'checkbox', label:'Show Markers', hover_tip:'Show the markers for the table data in list of icons.',
                                                             path:'@defaults.showMarkers', default: true, },
                                            defshowMarkersDate: {type: 'checkbox', label:'Show Markers in Date Selection', hover_tip:'Show the markers for the table data in list of icons when ordered by date.',
                                                                 path:'@defaults.showMarkersDate', default: false, },
                                            defshowHours: {type: 'checkbox', label:'Show Hours in Markers', hover_tip:'Show the hours and minutes for dates in list of icons markers',
                                                           path:'@defaults.showHours', default: false, },
                                        },
                                       };

        var settingsTabConfig ={type:'page',label:'Settings',
                                content:{
                                    sect_tbl_cnts:{type:'section',label:'Interface Configuration'},
                                    position: {type: 'dropdown', label: 'Position', default: 2, hover_tip: 'Where on the dashboard to install Item Inspector',
                                               content: {0: "Top", 1: "Below forecast", 2: "Below SRS", 3: "Below panels", 4: "Bottom"},
                                              },
                                    hoursFormat: {type:'dropdown',label:'Hours Format',hover_tip:'Choose the format for displaying hours',content:{'12hours':'12h', '24hours':'24h',},
                                                  default: '24h',},
                                    listMode: {type: 'checkbox', label:'Display as List', hover_tip:'Display the table as a list of icons',
                                               default: false, },
                                    numberOfLines: {type:'dropdown',label:'Number of Lines',hover_tip:'The number of lines that will be displayed in a table.', default:11,
                                                    content:{8:"8", 9:"9", 10:"10", 11:"11", 12:"12", 13:"13", 14:"14", 15:"15",},
                                                   },
                                    audioSource: {type:'dropdown',label:'Source of Audio',hover_tip:'Which audio is played in audio mode.', default:'random',
                                                  content:{'male': 'Male, Kenichi','female': 'Female, Kyoko', 'random': 'Random',},
                                                 },
                                    sect_tbl_cnts2:{type:'section',label:'Items Export Options'},
                                    noLatin: {type: 'checkbox', label:'No Latin Characters', default: false, hover_tip:'Radicals with latin characters not exported if set',},
                                    oneItemPerLine: {type: 'checkbox', label:'One item per line', default: false, hover_tip: 'One item per line if set\nAll items in one paragraph otherwise',},
                                    exportLimit: {type: 'number', label:'Export Limit', default: 0, hover_tip: 'Maximum number of items exported\n0 means no limit',},
                                    repeatWordCloud: {type: 'dropdown', label:'Repeat for Word Cloud', default: 'No Repeat', hover_tip: 'Repeat the items according this number',
                                                      content:wordCloudContents,},
                                }
                               }

        var config = {
            script_id: scriptId,
            title: 'Item Inspector',
            pre_open: preopen_quiz_settings,
            on_save: save_quiz_settings,
            on_close: close_quiz_settings,
            on_refresh: refresh_quiz_settings,
            no_bkgd: true,
            settings: {pgSettings: settingsTabConfig,
                       pg_items: {type:'page',label:'Tables',hover_tip:'Choose the table for which you want to define the settings',
                                  content:{
                                      grp_ipre_list: {type:'group',label:'Table List',content:{
                                          active_ipreset: {type:'list',refresh_on_change:true,hover_tip:'Choose a table to edit',content:{}},
                                      }},
                                      grp_ipre: {type:'group',label:'Selected Table',
                                                 content:{
                                                     sect_ipre_name: {type:'section',label:'Table Name'},
                                                     ipre_name: {type:'text',label:'Edit Table Name',on_change:refresh_ipresets,path:'@ipresets[@active_ipreset].name',hover_tip:'Enter a name for the selected table'},

                                                     sect_ipre_srcs: {type:'section',label:'Table Settings'},
                                                     ipre_srcs: {type:'tabset',
                                                                 content:{table_contents: contentsTabConfig, table_export: exportTabConfig},
                                                                }
                                                 },
                                                }
                                  },
                                 },
                       pgDefaultSettings: {type:'page',label:'Defaults',hover_tip:'Set the defaults settings for when you create temporaary tables',
                                           content:{sect_tbl_cnts3:{type:'section',label:'Defauts for Temporary Tables'},

                                                    ipre_npdefaults: {type:'tabset',
                                                                      content:{default_contents: contentsDefaultTabConfig, default_export: exportDefaultTabConfig},
                                                                     }},
                                          },
                      }};

        populate_items_config(config);

        quiz.settings_dialog = new wkof.Settings(config);
    };


    //========================================================================
    // preopen_quiz_settings()
    //------------------------------------------------------------------------
    function preopen_quiz_settings(dialog) {
        var btn_grp =
            '<div class="pre_list_btn_grp">'+
            '<button type="button" ref="###" action="new" class="ui-button ui-corner-all ui-widget" title="Create a new table">New</button>'+
            '<button type="button" ref="###" action="up" class="ui-button ui-corner-all ui-widget" title="Move the selected table up in the list"><span class="icon-arrow-up"></span></button>'+
            '<button type="button" ref="###" action="down" class="ui-button ui-corner-all ui-widget" title="Move the selected table down in the list"><span class="icon-arrow-down"></span></button>'+
            '<button type="button" ref="###" action="delete" class="ui-button ui-corner-all ui-widget" title="Delete the selected table">Delete</button>'+
            '</div>';

        var wrap = dialog.find('#Item_Inspector_active_ipreset').closest('.row');
        wrap.addClass('pre_list_wrap');
        wrap.prepend(btn_grp.replace(/###/g, 'ipreset'));
        wrap.find('.pre_list_btn_grp').on('click', 'button', preset_button_pressed);

        $('#Item_Inspector_ipre_srcs .row:first-child').each(function(i,e){
            var row = $(e);
            var right = row.find('>.right');
            row.prepend(right);
            row.addClass('src_enable');
        });

        // Customize the item source filters.
        var srcs = $('#Item_Inspector_ipre_srcs');
        var flt_grps = srcs.find('.wkof_group');
        flt_grps.addClass('filters');
        var filters = flt_grps.find('.row');
        filters.prepend('<div class="enable"><input type="checkbox"></div>');
        filters.on('change', '.enable input[type="checkbox"]', toggle_filter);

        init_settings();
        refresh_ipresets();
    }

    //========================================================================
    // open_quiz_settings()
    //------------------------------------------------------------------------
    var old_position;
    function open_quiz_settings() {
        document.getElementById("WkitSettings").blur();
        if (quiz_settings_state !== 'ready') return call_setup_quiz_settings();
        quiz_settings_state = 'open';
        var backup = {};
        quiz.backup = backup;
        //backup.max_quiz_size = quiz.settings.max_quiz_size;
        backup.ipre = JSON.stringify(quiz.settings.ipresets[quiz.settings.active_ipreset].content);
        old_position = quiz.settings.position;
        quiz.settings_dialog.open();

        function call_setup_quiz_settings(){
            setup_quiz_settings();
            wkof.Settings.load(scriptId)
                .then(function(){
                quiz_settings_state = 'ready';
                open_quiz_settings();
            });
        };
    }

    //========================================================================
    // save_quiz_settings()
    //------------------------------------------------------------------------
    function save_quiz_settings(settings) {
        quiz.settings = settings;
        populate_presets($('#Item_Inspector_source'), settings.ipresets, settings.active_ipreset);
        // check if the table list is empty
        if (!quiz.settings.ipresets.length){
            init_settings(); // restore defaults
        };
        add_defaults();

        initCurrentItem();
        setNumberOfLines();
        populateDropdown();
        if (old_position != quiz.settings.position){
            if (document.getElementById("WkitTopBar")){
                $('#WkitTopBar').empty();
                $('#WkitTopBar').remove();
                insertContainer();
                eventHandlers();
            };
        };

        quiz.settings.audioMode = false;
        formatControlBar();
        dataReload('table');
    }

    //========================================================================
    // close_quiz_settings()
    //------------------------------------------------------------------------
    function close_quiz_settings(settings) {
        quiz_settings_state = 'setup';
        quiz.settings = wkof.settings[scriptId]; // working around an obscure bug
    }

    //========================================================================
    // refresh_quiz_settings()
    //------------------------------------------------------------------------
    function refresh_quiz_settings(settings) {
        $('#Item_Inspector_ipre_srcs .wkof_group .row').each(function(i,e){
            var row = $(e);
            var panel = row.closest('[role="tabpanel"]');
            var source = panel.attr('id').match(/^Item_Inspector_pg_(.*)$/)[1];
            var filter_name = row.find('.setting').attr('name').slice((source+'_flt_').length);
            var preset = quiz.settings.ipresets[quiz.settings.active_ipreset].content;
            var enabled = false;
            try {
                enabled = preset[source].filters[filter_name].enabled;
            } catch(e) {}

            if (enabled) {
                row.addClass('checked');
            } else {
                row.removeClass('checked');
            }
            row.find('.enable input[type="checkbox"]').prop('checked', enabled);
        });
    }

    //========================================================================
    // refresh_ipresets()
    //------------------------------------------------------------------------
    function refresh_ipresets() {
        var settings = quiz.settings;
        populate_presets($('#Item_Inspector_active_ipreset'), settings.ipresets, settings.active_ipreset);
    }

    //========================================================================
    // preset_button_pressed()
    //------------------------------------------------------------------------
    function preset_button_pressed(e) {
        var settings = quiz.settings;
        var tablePresets = settings.tablePresets;
        var ref = e.currentTarget.attributes.ref.value;
        var action = e.currentTarget.attributes.action.value;
        var selected = Number(settings['active_'+ref]);
        var presets = settings[ref+'s'];
        var elem = $('#Item_Inspector_active_'+ref);

        var dflt;
        dflt = {name:'<untitled>', content:$.extend(true, {}, ipre_defaults)};

        switch (action) {
            case 'new':
                presets.push(dflt);
                tablePresets.push(table_defaults);
                selected = presets.length - 1;
                settings[ref+'s'] = presets;
                settings['active_'+ref] = selected;
                settings.tablePresets = tablePresets;
                populate_presets(elem, presets, selected);
                quiz.settings_dialog.refresh();
                $('#Item_Inspector_'+ref.slice(0,4)+'_name').focus().select();
                break;

            case 'up':
                if (selected <= 0) break;
                presets = [].concat(presets.slice(0, selected-1), presets[selected], presets[selected-1], presets.slice(selected+1));
                tablePresets = [].concat(tablePresets.slice(0, selected-1), tablePresets[selected], tablePresets[selected-1], tablePresets.slice(selected+1));
                selected--;
                settings[ref+'s'] = presets;
                settings['active_'+ref] = selected;
                settings.tablePresets = tablePresets;
                populate_presets(elem, presets, selected);
                break;

            case 'down':
                if (selected >= presets.length-1) break;
                presets = [].concat(presets.slice(0, selected), presets[selected+1], presets[selected], presets.slice(selected+2));
                tablePresets = [].concat(tablePresets.slice(0, selected), tablePresets[selected+1], tablePresets[selected], tablePresets.slice(selected+2));
                selected++;
                settings[ref+'s'] = presets;
                settings['active_'+ref] = selected;
                settings.tablePresets = tablePresets;
                populate_presets(elem, presets, selected);
                break;

            case 'delete':
                presets = presets.slice(0, selected).concat(presets.slice(selected+1));
                tablePresets = tablePresets.slice(0, selected).concat(tablePresets.slice(selected+1));
                selected = Math.max(0, selected-1);
                settings[ref+'s'] = presets;
                settings['active_'+ref] = selected;
                settings.tablePresets = tablePresets;
                populate_presets(elem, presets, selected);
                quiz.settings_dialog.refresh();
                break;
        }
    }

    function addTable(name){
        var settings = quiz.settings;
        var tablePresets = settings.tablePresets;
        var selected;
        var presets = settings.ipresets;

        var dflt;
        dflt = {name:name, content:$.extend(true, {}, ipre_defaults)};

        presets.push(dflt);
        tablePresets.push(table_defaults);
        selected = presets.length - 1;
        let keys = Object.keys(settings.defaults);
        for (var index in keys){
            let key = keys[index]
            tablePresets[selected][key] = settings.defaults[key];
        };
        add_defaults();
        settings.ipresets = presets;
        settings.active_ipreset = selected;
        settings.tablePresets = tablePresets;
        populateDropdown();
    };

    function removeTempTables(){
        var settings = quiz.settings;
        var tablePresets = settings.tablePresets;
        var presets = settings.ipresets;
        var selected = settings.active_ipreset;

        for (var j = presets.length - 1; j >=0; j--){
            if (presets[j].name.slice(0, 6) === '--Temp') deleteTable(j);
        };
        settings.ipresets = presets;
        settings.tablePresets = tablePresets;
        settings.active_ipreset = selected
        populateDropdown();

        function deleteTable(j){
            presets = presets.slice(0, j).concat(presets.slice(j+1));
            tablePresets = tablePresets.slice(0, j).concat(tablePresets.slice(j+1));
            if (selected > j){selected--};
        };
    };

    //========================================================================
    // init_settings()
    //------------------------------------------------------------------------
    var table_defaults;
    function init_settings() {
        var idx;
        // Merge some defaults
        var defaults = {
        };
        var settings = $.extend(true, {}, defaults, wkof.settings.Item_Inspector);
        wkof.settings.Item_Inspector = quiz.settings = settings;
        /*var settings;
        settings = quiz.settings = wkof.settings.Item_Inspector;*/


        let ipresets_defaults = [
            {name:'Leeches', content:{wk_items:{enabled:true,filters:{srs:{enabled:true,value:{appr1:true,appr2:true,appr3:true,appr4:true,guru1:true,guru2:true,mast:true}}
                                                                      ,additionalFilters_leechTraining:{enabled:true,value:1}}},
                                      tableContents:{currentItem:0,table_data:"Leech",sort1:"Default",sortOrder1:'Default',sort2:"Default",sortOrder2:'Default',
                                                     tooltip1:"Meaning_Full",tooltip2:"Reading_Full",tooltip3:"None",tooltip4:"None",tooltip5:"None",
                                                     tooltip6:"None",tooltip7:"None",tooltip8:"None",
                                                     displayMeaning:false,enlargingTooltip:true,showMarkers:true,showMarkersDate:false,showHours:false,leechStreakLimit:0,
                                                     randomSelection: 0,navigationDate:'Lesson_Date',
                                                     includeTitle:false,includeLabels:false,missingData:'Code_Word',separator:'\t',quotes:'Never',URLclickable:'Plain',
                                                     defhoursInDate:{'Review_Date': true},}}},
            {name:'Failed Last Review', content:{wk_items:{enabled:true,filters:{additionalFilters_failedLastReview:{enabled:true,value:24}}},
                                                 tableContents:{currentItem:0,table_data:"Leech",sort1:"Default",sortOrder1:'Default',sort2:"Default",sortOrder2:'Default',
                                                                tooltip1:"Meaning_Full",tooltip2:"Reading_Full",tooltip3:"None",tooltip4:"None",tooltip5:"None",
                                                                tooltip6:"None",tooltip7:"None",tooltip8:"None",
                                                                displayMeaning:false,enlargingTooltip:true,showMarkers:true,showMarkersDate:false,showHours:false,leechStreakLimit:0,
                                                                randomSelection: 0,navigationDate:'Lesson_Date',
                                                                includeTitle:false,includeLabels:false,missingData:'Code_Word',
                                                                separator:'\t',quotes:'Never',
                                                                URLclickable:'Plain',defhoursInDate:{'Review_Date': true},}}},
            {name:'Current Level SRS', content:{wk_items:{enabled:true,filters:{level:{enabled:true,value:"+0"},srs:{enabled:true,value:{appr1:true,appr2:true,appr3:true,appr4:true,guru1:true,guru2:true,mast:true,enli:true}}}},
                                                tableContents:{currentItem:0,table_data:"Srs",sort1:"Default",sortOrder1:'Default',sort2:"Default",sortOrder2:'Default',
                                                               tooltip1:"Review_Date",tooltip2:"Review_Wait",tooltip3:"None",tooltip4:"None",tooltip5:"None",
                                                               tooltip6:"None",tooltip7:"None",tooltip8:"None",
                                                               displayMeaning:false,enlargingTooltip:false,showMarkers:true,showMarkersDate:false,showHours:false,leechStreakLimit:0,
                                                               randomSelection: 0,navigationDate:'Lesson_Date',
                                                               includeTitle:false,includeLabels:false,missingData:'Code_Word',separator:'\t',quotes:'Never',
                                                               URLclickable:'Plain',defhoursInDate:{'Review_Date': true},}}},
            {name:'Previous Level SRS', content:{wk_items:{enabled:true,filters:{level:{enabled:true,value:"-1"},srs:{enabled:true,value:{appr1:true,appr2:true,appr3:true,appr4:true,guru1:true,guru2:true,mast:true,enli:true}}}},
                                                 tableContents:{currentItem:0,table_data:"Srs",sort1:"Default",sortOrder1:'Default',sort2:"Default",sortOrder2:'Default',
                                                                tooltip1:"Review_Date",tooltip2:"Review_Wait",tooltip3:"None",tooltip4:"None",tooltip5:"None",
                                                                tooltip6:"None",tooltip7:"None",tooltip8:"None",
                                                                displayMeaning:false,enlargingTooltip:false,showMarkers:true,showMarkersDate:false,showHours:false,leechStreakLimit:0,
                                                                randomSelection: 0,navigationDate:'Lesson_Date',
                                                                includeTitle:false,includeLabels:false,missingData:'Code_Word',separator:'\t',quotes:'Never',
                                                                URLclickable:'Plain',defhoursInDate:{'Review_Date': true},}}},
            {name:'Burned Items', content:{wk_items:{enabled:true,filters:{srs:{enabled:true,value:{burn:true}}}},
                                                 tableContents:{currentItem:0,table_data:"Level",sort1:"Default",sortOrder1:'Default',sort2:"Default",sortOrder2:'Default',
                                                                tooltip1:"Meaning_Full",tooltip2:"Reading_Full",tooltip3:"None",tooltip4:"None",tooltip5:"None",
                                                                tooltip6:"None",tooltip7:"None",tooltip8:"None",
                                                                displayMeaning:false,enlargingTooltip:true,showMarkers:true,showMarkersDate:false,showHours:false,leechStreakLimit:0,
                                                                randomSelection: 0,navigationDate:'Burned_Date',
                                                                includeTitle:false,includeLabels:false,missingData:'Code_Word',separator:'\t',quotes:'Never',
                                                                URLclickable:'Plain',defhoursInDate:{'Review_Date': true},}}},
        ];
        table_defaults = {currentItem:0,table_data:"Leech",sort1:"Default",sortOrder1:'Default',sort2:"Default",sortOrder2:'Default',
                          tooltip1:"Meaning_Full",tooltip2:"Reading_Full",tooltip3:"None",tooltip4:"None",tooltip5:"None",tooltip6:"None",tooltip7:"None",tooltip8:"None",
                          displayMeaning:false,enlargingTooltip:false,showMarkers:true,showMarkersDate:false,showHours:false,leechStreakLimit:0,randomSelection: 0,
                          navigationDate:'Lesson_Date',includeTitle:false,
                          includeLabels:false,missingData:'Code_Word',separator:'\t',quotes:'Never',URLclickable:'Plain',defhoursInDate:{'Review_Date': true},};
        for (var i = 0; i < exportedInfo.length; i++){
            table_defaults[exportedInfo[i]] = 'None';
        };
        // define defaults if presets not yet defined
        if (settings.ipresets === undefined) {
            settings.ipresets = ipresets_defaults;
            settings.active_ipreset = 0;
            settings.tablePresets = init_table_presets(ipresets_defaults);
        };
        // restore defaults when ipresets list is empty
        if (!settings.ipresets.length) {
            settings.ipresets = ipresets_defaults;
            settings.active_ipreset = 0;
            settings.tablePresets = init_table_presets(ipresets_defaults);
        };
        if (ipre_defaults) {
            for (idx in settings.ipresets) {
                settings.ipresets[idx].content = $.extend(true, {}, ipre_defaults, settings.ipresets[idx].content);
            }
        }

        function init_table_presets(ipresets_defaults){
            var x = [];
            for (var y of ipresets_defaults){x.push(y.content.tableContents)};
            return x;
        }
    }

    //========================================================================
    // populate_items_config()
    //------------------------------------------------------------------------
    var ipre_defaults;
    function populate_items_config(config) {
        var ipre_srcs = config.settings.pg_items.content.grp_ipre.content.ipre_srcs.content;
        var srcs = wkof.ItemData.registry.sources;
        ipre_defaults = {};
        let src_name = 'wk_items';
        var src = srcs[src_name];
        var pg_content = {};
        ipre_srcs['pg_'+src_name] = {type:'page',label:'Filters',content:pg_content};
        var settings = {};
        ipre_defaults[src_name] = settings;

        // Add 'Filters' section.
        if (src.filters && Object.keys(src.filters).length > 0) {
            settings.filters = {};
            var flt_content = {};
            pg_content['grp_'+src_name+'_filters'] = {type:'group',label:'',content:flt_content};
            for (var flt_name in src.filters) {
                var flt = src.filters[flt_name];
                if (flt.no_ui) continue;
                settings.filters[flt_name] = {enabled:false, value:flt.default};
                switch (flt.type) {
                    case 'checkbox':
                        flt_content[src_name+'_flt_'+flt_name] = {
                            type:'checkbox',
                            label:flt.label,
                            default:flt.default,
                            path:'@ipresets[@active_ipreset].content["'+src_name+'"].filters["'+flt_name+'"].value',
                            hover_tip:flt.hover_tip
                        }
                        break;
                    case 'multi':
                        var dflt = flt.default;
                        if (typeof flt.filter_value_map === 'function') dflt = flt.filter_value_map(dflt);
                        flt_content[src_name+'_flt_'+flt_name] = {
                            type:'list',
                            multi:true,
                            size:Math.min(4,Object.keys(flt.content).length),
                            label:flt.label,
                            content:flt.content,
                            default:dflt,
                            path:'@ipresets[@active_ipreset].content["'+src_name+'"].filters["'+flt_name+'"].value',
                            hover_tip:flt.hover_tip
                        }
                        settings.filters[flt_name].value = dflt;
                        break;
                    case 'text':
                    case 'number':
                    case 'input':
                        flt_content[src_name+'_flt_'+flt_name] = {
                            type:flt.type,
                            label:flt.label,
                            validate:flt.validate,
                            placeholder:flt.placeholder,
                            default:flt.default,
                            path:'@ipresets[@active_ipreset].content["'+src_name+'"].filters["'+flt_name+'"].value',
                            hover_tip:flt.hover_tip
                        }
                        break;
                    case 'button':
                        flt_content[src_name+'_flt_'+flt_name] = {
                            type:flt.type,
                            label:flt.label,
                            on_click:flt.on_click,
                            hover_tip:flt.hover_tip
                        }
                        break;
                }
            }
        }
    }

    //========================================================================
    // toggle_filter()
    //------------------------------------------------------------------------
    function toggle_filter(e) {
        var row = $(e.delegateTarget);
        var panel = row.closest('[role="tabpanel"]');
        var source = panel.attr('id').match(/^Item_Inspector_pg_(.*)$/)[1];
        var enabled = row.find('.enable input[type="checkbox"]').prop('checked');
        var preset = quiz.settings.ipresets[quiz.settings.active_ipreset].content;
        var filter_name = row.find('.setting').attr('name').slice((source+'_flt_').length);

        if (enabled) {
            row.addClass('checked');
        } else {
            row.removeClass('checked');
        }
        try {
            preset[source].filters[filter_name].enabled = enabled;
        } catch(e) {}
    }

    //========================================================================
    // populate_presets()
    //------------------------------------------------------------------------
    function populate_presets(elem, presets, active_preset) {
        var html = '';
        for (var idx in presets) {
            var preset = presets[idx];
            var name = preset.name.replace(/</g,'&lt;').replace(/>/g,'&gt;');
            html += '<option name="'+idx+'">'+name+'</option>';
        }
        var elem_name = elem.attr('id')
        if (elem_name === 'Item_Inspector_source' && quiz.custom.has_ipreset) {
            html += '<option name="custom">('+quiz.custom.ipreset.name+')</option>';
            if (quiz.custom.using_ipreset) active_preset = presets.length;
        }
        elem.html(html);
        elem.children().eq(active_preset).prop('selected', true);

    }

    //========================================================================
    // add_defaults()
    //------------------------------------------------------------------------
    function add_defaults(){
        let settings = quiz.settings;
        if (settings.hoursFormat == undefined){settings.hoursFormat = '24h'};
        if (settings.position == undefined){settings.position = 2};
        if (settings.numberOfLines == undefined){settings.numberOfLines = 11};
        if (settings.listMode == undefined){settings.listMode = false};
        if (settings.audioSource == undefined){settings.audioSource = 'random'};
        if (settings.audioMode == undefined){settings.audioMode = false};
        if (settings.noLatin == undefined){settings.noLatin = false};
        if (settings.oneItemPerLine == undefined){settings.oneItemPerLine = false};
        if (settings.exportLimit == undefined){settings.exportLimit = 0};
        if (settings.repeatWordCloud == undefined){settings.repeatWordCloud = 'No Repeat'};

        let tablePresets = quiz.settings.tablePresets;
        for (var i = 0; i < tablePresets.length; i++){
            if (tablePresets[i].table_data == undefined){tablePresets[i].table_data = 'Leech'};
            if (tablePresets[i].sort1 == undefined){tablePresets[i].sort1 = 'Default'};
            if (tablePresets[i].sortOrder1 == undefined){tablePresets[i].sortOrder1 = 'Default'};
            if (tablePresets[i].sort2 == undefined){tablePresets[i].sort2 = 'Default'};
            if (tablePresets[i].sortOrder2 == undefined){tablePresets[i].sortOrder2 = 'Default'};
            if (tablePresets[i].tooltip1 == undefined){tablePresets[i].tooltip1 = 'Meaning_Full'};
            if (tablePresets[i].tooltip2 == undefined){tablePresets[i].tooltip2 = 'Reading_Full'};
            if (tablePresets[i].tooltip3 == undefined){tablePresets[i].tooltip3 = 'None'};
            if (tablePresets[i].tooltip4 == undefined){tablePresets[i].tooltip4 = 'None'};
            if (tablePresets[i].tooltip5 == undefined){tablePresets[i].tooltip5 = 'None'};
            if (tablePresets[i].tooltip6 == undefined){tablePresets[i].tooltip6 = 'None'};
            if (tablePresets[i].tooltip7 == undefined){tablePresets[i].tooltip7 = 'None'};
            if (tablePresets[i].tooltip8 == undefined){tablePresets[i].tooltip8 = 'None'};
            if (tablePresets[i].displayMeaning == undefined){tablePresets[i].displayMeaning = false};
            if (tablePresets[i].enlargingTooltip == undefined){tablePresets[i].enlargingTooltip = false};
            if (tablePresets[i].showMarkers == undefined){tablePresets[i].showMarkers = true};
            if (tablePresets[i].showMarkersDate == undefined){tablePresets[i].showMarkersDate = false};
            if (tablePresets[i].showHours == undefined){tablePresets[i].showHours = false};
            if (tablePresets[i].leechStreakLimit == undefined){tablePresets[i].leechStreakLimit = 0};
            if (tablePresets[i].randomSelection == undefined){tablePresets[i].randomSelection = 0};
            if (tablePresets[i].navigationDate == undefined){tablePresets[i].navigationDate = 'Lesson_Date'};
            if (tablePresets[i].includeTitle == undefined){tablePresets[i].includeTitle = false};
            if (tablePresets[i].includeTitle == 0){tablePresets[i].includeTitle = false}; // fixing the consequence of a bug
            if (tablePresets[i].includeLabels == undefined){tablePresets[i].includeLabels = false};
            if (tablePresets[i].missingData == undefined){tablePresets[i].missingData = 'Code_Word'};
            if (tablePresets[i].separator == undefined){tablePresets[i].separator ='\t'};
            if (tablePresets[i].quotes == undefined){tablePresets[i].quotes = 'Never'};
            if (tablePresets[i].URLclickable == undefined){tablePresets[i].URLclickable = 'Plain'};
            if (tablePresets[i].URLclickable == false){tablePresets[i].URLclickable = 'Plain'};
            if (tablePresets[i].URLclickable == true){tablePresets[i].URLclickable = 'Spreadsheet'};
            if (tablePresets[i].hoursInDate == undefined){tablePresets[i].hoursInDate = {"Review_Date": true}};
            if (tablePresets[i].currentItem == undefined){tablePresets[i].currentItem = 0};
            if (tablePresets[i].nextCurrentItem == undefined){tablePresets[i].nextCurrentItem = 0};
            if (tablePresets[i].savedCurrentItem == undefined){tablePresets[i].savedCurrentItem = 0};
            if (tablePresets[i].savedNextCurrentItem == undefined){tablePresets[i].savedNextCurrentItem = 0};
            if (tablePresets[i].itemList == undefined){tablePresets[i].itemList = []};
            if (tablePresets[i].selection == undefined){tablePresets[i].selection = 'None'};
            if (tablePresets[i].startDate == undefined){tablePresets[i].startDate = 0};
            if (tablePresets[i].savedSelCurrentItem == undefined){tablePresets[i].savedSelCurrentItem = 0};
            if (tablePresets[i].savedSelNextCurrentItem == undefined){tablePresets[i].savedSelNextCurrentItem = 0};

            for (var j = 0; j < exportedInfo.length; j++){
                if(tablePresets[i][exportedInfo[j]] == undefined) tablePresets[i][exportedInfo[j]] = 'None';
            };
        }

        if (quiz.settings.defaults == undefined) quiz.settings.defaults = {};
        let defaults = quiz.settings.defaults;
        if (defaults.table_data == undefined){defaults.table_data = 'Level'};
        if (defaults.sort1 == undefined){defaults.sort1 = 'Level'};
        if (defaults.sortOrder1 == undefined){defaults.sortOrder1 = 'Default'};
        if (defaults.sort2 == undefined){defaults.sort2 = 'Default'};
        if (defaults.sortOrder2 == defaults){defaults.sortOrder2 = 'Default'};
        if (defaults.tooltip1 == undefined){defaults.tooltip1 = 'Meaning_Full'};
        if (defaults.tooltip2 == undefined){defaults.tooltip2 = 'Reading_Full'};
        if (defaults.tooltip3 == undefined){defaults.tooltip3 = 'Srs'};
        if (defaults.tooltip4 == undefined){defaults.tooltip4 = 'Unlock_Date'};
        if (defaults.tooltip5 == undefined){defaults.tooltip5 = 'Lesson_Date'};
        if (defaults.tooltip6 == undefined){defaults.tooltip6 = 'Passed_Date'};
        if (defaults.tooltip7 == undefined){defaults.tooltip7 = 'Burned_Date'};
        if (defaults.tooltip8 == undefined){defaults.tooltip8 = 'Leech'};
        if (defaults.displayMeaning == undefined){defaults.displayMeaning = false};
        if (defaults.enlargingTooltip == undefined){defaults.enlargingTooltip = false};
        if (defaults.showMarkers == undefined){defaults.showMarkers = true};
        if (defaults.showMarkersDate == undefined){defaults.showMarkersDate = false};
        if (defaults.showHours == undefined){defaults.showHours = false};
        if (defaults.leechStreakLimit == undefined){defaults.leechStreakLimit = 0};
        if (defaults.randomSelection == undefined){defaults.randomSelection = 0};
        if (defaults.navigationDate == undefined){defaults.navigationDate = 'Lesson_Date'};
        if (defaults.itemsLimit == undefined){defaults.itemsLimit = 200};
        if (defaults.includeTitle == undefined){defaults.includeTitle = false};
        if (defaults.includeLabels == undefined){defaults.includeLabels = false};
        if (defaults.missingData == undefined){defaults.missingData = 'Code_Word'};
        if (defaults.separator == undefined){defaults.separator ='\t'};
        if (defaults.quotes == undefined){defaults.quotes = 'Never'};
        if (defaults.URLclickable == undefined){defaults.URLclickable = 'Plain'};
        if (defaults.URLclickable == false){defaults.URLclickable = 'Plain'};
        if (defaults.URLclickable == true){defaults.URLclickable = 'Spreadsheet'};
        if (defaults.hoursInDate == undefined){defaults.hoursInDate = {"Review_Date": true}};
        if (defaults.currentItem == undefined){defaults.currentItem = 0};
        if (defaults.nextCurrentItem == undefined){defaults.nextCurrentItem = 0};
        if (defaults.savedCurrentItem == undefined){defaults.savedCurrentItem = 0};
        if (defaults.savedNextCurrentItem == undefined){defaults.savedNextCurrentItem = 0};
        if (defaults.itemList == undefined){defaults.itemList = []};
        if (defaults.selection == undefined){defaults.selection = 'None'};
        if (defaults.startDate == undefined){defaults.startDate = 0};
        if (defaults.savedSelCurrentItem == undefined){defaults.savedSelCurrentItem = 0};
        if (defaults.savedSelNextCurrentItem == undefined){defaults.savedSelNextCurrentItem = 0};
        for (j = 0; j < exportedInfo.length; j++){
            if(defaults[exportedInfo[j]] == undefined) defaults[exportedInfo[j]] = 'None';
        };

        return quiz.settings_dialog.save()
    }

    //########################################################################
    // QUIZ DIALOG
    //########################################################################

    //========================================================================
    // install_css()
    //------------------------------------------------------------------------
    function install_css() {
        $('head').append(
            '<style id="Item_Inspector_css" type="text/css">'+

            //--[ Settings dialog ]-------------------------------------------
            '#wkof_ds div[role="dialog"][aria-describedby="wkofs_Item_Inspector"] {z-index:12002;}'+

            '#wkofs_Item_Inspector.wkof_settings .pre_list_btn_grp {width:60px;float:left;margin-right:2px;}'+
            '#wkofs_Item_Inspector.wkof_settings .pre_list_btn_grp button {width:100%; padding:2px 0;}'+
            '#wkofs_Item_Inspector.wkof_settings .pre_list_btn_grp button:not(:last-child) {margin-bottom:2px;}'+
            '#wkofs_Item_Inspector.wkof_settings .pre_list_wrap {display:flex;}'+
            '#wkofs_Item_Inspector.wkof_settings .pre_list_wrap .right {flex:1;}'+
            '#wkofs_Item_Inspector.wkof_settings .pre_list_wrap .list {overflow:auto;height:100%;}'+

            '#wkofs_Item_Inspector.wkof_settings .filters .row {border-top:1px solid #ccc; padding:6px 4px; margin-bottom:0;}'+
            '#wkofs_Item_Inspector.wkof_settings .filters .row:not(.checked) {padding-top:0px;padding-bottom:0px;}'+
            '#wkofs_Item_Inspector .filters .row .enable input[type="checkbox"] {margin:0;}'+
            '#wkofs_Item_Inspector.narrow .filters .row.checked .right input[type="checkbox"]:after {content:"⇐yes?";margin-left:28px;line-height:30px;}'+
            '#wkofs_Item_Inspector .filters .row.checked {background-color:#f7f7f7;}'+
            '#wkofs_Item_Inspector .filters .row:not(.checked) {opacity:0.5;}'+
            '#wkofs_Item_Inspector .filters .row .enable {display:inline; margin:0; float:left;}'+
            '#wkofs_Item_Inspector:not(.narrow) .filters .left {width:170px;}'+

            '#wkofs_Item_Inspector .filters .row .enable input[type="checkbox"] {margin:0 4px 0 0;}'+
            '#wkofs_Item_Inspector .filters .row:not(.checked) .right {display:none;}'+
            '#wkofs_Item_Inspector .filters .row:not(.checked) .left label {text-align:left;}'+
            '#wkofs_Item_Inspector.narrow .filters .row .left {width:initial;}'+
            '#wkofs_Item_Inspector.narrow .filters .row .left label {line-height:30px;}'+
            '#wkofs_Item_Inspector #Item_Inspector_ipre_srcs .src_enable .left {width:initial;}'+
            '#wkofs_Item_Inspector #Item_Inspector_ipre_srcs .src_enable .left label {text-align:left;width:initial;line-height:30px;}'+
            '#wkofs_Item_Inspector #Item_Inspector_ipre_srcs .src_enable .right {float:left; margin:0 4px;width:initial;}'+
            //----------------------------------------------------------------

            '</style>'
        );
    }

    var subjectIndex = false;
    var subjectIndexVoc = {};
    var subjectIndexKan = {};
    var subjectIndexRad = {};
    //========================================================================
    // fetch_items()
    //------------------------------------------------------------------------
    function fetch_items(required) {
        var settings = quiz.settings;
        var ipreset = settings.ipresets[settings.active_ipreset].content;
        var presets = settings.tablePresets[settings.active_ipreset];

        let idList = presets.itemList;
        if (idList != undefined){
            if (idList.length > 0){
                if (subjectIndex === false){
                    let config2 = {wk_items: {filters:{}, options:{'subjects': true, 'assignments': true, 'review_statistics': true}}};
                    return wkof.ItemData.get_items(config2)
                        .then(function(items2){makeIndexes(items2);
                                               quiz.items = populateItemList();
                                              });
                } else {
                    quiz.items = populateItemList();
                    return Promise.resolve();
                };
            };
        };

        function populateItemList(){
            let items = [];
            for (let index in idList){
                let item = subjectIndexVoc[idList[index]];
                if (item === undefined) item = subjectIndexKan[idList[index]];
                if (item === undefined) item = subjectIndexRad[idList[index]];
                items.push(item);
            };
            return items;
        }

        //set_mode('loading');
        var config = {};
        for (var src_name in ipreset) {
            var src_preset = ipreset[src_name];
            if (!wkof.ItemData.registry.sources[src_name]) continue;
            var src_cfg = {};
            config[src_name] = src_cfg;
            src_cfg.filters = {};
            if (src_name === 'wk_items') src_cfg.options = {};
            var ipre_filters = src_preset.filters;
            for (var flt_name in ipre_filters) {
                var ipre_flt = ipre_filters[flt_name];
                if (!ipre_flt.enabled) continue;
                if (!wkof.ItemData.registry.sources[src_name].filters[flt_name]) continue;
                src_cfg.filters[flt_name] = {value: ipre_flt.value};
                if (ipre_flt.invert === true) src_cfg.filters[flt_name].invert = true;
            }
        }

        let needSubjects = presets.selection === 'Random';// random selection always need subject index
        //let presets = quiz.settings.tablePresets[settings.active_ipreset];
        if (required === undefined || required === 'table'){
            for (var settingName in standardInfo){
                var setting = presets[standardInfo[settingName]];
                needSubjects = needSubjects || needSubjectId[setting] === true;
                if ((setting != 'None') && (setting != 'Default')) {
                    src_cfg.options[metadata[setting].endPoint] = true;
                };
            };
        } else if (required === 'export') {
            for (settingName in exportedInfo){
                setting = presets[exportedInfo[settingName]];
                needSubjects = needSubjects || needSubjectId[setting] === true;
                if ((setting != 'None') && (setting != 'Default')) {
                    src_cfg.options[metadata[setting].endPoint] = true;
                };
            };
        };

        if (presets.leechStreakLimit != 0) {src_cfg.options.review_statistics = true};
        if (required === 'wordCloud') {src_cfg.options.review_statistics = true};

        // It is best not to run the two wkof.ItemData.get_items concurrently because they go for the same items.
        // The unfiltered request goes first and the filtered one will run on the cache once the items are there.
        // A concurrent run doesn't make sense and leads to weird bugs.
        if (subjectIndex === false && needSubjects ){
            let config2 = {wk_items: {filters:{}, options:{'subjects': true, 'assignments': true, 'review_statistics': true}}};
            return wkof.ItemData.get_items(config2)
                .then(function(items2){makeIndexes(items2);
                                       return wkof.ItemData.get_items(config)}).then(function(items){quiz.items = items;});
        } else {
            return wkof.ItemData.get_items(config)
                .then(function(items){quiz.items = items;});
        };

    };

    // Over 90% of the time we know the item type so we can search a smaller and faster index.
    // In the remaining cases we test the three indexes in a row to find the right one.
    // In the volume, accelerating the indexes when we know the type improves significantly the response time.
    function makeIndexes(items){
        for (let key in items){
            let item = items[key];
            switch (item.object){
                case 'vocabulary':
                    subjectIndexVoc[item.id] = item;
                    break;
                case 'kanji':
                    subjectIndexKan[item.id] = item;
                    break;
                case 'radical':
                    subjectIndexRad[item.id] = item;
                    break;
            };
        };

        subjectIndex = true;
    }

    //------------------------------
    // Calculating displayed data
    //------------------------------

    var theFuture = Date.parse("01 Jan 2090 00:00:00 GMT");
    var infinity = 100000000; // big enough
    var srsName = ["Initiate","Apprentice I","Apprentice II","Apprentice III","Apprentice IV","Guru I","Guru II","Master","Enlightened","Burned"];

    var metadata = {'Meaning_Brief': {'exists': ((item) => {return true}), 'label': 'Meaning ',
                                      'tableEntry': meaningsBrief,
                                      'tableEntryMarker': ((item)=>''),
                                      'tooltipEntry': meaningsBrief,
                                      'sortkey': ((item) => {return 0}),
                                      'sortOrder': 'Ascending',
                                      'sortkey2': ((item) => {return 0}),
                                      'sortOrder2': 'Ascending',
                                      'preciseSortkey': ((item) => {return 0}),
                                      'endPoint' : 'subjects',
                                      'title': 'Meaning',
                                      'needQuotes': true,
                                      'labelExport': '',
                                      'export': meaningsBrief,
                                      'itemList': ((item)=>'None'),
                                      'idList': ((item)=>[]),
                                      'isDate': false, 'isList': false,
                                     },
                    'Meaning_Full': {'exists': ((item) => {return true}), 'label': 'Meaning ',
                                     'tableEntry': meaningsFullTable,
                                     'tableEntryMarker': ((item)=>''),
                                     'tooltipEntry': meaningsFull,
                                     'sortkey': ((item) => {return 0}),
                                     'sortOrder': 'Ascending',
                                     'sortkey2': ((item) => {return 0}),
                                     'sortOrder2': 'Ascending',
                                     'preciseSortkey': ((item) => {return 0}),
                                     'endPoint' : 'subjects',
                                     'title': 'Meaning',
                                     'labelExport': '',
                                     'needQuotes': true,
                                     'export': meaningsFull,
                                     'itemList': ((item)=>'None'),
                                     'idList': ((item)=>[]),
                                     'isDate': false, 'isList': true,
                                    },
                    'Reading_Brief': {'exists': ((item) => {return !(item.data.readings == undefined)}), 'label': 'Reading ',
                                      'tableEntry': readingsBrief,
                                      'tableEntryMarker': ((item)=>''),
                                      'tooltipEntry': readingsBrief,
                                      'sortkey': ((item) => {return 0}),
                                      'sortOrder': 'Ascending',
                                      'sortkey2': ((item) => {return 0}),
                                      'sortOrder2': 'Ascending',
                                      'preciseSortkey': ((item) => {return 0}),
                                      'endPoint' : 'subjects',
                                      'title': 'Reading',
                                      'labelExport': '',
                                      'needQuotes': true,
                                      'export': readingsBrief,
                                      'itemList': ((item)=>'None'),
                                      'idList': ((item)=>[]),
                                      'isDate': false, 'isList': true,
                                     },
                    'Reading_Full': {'exists': ((item) => {return !(item.data.readings == undefined)}), 'label': 'Reading ',
                                     'tableEntry': ((item) => readingsFull(item, false)),
                                     'tableEntryMarker': ((item) => ''),
                                     'tooltipEntry': readingsFull,
                                     'sortkey': ((item) => {return 0}),
                                     'sortOrder': 'Ascending',
                                     'sortkey2': ((item) => {return 0}),
                                     'sortOrder2': 'Ascending',
                                     'preciseSortkey': ((item) => {return 0}),
                                     'endPoint' : 'subjects',
                                     'title': 'Reading',
                                     'labelExport': '',
                                     'needQuotes': true,
                                     'export': readingsFull,
                                     'itemList': ((item)=>'None'),
                                     'idList': ((item)=>[]),
                                     'isDate': false, 'isList': true,
                                    },
                    'Leech': {'exists': ((item) => {return true}), 'label': 'Leech ',
                              'tableEntry': leechScore,
                              'tableEntryMarker': leechScore,
                              'tooltipEntry': leechScore,
                              'tableEntryMarker': leechScore,
                              'sortkey': leechScore,
                              'sortOrder': 'Descending',
                              'sortkey2': ((item) => {return (item.review_statistics ? item.review_statistics.percentage_correct : infinity)}),
                              'sortOrder2': 'Ascending',
                              'preciseSortkey': leechScore,
                              'endPoint' : 'review_statistics',
                              'wordCloud': ((item) => {return Math.round(leechScore(item))}),
                              'title': 'Leech',
                              'labelExport': 'Leech: ',
                              'needQuotes': true,
                              'export': ((item)=>leechScore(item).toLocaleString()),
                              'itemList': ((item)=>'None'),
                              'idList': ((item)=>[]),
                              'isDate': false, 'isList': false,
                             },
                    'Total_Incorrect_Answers': {'exists': ((item) => {return true}), 'label': 'Tot.&nbsp;Incor. ',
                                                'tableEntry': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect + (item.object !== 'radical' ? item.review_statistics.reading_incorrect : 0) : 'Unavailable')}),
                                                'tableEntryMarker': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect + (item.object !== 'radical' ? item.review_statistics.reading_incorrect : 0) : 'Unavailable')}),
                                                'tooltipEntry':  ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect + (item.object !== 'radical' ? item.review_statistics.reading_incorrect : 0) : 'Unavailable')}),
                                                'sortkey': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect + (item.object !== 'radical' ? item.review_statistics.reading_incorrect : 0) : infinity)}),
                                                'sortOrder': 'Descending',
                                                'sortkey2': leechScore,
                                                'sortOrder2': 'Descending',
                                                'preciseSortkey': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect + (item.object !== 'radical' ? item.review_statistics.reading_incorrect : 0) : infinity)}),
                                                'endPoint' : 'review_statistics',
                                                'wordCloud': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect + (item.object !== 'radical' ? item.review_statistics.reading_incorrect : 0) : 'Unavailable')}),
                                                'title': 'Total Incor.',
                                                'labelExport': 'Total Incor: ',
                                                'needQuotes': false,
                                                'export': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect + (item.object !== 'radical' ? item.review_statistics.reading_incorrect : 0) : 'Unavailable')}),
                                                'itemList': ((item)=>'None'),
                                                'idList': ((item)=>[]),
                                                'isDate': false, 'isList': false,
                                               },
                    'Total_Correct_Answers': {'exists': ((item) => {return true}), 'label': 'Tot.&nbsp;Cor. ',
                                              'tableEntry': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct + (item.object === 'radical' ? item.review_statistics.reading_correct: 0) : 'Unavailable')}),
                                              'tableEntryMarker': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct + (item.object === 'radical' ? item.review_statistics.reading_correct: 0) : 'Unavailable')}),
                                              'tooltipEntry':  ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct + (item.object === 'radical' ? item.review_statistics.reading_correct: 0) : 'Unavailable')}),
                                              'sortkey': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct + (item.object === 'radical' ? item.review_statistics.reading_correct: 0) : infinity)}),
                                              'sortOrder': 'Ascending',
                                              'sortkey2': leechScore,
                                              'sortOrder2': 'Descending',
                                              'preciseSortkey': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct + (item.object === 'radical' ? item.review_statistics.reading_correct: 0) : infinity)}),
                                              'endPoint' : 'review_statistics',
                                              'wordCloud': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct + (item.object === 'radical' ? item.review_statistics.reading_correct: 0) : 'Unavailable')}),
                                              'title': 'Total Cor.',
                                              'needQuotes': false,
                                              'labelExport': 'Total Cor: ',
                                              'export': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct + (item.object === 'radical' ? item.review_statistics.reading_correct: 0) : 'Unavailable')}),
                                              'itemList': ((item)=>'None'),
                                              'idList': ((item)=>[]),
                                              'isDate': false, 'isList': false,
                                             },
                    'Percentage_Correct': {'exists': ((item) => {return true}), 'label': '%Total ',
                                           'tableEntry': ((item) => {return (item.review_statistics ? item.review_statistics.percentage_correct+'%' : 'Unavailable')}),
                                           'tableEntryMarker': ((item) => {return (item.review_statistics ? item.review_statistics.percentage_correct+'%' : 'Unavailable')}),
                                           'tooltipEntry':  ((item) => {return (item.review_statistics ? item.review_statistics.percentage_correct+'%' : 'Unavailable')}),
                                           'sortkey': ((item) => {return (item.review_statistics ? item.review_statistics.percentage_correct : infinity)}),
                                           'sortOrder': 'Ascending',
                                           'sortkey2': leechScore,
                                           'sortOrder2': 'Descending',
                                           'endPoint' : 'review_statistics',
                                           'preciseSortkey': ((item) => {return (item.review_statistics ? item.review_statistics.percentage_correct : infinity)}),
                                           'wordCloud': ((item) => {return (item.review_statistics ? item.review_statistics.percentage_correct : 0)}),
                                           'title': '%Total',
                                           'labelExport': '%Total: ',
                                           'needQuotes': false,
                                           'export': ((item) => {return (item.review_statistics ? item.review_statistics.percentage_correct+'%' : 'Unavailable')}),
                                           'itemList': ((item)=>'None'),
                                           'idList': ((item)=>[]),
                                           'isDate': false, 'isList': false,
                                          },
                    'Meaning_Correct': {'exists': ((item) => {return true}), 'label': '%Meaning ',
                                        'tableEntry': ((item) => {return (item.review_statistics ? MeaningCorrect(item)+'%' : 'Unavailable')}),
                                        'tableEntryMarker': ((item) => {return (item.review_statistics ? MeaningCorrect(item)+'%' : 'Unavailable')}),
                                        'tooltipEntry':  ((item) => {return (item.review_statistics ? MeaningCorrect(item)+'%' : 'None')}),
                                        'sortkey': ((item) => {return (item.review_statistics ? MeaningCorrect(item) : infinity)}),
                                        'sortOrder': 'Ascending',
                                        'sortkey2': leechScore,
                                        'sortOrder2': 'Descending',
                                        'preciseSortkey': ((item) => {return (item.review_statistics ? MeaningCorrect(item) : infinity)}),
                                        'endPoint' : 'review_statistics',
                                        'title': '%Meaning',
                                        'labelExport': '%Meaning: ',
                                        'needQuotes': false,
                                        'export': ((item) => {return (item.review_statistics ? MeaningCorrect(item)+'%' : 'Unavailable')}),
                                        'itemList': ((item)=>'None'),
                                        'idList': ((item)=>[]),
                                        'isDate': false, 'isList': false,
                                       },
                    'Reading_Correct': {'exists': ((item) => {return item.object !== 'radical'}), 'label': '%Reading ',
                                        'tableEntry': ((item) => {return (item.review_statistics ? ReadingCorrect(item)+'%' : 'Unavailable')}),
                                        'tableEntryMarker': ((item) => {return (item.review_statistics ? ReadingCorrect(item)+'%' : 'Unavailable')}),
                                        'tooltipEntry':  ((item) => {return (item.review_statistics ? ReadingCorrect(item)+'%' : 'Unavailable')}),
                                        'sortkey': ((item) => {return (item.review_statistics ? ReadingCorrect(item) : infinity)}),
                                        'sortOrder': 'Ascending',
                                        'sortkey2': leechScore,
                                        'sortOrder2': 'Descending',
                                        'preciseSortkey': ((item) => {return (item.review_statistics ? ReadingCorrect(item) : infinity)}),
                                        'endPoint' : 'review_statistics',
                                        'wordCloud': ((item) => {return (item.review_statistics ? ReadingCorrect(item) : 0)}),
                                        'title': '%Reading',
                                        'labelExport': '%Reading: ',
                                        'needQuotes': false,
                                        'export': ((item) => {return (item.review_statistics ? ReadingCorrect(item)+'%' : 'Unavailable')}),
                                        'itemList': ((item)=>'None'),
                                        'idList': ((item)=>[]),
                                        'isDate': false, 'isList': false,
                                       },
                    'Meaning_Incorrect_Answers': {'exists': ((item) => {return true}), 'label': 'Mg&nbsp;Incor. ',
                                                  'tableEntry': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect : 'Unavailable')}),
                                                  'tableEntryMarker': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect : 'Unavailable')}),
                                                  'tooltipEntry':  ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect : 'Unavailable')}),
                                                  'sortkey': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect : infinity)}),
                                                  'sortOrder': 'Descending',
                                                  'sortkey2': leechScore,
                                                  'sortOrder2': 'Descending',
                                                  'preciseSortkey': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect : infinity)}),
                                                  'endPoint' : 'review_statistics',
                                                  'wordCloud': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect : 'Unavailable')}),
                                                  'title': 'Meaning Incor.',
                                                  'labelExport': 'Meaning Incor: ',
                                                  'needQuotes': false,
                                                  'export': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_incorrect : 'Unavailable')}),
                                                  'itemList': ((item)=>'None'),
                                                  'idList': ((item)=>[]),
                                                  'isDate': false, 'isList': false,
                                                 },
                    'Meaning_Correct_Answers': {'exists': ((item) => {return true}), 'label': 'Mg&nbsp;Cor. ',
                                                'tableEntry': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct : 'Unavailable')}),
                                                'tableEntryMarker': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct : 'Unavailable')}),
                                                'tooltipEntry':  ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct : 'Unavailable')}),
                                                'sortkey': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct : infinity)}),
                                                'sortOrder': 'Ascending',
                                                'sortkey2': leechScore,
                                                'sortOrder2': 'Descending',
                                                'preciseSortkey': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct : infinity)}),
                                                'endPoint' : 'review_statistics',
                                                'wordCloud': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct : 'Unavailable')}),
                                                'title': 'Meaning Cor.',
                                                'labelExport': 'Meaning Cor: ',
                                                'needQuotes': false,
                                                'export': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_correct : 'Unavailable')}),
                                                'itemList': ((item)=>'None'),
                                                'idList': ((item)=>[]),
                                                'isDate': false, 'isList': false,
                                               },
                    'Meaning_Current_Streak': {'exists': ((item) => {return true}), 'label': 'Mg&nbsp;Cur.&nbsp;Str. ',
                                               'tableEntry': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_current_streak - 1 : 'Unavailable')}),
                                               'tableEntryMarker': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_current_streak - 1 : 'Unavailable')}),
                                               'tooltipEntry':  ((item) => {return (item.review_statistics ? item.review_statistics.meaning_current_streak -1 : 'Unavailable')}),
                                               'sortkey': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_current_streak : infinity)}),
                                               'sortOrder': 'Ascending',
                                               'sortkey2': leechScore,
                                               'sortOrder2': 'Descending',
                                               'preciseSortkey': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_current_streak : infinity)}),
                                               'endPoint' : 'review_statistics',
                                               'wordCloud': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_current_streak - 1 : 'Unavailable')}),
                                               'title': 'Meaning Cur. Str.',
                                               'labelExport': 'Meaning Cur. Str: ',
                                               'needQuotes': false,
                                               'export': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_current_streak - 1 : 'Unavailable')}),
                                               'itemList': ((item)=>'None'),
                                               'idList': ((item)=>[]),
                                               'isDate': false, 'isList': false,
                                              },
                    'Meaning_Max_Streak': {'exists': ((item) => {return true}), 'label': 'Mg&nbsp;Max.&nbsp;Str. ',
                                           'tableEntry': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_max_streak - 1 : 'Unavailable')}),
                                           'tableEntryMarker': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_max_streak - 1 : 'Unavailable')}),
                                           'tooltipEntry':  ((item) => {return (item.review_statistics ? item.review_statistics.meaning_max_streak -1 : 'Unavailable')}),
                                           'sortkey': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_max_streak : infinity)}),
                                           'sortOrder': 'Ascending',
                                           'sortkey2': leechScore,
                                           'sortOrder2': 'Descending',
                                           'preciseSortkey': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_max_streak : infinity)}),
                                           'endPoint' : 'review_statistics',
                                           'wordCloud': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_max_streak - 1 : 'Unavailable')}),
                                           'title': 'Meaning Max. Str.',
                                           'labelExport': 'Meaning Max. Str: ',
                                           'needQuotes': false,
                                           'export': ((item) => {return (item.review_statistics ? item.review_statistics.meaning_max_streak - 1 : 'Unavailable')}),
                                           'itemList': ((item)=>'None'),
                                           'idList': ((item)=>[]),
                                           'isDate': false, 'isList': false,
                                          },
                    'Reading_Incorrect_Answers': {'exists': ((item) => {return item.object !== 'radical'}), 'label': 'Rg&nbsp;Incor. ',
                                                  'tableEntry': ((item) => {return (item.review_statistics ? item.review_statistics.reading_incorrect : 'Unavailable')}),
                                                  'tableEntryMarker': ((item) => {return (item.review_statistics ? item.review_statistics.reading_incorrect : 'Unavailable')}),
                                                  'tooltipEntry':  ((item) => {return (item.review_statistics ? item.review_statistics.reading_incorrect : 'Unavailable')}),
                                                  'sortkey': ((item) => {return (item.review_statistics ? item.review_statistics.reading_incorrect : infinity)}),
                                                  'sortOrder': 'Descending',
                                                  'sortkey2': leechScore,
                                                  'sortOrder2': 'Descending',
                                                  'preciseSortkey': ((item) => {return (item.review_statistics ? item.review_statistics.reading_incorrect : infinity)}),
                                                  'endPoint' : 'review_statistics',
                                                  'wordCloud': ((item) => {return (item.review_statistics ? item.review_statistics.reading_incorrect : 'Unavailable')}),
                                                  'title': 'Reading Incor.',
                                                  'labelExport': 'Reading Incor: ',
                                                  'needQuotes': false,
                                                  'export': ((item) => {return (item.review_statistics ? item.review_statistics.reading_incorrect : 'Unavailable')}),
                                                  'itemList': ((item)=>'None'),
                                                  'idList': ((item)=>[]),
                                                  'isDate': false, 'isList': false,
                                                 },
                    'Reading_Correct_Answers': {'exists': ((item) => {return item.object !== 'radical'}), 'label': 'Rg&nbsp;Cor. ',
                                                'tableEntry': ((item) => {return (item.review_statistics ? item.review_statistics.reading_correct : 'Unavailable')}),
                                                'tableEntryMarker': ((item) => {return (item.review_statistics ? item.review_statistics.reading_correct : 'Unavailable')}),
                                                'tooltipEntry':  ((item) => {return (item.review_statistics ? item.review_statistics.reading_correct : 'Unavailable')}),
                                                'sortkey': ((item) => {return (item.review_statistics ? item.review_statistics.reading_correct : infinity)}),
                                                'sortOrder': 'Ascending',
                                                'sortkey2': leechScore,
                                                'sortOrder2': 'Descending',
                                                'preciseSortkey': ((item) => {return (item.review_statistics ? item.review_statistics.reading_correct : infinity)}),
                                                'endPoint' : 'review_statistics',
                                                'wordCloud': ((item) => {return (item.review_statistics ? item.review_statistics.reading_correct : 'Unavailable')}),
                                                'title': 'Reading Cor.',
                                                'labelExport': 'Reading Cor: ',
                                                'needQuotes': false,
                                                'export': ((item) => {return (item.review_statistics ? item.review_statistics.reading_correct : 'Unavailable')}),
                                                'itemList': ((item)=>'None'),
                                                'idList': ((item)=>[]),
                                                'isDate': false, 'isList': false,
                                               },
                    'Reading_Current_Streak': {'exists': ((item) => {return item.object !== 'radical'}), 'label': 'Rg&nbsp;Cur.&nbsp;Str. ',
                                               'tableEntry': ((item) => {return (item.review_statistics ? item.review_statistics.reading_current_streak - 1 : 'Unavailable')}),
                                               'tableEntryMarker': ((item) => {return (item.review_statistics ? item.review_statistics.reading_current_streak - 1 : 'Unavailable')}),
                                               'tooltipEntry':  ((item) => {return (item.review_statistics ? item.review_statistics.reading_current_streak - 1 : 'Unavailable')}),
                                               'sortkey': ((item) => {return (item.review_statistics ? item.review_statistics.reading_current_streak : infinity)}),
                                               'sortOrder': 'Ascending',
                                               'sortkey2': leechScore,
                                               'sortOrder2': 'Descending',
                                               'preciseSortkey': ((item) => {return (item.review_statistics ? item.review_statistics.reading_current_streak : infinity)}),
                                               'endPoint' : 'review_statistics',
                                               'wordCloud': ((item) => {return (item.review_statistics ? item.review_statistics.reading_current_streak - 1 : 'Unavailable')}),
                                               'title': 'Reading Cur. Str.',
                                               'labelExport': 'Reading Cur. Str: ',
                                               'needQuotes': false,
                                               'export': ((item) => {return (item.review_statistics ? item.review_statistics.reading_current_streak - 1 : 'Unavailable')}),
                                               'itemList': ((item)=>'None'),
                                               'idList': ((item)=>[]),
                                               'isDate': false, 'isList': false,
                                              },
                    'Reading_Max_Streak': {'exists': ((item) => {return item.object !== 'radical'}), 'label': 'Rg&nbsp;Max.&nbsp;Str. ',
                                           'tableEntry': ((item) => {return (item.review_statistics ? item.review_statistics.reading_max_streak - 1 : 'Unavailable')}),
                                           'tableEntryMarker': ((item) => {return (item.review_statistics ? item.review_statistics.reading_max_streak - 1 : 'Unavailable')}),
                                           'tooltipEntry':  ((item) => {return (item.review_statistics ? item.review_statistics.reading_max_streak - 1 : 'Unavailable')}),
                                           'sortkey': ((item) => {return (item.review_statistics ? item.review_statistics.reading_max_streak : infinity)}),
                                           'sortOrder': 'Ascending',
                                           'sortkey2': leechScore,
                                           'sortOrder2': 'Descending',
                                           'preciseSortkey': ((item) => {return (item.review_statistics ? item.review_statistics.reading_max_streak : infinity)}),
                                           'endPoint' : 'review_statistics',
                                           'wordCloud': ((item) => {return (item.review_statistics ? item.review_statistics.reading_max_streak - 1 : 'Unavailable')}),
                                           'title': 'Reading Max. Str.',
                                           'labelExport': 'Reading Max. Str: ',
                                           'needQuotes': false,
                                           'export': ((item) => {return (item.review_statistics ? item.review_statistics.reading_max_streak - 1 : 'Unavailable')}),
                                           'itemList': ((item)=>'None'),
                                           'idList': ((item)=>[]),
                                           'isDate': false, 'isList': false,
                                          },
                    'Level': {'exists': ((item) => {return true}), 'label': 'Level ',
                              'tableEntry': ((item) => {return item.data.level}),
                              'tableEntryMarker': ((item) => {return item.data.level}),
                              'tooltipEntry': ((item) => {return item.data.level}),
                              'sortkey': ((item) => {return item.data.level}),
                              'sortOrder': 'Ascending',
                              'sortkey2': ((item) => {return 0}),
                              'sortOrder2': 'Ascending',
                              'preciseSortkey': ((item) => {return item.data.level}),
                              'endPoint' : 'subjects',
                              'title': 'Level',
                              'labelExport': 'Level: ',
                              'needQuotes': false,
                              'export': ((item) => {return item.data.level}),
                              'itemList': ((item)=>'None'),
                              'idList': ((item)=>[]),
                              'isDate': false, 'isList': false,
                             },
                    'Srs': {'exists': ((item) => {return true}), 'label': 'SRS ',
                            'tableEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.srs_stage != undefined ? srsName[item.assignments.srs_stage] : 'Locked') : 'Locked')}),
                            'tableEntryMarker': ((item) => {return (item.assignments != undefined ? (item.assignments.srs_stage != undefined ? srsName[item.assignments.srs_stage] : 'Locked') : 'Locked')}),
                            'tooltipEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.srs_stage != undefined ? srsName[item.assignments.srs_stage] : 'Locked') : 'Locked')}),
                            'sortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.srs_stage != undefined ? item.assignments.srs_stage : 10) : 10)}),
                            'sortOrder': 'Ascending',
                            'sortkey2': ((item) => {return (item.assignments != undefined ? (item.assignments.available_at != undefined ? Date.parse(item.assignments.available_at) : theFuture) : theFuture)}),
                            'sortOrder2': 'Ascending',
                            'preciseSortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.srs_stage != undefined ? item.assignments.srs_stage : 10) : 10)}),
                            'endPoint' : 'assignments',
                            'title': 'SRS',
                            'labelExport': 'SRS: ',
                            'needQuotes': false,
                            'export': ((item) => {return (item.assignments != undefined ? (item.assignments.srs_stage != undefined ? srsName[item.assignments.srs_stage] : 'Locked') : 'Locked')}),
                            'itemList': ((item)=>'None'),
                            'idList': ((item)=>[]),
                            'isDate': false, 'isList': false,
                           },
                    'Review_Date': {'exists': ((item) => {return true}), 'label': 'Review ',
                                    'tableEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.available_at != undefined ? makeDate(item) : 'Unscheduled') : 'Unscheduled')}),
                                    'tableEntryMarker': ((item) => {return (item.assignments != undefined ? (item.assignments.available_at != undefined ? makeDateMarker(item) : 'Unscheduled') : 'Unscheduled')}),
                                    'tooltipEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.available_at != undefined ? makeDate(item) : 'Unscheduled') : 'Unscheduled')}),
                                    'sortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.available_at != undefined ? trimDate(Date.parse(item.assignments.available_at)) : theFuture) : theFuture)}),
                                    'sortOrder': 'Ascending',
                                    'sortkey2': ((item) => {return (item.assignments != undefined ? (item.assignments.srs_stage != undefined? item.assignments.srs_stage : 10) : 10)}),
                                    'sortOrder2': 'Ascending',
                                    'preciseSortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.available_at != undefined ? Date.parse(item.assignments.available_at) : theFuture) : theFuture)}),
                                    'endPoint' : 'assignments',
                                    'title': 'Review Date',
                                    'labelExport': 'Review Date: ',
                                    'needQuotes': false,
                                    'export': ((item) => {return (item.assignments != undefined ? (item.assignments.available_at != undefined ? forExportDate(item.assignments.available_at) : 'Unscheduled') : 'Unscheduled')}),
                                    'itemList': ((item)=>'None'),
                                    'idList': ((item)=>[]),
                                    'isDate': true, 'isList': false,
                                   },
                    'Review_Wait': {'exists': ((item) => {return true}), 'label': 'Wait ',
                                    'tableEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.available_at != undefined ? reviewWait(item) : 'Unscheduled') : 'Unscheduled')}),
                                    'tableEntryMarker': ((item) => {return (item.assignments != undefined ? (item.assignments.available_at != undefined ? reviewWait(item) : 'Unscheduled') : 'Unscheduled')}),
                                    'tooltipEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.available_at != undefined ? reviewWait(item) : 'Unscheduled') : 'Unscheduled')}),
                                    'sortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.available_at != undefined ? trimDate(Date.parse(item.assignments.available_at)) : theFuture) : theFuture)}),
                                    'sortOrder': 'Ascending',
                                    'sortkey2': ((item) => {return (item.assignments != undefined ? (item.assignments.srs_stage != undefined? item.assignments.srs_stage : 10) : 10)}),
                                    'sortOrder2': 'Ascending',
                                    'preciseSortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.available_at != undefined ? Date.parse(item.assignments.available_at) : theFuture) : theFuture)}),
                                    'endPoint' : 'assignments',
                                    'title': 'Wait',
                                    'labelExport': 'Wait: ',
                                    'needQuotes': false,
                                    'export': ((item) => 'None'),
                                    'itemList': ((item)=>'None'),
                                    'idList': ((item)=>[]),
                                    'isDate': true, 'isList': false,
                                   },
                    'Passed_Date': {'exists': ((item) => {return true}), 'label': 'Passed ',
                                    'tableEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.passed_at != undefined ? makePassedDate(item) : 'Not yet') : 'Not yet')}),
                                    'tableEntryMarker': ((item) => {return (item.assignments != undefined ? (item.assignments.passed_at != undefined ? makePassedDateMarker(item) : 'Not yet') : 'Not yet')}),
                                    'tooltipEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.passed_at != undefined ? makePassedDate(item) : 'Not yet') : 'Not yet')}),
                                    'sortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.passed_at != undefined ? trimDate(Date.parse(item.assignments.passed_at)) : 0) : 0)}),
                                    'sortOrder': 'Ascending',
                                    'sortkey2': ((item) => {return (item.assignments != undefined ? (item.assignments.srs_stage != undefined ? item.assignments.srs_stage : 10) : 10)}),
                                    'sortOrder2': 'Ascending',
                                    'preciseSortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.passed_at != undefined ? Date.parse(item.assignments.passed_at) : theFuture) : theFuture)}),
                                    'endPoint' : 'assignments',
                                    'title': 'Passed Guru',
                                    'labelExport': 'Passed Guru: ',
                                    'needQuotes': false,
                                    'export': ((item) => {return (item.assignments != undefined ? (item.assignments.passed_at != undefined ? forExportDate(item.assignments.passed_at) : 'Not yet') : 'Not yet')}),
                                    'itemList': ((item)=>'None'),
                                    'idList': ((item)=>[]),
                                    'isDate': true, 'isList': false,
                                   },
                    'Burned_Date': {'exists': ((item) => {return true}), 'label': 'Burned ',
                                    'tableEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.burned_at != undefined ? makeBurnedDate(item) : 'Not yet') : 'Not yet')}),
                                    'tableEntryMarker': ((item) => {return (item.assignments != undefined ? (item.assignments.burned_at != undefined ? makeBurnedDateMarker(item) : 'Not yet') : 'Not yet')}),
                                    'tooltipEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.burned_at != undefined ? makeBurnedDate(item) : 'Not yet') : 'Not yet')}),
                                    'sortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.burned_at != undefined ? trimDate(Date.parse(item.assignments.burned_at)) : 0) : 0)}),
                                    'sortOrder': 'Ascending',
                                    'sortkey2': ((item) => {return item.data.level}),
                                    'sortOrder2': 'Ascending',
                                    'preciseSortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.burned_at != undefined ? Date.parse(item.assignments.burned_at) : theFuture) : theFuture)}),
                                    'endPoint' : 'assignments',
                                    'title': 'Burned',
                                    'labelExport': 'Burned: ',
                                    'needQuotes': false,
                                    'export': ((item) => {return (item.assignments != undefined ? (item.assignments.burned_at != undefined ? forExportDate(item.assignments.burned_at) : 'Not yet') : 'Not yet')}),
                                    'itemList': ((item)=>'None'),
                                    'idList': ((item)=>[]),
                                    'isDate': true, 'isList': false,
                                   },
                    'Resurrected_Date': {'exists': ((item) => {return true}), 'label': 'Resurrected ',
                                         'tableEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.resurrected_at != undefined ? makeResurrectedDate(item) : 'Not yet') : 'Not yet')}),
                                         'tableEntryMarker': ((item) => {return (item.assignments != undefined ? (item.assignments.resurrected_at != undefined ? makeResurrectedDateMarker(item) : 'Not yet') : 'Not yet')}),
                                         'tooltipEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.resurrected_at != undefined ? makeResurrectedDate(item) : 'Not yet') : 'Not yet')}),
                                         'sortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.resurrected_at != undefined ? trimDate(Date.parse(item.assignments.resurrected_at)).toDateString() : 0) : 0)}),
                                         'sortOrder': 'Ascending',
                                         'sortkey2': ((item) => {return item.data.level}),
                                         'sortOrder2': 'Ascending',
                                         'preciseSortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.resurrected_at != undefined ? Date.parse(item.assignments.resurrected_at).toDateString() : theFuture) : theFuture)}),
                                         'endPoint' : 'assignments',
                                         'title': 'Resurrected',
                                         'labelExport': 'Resurrected: ',
                                         'needQuotes': false,
                                         'export': ((item) => {return (item.assignments != undefined ? (item.assignments.resurrected_at != undefined ? forExportDate(item.assignments.resurrected_at) : 'Not yet') : 'Not yet')}),
                                         'itemList': ((item)=>'None'),
                                         'idList': ((item)=>[]),
                                         'isDate': true, 'isList': false,
                                        },
                    'Lesson_Date': {'exists': ((item) => {return true}), 'label': 'Lesson ',
                                    'tableEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.started_at != undefined ? makeLessonDate(item) : 'Not yet') : 'Not yet')}),
                                    'tableEntryMarker': ((item) => {return (item.assignments != undefined ? (item.assignments.started_at != undefined ? makeLessonDateMarker(item) : 'Not yet') : 'Not yet')}),
                                    'tooltipEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.started_at != undefined ? makeLessonDate(item) : 'Not yet') : 'Not yet')}),
                                    'sortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.started_at ? trimDate(Date.parse(item.assignments.started_at)) : theFuture) : theFuture)}),
                                    'sortOrder': 'Ascending',
                                    'sortkey2': ((item) => {return item.data.level}),
                                    'sortOrder2': 'Ascending',
                                    'preciseSortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.started_at ? Date.parse(item.assignments.started_at) : theFuture) : theFuture)}),
                                    'endPoint' : 'assignments',
                                    'title': 'Lesson',
                                    'labelExport': 'Lesson: ',
                                    'needQuotes': false,
                                    'export': ((item) => {return (item.assignments != undefined ? (item.assignments.started_at != undefined ? forExportDate(item.assignments.started_at) : 'Not yet') : 'Not yet')}),
                                    'itemList': ((item)=>'None'),
                                    'idList': ((item)=>[]),
                                    'isDate': true, 'isList': false,
                                   },
                    'Unlock_Date': {'exists': ((item) => {return true}), 'label': 'Unlock ',
                                    'tableEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.unlocked_at != undefined ? makeUnlockDate(item) : 'Not yet') : 'Not yet')}),
                                    'tableEntryMarker': ((item) => {return (item.assignments != undefined ? (item.assignments.unlocked_at != undefined ? makeUnlockDateMarker(item) : 'Not yet') : 'Not yet')}),
                                    'tooltipEntry': ((item) => {return (item.assignments != undefined ? (item.assignments.unlocked_at != undefined ? makeUnlockDate(item) : 'Not yet') : 'Not yet')}),
                                    'sortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.unlocked_at ? trimDate(Date.parse(item.assignments.unlocked_at)) : theFuture) : theFuture)}),
                                    'sortOrder': 'Ascending',
                                    'sortkey2': ((item) => {return item.data.level}),
                                    'sortOrder2': 'Ascending',
                                    'preciseSortkey': ((item) => {return (item.assignments != undefined ? (item.assignments.unlocked_at ? Date.parse(item.assignments.unlocked_at) : theFuture) : theFuture)}),
                                    'endPoint' : 'assignments',
                                    'title': 'Unlock',
                                    'labelExport': 'Unlock: ',
                                    'needQuotes': false,
                                    'export': ((item) => {return (item.assignments != undefined ? (item.assignments.unlocked_at != undefined ? forExportDate(item.assignments.unlocked_at) : 'Not yet') : 'Not yet')}),
                                    'itemList': ((item)=>'None'),
                                    'idList': ((item)=>[]),
                                    'isDate': true, 'isList': false,
                                   },
                    'Item': {'exists': ((item) => {return true}), 'label': 'Item ',
                             'tableEntry': ((item) => {return 'None'}),
                             'tableEntryMarker': ((item) => {return ''}),
                             'tooltipEntry':  ((item) => {return 'None'}),
                             'sortkey':  ((item) => {return 0}),
                             'sortOrder': 'Ascending',
                             'sortkey2':  ((item) => {return 0}),
                             'sortOrder2': 'Ascending',
                             'preciseSortkey':  ((item) => {return 0}),
                             'endPoint' : 'subjects',
                             'title': 'Item',
                             'labelExport': '',
                             'needQuotes': false,
                             'export': ((item) => {return (item.data.characters ? item.data.characters : item.data.slug)}),
                             'itemList': ((item)=>'None'),
                             'idList': ((item)=>[]),
                             'isDate': false, 'isList': false,
                            },
                    'Type': {'exists': ((item) => {return true}), 'label': 'Type ',
                             'tableEntry':  ((item) => {return 'None'}),
                             'tableEntryMarker':  ((item) => {return ''}),
                             'tooltipEntry':  ((item) => {return 'None'}),
                             'sortkey':  ((item) => { return {'radical': 1, 'kanji': 2, 'vocabulary': 3}[item.object]}),
                             'sortOrder': 'Ascending',
                             'sortkey2':  ((item) => { return {'radical': 1, 'kanji': 2, 'vocabulary': 3}[item.object]}),
                             'sortOrder2': 'Ascending',
                             'preciseSortkey':  ((item) => { return {'radical': 1, 'kanji': 2, 'vocabulary': 3}[item.object]}),
                             'endPoint' : 'assignments',
                             'title': 'Type',
                             'labelExport': '',
                             'needQuotes': false,
                             'export': ((item) => {return (item.object != undefined ? item.object : 'Unavailable')}),
                             'itemList': ((item)=>'None'),
                             'idList': ((item)=>[]),
                             'isDate': false, 'isList': false,
                            },
                    'Export_Date': {'exists': ((item) => {return true}), 'label': 'Export&nbsp;Date',
                                    'tableEntry':  ((item) => {return 'None'}),
                                    'tableEntryMarker':  ((item) => {return ''}),
                                    'tooltipEntry':  ((item) => {return 'None'}),
                                    'sortkey':  ((item) => {return 0}),
                                    'sortOrder': 'Ascending',
                                    'sortkey2':  ((item) => {return 0}),
                                    'sortOrder2': 'Ascending',
                                    'preciseSortkey':  ((item) => {return 0}),
                                    'endPoint' : 'subjects',
                                    'title': 'Export Date',
                                    'labelExport': 'Export Date: ',
                                    'needQuotes': false,
                                    'export': ((item) => {return today()}),
                                    'itemList': ((item)=>'None'),
                                    'idList': ((item)=>[]),
                                    'isDate': true, 'isList': false,
                                   },
                    'Item_Page': {'exists': ((item) => {return true}), 'label': 'Item&nbsp;Page',
                                  'tableEntry':  ((item) => {return 'None'}),
                                  'tableEntryMarker':  ((item) => {return ''}),
                                  'tooltipEntry':  ((item) => {return 'None'}),
                                  'sortkey':  ((item) => {return 0}),
                                  'sortOrder': 'Ascending',
                                  'sortkey2':  ((item) => {return 0}),
                                  'sortOrder2': 'Ascending',
                                  'preciseSortkey':  ((item) => {return 0}),
                                  'endPoint' : 'subjects',
                                  'title': 'Item Page URL',
                                  'labelExport': '',
                                  'needQuotes': false,
                                  'export': ((item) => {return item.data.document_url}),
                                  'itemList': ((item)=>'None'),
                                  'idList': ((item)=>[]),
                                  'isDate': false, 'isList': false,
                                 },
                    'Used_In': {'exists': ((item) => {return (item.object === 'radical' || item.object === 'kanji')}), 'label': 'Used&nbsp;In',
                                'tableEntry':  ((item) => {return 'None'}),
                                'tableEntryMarker':  ((item) => {return ''}),
                                'tooltipEntry':  ((item) => {return (item.object === 'radical' ? makeListBySubjectKan(item.data.amalgamation_subject_ids) : makeListBySubjectVoc(item.data.amalgamation_subject_ids))}),
                                'sortkey':  ((item) => {return 0}),
                                'sortOrder': 'Ascending',
                                'sortkey2':  ((item) => {return 0}),
                                'sortOrder2': 'Ascending',
                                'preciseSortkey':  ((item) => {return 0}),
                                'endPoint' : 'subjects',
                                'title': 'Used In',
                                'labelExport': 'Used In: ',
                                'needQuotes': true,
                                'export': ((item) => {return (item.object === 'radical' ? makeListBySubjectKan(item.data.amalgamation_subject_ids) : makeListBySubjectVoc(item.data.amalgamation_subject_ids))}),
                                'itemList': ((item)=>{return (item.object === 'radical' ? makeItemListKan(item.data.amalgamation_subject_ids) : makeItemListVoc(item.data.amalgamation_subject_ids))}),
                                'idList': ((item)=>(item.object === 'radical' || item.object === 'kanji' ? item.data.amalgamation_subject_ids : [])),
                                'isDate': false, 'isList': true,
                               },
                    'Components': {'exists': ((item) => {return (item.object === 'kanji' || item.object === 'vocabulary')}), 'label': 'Compnts',
                                   'tableEntry':  ((item) => {return 'None'}),
                                   'tableEntryMarker':  ((item) => {return ''}),
                                   'tooltipEntry':  ((item) => {return (item.object === 'kanji' ? makeListBySubjectRad(item.data.component_subject_ids) : makeListBySubjectKan(item.data.component_subject_ids))}),
                                   'sortkey':  ((item) => {return 0}),
                                   'sortOrder': 'Ascending',
                                   'sortkey2':  ((item) => {return 0}),
                                   'sortOrder2': 'Ascending',
                                   'preciseSortkey':  ((item) => {return 0}),
                                   'endPoint' : 'subjects',
                                   'title': 'Components',
                                   'labelExport': 'Components: ',
                                   'needQuotes': true,
                                   'export': ((item) => {return (item.object === 'kanji' ? makeListBySubjectRad(item.data.component_subject_ids) : makeListBySubjectKan(item.data.component_subject_ids))}),
                                   'itemList': ((item)=>{return (item.object === 'kanji' ? makeItemListRad(item.data.component_subject_ids) : makeItemListKan(item.data.component_subject_ids))}),
                                   'idList': ((item)=>(item.object === 'kanji' || item.object === 'vocabulary' ? item.data.component_subject_ids : [])),
                                   'isDate': false, 'isList': true,
                                  },
                    'Vis_Sim_Kanji': {'exists': ((item) => {return item.object === 'kanji'}), 'label': 'Vis.&nbsp;Sim.',
                                      'tableEntry':  ((item) => {return 'None'}),
                                      'tableEntryMarker':  ((item) => {return ''}),
                                      'tooltipEntry':  ((item) => {return makeListBySubjectKan(item.data.visually_similar_subject_ids)}),
                                      'sortkey':  ((item) => {return 0}),
                                      'sortOrder': 'Ascending',
                                      'sortkey2':  ((item) => {return 0}),
                                      'sortOrder2': 'Ascending',
                                      'preciseSortkey':  ((item) => {return 0}),
                                      'endPoint' : 'subjects',
                                      'title': 'Vis. Sim. Kanjis',
                                      'labelExport': 'Vis. Sim. Kanjis: ',
                                      'needQuotes': true,
                                      'export': ((item) => {return makeListBySubjectKan(item.data.visually_similar_subject_ids)}),
                                      'itemList': ((item)=>{return makeItemListKan(item.data.visually_similar_subject_ids)}),
                                      'idList': ((item)=>(item.object === 'kanji' ? item.data.visually_similar_subject_ids : [])),
                                      'isDate': false, 'isList': true,
                                     },
                    'Part_Of_Speech': {'exists': ((item) => {return item.object === 'vocabulary'}), 'label': 'Part&nbsp;of&nbsp;Sp.',
                                       'tableEntry':  ((item) => {return item.data.parts_of_speech.join(', ')}),
                                       'tableEntryMarker':  ((item) => {return ''}),
                                       'tooltipEntry':  ((item) => {return item.data.parts_of_speech.join(', ')}),
                                       'sortkey':  ((item) => {return 0}),
                                       'sortOrder': 'Ascending',
                                       'sortkey2':  ((item) => {return 0}),
                                       'sortOrder2': 'Ascending',
                                       'preciseSortkey':  ((item) => {return 0}),
                                       'endPoint' : 'subjects',
                                       'title': 'Part of Speech',
                                       'labelExport': 'Part of Speech: ',
                                       'needQuotes': true,
                                       'export': ((item) => {return item.data.parts_of_speech.join(', ')}),
                                       'itemList': ((item)=>'None'),
                                       'idList': ((item)=>[]),
                                       'isDate': false, 'isList': true,
                                      },
                    'Reading_by_Type': {'exists': ((item) => {return item.object === 'kanji'}), 'label': 'Rd.&nbsp;Type',
                                        'tableEntry':  ((item) => {return readingsFull(item, true)}),
                                        'tableEntryMarker':  ((item) => {return ''}),
                                        'tooltipEntry':  ((item) => {return readingsFull(item, true)}),
                                        'sortkey':  ((item) => {return 0}),
                                        'sortOrder': 'Ascending',
                                        'sortkey2':  ((item) => {return 0}),
                                        'sortOrder2': 'Ascending',
                                        'preciseSortkey':  ((item) => {return 0}),
                                        'endPoint' : 'subjects',
                                        'title': 'Readings by Type',
                                        'labelExport': '',
                                        'needQuotes': true,
                                        'export': ((item) => {return readingsFull(item, true)}),
                                        'itemList': ((item)=>'None'),
                                        'idList': ((item)=>[]),
                                        'isDate': false, 'isList': true,
                                       },
                    'Block_List': {'exists': ((item) => {return true}), 'label': 'Block&nbsp;List',
                                   'tableEntry':  ((item) => {return makeAuxMeaningList(item.data.auxiliary_meanings, 'blacklist')}),
                                   'tableEntryMarker':  ((item) => {return ''}),
                                   'tooltipEntry':  ((item) => {return makeAuxMeaningList(item.data.auxiliary_meanings, 'blacklist')}),
                                   'sortkey':  ((item) => {return 0}),
                                   'sortOrder': 'Ascending',
                                   'sortkey2':  ((item) => {return 0}),
                                   'sortOrder2': 'Ascending',
                                   'preciseSortkey':  ((item) => {return 0}),
                                   'endPoint' : 'subjects',
                                   'title': 'Block List',
                                   'labelExport': 'Block List: ',
                                   'needQuotes': true,
                                   'export': ((item) => {return makeAuxMeaningList(item.data.auxiliary_meanings, 'blacklist')}),
                                   'itemList': ((item)=>'None'),
                                   'idList': ((item)=>[]),
                                   'isDate': false, 'isList': true,
                                  },
                    'Allow_List': {'exists': ((item) => {return true}), 'label': 'Allow&nbsp;List',
                                   'tableEntry':  ((item) => {return makeAuxMeaningList(item.data.auxiliary_meanings, 'whitelist')}),
                                   'tableEntryMarker':  ((item) => {return ''}),
                                   'tooltipEntry':  ((item) => {return makeAuxMeaningList(item.data.auxiliary_meanings, 'whitelist')}),
                                   'sortkey':  ((item) => {return 0}),
                                   'sortOrder': 'Ascending',
                                   'sortkey2':  ((item) => {return 0}),
                                   'sortOrder2': 'Ascending',
                                   'preciseSortkey':  ((item) => {return 0}),
                                   'endPoint' : 'subjects',
                                   'title': 'Allow List',
                                   'labelExport': 'Allow List: ',
                                   'needQuotes': true,
                                   'export': ((item) => {return makeAuxMeaningList(item.data.auxiliary_meanings, 'whitelist')}),
                                   'itemList': ((item)=>'None'),
                                   'idList': ((item)=>[]),
                                   'isDate': false, 'isList': true,
                                  },
                   }

    function isValidDate(dateString) {
      var regEx = /^\d{4}-\d{2}-\d{2}$/;
      if(!dateString.match(regEx)) return false; // Invalid format
      var d = new Date(dateString);
      var dNum = d.getTime();
      if(!dNum && dNum !== 0) return false; // NaN value, Invalid date
      return d.toISOString().slice(0,10) === dateString;
    }

    function nameItem(item){
        return (item.data.characters === null ? item.data.slug : item.data.characters);
    };

    function makeListBySubjectRad(subjectArray){
        if (subjectArray.length === 0)return '-Empty-';
        let list = 0;
        let firstElement = true;
        for (var i = 0; i < subjectArray.length; i++){
            let item = subjectIndexRad[subjectArray[i]];
            if (firstElement){
                list = nameItem(item);
                firstElement = false;
            } else {
                list += ', '+nameItem(item);
            }
        };
        return list;
    }

    function makeListBySubjectKan(subjectArray){
        if (subjectArray.length === 0)return '-Empty-';
        let list;
        let firstElement = true;
        for (var i = 0; i < subjectArray.length; i++){
            let item = subjectIndexKan[subjectArray[i]];
            if (firstElement){
                list = nameItem(item);
                firstElement = false;
            } else {
                list += ', '+nameItem(item);
            }
        };
        return list;
    }

    function makeListBySubjectVoc(subjectArray){
        if (subjectArray.length === 0)return '-Empty-';
        let list;
        let firstElement = true;
        for (var i = 0; i < subjectArray.length; i++){
            let item = subjectIndexVoc[subjectArray[i]];
            if (firstElement){
                list = nameItem(item);
                firstElement = false;
            } else {
                list += ', '+nameItem(item);
            }
        };
        return list;
    }

    function makeItemListRad(subjectArray){
        if (subjectArray === undefined){return []};
        let l = [];
        subjectArray.forEach(a=>{l.push(subjectIndexRad[a]);});
        return l;
    }

    function makeItemListKan(subjectArray){
        if (subjectArray === undefined){return []};
        let l = [];
        subjectArray.forEach(a=>{l.push(subjectIndexKan[a]);});
        return l;
    }

    function makeItemListVoc(subjectArray){
        if (subjectArray === undefined){return []};
        let l = [];
        subjectArray.forEach(a=>{l.push(subjectIndexVoc[a]);});
        return l;
    }

    function MeaningCorrect(item){
        let stats = item.review_statistics;
        let denominator = stats.meaning_correct + stats.meaning_incorrect;
        if (denominator == 0){
            return 100
        } else {
            return Math.floor(100 * stats.meaning_correct / denominator)
        }
    }

    function ReadingCorrect(item){
        let stats = item.review_statistics;
        let denominator = stats.reading_correct + stats.reading_incorrect;
        if (denominator == 0){
            return 100
        } else {
            return Math.floor(100 * stats.reading_correct / denominator)
        }
    }

    function leechScore(item){
        if (item.review_statistics != undefined){
            let reviewStats = item.review_statistics;
            let meaningScore = getLeechScore(reviewStats.meaning_incorrect, reviewStats.meaning_current_streak);
            let readingScore = getLeechScore(reviewStats.reading_incorrect, reviewStats.reading_current_streak);

            return Math.max(meaningScore, readingScore);
        } else {return 0}
    }

    function getLeechScore(incorrect, currentStreak) {
        //get incorrect number than lessen it using the user's correctStreak
        let leechScore = incorrect / Math.pow((currentStreak || 0.5), 1.5); // '||' => if currentstreak zero make 0.5 instead (prevents dividing by zero)
        leechScore = Math.round(leechScore * 100) / 100; //round to two decimals
        return leechScore;
    }

    function reviewWait(item){
        return (Date.parse(item.assignments.available_at) < Date.now() ? 'Now' : s_to_dhm((Date.parse(item.assignments.available_at)-Date.now())/1000))
    }

    // Converts seconds to days, hours, and minutes
    function s_to_dhm(s) {
        var d = Math.floor(s/60/60/24);
        var h = Math.floor(s%(60*60*24)/60/60);
        var m = Math.ceil(s%(60*60*24)%(60*60)/60);
        return (d>0?d+'d ':'')+(h>0?h+'h ':'')+(m>0?m+'m':'1m');
    }

    function makeDate(item){
        return formatDate(new Date(item.assignments.available_at), true, /* is_next_date */);
    }

    function makeDateMarker(item){
        return formatDateMarker(new Date(item.assignments.available_at), true, /* is_next_date */);
    }

    function makePassedDate(item){
        return formatDate(new Date(item.assignments.passed_at), false, /* is_next_date */);
    }

    function makePassedDateMarker(item){
        return formatDateMarker(new Date(item.assignments.passed_at), false, /* is_next_date */);
    }

    function makeBurnedDate(item){
        return formatDate(new Date(item.assignments.burned_at), false, /* is_next_date */);
    }

    function makeBurnedDateMarker(item){
        return formatDateMarker(new Date(item.assignments.burned_at), false, /* is_next_date */);
    }

    function makeResurrectedDate(item){
        return formatDate(new Date(item.assignments.resurrected_at), false, /* is_next_date */);
    }

    function makeResurrectedDateMarker(item){
        return formatDateMarker(new Date(item.assignments.resurrected_at), false, /* is_next_date */);
    }

    function makeLessonDate(item){
        return formatDate(new Date(item.assignments.started_at), false, /* is_next_date */);
    }

    function makeLessonDateMarker(item){
        return formatDateMarker(new Date(item.assignments.started_at), false, /* is_next_date */);
    }

    function makeUnlockDate(item){
        return formatDate(new Date(item.assignments.unlocked_at), false, /* is_next_date */);
    }

    function makeUnlockDateMarker(item){
        return formatDateMarker(new Date(item.assignments.unlocked_at), false, /* is_next_date */);
    }

    function forExportDate(date) {
        return new Date(date).toISOString().slice(0, 16).replace('T', ' ');
    }

    function formatDateMarker(date) {
        var YY = ''+date.getFullYear(),
            MM = ''+(date.getMonth()+1),
            DD = ''+date.getDate(),
            hh = ''+date.getHours(),
            mm = ''+date.getMinutes();

        if (MM.length < 2) MM = '0' + MM;
        if (DD.length < 2) DD = '0' + DD;
        let s = YY+'-'+MM+'-'+DD;
        if (quiz.settings.tablePresets[quiz.settings.active_ipreset].showHours){
            if (quiz.settings.hoursFormat === '24hours') {
                s += ' '+('0'+hh).slice(-2)+':'+('0'+mm).slice(-2);
            } else {
                s += ' '+(((hh+11)%12)+1)+':'+('0'+mm).slice(-2)+['am','pm'][Math.floor(date.getHours()/12)];
            }
        };
        return s;
    }

    function today() {
        var d = new Date(),
            month = '' + (d.getMonth() + 1),
            day = '' + d.getDate(),
            year = d.getFullYear(),
            hh = '' + d.getHours(),
            mm = '' + d.getMinutes();

        if (month.length < 2) month = '0' + month;
        if (day.length < 2) day = '0' + day;
        if (hh.length < 2) hh = '0' + hh;
        if (mm.length < 2) mm = '0' + mm;
        return [year, month, day].join('-') + ' ' + hh + ':' + mm;
    }

    //========================================================================
    // Print date in pretty format.
    //-------------------------------------------------------------------
    function formatDate(d, is_next_date, show_year){
        var s = '';
        var now = new Date();
        var YY = d.getFullYear(),
            MM = d.getMonth(),
            DD = d.getDate(),
            hh = d.getHours(),
            mm = d.getMinutes(),
            one_day = 24*60*60*1000;

        if (is_next_date && d < now) return "Available Now";
        var same_day = ((YY == now.getFullYear()) && (MM == now.getMonth()) && (DD == now.getDate()) ? 1 : 0);

        //    If today:  "Today 8:15pm"
        //    otherwise: "Wed, Apr 15, 8:15pm"
        if (same_day) {
            s += 'Today ';
        } else if (show_year){
            s += d.toISOString().slice(10);
        } else {
            s += ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][d.getDay()]+', '+
                ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'][MM]+' '+DD+', ';
        }
        if (quiz.settings.hoursFormat === '24hours') {
            s += ('0'+hh).slice(-2)+':'+('0'+mm).slice(-2);
        } else {
            s += (((hh+11)%12)+1)+':'+('0'+mm).slice(-2)+['am','pm'][Math.floor(d.getHours()/12)];
        }

        return s;
    }

    //========================================================================
    // Reduce date in milliseconds to minutes boundary
    // This makes secondary sorting match the primary sort data seen by the user
    //------------------------------------------------------------------------
    function trimDate(d){
        return Math.floor((d/1000)/60)*1000*60;
    }

    function meaningsFullTable(item){
        var meanings = meaningsFull(item);
        if (meanings.length > 20){meanings = meanings.slice(0, 20) + '...'}
        return meanings;
    }

    function meaningsFull(item){
        // make sure meanings are returned in the order WK provides them, but primary comes first
        var meanings = "";
        var meaningsPrimary = "";
        for (var k = 0; k < item.data.meanings.length; k++){
            if(item.data.meanings[k].primary){
                if (meaningsPrimary.length != 0){
                    meaningsPrimary += ', ' + item.data.meanings[k].meaning;
                } else {
                    meaningsPrimary = item.data.meanings[k].meaning;
                }
            } else {
                if (meanings.length != 0){
                    meanings += ', ' + item.data.meanings[k].meaning;
                } else {
                    meanings = item.data.meanings[k].meaning;
                }
            }
        }
        if (meanings.length != 0){meaningsPrimary = meaningsPrimary + ', ' + meanings}
        return meaningsPrimary;
    }


    function meaningsBrief(item){
        var meanings = item.data.meanings[0].meaning;
        for (var k = 0; k < item.data.meanings.length; k++){if (item.data.meanings[k].primary){return item.data.meanings[k].meaning}};
        return meanings;
    }

    function makeAuxMeaningList(list, type){
        if (list.length === 0)return '-Empty-';
        let firstElement = true;
        let l = 'Empty';
        for (var i = 0; i < list.length; i++){
            if (list[i].type === type){
                if (firstElement){
                    l = list[i].meaning;
                    firstElement = false;
                } else {
                    l += ', '+ list[i].meaning;
                };
            };
        };
        return l;
    };

    function readingsFull(item, needType){
        // make sure readings are returned in the order WK provides them, but primary comes first
        var readings = "";
        var readingsPrimary = "";
        const shortLabel = {'onyomi' : 'on', 'kunyomi' : 'kun', 'nanori': 'nan'};
        for (var k = 0; k < item.data.readings.length; k++){
            if(item.data.readings[k].primary){
                if (readingsPrimary.length != 0){
                    readingsPrimary += ', ' + item.data.readings[k].reading;
                    if(needType) readingsPrimary += ':'+ shortLabel[item.data.readings[k].type];
                } else {
                    readingsPrimary = item.data.readings[k].reading;
                    if(needType) readingsPrimary += ':'+ shortLabel[item.data.readings[k].type];
                }
            } else {
                if (readings.length != 0){
                    readings += ', ' + item.data.readings[k].reading;
                    if(needType) readings += ':'+ shortLabel[item.data.readings[k].type];
                } else {
                    readings = item.data.readings[k].reading;
                    if(needType) readings += ':'+ shortLabel[item.data.readings[k].type];
                }
            }
        }
        if (readings.length != 0){readingsPrimary = readingsPrimary + ', ' + readings}
        return readingsPrimary;
    }

    function readingsBrief(item){
        var readings = item.data.readings[0].reading;
        for (var k = 0; k < item.data.readings.length; k++){if (item.data.readings[k].primary){return item.data.readings[k].reading}};
        return readings;
    }

    function shuffle(items){
        for(let i = items.length - 1; i > 0; i--){
            const j = Math.floor(Math.random() * i);
            const temp = items[i];
            items[i] = items[j];
            items[j] = temp;
        }
        return items
    }

    function orderByDate(){
        let settings = quiz.settings.tablePresets[quiz.settings.active_ipreset];
        let sortKey = metadata[settings.navigationDate].preciseSortkey;
        let items = quiz.items;
        items.forEach((item) => {item.sortKey = sortKey(item);});
        items = items.sort(function(a, b){return a.sortKey - b.sortKey });
        let referenceDate = settings.startDate;
        var i = 0;
        var startDate = settings.startDate;

        let start=0, end=items.length-1;
        let mid;
        // binary search - searching for startDate
        while (start<=end){
            mid=Math.floor((start + end)/2);
            if (mid === 0) break;
            if (items[mid].sortKey===startDate && items[mid-1].sortKey!==startDate){
                break;
            } else if (items[mid].sortKey < startDate) {
                 start = mid + 1;
            } else {
                 end = mid - 1;
            }
        }
        currentItem = mid;

        start=0; end=items.length-1;
        // binary search - searching for theFuture === missing date.
        while (start<=end){
            mid=Math.floor((start + end)/2);
            if (mid === 0){break}
            if (items[mid].sortKey===theFuture && items[mid-1].sortKey!==theFuture){
                break;
            } else if (items[mid].sortKey < theFuture) {
                 start = mid + 1;
            } else {
                 end = mid - 1;
            }
        }
        if (items[mid].sortKey === theFuture) quiz.items = items.slice(0, mid);
        if (currentItem >= quiz.items.length) currentItem = Math.max(quiz.items.length - nbItems, 0);
    };

    function updatePage(noCreateTable) {
        let leechStreakLimit = quiz.settings.tablePresets[quiz.settings.active_ipreset].leechStreakLimit;
        if (leechStreakLimit != 0) {
            quiz.items = quiz.items.filter((item => {return ((item.review_statistics != undefined) ?
                                                             ((item.review_statistics.meaning_current_streak < (leechStreakLimit+1)) || (item.review_statistics.reading_current_streak < (leechStreakLimit+1))) : false)}));
        };

        let settings = quiz.settings.tablePresets[quiz.settings.active_ipreset];
        let tableKey = settings.table_data;
        let sort1 = settings.sort1;
        let sort2 = settings.sort2;
        let sortKey, sortKey2;
        let sortOrder = settings.sortOrder1;
        let sortOrder2 = settings.sortOrder2;
        if ((sort1 == "Default") && (sort2 == 'Default')){
            sortKey = metadata[tableKey].sortkey;
            if (sortOrder === 'Default'){sortOrder = metadata[tableKey].sortOrder};
            sortKey2 = metadata[tableKey].sortkey2;
            if (sortOrder2 === 'Default'){sortOrder2 = metadata[tableKey].sortOrder2};
        } else if ((sort1 == "Default") && (sort2 != "Default")){
            sortKey = metadata[tableKey].sortkey;
            if (sortOrder === 'Default'){sortOrder = metadata[tableKey].sortOrder};
            sortKey2 = metadata[sort2].sortkey;
            if (sortOrder2 === 'Default'){sortOrder2 = metadata[sort2].sortOrder};
        } else if ((sort1 != "Default") && (sort2 == "Default")){
            sortKey = metadata[sort1].sortkey;
            if (sortOrder === 'Default'){sortOrder = metadata[sort1].sortOrder};
            sortKey2 = metadata[sort1].sortkey2;
            if (sortOrder2 === 'Default'){sortOrder2 = metadata[sort1].sortOrder2};
        } else {
            sortKey = metadata[sort1].sortkey;
            if (sortOrder === 'Default'){sortOrder = metadata[sort1].sortOrder};
            sortKey2 = metadata[sort2].sortkey;
            if (sortOrder === 'Default'){sortOrder2 = metadata[sort2].sortOrder};
        }
        quiz.items.forEach(((item) => {item.sortKey = sortKey(item); item.sortKey2 = sortKey2(item)}));

        if ((sortOrder == 'Descending') && (sortOrder2 == 'Descending')){
            quiz.items = quiz.items.sort(function(a, b){return b.sortKey == a.sortKey ? b.sortKey2 - a.sortKey2 : b.sortKey - a.sortKey });
        } else if ((sortOrder == 'Descending') && (sortOrder2 == 'Ascending')){
            quiz.items = quiz.items.sort(function(a, b){return b.sortKey == a.sortKey ? a.sortKey2 - b.sortKey2 : b.sortKey - a.sortKey });
        } else if ((sortOrder == 'Ascending') && (sortOrder2 == 'Descending')){
            quiz.items = quiz.items.sort(function(a, b){return a.sortKey == b.sortKey ? b.sortKey2 - a.sortKey2 : a.sortKey - b.sortKey });
        } else {
            quiz.items = quiz.items.sort(function(a, b){return(a.sortKey == b.sortKey ? a.sortKey2 - b.sortKey2 : a.sortKey - b.sortKey)});
        };

        if (settings.selection === 'Random') {
            let storageName = 'Wkit_' + quiz.settings.ipresets[quiz.settings.active_ipreset].name;
            let items = sessionStorage.getItem(storageName);
            if (items === null){
                settings.selection = "None";
            } else {
                delete quiz.savedItems;
                quiz.savedItems = quiz.items.slice(0, quiz.items.length);
                retrieveSelecteditems();
                currentItem = settings.currentItem;
                nextCurrentItem = settings.nextCurrentItem;
                if (!$('#WkitRandomSelection').hasClass("WkitActive")) $('#WkitRandomSelection').toggleClass("WkitActive");
                if ($('#WkitDateOrdering').hasClass("WkitActive")) $('#WkitDateOrdering').toggleClass("WkitActive");
            }
            return quiz.settings_dialog.save().then(function(){if (!noCreateTable){displayItems()};});
        } else if (settings.selection === 'Date') {
            delete quiz.savedItems;
            quiz.savedItems = quiz.items.slice(0, quiz.items.length);
            orderByDate(quiz.items);
            settings.currentItem = currentItem; // should be determined by order by date
            settings.nextCurrentItem = nextCurrentItem = currentItem;
            if ($('#WkitRandomSelection').hasClass("WkitActive")) $('#WkitRandomSelection').toggleClass("WkitActive");
            if (!$('#WkitDateOrdering').hasClass("WkitActive")) $('#WkitDateOrdering').toggleClass("WkitActive");
            return quiz.settings_dialog.save().then(function(){if (!noCreateTable){displayItems()};});
        } else {
            if ($('#WkitRandomSelection').hasClass("WkitActive")) $('#WkitRandomSelection').toggleClass("WkitActive");
            if ($('#WkitDateOrdering').hasClass("WkitActive")) $('#WkitDateOrdering').toggleClass("WkitActive");
            currentItem = settings.currentItem;
            nextCurrentItem = settings.nextCurrentItem;
            if (settings.currentItem >= quiz.items.length){
                settings.currentItem = currentItem = 0;
                settings.nextCurrentItem = nextCurrentItem = 0;
            };
            if (!noCreateTable){displayItems()};
            return Promise.resolve();
        };
    };

    function displayItems(){
        if (quiz.settings.listMode){
            createItemList(quiz.items, false);
        } else {
            createTopLeechTables(quiz.items);
        };
    };

    function itemsCharacterCallback (item, override){
        let maxItemLength = 28;
        if (quiz.settings.tablePresets[quiz.settings.active_ipreset].displayMeaning && !override){
            let text = meaningsBrief(item);
            if (wideElements[quiz.settings.tablePresets[quiz.settings.active_ipreset].table_data]){
                return [text.slice(0,maxItemLength), false , ''];
            } else {
                return [text, false, ''];
            }
        };
        //check if an item has characters. Kanji and vocabulary will always have these but wk-specific radicals (e.g. gun, leaf, stick) use images instead
        if(item.data.characters!= null) {
            return [item.data.characters, true, 'lang="JP"'];
        } else if (item.data.character_images!= null){
            let imgUrl = item.data.character_images.find(a=>a.content_type=="image/svg+xml"&&a.metadata.inline_styles).url;
            return ['<img height=14px width=14px src='+imgUrl+'"></img>', true, 'lang="JP"'];
        } else {
            //if both characters and character_images are somehow absent try using slug instead
            return [item.data.slug, true, 'lang="JP"'];
        }
    }

    function makeTableEntry(item, selectedTable){
        let presets = quiz.settings.tablePresets[selectedTable];
        let tableData;
        if (presets.selection === "Date"){
            tableData = metadata[presets.navigationDate];
        } else {
            tableData = metadata[presets.table_data];
        };
        return (tableData.exists(item) ? tableData.tableEntry(item) : '')
    }

    function makeIconForTooltip(item){
        let itemData;
        if(item.data.characters!= null) {
            itemData = item.data.characters;
        } else if (item.data.character_images!= null){
            let imgUrl = item.data.character_images.find(a=>a.content_type=="image/svg+xml"&&a.metadata.inline_styles).url;
            let list = ['<img height=14px width=14px src='];
            list.push(imgUrl);
            list.push('"></img>')
            itemData = list.join('');
        } else {
            //if both characters and character_images are somehow absent try using slug instead
            itemData = item.data.slug;
        }
        let stringList = [];
        stringList.push('<div class="WkitMiniIcon ');
        stringList.push(item.object);
        stringList.push('"><span class="WkitMiniIconLink" style="color: ');
            stringList.push(fontColor);
            stringList.push(' !important;" lang="JP">');
            stringList.push(itemData);
        stringList.push('</span></div>');
        return stringList.join('');
    };

    function makeTooltipIcon(item, tableName){
        let html = '';
        let tableData = metadata[tableName];
        if (tableData.exists(item)) {
            let iconLimit = (quiz.settings.listMode ? 15 : 40);
            let overhead = 0.8;
            let itemList = tableData.itemList(item);
            let itemListShort = [];
            let charCount = 0;
            let index = 0;
            while (charCount < iconLimit && index < itemList.length){
                let item2 = itemList[index];
                itemListShort.push(item2);
                charCount += (item2.data.characters != null ? item2.data.characters.length : 1) + overhead;
                index++;
            };
            let stringList = ['<tr><td class="WkitLabel">'];
            stringList.push(tableData.label);
            stringList.push('</td><td class="WkitTipValue">');
            stringList.push('<div class="WkitMiniContainer">');
            itemListShort.forEach(a=>{stringList.push(makeIconForTooltip(a))});
            if (charCount >= iconLimit) stringList.push('<span class="WkitIconWarning">And more</span>');
            stringList.push('</div></td></tr>');
            html = stringList.join('');
        };
        return html;
    };

    function makeTooltipEntry(item, tableName){
        let html = '';
        let tableData = metadata[tableName];
        if (tableData.exists(item)) {
            let stringList = ['<tr><td class="WkitLabel">'];
            stringList.push(tableData.label);
            stringList.push('</td><td class="WkitTipValue">');
            stringList.push(tableData.tooltipEntry(item));
            stringList.push('</td></tr>');
            html = stringList.join('');
        };
        return html;
    };

    var audioCounter = 0;
    function makeItemLink(item, itemData, itemClass, audioOk){
        let stringList = [];
        if (quiz.settings.audioMode && item.object === 'vocabulary' && audioOk){
            let gender = quiz.settings.audioSource;
            let audioId = 'Wkitaudio'+audioCounter; audioCounter++;

            if (gender == 'male' || gender == 'random'){
                let soundUrlmpeg = item.data.pronunciation_audios.find(a=>a.content_type=="audio/mpeg"&&a.metadata.gender==='male');
                if (soundUrlmpeg != undefined){soundUrlmpeg = soundUrlmpeg.url};
                let soundUrlogg = item.data.pronunciation_audios.find(a=>a.content_type=="audio/ogg"&&a.metadata.gender==='male');
                if (soundUrlogg != undefined){soundUrlogg = soundUrlogg.url};
                if (soundUrlmpeg != undefined && soundUrlogg != undefined){
                    if(soundUrlogg != undefined) stringList.push('<link ref="prefetch" href="'+soundUrlogg+'">');
                    if(soundUrlmpeg != undefined) stringList.push('<link ref="prefetch" href="'+soundUrlmpeg+'">');
                    stringList.push('<audio id="'+audioId+'male">');
                    if(soundUrlogg != undefined) stringList.push('<source src="'+soundUrlogg+'" type="audio/ogg"></source>');
                    if(soundUrlmpeg != undefined) stringList.push('<source src="'+soundUrlmpeg+'" type="audio/mpeg"></source>');
                    stringList.push('</audio>');
                }
            };

            if (gender == 'female' || gender == 'random'){
                let soundUrlmpeg = item.data.pronunciation_audios.find(a=>a.content_type=="audio/mpeg"&&a.metadata.gender==='female');
                if (soundUrlmpeg != undefined){soundUrlmpeg = soundUrlmpeg.url};
                let soundUrlogg = item.data.pronunciation_audios.find(a=>a.content_type=="audio/ogg"&&a.metadata.gender==='female');
                if (soundUrlogg != undefined){soundUrlogg = soundUrlogg.url};
                if (soundUrlmpeg != undefined && soundUrlogg != undefined){
                    if(soundUrlogg != undefined) stringList.push('<link ref="prefetch" href="'+soundUrlogg+'">');
                    if(soundUrlmpeg != undefined) stringList.push('<link ref="prefetch" href="'+soundUrlmpeg+'">');
                    stringList.push('<audio id="'+audioId+'female">');
                    if(soundUrlogg != undefined) stringList.push('<source src="'+soundUrlogg+'" type="audio/ogg"></source>');
                    if(soundUrlmpeg != undefined) stringList.push('<source src="'+soundUrlmpeg+'" type="audio/mpeg"></source>');
                    stringList.push('</audio>');
                }
            };

            stringList.push('<a onclick="playAudio('+"'"+audioId+"','"+gender+"'"+');">');
            stringList.push('<span '+itemClass+'>'+itemData[0]+'</span>');
            stringList.push('</a>');
            return stringList.join('');
        } else {
            stringList.push('<a style="padding-right:0;" target="_blank" href="');
            stringList.push(item.data.document_url);
            stringList.push('"><span ');
            stringList.push(itemClass);
            stringList.push('>');
            stringList.push(itemData[0]);
            stringList.push('</span></a>');
            return stringList.join('');
        };
    };

    function makeTooltips(item, selectedTable, mode){
        let stringList = []
        iconEntries.forEach(function (tableName){stringList.push(makeTooltipIcon(item, tableName))});
        toolTipEntries.forEach(function (tableName){stringList.push(makeTooltipEntry(item, tableName))});
        let presets = quiz.settings.tablePresets[selectedTable]
        let selection = presets.selection;
        if (mode === 'list') stringList.push(makeTooltipEntry(item, presets.table_data));
        if (mode === 'table' && selection == 'Date') stringList.push(makeTooltipEntry(item, presets.table_data));
        if (mode === 'list' && selection == 'Date') stringList.push(makeTooltipEntry(item, presets.navigationDate));

        let makeTableButton = '';
        if (iconEntries.length != 0) makeTableButton = '<button class="WkitMiniButton" SubjectId="'+item.id+'">Make Table</button>';

        var info = {
            type: item.object,
            characters: item.data.characters,
            url: item.data.document_url,
            svg: (item.data.characters === null ? item.data.character_images.find(a=>a.content_type=="image/svg+xml"&&a.metadata.inline_styles).url : null),
        };

        let stringList2 = ['<div class="WkitTooltipContent"><div class="left"><span class="'];
        stringList2.push(info.type);
        stringList2.push('" style="color: ');
        stringList2.push(fontColor)
        stringList2.push(' !important;">');
        if (info.characters === null){
            stringList2.push('<img src="');
            stringList2.push(info.svg);
            stringList2.push('">');
        } else {
            stringList2.push(info.characters);
        };
        stringList2.push('</span></div>');
        if (stringList.length != 0){
            stringList2.push('<div class="right"><table class="WkitTablePopup"><tbody>');
            stringList2.push(stringList.join(''));
            stringList2.push('</tbody></table>');
            stringList2.push(makeTableButton);
            stringList2.push('</div>');
        };
        stringList2.push('</div>');
        return stringList2.join('');
    }

    var toolTipEntries;
    var iconEntries;
    function initTooltipGlobals(){
        let presets = quiz.settings.tablePresets[quiz.settings.active_ipreset];
        toolTipEntries = [];
        iconEntries = [];
        let tableNames = ['tooltip1', 'tooltip2', 'tooltip3', 'tooltip4', 'tooltip5', 'tooltip6', 'tooltip7', 'tooltip8', ];
        let entriesWithIcons = {'Vis_Sim_Kanji': true, 'Components': true, 'Used_In': true, };
        tableNames.forEach(processName);

        function processName(name){
            if (presets[name] != 'None'){
                if (entriesWithIcons[presets[name]]){
                    iconEntries.push(presets[name]);
                } else {
                    toolTipEntries.push(presets[name]);
                };
            };
        };
    };

    function makeEnlargingTooltip (item, selectedTable){
        let html;
        if (quiz.settings.tablePresets[selectedTable].enlargingTooltip === true){
            let stringList = ['<div class="WkitEnlargedTooltip">'];
            stringList.push('<span class="');
            stringList.push(item.object);
            stringList.push('" style="color: ');
            stringList.push(fontColor);
            stringList.push(' !important;">');
            stringList.push((item.data.characters === null ? '<img src="'+item.data.character_images.find(a=>{ return a.content_type=="image/svg+xml"&&a.metadata.inline_styles}).url+'"' : item.data.characters));
            stringList.push('</span></div>');
            html = stringList.join('');
        } else {
            html = '';
        };
        return html;
    };

    const Wkit_navigation = 'Wkit_navigation';
    const Wkit_quiz = 'Wkit_quiz';
    /* Event handlers for buttons */
    function makeTableHandler(event) {
        //test prevents multiple clicks
        if (!event.detail || event.detail == 1) {
            dataReady = false;
            wkof.wait_state(Wkit_navigation, 'Ready')
                .then(function(){
                    let subjectId = Number($(event.target).attr("subjectid"))
                    let calledItem = subjectIndexVoc[subjectId];
                    if (calledItem === undefined) calledItem = subjectIndexKan[subjectId];
                    if (calledItem === undefined) calledItem = subjectIndexRad[subjectId];
                    let items = [];
                    iconEntries.forEach(t=>metadata[t].itemList(calledItem).forEach(a=>items.push(a)));
                    quiz.items = items;
                    let tableName = "--Temp "+calledItem.object.slice(0,3)+' '+(calledItem.data.characters != null ? calledItem.data.characters : calledItem.data.slug);
                    addTable(tableName);
                    nextCurrentItem = items.length;
                    currentItem = 0;
                    let subjectIdList = [];
                    iconEntries.forEach(t=>metadata[t].idList(calledItem).forEach(a=>subjectIdList.push(a)));
                    quiz.settings.tablePresets[quiz.settings.active_ipreset].itemList = subjectIdList;
                    quiz.settings.tablePresets[quiz.settings.active_ipreset].selection = 'None';
                    setSelectionButtonsColors()
                    quiz.settings.audioMode = false;
                    formatControlBar();
                    wkof.set_state(Wkit_navigation, 'Pending')
                    quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                    displayItems();
                    dataReady = true;
             })
        };
        return;
    };

    function clickedFirst(event) {
        document.getElementById("WkitFirstButton").blur();
        //test prevents multiple clicks
        if (!event.detail || event.detail == 1) {
            dataReady = false;
            wkof.wait_state(Wkit_navigation, 'Ready')
                .then(function(){
                        let presets = quiz.settings.tablePresets[quiz.settings.active_ipreset]
                        currentItem = 0;
                        presets.currentItem = currentItem;
                        presets.nextCurrentItem = nextCurrentItem;
                        if (presets.selection === 'Date') presets.startDate = quiz.items[currentItem].sortKey;
                        if (presets.selection === 'Selection'){
                            presets.savedSelCurrentItem = currentItem;
                            presets.savedSelNextCurrentItem = nextCurrentItem;
                        };
                        quiz.settings.audioMode = false;
                        formatControlBar();
                        wkof.set_state(Wkit_navigation, 'Pending')
                        quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                        displayItems();
                        dataReady = true;
            });
        };
        return
    }

    function clickedBackward(event) {
        document.getElementById("WkitBackwardButton").blur();
        //test prevents multiple clicks
        if (!event.detail || event.detail == 1) {
            if (currentItem > 0){
                dataReady = false;
                wkof.wait_state(Wkit_navigation, 'Ready')
                    .then(function(){
                            let presets = quiz.settings.tablePresets[quiz.settings.active_ipreset];
                            if (quiz.settings.listMode){
                                direction = 'Backward';
                                presets.nextCurrentItem = nextCurrentItem = currentItem;
                                presets.currentItem = currentItem - 1;
                                quiz.settings.audioMode = false;
                                formatControlBar();
                                wkof.wait_state(Wkit_navigation, 'Ready')
                                wkof.set_state(Wkit_navigation, 'Pending')
                                quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                                wkof.set_state(Wkit_quiz, 'Ready')
                                displayItems();
                                direction = 'Forward';
                                if (presets.selection === 'Date') {
                                    presets.startDate = quiz.items[currentItem].sortKey;
                                    wkof.set_state(Wkit_navigation, 'Pending')
                                    quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                                }
                                if (presets.selection === 'Selection'){
                                    presets.savedSelCurrentItem = currentItem;
                                    presets.savedSelNextCurrentItem = nextCurrentItem;
                                    wkof.wait_state(Wkit_navigation, 'Ready')
                                    wkof.set_state(Wkit_navigation, 'Pending')
                                    quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                                };
                                dataReady = true;
                            } else {
                                presets.nextCurrentItem = nextCurrentItem = currentItem;
                                currentItem = Math.max(currentItem - nbItems, 0);
                                presets.currentItem = currentItem;
                                if (presets.selection === 'Date') presets.startDate = quiz.items[currentItem].sortKey;
                                if (presets.selection === 'Selection'){
                                    presets.savedSelCurrentItem = currentItem;
                                    presets.savedSelNextCurrentItem = nextCurrentItem;
                                };
                                quiz.settings.audioMode = false;
                                formatControlBar();
                                wkof.set_state(Wkit_navigation, 'Pending')
                                quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                                displayItems()
                                dataReady = true;
                            }
                });
            }
        };
        return
    }

    function clickedForward(event) {
        document.getElementById("WkitForwardButton").blur();
        //test prevents multiple clicks
        if (!event.detail || event.detail == 1) {
            if(currentItem < nextCurrentItem && nextCurrentItem < quiz.items.length){
                dataReady = false;
                wkof.wait_state(Wkit_navigation, 'Ready')
                    .then(function(){
                            let presets = quiz.settings.tablePresets[quiz.settings.active_ipreset];
                            currentItem = nextCurrentItem;
                            presets.currentItem = currentItem;
                            presets.nextCurrentItem = nextCurrentItem;
                            if (presets.selection === 'Date') presets.startDate = quiz.items[currentItem].sortKey;
                            if (presets.selection === 'Selection'){
                                presets.savedSelCurrentItem = currentItem;
                                presets.savedSelNextCurrentItem = nextCurrentItem;
                            };
                            quiz.settings.audioMode = false;
                            formatControlBar();
                            wkof.set_state(Wkit_navigation, 'Pending')
                            quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                            displayItems();
                            dataReady = true;
                });
            };
        };
        return
    }

    function clickedLast(event) {
        document.getElementById("WkitLastButton").blur();
        //test prevents multiple clicks
        if (!event.detail || event.detail == 1) {
            dataReady = false;
            wkof.wait_state(Wkit_navigation, 'Ready')
                .then(function(){
                        let presets = quiz.settings.tablePresets[quiz.settings.active_ipreset];
                        if (quiz.settings.listMode){
                            direction = 'Backward';
                            presets.currentItem = currentItem = quiz.items.length;
                            presets.nextCurrentItem = nextCurrentItem = currentItem;
                            quiz.settings.audioMode = false;
                            formatControlBar();
                            wkof.set_state(Wkit_navigation, 'Pending')
                            quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                            displayItems();
                            if (presets.selection === 'Date') presets.startDate = quiz.items[currentItem].sortKey;
                            if (presets.selection === 'Selection'){
                                presets.savedSelCurrentItem = currentItem;
                                presets.savedSelNextCurrentItem = nextCurrentItem;
                            };
                            presets.currentItem = currentItem;
                            wkof.set_state(Wkit_navigation, 'Pending')
                            quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                            displayItems();
                            direction = 'Forward';
                            dataReady = true;
                        } else {
                            presets.nextCurrentItem = nextCurrentItem = currentItem;
                            currentItem = Math.max(quiz.items.length - nbItems, 0);
                            presets.currentItem = currentItem;
                            if (presets.selection === 'Date') presets.startDate = quiz.items[currentItem].sortKey;
                            if (presets.selection === 'Selection'){
                                presets.savedSelCurrentItem = currentItem;
                                presets.savedSelNextCurrentItem = nextCurrentItem;
                            };
                            quiz.settings.audioMode = false;
                            formatControlBar();
                            wkof.set_state(Wkit_navigation, 'Pending')
                            quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                            displayItems();
                            direction = 'Forward';
                            dataReady = true;
                        }
            });
        };
        return
    }

    function selectTable(event) {
        dataReady = false;
        document.getElementById("WkitTableSelector").blur();
        wkof.wait_state(Wkit_navigation, 'Ready')
            .then(function(){
                    let selected = quiz.settings.active_ipreset = $('#WkitTableSelector').prop('selectedIndex');
                    setSelectionButtonsColors()
                    if (quiz.settings.ipresets[selected].name.slice(0, 6) !== '--Temp') removeTempTables();
                    quiz.settings.audioMode = false;
                    formatControlBar();
                    wkof.set_state(Wkit_navigation, 'Pending')
                    quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                    fetch_items('table')
                        .then(updatePage)
                        .then(function(){dataReady = true;});
        });
    };

    function toggleDisplay(event) {
        document.getElementById("WkitToogleDisplay").blur();
        //test prevents multiple clicks
        if (!event.detail || event.detail == 1) {
            dataReady = false;
            wkof.wait_state(Wkit_navigation, 'Ready')
                .then(function(){
                        quiz.settings.listMode = !quiz.settings.listMode;
                        quiz.settings.audioMode = false;
                        formatControlBar();
                        wkof.set_state(Wkit_navigation, 'Pending')
                        quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                        displayItems();
                        dataReady = true;
            });
        };
        return
    };

    function toggleLanguage(event) {
        document.getElementById("WkitToogleLanguage").blur();
        //test prevents multiple clicks
        if (!event.detail || event.detail == 1) {
            dataReady = false;
            wkof.wait_state(Wkit_navigation, 'Ready')
                .then(function(){
                        let a = quiz.settings.tablePresets[quiz.settings.active_ipreset].displayMeaning;
                        quiz.settings.tablePresets[quiz.settings.active_ipreset].displayMeaning = !a;
                        quiz.settings.audioMode = false;
                        formatControlBar();
                        wkof.set_state(Wkit_navigation, 'Pending')
                        quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                        displayItems();
                        dataReady = true;
            });
        };
        return
    };

    function toggleAudio(event) {
        document.getElementById("WkitToogleAudio").blur();
        //test prevents multiple clicks
        if (!event.detail || event.detail == 1) {
            let a = quiz.settings.audioMode;
            quiz.settings.audioMode = !a;
            formatControlBar();
            displayItems();
        };
        return
    };


    function toggleRandomSelection(event) {
        document.getElementById("WkitRandomSelection").blur();
        //test prevents multiple clicks
        if (!event.detail || event.detail == 1) {
            dataReady = false;
            wkof.wait_state(Wkit_navigation, 'Ready')
                .then(function(){
                        let settings = quiz.settings;
                        let presets = settings.tablePresets[settings.active_ipreset];
                        settings.audioMode = false;
                        if (presets.selection === 'None'){
                            presets.selection = 'Random';
                            presets.savedCurrentItem = currentItem;
                            presets.savedNextCurrentItem = nextCurrentItem;
                            delete quiz.savedItems;
                            quiz.savedItems = quiz.items.slice(0, quiz.items.length);
                            doRandomSelection();
                            $('#WkitRandomSelection').toggleClass("WkitActive");
                        } else if (presets.selection === 'Date') {
                            presets.selection = 'Random';
                            delete quiz.items;
                            quiz.items = quiz.savedItems.slice(0, quiz.savedItems.length);
                            doRandomSelection();
                            $('#WkitRandomSelection').toggleClass("WkitActive");
                            $('#WkitDateOrdering').toggleClass("WkitActive");
                        } else if (presets.selection === 'Selection') {
                            presets.selection = 'Random';
                            delete quiz.items;
                            quiz.items = quiz.savedItems.slice(0, quiz.savedItems.length);
                            doRandomSelection();
                            $('#WkitRandomSelection').toggleClass("WkitActive");
                        } else {
                            presets.selection = 'None';
                            delete quiz.items;
                            quiz.items = quiz.savedItems;
                            presets.currentItem = currentItem = presets.savedCurrentItem;
                            presets.nextCurrentItem = nextCurrentItem = presets.savedNextCurrentItem;
                            $('#WkitRandomSelection').toggleClass("WkitActive");
                        };
                        wkof.set_state(Wkit_navigation, 'Pending')
                        quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                        displayItems();
                        dataReady = true;
            });

        };
        return
    };

    function doRandomSelection(){
        let settings = quiz.settings;
        let presets = settings.tablePresets[settings.active_ipreset];
        let selection = presets.selectionCriterion;
        shuffle(quiz.items);
        presets.currentItem = currentItem = 0;
        if (presets.randomSelection !== 0){
            nextCurrentItem = presets.randomSelection;
        } else if (settings.listMode){
            createItemList(quiz.items, true); // find out how many items fit the screen
        } else {
            nextCurrentItem = currentItem + nbItems;
        };
        quiz.items = quiz.items.slice(0, nextCurrentItem);
        presets.nextCurrentItem = nextCurrentItem;
        saveSelectedItems()
    };

    function saveSelectedItems(){
        let settings = quiz.settings;
        let savedSubjectindex = []
        quiz.items.forEach(item=>{savedSubjectindex.push(item.id)});
        let storageName = 'Wkit_' + settings.ipresets[settings.active_ipreset].name;
        sessionStorage.setItem(storageName, JSON.stringify(savedSubjectindex));
    };

    function retrieveSelecteditems(){
        let settings = quiz.settings;
        let storageName = 'Wkit_' + settings.ipresets[settings.active_ipreset].name;
        let ids = JSON.parse(sessionStorage.getItem(storageName));
        quiz.items = [];
        for (var idx in ids){
            let id = ids[idx];
            let item = subjectIndexVoc[id];
            if (item === undefined) item = subjectIndexKan[id];
            if (item === undefined) item = subjectIndexRad[id];
            quiz.items.push(item);
        };
    }

    function toggleDateOrdering(event) {
        document.getElementById("WkitDateOrdering").blur();
        //test prevents multiple clicks
        if (!event.detail || event.detail == 1) {
            dataReady = false;
            wkof.wait_state(Wkit_navigation, 'Ready')
                .then(function(){
                        let settings = quiz.settings;
                        let presets = settings.tablePresets[settings.active_ipreset];
                        settings.audioMode = false;
                        if (presets.selection === 'None'){
                            presets.selection = 'Date';
                            delete quiz.savedItems;
                            quiz.savedItems = quiz.items.slice(0, quiz.items.length);
                            doDateOrdering();
                            $('#WkitDateOrdering').toggleClass("WkitActive");
                        } else if (presets.selection === 'Random') {
                            presets.selection = 'Date';
                            delete quiz.items;
                            quiz.items = quiz.savedItems.slice(0, quiz.savedItems.length);
                            orderByDate(quiz.items);
                            presets.currentItem = currentItem; // should be determined by order by date
                            presets.nextCurrentItem = nextCurrentItem = currentItem;
                            $('#WkitRandomSelection').toggleClass("WkitActive");
                            $('#WkitDateOrdering').toggleClass("WkitActive");
                        } else if (presets.selection === 'Selection') {
                            presets.selection = 'Date';
                            presets.savedSelCurrentItem = currentItem;
                            presets.savedSelNextCurrentItem = nextCurrentItem;
                            delete quiz.items;
                            quiz.items = quiz.savedItems.slice(0, quiz.savedItems.length)
                            orderByDate(quiz.items);
                            presets.currentItem = currentItem; // should be determined by order by date
                            presets.nextCurrentItem = nextCurrentItem = currentItem;
                            $('#WkitDateOrdering').toggleClass("WkitActive");
                        } else {
                            presets.selection = 'None';
                            delete quiz.items
                            quiz.items = quiz.savedItems;
                            presets.currentItem = currentItem = presets.savedCurrentItem;
                            presets.nextCurrentItem = nextCurrentItem = presets.savedNextCurrentItem;
                            $('#WkitDateOrdering').toggleClass("WkitActive");
                        };
                        wkof.set_state(Wkit_navigation, 'Pending')
                        quiz.settings_dialog.save().then(function(){wkof.set_state(Wkit_navigation, 'Ready')})
                        displayItems();
                        dataReady = true;
            });
        };
        return
    };

    function doDateOrdering (){
        let settings = quiz.settings;
        let presets = settings.tablePresets[settings.active_ipreset];
        presets.savedCurrentItem = currentItem;
        presets.savedNextCurrentItem = nextCurrentItem;
        orderByDate(quiz.items);
        presets.currentItem = currentItem; // should be determined by order by date
        presets.nextCurrentItem = nextCurrentItem = currentItem;
    }

    function setSelectionButtonsColors(){
        let settings = quiz.settings;
        let presets = settings.tablePresets[settings.active_ipreset];
        let selection = presets.selection;
        if (selection === 'None'){
            if ($('#WkitRandomSelection').hasClass("WkitActive")) $('#WkitRandomSelection').toggleClass("WkitActive");
            if ($('#WkitDateOrdering').hasClass("WkitActive")) $('#WkitDateOrdering').toggleClass("WkitActive");
        } else if (selection === 'Random') {
            if (!$('#WkitRandomSelection').hasClass("WkitActive")) $('#WkitRandomSelection').toggleClass("WkitActive");
            if ($('#WkitDateOrdering').hasClass("WkitActive")) $('#WkitDateOrdering').toggleClass("WkitActive");
        } else if (selection === 'Date'){
            if ($('#WkitRandomSelection').hasClass("WkitActive")) $('#WkitRandomSelection').toggleClass("WkitActive");
            if (!$('#WkitDateOrdering').hasClass("WkitActive")) $('#WkitDateOrdering').toggleClass("WkitActive");
        }
    }

    /* control variables for the currently displayed tables*/
    var currentItem = 0;
    var nextCurrentItem;
    var nbItems = 0;

    function initCurrentItem(){
        currentItem = quiz.settings.tablePresets[quiz.settings.active_ipreset].currentItem;
        if (currentItem == undefined){currentItem = 0; nextCurrentItem = 0;};
        nextCurrentItem = quiz.settings.tablePresets[quiz.settings.active_ipreset].nextCurrentItem;
        if (nextCurrentItem == undefined){nextCurrentItem = currentItem;};
        nbItems = 3 * quiz.settings.numberOfLines;
    }

    var script = '<script type="text/javascript">'
    script += 'function playAudio(id, gender){';
    script +=      'if (gender === "random"){gender = ["male", "female"][Math.floor(Math.random()*2)]};'
    script +=      'id += gender;';
    script +=      'document.getElementById(id).play();';
    script += '};';
    script += '</script>';
    var $script = $(script);

    const numberOfTables = 3;
    var itemPer;
    var nbDisplayedItems;
    var sizeOfList;
    var sizeOfTable;
    var numberPerTable;
    function setNumberOfLines (){
        if (quiz.settings.numberOfLines === undefined){
            numberPerTable = 11;
        } else {
            numberPerTable = Number(quiz.settings.numberOfLines);
        };
        sizeOfTable = numberOfTables * numberPerTable;
        sizeOfList = 115;
        if (quiz.settings.listMode){nbDisplayedItems = sizeOfList} else {nbDisplayedItems = sizeOfTable};
    };

    const emptyMessage = `<div class="emptyMessage"><p><b>No items match your criteria. You may try relaxing them if possible.</b></p></div>`;
    function createTopLeechTables(items) {
        let startnumberTable = currentItem;
        let endNumberTable = currentItem + numberPerTable;
        let itemsLength = items.length;
        let nrOfTables = numberOfTables;
        let totalNumberOfLeeches = numberPerTable * nrOfTables;
        let meanings = "";
        let readings = "";
        audioCounter = 0;
        let activeTable = quiz.settings.active_ipreset;
        initTooltipGlobals();
        let elemenentsList = [];

        //make sure we don't create empty tables if there are too few items
        if(items.length == 0){
            nrOfTables = 0;
            elemenentsList.push($(emptyMessage));
        } else if(items.length < totalNumberOfLeeches) { //if less leeches available then user requested
            var ratio = items.length / (numberPerTable*3);
            if(ratio <= 0.34){
                nrOfTables = 1;
            } else if(ratio <= 0.67){
                nrOfTables = 2;
            }
        } else if (numberPerTable >= totalNumberOfLeeches){ //if table capacity greater than user's requested amount of leeches
            nrOfTables = 1;
        }

        //Create tables
        if (quiz.settings.audioMode) elemenentsList.push($script);
        for (var i = 0; i < nrOfTables; i++){
            //In case there are less than the requested amount of items
            if(items.length <= endNumberTable){
                endNumberTable = items.length;
                nrOfTables = i - 1;
            };
            let $tableColumn = $('<div class="span4" style="width=290px;"><div>');
            let $currentElement = $tableColumn;
            let $tempElement = $('<div class="WkitTableList" style="position: relative;"></div>');
            $currentElement.append($tempElement);
            $currentElement = $tempElement;
            $tempElement = $('<table></table>');
            $currentElement.append($('<h3 class="WkitSmallCaps">Items '+(startnumberTable+1)+'-'+endNumberTable+' of '+itemsLength+'</h3>'), $tempElement);
            $currentElement = $tempElement;
            let $tbody = $('<tbody></tbody>');
            let sectionContents = '';
            $currentElement.append($tbody);
            for (var j = startnumberTable; j < endNumberTable; j++){
                let itemData = itemsCharacterCallback(items[j], false);
                let tableEntry = makeTableEntry(items[j], activeTable);
                let itemLink = makeItemLink(items[j], itemData, 'class="WkitMainElement WkitItem'+itemData[2]+'" style="color: '+fontColor+' !important"', true);
                let addClass = (j <= startnumberTable + 2 ? 'WkitFirstItem' : 'WkitLaterItem');
                let tooltip = makeTooltips(items[j], activeTable, 'table');
                let tooltip2;
                if (itemData[1]){
                    tooltip2 = '<div class="WkitTooltip2"><p><span> </span></p>'+makeEnlargingTooltip(items[j], activeTable)+'</div>';
                } else {
                    tooltip2 = '';
                };
                sectionContents += `<tr class="${items[j].object}">` +
                    '<td>' +
                    '<div class="WkitTooltip '+addClass+'">' +
                    itemLink +
                    tooltip +
                    '</div>' +
                    tooltip2 +
                    '</td>' +
                    '<td>' +
                    '<div style="text-align: right"><a class="WkitMainElement" style="padding-left:0;"><span style="color: '+secondaryFontColor+' !important">'+tableEntry+'</span></a>' +
                    '</div>' +
                    '</td>' +
                    '</tr>';
            }
            $tbody.append($(sectionContents));
            //preparing for next table
            startnumberTable += numberPerTable;
            endNumberTable += numberPerTable;
            elemenentsList.push($tableColumn);
        }

        nextCurrentItem = Math.min(j, items.length);
        //$('#leech_table').empty().append($script, $(sectionContents));//replace existing table
        // replace existing table
        let $leech_table = $('#leech_table').empty();
        elemenentsList.forEach(elem=>$leech_table.append(elem))
        if (iconEntries.length != 0) $('.WkitMiniButton').click(makeTableHandler);
    }

    var direction = 'Forward';
    function createItemList(items, noDisplay){
        let startNumberItem = currentItem;
        let itemsLength = items.length;
        let selected_table = quiz.settings.active_ipreset;
        let presets = quiz.settings.tablePresets[selected_table]
        let meaningMode = presets.displayMeaning;
        let get_table_data = metadata[presets.table_data].tableEntryMarker;
        let showMarkers = presets.showMarkers;
        if (presets.selection === 'Random') showMarkers = false;
        if (presets.selection === 'Date') showMarkers = presets.showMarkersDate;
        let dateSelection = (presets.selection === 'Date');
        let dateSelected = presets.navigationDate;
        if (dateSelection) get_table_data = metadata[dateSelected].tableEntryMarker;
        audioCounter = 0;
        initTooltipGlobals();

        // These variables control how many items will be on the screen so they don't overflow it
        let firstLineLimit = meaningMode ? 120.0 : 70.0;
        let maxCharCount = meaningMode ? 550.0 : 333.0;
        let overheadVocab = 0.9;
        let overheadOther = 0.8;
        let markerFactor = 0.27;
        let markerOverhead = 0.9;
        let meaningFactor = 0.27;
        let meaningOverhead = 0.9;
        let itemLimit = (meaningMode ? 170 : 108);

        let htmlList = ['']; // reserve element 0 for the summary marker
        let charCount = 0;
        let oldMarker = undefined;
        let newMarker = undefined;
        let markerString;

        if (direction === 'Forward'){
            let i = currentItem;
            let endNumberItem = items.length - 1;
            while (charCount < maxCharCount && i <= endNumberItem){
                processItem(i);
                i++;
            }
            nextCurrentItem = i;
            htmlList[0] = `<div class="WkitSmallCapsList${meaningMode ? ' WkitMeaning' : ' WkitReading'}"><span>Items ${startNumberItem + 1}-${i} of ${itemsLength}</span></div>`;
        } else {
            let i = currentItem -1;
            while (charCount < maxCharCount && i >= 0){
                calculateCount(i);
                i--;
            };
            charCount = 0;
            oldMarker = undefined;
            newMarker = undefined;
            i = i + 1; // the last i was not processed
            currentItem = i;
            let j = i;
            if (i > 0){
                while (j < startNumberItem){
                    processItem(j);
                    j++;
                };
                htmlList[0] = `<div class="WkitSmallCapsList${meaningMode ? ' WkitMeaning' : ' WkitReading'}"><span>Items ${i+1}-${startNumberItem} of ${itemsLength}</span></div>`;
            } else {
                // i is 0. We have to fill the whole table - relying on startnumber would display too few items.
                let endNumberItem = items.length - 1;
                while (charCount < maxCharCount && i <= endNumberItem){
                    processItem(i);
                    i++;
                };
                nextCurrentItem = i;
                htmlList[0] = `<div class="WkitSmallCapsList${meaningMode ? ' WkitMeaning' : ' WkitReading'}"><span>Items ${1}-${i} of ${itemsLength}</span></div>`;
            };
        };

        let $mainElement;
        if (items.length === 0){
            $mainElement = $(emptyMessage);
        } else {
            $mainElement = $('<div class="WkitItemList '+(charCount < firstLineLimit ? 'WkitFlexLeft' : 'WkitFlexJustified')+'"></div>');
            $mainElement.append($(htmlList.join('')));
        };
        if (!noDisplay){
            let $leech_table = $('#leech_table').empty();
            if (items.length !== 0 && quiz.settings.audioMode) $leech_table.append($(script));
            $leech_table.append($mainElement);
            if (iconEntries.length != 0) $('.WkitMiniButton').click(makeTableHandler);
        }

        function processItem(i){
            newMarker = get_table_data(items[i]);
            if (newMarker !== oldMarker){
                oldMarker = newMarker;
                if (showMarkers && newMarker !== ''){
                    htmlList.push(makeMarkerElement(newMarker, meaningMode));
                    markerString = (typeof newMarker === 'number' ? newMarker.toString() : newMarker);
                    charCount += (markerString.length * markerFactor) + markerOverhead;
                };
            };
            if (meaningMode){
                let meaning = metadata.Meaning_Brief.tableEntry(items[i]);
                htmlList.push(makeListElement(items[i], selected_table, charCount, 'WkitTooltipIconMeaning', itemLimit));
                charCount += meaning.length * meaningFactor + meaningOverhead;
            } else {
                htmlList.push(makeListElement(items[i], selected_table, charCount, 'WkitTooltipIcon', itemLimit));
                charCount += (items[i].data.characters === undefined || items[i].data.characters === null ? 1 + overheadOther : (items[i].data.characters.length === 1 ? 1 + overheadOther : items[i].data.characters.length + overheadVocab));
            };
        }

        function calculateCount(i){
            newMarker = get_table_data(items[i]);
            if (newMarker != oldMarker){
                oldMarker = newMarker;
                if (showMarkers && newMarker != ''){
                    markerString = (typeof newMarker === 'number' ? newMarker.toString() : newMarker);
                    charCount += (markerString.length * markerFactor) + markerOverhead;
                };
            };
            if (meaningMode){
                let meaning = metadata.Meaning_Brief.tableEntry(items[i]);
                charCount += meaning.length * meaningFactor + meaningOverhead;
            } else {
                charCount += (items[i].data.characters === undefined || items[i].data.characters === null ? 1 + overheadOther : (items[i].data.characters.length === 1 ? 1 + overheadOther : items[i].data.characters.length + overheadVocab));
            };
        }

        function makeListElement(item, selected_table, charCount, itemClass, firstObjectLimit){
            let stringList = [' class="'];
            stringList.push(item.object);
            stringList.push('"style="color: ');
            stringList.push(fontColor);
            stringList.push(' !important;"');

            let itemLink = makeItemLink(item, itemsCharacterCallback(item, false), stringList.join(''), true);

            stringList = ['<div class="WkitTooltip '];
            stringList.push(itemClass);
            stringList.push(' ');
            stringList.push(item.object);
            stringList.push(charCount <= firstObjectLimit ? " WkitFirstItem" : " WkitLaterItem");
            stringList.push('">');
            stringList.push(makeTooltips(item, selected_table, 'list'));
            stringList.push('<div class="WkitItemListed">');
            stringList.push(itemLink);
            stringList.push('</div></div>');

            return stringList.join('');
        };

        function makeMarkerElement(marker, meaningMode){
            let stringList = ['<div class="WkitTooltip WkitTooltipIcon'];
            stringList.push(meaningMode ? ' WkitMarkerMeaning' : ' WkitMarker');
            stringList.push('"><div class="');
            stringList.push(meaningMode ? 'WkitMarkerMeaning' : 'WkitMarker');
            stringList.push('" style="color: #000000 !important;"><span>');
            stringList.push(marker);
            stringList.push('</span></div></div>');

            return stringList.join('');
        };
    };

    function fillClipboard(){
        document.getElementById("WkitWordExport").blur();
        quiz.exportBackup = quiz.items;
        if (quiz.settings.repeatWordCloud != 'No Repeat'){
            // make sure the repeat field endpoint is available in the items
            dataReload('wordCloud');
        } else {
            performWordCloud();
        };
    };

    function performWordCloud(){
        let items = quiz.items;
        let text = '';
        let noLatin = quiz.settings.noLatin;
        if (noLatin === undefined){noLatin = false};
        let oneItemPerLine = quiz.settings.oneItemPerLine;
        if (oneItemPerLine === undefined){oneItemPerLine = false};
        let exportLimit = quiz.settings.exportLimit;
        if (exportLimit === undefined){exportLimit = 0};
        let exportCount = 0;
        let repeatWordCloud = quiz.settings.repeatWordCloud;
        let repeatCount;

        for (var i = 0; i < items.length; i++){
            let itemsData = items[i].data;
            if (repeatWordCloud != 'No Repeat'){
                repeatCount = metadata[repeatWordCloud].wordCloud(items[i]);
            } else {
                repeatCount = 1;
            };
            for (var j = 0; j < repeatCount; j++){
                if(itemsData.characters!= null) {
                    text += itemsData.characters+' ';
                    if (oneItemPerLine){text += '\n'};
                } else if (!noLatin){
                    text += itemsData.slug+' ';
                    if (oneItemPerLine){text += '\n'};
                };
            };
            if (repeatCount != 0){exportCount += 1;};
            if (exportLimit != 0 && exportCount >= exportLimit){break};
        };

        exportDialog(text, exportCount, 'txt')
    };

    function exportTable(){
        document.getElementById("WkitExport").blur();
        let currentPreset = quiz.settings.tablePresets[quiz.settings.active_ipreset];
        let currentColumn = currentPreset[exportedInfo[0]];
        if (currentColumn === undefined || currentColumn == 'None' ){
            alert('The first column is not exported.\nPlease configure your export settings.');
            return;
        };

        // make sure all export data is available in the items
        quiz.exportBackup = quiz.items;
        dataReload('export');
    };

    function performExport(){
        let currentPreset = quiz.settings.tablePresets[quiz.settings.active_ipreset];
        let currentColumn = currentPreset[exportedInfo[0]];
        let items = quiz.items;
        let text = '';
        let exportCount = 0;
        let quotes = currentPreset.quotes;
        let separator = currentPreset.separator;
        if(separator === ',' && quotes === 'Never'){
            alert('Inconsistent settings.\nMust use quotes when separator is comma.\nChanging separator to horizontal tab.');
            separator = '\t';
        };
        let missingData = currentPreset.missingData === 'Empty_Cell';
        let includeLabels = currentPreset.includeLabels;
        let URLclickable = currentPreset.URLclickable;
        if (URLclickable === 'Spreadsheet' && quotes === 'Never' && (separator === ';' || separator === ',')){
            let URLcolumn = false;
            exportedInfo.forEach(item => {if (currentPreset[item] === 'Item_Page') URLcolumn = true})
            if (URLcolumn){
                alert('Inconsistent settings.\nYou have requested a clickable URL column for spreadsheet with a comma or a semicolumn separator without quotes.\nThis combination will break the csv.\nChanging separator to horizontal tab.');
                separator = '\t';
            }
        }
        if (URLclickable !== 'Plain'){
            let URLexported = false;
            let emptyColumn = '';
            let emptyColumnNumber = 0;
            for (var i = 0; i < exportedInfo.length; i++){
                if (currentPreset[exportedInfo[i]] === "Item_Page"){URLexported = true};
                if (currentPreset[exportedInfo[i]] === 'None'){
                    emptyColumnNumber = i + 1;
                    emptyColumn = exportedInfo[i];
                };
            };
            if (!URLexported){
                alert('Inconsistent settings.\nYou have requested a clickable URL but have not selected "URL of Item Page" in any column.\nAutomatically adding "URL of Item Page" to column '+i);
                currentPreset[emptyColumn] = "Item_Page";
            };
        };
        let hoursInDate = currentPreset.hoursInDate;

        let titleEntry;
        let firstElement = true;
        if (currentPreset.includeTitle){
            for (i = 0; i < exportedInfo.length; i++){
                let currentColumn = currentPreset[exportedInfo[i]];
                if (currentColumn !='None' && currentColumn != undefined){
                    titleEntry = metadata[currentColumn].title;
                    if (quotes === 'Always' || (quotes === 'As_Needed' && titleEntry.indexOf(' ') != -1)){titleEntry = '"'+titleEntry+'"';}
                    if (firstElement){
                        text += titleEntry;
                        firstElement = false;
                    } else {
                        text += separator+titleEntry;
                    };
                };
            };
            text += '\n';
        };

        for (i = 0; i < items.length; i++){
            firstElement = true;
            for (var j = 0; j < exportedInfo.length; j++){
                currentColumn = currentPreset[exportedInfo[j]];
                if (currentColumn !='None' && currentColumn != undefined){
                    let metaCol = metadata[currentColumn];
                    if (metaCol.exists(items[i])) {
                        titleEntry = metaCol.export(items[i]);
                        if (missingData && titleEntry === 'Unavailable'){
                            titleEntry = '';
                        } else {
                            if (metaCol.isDate && !(hoursInDate[currentColumn] === true)){
                                if (titleEntry != 'Unscheduled' && titleEntry != 'Not Yet'){titleEntry = titleEntry.slice(0, 10)};
                            };
                            if (titleEntry === ''){titleEntry = '-Empty-'};
                            if (includeLabels) titleEntry = metaCol.labelExport+titleEntry;
                            if (currentColumn === 'Item_Page' && URLclickable !== 'Plain'){
                                let item = items[i];
                                let indentification = item.object.slice(0,3) + ' '+ (item.data.characters != undefined ? item.data.characters : item.data.slug);
                                if (URLclickable === 'Spreadsheet'){
                                    if (quotes === 'Always' || (quotes === 'As_Needed' && (separator === ';' || separator === ','))){
                                        titleEntry = '=HYPERLINK(""'+titleEntry+'""; ""Link '+indentification+'"")';
                                    } else {
                                        titleEntry = '=HYPERLINK("'+titleEntry+'"; "Link '+indentification+'")';
                                    };
                                } else if (URLclickable === 'html') {
                                    if (quotes === 'Always'){
                                        titleEntry = "<a href='"+titleEntry+"'>"+indentification+"</a>";
                                    } else {
                                        titleEntry = '<a href="'+titleEntry+'">'+indentification+'</a>';
                                    };
                                };
                            };
                            if (quotes === 'Always') titleEntry = '"'+titleEntry+'"';
                            if (quotes === 'As_Needed' && metaCol.needQuotes) titleEntry = '"'+titleEntry+'"';
                            if (quotes === 'As_Needed' && URLclickable && currentColumn === 'Item_Page' && (separator === ';' || separator === ',')) titleEntry = '"'+titleEntry+'"';
                        }
                    } else {
                        titleEntry = (missingData ? '' : includeLabels ? metaCol.labelExport+'Unavailable' : 'Unavailable');
                    };
                    if (firstElement){
                        text += titleEntry;
                        firstElement = false;
                    } else {
                        text += separator+titleEntry;
                    };
                };
            };
            text += '\n';
            exportCount += 1;
        };

        exportDialog(text, exportCount, 'csv')
    };

    var text;
    var exportCount;
    function exportDialog(xtext,xexportCount,ext){
        text = xtext;
        exportCount = xexportCount;

        let encoded = encodeURI("\uFEFF"+text);
        let link = '<a href="data:text/csv; charset=utf-8,'+encoded+'" download="Item Inspector Export.'+ext+'">Download</a>';
        let dialog = '<button id="WkitClipboardButton" class="WkitExportButton">Copy to Clipboard</button>' +
            '<button id="WkitDownLoadButton" class="WkitExportButton">'+link+'</button>' +
            '<button id="WkitCancelButton" class="WkitExportButton">Cancel</button>';

        $("#WkitDialogContainer").html(dialog);
        $("#WkitClipboardButton").click(clipboardHandler);
        $("#WkitDownLoadButton").click(downloadlHandler);
        $("#WkitCancelButton").click(cancelHandler);
        $("#WkitDialogContainer").css('display', 'block');

        function clipboardHandler(e){
            $("#WkitDialogContainer").html('');
            $("#WkitDialogContainer").css('display', 'none');
            quiz.items = quiz.exportBackup;
            delete quiz.exportBackup;
            navigator.clipboard.writeText(text)
                .then(function(){alert(exportCount+' items have been exported to the clipboard.');})
        }

        function downloadlHandler(e){
            $("#WkitDialogContainer").html('');
            $("#WkitDialogContainer").css('display', 'none');
            quiz.items = quiz.exportBackup;
            delete quiz.exportBackup;
            alert(exportCount+' items are being downloaded.')
        }

        function cancelHandler(e){
            $("#WkitDialogContainer").html('');
            $("#WkitDialogContainer").css('display', 'none');
            quiz.items = quiz.exportBackup;
            delete quiz.exportBackup;
        }
    }

	// BEGIN Item Inspector wkof Filter

    function waitForItemDataRegistry() {
        return wkof.wait_state('wkof.ItemData.registry', 'ready');
	}

	function registerItemInspectorFilter() {
        waitForItemDataRegistry()
           .then(function(){
                delete wkof.ItemData.registry.sources.wk_items.filters.itemInspectorFilter;
                delete wkof.ItemData.registry.sources.wk_items.filters.itemInspectorFilterName;
                wkof.ItemData.registry.sources.wk_items.filters.itemInspectorFilter = {
                    type: 'text',
                    label: 'Item Inspector',
                    default: '',
                    placeholder: 'The input is not used',
                    filter_func: itemInspectorFilter,
                    set_options: function(options) { return },
                    hover_tip: 'Tool for Item Inspector Integration\nShould Be Turned OFF\nMay Cause Problems If Turned On',
                    no_ui: true,
                };
        })
	}

    var quizzedItems = {};
	function itemInspectorFilter(filterValue, item) {
		return (quizzedItems[item.id] === true);
	}
	// END Item Inspector wkof Filter

    var dataReady = false;
    function quizOnWholeTable(e){
        document.getElementById("WkitQuizTable").blur();
        if (dataReady) launchSelfStudyQuiz(0, quiz.items.length);
    };

    function quizOnSelection(e){
        document.getElementById("WkitQuizSelection").blur();
        if (dataReady) launchSelfStudyQuiz(currentItem, nextCurrentItem);
    }

    function launchSelfStudyQuiz(start, end){
        quizzedItems = {};
        let items = quiz.items;
        let i = start;
        while (i < end){
            quizzedItems[items[i].id] = true;
            i++
        }
        let config = {ipreset: {name: 'Item_Inspector', content: {
                                wk_items: {enabled: true, filters: {itemInspectorFilter: {enabled: true, value: ''},}},
                           }},
                  };
        wkof.wait_state('ss_quiz', 'ready').then(function(){ss_quiz.open(config)});
    };

    const waitMessage = '<div class="emptyMessage"><p id="WkitWaitMessage"><b>Item Inspector is loading the data<b></p></div>'

    function dataReload(fetchOption){
        $('#leech_table').html = waitMessage;
        switch (fetchOption){
            case 'export':
                return fetch_items(fetchOption).then(performExport);
                break;
            case 'wordCloud':
                return fetch_items(fetchOption).then(performWordCloud);
                break;
            case 'table':
            default:
                return fetch_items(fetchOption).then(updatePage);
                break;
        };
    }

    function insertContainer(){
        /* build containers for the table elements */
        const helpURL = 'https://community.wanikani.com/t/userscript-wanikani-item-inspector/44564';
        let sectionContainer = '<div id="WkitTopBar" class="WkitTopBar"></div> ';
        let topBlock = '<div id="WkitControlBar" class="WkitControlBar">' +
            '<div class="WkitHeader">' +
            '<div class="WkitControlLeft">'+
            '<button id="WkitFirstButton" type="button" class="WkitButton WkitButtonleft icon-fast-backward"></button>' +
            '<button id="WkitBackwardButton" type="button" class="WkitButton WkitButtonleft" style="padding-right: 8px; padding-bottom: 3px;">&#9668</button>' +
            '<button id="WkitForwardButton" type="button" class="WkitButton WkitButtonleft" style="padding-left: 7px; padding-bottom: 3px;">&#9658</button>' +
            '<button id="WkitLastButton" type="button" class="WkitButton WkitButtonleft icon-fast-forward"></button>' +
            '<select id="WkitTableSelector" class="WkitSelector" title="Choose the table you want to display"></select>'+
            '<button id="WkitToogleDisplay" type="button" class="WkitButton WkitButtonleft icon-bullseye" title="Toggles between Tables and Lists of icons"icon-bullseye></button>' +
            '<button id="WkitToogleLanguage" type="button" class="WkitButton WkitButtonleft" title="Toggles the current page between English and Japanese\nPages other than the current one are unaffected." style="font-size:18px; font-weight: 500;" lang="JP"></button>' +
            '<button id="WkitToogleAudio" type="button" class="WkitButton WkitButtonleft" title="Turns on/off clicking on vocabulary items to play audio.\nAudio is automalically turned off when you click on a button that may change the screen." style="font-size:15px; font-weight: bold; padding-bottom: 1px"></button>' +
            '<button id="WkitRandomSelection" type="button" class="WkitButton WkitButtonleft icon-retweet" title="Fill the screen with randomly chosen items.\nPermits to be quized on randomly picked items.\nClick again to return to whole table."></button>' +
            '<button id="WkitDateOrdering" type="button" class="WkitButton WkitButtonleft icon-sort-by-attributes" title="Toggles the ordering of items by date and time.\nEnables navigation over time ranges.\nPermits to be quized on items selected by date.\nClick again to return to whole table,"></button>' +
            '</div>' +
            '<p class="WkitTitle"><b>Wanikani Item Inspector</b></p>' +
            '<div class="WkitControlRight">'+
            '<button id="WkitDocumentation"type="button" class="WkitButton WkitButtonRight" title="Go to Item Inspector Page" style="font-size:22px; font-weight: bold; padding: 4px"><a href="'+helpURL+'" target="_blank">?</a></button>' +
            '<button id="WkitSettings" type="button" class="WkitButton WkitButtonRight icon-gear" title="Settings" style="font-size:20px;"></button>' +
            '<button id="WkitWordExport" type="button" class="WkitButton WkitButtonRight icon-cloud" title="Export items\nSuitable for word clouds."></button>' +
            '<button id="WkitExport" type="button" class="WkitButton WkitButtonRight" title="Export to format csv.\nSuitable for spreasheet, Anki and Kitsun." style="font-size:20px;">&#8686;</button>' +
            '<button id="WkitQuizSelection" type="button" class="WkitButton WkitButtonRight icon-desktop" title="Quiz on items shown on the screen.\nUse navigation and random selection options\n to control which items are displayed."></button>' +
            '<button id="WkitQuizTable" type="button" class="WkitButton WkitButtonRight icon-table" title="Quizzes on the whole table.\nWhen a random selection is activee quizzes on the selection."></button>' +
            '</div>' +
            '</div>' +
            '</div>' +
            '<div id="WkitDialogContainer" class="WkitDialogContainer">Text here for testing</div>' +
            '<div id="leech_table">'+waitMessage+'</div>';

        if (quiz.settings.position === undefined) {quiz.settings.position = 2};
        let position = [".progress-and-forecast", '.progress-and-forecast', '.srs-progress',  '.span12 .row', '.span12 .row:last-of-type',][quiz.settings.position];
        if (quiz.settings.position == 0){
            $(position).before(sectionContainer);
        } else {
            $(position).after(sectionContainer);
        }
        // insert the top block - must be separate from the sectionContainer to work around a bug
        $('#WkitTopBar').append(topBlock);  // must be appended - someone else may be there due to the bug
        formatControlBar();
        populateDropdown();
    };

    function populateDropdown(){
        // Populate the dropdown with the configured tables
        let activeTable = quiz.settings.active_ipreset;
        var tableList = '';
        var ipresets = quiz.settings.ipresets;
        for (var table of ipresets) {
            tableList += '<option>' + table.name.replace(/</g,'&lt;').replace(/>/g,'&gt;') +'</option>'
        };
        var dropdown = $('#WkitTableSelector');
        dropdown.html(tableList);
        $('#WkitTableSelector').prop('selectedIndex',activeTable);
    };

    function formatControlBar (){
        if (quiz.settings.tablePresets[quiz.settings.active_ipreset].displayMeaning){$('#WkitToogleLanguage').html('字')} else {$('#WkitToogleLanguage').html('<span class="WkitEnglishButton">E</span>')};
        if (quiz.settings.audioMode){$('#WkitToogleAudio').html('<span style="padding-left: 2px;">&#9654;</span>')} else {$('#WkitToogleAudio').html('<span style="text-decoration: underline; font-size: 18px; padding-bottom: 8px; padding-left: 0px;">L</span>')};
    };

    function eventHandlers() {
        /* Define the button actions. Must be done when the DOC is completed */
        $("#WkitFirstButton").click(clickedFirst);
        $("#WkitBackwardButton").click(clickedBackward);
        $("#WkitForwardButton").click(clickedForward);
        $("#WkitLastButton").click(clickedLast);
        $('#WkitTableSelector').change(selectTable);
        $('#WkitToogleDisplay').click(toggleDisplay);
        $('#WkitToogleLanguage').click(toggleLanguage);
        $('#WkitToogleAudio').click(toggleAudio);
        $('#WkitRandomSelection').click(toggleRandomSelection);
        $('#WkitDateOrdering').click(toggleDateOrdering);
        $('#WkitQuizTable').click(quizOnWholeTable);
        $('#WkitQuizSelection').click(quizOnSelection);
        $("#WkitWordExport").click(fillClipboard);
        $("#WkitExport").click(exportTable);
        $("#WkitSettings").click(open_settings_dialog);
    };

    //------------------------------------------
    // Starting the program
    // at the end to ensure the global variables are defined
    //------------------------------------------
    var notSelfStudyQuiz = false;
    function check_Self_Study_Quiz(){
        if ($('#selfstudyquiz_script_link a').length === 0) {
            script_name = 'Wanikani Item Inspector';
            response = confirm(script_name + ' requires  Self Study Quiz\n Click "OK" to be forwarded to installation instructions.');
            if (response) {
                window.location.href = 'https://community.wanikani.com/t/userscript-self-study-quiz/13191';
            };
        } else {
            notSelfStudyQuiz = true;
        }
    };

    var notAdditionalFilters = false;
    function check_additional_filters(){
        if (!window.wkof.ItemData.registry.sources.wk_items.filters.additionalFilters_leechTraining) {
            script_name = 'Wanikani Item Inspector';
            response = confirm(script_name + ' requires  WaniKani Open Framework Additional Filters.\nIf you have already installed it please enable the filters in the settings.\n Click "OK" to be forwarded to installation instructions.');
            if (response) {
                window.location.href = 'https://community.wanikani.com/t/userscript-wanikani-open-framework-additional-filters-recent-lessons-leech-training-related-items-and-more/30512';
            };
        } else {
            notAdditionalFilters = true;
        }
    };

    function initSequence(){
        if (notAdditionalFilters && notSelfStudyQuiz){
            install_css();
            install_menu();
            init_settings();
            setup_quiz_settings();
            wkof.Settings.load(scriptId)
                .then( function(){
                    init_settings();
                    add_defaults();
                    table_css();
                    registerItemInspectorFilter();
                    initCurrentItem();
                    setNumberOfLines();
                    insertContainer();
                    eventHandlers();
                    wkof.set_state(Wkit_navigation, 'Ready');
                    dataReload('table');
                    wkof.set_state(Wkit_quiz, 'Ready');
                })
        }
    }

    wkof.include('ItemData, Menu, Settings');
    wkof.ready('ItemData, Menu, Settings')
        .then(function(){wkof.wait_state('additionalFilters', 'ready')})
        .then(check_additional_filters)
        .then(function(){wkof.wait_state('ss_quiz', 'ready')})
        .then(check_Self_Study_Quiz)
        .then(initSequence)

    // Handy little function that rfindley wrote. Checks whether the theme is dark.
    function is_dark_theme() {
        // Grab the <html> background color, average the RGB.  If less than 50% bright, it's dark theme.
        return $('body').css('background-color').match(/\((.*)\)/)[1].split(',').slice(0,3).map(str => Number(str)).reduce((a, i) => a+i)/(255*3) < 0.5;
    }


})();