@ -200,7 +200,7 @@
< button id = "uploadfile-button"
< button id = "uploadfile-button"
style="color: white; border: none; text-align: center; cursor: pointer;"
style="color: white; border: none; text-align: center; cursor: pointer;"
title="Upload File">
title="Upload File">
< img src = "./images/uploadfile.png" alt = "Upload" onclick = "func_FileUpload()"
< img src = "./images/uploadfile.png" alt = "Upload"
style="height: 26px; width: 26px; vertical-align: middle; margin-right: 5px;">
style="height: 26px; width: 26px; vertical-align: middle; margin-right: 5px;">
< / button >
< / button >
< button id = "refreshfile-button"
< button id = "refreshfile-button"
@ -273,27 +273,46 @@
< / div >
< / div >
< script >
< script >
var BufferSize = 512; // Buffer 最大 Row 數
var getPythonBufferIntervalTime = 50;
var getPythonStatusIntervalTime = 50;
var receivedCountThreshold = 37500 / getPythonStatusIntervalTime
var dataReceivedCount = 0;
var getPythonBufferSize = 64;
var getBufferStatusTemp = null;
var getBufferSignal = null;
//var displayDataCounter = 0;
var currentRunningFile = ''; // temp running file name
var g_isPythonRunning = 0;
var pythoncode = ""
var currentFileName = '';
// 初始化為 null,確保 intervalId 定義過
var intervalId = null; // Ming add 2024/08/22
var autoScroll = true; // Ming 2024-08-29
var isUserScrolling = false; // Ming 2024-08-29
Status_intervalId = null;
// 取得語系
// 取得語系
func_get_lang_cookie();
func_get_lang_cookie();
// 檔案列表
func_getFileList(null);
// func_getPythonStatus();
// 當網頁加載完成後自動載入 hello.py
// 當網頁加載完成後自動載入 hello.py
window.onload = function() { // Ming add 2024/08/22
window.onload = function() { // Ming add 2024/08/22
// 自動加載並顯示 hello.py 的內容
// 自動加載並顯示 hello.py 的內容
currentFileName = 'hello.py';
currentFileName = 'hello.py';
func_FileGet(currentFileName);
func_FileGet(currentFileName);
// 加載文件列表並選中 hello.py
// 加載文件列表並選中 hello.py
func_getFileList(currentFileName);
func_getFileList(currentFileName);
// func_getPythonBuffer();
// 確認之前執行狀態
func_enablePythonfile();
// 確認有無回傳的資料
func_getPythonStatus();
};
};
var currentFileName = '';
// 初始化為 null,確保 intervalId 定義過
var intervalId = null; // Ming add 2024/08/22
var autoScroll = true; // Ming 2024-08-29
var isUserScrolling = false; // Ming 2024-08-29
// 取得資料夾中的所有檔案名稱
// 取得資料夾中的所有檔案名稱
function func_getFileList(pyFileName) {
function func_getFileList(pyFileName) {
console.log('in get file list');
console.log('in get file list');
@ -350,10 +369,45 @@
}
}
});
});
}
}
// 儲存文件內容
function func_FileSave(file_name) {
var pyFileName = file_name;
pythoncode = $('#code-editor textarea').val();
var encoded = encodeURIComponent(pythoncode);
console.log("func_FileSave pyFileName ---------- ",pyFileName)
$.ajax({
url: "/pythonsave?file=" + pyFileName + "& code=" + encoded,
method: "GET",
async: true,
beforeSend: function (xmlHttp) {
xmlHttp.setRequestHeader("If-Modified-Since", "0");
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
},
success: function (response) {
console.log("response: ", response);
// 如果更新成功,則更新列表
if (response === "File save successfully") {
$('#console').append("Saving successfully");
$('#console').append(' '); // 換行
func_getFileList(pyFileName);
} else {
Swal.fire({
title: 'Error!',
text: response,
icon: 'error',
confirmButtonText: 'OK'
});
}
},
error: function () {
console.warn(retdata);
}
});
return false;
}
// 更新文件內容
// 更新文件內容
function func_FileUpload(file_name) {
function func_FileUpload(file_name) {
var pyFileName = file_name;
var pyFileName = file_name;
var pythoncode = $('#code-editor textarea').val();
var encoded = encodeURIComponent(pythoncode);
var encoded = encodeURIComponent(pythoncode);
console.log("func_FileUpload pyFileName ---------- ",pyFileName)
console.log("func_FileUpload pyFileName ---------- ",pyFileName)
$.ajax({
$.ajax({
@ -396,13 +450,14 @@
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
},
},
success: function (retdata) {
success: function (retdata) {
currentFileName = '';
// 直接刷新文件列表,無需指定 Index 刪除行
// 直接刷新文件列表,無需指定 Index 刪除行
func_getFileList(pyFileNmae); // 2024/08/22 Ming add
console.log("Delete File successfully !!!")
console.log("Delete File successfully !!!")
// $('#console').append(' '); // 換行
$('#console').append(' '); // 換行
$('#console').append(retdata.replace(/\n/g, '< br > '));
$('#console').append(retdata.replace(/\n/g, '< br > '));
currentFileName = 'hello.py';
func_getFileList(currentFileName); // 2024/08/22 Ming add
},
},
error: function () {
error: function () {
console.warn();
console.warn();
@ -412,6 +467,23 @@
// 停止 Python 檔案
// 停止 Python 檔案
function func_stopPython(file_name) {
function func_stopPython(file_name) {
console.log("func_stopPython");
console.log("func_stopPython");
currentRunningFile = ''; //
$('#file-data-grid').datagrid('reload');
var json_data = '{';
json_data += '"system_setting": {';
json_data += '"enable_python_file": "' + 'No python running' + '"';
json_data += '}';
json_data += '}';
func_setconfigfile(json_data);
var rows = $('#file-data-grid').datagrid('getRows'); // 取得所有行的資料
rows.forEach(function (row, index) {
var $row = $('#file-data-grid').datagrid('getPanel').find('tr[datagrid-row-index="' + index + '"]');
$row.find('td[field="filename"] img').attr('src', './images/py.png');
});
$.ajax({
$.ajax({
url: "/stoppython",
url: "/stoppython",
method: "GET",
method: "GET",
@ -441,7 +513,6 @@
function func_convertSpecialChars(retdata) {
function func_convertSpecialChars(retdata) {
// 將特殊字元轉換為 Web 可解析的形式
// 將特殊字元轉換為 Web 可解析的形式
var result = '';
var result = '';
for (var i = 0; i < retdata.length ; i + + ) {
for (var i = 0; i < retdata.length ; i + + ) {
const char = retdata[i];
const char = retdata[i];
@ -469,25 +540,22 @@
data = data.replace(/< br \ / > /g, '< br/> '); // Show < br / >
data = data.replace(/< br \ / > /g, '< br/> '); // Show < br / >
return data.replace(/< /g, "< ").replace(/>/g, "> ");
return data.replace(/< /g, "< ").replace(/>/g, "> ");
}
}
var BufferSize = 512; // Buffer 最大 Row 數
var getPythonBufferIntervalTime = 50;
var getPythonStatusIntervalTime = 50;
var receivedCountThreshold = 1000 / getPythonStatusIntervalTime
var dataReceivedCount = 0;
var getPythonBufferSize = 64;
var getBufferStatusTemp = null;
var getBufferSignal = null;
//var displayDataCounter = 0;
// 取得 Python 執行狀態
// 取得 Python 執行狀態
function func_getPythonStatus(){
function func_getPythonStatus(){
console.log("func_getPythonStatus");
console.log("func_getPythonStatus");
if (Status_intervalId !== null) {
clearInterval(Status_intervalId);
Status_intervalId = null;
}
Status_intervalId = setInterval(function () {
Status_intervalId = setInterval(function () {
$.ajax({
$.ajax({
url: "/pythongetstatus",
url: "/pythongetstatus",
method: "GET",
method: "GET",
async: true,
async: true,
success: function (retdata) {
success: function (retdata) {
console.log("-------------------",currentRunningFile);
updateFileIcon();
// console.log("GET Status Succeeded.");
// console.log("GET Status Succeeded.");
// console.log("--------------dataReceivedCount--------------",dataReceivedCount)
// console.log("--------------dataReceivedCount--------------",dataReceivedCount)
if (dataReceivedCount >= receivedCountThreshold) {
if (dataReceivedCount >= receivedCountThreshold) {
@ -497,35 +565,39 @@
g_isPythonRunning = 0;
g_isPythonRunning = 0;
clearInterval(Status_intervalId);
clearInterval(Status_intervalId);
Status_intervalId = null;
Status_intervalId = null;
// 開啟 「 Run
// 開啟 Run
$("#run-button").prop("disabled", false);
$("#run-button").prop("disabled", false);
}
}
dataReceivedCount = 0;
dataReceivedCount = 0;
}
}
try
if (g_isPythonRunning == 1)
{
{
var existData = $('#console').html();
var existData = $('#console').html();
console.log("Get Status: ", retdata);
console.log("Get Status: ", retdata);
var displayData = func_convertSpecialChars(retdata);
var displayData = func_convertSpecialChars(retdata);
//console.log("Get displayData: ", displayData);
var data = JSON.parse(displayData);
try {
getBufferStatusTemp = parseInt(data['status']);
var data = JSON.parse(displayData);
getBufferSignal = parseInt(data['bufferSignal']);
getBufferStatusTemp = parseInt(data['status']);
console.log('getBufferStatusTemp',getBufferStatusTemp);
getBufferSignal = parseInt(data['bufferSignal']);
console.log('getBufferSignal',getBufferSignal);
console.log('getBufferStatusTemp',getBufferStatusTemp);
console.log('getBufferSignal',getBufferSignal);
} catch (error) {
if (getBufferStatusTemp == 2)
console.log(error);
{
}
func_getPythonBuffer();
if (g_isPythonRunning == 1 || getBufferStatusTemp == 2)
}
{
func_getPythonBuffer();
} catch (error) {
}
console.log(error);
else if (g_isPythonRunning = 0 || getBufferSignal == 0) // python finish or stop need to clear file
}
{
var json_data = '{';
}
json_data += '"system_setting": {';
json_data += '"enable_python_file": "' + 'No python running' + '"';
json_data += '}';
json_data += '}';
func_setconfigfile(json_data);
currentRunningFile = ''
}
dataReceivedCount++;
dataReceivedCount++;
},
},
error: function (xhr, textStatus, errorThrown) {
error: function (xhr, textStatus, errorThrown) {
@ -594,23 +666,45 @@
}
}
}
}
var g_isPythonRunning = 0;
Status_intervalId = null;
// 更改檔案圖示
function updateFileIcon() {
var rows = $('#file-data-grid').datagrid('getRows'); // 取得所有行的資料
rows.forEach(function (row, index) {
var $row = $('#file-data-grid').datagrid('getPanel').find('tr[datagrid-row-index="' + index + '"]');
if (row.filename.endsWith('.py')) { // 只對 .py 檔案進行操作
if (row.filename === currentRunningFile) {
// 如果是正在執行的檔案,顯示播放圖示
$row.find('td[field="filename"] img').attr('src', './images/play.png');
} else {
// 否則,顯示 py.png 圖示
$row.find('td[field="filename"] img').attr('src', './images/py.png');
}
}
});
}
function func_runPython(file_name) {
function func_runPython(file_name) {
func_getPythonStatus();
func_getPythonStatus();
g_isPythonRunning = 1;
currentRunningFile = file_name;
console.log("currentFileName",currentFileName);
var json_data = '{';
json_data += '"system_setting": {';
json_data += '"enable_python_file": "' + currentRunningFile + '"';
json_data += '}';
json_data += '}';
func_setconfigfile(json_data);
console.log("func_runPython");
console.log("func_runPython");
autoScroll = true;
autoScroll = true;
var python_content = $('#code-textarea').val();
var python_content = $('#code-textarea').val();
var json_data = "lifile_liname=" + file_name + ",lipython_licontent=" + python_content;
var json_data = "lifile_liname=" + file_name;
console.log(file_name);
console.log(file_name);
var emptyCount = 0;
updateFileIcon();
var previousData = [];
g_isPythonRunning = 1;
$.ajax({
$.ajax({
url: "/sendpycode",
url: "/sendpycode",
method: "POST",
method: "POST",
@ -625,9 +719,9 @@
success: function (retdata) {
success: function (retdata) {
console.log("[/sendpycode] retdata:", retdata); // 2024/08/21
console.log("[/sendpycode] retdata:", retdata); // 2024/08/21
// resolve(retdata);
// resolve(retdata);
// $('#console').text("Running.....\n");
// $('#console').text("Running.....\n");
},
},
error: function (retdata) {
error: function (retdata) {
console.error("GET request failed: ", retdata); //2024/08/21
console.error("GET request failed: ", retdata); //2024/08/21
// reject(retdata);
// reject(retdata);
@ -636,52 +730,77 @@
return false;
return false;
}
}
function func_setconfigfile(json_data) {
$.ajax({
url: "/setconfigfile",
method: "POST",
async: false,
data: json_data,
contentType: false,
processData: false,
beforeSend: function (xmlHttp) {
xmlHttp.setRequestHeader("If-Modified-Since", "0");
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
//xmlHttp.setRequestHeader("Authorization", "Basic " + btoa("username:password"));
},
success: function () {
//console.info();
},
error: function () {
console.warn();
k_index++;
if (k_index < = 94) {
waitSeconds(500);
func_setconfigfile(json_data);
}
}
});
return false;
}
// enable_python = "Yes" 則開啟上次未執行完成的 python file
function func_enablePythonfile() { // Ming 2024-10-04
$.ajax({
url: "/getconfigfile?ch=all",
type: "GET",
async: true,
beforeSend: function (xmlHttp) {
xmlHttp.setRequestHeader("If-Modified-Since", "0");
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
//xmlHttp.setRequestHeader("Authorization", "Basic " + btoa("username:password"));
},
success: function (retdata) {
var jsonbuf = JSON.parse(retdata);
if ("enable_python_file" in jsonbuf["system_setting"]) {
currentRunningFile = jsonbuf["system_setting"]["enable_python_file"];
g_isPythonRunning = 1;
if (currentRunningFile.endsWith('.py'))
{
$('#console').html("Execute unfinished python file !!");
$('#console').append(' '); // 換行
$('#console').append("Running...");
$('#console').append(' '); // 換行
console.log("找到可執行 Python 檔案 !!!!!!!!!!!!!! ");
}
else
{
console.log("未找到可執行 Python 檔案 !!!!!!!!!!!!!! ");
}
} else {
console.log("未找到 enable_python_file 設置");
}
},
error: function (retdata) {
// setTimeout(func_enablePythonfile(), 3000);
console.warn(retdata);
}
});
}
// 新建檔案
// upload python file (uncomplete)
function addNewFile() {
function addNewFile() {
var $grid = $('#file-data-grid');
var $grid = $('#file-data-grid');
var rows = $grid.datagrid('getRows');
var rows = $grid.datagrid('getRows');
@ -701,6 +820,7 @@
if (e.which == 13) { // 按下 Enter
if (e.which == 13) { // 按下 Enter
var newFileName = $(this).val();
var newFileName = $(this).val();
if (newFileName) {
if (newFileName) {
pythoncode = ""
func_FileUpload(newFileName);
func_FileUpload(newFileName);
}
}
$grid.datagrid('deleteRow', 0);
$grid.datagrid('deleteRow', 0);
@ -724,7 +844,6 @@
}
}
$(document).ready(function () {
$(document).ready(function () {
// 副檔名圖片
// 副檔名圖片
$('#file-data-grid').datagrid({
$('#file-data-grid').datagrid({
title: 'Files',
title: 'Files',
@ -767,14 +886,17 @@
onClickRow: function (rowIndex, rowData) {
onClickRow: function (rowIndex, rowData) {
currentFileName = rowData.filename;
currentFileName = rowData.filename;
func_FileGet(currentFileName);
func_FileGet(currentFileName);
// func_stopPython(); // Ming 2024-09-27 switch file need to stop python
}
}
});
});
// 按 Ctrl + S
// 按 Ctrl + S
$(document).keydown(function (event) {
$(document).keydown(function (event) {
if (event.ctrlKey & & event.which === 83) {
if (event.ctrlKey & & event.which === 83) {
event.preventDefault();
event.preventDefault();
func_FileUpload (currentFileName); // 使用現在的文件名稱進行上傳
func_FileSave (currentFileName); // 使用現在的文件名稱進行上傳
}
}
});
});
// 按 SHIFT + ENTER 執行
// 按 SHIFT + ENTER 執行
@ -789,18 +911,18 @@
}
}
});
});
// 設定 Textarea 可使用 Tab
// 設定 Textarea 可使用 Tab
/* $('#code-textarea').on('keydown', function(e) {
$('#code-textarea').on('keydown', function(e) {
if (e.key === 'Tab') {
if (e.key === 'Tab') {
e.preventDefault();
e.preventDefault();
var start = this.selectionStart;
var start = this.selectionStart;
var end = this.selectionEnd;
var end = this.selectionEnd;
this.value = this.value.substring(0, start) + '\t ' + this.value.substring(end);
this.value = this.value.substring(0, start) + ' ' + ' ' + ' ' + ' ' + this.value.substring(end);
this.selectionStart = this.selectionEnd = start + 1 ;
this.selectionStart = this.selectionEnd = start + 4 ;
}
}
});*/
});
$('#console').on('mousedown', function() {
$('#console').on('mousedown', function() {
isUserScrolling = true;
isUserScrolling = true;
@ -824,7 +946,7 @@
// 按儲存按鈕
// 按儲存按鈕
$('#save-button').click(function (event) {
$('#save-button').click(function (event) {
console.log("Click event triggered on #save-button");
console.log("Click event triggered on #save-button");
func_FileUpload (currentFileName); // 使用現在的文件名稱進行上傳
func_FileSave (currentFileName); // 使用現在的文件名稱進行上傳
});
});
// 按刪除按鈕
// 按刪除按鈕
$('#deletefile-button').click(function () {
$('#deletefile-button').click(function () {
@ -840,7 +962,23 @@
});
});
}
}
});
});
// 上傳按鈕 (只接受 .py 檔案)
$('#uploadfile-button').click(function() {
var fileInput = $('< input type = "file" accept = ".py" > ');
fileInput.click();
fileInput.on('change', function(e) {
var file = e.target.files[0];
if (file) {
var reader = new FileReader();
reader.onload = function(e) {
pythoncode = e.target.result;
var fileName = file.name;
func_FileUpload(fileName);
};
reader.readAsText(file);
}
});
});
// 按執行按鈕
// 按執行按鈕
$('#run-button').click(function () {
$('#run-button').click(function () {
$('#console').append("Running.....\n");
$('#console').append("Running.....\n");