cocoblockly.js 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726
  1. redirect_based_lang((window.navigator.systemLanguage ? window.navigator.systemLanguage : window.navigator.language).toLowerCase());
  2. // redirect_based_lang('zh-tw');
  3. // -------- get translation & examples' map from 'data.json' -------- //
  4. isgetmcnty = null;
  5. var _uploadererror = [
  6. ["isn't defined", "error_pv"],
  7. ["PermissionError", "error_pp"],
  8. ["file “<stadin>” line", "error_tc"],
  9. ["Timeout", "error_tp"],
  10. ["EPERM", "EPERM"],
  11. ["ENOEN", "ENOEN"],
  12. ["ESRCH", "ESRCH"],
  13. ["EINTR", "EINTR"],
  14. ["EIO", "EIO"],
  15. ["ENXIO", "ENXIO"],
  16. ["E2BIG", "E2BIG"],
  17. ["ENOEX", "ENOEX"],
  18. ["EBADF", "EBADF"],
  19. ["ECHIL", "ECHIL"],
  20. ["EAGAI", "EAGAI"],
  21. ["ENOME", "ENOME"],
  22. ["EACCE", "EACCE"],
  23. ["EFAUL", "EFAUL"],
  24. ["ENOTB", "ENOTB"],
  25. ["EBUSY", "EBUSY"],
  26. ["EEXIS", "EEXIS"],
  27. ["EXDEV", "EXDEV"],
  28. ["ENODE", "ENODE"],
  29. ["ENOTD", "ENOTD"],
  30. ["EISDI", "EISDI"],
  31. ["EINVA", "EINVA"],
  32. ["ENFIL", "ENFIL"],
  33. ["EMFIL", "EMFIL"],
  34. ["ENOTT", "ENOTT"],
  35. ["ETXTB", "ETXTB"],
  36. ["EFBIG", "EFBIG"],
  37. ["ENOSP", "ENOSP"],
  38. ["ESPIP", "ESPIP"],
  39. ["EROFS", "EROFS"],
  40. ["EMLIN", "EMLIN"],
  41. ["EPIPE", "EPIPE"],
  42. ["EDOM ", "EDOM"],
  43. ["ERANG", "ERANG"],
  44. ["EAFNOSUPP", "EAFNOSUPP"],
  45. ["ECONNRES", "ECONNRES"],
  46. ["ETIMEDO", "ETIMEDO"],
  47. ["EINPROGRE", "EINPROGRE"]
  48. ];
  49. const eproxy = new EventProxy();
  50. const CCB = {
  51. lang: (() => {
  52. let lang = 'en';
  53. document.location.search.substring(1).split('&').forEach((item) => {
  54. if (item.split('=')[0] == 'lang') {
  55. lang = item.split('=')[1];
  56. }
  57. });
  58. return lang;
  59. })(),
  60. base_url: '//api.cocorobo.cn/',
  61. // base_url: '//staging.cocorobo.cn/api/', // staging
  62. CompileURL: "//compile-service.cocorobo.cn/compile", // production, new
  63. // CompileURL: "//compiler.cocorobo.cn/dispatcher/compile", // production, old
  64. // CompileURL: "//staging.cocorobo.cn/dispatcher/compile", // staging, old
  65. // CompileURL: "//localhost:3000/compile", //local test environment
  66. str_group: null,
  67. examplesMap: null,
  68. socket: null,
  69. ws_url: 'http://localhost',
  70. pluginVersion: null,
  71. status: 'idle',
  72. isOpen: false,
  73. iconTool: 'code',
  74. mode: true,
  75. reupload: false,
  76. boards: [],
  77. cloudFileList: [],
  78. userState: false,
  79. asIframe: false,
  80. ACCategory_index: 1
  81. };
  82. const USER = {
  83. api_key: null,
  84. evnets: null,
  85. };
  86. const progress = { toast_timer: null, xhr: null };
  87. function changeLanguage(val) {
  88. let search = window.location.search.substring(1);
  89. let redirect = true;
  90. if (search.length == 0)
  91. search = `?lang=${val}`;
  92. else {
  93. if (search.indexOf('lang') >= 0) {
  94. let arr = search.split('&');
  95. for (let i = 0; i < arr.length; i++) {
  96. if (arr[i].indexOf('lang') >= 0) {
  97. arr[i].indexOf(val) >= 0 ? redirect = false : arr[i] = `lang=${val}`;
  98. break;
  99. }
  100. }
  101. redirect ? search = `?${arr.join('&')}` : '';
  102. } else
  103. search = `?lang=${val}&${search}`;
  104. }
  105. redirect ? window.location.href = `//${window.location.host}${window.location.pathname}${search}` : null;
  106. };
  107. function getJsonData(filepath) {
  108. return new Promise(resolve => {
  109. $.getJSON(filepath, data => resolve(data));
  110. });
  111. }
  112. /**
  113. * Redirect web page base on the user's language.
  114. * @param {string} lang User's languge
  115. * @returns {void} void
  116. */
  117. function redirect_based_lang(lang) {
  118. console.log('System language is: ' + window.navigator.language.toLowerCase());
  119. if (window.location !== window.parent.location) {
  120. console.log("In an iframe.");
  121. if (document.location.search.indexOf('lang') < 0) {
  122. if (lang === 'zh-cn' || lang === 'zh')
  123. changeLanguage('zh-hans');
  124. else if (lang === 'zh-tw' || lang === 'zh-hk')
  125. changeLanguage('zh-hant');
  126. else
  127. changeLanguage('en');
  128. }
  129. } else {
  130. console.log("Not in an iframe.");
  131. if (document.location.search.indexOf('lang') < 0) {
  132. if (lang === 'zh-cn' || lang === 'zh')
  133. changeLanguage('zh-hans');
  134. else if (lang === 'zh-tw' || lang === 'zh-hk')
  135. changeLanguage('zh-hant');
  136. else
  137. changeLanguage('en');
  138. }
  139. }
  140. return;
  141. }
  142. /**
  143. * Add a project button to the page & it's not finished yet.
  144. * @returns {void} void
  145. */
  146. function add_project_btn() {
  147. var projectsBtn = $('<a></a>').html(CCB.str_group.project).click(function () { });
  148. projectsBtn.addClass('waves-effect waves-light btn resize disabled');
  149. $('.blocklyTreeRoot').after(projectsBtn);
  150. }
  151. /**
  152. * create a fragment of chrome& Opera for reload.
  153. * @returns {DOM} fragment
  154. */
  155. function createChromeOperaFragment() {
  156. const fragment = document.createDocumentFragment();
  157. const container = document.createElement('div');
  158. const chromeLink = document.createElement('a');
  159. const chromeIcon = document.createElement('img');
  160. const operaLink = document.createElement('a');
  161. const operaIcon = document.createElement('img');
  162. chromeIcon.src = './icons/chrome_icon.png';
  163. chromeLink.href = 'https://www.google.com/chrome/';
  164. chromeLink.target = '_blank';
  165. operaIcon.src = './icons/opera_icon.png';
  166. operaLink.href = 'https://www.opera.com/download';
  167. operaLink.target = '_blank';
  168. container.id = 'browserLink';
  169. chromeLink.appendChild(chromeIcon);
  170. operaLink.appendChild(operaIcon);
  171. container.appendChild(chromeLink);
  172. container.appendChild(operaLink);
  173. fragment.appendChild(container);
  174. return fragment;
  175. }
  176. /**
  177. * Popout a warning modal.
  178. * @param {string} title Modal title
  179. * @param {string} body Modal main content
  180. * @param {boolean} confirm
  181. * @param {string} img Image's url
  182. * @param {DocumentFragment} fragment
  183. * @param {function} callback
  184. */
  185. function popWarning(title, body, confirm, img, fragment, callback) {
  186. if (img)
  187. $('#gen_warn_image').attr('src', img);
  188. else
  189. $('#gen_warn_image').css('display', 'none');
  190. $('#gen_warn_title').text(title);
  191. const $modalBody = $('#gen_warn_body > span');
  192. $modalBody.text('');
  193. $modalBody.append(body);
  194. if (fragment)
  195. $('#gen_warn_others').append(fragment);
  196. else
  197. $('#gen_warn_others').empty();
  198. if (confirm == true) {
  199. $('#gen_warn_cancel_link').css({ 'display': 'inline-block' });
  200. if (callback)
  201. $('#gen_warn_ok_link').bind('click', callback);
  202. } else {
  203. $('#gen_warn_cancel_link').css({ 'display': 'none' });
  204. $('#gen_warn_ok_link').unbind('click');
  205. }
  206. $('#gen_warn').modal('open');
  207. window.location.hash = '';
  208. };
  209. /**
  210. * bind selector click handler with example name on map.
  211. * @param {DOM} selector DOM Node
  212. * @param {map} map the map contain eaxmples
  213. */
  214. function bind_open_example(selector, map) {
  215. let $group = $(selector);
  216. $group.on('click', (e) => {
  217. let node = e.target;
  218. while (node.id === "")
  219. node = node.parentNode;
  220. let id = node.id;
  221. if (/\.label/.test(id))
  222. id = id.replace(/\.label/, "");
  223. if (map[id]) {
  224. let fileName = '../examples/' + map[id] + '.xml';
  225. Ardublockly.loadServerXmlFile(fileName);
  226. }
  227. });
  228. }
  229. /**
  230. * copy the Arduino code onto clipboard
  231. * @param {object} data ardunio code
  232. */
  233. function clipboard_copy(...data) {
  234. data.forEach(item => {
  235. let clip = new ClipboardJS(item);
  236. clip.on('success', (e) => {
  237. Materialize.toast(CCB.str_group.copy_success, 2000);
  238. e.clearSelection();
  239. });
  240. });
  241. }
  242. /**
  243. * bind tooltip from list
  244. * get selector and content from list
  245. */
  246. function add_tooltips(tooltip_list) {
  247. tooltip_list.forEach((i) => {
  248. $(i.selector).tooltip({
  249. delay: i.delay,
  250. position: i.position,
  251. tooltip: i.tooltip
  252. });
  253. });
  254. }
  255. /**
  256. * check version of uploader
  257. */
  258. function ver_reminder(socket) {
  259. socket.on('version', version => {
  260. clearTimeout(timer);
  261. CCB.pluginVersion = version;
  262. eproxy.emit('ver', version);
  263. });
  264. let timer = setTimeout(() => {
  265. CCB.pluginVersion = "0.0.0";
  266. eproxy.emit('ver', "0.0.0");
  267. }, 2000);
  268. }
  269. /**
  270. * Function to remove elements 'disabled' class.
  271. * @param {Array} args Selectors of element
  272. * @returns {void} void
  273. */
  274. function rm_disabled(...args) {
  275. for (let i = 0; i < args.length; i++)
  276. $(args[i]).removeClass('disabled');
  277. }
  278. /**
  279. * Function to add elements 'disabled' class.
  280. * @param {Array} args Selectors of element
  281. * @returns {void} void
  282. */
  283. function add_disabled(...args) {
  284. for (let i = 0; i < args.length; i++)
  285. $(args[i]).addClass('disabled');
  286. }
  287. /**
  288. * create options when detecting ports of hardware devices via uploader
  289. * @param {String} text info of port
  290. * @param {String} value refer to the port
  291. */
  292. function create_opts(text, value, disabled = false) {
  293. const option = document.createElement('option');
  294. option.textContent = text;
  295. option.value = value;
  296. disabled ? option.disabled = 'true' : null;
  297. return option;
  298. }
  299. /**
  300. * handle ports information received from uploader
  301. * change mode bewteen mainControl mode and wifi mode when detect ports
  302. * main control - manufacturer: Arduino
  303. * WiFi - manufacturer: Silicon
  304. * @param {String} ports info of ports
  305. * @param {DOM} parent DOM the select append to
  306. */
  307. function parse_ports(ports, parent) {
  308. let fragment = document.createDocumentFragment();
  309. let $select = $(parent);
  310. let alls = ports.boards.concat(ports.wifi);
  311. let maps = {},
  312. newboard = null,
  313. list = null;
  314. // detect if there are newboards connected
  315. for (let i = 0; i < CCB.boards.length; i++)
  316. maps[CCB.boards[i]] = true;
  317. for (let i = 0; i < alls.length; i++)
  318. !maps[alls[i].path || alls[i].comName] ? newboard = alls[i] : null;
  319. CCB.boards = [];
  320. for (let i = 0; i < alls.length; i++)
  321. CCB.boards.push(alls[i].path || alls[i].comName);
  322. // show all connected boards in select element depending on the mode
  323. list = alls;// CCB.mode ? ports.boards : ports.wifi;
  324. if (list.length > 0) {
  325. for (let i = 0; i < list.length; i++)
  326. fragment.appendChild(create_opts(list[i].path || list[i].comName, list[i].path || list[i].comName));
  327. if (CCB.status === 'idle')
  328. rm_disabled('#compile-btn', '#upload-btn', '#comms-cnt');
  329. disableCompileUploadBtn();
  330. } else {
  331. fragment.appendChild(create_opts(CCB.str_group.no_port_option, null));
  332. add_disabled('#upload-btn', '#comms-cnt');
  333. if (CCB.isOpen) {
  334. $('#comms-cnt').css("display", "block");
  335. $('#comms-discnt').css("display", "none");
  336. add_disabled('#comms-send');
  337. CCB.isOpen = false;
  338. }
  339. }
  340. $select.empty().append(fragment).material_select();
  341. $('#ports-monitor')[0].children[1].textContent = $select.val() != "null" ? $select.val() : '';
  342. if (newboard !== null) {
  343. isgetmcnty = false;
  344. $("#gettype")[0].click();
  345. // if (newboard.manufacturer.indexOf("Arduino") > -1 && CCB.mode == false)
  346. // $('#network-btn').click();
  347. // else if (newboard.manufacturer.indexOf("Silicon") > -1 && CCB.mode == true)
  348. // $('#network-btn').click();
  349. }
  350. }
  351. function getmcnty() {
  352. $('#status_bar').replaceWith(`<span id="status_bar"><span id="status_txt">${Ardublockly.LOCALISED_TEXT.statuscontect}&nbsp&nbsp&nbsp&nbsp</span></span>`);
  353. //上传中的处理
  354. $.ajax(`${CCB.socket.io.uri}/getmcnty`, {
  355. method: 'POST',
  356. data: { comname: $("#ports")[0].value, sid: CCB.socket.id },//newboard.path
  357. complete: (data) => {
  358. if (data.responseText == "IoT") {
  359. $('#status_bar').replaceWith(`<span id="status_bar"><span id="status_txt">${Ardublockly.LOCALISED_TEXT.statusbar}&nbsp&nbsp&nbsp&nbsp</span></span>`);
  360. isgetmcnty = true;
  361. $('#ports').material_select();
  362. $("#mode")[0].selectedIndex = 0;
  363. $("#mode")[0].onchange();
  364. $('#progress').css("display", "block");
  365. $('.selectMode_input')[0].value = Ardublockly.LOCALISED_TEXT.iot_module;
  366. appearExample(1);
  367. } else if (data.responseText == "AI") {
  368. $('#status_bar').replaceWith(`<span id="status_bar"><span id="status_txt">${Ardublockly.LOCALISED_TEXT.statusbar}&nbsp&nbsp&nbsp&nbsp</span></span>`);
  369. isgetmcnty = true;
  370. $('#ports').material_select();
  371. $("#mode")[0].selectedIndex = 1;
  372. $("#mode")[0].onchange();
  373. $('#progress').css("display", "block");
  374. $('.selectMode_input')[0].value = Ardublockly.LOCALISED_TEXT.ai_module;
  375. appearExample(0);
  376. }
  377. },
  378. error: function (error) {
  379. getmcnty();
  380. }
  381. });
  382. }
  383. var _ndiv = [];
  384. function repl(socket, res) {
  385. if ($("#repl_box")[0].className.indexOf("hidden") == -1) {
  386. const { code } = res;
  387. var _str = code.replace(/[\r\n]/g, function (str) {
  388. return "</div><div>";
  389. });
  390. _str = "<div>" + _str + "</div>";
  391. var _f = document.createDocumentFragment();
  392. var _div = $$("div", { "innerHTML": _str });
  393. for (var i = 0; i < _div.children.length; i++) {
  394. if (_div.children[i].innerText != "") {
  395. if (_div.children[i].innerText == ">>> ") {
  396. $$("span", { "innerHTML": "&nbsp", "contentEditable": true }, _div.children[i])
  397. }
  398. }
  399. else {
  400. _div.removeChild(_div.children[i])
  401. i--;
  402. }
  403. }
  404. _ndiv = _ndiv.concat(Array.prototype.slice.call(_div.children));
  405. var _child = Array.prototype.slice.call($("#repl_box_content")[0].children).concat(Array.prototype.slice.call(_div.children)).slice(-200);
  406. for (var i = 0; i < _child.length; i++) {
  407. _f.appendChild(_child[i])
  408. }
  409. $("#repl_box_content")[0].innerHTML = "";
  410. $("#repl_box_content")[0].appendChild(_f);
  411. // console.log($("#repl_box_content").css("height").split("px")[0])
  412. $("#repl_box")[0].scrollTop = $("#repl_box")[0].scrollHeight;
  413. let arr = [];
  414. for (let i = 0; i < _ndiv.length; i++) {
  415. let data = _ndiv[i].innerText
  416. if (data == "OK" || data == ">") {
  417. } else {
  418. data.split(',').map((x, ind) => {
  419. if (Number(x)) {
  420. arr[ind] = (arr[ind] && arr[ind].length != 0) ? arr[ind].concat([x]) : [x]
  421. } else {
  422. x = 0
  423. arr[ind] = (arr[ind] && arr[ind].length != 0) ? arr[ind].concat([x]) : [x]
  424. }
  425. return x;
  426. })
  427. }
  428. } if (arr.length > 10) {
  429. $('#echartsMainSpan').text(CCB.str_group.number_only);
  430. $('#echartsMains').css('display', 'block')
  431. $('#echartsMain').css('display', 'none')
  432. } else {
  433. $('#echartsMains').css('display', 'none')
  434. $('#echartsMain').css('display', 'block')
  435. const corlor = ['red', 'black', 'green', 'orange', "bule", "purple", "grey", "cyan", "pink", "yellow"]
  436. let arrs = arr.map((x, ind) => {
  437. if (x.length > 30) {
  438. x = x.slice(x.length - 31, x.length)
  439. }
  440. return {
  441. name: corlor[ind],
  442. smooth: true, //这句就是让曲线变平滑的
  443. type: 'line',
  444. data: x,
  445. itemStyle: {
  446. normal: {
  447. color: corlor[ind],
  448. borderColor: 'rgba(0,136,212,0.2)',
  449. }
  450. },
  451. }
  452. })
  453. if (arrs.length > 0) {
  454. document.getElementById('echartsMain').lastChild.innerHTML = "";
  455. document.getElementById('echartsMain').lastChild.removeAttribute("class");
  456. options = {
  457. animation: false,
  458. tooltip: {
  459. },
  460. grid: {
  461. top: 40,
  462. left: 50,
  463. right: 40,
  464. bottom: 50
  465. },
  466. legend: {
  467. },
  468. xAxis: {
  469. data: arrs[0].data.map((x, ind) => ind),
  470. boundaryGap: false
  471. },
  472. yAxis: {
  473. },
  474. dataZoom: [{
  475. show: true,
  476. }],
  477. series: arrs
  478. };
  479. myChart.setOption(options);
  480. }
  481. }
  482. }
  483. }
  484. /**
  485. * handle upload process via socket
  486. * upload the binary result into device
  487. * @param {object} socket socket connected between browser and uplaoder
  488. * @param {string} res binary result
  489. */
  490. function handle_upload(socket, res) {
  491. const { ProgrammerStatus, Error = '' } = res;
  492. if (ProgrammerStatus === 'Starting') {
  493. eproxy.emit('progress-start', 'upload');
  494. } else if (ProgrammerStatus === 'Break') {
  495. eproxy.emit('progress-break');
  496. } else {
  497. if (ProgrammerStatus === 'Done') {
  498. eproxy.emit('progress-response', 'upload-success');
  499. } else if (ProgrammerStatus === 'Error') {
  500. const { lang } = CCB;
  501. let language = lang.indexOf("-hant") ?
  502. "zhHant" : lang.indexOf("-hans") ? "zhHans" : "en";
  503. $('#error-btn').css('display', 'block');
  504. if (typeof (Error) === "string") {
  505. $('#err-msg').text(err);
  506. } else {
  507. var errormsg = Error.sol[language];
  508. for (var i = 0; i < _uploadererror.length; i++) {
  509. if (Error.msg.indexOf(_uploadererror[i][0]) > -1) {
  510. errormsg = Ardublockly.LOCALISED_TEXT[_uploadererror[i][1]]
  511. }
  512. }
  513. $('#err-msg').text(`${CCB.str_group.errCode} ${Error.code}
  514. \n${CCB.str_group.errMsg} ${Error.msg}
  515. \n${CCB.str_group.errSol}\n${errormsg}`);
  516. }
  517. $('.card-reveal').css({ 'display': 'block', 'transform': 'translateY(-100%)', 'padding': '8px 13px' });
  518. eproxy.emit('progress-response', 'upload-error');
  519. }
  520. setTimeout(function () {
  521. socket.emit('command', { cmd: 'list' });
  522. // console.log('getting port, 1');
  523. }, 500);
  524. setTimeout(function () {
  525. socket.emit('command', { cmd: 'list' });
  526. // console.log('getting port, 2');
  527. }, 1000);
  528. setTimeout(function () {
  529. socket.emit('command', { cmd: 'list' });
  530. // console.log('getting port, 3');
  531. }, 1500);
  532. }
  533. }
  534. /*
  535. make sure the compile and upload button is disabled when uploading procesdure is still in progress.
  536. */
  537. function disableCompileUploadBtn() {
  538. var uploadingStatusDetected = document.getElementById('status_bar').innerHTML;
  539. if (uploadingStatusDetected.includes(CCB.str_group.uploading) == true) {
  540. $('#send_file').addClass("disabled");
  541. $('#uploadpy').addClass("disabled");
  542. console.log("Disabling Upload Button...");
  543. }
  544. }
  545. /**
  546. * Replace the prograss text on upload area during uploading program
  547. * depending on uploading status.
  548. * @param {string} msg Message about uploading status
  549. * @param {string} percent Percent of uploading prograss
  550. * @returns {void} void
  551. */
  552. function progress_text(msg, percent) {
  553. // percent != "0%" ?
  554. // $('#status_bar').replaceWith(`<span id="status_bar"><span id="status_txt">${msg}&nbsp&nbsp&nbsp&nbsp</span><span>${percent}</span></span>`) :
  555. // $('#status_bar').replaceWith(`<span id="status_bar"><span id="status_txt">${msg}&nbsp&nbsp&nbsp&nbsp</span><span></span></span>`);
  556. percent != "0%" ?
  557. $("#runSuccess").css("display", "block") :
  558. $("#runSuccess").css("display", "none");
  559. percent != "0%" ?
  560. $('#statusMsg').replaceWith(`<span id="statusMsg"><span id="statusMsg_txt">${msg}&nbsp&nbsp&nbsp&nbsp</span></span>`) :
  561. $('#statusMsg').replaceWith(`<span id="statusMsg"><span id="statusMsg_txt">${msg}&nbsp&nbsp&nbsp&nbsp</span><span></span></span>`);
  562. msg == CCB.str_group.upload_fail ?
  563. $("#runFail").css("display", "block") :
  564. $("#runFail").css("display", "none");
  565. $('.progress > .determinate').css('width', percent);
  566. disableCompileUploadBtn();
  567. }
  568. /**
  569. * Show the prograss bar animation during uploading program depending
  570. * on random numbers.
  571. * @returns {Array} An array store every setTimeout func's id.
  572. */
  573. function progress_bar() {
  574. const timers = [];
  575. return function (state) {
  576. if (state) {
  577. let now = 0;
  578. for (let i = 1; i < 10; i++)
  579. timers.push(setTimeout(() => {
  580. const rand = Math.random();
  581. now += parseInt((rand < 0.5 ? rand + 0.5 : rand) * 12);
  582. $('#status_txt + span').text(`${now}%`);
  583. $('.progress > .determinate').css('width', `${now}%`);
  584. timers[i - 1] = null;
  585. }, 15000 / i));
  586. } else {
  587. timers.forEach(timer => timer ? clearTimeout(timer) : '');
  588. timers.length = 0;
  589. }
  590. };
  591. }
  592. /**
  593. * Action that communicating with boards.
  594. * @param {Object} incomingMsg Received messages
  595. * @param {Boolean} incomingMsg.Open Whether communication open or not
  596. * @param {Boolean} incomingMsg.Close Whether communication closed or not
  597. * @returns {void} void
  598. */
  599. function comm_boards(incomingMsg, isOpen) {
  600. if (incomingMsg.Open) {
  601. $('#comms-cnt').css("display", "none");
  602. $('#comms-discnt').css("display", "block");
  603. rm_disabled('#comms-send');
  604. Materialize.toast(CCB.str_group.success_openComm_monitor, 2000);
  605. CCB.isOpen = true
  606. } else if (incomingMsg.Open === false)
  607. Materialize.toast(CCB.str_group.fail_openComm_monitor, 2000);
  608. else if (incomingMsg.Close) {
  609. $('#comms-cnt').css("display", "block");
  610. $('#comms-discnt').css("display", "none");
  611. $('#comms-send').addClass('disabled');
  612. Materialize.toast(CCB.str_group.success_closeComm_monitor, 2000);
  613. CCB.isOpen = false;
  614. } else if (incomingMsg.Close === false)
  615. Materialize.toast(CCB.str_group.fail_closeComm_monitor, 2000);
  616. else if (data.updateBaud)
  617. Materialize.toast(CCB.str_group.success_setBaud_monitor, 2000);
  618. else if (data.updateBaud === false)
  619. Materialize.toast(CCB.str_group.fail_setBaud_monitor, 2000);
  620. }
  621. /**
  622. * Handle websocket disconnection.
  623. * @param {Object} socket Connected socket
  624. * @param {Function} empty Callback function to empty data list
  625. * @returns {void} void
  626. */
  627. function ws_disconn(socket, empty) {
  628. let select = $('#ports');
  629. if (CCB.isOpen)
  630. socket.emit('command', { cmd: 'close' });
  631. add_disabled('#upload-btn', '#comms-cnt', '#uploader-relaunch-btn');
  632. $('#discnt_icon').css('display', 'inline-block');
  633. $("#progress").css('display', 'none');
  634. $('#cnt_icon').css('display', 'none');
  635. select.empty()
  636. .append(create_opts(CCB.str_group.no_port_option, null, true))
  637. .material_select();
  638. // remove an event handler
  639. $('#comms-cnt').off("click");
  640. $('#comms-discnt').off('click');
  641. $('#serial_baud').off("change");
  642. $('#comms-send').off("click");
  643. $('#comms-clear').off("click", empty);
  644. $('#upload-btn').off('click');
  645. $('#uploader-relaunch-btn').off('click');
  646. socket.close();
  647. CCB.socket = null;
  648. CCB.pluginVersion = null;
  649. socket = null;
  650. try {
  651. Materialize.Toast.removeAll();
  652. } catch (e) { }
  653. Materialize.toast(CCB.str_group.ws_connect_loss, 2500);
  654. eproxy.emit('wsreconn');
  655. }
  656. /**
  657. * Bind event's action to elements with socket.
  658. * @param {Object} socket Connected socket
  659. * @param {Array} list Incoming messages list
  660. * @param {Function} empty Callback function to empty data list
  661. * @returns {void} void
  662. */
  663. function bind_with_socket(socket, list, empty) {
  664. // $('#runCode')[0].onclick = async () => {
  665. // $.ajax(`${CCB.socket.io.uri}/pythonupload`, {
  666. // method: 'POST',
  667. // data: { code: pythonnewcode, sid: socket.id },
  668. // complete: (data) => {
  669. // }
  670. // });
  671. // };
  672. /*
  673. let print_timer = null;
  674. let $commsPanel = $('#commsBox');
  675. let panelHeight = $commsPanel.css("height").split("px")[0];
  676. $('#comms-cnt').on("click", () => {
  677. if ($('#ports').val() && CCB.isOpen !== true) {
  678. socket.emit('command', {
  679. cmd: 'open',
  680. option: { port: $('#ports').val(), baud: $('#serial_baud').val() }
  681. });
  682. print_timer = setInterval(() => {
  683. if (list.length > 0) {
  684. $commsPanel.val($commsPanel.val() + list.shift());
  685. if ($("#autoscroll")[0].checked)
  686. $commsPanel[0].scrollTop = $commsPanel[0].scrollHeight - panelHeight;
  687. }
  688. }, 0);
  689. }
  690. });
  691. $('#comms-discnt').on('click', () => {
  692. if (CCB.isOpen) {
  693. socket.emit('command', { cmd: 'close' });
  694. clearInterval(print_timer);
  695. list.length = 0;
  696. }
  697. });
  698. $('#serial_baud').on("change", e => {
  699. if (CCB.isOpen)
  700. socket.emit('command', { cmd: 'updateBaud', option: { baud: e.target.value } });
  701. });
  702. $('#comms-send').on("click", () => {
  703. if (CCB.isOpen)
  704. socket.emit('command', {
  705. cmd: 'send',
  706. option: { msg: $("#comms-msg").val(), postfix: $('#serial_output_style').val() }
  707. });
  708. $('#comms-msg').val('');
  709. });
  710. $('#comms-clear').on("click", empty);
  711. $('#upload-btn').on('click', async () => {
  712. $('#error-btn').css('display') !== 'none' ? $('#error-btn').css('display', 'none') : null;
  713. let board = $('#network-btn').prop('checked') ? 'esp8266:esp8266:nodemcuv2' : 'arduino:avr:leonardo';
  714. let code = $('#content_arduino').text();
  715. let port = $('#ports').val();
  716. CCB.status = 'busy-upload';
  717. compile_request(board, code)
  718. .then(code => {
  719. $.ajax(`${CCB.socket.io.uri}/upload`, {
  720. method: 'POST',
  721. data: { board, port, code, sid: socket.id },
  722. complete: () => CCB.status = 'idle',
  723. });
  724. })
  725. .fail(err => {
  726. console.warn(err);
  727. CCB.status = 'idle';
  728. });
  729. });
  730. $('#uploader-relaunch-btn').on('click', () => {
  731. socket.emit('command', { cmd: 'relaunch' });
  732. switch (CCB.status) {
  733. case 'busy-upload':
  734. eproxy.emit('progress-init');
  735. break;
  736. default:
  737. break;
  738. }
  739. });
  740. */
  741. }
  742. /**
  743. * Use Socket.io to connect with Uploader, and eventproxy to
  744. * control all async functions.
  745. * @returns {void} void
  746. */
  747. function ws_connect() {
  748. const ports = [9991, 9992, 9993, 9994, 9995, 9996, 9997, 9998, 9999, 10000];
  749. const { ws_url } = CCB;
  750. let fail = 0;
  751. for (let i = 0; i < ports.length; i++) {
  752. let ws = io(`${ws_url}:${ports[i]}`);
  753. ws.on('connect', () => {
  754. CCB.socket = ws;
  755. eproxy.emit('wsconn', ws);
  756. });
  757. ws.on('connect_error', () => {
  758. ws = ws.close() ? null : null;
  759. ++fail === ports.length ? setTimeout(() => eproxy.emit('wsreconn'), 1000) : null;
  760. });
  761. ws.on('close', () => {
  762. ++fail === ports.length ? setTimeout(() => eproxy.emit('wsreconn'), 1000) : null;
  763. });
  764. }
  765. return;
  766. }
  767. /**
  768. * Do after websocket is connected.
  769. * @param {Object} socket Connected websocket
  770. * @returns {void} void
  771. */
  772. function ws_conned(socket) {
  773. let dataList = [],
  774. lostTimer = null;
  775. const cb = () => dataList.length = 0;
  776. const { reupload, status } = CCB;
  777. const { ws_connect_success, upload_area_init } = CCB.str_group;
  778. // popout tips for users
  779. try {
  780. Materialize.Toast.removeAll();
  781. } catch (e) { }
  782. Materialize.toast(ws_connect_success, 2500);
  783. $('#discnt_icon').css('display', 'none');
  784. $('#cnt_icon').css('display', 'inline-block');
  785. $('#uploader-relaunch-btn').removeClass('disabled');
  786. bind_with_socket(socket, dataList, cb);
  787. ver_reminder(socket);
  788. // if upload process interupt before
  789. if (reupload) {
  790. if ($('#ports').val()) {
  791. $('#upload-btn').click();
  792. } else {
  793. CCB.status = 'idle';
  794. progress_text(upload_area_init, '0%');
  795. }
  796. }
  797. // emit when connected
  798. socket.emit('command', { cmd: 'list' });
  799. // sent and received probes
  800. socket.on('ping', () => lostTimer = setTimeout(() => {
  801. status === 'busy-upload' ?
  802. handle_upload(socket, { programmerStatus: 'Break' }) : '';
  803. socket.emit('command', { cmd: 'relaunch' });
  804. }, 200));
  805. socket.on('pong', () => clearTimeout(lostTimer));
  806. // add event listener
  807. socket.on('list', data => parse_ports(data.List, document.getElementById('ports')));
  808. socket.on('upload', data => { handle_upload(socket, data); });
  809. socket.on('communicate', data => comm_boards(data));
  810. socket.on('message', data => dataList.push(data));
  811. socket.on('disconnect', () => ws_disconn(socket, cb));
  812. socket.on('repl', data => { repl(socket, data); });
  813. }
  814. function export_data(data, postfix, is_firefox) {
  815. let url = new Blob([data], { type: 'text/plain' });
  816. let download_link = URL.createObjectURL(url);
  817. let a = document.createElement('a');
  818. a.style = "display:none";
  819. a.href = download_link;
  820. a.download = $("#sketch_name").val() + postfix;
  821. if (is_firefox) {
  822. document.body.appendChild(a);
  823. a.click();
  824. setTimeout(() => document.body.removeChild(a), 100);
  825. } else
  826. a.click();
  827. // URL.revokeObjectURL(download_link);
  828. // IE edge need a short delay before revoke virtual download link
  829. setTimeout(() => URL.revokeObjectURL(download_link), 100);
  830. }
  831. /**
  832. * Rise a request for compiling
  833. * @param {string} board board info
  834. * @param {string} code ardunio code
  835. * @returns {void} void
  836. */
  837. function compile_request(board, code) {
  838. const defer = $.Deferred();
  839. let compile_path = `${CCB.CompileURL}/${board.indexOf('esp8266') > -1 ? 'w' : 'm'}`;
  840. progress.xhr = $.ajax(compile_path, {
  841. method: 'POST',
  842. xhrFields: { withCredentials: true },
  843. data: { sketch: code },
  844. beforeSend: () => eproxy.emit('progress-start', 'compile'),
  845. success: data => {
  846. let res = '';
  847. if (data.error) {
  848. res = 'compile-error';
  849. $('#error-btn').css('display', 'block');
  850. $('#err-msg').text(data.error);
  851. defer.reject(data.error);
  852. } else if (data.response) {
  853. res = 'compile-success';
  854. defer.resolve(data.response);
  855. } else {
  856. res = 'compile-timeout';
  857. defer.reject('compile timeout');
  858. }
  859. eproxy.emit('progress-response', res);
  860. },
  861. error: err => {
  862. eproxy.emit('progress-response', 'compile-offline');
  863. $('#error-btn').css('display', 'block');
  864. $('#err-msg').text(CCB.str_group.compile_offline_handle);
  865. defer.reject(err);
  866. },
  867. complete: () => progress.xhr = null,
  868. });
  869. return defer.promise();
  870. }
  871. /**
  872. * Handle selectors' "active" class.
  873. * @param {Array} selectors1 Selectors which are to remove 'active' class
  874. * @param {Array} selectors2 Selectors which are to add 'active' class
  875. * @returns {void} void
  876. */
  877. function handle_active(selectors1, selectors2 = []) {
  878. selectors1.forEach(selector => $(selector).removeClass('active'));
  879. selectors2.forEach(selector => $(selector).addClass('active'));
  880. }
  881. /**
  882. * Resize workspace.
  883. * @returns {void} void
  884. */
  885. function resize() {
  886. Ardublockly.resizeBlocklyWorkspace();
  887. Blockly.asyncSvgResize();
  888. };
  889. /**
  890. * Click function. Hanle changing icon tool mode & show the animaiton.
  891. * @param {string} val Icon tool's value
  892. * @returns {void} void
  893. */
  894. function changeSideCard(val) {
  895. let val_old = CCB.iconTool;
  896. CCB.iconTool = val;
  897. let icon_loc = (num) => `#icon-tool>li:nth-child(${num})`;
  898. // Height & opacity settings of element's animation
  899. let hei_opa_full = { height: '100%', opacity: 1 };
  900. let hei_opa_none = { height: 0, opacity: 0 };
  901. // Blockly resize
  902. resize();
  903. // Show different contents depending on input value
  904. if (val === 'code' && val_old === 'monitor') {
  905. handle_active([icon_loc(2)], [icon_loc(1)]);
  906. $('#Ardunio-main')
  907. .css('display', 'block')
  908. .animate(hei_opa_full, 300, "linear",
  909. () => $('#Serial-monitor').css('display', 'none').css('height', 0)
  910. );
  911. $('#Serial-monitor').animate({ opacity: 0 }, 80, "linear");
  912. } else if (val === 'monitor' && val_old === 'code') {
  913. handle_active([icon_loc(1)], [icon_loc(2)]);
  914. $('#Serial-monitor').css('display', 'block').css('height', '98.3%');
  915. $('#Ardunio-main').animate(hei_opa_none, 300, "linear",
  916. () => $('#Ardunio-main').css('display', 'none').css('height', 0)
  917. );
  918. $('#Serial-monitor').animate({ opacity: 1 }, 80, "linear");
  919. } else if (val === 'fullmode') {//&& val_old !== 'fullmode'
  920. // handle_active([icon_loc(1), icon_loc(2)], [icon_loc(3)]);
  921. // $('#sss').removeClass('l4').addClass('l0');
  922. // $('.blockpy-editor').removeClass('l8').addClass('l12');
  923. $('.white.blockpy-blocks.blockpy-editor-menu').toggleClass("fullscreen");
  924. $("#blockpy-content > .blockpy-editor img.fullscreenIcon").toggleClass("hidden");
  925. $("html").toggleClass("fullscreenMode");
  926. $('.blockpy-editor')[0].style.cssText = ''
  927. setTimeout(function () {
  928. Blockly.svgResize(blockpy.components.editor.blockly);
  929. Blockly.svgResize(Blockly.mainWorkspace);
  930. }, 100)
  931. } else if (val !== 'fullmode' && val_old === 'fullmode') {
  932. handle_active([icon_loc(3)]);
  933. // $('#sss').removeClass('l0').addClass('l4');
  934. // $('.blockpy-editor').removeClass('l12').addClass('l8');
  935. resize();
  936. if (val === 'code') {
  937. handle_active([], [icon_loc(1)]);
  938. if ($('#Ardunio-main').css('display') === 'none') {
  939. $('#Ardunio-main')
  940. .css('display', 'block')
  941. .animate(hei_opa_full, 300, "linear",
  942. () => $('#Serial-monitor').css('display', 'none').css('height', 0)
  943. );
  944. $('#Serial-monitor').animate({ opacity: 0 }, 80, "linear");
  945. }
  946. } else if (val === 'monitor') {
  947. handle_active([], [icon_loc(2)]);
  948. if ($('#Serial-monitor').css('display') === 'none') {
  949. $('#Serial-monitor').css('display', 'block').css('height', '98.3%');
  950. $('#Ardunio-main').animate(hei_opa_none, 300, "linear",
  951. () => $('#Ardunio-main').css('display', 'none').css('height', 0)
  952. );
  953. $('#Serial-monitor').animate({ opacity: 1 }, 80, "linear");
  954. }
  955. }
  956. }
  957. };
  958. /**
  959. * Post request to server to delete copmiler's cache files.
  960. * @returns {void} void
  961. */
  962. function deleteCompilerCache() {
  963. $.ajax(`${CCB.CompileURL}/del`, {
  964. type: 'POST',
  965. xhrFields: {
  966. withCredentials: true
  967. },
  968. data: '',
  969. });
  970. }
  971. /**
  972. * Swtich mode between wifi mode and main control mode & change
  973. * background-color between blue and red at the same time.
  974. * @returns {void} void
  975. */
  976. function PageModeSwitch() {
  977. let toolbox = blockpy.components.editor.blockly.toolbox_,
  978. temp = toolbox.tree_;
  979. let $toolboxDiv = $('.blocklyToolboxDiv');
  980. toolbox.flyout_.hide();
  981. toolbox.tree_ = toolbox.tree_old_;
  982. toolbox.tree_old_ = temp;
  983. if ($('#network-btn').prop('checked')) {
  984. Materialize.toast(CCB.str_group.wifi_mode, 1000);
  985. toolbox.HtmlDiv = $toolboxDiv[1];
  986. $('#wifi_mode_label').css('color', '#000');
  987. $toolboxDiv.first().css('display', 'none');
  988. $toolboxDiv.last().css('display', 'block');
  989. $("#icon-tool > li").addClass("color-red");
  990. $(".card-icon-area").css("border-left-color", "#e03021");
  991. $("#nav_").addClass("arduino_red");
  992. $("#footer_").addClass("arduino_red");
  993. saveLocalStorageBlocks("mc-mode-blocks-xml");
  994. blockpy.components.editor.blockly.clear();
  995. loadLocalStorageBlocks("wifi-mode-blocks-xml");
  996. CCB.mode = false;
  997. } else {
  998. Materialize.toast(CCB.str_group.maincontrol_mode, 1000);
  999. toolbox.HtmlDiv = $toolboxDiv[0];
  1000. $('#main_mode_label').css('color', '#000');
  1001. $toolboxDiv.first().css('display', 'block');
  1002. $toolboxDiv.last().css('display', 'none');
  1003. $("#icon-tool > li").removeClass("color-red");
  1004. $(".card-icon-area").css("border-left-color", "#3258cd");
  1005. $("#nav_").removeClass("arduino_red");
  1006. $("#footer_").removeClass("arduino_red");
  1007. saveLocalStorageBlocks("wifi-mode-blocks-xml");
  1008. blockpy.components.editor.blockly.clear();
  1009. loadLocalStorageBlocks("mc-mode-blocks-xml");
  1010. CCB.mode = true;
  1011. }
  1012. CCB.socket && CCB.isOpen ? CCB.socket.emit('command', { cmd: 'close' }) : null;
  1013. CCB.socket ? CCB.socket.emit('command', { cmd: 'list' }) : null;
  1014. resize();
  1015. }
  1016. /**
  1017. * Transform blocks in workspace to text.
  1018. * @returns {String}
  1019. */
  1020. function workspaceToText() {
  1021. const xml = Blockly.Xml.workspaceToDom(blockpy.components.editor.blockly);
  1022. const text = Blockly.Xml.domToText(xml);
  1023. return text;
  1024. }
  1025. function textToWorkspace(text) {
  1026. const xml = Blockly.Xml.textToDom(text);
  1027. Blockly.Xml.domToWorkspace(xml, blockpy.components.editor.blockly);
  1028. return;
  1029. }
  1030. function saveLocalStorageBlocks(name) {
  1031. const text = workspaceToText();
  1032. localStorage.setItem(name, text);
  1033. }
  1034. function loadLocalStorageBlocks(name) {
  1035. // let text = localStorage.getItem(name);
  1036. // text ? textToWorkspace(text) : '';
  1037. // return text;
  1038. var loadBlocks = localStorage.getItem(name);
  1039. if (loadBlocks) {
  1040. var xml = Blockly.Xml.textToDom(loadBlocks);
  1041. blockpy.components.editor.setBlocksFromXml(xml);
  1042. }
  1043. }
  1044. function getLocalStorage(name) {
  1045. var text = localStorage.getItem(name);
  1046. return text;
  1047. }
  1048. function saveLocalStorage(name, text) {
  1049. localStorage.setItem(name, text);
  1050. }
  1051. /**
  1052. * switch section on APP Center
  1053. * @param {Number} index section index
  1054. */
  1055. function ACCategorySelect(index) {
  1056. $("#center_categories >a:nth-child(" + CCB.ACCategory_index + ")").removeClass("active");
  1057. $("#center_categories >a:nth-child(" + index + ")").addClass("active");
  1058. var lastCate = $("#center_categories").children()[CCB.ACCategory_index - 1].name;
  1059. var newCate = $("#center_categories").children()[index - 1].name;
  1060. $("#" + lastCate).css("display", "none");
  1061. $("#" + newCate).css("display", "block");
  1062. CCB.ACCategory_index = index;
  1063. // update tab indicator when switching between tabs
  1064. jQuery(document).ready(function () {
  1065. jQuery('.tabs').tabs();
  1066. });
  1067. window.addEventListener('orientationchange', function () {
  1068. setTimeout(function () {
  1069. jQuery('.tabs').tabs('updateTabIndicator');
  1070. }, 500)
  1071. });
  1072. console.log("Tab updated.");
  1073. }
  1074. /**
  1075. * browser detect
  1076. */
  1077. function envDetect(e) {
  1078. const { os, name, version } = e.data;
  1079. $('#detect_result').css('display', 'none');
  1080. $('#detect_before').css('display', 'block');
  1081. $('#detect_preload').css('display', 'block');
  1082. envDetectProcess(os, name, version)
  1083. .then(() => {
  1084. $('#detect_before').css('display', 'none');
  1085. $('#detect_result').css('display', 'block');
  1086. })
  1087. }
  1088. /**
  1089. * browser detect
  1090. * set support OS and Browser
  1091. */
  1092. const envDetectProcess = (function () {
  1093. const check = '<i class="material-icons small" style="color:#00cf00;">check</i>';
  1094. const warn = '<i class="material-icons small" style="color:#ffcf00;">priority_high</i>';
  1095. let latest = null;
  1096. return function (os, name, version) {
  1097. const defer = $.Deferred();
  1098. const isOsSupport = osSupportDetect(os.family, os.version);
  1099. const isBrowserSupport = browserDetect(name, version);
  1100. const {
  1101. envDetectGood,
  1102. osSuggest,
  1103. browserSuggest,
  1104. pluginNetwork,
  1105. pluginConnect,
  1106. plutginNotOpen,
  1107. pluginDisconnect,
  1108. pluginSuggest
  1109. } = CCB.str_group;
  1110. const { pluginVersion } = CCB;
  1111. const pluginSupportSuggest = (support, suggest) => {
  1112. $('#env_detect_plugin > div:nth-child(3)').html(support);
  1113. $('#env_detect_plugin > div:nth-child(4)').html(suggest);
  1114. }
  1115. $('#env_detect_os > div:nth-child(2)').text(os.toString());
  1116. $('#env_detect_os > div:nth-child(3)').html(isOsSupport ? check : warn);
  1117. $('#env_detect_os > div:nth-child(4)').text(isOsSupport ? envDetectGood : osSuggest);
  1118. $('#env_detect_browser > div:nth-child(2)').text(`${name} ${version}`);
  1119. $('#env_detect_browser > div:nth-child(3)').html(isBrowserSupport ? check : warn);
  1120. $('#env_detect_browser > div:nth-child(4)').html(isBrowserSupport ? envDetectGood : browserSuggest);
  1121. pluginLatestVer()
  1122. // .then(data => {
  1123. // latest = data.releases.version
  1124. // if (!pluginVersion) {
  1125. // pluginSupportSuggest(warn, pluginDisconnect);
  1126. // $('#env_detect_plugin > div:nth-child(2)').text(plutginNotOpen);
  1127. // return defer.resolve();
  1128. // }
  1129. // $('#env_detect_plugin > div:nth-child(2)').text(`v${pluginVersion}`);
  1130. // if (!latest)
  1131. // return pluginSupportSuggest('', pluginNetwork);
  1132. // if (pluginVersion < latest.substring(1))
  1133. // pluginSupportSuggest(warn, `${pluginConnect}<br />${pluginSuggest}`);
  1134. // else
  1135. // pluginSupportSuggest(check, pluginConnect);
  1136. // return defer.resolve();
  1137. // })
  1138. // .catch(e => {
  1139. // e.abort()
  1140. // if (!pluginVersion) {
  1141. // pluginSupportSuggest(warn, pluginDisconnect);
  1142. // $('#env_detect_plugin > div:nth-child(2)').text(plutginNotOpen);
  1143. // return defer.resolve();
  1144. // }
  1145. // $('#env_detect_plugin > div:nth-child(2)').text(`v${pluginVersion}`);
  1146. // if (!latest)
  1147. // return pluginSupportSuggest('', pluginNetwork);
  1148. // if (pluginVersion < latest.substring(1))
  1149. // pluginSupportSuggest(warn, `${pluginConnect}<br />${pluginSuggest}`);
  1150. // else
  1151. // pluginSupportSuggest(check, pluginConnect);
  1152. // return defer.resolve();
  1153. // })
  1154. .success(data => latest = data.releases.version)
  1155. .error(e => e.abort())
  1156. .complete(() => {
  1157. if (!pluginVersion) {
  1158. pluginSupportSuggest(warn, pluginDisconnect);
  1159. $('#env_detect_plugin > div:nth-child(2)').text(plutginNotOpen);
  1160. return defer.resolve();
  1161. }
  1162. $('#env_detect_plugin > div:nth-child(2)').text(`v${pluginVersion}`);
  1163. if (!latest)
  1164. return pluginSupportSuggest('', pluginNetwork);
  1165. if (pluginVersion.toString().split(".")[0] < latest.substring(1).split(".")[0]) {
  1166. console.log(pluginVersion);
  1167. console.log(latest.substring(1));
  1168. pluginSupportSuggest(warn, `${pluginConnect}<br />${pluginSuggest}`);
  1169. } else if (pluginVersion.toString().split(".")[0] == latest.substring(1).split(".")[0]) {
  1170. if (pluginVersion.toString().split(".")[1] < latest.substring(1).split(".")[1]) {
  1171. console.log(pluginVersion);
  1172. console.log(latest.substring(1));
  1173. pluginSupportSuggest(warn, `${pluginConnect}<br />${pluginSuggest}`);
  1174. } else if (pluginVersion.toString().split(".")[1] == latest.substring(1).split(".")[1]) {
  1175. if (pluginVersion.toString().split(".")[2] < latest.substring(1).split(".")[2]) {
  1176. console.log(pluginVersion);
  1177. console.log(latest.substring(1));
  1178. pluginSupportSuggest(warn, `${pluginConnect}<br />${pluginSuggest}`);
  1179. } else if (pluginVersion.toString().split(".")[2] == latest.substring(1).split(".")[2]) {
  1180. pluginSupportSuggest(check, pluginConnect);
  1181. }
  1182. }
  1183. }
  1184. return defer.resolve();
  1185. });
  1186. return defer.promise();
  1187. }
  1188. })();
  1189. const osSupportDetect = (function () {
  1190. const win = {
  1191. '10': 10,
  1192. '10 Technical Preview': 6.4,
  1193. '8.1': 6.3,
  1194. '8': 6.2,
  1195. '7': 6.1,
  1196. 'Vista': 6,
  1197. 'XP 64-bit': 5.2,
  1198. 'XP': 5.1,
  1199. '2000 SP1': 5.01,
  1200. '2000': 5.0,
  1201. 'NT': 4.0,
  1202. 'ME': 4.90
  1203. };
  1204. const mac = { int: 10, float: 9 };
  1205. return (family, version) => {
  1206. let result = false;
  1207. if (family.toLowerCase().indexOf("windows") > -1) {
  1208. win[version] >= 5.1 ? result = true : "";
  1209. } else if (family.toLowerCase().indexOf("os x") > -1) {
  1210. const ver = version.split(".");
  1211. if (ver[0] > mac.int || (parseInt(ver[0]) === mac.int &&
  1212. ver[1] >= mac.float)) {
  1213. result = true;
  1214. }
  1215. }
  1216. return result;
  1217. }
  1218. })();
  1219. function browserDetect(name, version) {
  1220. let result = false;
  1221. const versionParse = (sep, ver) => {
  1222. const arr = version.split(sep);
  1223. return arr[0] > ver;
  1224. }
  1225. if (name === "Chrome") {
  1226. result = versionParse('.', 50);
  1227. } else if (name === "Firefox") {
  1228. result = versionParse('.', 50);
  1229. } else if (name === "Opera") {
  1230. result = versionParse('.', 43);
  1231. } else if (name === 'Safari') {
  1232. result = versionParse('.', 10);
  1233. } else if (name === 'Maxthon') {
  1234. result = versionParse('.', 4);
  1235. }
  1236. return result;
  1237. }
  1238. /**
  1239. * get latest version info of uploader from github
  1240. */
  1241. function pluginLatestVer() {
  1242. // $.ajax(`${CCB.base_url}releases/pythonuploaderv0.1`, {
  1243. // type: 'GET',
  1244. // xhrFields: { withCredentials: true }
  1245. // }).then(res => {
  1246. // console.log(res, '1111111111')
  1247. // }).catch(err => {
  1248. // console.log(err, '2222222222222')
  1249. // })
  1250. return $.ajax(`${CCB.base_url}releases/pythonuploaderv0.1`, {
  1251. type: 'GET',
  1252. xhrFields: { withCredentials: true }
  1253. });
  1254. }
  1255. /**
  1256. * possMessage listener
  1257. */
  1258. window.addEventListener('message', e => {
  1259. const data = e.data;
  1260. if (typeof (data) === 'object' && data.id === "asIframe" && data.status) {
  1261. CCB.asIframe = true;
  1262. let { mcXml, wfXml } = data;
  1263. mcXml ? localStorage.setItem('mc-mode-blocks-xml', mcXml) : '';
  1264. wfXml ? localStorage.setItem('wifi-mode-blocks-xml', wfXml) : '';
  1265. }
  1266. });
  1267. /**
  1268. * bind eventListener when page load
  1269. */
  1270. async function cocoblockly() {
  1271. //$(".se-pre-con").fadeOut("slow");
  1272. Ardublockly.init();
  1273. //window.parent.postMessage({ id: 'windowLoad', status: 'onload' }, '*');
  1274. let jsonData = await getJsonData('./data.json');
  1275. CCB.str_group = jsonData.translation[CCB.lang];
  1276. CCB.examplesMap = jsonData.examples;
  1277. document.getElementById('ConnectBtn').innerHTML = CCB.str_group.connect;
  1278. //document.getElementById('ConnectBtn').innerHTML = CCB.str_group.connect;
  1279. // document.getElementById('resetDevice').innerText = CCB.str_group.reset_device;
  1280. // document.getElementById('runCode').innerText = CCB.str_group.run_code;
  1281. document.getElementById('ipAddress').placeholder = CCB.str_group.ipAddress;
  1282. //document.getElementById('ipAddress').value = CCB.str_group.select_device;
  1283. // document.getElementById('ipAddress').placeholder = CCB.str_group.select_device;
  1284. document.getElementById('select-connected').children[0].innerHTML = CCB.str_group.select_connected_Wired;
  1285. document.getElementById('select-connected').children[1].innerHTML = CCB.str_group.select_connected_Wireless;
  1286. document.getElementById("Wired").innerHTML = CCB.str_group.select_connected_Wired;
  1287. document.getElementById('Wireless').innerHTML = CCB.str_group.select_connected_Wireless;
  1288. const progressAnimate = progress_bar();
  1289. if (CCB.lang == 'en') {
  1290. // for (var i = 0; i < $('.Hardware2').length - 1; i++) {
  1291. // $('.HarxA')[i].className = 'Hardware2 HarxA max'
  1292. // }
  1293. $("#python_SourceCode")[0].style.marginLeft = '0px';
  1294. // $("#repl_delete")[0].style.left = '310px'
  1295. } else {
  1296. // for (var i = 0; i < $('.Hardware2').length - 1; i++) {
  1297. // $('.HarxA')[i].className = 'Hardware2 HarxA'
  1298. // }
  1299. $("#python_SourceCode")[0].style.marginLeft = '0px';
  1300. // $("#repl_delete")[0].style.left = '260px'
  1301. }
  1302. // (function() {
  1303. // const { name } = platform;
  1304. // if (name === 'Firefox' || name === 'Chrome' || name === 'Opera') {
  1305. // CCB.ws_url = 'http://127.0.0.1';
  1306. // }
  1307. // })();
  1308. // $('#\\:0').on('touchstart', Ardublockly.bindTouchMove);
  1309. // $('#\\:26').on('touchstart', Ardublockly.bindTouchMove);
  1310. let hide_timer = null;
  1311. let tooltips = [
  1312. { selector: "#cnt_icon", delay: 50, position: "top", tooltip: CCB.str_group.connect_tooltip },
  1313. { selector: "#discnt_icon", delay: 50, position: "top", tooltip: CCB.str_group.disconnect_tooltip },
  1314. { selector: "#code-copy", delay: 500, position: "bottom", tooltip: CCB.str_group.code_copy_tooltip },
  1315. { selector: '#code-download', delay: 500, position: 'bottom', tooltip: CCB.str_group.code_download_tooltip },
  1316. // { selector: '#plugin_download', delay: 1000, position: 'right', tooltip: CCB.str_group.plugin_download_tooltip },
  1317. { selector: '#uploader>.code-header>a.upload_instruction', delay: 500, position: 'top', tooltip: CCB.str_group.upload_instruction_tooltip },
  1318. { selector: '#icon-tool > li:first-child', delay: 1000, position: 'left', tooltip: CCB.str_group.icon_tool_1 },
  1319. { selector: '#icon-tool>li:nth-child(2)', delay: 1000, position: 'left', tooltip: CCB.str_group.icon_tool_2 },
  1320. { selector: '#icon-tool>li:nth-child(3)', delay: 1000, position: 'left', tooltip: CCB.str_group.icon_tool_3 },
  1321. { selector: '#icon-tool>li:nth-child(4)', delay: 1000, position: 'left', tooltip: CCB.str_group.icon_tool_4 },
  1322. { selector: '#icon-tool>li:nth-child(5)', delay: 1000, position: 'left', tooltip: CCB.str_group.icon_tool_5 },
  1323. { selector: '#icon-tool>li:nth-child(6)', delay: 1000, position: 'left', tooltip: CCB.str_group.icon_tool_6 },
  1324. { selector: '#icon-tool>li:nth-child(7)', delay: 1000, position: 'left', tooltip: CCB.str_group.icon_tool_7 },
  1325. { selector: '#back_home', delay: 200, position: 'bottom', tooltip: CCB.str_group.back_home },
  1326. { selector: '#nav_devices', delay: 200, position: 'bottom', tooltip: CCB.str_group.nav_devices },
  1327. //{ selector: '#nav_journal', delay: 200, position: 'bottom', tooltip: CCB.str_group.nav_journal },
  1328. // { selector: '#nav_language', delay: 200, position: 'bottom', tooltip: CCB.str_group.nav_language },
  1329. // { selector: '#local_connect', delay: 200, position: 'bottom', tooltip: CCB.str_group.Connect },
  1330. // { selector: '#local_storage', delay: 200, position: 'bottom', tooltip: CCB.str_group.local_storage },
  1331. // { selector: '#help', delay: 200, position: 'bottom', tooltip: CCB.str_group.help },
  1332. { selector: '#button_delete', delay: 200, position: 'bottom', tooltip: CCB.str_group.button_delete },
  1333. { selector: '#workspace_screenshot', delay: 200, position: 'bottom', tooltip: CCB.str_group.workspace_screenshot },
  1334. { selector: '#nav_account', delay: 200, position: 'bottom', tooltip: CCB.str_group.nav_account },
  1335. { selector: '#update_Coevent', delay: 500, position: 'bottom', tooltip: CCB.str_group.update_Coevent_tooltip },
  1336. { selector: '#apikey-copy', delay: 500, position: 'bottom', tooltip: CCB.str_group.apikey_copy_tooltip },
  1337. { selector: '#uploader-relaunch-btn', delay: 500, position: 'top', tooltip: CCB.str_group.uploader_relaunch_tooltip },
  1338. { selector: '.cloudBtn-open', delay: 500, position: 'top', tooltip: CCB.str_group.cloudFileOpenMsg },
  1339. { selector: '.cloudBtn-update', delay: 500, position: 'top', tooltip: CCB.str_group.cloudFileSaveMsg },
  1340. { selector: '.cloudBtn-rename', delay: 500, position: 'top', tooltip: CCB.str_group.cloudFileEditMsg },
  1341. { selector: '.cloudBtn-delete', delay: 500, position: 'top', tooltip: CCB.str_group.cloudFileDeleteMsg },
  1342. { selector: '#runCode', delay: 500, position: 'top', tooltip: CCB.str_group.runCode },
  1343. { selector: '#uploadFiles', delay: 500, position: 'top', tooltip: CCB.str_group.uploadFiles },
  1344. // { selector: '#editDiv', delay: 200, position: 'bottom', tooltip: CCB.str_group.close_editing },
  1345. { selector: '#cloudBtn-shares', delay: 500, position: 'bottom', tooltip: CCB.str_group.cloudShares },
  1346. { selector: '#fullscreenIcon', delay: 500, position: 'bottom', tooltip: CCB.str_group.fullscreen },
  1347. { selector: '#fullscreenExitIcon', delay: 500, position: 'bottom', tooltip: CCB.str_group.fullscreenExit },
  1348. { selector: '#edit-off', delay: 500, position: 'bottom', tooltip: CCB.str_group.editing },
  1349. { selector: '#edit-on', delay: 500, position: 'bottom', tooltip: CCB.str_group.close_editing },
  1350. { selector: '#copy_code_view', delay: 500, position: 'bottom', tooltip: CCB.str_group.copy_code },
  1351. { selector: '#blockpy-toolbar-upload', delay: 500, position: 'bottom', tooltip: CCB.str_group.blockpy_toolbar_upload },
  1352. { selector: '#blockpy-toolbar-download', delay: 500, position: 'bottom', tooltip: CCB.str_group.blockpy_toolbar_download },
  1353. { selector: '#repl_delete', delay: 500, position: 'bottom', tooltip: CCB.str_group.repl_delete },
  1354. { selector: '#refresh', delay: 500, position: 'bottom', tooltip: CCB.str_group.reset_device }
  1355. ];
  1356. // /* ************ ajax request - begin ************ */
  1357. // // -------- get latest uploader version from release -------- //
  1358. // $.ajax(`${CCB.base_url}releases/pythonuploaderv0.1`, {
  1359. // type: 'GET',
  1360. // xhrFields: { withCredentials: true },
  1361. // success: res => {
  1362. // eproxy.emit('latest_ver', res.releases.version.substring(1, res.releases.version.length));
  1363. // }
  1364. // });
  1365. /* ************ ajax request - end ************ */
  1366. /* ************ set event proxy listeners - beigin ************ */
  1367. eproxy.tail('download_opts', trig => {
  1368. if (trig === true) {
  1369. if (hide_timer) {
  1370. clearTimeout(hide_timer);
  1371. hide_timer = null;
  1372. } else
  1373. $('.plugin_options').addClass('options_active').removeClass('options_hide');
  1374. } else
  1375. hide_timer = setTimeout(() => {
  1376. $('.plugin_options').addClass('options_hide').removeClass('options_active');
  1377. hide_timer = null;
  1378. }, 500);
  1379. });
  1380. eproxy.tail('wsreconn', () => ws_connect());
  1381. eproxy.tail('wsconned', ws => ws_conned(ws));
  1382. eproxy.tail('wsconn', data => eproxy.emit('wsconned', data));
  1383. eproxy.tail('ver', (ver, latest) => {
  1384. if (ver < latest) {
  1385. if (ver == "0.0.0") {
  1386. $('#uploader_currentVersion').html(CCB.str_group.out_date);
  1387. document.getElementById('uploader_content_update').style = "display:none";
  1388. document.getElementById('uploader_content_redownload').style = "display:block";
  1389. }
  1390. else {
  1391. $('#uploader_currentVersion').html(ver);
  1392. document.getElementById('uploader_content_update').style = "display:block";
  1393. document.getElementById('uploader_content_redownload').style = "display:none";
  1394. }
  1395. $('#uploader_newVersion').html(latest);
  1396. $('#uploader_reminder').modal('open');
  1397. }
  1398. });
  1399. eproxy.tail('latest_ver', (ver, latest) => {
  1400. if (ver < latest) {
  1401. if (ver == "0.0.0") {
  1402. $('#uploader_currentVersion').html(CCB.str_group.out_date);
  1403. document.getElementById('uploader_content_update').style = "display:none";
  1404. document.getElementById('uploader_content_redownload').style = "display:block";
  1405. } else {
  1406. $('#uploader_currentVersion').html(ver);
  1407. document.getElementById('uploader_content_update').style = "display:block";
  1408. document.getElementById('uploader_content_redownload').style = "display:none";
  1409. }
  1410. $('#uploader_newVersion').html(latest);
  1411. $('#uploader_reminder').modal('open');
  1412. }
  1413. });
  1414. eproxy.on('progress-start', type => {
  1415. if (type === 'compile') {
  1416. const { compiling, compile_slow } = CCB.str_group;
  1417. progress_text(compiling, '0%');
  1418. progress.toast_timer = setTimeout(
  1419. () => Materialize.toast(compile_slow, 20000), 10000);
  1420. } else if (type === 'upload') {
  1421. progress_text(CCB.str_group.uploading, '0%');
  1422. }
  1423. add_disabled('#compile-btn', '#upload-btn', '#comms-cnt');
  1424. progressAnimate(true);
  1425. });
  1426. eproxy.on('progress-response', type => {
  1427. let percent = '0%',
  1428. text = null;
  1429. const { str_group } = CCB;
  1430. const types = type.split('-');
  1431. progressAnimate(false);
  1432. try {
  1433. Materialize.Toast.removeAll();
  1434. } catch (e) { }
  1435. $('#ports').val() != "null" ? rm_disabled('#compile-btn', '#upload-btn', '#comms-cnt') : rm_disabled('#compile-btn');
  1436. disableCompileUploadBtn();
  1437. if (types[0] === 'compile') {
  1438. clearTimeout(progress.toast_timer);
  1439. progress.toast_timer = null;
  1440. if (types[1] === 'success') {
  1441. percent = '100%';
  1442. text = str_group.compile_success;
  1443. } else if (types[1] === 'error') {
  1444. text = str_group.compile_fail;
  1445. } else if (types[1] === 'timeout') {
  1446. text = str_group.compile_timeout;
  1447. } else if (types[1] === 'offline') {
  1448. text = str_group.compile_offline;
  1449. }
  1450. } else if (types[0] === 'upload') {
  1451. if (types[1] === 'success') {
  1452. percent = '100%';
  1453. text = str_group.upload_success;
  1454. }
  1455. else if (types[1] === 'error') {
  1456. text = str_group.upload_fail;
  1457. }
  1458. }
  1459. CCB.status = 'idle';
  1460. progress_text(text, percent);
  1461. });
  1462. eproxy.on('progress-break', () => {
  1463. progress_text(CCB.str_group.auto_relaunch, '0%');
  1464. CCB.reupload = true;
  1465. });
  1466. eproxy.on('progress-init', () => {
  1467. const { xhr } = progress;
  1468. xhr ? xhr.abort() : '';
  1469. progressAnimate(false)
  1470. progress_text(CCB.str_group.upload_area_init, '0%');
  1471. $('#error-btn').css('display', 'none');
  1472. $('#err-msg').text('');
  1473. });
  1474. /* ************ set event proxy listeners - end ************ */
  1475. /* -------- set toolbox tree_ control from wifi's to main control's -------- */
  1476. // let tree_temp = blockpy.components.editor.blockly.toolbox_.tree_;
  1477. // blockpy.components.editor.blockly.toolbox_.tree_ = blockpy.components.editor.blockly.toolbox_.tree_old_;
  1478. // blockpy.components.editor.blockly.toolbox_.tree_old_ = tree_temp;
  1479. // setTimeout(() => {
  1480. // // load blocks from local storage
  1481. // loadLocalStorageBlocks("mc-mode-blocks-xml");
  1482. // if (!CCB.asIframe) {
  1483. // // switch mode based on mode-state in local storage
  1484. // let mode_storage = localStorage.getItem("blockly_mode_storage");
  1485. // (mode_storage && mode_storage == "false") ? $("#network-btn").click() : null;
  1486. // }
  1487. // }, 1000);
  1488. /* -------- init '#ports' select element -------- */
  1489. $('#ports')
  1490. .empty()
  1491. .append(create_opts(CCB.str_group.no_port_option, null, true))
  1492. .material_select();
  1493. /* -------- show/hide plugin download options -------- */
  1494. $('#plugin_download').hover(
  1495. () => eproxy.emit('download_opts', true),
  1496. () => eproxy.emit('download_opts', false)
  1497. );
  1498. $('.plugin_options').hover(
  1499. () => eproxy.emit('download_opts', true),
  1500. () => eproxy.emit('download_opts', false)
  1501. );
  1502. /* -------- show/hide side bar buttons & side languages selection -------- */
  1503. $('#icon-tool > li:nth-child(4)').click(() => {
  1504. if ($('#side-lang').css('display') === 'none') {
  1505. $('#icon-tool > li:nth-child(4)').addClass('active');
  1506. $('#side-lang-trigger').click();
  1507. setTimeout(() => $(document).on('click', sideLangClose), 0);
  1508. }
  1509. });
  1510. // 点击切换语言
  1511. // $('#icon-tool > li:nth-child(4)').click(function (e) {
  1512. // $('#languages').addClass('active');
  1513. // $('#languages').css({ display: 'block', opacity: 1, position: 'absolute' })
  1514. // var ev = e || window.event;
  1515. // if (ev.stopPropagation) { //阻止冒泡,否则会触发点击空白区域的事件
  1516. // ev.stopPropagation();
  1517. // } else if (window.event) {
  1518. // window.event.cancelBubble = true;//兼容IE
  1519. // }
  1520. // })
  1521. $('#icon-tool > li:nth-child(6)').click(() => {
  1522. if ($('#side-storage').css('display') === 'none') {
  1523. $('#icon-tool > li:nth-child(6)').addClass('active');
  1524. $('#side-storage-trigger').click();
  1525. setTimeout(() => $(document).on('click', sideStorageClose), 0);
  1526. }
  1527. });
  1528. $('#icon-tool').hover(
  1529. () => $('#icon-tool').addClass('hover'),
  1530. () => $('#side-lang').css('display') === 'none' ? $('#icon-tool').removeClass('hover') : '',
  1531. () => $('#side-storage').css('display') === 'none' ? $('#icon-tool').removeClass('hover') : ''
  1532. );
  1533. function sideLangClose(e) {
  1534. $(document).off('click', sideLangClose);
  1535. $('#icon-tool > li:nth-child(4)').removeClass('active');
  1536. if (!(e.target.id === 'lang-tool' ||
  1537. (e.target.parentNode && e.target.parentNode.id === 'lang-tool'))) {
  1538. $('#icon-tool').removeClass('hover');
  1539. }
  1540. }
  1541. function sideStorageClose(e) {
  1542. $(document).off('click', sideStorageClose);
  1543. $('#icon-tool > li:nth-child(6)').removeClass('active');
  1544. if (!(e.target.id === 'bar_storage' ||
  1545. (e.target.parentNode && e.target.parentNode.id === 'bar_storage'))) {
  1546. $('#icon-tool').removeClass('hover');
  1547. }
  1548. }
  1549. // -------- close reminder modal -------- //
  1550. $('#reminder_close').on("click", () => $("#uploader_reminder").modal("close"));
  1551. // -------- add plugin download link -------- //
  1552. // if (platform.os.family.toLowerCase().indexOf('mac') > -1)
  1553. // $('#plugin_download').attr('href', 'http://api.cocorobo.cn/releases/pythonuploaderv0.1/download/mac');
  1554. // else if (platform.os.family.toLowerCase().indexOf('windows') > -1)
  1555. // $('#plugin_download').attr('href', 'http://api.cocorobo.cn/releases/pythonuploaderv0.1/download/windows');
  1556. // -------- download arduino source code -------- //
  1557. $('#code-download').on("click", () => export_data($("#content_arduino").text(), '.ino', platform.name.toLowerCase().indexOf('firefox') > -1));
  1558. // -------- clear serial monitor's output -------- //
  1559. $('#comms-clear').on("click", () => $('#commsBox').val(''));
  1560. // -------- call function of modal to export file-------- //
  1561. $('#modal-export-confirm-btn').on('click', () => {
  1562. let cdata = document.getElementById('commsBox').value;
  1563. cdata = cdata.replace(/([^\r])\n/g, "$1\r\n");
  1564. export_data(cdata, `.${document.getElementById('export-file-type').value}`, platform.name.toLowerCase().indexOf('firefox') > -1);
  1565. });
  1566. // -------- AJAX to call server's compile function -------- //
  1567. $('#compile-btn').on('click', () => {
  1568. $('#error-btn').css('display') !== 'none' ? $('#error-btn').css('display', 'none') : null;
  1569. let board = $('#network-btn').prop('checked') ? 'esp8266:esp8266:nodemcuv2' : 'arduino:avr:leonardo';
  1570. let code = $('#content_arduino').text();
  1571. CCB.status = 'busy-compile';
  1572. compile_request(board, code).always(() => CCB.status = 'idle');
  1573. });
  1574. // -------- bind functions to tourmode modal -------- //
  1575. $('#tourmode > div.modal-footer > a').on('click', () => {
  1576. blockpy.components.editor.blockly.toolbox_.tree_.collapseAll();
  1577. document.getElementsByClassName('slick-track')[0].setAttribute("style", "opacity: 1; width: 95000px; transform: translate3d(-790px, 0px, 0px);");
  1578. $('.slick-dots>li')[0].click();
  1579. $('#tour_slider_modal').modal('open');
  1580. });
  1581. $('#tour_modal_close').on('click', () => $('#tour_slider_modal').modal('close'));
  1582. $('#detect-btn').on('click', platform, envDetect);
  1583. // add_project_btn();
  1584. bind_open_example("#\\:l>div:last-child", CCB.examplesMap);
  1585. bind_open_example("#\\:2o>div:last-child", CCB.examplesMap);
  1586. clipboard_copy("#err-copy", "#apikey-copy", "#code-copy");
  1587. add_tooltips(tooltips);
  1588. ws_connect();
  1589. getlxfiles(0,getFileList);
  1590. };
  1591. // $(window).one("beforeunload", () => {
  1592. // localStorage.setItem("blockly_mode_storage", CCB.mode);
  1593. // if (CCB.mode) {
  1594. // saveLocalStorageBlocks("pythonmc-mode-blocks-xml");
  1595. // } else {
  1596. // saveLocalStorageBlocks("pythonai-mode-blocks-xml");
  1597. // //restore network-btn to main_control mode before unload
  1598. // document.getElementById("network-btn").click();
  1599. // }
  1600. // if (CCB.asIframe) {
  1601. // window.parent.postMessage({
  1602. // id: 'blocksSave',
  1603. // mcXml: localStorage.getItem('mc-mode-blocks-xml'),
  1604. // wfXml: localStorage.getItem('wifi-mode-blocks-xml')
  1605. // }, '*');
  1606. // localStorage.removeItem('mc-mode-blocks-xml');
  1607. // localStorage.removeItem('wifi-mode-blocks-xml');
  1608. // }
  1609. // deleteCompilerCache();
  1610. // });