toolbar.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /**
  2. * An object that manages the main toolbar, including the different mode buttons.
  3. * This doesn't actually have many responsibilities after the initial load.
  4. *
  5. * @constructor
  6. * @this {BlockPyToolbar}
  7. * @param {Object} main - The main BlockPy instance
  8. * @param {HTMLElement} tag - The HTML object this is attached to.
  9. */
  10. function BlockPyToolbar(main, tag) {
  11. this.main = main;
  12. this.tag = tag;
  13. // Holds the HTMLElement tags for each of the toolbar items
  14. this.tags = {};
  15. this.tags.mode_set_text = this.tag.find('.blockpy-mode-set-text');
  16. this.tags.filename_picker = this.tag.find('.blockpy-toolbar-filename-picker');
  17. // Actually set up the toolbar!
  18. this.activateToolbar();
  19. }
  20. BlockPyToolbar.prototype.notifyFeedbackUpdate = function () {
  21. this.tag.find(".blockpy-toolbar-feedback").show().fadeOut(7000);
  22. }
  23. /**
  24. * Register click events for more complex toolbar actions.
  25. */
  26. BlockPyToolbar.prototype.activateToolbar = function () {
  27. var main = this.main;
  28. this.tag.find('.blockpy-run').click(function () {
  29. main.components.server.logEvent('editor', 'run')
  30. main.components.engine.on_run();
  31. });
  32. this.tags.mode_set_text.click(function () {
  33. main.components.server.logEvent('editor', 'text')
  34. main.model.settings.editor("Text");
  35. });
  36. this.tag.find('.blockpy-toolbar-reset').click(function () {
  37. main.model.programs['__main__'](main.model.programs['starting_code']());
  38. //main.components.editor.updateBlocks();
  39. main.components.server.logEvent('editor', 'reset');
  40. if (main.model.assignment.parsons()) {
  41. main.components.editor.blockly.shuffle();
  42. }
  43. });
  44. this.tag.find('.blockpy-toolbar-load-sample').click(function () {
  45. var blob = null;
  46. var xhr = new XMLHttpRequest();
  47. xhr.open("GET", "../20190114_python-blockly_plotting-temp-data.py");
  48. xhr.responseType = "blob"; //force the HTTP response, response-type header to be blob
  49. xhr.onload = function () {
  50. blob = xhr.response; //xhr.response is now a blob object
  51. var fr = new FileReader();
  52. fr.onload = function (e) {
  53. main.setCode(e.target.result)
  54. main.components.server.logEvent('editor', 'upload')
  55. main.components.engine.on_run();
  56. };
  57. fr.readAsText(blob);
  58. }
  59. xhr.send();
  60. });
  61. this.tag.find('.blockpy-mode-set-blocks').click(function (event) {
  62. if (main.model.areBlocksUpdating()) {
  63. main.components.server.logEvent('editor', 'blocks')
  64. main.model.settings.editor("Blocks");
  65. } else {
  66. event.preventDefault();
  67. return false;
  68. }
  69. });
  70. /*this.tag.find('.blockpy-mode-set-instructor').click(function() {
  71. main.model.settings.editor("Instructor");
  72. main.components.server.logEvent('editor', 'instructor')
  73. });*/
  74. this.tag.find('.blockpy-mode-set-split').click(function (event) {
  75. if (main.model.areBlocksUpdating()) {
  76. main.model.settings.editor("Split");
  77. main.components.server.logEvent('editor', 'split')
  78. } else {
  79. event.preventDefault();
  80. return false;
  81. }
  82. });
  83. this.tag.find('.blockpy-toolbar-import').click(function () {
  84. main.components.corgis.openDialog();
  85. main.components.server.logEvent('editor', 'import')
  86. });
  87. this.tag.find('.blockpy-toolbar-history').click(function () {
  88. main.components.history.openDialog();
  89. main.components.server.logEvent('editor', 'history')
  90. });
  91. var instructorDialog = this.main.model.constants.container.find('.blockpy-instructor-popup');
  92. this.tag.find('.blockpy-toolbar-instructor').click(function () {
  93. instructorDialog.modal({ 'backdrop': false }).modal('show');
  94. instructorDialog.draggable({
  95. 'handle': '.modal-title'
  96. });
  97. main.components.server.logEvent('editor', 'instructor')
  98. });
  99. this.tag.find('.blockpy-toolbar-english').click(function () {
  100. main.components.english.openDialog();
  101. main.components.server.logEvent('editor', 'english')
  102. });
  103. // var uploadButton = this.tag.find('.blockpy-toolbar-upload');
  104. const uploadButton = $('#fileImport > input');
  105. uploadButton.change(function () {
  106. console.log('222222222222',134)
  107. var fr = new FileReader();
  108. var files = uploadButton[0].files;
  109. const file = files[0];
  110. Ardublockly.alertExampleMessage(
  111. '', Ardublockly.getLocalStr('loadBlockBody'),
  112. true, {});
  113. fr.onload = function (e) {
  114. main.setCode(e.target.result)
  115. main.components.server.logEvent('editor', 'upload')
  116. main.components.engine.on_run();
  117. };
  118. fr.readAsText(file);
  119. setTimeout(() => {
  120. $('#loading').css({ 'display': 'none' });
  121. $('#example_alert').modal('close');
  122. }, 300)
  123. $('#sketch_name').val(file.name.match(/(.+).py$/)[1]);
  124. uploadButton.val("");
  125. });
  126. const uploadXmlButton = $('#xmlFileImport > input');
  127. uploadXmlButton.change(function () {
  128. Ardublockly.handleFileSelect(event, uploadXmlButton[0].files);
  129. // var fr = new FileReader();
  130. // var files = uploadXmlButton[0].files;
  131. // const file = files[0];
  132. // fr.onload = function (e) {
  133. // try {
  134. // var xmlfile = Blockly.Xml.textToDom(e.target.result);
  135. // blockpy.components.editor.setBlocksFromXml(xmlfile);
  136. // } catch (e) {
  137. // alert("无效的xml文件");
  138. // }
  139. // if (blockpy.components.editor.getBlocksFromXml().childNodes < 1) {
  140. // alert("无效的xml文件");
  141. // }
  142. // };
  143. // fr.readAsText(file);
  144. uploadXmlButton.val("");
  145. });
  146. $('#button_load').click(e => $('#pyFileImport > input').click());
  147. $('#side_button_load').click(e => $('#xmlFileImport > input').click());
  148. // $('#downloadbutton').click(downloadXml);
  149. function downloadCode() {
  150. var data = main.model.programs['__main__']();
  151. let filename = $('#sketch_name').val();
  152. // Make safe
  153. // filename = filename.replace(/[^a-z0-9]/gi, '_').toLowerCase();
  154. filename = filename + '.py'
  155. // Make the data download as a file
  156. var blob = new Blob([data], { type: 'text/plain' });
  157. if (window.navigator.msSaveOrOpenBlob) {
  158. window.navigator.msSaveBlob(blob, filename);
  159. } else {
  160. var elem = window.document.createElement('a');
  161. elem.href = window.URL.createObjectURL(blob);
  162. elem.download = filename;
  163. document.body.appendChild(elem);
  164. elem.click();
  165. document.body.removeChild(elem);
  166. }
  167. main.components.server.logEvent('editor', 'download')
  168. }
  169. /**
  170. * Save blocks as XML file. Note that MSIE 11 does not support
  171. * @param {String} filename
  172. */
  173. function downloadXml() {
  174. var _xml = blockpy.components.editor.getBlocksFromXml();
  175. _xml.setAttribute("type", $("#mode")[0].selectedIndex == 1 ? "AI" : "IoT")
  176. var data = Blockly.Xml.domToPrettyText(_xml);
  177. let filename = $('#sketch_name').val();
  178. let reg = new RegExp(/[^a-z0-9]/)
  179. // Make safe
  180. filename = reg.test(filename) ? filename : filename.replace(/[^a-z0-9]/gi, '_').toLowerCase();
  181. filename = filename + '.xml'
  182. var blob = new Blob([data], { type: 'text/plain;charset=utf-8' });
  183. // if (window.navigator.msSaveOrOpenBlob) {
  184. // window.navigator.msSaveBlob(blob, filename);
  185. // } else {
  186. var elem = window.document.createElement('a');
  187. elem.href = window.URL.createObjectURL(blob);
  188. elem.download = filename;
  189. document.body.appendChild(elem);
  190. elem.click();
  191. document.body.removeChild(elem);
  192. // }
  193. }
  194. $('#downloadbutton').click(downloadCode);
  195. $("#AIYdownload").click(downloadCode);
  196. var downloadButton = this.tag.find('.blockpy-toolbar-download');
  197. downloadButton.click(downloadCode);
  198. $('#button_save').click(downloadCode);
  199. $('#side_button_save').click(downloadXml);
  200. this.tag.find('.blockpy-toolbar-filename-picker label').click(function () {
  201. main.model.settings.filename($(this).data('filename'))
  202. });
  203. $("#aiyModalRun").click(() => {
  204. console.log("click now")
  205. $("#modal_preload").css("display", "block");
  206. $("#aiyModalRun").addClass("disabled");
  207. setTimeout(() => {
  208. $("#modal_preload").css("display", "none");
  209. $("#aiyModalRun").removeClass("disabled");
  210. }, 2000)
  211. })
  212. $("#aiyModalStop").click(() => {
  213. console.log("click to stop")
  214. })
  215. /**
  216. * Bind a function to a drag event.
  217. * drag a file into the webpage
  218. * @param {!Element|string} el drag element or ID thereof.
  219. * @param {!function} func1 Drag over handler to bind.
  220. * @param {!function} func2 Drag leave handler to bind.
  221. * @private
  222. */
  223. function binddrag_(el, func1, func2) {
  224. if (typeof el == 'string') {
  225. el = document.getElementById(el);
  226. }
  227. el.addEventListener('dragenter', func1);
  228. el.addEventListener('dragover', (e) => {
  229. e.stopPropagation();
  230. e.preventDefault();
  231. });
  232. el.addEventListener('dragleave', func2);
  233. }
  234. /**
  235. * Bind a function to a drop event.
  236. * drop a file into the webpage
  237. * @param {!Element|string} el drag element or ID thereof.
  238. * @private
  239. */
  240. function binddrop_(el, func) {
  241. if (typeof el == 'string') {
  242. el = document.getElementById(el);
  243. }
  244. el.addEventListener('drop', func);
  245. }
  246. /**
  247. * handle File Select by drag from local folder
  248. */
  249. function handleFileSelect(e) {
  250. // e.stopPropagation();
  251. // e.preventDefault();
  252. // var files = e.dataTransfer.files;
  253. // //检测是否是拖拽文件到页面的操作
  254. // if (files.length == 0) {
  255. // return false;
  256. // }
  257. // //检测文件是不是xml
  258. // if (files[0].type.indexOf('text/xml') === -1) {
  259. // // Ardublockly.alertMessage(
  260. // // Ardublockly.getLocalStr('ErrorFileDragTitle'),
  261. // // Ardublockly.getLocalStr('ErrorFileDragBody'),
  262. // // false);
  263. // alert("ERROR!\n Unexcepted format of file is dragged\nOnly accept XML file")
  264. // return false;
  265. // }
  266. // var fr = new FileReader();
  267. // const file = files[0];
  268. // fr.onload = function (e) {
  269. // var xmlfile = Blockly.Xml.textToDom(e.target.result);
  270. // blockpy.components.editor.setBlocksFromXml(xmlfile);
  271. // };
  272. // fr.readAsText(file);
  273. // $('#sketch_name').val(file.name.match(/(.+).xml$/)[1]);
  274. }
  275. /**
  276. * handle drag over function of local file
  277. */
  278. function handleDragEnter(e) {
  279. e.stopPropagation();
  280. e.preventDefault();
  281. e.dataTransfer.dropEffect = "copy";
  282. }
  283. /**
  284. * handle drag file leave the designated area
  285. */
  286. function handleDragLeave(e) {
  287. e.stopPropagation();
  288. e.preventDefault();
  289. }
  290. // binddrag_('main_content', (e) => {
  291. // if (e.dataTransfer && e.dataTransfer.types && e.dataTransfer.types[0] == "Files") {
  292. // handleDragEnter(e);
  293. // $("#main_shadow").css("display", "block");
  294. // }
  295. // });
  296. // binddrag_('shadow_content', (e) => {
  297. // // handleDragEnter(e);
  298. // // $("#main_shadow").css("display", "block");
  299. // handleFileSelect(e);
  300. // $("#main_shadow").css("display", "block");
  301. // //$("#main_shadow").css("display", "none");
  302. // }, (e) => {
  303. // handleDragLeave(e);
  304. // $("#main_shadow").css("display", "none");
  305. // });
  306. // binddrop_('shadow_content', (e) => {
  307. // handleFileSelect(e);
  308. // $("#main_shadow").css("display", "none");
  309. // });
  310. }