|
| 1 | +// Ask the user to go before he goes. |
| 2 | +$(window).bind("beforeunload", function(){ |
| 3 | + if (HuConApp.UnsavedContent) { |
| 4 | + return "Do you really want to go?\nAll your unsaved data will be lost."; |
| 5 | + } |
| 6 | +}); |
| 7 | + |
1 | 8 | // On document ready this function will be called and do a base initialization. |
2 | 9 | $(document).ready(function () { |
3 | 10 | // Update the version information on the ui |
4 | 11 | HuConApp.updateVersion(); |
| 12 | + |
| 13 | + $('#loadModal').modal({allowMultiple: true}); |
| 14 | + $('#newFolderModal').modal('attach events', '#newFolderButton') |
| 15 | +; |
| 16 | +; |
5 | 17 | }); |
6 | 18 |
|
7 | 19 | // Handle some key bindings |
@@ -38,6 +50,15 @@ var HuConApp = {} |
38 | 50 | // Id for JSON-RPC protocol |
39 | 51 | HuConApp.RpcId = 0; |
40 | 52 |
|
| 53 | +// Folder path to save and load on the device |
| 54 | +HuConApp.Folder = ''; |
| 55 | + |
| 56 | +// File extension which is currently used. |
| 57 | +HuConApp.FileExt = ''; |
| 58 | + |
| 59 | +// Remeber any changes after save. |
| 60 | +HuConApp.UnsavedContent = false; |
| 61 | + |
41 | 62 | // Get a new JSON-RPC message data with a new id. |
42 | 63 | HuConApp.getRpcRequest = function() { |
43 | 64 | jsonRpc = {}; |
@@ -311,3 +332,271 @@ HuConApp.buttonModal = function() { |
311 | 332 | $('#buttonModal').modal('show'); |
312 | 333 | $('#buttonEmbed').embed(); |
313 | 334 | } |
| 335 | + |
| 336 | +// Set the breadcrump based on the current folder. |
| 337 | +HuConApp.setBreadcrumb = function(modal) { |
| 338 | + modal.html('<div class="divider">/</div>'); |
| 339 | + |
| 340 | + var folderPath = HuConApp.Folder.split('/'); |
| 341 | + for (var i = 0; i < folderPath.length; i++) { |
| 342 | + if (folderPath[i] != '') { |
| 343 | + modal.append('<div class="section">' + folderPath[i] + '</div>'); |
| 344 | + modal.append('<div class="divider">/</div>'); |
| 345 | + } |
| 346 | + } |
| 347 | +} |
| 348 | + |
| 349 | +// Show a form to create a new folder. |
| 350 | +HuConApp.createNewFolder = function() { |
| 351 | + foldername = $('#folderFilename').val(); |
| 352 | + |
| 353 | + if (foldername != '') { |
| 354 | + var rpcRequest = HuConApp.getRpcRequest(); |
| 355 | + rpcRequest['method'] = 'create_folder'; |
| 356 | + rpcRequest['params'] = HuConApp.Folder + '/' + foldername; |
| 357 | + |
| 358 | + $.ajax('/API', { |
| 359 | + method: 'POST', |
| 360 | + data: JSON.stringify(rpcRequest), |
| 361 | + dataType: 'json', |
| 362 | + error: HuConApp.appendErrorLog |
| 363 | + }); |
| 364 | + |
| 365 | + HuConApp.saveFileModal(HuConApp.Folder); |
| 366 | + } |
| 367 | + console.log($('#folderFilename')); |
| 368 | +} |
| 369 | + |
| 370 | +// Show the file open modal and list all folder. |
| 371 | +HuConApp.openFileModal = function(newFolder) { |
| 372 | + |
| 373 | + if (newFolder != undefined) { |
| 374 | + HuConApp.Folder = newFolder; |
| 375 | + } |
| 376 | + |
| 377 | + HuConApp.setBreadcrumb($('#openBreadcrumb')); |
| 378 | + |
| 379 | + var rpcRequest = HuConApp.getRpcRequest(); |
| 380 | + rpcRequest['method'] = 'get_file_list'; |
| 381 | + rpcRequest['params'] = HuConApp.Folder; |
| 382 | + |
| 383 | + $.ajax('/API', { |
| 384 | + method: 'POST', |
| 385 | + data: JSON.stringify(rpcRequest), |
| 386 | + dataType: 'json', |
| 387 | + success: function(rpcResponse) { |
| 388 | + HuConApp.configureLoadSaveModal(rpcResponse, $('#openFileList'), 'openFileModal', true); |
| 389 | + |
| 390 | + $('#openModal').modal('show'); |
| 391 | + }, |
| 392 | + error: function(request, status, error) { |
| 393 | + HuConApp.Folder = ''; |
| 394 | + HuConApp.appendErrorLog(request, status, error); |
| 395 | + } |
| 396 | + }); |
| 397 | +} |
| 398 | + |
| 399 | +// Hide the open file modal and load the content from the file. |
| 400 | +HuConApp.loadFileFromDevice = function(filename) { |
| 401 | + $('#openModal').modal('hide'); |
| 402 | + $('#consoleLog').html(''); |
| 403 | + |
| 404 | + var rpcRequest = HuConApp.getRpcRequest(); |
| 405 | + rpcRequest['method'] = 'load_file'; |
| 406 | + rpcRequest['params'] = HuConApp.Folder + '/' + filename; |
| 407 | + |
| 408 | + // Store the filename for the save dialog |
| 409 | + $('#saveFilename').val(filename); |
| 410 | + |
| 411 | + $.ajax('/API', { |
| 412 | + method: 'POST', |
| 413 | + data: JSON.stringify(rpcRequest), |
| 414 | + dataType: 'json', |
| 415 | + success: function(rpcResponse) { |
| 416 | + if (HuConApp.isResponseError(rpcResponse)) { |
| 417 | + return |
| 418 | + } |
| 419 | + |
| 420 | + if (rpcResponse['result']) { |
| 421 | + setFileContent(rpcResponse['result']); |
| 422 | + |
| 423 | + HuConApp.appendConsoleLog('File "' + HuConApp.Folder + '/' + filename + '" loaded from local device.', 'green'); |
| 424 | + |
| 425 | + HuConApp.UnsavedContent = false; |
| 426 | + } |
| 427 | + }, |
| 428 | + error: HuConApp.appendErrorLog |
| 429 | + }); |
| 430 | +} |
| 431 | + |
| 432 | +// Show the save file modal and load the file list from the device. |
| 433 | +HuConApp.saveFileModal = function(newFolder) { |
| 434 | + |
| 435 | + // Set the new Folder |
| 436 | + if (newFolder != undefined) { |
| 437 | + HuConApp.Folder = newFolder; |
| 438 | + } |
| 439 | + |
| 440 | + // The example folder is read only, so go back to root on save. |
| 441 | + if (HuConApp.Folder == '/examples') { |
| 442 | + HuConApp.Folder = ''; |
| 443 | + } |
| 444 | + |
| 445 | + HuConApp.setBreadcrumb($('#saveBreadcrumb')); |
| 446 | + |
| 447 | + var rpcRequest = HuConApp.getRpcRequest(); |
| 448 | + rpcRequest['method'] = 'get_file_list'; |
| 449 | + rpcRequest['params'] = HuConApp.Folder; |
| 450 | + |
| 451 | + $.ajax('/API', { |
| 452 | + method: 'POST', |
| 453 | + data: JSON.stringify(rpcRequest), |
| 454 | + dataType: 'json', |
| 455 | + success: function(rpcResponse) { |
| 456 | + HuConApp.configureLoadSaveModal(rpcResponse, $('#saveFileList'), 'saveFileModal', false); |
| 457 | + |
| 458 | + $('#saveModal').modal('show'); |
| 459 | + }, |
| 460 | + error: function(request, status, error) { |
| 461 | + HuConApp.Folder = ''; |
| 462 | + HuConApp.appendErrorLog(request, status, error); |
| 463 | + } |
| 464 | + }); |
| 465 | +} |
| 466 | + |
| 467 | +// Save the file on the device and hide the file save modal. |
| 468 | +HuConApp.saveFileOnDevice = function() { |
| 469 | + $('#saveModal').modal('hide'); |
| 470 | + |
| 471 | + $('#consoleLog').html(''); |
| 472 | + |
| 473 | + // Abort on write within the example folder |
| 474 | + if (HuConApp.Folder == '/examples') { |
| 475 | + HuConApp.appendConsoleLog('The file is not written on device.\nThe examples folder is read only!', 'red'); |
| 476 | + return; |
| 477 | + } |
| 478 | + |
| 479 | + // Get the filename without any extension. |
| 480 | + filename = $('#saveFilename').val(); |
| 481 | + if (filename.substr(-HuConApp.FileExt.length) == HuConApp.FileExt) { |
| 482 | + filename = filename.slice(0, -HuConApp.FileExt.length); |
| 483 | + } |
| 484 | + $('#saveFilename').val(filename + HuConApp.FileExt); |
| 485 | + |
| 486 | + var rpcRequest = HuConApp.getRpcRequest(); |
| 487 | + rpcRequest['method'] = 'save_file'; |
| 488 | + rpcRequest['params'] = {}; |
| 489 | + |
| 490 | + // Store the blockly code if needed |
| 491 | + if (HuConApp.FileExt == '.xml') { |
| 492 | + rpcRequest['params']['filename'] = HuConApp.Folder + '/' + filename + '.xml'; |
| 493 | + rpcRequest['params']['data'] = getBlocklyCode(); |
| 494 | + $.ajax('/API', { |
| 495 | + method: 'POST', |
| 496 | + data: JSON.stringify(rpcRequest), |
| 497 | + dataType: 'json', |
| 498 | + success: function (rpcResponse) { |
| 499 | + if (HuConApp.isResponseError(rpcResponse)) { |
| 500 | + return |
| 501 | + } |
| 502 | + |
| 503 | + HuConApp.appendConsoleLog(rpcResponse['result']); |
| 504 | + }, |
| 505 | + error: HuConApp.appendErrorLog |
| 506 | + }); |
| 507 | + } |
| 508 | + |
| 509 | + // Store the python code |
| 510 | + rpcRequest['params']['filename'] = HuConApp.Folder + '/' + filename + '.py'; |
| 511 | + rpcRequest['params']['data'] = getPythonCode(); |
| 512 | + $.ajax('/API', { |
| 513 | + method: 'POST', |
| 514 | + data: JSON.stringify(rpcRequest), |
| 515 | + dataType: 'json', |
| 516 | + success: function (rpcResponse) { |
| 517 | + if (HuConApp.isResponseError(rpcResponse)) { |
| 518 | + return |
| 519 | + } |
| 520 | + |
| 521 | + HuConApp.appendConsoleLog(rpcResponse['result']); |
| 522 | + }, |
| 523 | + error: HuConApp.appendErrorLog |
| 524 | + }); |
| 525 | + |
| 526 | + HuConApp.UnsavedContent = false; |
| 527 | +} |
| 528 | + |
| 529 | +// Configure the load or save modal correctly. |
| 530 | +HuConApp.configureLoadSaveModal = function(rpcResponse, modal, folderCallback, openFile) { |
| 531 | + // clear the list |
| 532 | + modal.html(''); |
| 533 | + |
| 534 | + if (HuConApp.isResponseError(rpcResponse)) { |
| 535 | + return |
| 536 | + } |
| 537 | + |
| 538 | + folderHtml = ` |
| 539 | + <div onclick="HuConApp.{1}(\'{2}\')" class="item ok"> |
| 540 | + <i class="folder icon"></i> |
| 541 | + <div class="content header">{3}</div> |
| 542 | + </div> |
| 543 | + `; |
| 544 | + |
| 545 | + // Append the folder up if needed. |
| 546 | + if (HuConApp.Folder != '') { |
| 547 | + // Determine the parent folder |
| 548 | + var upperFolder = HuConApp.Folder.slice(0, HuConApp.Folder.lastIndexOf('/')); |
| 549 | + modal.append(HuConApp.formatVarString(folderHtml, folderCallback, upperFolder, '..')); |
| 550 | + } |
| 551 | + |
| 552 | + // Add the folder to the empty list |
| 553 | + for (i=0; i<rpcResponse['result'].length; i++) { |
| 554 | + var filename = rpcResponse['result'][i]; |
| 555 | + if (filename.indexOf('.') === -1) { |
| 556 | + var newFolder = HuConApp.Folder + '/' + filename; |
| 557 | + |
| 558 | + // Do not show the examples folder as possible folder. |
| 559 | + if (!openFile && (newFolder == '/examples')) { |
| 560 | + continue; |
| 561 | + } |
| 562 | + |
| 563 | + modal.append(HuConApp.formatVarString(folderHtml, folderCallback, newFolder, filename)); |
| 564 | + } |
| 565 | + } |
| 566 | + |
| 567 | + fileHtml = ''; |
| 568 | + if (openFile) { |
| 569 | + fileHtml = ` |
| 570 | + <div onclick="HuConApp.loadFileFromDevice(\'{1}\');" class="item ok"> |
| 571 | + <i class="file icon"></i> |
| 572 | + <div class="content header">{1}</div> |
| 573 | + </div> |
| 574 | + `; |
| 575 | + } else { |
| 576 | + fileHtml = ` |
| 577 | + <div onclick="$(\'#saveFilename\').val(\'{1}\');" class="item ok"> |
| 578 | + <i class="file icon"></i> |
| 579 | + <div class="content header">{1}</div> |
| 580 | + </div> |
| 581 | + `; |
| 582 | + } |
| 583 | + |
| 584 | + // Add the files to the empty list |
| 585 | + for (i=0; i<rpcResponse['result'].length; i++) { |
| 586 | + var filename = rpcResponse['result'][i]; |
| 587 | + if (filename.substr(-HuConApp.FileExt.length) === HuConApp.FileExt) { |
| 588 | + modal.append(HuConApp.formatVarString(fileHtml, filename)); |
| 589 | + } |
| 590 | + } |
| 591 | +} |
| 592 | + |
| 593 | +HuConApp.formatVarString = function() { |
| 594 | + var args = [].slice.call(arguments); |
| 595 | + if(this.toString() != '[object Object]') |
| 596 | + { |
| 597 | + args.unshift(this.toString()); |
| 598 | + } |
| 599 | + |
| 600 | + var pattern = new RegExp('{([1-' + args.length + '])}','g'); |
| 601 | + return String(args[0]).replace(pattern, function(match, index) { return args[index]; }); |
| 602 | +} |
0 commit comments