/** * An object that manages the main toolbar, including the different mode buttons. * This doesn't actually have many responsibilities after the initial load. * * @constructor * @this {BlockPyToolbar} * @param {Object} main - The main BlockPy instance * @param {HTMLElement} tag - The HTML object this is attached to. */ function BlockPyToolbar(main, tag) { this.main = main; this.tag = tag; // Holds the HTMLElement tags for each of the toolbar items this.tags = {}; this.tags.mode_set_text = this.tag.find('.blockpy-mode-set-text'); this.tags.filename_picker = this.tag.find('.blockpy-toolbar-filename-picker'); // Actually set up the toolbar! this.activateToolbar(); } BlockPyToolbar.prototype.notifyFeedbackUpdate = function () { this.tag.find(".blockpy-toolbar-feedback").show().fadeOut(7000); } /** * Register click events for more complex toolbar actions. */ BlockPyToolbar.prototype.activateToolbar = function () { var main = this.main; this.tag.find('.blockpy-run').click(function () { main.components.server.logEvent('editor', 'run') main.components.engine.on_run(); }); this.tags.mode_set_text.click(function () { main.components.server.logEvent('editor', 'text') main.model.settings.editor("Text"); }); this.tag.find('.blockpy-toolbar-reset').click(function () { main.model.programs['__main__'](main.model.programs['starting_code']()); //main.components.editor.updateBlocks(); main.components.server.logEvent('editor', 'reset'); if (main.model.assignment.parsons()) { main.components.editor.blockly.shuffle(); } }); this.tag.find('.blockpy-toolbar-load-sample').click(function () { var blob = null; var xhr = new XMLHttpRequest(); xhr.open("GET", "../20190114_python-blockly_plotting-temp-data.py"); xhr.responseType = "blob"; //force the HTTP response, response-type header to be blob xhr.onload = function () { blob = xhr.response; //xhr.response is now a blob object var fr = new FileReader(); fr.onload = function (e) { main.setCode(e.target.result) main.components.server.logEvent('editor', 'upload') main.components.engine.on_run(); }; fr.readAsText(blob); } xhr.send(); }); this.tag.find('.blockpy-mode-set-blocks').click(function (event) { if (main.model.areBlocksUpdating()) { main.components.server.logEvent('editor', 'blocks') main.model.settings.editor("Blocks"); } else { event.preventDefault(); return false; } }); /*this.tag.find('.blockpy-mode-set-instructor').click(function() { main.model.settings.editor("Instructor"); main.components.server.logEvent('editor', 'instructor') });*/ this.tag.find('.blockpy-mode-set-split').click(function (event) { if (main.model.areBlocksUpdating()) { main.model.settings.editor("Split"); main.components.server.logEvent('editor', 'split') } else { event.preventDefault(); return false; } }); this.tag.find('.blockpy-toolbar-import').click(function () { main.components.corgis.openDialog(); main.components.server.logEvent('editor', 'import') }); this.tag.find('.blockpy-toolbar-history').click(function () { main.components.history.openDialog(); main.components.server.logEvent('editor', 'history') }); var instructorDialog = this.main.model.constants.container.find('.blockpy-instructor-popup'); this.tag.find('.blockpy-toolbar-instructor').click(function () { instructorDialog.modal({ 'backdrop': false }).modal('show'); instructorDialog.draggable({ 'handle': '.modal-title' }); main.components.server.logEvent('editor', 'instructor') }); this.tag.find('.blockpy-toolbar-english').click(function () { main.components.english.openDialog(); main.components.server.logEvent('editor', 'english') }); // var uploadButton = this.tag.find('.blockpy-toolbar-upload'); const uploadButton = $('#fileImport > input'); uploadButton.change(function () { var fr = new FileReader(); var files = uploadButton[0].files; const file = files[0]; Ardublockly.alertExampleMessage( '',Ardublockly.getLocalStr('loadBlockBody'), true,{}); fr.onload = function (e) { main.setCode(e.target.result) main.components.server.logEvent('editor', 'upload') main.components.engine.on_run(); }; fr.readAsText(file); setTimeout(() => { $('#loading').css({'display':'none'}); $('#example_alert').modal('close'); }, 300) $('#sketch_name').val(file.name.match(/(.+).py$/)[1]); uploadButton.val(""); }); const uploadXmlButton = $('#xmlFileImport > input'); uploadXmlButton.change(function () { Ardublockly.handleFileSelect(event, uploadXmlButton[0].files); // var fr = new FileReader(); // var files = uploadXmlButton[0].files; // const file = files[0]; // fr.onload = function (e) { // try { // var xmlfile = Blockly.Xml.textToDom(e.target.result); // blockpy.components.editor.setBlocksFromXml(xmlfile); // } catch (e) { // alert("无效的xml文件"); // } // if (blockpy.components.editor.getBlocksFromXml().childNodes < 1) { // alert("无效的xml文件"); // } // }; // fr.readAsText(file); uploadXmlButton.val(""); }); $('#button_load').click(e => $('#xmlFileImport > input').click()); $('#side_button_load').click(e => $('#xmlFileImport > input').click()); $('#downloadbutton').click(downloadXml); function downloadCode() { var data = main.model.programs['__main__'](); let filename = $('#sketch_name').val(); let reg = new RegExp(/[^a-z0-9]/) // Make safe filename = reg.test(filename) ? filename : filename.replace(/[^a-z0-9]/gi, '_').toLowerCase(); filename = filename + '.py' // Make the data download as a file var blob = new Blob([data], { type: 'text/plain' }); if (window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveBlob(blob, filename); } else { var elem = window.document.createElement('a'); elem.href = window.URL.createObjectURL(blob); elem.download = filename; document.body.appendChild(elem); elem.click(); document.body.removeChild(elem); } main.components.server.logEvent('editor', 'download') } /** * Save blocks as XML file. Note that MSIE 11 does not support * @param {String} filename */ function downloadXml() { var _xml = blockpy.components.editor.getBlocksFromXml(); _xml.setAttribute("type", $("#mode")[0].selectedIndex == 1 ? "AI" : "IoT") var data = Blockly.Xml.domToPrettyText(_xml); let filename = $("#sketch_name").val() != '' ? $("#sketch_name").val() : "未命名"; let reg = new RegExp(/[^a-z0-9]/) // Make safe filename = reg.test(filename) ? filename : filename.replace(/[^a-z0-9]/gi, '_').toLowerCase(); filename = filename + '.xml' var blob = new Blob([data], { type: 'text/plain;charset=utf-8' }); // if (window.navigator.msSaveOrOpenBlob) { // window.navigator.msSaveBlob(blob, filename); // } else { var elem = window.document.createElement('a'); elem.href = window.URL.createObjectURL(blob); elem.download = filename; document.body.appendChild(elem); elem.click(); document.body.removeChild(elem); // } } $("#AIYdownload").click(downloadCode); var downloadButton = this.tag.find('.blockpy-toolbar-download'); downloadButton.click(downloadCode); // $('#button_save').click(downloadXml); // $('#side_button_save').click(downloadXml); this.tag.find('.blockpy-toolbar-filename-picker label').click(function () { main.model.settings.filename($(this).data('filename')) }); $("#aiyModalRun").click(() => { console.log("click now") $("#modal_preload").css("display", "block"); $("#aiyModalRun").addClass("disabled"); setTimeout(() => { $("#modal_preload").css("display", "none"); $("#aiyModalRun").removeClass("disabled"); }, 2000) }) $("#aiyModalStop").click(() => { console.log("click to stop") }) /** * Bind a function to a drag event. * drag a file into the webpage * @param {!Element|string} el drag element or ID thereof. * @param {!function} func1 Drag over handler to bind. * @param {!function} func2 Drag leave handler to bind. * @private */ function binddrag_(el, func1, func2) { if (typeof el == 'string') { el = document.getElementById(el); } el.addEventListener('dragenter', func1); el.addEventListener('dragover', (e) => { e.stopPropagation(); e.preventDefault(); }); el.addEventListener('dragleave', func2); } /** * Bind a function to a drop event. * drop a file into the webpage * @param {!Element|string} el drag element or ID thereof. * @private */ function binddrop_(el, func) { if (typeof el == 'string') { el = document.getElementById(el); } el.addEventListener('drop', func); } /** * handle File Select by drag from local folder */ function handleFileSelect(e) { // e.stopPropagation(); // e.preventDefault(); // var files = e.dataTransfer.files; // //检测是否是拖拽文件到页面的操作 // if (files.length == 0) { // return false; // } // //检测文件是不是xml // if (files[0].type.indexOf('text/xml') === -1) { // // Ardublockly.alertMessage( // // Ardublockly.getLocalStr('ErrorFileDragTitle'), // // Ardublockly.getLocalStr('ErrorFileDragBody'), // // false); // alert("ERROR!\n Unexcepted format of file is dragged\nOnly accept XML file") // return false; // } // var fr = new FileReader(); // const file = files[0]; // fr.onload = function (e) { // var xmlfile = Blockly.Xml.textToDom(e.target.result); // blockpy.components.editor.setBlocksFromXml(xmlfile); // }; // fr.readAsText(file); // $('#sketch_name').val(file.name.match(/(.+).xml$/)[1]); } /** * handle drag over function of local file */ function handleDragEnter(e) { e.stopPropagation(); e.preventDefault(); e.dataTransfer.dropEffect = "copy"; } /** * handle drag file leave the designated area */ function handleDragLeave(e) { e.stopPropagation(); e.preventDefault(); } binddrag_('main_content', (e) => { handleDragEnter(e); $("#main_shadow").css("display", "block"); }); binddrag_('shadow_content', (e) => { handleDragEnter(e); $("#main_shadow").css("display", "block"); }, (e) => { handleDragLeave(e); $("#main_shadow").css("display", "none"); }); binddrop_('shadow_content', (e) => { handleFileSelect(e); $("#main_shadow").css("display", "none"); }); }