You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1040 lines
44 KiB

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="cache-control" content="max-age=0" />
<meta http-equiv="cache-control" content="no-store" />
<meta http-equiv="expires" content="-1" />
<meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" />
<meta http-equiv="pragma" content="no-cache" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta charset="utf-8" />
<script src="lang.js"></script>
<script src="config.js"></script>
<script src="cookie.min.js"></script>
<script src="lang_cookie.js"></script>
<script src="sweetalert2.min.js"></script>
<script src="jquery_3_2_1.min.js"></script>
<script src="fabric_jquery.easyui.min_compressed_on_nvr.js"></script>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery.easyui.min.js"></script>
<link rel="stylesheet" type="text/css" href="bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="easyui.css">
<link rel="stylesheet" href="css/sweetalert2.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/codemirror.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.7/mode/python/python.min.js"></script>
<script>
window.onerror = function (message, url, linenumber) {
console.log('JavaScript error: ' + message + ' on line ' + linenumber + ' for ' + url);
if (url.search("fabric_jquery.easyui.min_compressed_on_nvr.js") >= 1) {
loadScript("fabric_jquery.easyui.min_compressed_on_nvr.js", function () {
});
}
else if (url.search("jquery_3_2_1.min.js") >= 1) {
loadScript("jquery_3_2_1.min.js", function () {
});
}
else if (url.search("config.js") >= 1) {
loadScript("config.js", function () {
});
}
else if (url.search("cookie.min.js") >= 1) {
loadScript("cookie.min.js", function () {
});
}
else if (url.search("lang.js") >= 1) {
loadScript("lang.js", function () {
});
}
else if (url.search("lang_cookie.js") >= 1) {
loadScript("lang_cookie.js", function () {
});
}
else if (url.search("sweetalert2.min.js") >= 1) {
loadScript("sweetalert2.min.js", function () {
});
}
else if (message.search("slider") >= 1) {
loadScript("fabric_jquery.easyui.min_compressed_on_nvr.js", function () {
});
}
else if (message.search("cookie") >= 1) {
loadScript("cookie.min.js", function () {
});
}
else {
// # If an unknown error occurs, the page is reorganized
// var replaceUrl = 'http://' + window.location.hostname + ':' + GetUrlPort() + '/Aida/python.html';
// window.location.replace(replaceUrl);
}
}
function GetUrlPort() {
var url_href = window.location.href;
console.log("url_href",url_href);
var arr_url = url_href.split(":")[2].split("/")[0];
return arr_url;
}
if (window.history.replaceState) {
window.history.replaceState(null, null, window.location.href);
}
</script>
<style>
* {
box-sizing: border-box;
}
body,
html {
height: 100vh;
margin: 0;
font-family: 'Arial', sans-serif;
}
#sidebar {
width: 310px;
height: 200vh;
background-color: #f9f9f9;
padding: 5px;
max-height: calc(100vh - 20px);
}
@media (max-height: 600px) {
#sidebar {
max-height: 80vh;
}
}
@media (max-height: 400px) {
#sidebar {
max-height: 70vh;
}
}
/*負責裝按鈕的 container*/
#editor-container {
flex-grow: 1;
display: flex;
flex-direction: column;
height: 100vh; /* 確保編輯器容器填滿整個視窗的高度 */
width: 100%; /* 填滿視窗的寬度 */
background-color: #f9f9f9;
}
/*Program container*/
#code-editor {
flex-grow: 1; /* 讓編輯器占據剩餘的空間 */
width: 100%; /* 宽度充满容器 */
height: 100%; /* 高度填滿容器 */
margin-bottom: 10px; /* 可調整底部間距 */
}
/*Program textarea*/
#code-textarea {
width: 100%;
height: 100%; /* 讓編輯器的大小隨著容器調整 */
font-size: 1vw; /* 可以適當調整字體大小,讓它看起來更清楚 */
resize: none; /* 禁用手動調整大小,以便由容器控制 */
}
/*Messege textarea*/
#console {
height: 50vh;
padding: 10px;
border: 2px solid #ccc;
font-size: 1vw;
overflow-x: auto;
overflow-y: auto;
flex-grow: 1;
}
#code-editor, #console {
flex-grow: 1; /* 讓這些元素自動根據剩餘空間調整大小 */
}
.editor-container {
font-size: 1vw;
font-weight: normal;
margin-left: 15px;
margin-top: 10px;
line-height: normal;
}
.container {
display: flex;
height: 100vh;
}
.console-container {
font-size: 1vw;
font-weight: normal;
margin-left: 15px;
margin-bottom: 5px;
line-height: normal;
}
</style>
</head>
<body>
<div class="progress" style="background-color:white">
<div class="progress-bar progress-bar-striped" style="min-width: 20px;visibility:hidden;"></div>
</div>
<div style="border:1px gray solid;padding:5px;margin:5px 5px 5px 5px;height: 560px;">
<div id="container" style="height: 100vh; display: flex;">
<div id="sidebar" style="background-color: #f9f9f9;">
<div style="padding: 10px;">
<input type="text" id="search-box" placeholder="Search"
style="width: 108%; height: 40px; border-radius: 5px; border: 1px solid #ccc;margin-right: 0; align-self: start; position: relative; left: -10px;">
</div>
<div id="file-results"></div>
<div style="display: flex; justify-content: space-between;">
<button id="uploadfile-button"
style="color: white; border: none; text-align: center; cursor: pointer;"
title="Upload File">
<img src="./images/uploadfile.png" alt="Upload"
style="height: 26px; width: 26px; vertical-align: middle; margin-right: 5px;">
</button>
<button id="refreshfile-button"
style="color: white; border: none; text-align: center; cursor: pointer;"
title="Refresh">
<img src="./images/refreshfile.png" alt="refresh" onclick="func_getFileList(null)"
style="height: 26px; width: 26px; vertical-align: middle; margin-right: 5px;">
</button>
<button id="addfile-button"
style="color: white; border: none; text-align: center; cursor: pointer;"
title="New File">
<img src="./images/addfile.png" alt="add" onclick="addNewFile()"
style="height: 26px; width: 26px; vertical-align: middle; margin-right: 5px;">
</button>
<button id="deletefile-button"
style="color: white; border: none; text-align: center; cursor: pointer;"
title="Delete File">
<img src="./images/deletefile.png" alt="delete" onclick=""
style="height: 26px; width: 26px; vertical-align: middle; margin-right: 5px;">
</button>
</div>
<table id="file-data-grid" style="height: 460px;">
</table>
</div>
<div id="editor-container" style="overflow: auto;">
<div id="btn"
style="display: flex; justify-content: flex-end; background-color: #f0f0f0; padding: 5px;">
<button id="run-button" style="color: white; border: none; text-align: center; cursor: pointer;"
title="Run">
<img src="./images/play.png" alt="Run" onclick=""
style="height: 26px; width: 26px; vertical-align: middle; margin-right: 5px;">
</button>
<button id="stop-button" style="color: white; border: none; text-align: center; cursor: pointer;"
title="Stop" onclick="">
<img src="./images/stop.png" alt="stop" onclick=""
style="height: 26px; width: 26px; vertical-align: middle; margin-right: 5px;">
</button>
<button id="save-button" style="color: white; border: none; text-align: center; cursor: pointer;"
title="Save">
<img src="./images/save.png" alt="Save" onclick=""
style="height: 26px; width: 26px; vertical-align: middle; margin-right: 5px;">
</button>
<button id="delete-button" style="color: white; border: none; text-align: center; cursor: pointer;"
title="Clear File">
<img src="./images/delete.png" alt="ClearFile" onclick=""
style="height: 26px; width: 26px; vertical-align: middle; margin-right: 5px;">
</button>
<button id="ClearConsole-button" style="color: white; border: none; text-align: center; cursor: pointer;"
title="Clear Console">
<img src="./images/clear.png" alt="ClearConsole" onclick=""
style="height: 26px; width: 26px; vertical-align: middle; margin-right: 5px;">
</button>
</div>
<div class="editor-container">
<label for="code-textarea">Program</label>
</div>
<div id="code-editor" style="overflow: auto;">
<textarea id="code-textarea" tabindex="0"></textarea>
</div>
<div class="console-container">
<label for="console">Message</label>
</div>
<textarea id="console" readonly='true'></textarea>
</div>
</div>
</div>
<script>
var fileArray = [];
var BufferSize = 512; // Buffer 最大 Row 數
var getPythonBufferIntervalTime = 50;
var getPythonStatusIntervalTime = 50;
var receivedCountThreshold = 37500 / getPythonStatusIntervalTime // 約等於 15 秒
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();
// 當網頁加載完成後自動載入 hello.py
window.onload = function() { // Ming add 2024/08/22
// 自動加載並顯示 hello.py 的內容
currentFileName = 'hello.py';
func_FileGet(currentFileName);
// 加載文件列表並選中 hello.py
func_getFileList(currentFileName);
// 確認之前執行狀態
func_enablePythonfile();
// 確認有無回傳的資料
func_getPythonStatus();
};
// 初始化 CodeMirror
var editor = CodeMirror.fromTextArea(document.getElementById('code-textarea'), {
lineNumbers: true,
mode: "python",
theme: "default",
lineWrapping: true,
indentUnit: 4,
matchBrackets: true
});
// 動態調整大小,使其適應容器
function resizeEditor() {
editor.setSize("100%", "100%");
}
// 動態設置編輯器的樣式
editor.getWrapperElement().style.fontSize = '1.0vw'; // 使用相對單位 'vw' 來設定字體大小,隨著視窗大小改變
// 初次加載時調整大小
resizeEditor();
// 當視窗大小改變時自動調整編輯器大小
window.addEventListener('resize', function() {
resizeEditor();
});
// 取得資料夾中的所有檔案名稱
function func_getFileList(pyFileName) {
console.log('in get file list');
$.ajax({
url: "/python?getfilelist=all",
type: "GET",
beforeSend: function (xmlHttp) {
xmlHttp.setRequestHeader("If-Modified-Since", "0");
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
},
success: function (retdata) {
var data;
if (typeof retdata === 'string') {
data = JSON.parse(retdata);
} else {
data = retdata;
}
var fileList = data.file_list;
fileArray = Object.values(fileList); // 儲存所有 python 檔名
updateDataGrid(fileArray); // 更新顯示的檔案列表
if (pyFileName != null) {
selectFileInDataGrid(pyFileName); // 此時 fileList 已包含新文件
}
},
error: function (retdata) {
console.warn(retdata);
}
});
}
// 更新 Files 列表
function updateDataGrid(files) {
var dataForGrid = files.map(function (filename) {
return {
filename: filename,
lastModified: 'Not available'
};
});
$('#file-data-grid').datagrid('loadData', dataForGrid);
}
// 查看 Search box 有無輸入
document.getElementById('search-box').addEventListener('input', function () {
var searchTerm = this.value.toLowerCase(); // 將輸入的內容轉為小寫
var filteredFiles = fileArray.filter(function (file) {
return file.toLowerCase().includes(searchTerm); // 根據輸入進行過濾
});
updateDataGrid(filteredFiles);
});
// 取得文件內容
function func_FileGet(file_name) {
var reqFileNmae = file_name;
$.ajax({
url: "/pythonget?file=" + reqFileNmae,
type: "GET",
async: true,
beforeSend: function (xmlHttp) {
xmlHttp.setRequestHeader("If-Modified-Since", "0");
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
},
success: function (retdata) {
editor.setValue(retdata);
},
error: function (retdata) {
console.warn(retdata);
}
});
}
// 儲存文件內容
function func_FileSave(file_name) {
var pyFileName = file_name;
pythoncode = editor.getValue();
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('&#13;&#10;'); // 換行
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) {
var pyFileName = file_name;
var encoded = encodeURIComponent(pythoncode);
console.log("func_FileUpload pyFileName ---------- ",pyFileName)
$.ajax({
url: "/pythonupload?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 uploaded successfully") {
func_getFileList(pyFileName);
} else {
Swal.fire({
title: 'Error!',
text: response,
icon: 'error',
confirmButtonText: 'OK'
});
}
},
error: function () {
console.warn(retdata);
}
});
return false;
}
// 刪除檔案
function func_FileDelete(file_name) {
var pyFileNmae = file_name;
$.ajax({
url: "/pythondelete?file=" + pyFileNmae,
method: "GET",
async: true,
beforeSend: function (xmlHttp) {
xmlHttp.setRequestHeader("If-Modified-Since", "0");
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
},
success: function (retdata) {
// 直接刷新文件列表,無需指定 Index 刪除行
console.log("Delete File successfully !!!")
$('#console').append('&#13;&#10;'); // 換行
$('#console').append(retdata.replace(/\n/g, '<br>'));
currentFileName = 'hello.py';
func_getFileList(currentFileName); // 2024/08/22 Ming add
},
error: function () {
console.warn();
}
});
}
// 停止 Python 檔案
function func_stopPython(file_name) {
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);
$.ajax({
url: "/stoppython",
method: "GET",
async: true,
success: function (retdata) {
clearInterval(Status_intervalId);
$('#console').append('&#13;&#10;'); // 換行
$('#console').append(retdata.replace(/\n/g, '<br>'));
$('#console').append('&#13;&#10;'); // 換行
// 根據 autoScroll 開關自動滾動 Ming 2024-09-13
if (autoScroll) {
var textarea = $('#console')[0];
textarea.scrollTop = textarea.scrollHeight;
}
},
error: function (retdata) {
console.warn(retdata);
}
});
return false;
}
function func_convertSpecialChars(retdata) {
// 將特殊字元轉換為 Web 可解析的形式
var result = '';
for (var i = 0; i < retdata.length; i++) {
const char = retdata[i];
switch (char) {
case '\b':
// 刪除結果中的前一個字元
result = result.slice(0, -1);
break;
case '\r':
// 回到該行的開頭,可以將當前行的內容清空
result = result.replace(/.*$/, ''); // 清空當前行的內容
break;
case '\n':
result += '&#13;&#10;'; // newline for textarea
break;
default:
result += char; // 其他字元保留原樣
break;
}
}
return result;
}
function func_checkSpecialChar(data) {
data = data.replace(/<br\/>/g, '&lt;br/&gt;'); // Show <br/>
return data.replace(/</g, "&#60;").replace(/>/g, "&#62;");
}
// 取得 Python 執行狀態
function func_getPythonStatus(){
console.log("func_getPythonStatus");
if (Status_intervalId !== null) {
clearInterval(Status_intervalId);
Status_intervalId = null;
}
Status_intervalId = setInterval(function () {
$.ajax({
url: "/pythongetstatus",
method: "GET",
async: true,
success: function (retdata) {
console.log("-------------------",currentRunningFile);
updateFileIcon();
// console.log("GET Status Succeeded.");
// console.log("--------------dataReceivedCount--------------",dataReceivedCount)
// every 15 second to check PythonRunning status
if (dataReceivedCount >= receivedCountThreshold) {
if (getBufferStatusTemp == 5 && getBufferSignal == 0)
{
g_isPythonRunning = 0;
clearInterval(Status_intervalId);
Status_intervalId = null;
// 開啟 Run
$("#run-button").prop("disabled", false);
}
dataReceivedCount = 0;
}
try
{
var existData = $('#console').html();
console.log("Get Status: ", retdata);
var displayData = func_convertSpecialChars(retdata);
var data = JSON.parse(displayData);
getBufferStatusTemp = parseInt(data['status']);
getBufferSignal = parseInt(data['bufferSignal']);
console.log('getBufferStatusTemp',getBufferStatusTemp);
console.log('getBufferSignal',getBufferSignal);
console.log("g_isPythonRunning",g_isPythonRunning);
} catch (error) {
console.log(error);
}
if (g_isPythonRunning == 1 || getBufferStatusTemp == 2)
{
func_getPythonBuffer();
}
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 = ''
$("#run-button").prop("disabled", false);
}
dataReceivedCount++;
},
error: function (xhr, textStatus, errorThrown) {
if (textStatus === "timeout") {
console.error("Request timed out.");
} else {
console.error("Failed to fetch data:", errorThrown);
}
clearInterval(Status_intervalId); // 在錯誤情況下清除定時器
}
});
}, getPythonStatusIntervalTime);
}
// 取得 Python 結果
function func_getPythonBuffer() {
console.log("func_getPythonBuffer() start");
try {
$.ajax({
url: "/pythongetbuffer?buffersize=" + getPythonBufferSize.toString(),
method: "GET",
async: true,
success: function (retdata) {
// console.log("GET request succeeded.");
var existData = $('#console').html();
// console.log("Get Data: ", retdata);
console.log("Get Data:", JSON.stringify(retdata));
// $('#console').append(retdata);
displayData = func_checkSpecialChar(retdata);
console.log("Get displayData",JSON.stringify(displayData));
$('#console').append(displayData);
// 根據 autoScroll 開關自動滾動 Ming 2024-08-29
if (autoScroll) {
var textarea = $('#console')[0];
textarea.scrollTop = textarea.scrollHeight;
}
},
error: function (xhr, textStatus, errorThrown) {
if (textStatus === "timeout") {
console.error("Request timed out.");
} else {
console.error("Failed to fetch data:", errorThrown);
}
}
});
} catch (error) {
console.log(error);
}
}
// 更改檔案圖示
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) {
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");
autoScroll = true;
var python_content = editor.getValue();
var json_data = "lifile_liname=" + file_name;
console.log(file_name);
updateFileIcon();
$.ajax({
url: "/sendpycode",
method: "POST",
async: true,
data: json_data,
contentType: false,
processData: false,
beforeSend: function (xmlHttp) {
xmlHttp.setRequestHeader("If-Modified-Since", "0");
xmlHttp.setRequestHeader("Cache-Control", "no-cache");
},
success: function (retdata) {
console.log("[/sendpycode] retdata:", retdata); // 2024/08/21
// resolve(retdata);
// $('#console').text("Running.....\n");
g_isPythonRunning = 0;
},
error: function (retdata) {
console.error("GET request failed: ", retdata); //2024/08/21
// reject(retdata);
}
});
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('&#13;&#10;'); // 換行
$('#console').append("Running...");
$('#console').append('&#13;&#10;'); // 換行
console.log("find enable python file !!!!!!!!!!!!!! ");
}
else
{
console.log("not found enable python file !!!!!!!!!!!!!! ");
}
} else {
console.log("not found enable python setting");
}
},
error: function (retdata) {
// setTimeout(func_enablePythonfile(), 3000);
console.warn(retdata);
}
});
}
// 新建檔案
function addNewFile() {
var $grid = $('#file-data-grid');
var rows = $grid.datagrid('getRows');
if (rows.length > 0 && rows[0].isNew) {
return;
}
// 增加輸入欄位在最上面
$grid.datagrid('insertRow', {
index: 0,
row: { filename: '<input type="text" class="new-file-name" placeholder="Enter new file name">', isNew: true }
});
$grid.datagrid('selectRow', 0);
$('.new-file-name').on('keypress', function (e) {
if (e.which == 13) { // 按下 Enter
var newFileName = $(this).val();
if (newFileName) {
pythoncode = ""
func_FileUpload(newFileName);
}
$grid.datagrid('deleteRow', 0);
}
});
}
// 自動選擇列表中的某個文件
function selectFileInDataGrid(fileName) {
var $grid = $('#file-data-grid');
var rows = $grid.datagrid('getRows');
for (var i = 0; i < rows.length; i++) {
if (rows[i].filename === fileName) {
$grid.datagrid('selectRow', i);
currentFileName = rows[i].filename;
func_FileGet(currentFileName);
break;
}
}
}
$(document).ready(function () {
// 副檔名圖片
$('#file-data-grid').datagrid({
title: 'Files',
columns: [[
{
field: 'filename',
title: 'Name',
width: 460,
formatter: function (value, row, index) {
var icon = '<img src="./images/file.png" style="height:16px; width:16px;"/>';
if (value.endsWith('.py')) {
icon = '<img src="./images/py.png" style="height:16px; width:16px;"/>';
} else if (value.endsWith('.html')) {
icon = '<img src="./images/html.png" style="height:16px; width:16px;"/>';
} else if (value.endsWith('.js')) {
icon = '<img src="./images/js.png" style="height:16px; width:16px;"/>';
} else if (value.endsWith('.bin')) {
icon = '<img src="./images/bin.png" style="height:16px; width:16px;"/>';
} else if (value.endsWith('.png')) {
icon = '<img src="./images/png.png" style="height:16px; width:16px;"/>';
} else if (value.endsWith('.jpg')) {
icon = '<img src="./images/jpg.png" style="height:16px; width:16px;"/>';
} else if (value.endsWith('.json')) {
icon = '<img src="./images/json.png" style="height:16px; width:16px;"/>';
} else if (value.endsWith('.zip') || value.endsWith('.rar') || value.endsWith('.7z')) {
icon = '<img src="./images/zip.png" style="height:16px; width:16px;"/>';
}
return icon + ' ' + value;
}
}
]],
singleSelect: true,
fitColumns: false, // This will fit the columns to the grid width
nowrap: true // This will prevent wrapping in a cell and possibly remove the need for horizontal scrolling
});
// 選擇某檔案時,更新當前文件內容
$('#file-data-grid').datagrid({
onClickRow: function (rowIndex, rowData) {
currentFileName = rowData.filename;
func_FileGet(currentFileName);
// func_stopPython(); // Ming 2024-09-27 switch file need to stop python
}
});
// Ctrl + S 保存
editor.on('keydown', function (instance, event) {
if (event.ctrlKey && event.which === 83) {
event.preventDefault();
func_FileSave(currentFileName); // 使用現在的文件名稱進行上傳
}
});
// Shift + Enter 執行
editor.on('keydown', function (instance, event) {
if (event.shiftKey && event.which === 13) {
event.preventDefault();
console.log("Now Running:", currentFileName);
// 禁用「Run」,防止連續點擊
$("#run-button").prop("disabled", true);
func_runPython(currentFileName); // 使用現在的文件名稱執行 Python
}
});
// 設定 Textarea 可使用 Tab
editor.setOption("extraKeys", {
Tab: function(cm) {
cm.replaceSelection(" ", "end");
}
});
$('#console').on('mousedown', function() {
isUserScrolling = true;
});
$('#console').on('mouseup mouseleave', function() {
isUserScrolling = false;
});
// Textarea 自動滾動 Ming 2024-08-29
$('#console').on('scroll', function() {
var textarea = this;
// 用滑鼠滾動條控制
if (isUserScrolling) {
if (textarea.scrollTop + textarea.clientHeight < textarea.scrollHeight) {
autoScroll = false;
} else {
autoScroll = true;
}
}
});
// 按儲存按鈕
$('#save-button').click(function (event) {
console.log("Click event triggered on #save-button");
func_FileSave(currentFileName); // 使用現在的文件名稱進行上傳
});
// 按刪除按鈕
$('#deletefile-button').click(function () {
if (currentFileName) {
Swal.fire({
title: MESSAGE108 + "<" + currentFileName + ">",
icon: 'warning',
showCancelButton: true,
}).then((result) => {
if (result.isConfirmed) {
func_FileDelete(currentFileName);
}
});
}
});
// 上傳按鈕 (只接受 .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 () {
$('#console').append("Running.....\n");
var startTime = Date.now(); // 記錄開始時間
// 禁用「Run」,防止連續點擊
$("#run-button").prop("disabled", true);
func_runPython(currentFileName); // 使用現在文件執行 Python
// StartGetPythonBuffer(currentFileName)
});
// 按暫停按鈕
$('#stop-button').click(function () {
// 開啟 「Run」& Func_funpython
$("#run-button").prop("disabled", false);
func_stopPython(currentFileName)
});
// 按清除 Console 按鈕
$('#ClearConsole-button').click(function () {
//displayDataCounter = 0;
$('#console').html('');
});
// 將程式碼清空並上傳
$('#delete-button').click(function () {
console.log("");
Swal.fire({
title: MESSAGE109,
icon: 'warning',
showCancelButton: true,
}).then((result) => {
if (result.isConfirmed) {
// 清空 textarea 的内容
//var codeContent = editor.getValue();
editor.setValue("");
func_FileUpload(currentFileName);
}
});
});
});
</script>
</body>
</html>