See More

/* * Project Name : Visual Python * Description : GUI-based Python code generator * File Name : BoardFrame.js * Author : Black Logic * Note : Render and load board frame * License : GNU GPLv3 with Visual Python special exception * Date : 2021. 09. 13 * Change Date : */ //============================================================================ // [CLASS] BoardFrame //============================================================================ define([ 'text!../../html/boardFrame.html!strip', 'css!../../css/boardFrame.css', '../com/com_Config', '../com/com_String', '../com/com_util', '../com/com_interface', '../com/component/Component', '../com/component/FileNavigation', './Block', './BlockMenu', './CodeView' ], function(boardFrameHtml, boardFrameCss, com_Config, com_String, com_util, com_interface, Component, FileNavigation, Block, BlockMenu, CodeView) { 'use strict'; //======================================================================== // Define Variable //======================================================================== const BLOCK_PADDING = 20; /** * BoardFrame */ class BoardFrame extends Component{ //======================================================================== // Constructor //======================================================================== constructor($target, state, prop) { super($target, state, prop); /* * state.vp_note_display * state.vp_note_width * prop.parent: MainFrame */ } //======================================================================== // Internal call function //======================================================================== _init() { // selected block this.selectedBlock = null; this.blockList = []; // state this.state = { vp_note_display: true, viewDepthNumber: false, indentCount: 4, ...this.state }; // temporary state this.tmpState = { boardTitle: 'Untitled', boardPath: null, copy: { start: 0, end: 0 } } this.headBlocks = ['lgCtrl_if', 'lgCtrl_for', 'lgCtrl_try']; this.subBlocks = ['lgCtrl_elif', 'lgCtrl_else', 'lgCtrl_except', 'lgCtrl_finally']; } _bindEvent() { let that = this; // board menu toggle button $(this.wrapSelector('.vp-board-header-button')).on('click', function(evt) { $(that.wrapSelector('.vp-board-header-button-inner')).toggle(); evt.stopPropagation(); }); // board menu button click $(this.wrapSelector('.vp-board-header-button-inner ul li')).on('click', function() { let menu = $(this).data('menu'); switch (menu) { case 'new': that.createNewNoteWithChecking(); break; case 'open': that.openNote(); break; case 'save': that.saveNote(); break; case 'save-as': that.saveAsNote(); break; case 'run-all': that.runAll(); break; case 'code-view': that.viewCode(); break; case 'code-export': that.exportCode(); break; case 'clear': that.clearBoardWithChecking(); break; } }); // footer +code, +text button $('.vp-board-footer-buttons button').on('click', function() { let menu = $(this).data('menu'); if (menu === 'code') { // code $('#vp_wrapper').trigger({ type: 'create_option_page', blockType: 'block', menuId: 'lgExe_code', menuState: {} }); } else if (menu === 'text') { // text $('#vp_wrapper').trigger({ type: 'create_option_page', blockType: 'block', menuId: 'apps_markdown', menuState: {} }); } }); // change of boardTitle $(this.wrapSelector('#vp_boardTitle')).on('change', function() { let fileName = $(this).val(); that.tmpState.boardTitle = fileName; that.tmpState.boardPath = null; }); // click board - blur block $(this.wrapSelector()).on('click', function() { that.blurAllblock(); }); } _bindSortable() { let that = this; let parent = this.prop.parent; let position = -1; let targetBlock = null; let targetId = ''; let groupedBlocks = null; let parentBlock = null; let depth = 0; let revert = false; $('.vp-board-body').sortable({ items: '> .vp-block', axis: 'y', scroll: true, revert: false, cursor: 'move', handle: '.vp-block-header', helper: function(evt, currentItem) { let header = currentItem.data('name'); let tag = new com_String(); tag.appendLine('

'); tag.appendFormatLine('
{0}
', header); tag.appendLine('
'); return tag.toString(); }, placeholder: { element: function(currentItem) { let block = currentItem.data('block'); let color = currentItem.data('color'); targetId = currentItem.data('menu'); if (block) { let tag = new com_String(); tag.appendFormatLine('
', block.getColorLabel()); tag.appendFormatLine('
{0}
', block.name); tag.appendLine('
'); return tag.toString(); } else { let header = currentItem.find('.vp-block-header').text(); let tag = new com_String(); tag.appendFormatLine('
', color); tag.appendFormatLine('
{0}
', header); tag.appendLine('
'); return tag.toString(); } }, update: function(container, p) { // container: container // p: placeholder object return; } }, start: function(evt, ui) { position = ui.item.index(); targetBlock = that.blockList[position]; if (targetBlock) { if (targetBlock.isSubBlock) { revert = true; return; } // hide grouped item groupedBlocks = targetBlock.getGroupedBlocks(); groupedBlocks.forEach(block => { block.hide(); }); } else { // hide original item ui.item.hide(); } }, sort: function(evt, ui) { let tmpPos = ui.placeholder.index(); let currCursorX = evt.clientX; let currCursorY = evt.clientY; if (position < tmpPos && groupedBlocks) { tmpPos += (1 - groupedBlocks.length); } // sorting is not allowed for sub blocks (elif, else, except, finally) if (revert) { ui.placeholder.removeClass('vp-block-group'); ui.placeholder.insertAfter($('.vp-block:not(.vp-draggable-helper):not(.vp-sortable-placeholder):nth('+(position - 1)+')')); return; } let befBlockTag = $('.vp-block:not(.vp-draggable-helper):not(.vp-sortable-placeholder):nth('+(tmpPos - 1)+')'); if (befBlockTag && befBlockTag.length > 0) { let befBlock = befBlockTag.data('block'); let befGroupBlock = befBlock.getGroupBlock(); let rect = befBlockTag[0].getBoundingClientRect(); let befStart = rect.y; let befRange = rect.y + rect.height; let befGroupRange = befRange + (rect.height/2); let befDepth = befBlock.getChildDepth(); let isMarkdown = false; // if befBlock or thisBlock is markdown // check if thisBlock is markdown block or befBlock is markdown block if (targetId == 'apps_markdown' || (befBlock && befBlock.id == 'apps_markdown')) { isMarkdown = true; } if (isMarkdown) { let befGroupedBlocks = befGroupBlock.getGroupedBlocks(); let befGroupLastBlock = befGroupedBlocks[befGroupedBlocks.length - 1]; // last block of previous group if (!befBlock.equals(befGroupLastBlock)) { ui.placeholder.insertAfter(befGroupLastBlock.getTag()); return; } } if (!isMarkdown) { if (befBlock.isSubBlock || (befStart < currCursorY && currCursorY < befRange)) { // sort as child of befBlock (except Markdown) // - if befBlock is subBlock, no group block is allowed parentBlock = befBlock; depth = befDepth; ui.placeholder.removeClass('vp-block-group'); ui.placeholder.css({ 'padding-left': depth*BLOCK_PADDING + 'px'}); return; } if (befRange <= currCursorY && currCursorY < befGroupRange) { // sort as child of befGroupBlock (except Markdown) parentBlock = befGroupBlock; depth = befGroupBlock.getChildDepth(); ui.placeholder.removeClass('vp-block-group'); ui.placeholder.css({ 'padding-left': depth*BLOCK_PADDING + 'px'}); return; } } // sort after befBlock parentBlock = null; if (!ui.placeholder.hasClass('vp-block-group')) { ui.placeholder.addClass('vp-block-group'); } ui.placeholder.css({ 'padding-left': 0}); depth = 0; } }, stop: function(evt, ui) { var spos = position; var epos = ui.item.index(); if (revert) { revert = false; return; } if (spos < epos && groupedBlocks) { epos += (1 - groupedBlocks.length); } if (epos > -1) { // move list element if (parentBlock) { that.moveBlock(spos, epos, parentBlock); } else { that.moveBlock(spos, epos); } } if (targetBlock && groupedBlocks) { // show grouped block groupedBlocks.forEach(block => { block.show(); }); } else { // show original item ui.item.show(); } } }).disableSelection(); } //======================================================================== // External call function //======================================================================== /** * Make template */ template() { return boardFrameHtml; } /** * Render and load on parentDom, bind events */ render() { super.render(); // display note if (!this.state.vp_note_display) { this.hide(); } // set width using metadata $(this.wrapSelector()).width(this.state.vp_note_width); // render taskBar this.renderBlockList([]); this._bindSortable(); this.blockMenu = new BlockMenu(this); } /** * Render block list */ renderBlockList(blockPopupList) { let that = this; let parent = this.prop.parent; $('.vp-board-body').html(''); blockPopupList && blockPopupList.forEach(task => { let block = new Block(this, { task: task }); that.blockList.push(block); }); } /** * Reload block list on the board */ reloadBlockList() { let num = 1; // init boardframe body $(this.wrapSelector('.vp-board-body')).html(''); // render block list this.blockList.forEach(block => { // if it's already rendered and block if (block && block instanceof Block) { if (block.isGroup) { block.setNumber(num++); } block.render(); } }) this.renderInfo(); } renderInfo() { let num = 1; $('.vp-block.vp-block-group').each(function(i, block) { let numInfo = $(block).find('.vp-block-num-info'); $(numInfo).html(num++); }); } show() { // show note area $(this.wrapSelector()).show(); $('#vp_toggleBoard').removeClass('vp-hide'); $('#vp_toggleBoard').attr('title', 'Hide VP Note'); // set width let boardWidth = com_Config.BOARD_MIN_WIDTH; $(this.wrapSelector()).width(boardWidth); // save as metadata vpConfig.setMetadata({ vp_note_display: true, vp_note_width: boardWidth }); } hide() { // hide note area $(this.wrapSelector()).hide(); if (!$('#vp_toggleBoard').hasClass('vp-hide')) { $('#vp_toggleBoard').addClass('vp-hide'); } $('#vp_toggleBoard').attr('title', 'Show VP Note'); // set width let boardWidth = 0; $(this.wrapSelector()).width(boardWidth); // save as metadata vpConfig.setMetadata({ vp_note_display: false, vp_note_width: boardWidth }); } showLoadingBar() { $(this.wrapSelector('#vp_boardLoading')).show(); } hideLoadingBar() { $(this.wrapSelector('#vp_boardLoading')).hide(); } //======================================================================== // Note control //======================================================================== /** * Check if note has changes to save */ checkNote() { if (this.blockList.length > 0) { return true; } return false; } createNewNoteWithChecking() { // alert before closing let that = this; if (this.checkNote()) { // render update modal com_util.renderModal({ title: 'Unsaved changes', message: 'Do you want to save?', buttons: ['Cancel', 'No', 'Save'], defaultButtonIdx: 0, buttonClass: ['cancel', '', 'activated'], finish: function(clickedBtnIdx) { switch (clickedBtnIdx) { case 0: // cancel - do nothing return; case 1: // don't save that.createNewNote(); break; case 2: // save that.saveAsNote(function() { that.createNewNote(); }); break; } } }); return; } this.createNewNote(); } createNewNote() { // clear board before create new note this.clearBoard(); // set title to Untitled this.tmpState.boardTitle = 'Untitled'; // set path to empty this.tmpState.boardPath = null; // set title $(this.wrapSelector('#vp_boardTitle')).val('Untitled'); } openNote() { // TODO: check save as let that = this; // open file navigation let fileNavi = new FileNavigation({ type: 'open', extensions: ['vp'], finish: function(filesPath, status, error) { // clear board before open note that.clearBoard(); let vpFilePath = filesPath[0].path; let vpFileName = filesPath[0].file; // read file fetch(vpFilePath).then(function(file) { if (file.status != 200) { com_util.renderAlertModal('The file format is not valid. (file: '+file+')'); return; } file.text().then(function(data) { // var parsedData = decodeURIComponent(data); try { var jsonList = JSON.parse(data); // load blocks that.jsonToBlock(jsonList); var indexVp = vpFileName.indexOf('.vp'); var saveFileName = vpFileName.slice(0,indexVp); // show title of board and path $('#vp_boardTitle').val(saveFileName); that.tmpState.boardTitle = saveFileName; that.tmpState.boardPath = vpFilePath; com_util.renderSuccessMessage('Successfully opened file. (' + vpFileName + ')'); } catch (ex) { com_util.renderAlertModal('Not applicable file contents with vp format! (JSON)'); } }); }); } }); fileNavi.open(); } saveNote() { let { boardPath, boardTitle } = this.tmpState; // if path exists, save note if (boardPath && boardPath != '') { // save vp file let idx = boardTitle.lastIndexOf('.vp'); if (idx < 0) { boardTitle += '.vp'; } let saveData = this.blockToJson(this.blockList); let saveDataStr = JSON.stringify(saveData); vpKernel.saveFile(boardTitle, boardPath, saveDataStr); return; } this.saveAsNote(); } saveAsNote(callback) { let that = this; // save file navigation let fileNavi = new FileNavigation({ type: 'save', fileName: this.tmpState.boardTitle, extensions: ['vp'], finish: function(filesPath, status, error) { let boardTitle = filesPath[0].file; let boardPath = filesPath[0].path; // save vp file let saveData = that.blockToJson(that.blockList); let saveDataStr = JSON.stringify(saveData); vpKernel.saveFile(boardTitle, boardPath, saveDataStr); // save it in tmpState // detach extension let idx = boardTitle.lastIndexOf('.vp'); boardTitle = boardTitle.substring(0, idx); that.tmpState.boardTitle = boardTitle; that.tmpState.boardPath = boardPath; $('#vp_boardTitle').val(boardTitle); if (callback != undefined && typeof callback === 'function') { callback(); } } }); fileNavi.open(); } runBlock(block, execute=true, addcell=true) { if (block.id == 'apps_markdown') { // if markdown, run single return block.popup.run(execute, addcell); } let rootBlockDepth = block.depth; let groupedBlocks = block.getGroupedBlocks(); let code = new com_String(); let indentCount = this.state.indentCount; groupedBlocks.forEach((groupBlock, idx) => { let prevNewLine = idx > 0?'\n':''; let indent = ' '.repeat((groupBlock.depth - rootBlockDepth) * indentCount); let thisBlockCode = groupBlock.popup.generateCode(); if (Array.isArray(thisBlockCode)) { for (let i = 0; i < thisBlockCode.length; i++) { thisBlockCode[i] = thisBlockCode[i].replaceAll('\n', '\n' + indent); } if (addcell) { // insert single cell using prev code com_interface.insertCell('code', code.toString(), execute, block.sigText); code = new com_String(); // insert cells using this block code list com_interface.insertCells('code', thisBlockCode, execute, block.sigText); } } else { // set indent to every line of thisblockcode thisBlockCode = thisBlockCode.replaceAll('\n', '\n' + indent); code.appendFormat('{0}{1}{2}', prevNewLine, indent, thisBlockCode); } }); if (addcell) { com_interface.insertCell('code', code.toString(), execute, block.sigText); } return code.toString(); } runAll() { let that = this; this.blockList.forEach(block => { if (block.isGroup) { that.runBlock(block); } }) } getOverallCode() { let overallCode = new com_String(); let that = this; this.blockList.forEach((block) => { if (block.isGroup) { if (overallCode.toString() != '') { overallCode.appendLine(); overallCode.appendLine(); } let groupCode = that.runBlock(block, false, false); if (block.id == 'apps_markdown') { // if markdown, add # groupCode = '#' + groupCode.replaceAll('\n', '\n# '); } overallCode.appendFormatLine('# Visual Python: {0} > {1}', block.name, block.name, block.id == 'apps_markdown'? ' - Markdown':''); overallCode.append(groupCode); } }); return overallCode.toString(); } viewCode() { let overallCode = this.getOverallCode(); let codeview = new CodeView({ codeview: overallCode, config: { id: 'boardCodeview', name: 'Overall Codeview', path: '' } }); codeview.open(); } exportCode() { let that = this; // save .py file let fileNavi = new FileNavigation({ type: 'save', fileName: this.tmpState.boardTitle, extensions: ['py'], finish: function(filesPath, status, error) { let fileName = filesPath[0].file; let filePath = filesPath[0].path; // save py file let overallCode = that.getOverallCode(); vpKernel.saveFile(fileName, filePath, overallCode); } }); fileNavi.open(); } /** * Deprecated on v2.0.2. */ // viewDepthInfo() { // this.state.viewDepthNumber = !this.state.viewDepthNumber; // if (this.state.viewDepthNumber) { // $(this.wrapSelector('.vp-board-header-button-inner li[data-menu="view-depth"]')).text('Hide Depth Number'); // } else { // $(this.wrapSelector('.vp-board-header-button-inner li[data-menu="view-depth"]')).text('View Depth Number'); // } // // reloadBlockList // this.reloadBlockList(); // } clearBoardWithChecking() { // alert before closing let that = this; if (this.checkNote()) { // render update modal com_util.renderModal({ title: 'Unsaved changes', message: 'Do you want to save?', buttons: ['Cancel', "No", 'Save'], defaultButtonIdx: 0, buttonClass: ['cancel', '', 'activated'], finish: function(clickedBtnIdx) { switch (clickedBtnIdx) { case 0: // cancel - do nothing return; case 1: // don't save that.clearBoard(); break; case 2: // save that.saveAsNote(function() { that.clearBoard(); }); break; } } }); return; } this.clearBoard(); } clearBoard() { // clear board this.blockList.forEach(block => { block.popup.remove(); }) this.blockList = []; // render block list this.reloadBlockList(); } /** * Deprecated on v2.0.2. */ // closeBoard() { // this.createNewNote(); // } //======================================================================== // Block control //======================================================================== createBlock(component, state) { let createdBlock = new Block(this, state); component.setTaskItem(createdBlock); return createdBlock; } addBlock(option, position=-1, blockState={}) { let block = new Block(this, { task: option, ...blockState }); option.setTaskItem(block); if (position < 0) { // add to the end this.blockList.push(block); position = this.blockList.length; } else { // add to specific position this.blockList.splice(position, 0, block); } return block; } removeBlock(blockToRemove) { let that = this; // if sub block, change group block's state let groupBlock = blockToRemove.getGroupBlock(); if (blockToRemove.id === 'lgCtrl_else') { groupBlock.state.elseFlag = false; } if (blockToRemove.id === 'lgCtrl_finally') { groupBlock.state.finallyFlag = false; } // remove grouped blocks (under this depth) let groupedBlocks = blockToRemove.getGroupedBlocks(); groupedBlocks.forEach(block => { // remove block if (blockToRemove.isGroup || blockToRemove.equals(block) || block.depth > blockToRemove.depth) { const blockIdx = that.blockList.indexOf(block); block.popup.remove(); that.blockList.splice(blockIdx, 1); } }); // render block list this.reloadBlockList(); } /** * Change position of task in blockPopupList * @param {int} startIdx * @param {int} endIdx */ moveBlock(startIdx, endIdx, parentBlock=null) { var movingBlock = this.blockList[startIdx]; if (movingBlock) { let groupBlocks = this.getGroupedBlocks(movingBlock); this.blockList.splice(startIdx, groupBlocks.length); this.blockList.splice(endIdx, 0, ...groupBlocks); // move tag if (parentBlock != null) { // set this movingBlock as child of parentBlock movingBlock.setChildBlock(parentBlock.getChildDepth()); } else { // set group block movingBlock.setGroupBlock(); } this.reloadBlockList(); } } copyBlock(block) { const blockIdx = this.blockList.indexOf(block); let groupedBlocks = block.getGroupedBlocks(); let dupPosition = blockIdx + groupedBlocks.length; let groupedBlockStateList = []; groupedBlocks.forEach((groupBlock, idx) => { let menuId = groupBlock.id; let popupState = groupBlock.popup.state; groupedBlockStateList.push({ blockType: 'block', menuId: menuId, menuState: { taskState: JSON.parse(JSON.stringify(popupState)), blockState: { isGroup: groupBlock.isGroup, depth: groupBlock.depth } }, position: dupPosition + idx, createChild: false }); }); this.prop.parent.createPopup(groupedBlockStateList); } showMenu(block, left, top) { this.blockMenu.open(block, left, top); } getGroupedBlocks(parentBlock) { const parentIdx = this.blockList.indexOf(parentBlock); let nextGroupIdx = parentIdx + 1; if (parentBlock.canMakeChild()) { while (nextGroupIdx < this.blockList.length) { let block = this.blockList[nextGroupIdx]; let isGroup = block.isGroup; if (isGroup) { // find next group block break; } let isSubBlock = (this.headBlocks.includes(parentBlock.id) && block.depth == parentBlock.depth && this.subBlocks.includes(block.id)); if (!parentBlock.isGroup && !isSubBlock && block.depth <= parentBlock.depth) { break; } nextGroupIdx++; } } // grouped blocks (include this parentBlock) let groupedBlocks = this.blockList.slice(parentIdx, nextGroupIdx); return groupedBlocks; } getGroupBlock(thisBlock) { if (thisBlock.isGroup) { return thisBlock; } let groupBlockIdx = this.blockList.indexOf(thisBlock) - 1; while (groupBlockIdx > 0) { if (this.blockList[groupBlockIdx].isGroup) { break; } groupBlockIdx--; } return this.blockList[groupBlockIdx]; } blurAllblock() { this.blockList.forEach(block => { block.blurItem(); }); } scrollToBlock(block) { $(this.wrapSelector('#vp_boardBody')).animate({scrollTop: $(block.getTag()).position().top}, "fast"); } //======================================================================== // Block sub block control //======================================================================== checkFlag(block) { let groupedBlocks = block.getGroupedBlocks(); let elseBlock = groupedBlocks.filter(obj => (obj.id === 'lgCtrl_else' && obj.depth === block.depth)); let finallyBlock = groupedBlocks.find(obj => (obj.id === 'lgCtrl_finally' && obj.depth === block.depth)); block.state.elseFlag = elseBlock!=undefined?true:false; block.state.finallyFlag = finallyBlock!=undefined?true:false; } toggleElseBlock(block) { const blockIdx = this.blockList.indexOf(block); let groupedBlocks = block.getGroupedBlocks(); let position = blockIdx + groupedBlocks.length; // add position // check if it has else block let elseFlag = block.state.elseFlag; if (!elseFlag) { // if finally is available, change add position if (block.state.finallyFlag) { let finallyBlock = groupedBlocks.find(obj => (obj.id === 'lgCtrl_finally' && obj.depth === block.depth)); let finallyPosition = this.blockList.indexOf(finallyBlock); position = finallyPosition; } // add else let blockState = { isGroup: false, depth: block.depth } this.prop.parent.createPopup([{ blockType: 'block', menuId: 'lgCtrl_else', menuState: { blockState: blockState }, position: position }]); block.state.elseFlag = true; setTimeout(function() { block.focusItem(); }, 100); } else { // remove else let elseBlock = groupedBlocks.filter(obj => (obj.id === 'lgCtrl_else' && obj.depth === block.depth)); if (elseBlock.length > 0) { this.removeBlock(elseBlock[0]); } // focus it setTimeout(function() { block.focusItem(); }, 100); } } toggleFinallyBlock(block) { const blockIdx = this.blockList.indexOf(block); let groupedBlocks = block.getGroupedBlocks(); let position = blockIdx + groupedBlocks.length; // add position // check if it has finally block let finallyFlag = block.state.finallyFlag; if (!finallyFlag) { // add finally let blockState = { isGroup: false, depth: block.depth } this.prop.parent.createPopup([{ blockType: 'block', menuId: 'lgCtrl_finally', menuState: { blockState: blockState }, position: position }]); block.state.finallyFlag = true; setTimeout(function() { block.focusItem(); }, 100); } else { // remove finally let finallyBlock = groupedBlocks.find(obj => (obj.id === 'lgCtrl_finally' && obj.depth === block.depth)); if (finallyBlock) { this.removeBlock(finallyBlock); } // focus it setTimeout(function() { block.focusItem(); }, 100); } } addElifBlock(block) { const blockIdx = this.blockList.indexOf(block); let groupedBlocks = block.getGroupedBlocks(); let position = blockIdx + groupedBlocks.length; // add position // if else is available, change add position if (block.state.elseFlag) { let elseBlock = groupedBlocks.find(obj => (obj.id === 'lgCtrl_else' && obj.depth === block.depth)); let elsePosition = this.blockList.indexOf(elseBlock); position = elsePosition; } // add elif let blockState = { isGroup: false, depth: block.depth } this.prop.parent.createPopup([{ blockType: 'block', menuId: 'lgCtrl_elif', menuState: { blockState: blockState }, position: position }]); setTimeout(function() { block.focusItem(); }, 100); } addExceptBlock(block) { const blockIdx = this.blockList.indexOf(block); let groupedBlocks = block.getGroupedBlocks(); let position = blockIdx + groupedBlocks.length; // add position // if finally is available, change add position if (block.state.finallyFlag) { let finallyBlock = groupedBlocks.find(obj => (obj.id === 'lgCtrl_finally' && obj.depth === block.depth)); let finallyPosition = this.blockList.indexOf(finallyBlock); position = finallyPosition; } // if else is available, change add position if (block.state.elseFlag) { let elseBlock = groupedBlocks.find(obj => (obj.id === 'lgCtrl_else' && obj.depth === block.depth)); let elsePosition = this.blockList.indexOf(elseBlock); position = elsePosition; } // add except let blockState = { isGroup: false, depth: block.depth } this.prop.parent.createPopup([{ blockType: 'block', menuId: 'lgCtrl_except', menuState: { blockState: blockState }, position: position }]); setTimeout(function() { block.focusItem(); }, 100); } //======================================================================== // Block save/load //======================================================================== blockToJson(blockList) { let result = []; blockList && blockList.forEach(block => { let jsonBlock = block.toJson(); result.push(jsonBlock); }); return result; } jsonToBlock(jsonList) { let parent = this.prop.parent; // MainFrame let blockList = []; jsonList && jsonList.forEach((obj, idx) => { let { isGroup, depth, blockNumber, taskId, taskState } = obj; let state = { taskState: taskState, blockState: { isGroup: isGroup, depth: depth, blockNumber: blockNumber } }; blockList.push({ blockType: 'block', menuId: taskId, menuState: state, position: idx, createChild: false }); }); parent.createPopup(blockList); } } // class return BoardFrame; }); /* End of file */