commit 13/10/2025

Soundbank menu
This commit is contained in:
2025-10-13 15:55:09 +07:00
parent e78fb932b2
commit 110e6d5b12
20 changed files with 874 additions and 47 deletions

629
html/webpage/assets/css/select2.min.css vendored Normal file
View File

@@ -0,0 +1,629 @@
.select2-container {
box-sizing: border-box;
display: inline-block;
margin: 0;
position: relative;
vertical-align: middle;
}
.select2-container .select2-selection--single {
box-sizing: border-box;
cursor: pointer;
display: block;
height: 28px;
user-select: none;
-webkit-user-select: none;
}
.select2-container .select2-selection--single .select2-selection__rendered {
display: block;
padding-left: 8px;
padding-right: 20px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.select2-container .select2-selection--single .select2-selection__clear {
position: relative;
}
.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
padding-right: 8px;
padding-left: 20px;
}
.select2-container .select2-selection--multiple {
box-sizing: border-box;
cursor: pointer;
display: block;
min-height: 32px;
user-select: none;
-webkit-user-select: none;
}
.select2-container .select2-selection--multiple .select2-selection__rendered {
display: inline-block;
overflow: hidden;
padding-left: 8px;
text-overflow: ellipsis;
white-space: nowrap;
}
.select2-container .select2-search--inline {
float: left;
}
.select2-container .select2-search--inline .select2-search__field {
box-sizing: border-box;
border: none;
font-size: 100%;
margin-top: 5px;
padding: 0;
}
.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
-webkit-appearance: none;
}
.select2-dropdown {
background-color: white;
border: 1px solid #aaa;
border-radius: 4px;
box-sizing: border-box;
display: block;
position: absolute;
left: -100000px;
width: 100%;
z-index: 1051;
}
.select2-results {
display: block;
}
.select2-results__options {
list-style: none;
margin: 0;
padding: 0;
}
.select2-results__option {
padding: 6px;
user-select: none;
-webkit-user-select: none;
}
.select2-results__option[aria-selected] {
cursor: pointer;
}
.select2-container--open .select2-dropdown {
left: 0;
}
.select2-container--open .select2-dropdown--above {
border-bottom: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.select2-container--open .select2-dropdown--below {
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.select2-search--dropdown {
display: block;
padding: 4px;
}
.select2-search--dropdown .select2-search__field {
padding: 4px;
width: 100%;
box-sizing: border-box;
}
.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
-webkit-appearance: none;
}
.select2-search--dropdown.select2-search--hide {
display: none;
}
.select2-close-mask {
border: 0;
margin: 0;
padding: 0;
display: block;
position: fixed;
left: 0;
top: 0;
min-height: 100%;
min-width: 100%;
height: auto;
width: auto;
opacity: 0;
z-index: 99;
background-color: #fff;
filter: alpha(opacity=0);
}
.select2-hidden-accessible {
border: 0 !important;
clip: rect(0 0 0 0) !important;
-webkit-clip-path: inset(50%) !important;
clip-path: inset(50%) !important;
height: 1px !important;
overflow: hidden !important;
padding: 0 !important;
position: absolute !important;
width: 1px !important;
white-space: nowrap !important;
}
.select2-container--default .select2-selection--single {
background-color: #fff;
border: 1px solid #aaa;
border-radius: 4px;
}
.select2-container--default .select2-selection--single .select2-selection__rendered {
color: #444;
line-height: 28px;
}
.select2-container--default .select2-selection--single .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
}
.select2-container--default .select2-selection--single .select2-selection__placeholder {
color: #999;
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
height: 26px;
position: absolute;
top: 1px;
right: 1px;
width: 20px;
}
.select2-container--default .select2-selection--single .select2-selection__arrow b {
border-color: #888 transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
left: 50%;
margin-left: -4px;
margin-top: -2px;
position: absolute;
top: 50%;
width: 0;
}
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear {
float: left;
}
.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow {
left: 1px;
right: auto;
}
.select2-container--default.select2-container--disabled .select2-selection--single {
background-color: #eee;
cursor: default;
}
.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
display: none;
}
.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #888 transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--default .select2-selection--multiple {
background-color: white;
border: 1px solid #aaa;
border-radius: 4px;
cursor: text;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered {
box-sizing: border-box;
list-style: none;
margin: 0;
padding: 0 5px;
width: 100%;
}
.select2-container--default .select2-selection--multiple .select2-selection__rendered li {
list-style: none;
}
.select2-container--default .select2-selection--multiple .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
margin-top: 5px;
margin-right: 10px;
padding: 1px;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background-color: #e4e4e4;
border: 1px solid #aaa;
border-radius: 4px;
cursor: default;
float: left;
margin-right: 5px;
margin-top: 5px;
padding: 0 5px;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
color: #999;
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-right: 2px;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
color: #333;
}
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline {
float: right;
}
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
margin-left: 5px;
margin-right: auto;
}
.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
margin-left: 2px;
margin-right: auto;
}
.select2-container--default.select2-container--focus .select2-selection--multiple {
border: solid black 1px;
outline: 0;
}
.select2-container--default.select2-container--disabled .select2-selection--multiple {
background-color: #eee;
cursor: default;
}
.select2-container--default.select2-container--disabled .select2-selection__choice__remove {
display: none;
}
.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.select2-container--default .select2-search--dropdown .select2-search__field {
border: 1px solid #aaa;
}
.select2-container--default .select2-search--inline .select2-search__field {
background: transparent;
border: none;
outline: 0;
box-shadow: none;
-webkit-appearance: textfield;
}
.select2-container--default .select2-results > .select2-results__options {
max-height: 200px;
overflow-y: auto;
}
.select2-container--default .select2-results__option[role=group] {
padding: 0;
}
.select2-container--default .select2-results__option[aria-disabled=true] {
color: #999;
}
.select2-container--default .select2-results__option[aria-selected=true] {
background-color: #ddd;
}
.select2-container--default .select2-results__option .select2-results__option {
padding-left: 1em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__group {
padding-left: 0;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option {
margin-left: -1em;
padding-left: 2em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -2em;
padding-left: 3em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -3em;
padding-left: 4em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -4em;
padding-left: 5em;
}
.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
margin-left: -5em;
padding-left: 6em;
}
.select2-container--default .select2-results__option--highlighted[aria-selected] {
background-color: #5897fb;
color: white;
}
.select2-container--default .select2-results__group {
cursor: default;
display: block;
padding: 6px;
}
.select2-container--classic .select2-selection--single {
background-color: #f7f7f7;
border: 1px solid #aaa;
border-radius: 4px;
outline: 0;
background-image: -webkit-linear-gradient(top, #fff 50%, #eee 100%);
background-image: -o-linear-gradient(top, #fff 50%, #eee 100%);
background-image: linear-gradient(to bottom, #fff 50%, #eee 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0);
}
.select2-container--classic .select2-selection--single:focus {
border: 1px solid #5897fb;
}
.select2-container--classic .select2-selection--single .select2-selection__rendered {
color: #444;
line-height: 28px;
}
.select2-container--classic .select2-selection--single .select2-selection__clear {
cursor: pointer;
float: right;
font-weight: bold;
margin-right: 10px;
}
.select2-container--classic .select2-selection--single .select2-selection__placeholder {
color: #999;
}
.select2-container--classic .select2-selection--single .select2-selection__arrow {
background-color: #ddd;
border: none;
border-left: 1px solid #aaa;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
height: 26px;
position: absolute;
top: 1px;
right: 1px;
width: 20px;
background-image: -webkit-linear-gradient(top, #eee 50%, #ccc 100%);
background-image: -o-linear-gradient(top, #eee 50%, #ccc 100%);
background-image: linear-gradient(to bottom, #eee 50%, #ccc 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0);
}
.select2-container--classic .select2-selection--single .select2-selection__arrow b {
border-color: #888 transparent transparent transparent;
border-style: solid;
border-width: 5px 4px 0 4px;
height: 0;
left: 50%;
margin-left: -4px;
margin-top: -2px;
position: absolute;
top: 50%;
width: 0;
}
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear {
float: left;
}
.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow {
border: none;
border-right: 1px solid #aaa;
border-radius: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
left: 1px;
right: auto;
}
.select2-container--classic.select2-container--open .select2-selection--single {
border: 1px solid #5897fb;
}
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {
background: transparent;
border: none;
}
.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {
border-color: transparent transparent #888 transparent;
border-width: 0 4px 5px 4px;
}
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0;
background-image: -webkit-linear-gradient(top, #fff 0%, #eee 50%);
background-image: -o-linear-gradient(top, #fff 0%, #eee 50%);
background-image: linear-gradient(to bottom, #fff 0%, #eee 50%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0);
}
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {
border-bottom: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
background-image: -webkit-linear-gradient(top, #eee 50%, #fff 100%);
background-image: -o-linear-gradient(top, #eee 50%, #fff 100%);
background-image: linear-gradient(to bottom, #eee 50%, #fff 100%);
background-repeat: repeat-x;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0);
}
.select2-container--classic .select2-selection--multiple {
background-color: white;
border: 1px solid #aaa;
border-radius: 4px;
cursor: text;
outline: 0;
}
.select2-container--classic .select2-selection--multiple:focus {
border: 1px solid #5897fb;
}
.select2-container--classic .select2-selection--multiple .select2-selection__rendered {
list-style: none;
margin: 0;
padding: 0 5px;
}
.select2-container--classic .select2-selection--multiple .select2-selection__clear {
display: none;
}
.select2-container--classic .select2-selection--multiple .select2-selection__choice {
background-color: #e4e4e4;
border: 1px solid #aaa;
border-radius: 4px;
cursor: default;
float: left;
margin-right: 5px;
margin-top: 5px;
padding: 0 5px;
}
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {
color: #888;
cursor: pointer;
display: inline-block;
font-weight: bold;
margin-right: 2px;
}
.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {
color: #555;
}
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
float: right;
margin-left: 5px;
margin-right: auto;
}
.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
margin-left: 2px;
margin-right: auto;
}
.select2-container--classic.select2-container--open .select2-selection--multiple {
border: 1px solid #5897fb;
}
.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {
border-top: none;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {
border-bottom: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.select2-container--classic .select2-search--dropdown .select2-search__field {
border: 1px solid #aaa;
outline: 0;
}
.select2-container--classic .select2-search--inline .select2-search__field {
outline: 0;
box-shadow: none;
}
.select2-container--classic .select2-dropdown {
background-color: #fff;
border: 1px solid transparent;
}
.select2-container--classic .select2-dropdown--above {
border-bottom: none;
}
.select2-container--classic .select2-dropdown--below {
border-top: none;
}
.select2-container--classic .select2-results > .select2-results__options {
max-height: 200px;
overflow-y: auto;
}
.select2-container--classic .select2-results__option[role=group] {
padding: 0;
}
.select2-container--classic .select2-results__option[aria-disabled=true] {
color: grey;
}
.select2-container--classic .select2-results__option--highlighted[aria-selected] {
background-color: #3875d7;
color: #fff;
}
.select2-container--classic .select2-results__group {
cursor: default;
display: block;
padding: 6px;
}
.select2-container--classic.select2-container--open .select2-dropdown {
border-color: #5897fb;
}

2
html/webpage/assets/js/select2.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -26,11 +26,7 @@ window.soundbankdata = [];
*/
window.selectedsoundrow = null;
/**
* List of sound files in the soundbank directory, that ends with .wav or .mp3
* @type {string[]}
*/
window.soundbankfiles = [];
/**
* Select2 data source
@@ -97,28 +93,58 @@ function fill_soundbanktablebody(vv) {
$('#tablesize').text("Table Size: " + vv.length);
}
/**
* Reload soundbank files from server
* @param {String} APIURL API URL endpoint (default "SoundBank/")
* Reload soundbank files from server and filter by language, category, and voiceType
* @param {String} language
* @param {String} category
* @param {String} voiceType
*/
function reloadSoundbankFiles(APIURL = "SoundBank/") {
window.soundbankfiles = [];
fetchAPI(APIURL + "ListFiles", "GET", {}, null, (okdata) => {
// okdata is a string contains elements separated by semicolon ;
if (Array.isArray(okdata)) {
window.soundbankfiles = okdata.filter(item => item.trim().length > 0);
// refill select2data
window.select2data = window.soundbankfiles.map((item, index) => ({ id: index + 1, text: item }));
} else console.log("reloadSoundbankFiles: okdata is not array");
}, (errdata) => {
alert("Error loading soundbank files : " + errdata.message);
});
function reloadSoundbankFiles(language, category, voiceType) {
window.select2data = [];
$('#modalpath').empty().trigger('change');
if (language && language.length > 0) {
if (category && category.length > 0) {
if (voiceType && voiceType.length > 0) {
fetchAPI(`ListFiles/${language}/${voiceType}/${category}`, "GET", {}, null, (okdata) => {
console.log("reloadSoundbankFiles: got " + okdata.length + " items");
if (Array.isArray(okdata)){
window.select2data = okdata.map(p => ({id: getFilenameFromPath(p), text: getFilenameFromPath(p)}));
$('#modalpath').select2({
data: window.select2data,
placeholder: 'Select a sound file',
allowClear: true,
width: '100%',
dropdownParent: $('#soundbankmodal')
});
}
}, (errdata) => {
alert("Error loading soundbank files : " + errdata.message);
});
}
}
}
}
function getFilenameFromPath(path) {
if (!path || path.length === 0) return "";
if (path.includes('\\')) {
let parts = path.split('\\');
return parts[parts.length - 1];
} else if (!path.includes('/')) {
let parts = path.split('/');
return parts[parts.length - 1];
}
}
$(document).ready(function () {
console.log("soundbank.js loaded successfully");
reloadSoundbankFiles();
$('#soundbanktablebody').empty();
window.selectedsoundrow = null;
let $btnClear = $('#btnClear');
@@ -137,7 +163,9 @@ $(document).ready(function () {
let $modalcategory = $modal.find('#modalcategory');
let $modallanguage = $modal.find('#modallanguage');
let $modalvoicetype = $modal.find('#modalvoicetype');
let $modalpath = $modal.find('#modalpath');
let selected_category = null;
let selected_language = null;
let selected_voicetype = null;
/**
* Clear soundbank modal inputs
@@ -164,12 +192,8 @@ $(document).ready(function () {
$modalvoicetype.append(new Option(vt, vt));
});
$modalvoicetype.val(null);
// fill modalpath options from soundbankfiles[]
// TODO read https://jeesite.com/front/jquery-select2/4.0/index.htm
console.log("window.select2data has " + window.select2data.length + " items");
$('#modalpath').select2({
data: window.select2data
})
$('#modalpath').select2()
}
reloadSoundBank(APIURL);
@@ -193,14 +217,80 @@ $(document).ready(function () {
});
});
function SetupEventForCategoryLanguageVoiceType() {
$modalcategory.off('change').on('change', function () {
selected_category = $(this).val();
reloadSoundbankFiles(selected_language, selected_category, selected_voicetype);
});
$modallanguage.off('change').on('change', function () {
selected_language = $(this).val();
reloadSoundbankFiles(selected_language, selected_category, selected_voicetype);
});
$modalvoicetype.off('change').on('change', function () {
selected_voicetype = $(this).val();
reloadSoundbankFiles(selected_language, selected_category, selected_voicetype);
});
}
$btnAdd.click(() => {
$modal.modal('show');
clearSoundbankModal();
// event on selection change of language, category, voiceType
SetupEventForCategoryLanguageVoiceType();
// event on Click save button
$modal.off('click.soundbanksave').on('click.soundbanksave', '#soundbanksave', function () {
//TODO Add soundbank save process here
let description = $modaldescription.val().trim();
let tag = $modaltag.val().trim();
let category = $modalcategory.val();
let language = $modallanguage.val();
let voiceType = $modalvoicetype.val();
let path = $('#soundbankmodal #modalpath').val();
if (!description || description.length === 0) {
alert("Description is required");
return;
}
if (!tag || tag.length === 0) {
alert("Tag is required");
return;
}
if (!category || category.length === 0) {
alert("Category is required");
return;
}
if (!language || language.length === 0) {
alert("Language is required");
return;
}
if (!voiceType || voiceType.length === 0) {
alert("Voice Type is required");
return;
}
if (!path || path.length === 0) {
alert("Path is required");
return;
}
$modal.modal('hide');
/**
* @type {SoundBank}
*/
let nsb = {
Description: description,
TAG: tag,
Category: category,
Language: language,
VoiceType: voiceType,
Path: path
}
fetchAPI(APIURL + "Add", "POST", {}, nsb, (okdata) => {
reloadSoundBank(APIURL);
alert("Success add soundbank : " + okdata.message);
}, (errdata) => {
alert("Error add soundbank : " + errdata.message);
});
});
// event on Click close button
$modal.off('click.soundbankclose').on('click.soundbankclose', '#soundbankclose', function () {
@@ -236,27 +326,82 @@ $(document).ready(function () {
/** @type {SoundBank} */
let sb = {
index: cells.eq(0).text(),
description: cells.eq(1).text(),
tag: cells.eq(2).text(),
category: cells.eq(3).text(),
language: cells.eq(4).text(),
voiceType: cells.eq(5).text(),
path: cells.eq(6).text()
Description: cells.eq(1).text(),
TAG: cells.eq(2).text(),
Category: cells.eq(3).text(),
Language: cells.eq(4).text(),
VoiceType: cells.eq(5).text(),
Path: cells.eq(6).text()
}
if (confirm(`Are you sure to edit soundbank [${sb.index}] Description=${sb.description} Tag=${sb.tag}?`)) {
if (confirm(`Are you sure to edit soundbank [${sb.index}] Description=${sb.Description} Tag=${sb.TAG}?`)) {
$modal.modal('show');
$modal.off('hidden.bs.modal').on('hidden.bs.modal', function () {
clearSoundbankModal();
$modalindex.val(sb.index).prop('disabled', true);
$modaldescription.val(sb.Description);
$modaltag.val(sb.TAG);
$modalcategory.val(sb.Category);
$modallanguage.val(sb.Language);
$modalvoicetype.val(sb.VoiceType);
$('#modalpath').val(sb.Path).trigger('change');
// event on Click save button
SetupEventForCategoryLanguageVoiceType();
// event on Click save button
$modal.off('click.soundbanksave').on('click.soundbanksave', '#soundbanksave', function () {
//TODO Add soundbank save process here
let description = $modaldescription.val().trim();
let tag = $modaltag.val().trim();
let category = $modalcategory.val();
let language = $modallanguage.val();
let voiceType = $modalvoicetype.val();
let path = $('#soundbankmodal #modalpath').val();
if (!description || description.length === 0) {
alert("Description is required");
return;
}
if (!tag || tag.length === 0) {
alert("Tag is required");
return;
}
if (!category || category.length === 0) {
alert("Category is required");
return;
}
if (!language || language.length === 0) {
alert("Language is required");
return;
}
if (!voiceType || voiceType.length === 0) {
alert("Voice Type is required");
return;
}
if (!path || path.length === 0) {
alert("Path is required");
return;
}
if (description === sb.Description && tag === sb.TAG && category === sb.Category && language === sb.Language && voiceType === sb.VoiceType && path === sb.Path) {
alert("No changes detected");
return;
}
sb.Description = description;
sb.TAG = tag;
sb.Category = category;
sb.Language = language;
sb.VoiceType = voiceType;
sb.Path = path;
fetchAPI(APIURL + "UpdateByIndex/" + sb.index, "PUT", {}, sb, (okdata) => {
reloadSoundBank(APIURL);
alert("Success update soundbank : " + okdata.message);
}, (errdata) => {
alert("Error update soundbank : " + errdata.message);
});
$modal.modal('hide');
});
// event on Click close button
$modal.off('click.soundbankclose').on('click.soundbankclose', '#soundbankclose', function () {
$modal.modal('hide');
});
});
}
}
});