So the web app is built with bootstrap and jquery(for lazy ppl like me). And I can’t believe I’ve spent over two hours on an auto-resizing textarea. It wasn’t a problem to increase the height as typing, but it is a problem when trying to load the element with height according to the content at loading. Since Chrome wouldn’t calculate the scrollHeight of a tab that is not active, I will have to trigger this calculation only when the tab-pane is clicked, otherwise, the textarea will have 0 size.
Triggered when the GPT-2 part is loaded:
$('textarea').each(function() {
if($(this).closest(".tab-pane").hasClass('active')){
this.style.height = (this.scrollHeight) + 'px';
}
}).on('input', function () {
this.style.height = (this.scrollHeight) + 'px';
});
Triggered when a tab is clicked:
$("a.nav-link").click(function(){
$('.tab-pane').each(function(){
if($(this).hasClass('active')) {
$(this).find('textarea').each(function() {
this.style.height = (this.scrollHeight) + 'px';
});
}
});
});
Apart from that, the web app mainly uses jquery load to load content from another page, I’ve decided to design in this way so that I don’t have to refresh the whole page and only load partial content every time an operation is finished.
function refresh(){
$("#status").load("{{ url_for('status') }}");
$("#sentences").load("{{ url_for('sentences') }}");
$("#gpt2").load("{{ url_for('gpt2') }}", function() {
$('textarea').each(function() {
if($(this).closest(".tab-pane").hasClass('active')){
this.style.height = 'auto';
this.style.height = (this.scrollHeight) + 'px';
}
}).on('input', function() {
this.style.height = 'auto';
this.style.height = (this.scrollHeight) + 'px';
});
});
}
And here is a sample submit/button click ajax request:
$("#createVideo").click(function () {
$.ajax({
url: "{{ url_for('create_base') }}",
success: function (message) {
alert(message);
refresh();
},
error: function (response) {
alert(response.responseText);
}
});
});
To modify speaker:
$("#modify").click(function () {
const data = $('tbody tr').map(function() {
let obj = [];
$(this).find('select').each(function() {
obj.push($(this).val());
});
return obj;
}).get();
$.ajax({
type: "POST",
url: "{{ url_for('modify') }}",
contentType: "application/json",
data: JSON.stringify(data),
success: function (message) {
alert(message);
refresh();
},
error: function (response) {
alert(response.responseText);
}
});
});
the data is get from the mapping of the table tag, tr specifically. I obtain a value from the select tag inside tr and store it as a list/array. In the ajax, I use JSON.stringify(data) to send the data.
And to enrich the app experience, there’s a preview image function for animating an image, and it changes according to the select box value.
$("#animate").find("select").each(function(){
let img = $('<img />', {src: "image/" + $(this).val()});
img.insertAfter($(this));
}).on('change', function(){
$(this).parent().find("img").attr('src', "image/" + $(this).val());
});
This appends an img tag after the select tag and the src of the img tag is the select’s value.
$("#view").click(function () {
if (!$(this).parent().has('video').length) {
let video = $('<video />', {
src: "{{ url_for('video') }}",
type: 'video/mp4',
controls: true
});
video.insertAfter($(this));
} else {
$(this).parent().find("video").attr('src', "{{ url_for('video') }}");
}
});
Similar concepts for video preview, but it appends once if it didn’t exist, and replace content if the video tag exists.