'use strict'; goog.provide('Blockly.JavaScript.Trigger'); goog.require('Blockly.JavaScript'); Blockly.CustomBlocks = Blockly.CustomBlocks || []; Blockly.CustomBlocks.push('Trigger'); Blockly.Trigger = { HUE: 330, blocks: {} }; // --- ON Extended----------------------------------------------------------- Blockly.Trigger.blocks['on_ext'] = '' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ''; Blockly.Blocks['on_ext_oid_container'] = { /** * Mutator block for container. * @this Blockly.Block */ init: function() { this.setColour(Blockly.Trigger.HUE); this.appendDummyInput() .appendField(Blockly.Words['on_ext_on'][systemLang]); this.appendStatementInput('STACK'); this.setTooltip(Blockly.Words['on_ext_on_tooltip'][systemLang]); this.contextMenu = false; } }; Blockly.Blocks['on_ext_oid'] = { /** * Mutator block for add items. * @this Blockly.Block */ init: function() { this.setColour(Blockly.Trigger.HUE); this.appendDummyInput('OID') .appendField(Blockly.Words['on_ext_oid'][systemLang]); this.setPreviousStatement(true); this.setNextStatement(true); this.setTooltip(Blockly.Words['on_ext_oid_tooltip'][systemLang]); this.contextMenu = false; } }; Blockly.Blocks['on_ext'] = { init: function() { this.itemCount_ = 1; this.updateShape_(); this.setMutator(new Blockly.Mutator(['on_ext_oid'])); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setInputsInline(false); this.setColour(Blockly.Trigger.HUE); this.setTooltip(Blockly.Words['on_ext_tooltip'][systemLang]); this.setHelpUrl(getHelp('on_help')); }, /** * Create XML to represent number of text inputs. * @return {!Element} XML storage element. * @this Blockly.Block */ mutationToDom: function () { var container = document.createElement('mutation'); container.setAttribute('items', this.itemCount_); return container; }, /** * Parse XML to restore the text inputs. * @param {!Element} xmlElement XML storage element. * @this Blockly.Block */ domToMutation: function (xmlElement) { this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10); this.updateShape_(); }, /** * Populate the mutator's dialog with this block's components. * @param {!Blockly.Workspace} workspace Mutator's workspace. * @return {!Blockly.Block} Root block in mutator. * @this Blockly.Block */ decompose: function (workspace) { var containerBlock = workspace.newBlock('on_ext_oid_container'); containerBlock.initSvg(); var connection = containerBlock.getInput('STACK').connection; for (var i = 0; i < this.itemCount_; i++) { var itemBlock = workspace.newBlock('on_ext_oid'); itemBlock.initSvg(); connection.connect(itemBlock.previousConnection); connection = itemBlock.nextConnection; } return containerBlock; }, /** * Reconfigure this block based on the mutator dialog's components. * @param {!Blockly.Block} containerBlock Root block in mutator. * @this Blockly.Block */ compose: function (containerBlock) { var itemBlock = containerBlock.getInputTargetBlock('STACK'); // Count number of inputs. var connections = []; while (itemBlock) { connections.push(itemBlock.valueConnection_); itemBlock = itemBlock.nextConnection && itemBlock.nextConnection.targetBlock(); } // Disconnect any children that don't belong. for (var i = 0; i < this.itemCount_; i++) { var connection = this.getInput('OID' + i).connection.targetConnection; if (connection && connections.indexOf(connection) === -1) { connection.disconnect(); } } this.itemCount_ = connections.length; if (this.itemCount_ < 1) this.itemCount_ = 1; this.updateShape_(); // Reconnect any child blocks. for (var i = 0; i < this.itemCount_; i++) { Blockly.Mutator.reconnect(connections[i], this, 'OID' + i); } }, /** * Store pointers to any connected child blocks. * @param {!Blockly.Block} containerBlock Root block in mutator. * @this Blockly.Block */ saveConnections: function(containerBlock) { var itemBlock = containerBlock.getInputTargetBlock('STACK'); var i = 0; while (itemBlock) { var input = this.getInput('OID' + i); itemBlock.valueConnection_ = input && input.connection.targetConnection; i++; itemBlock = itemBlock.nextConnection && itemBlock.nextConnection.targetBlock(); } }, /** * Modify this block to have the correct number of inputs. * @private * @this Blockly.Block */ updateShape_: function() { this.removeInput('CONDITION'); this.removeInput('ACK_CONDITION'); var input; for (var j = 0; input = this.inputList[j]; j++) { if (input.name === 'STATEMENT') { this.inputList.splice(j, 1); break; } } // Add new inputs. for (var i = 0; i < this.itemCount_; i++) { var _input = this.getInput('OID' + i); if (!_input) { _input = this.appendValueInput('OID' + i); if (i === 0) { _input.appendField(Blockly.Words['on_ext'][systemLang]); } var shadow = this.workspace.newBlock('field_oid'); shadow.setShadow(true); shadow.outputConnection.connect(_input.connection); shadow.initSvg(); shadow.render(); } else { if (!_input.connection.isConnected()) { var shadow = this.workspace.newBlock('field_oid'); shadow.setShadow(true); shadow.outputConnection.connect(_input.connection); shadow.initSvg(); shadow.render(); } } } // Remove deleted inputs. while (this.getInput('OID' + i)) { this.removeInput('OID' + i); i++; } this.appendDummyInput('CONDITION') .appendField(new Blockly.FieldDropdown([ [Blockly.Words['on_onchange'][systemLang], 'ne'], [Blockly.Words['on_any'][systemLang], 'any'], [Blockly.Words['on_gt'][systemLang], 'gt'], [Blockly.Words['on_ge'][systemLang], 'ge'], [Blockly.Words['on_lt'][systemLang], 'lt'], [Blockly.Words['on_le'][systemLang], 'le'], [Blockly.Words['on_true'][systemLang], 'true'], [Blockly.Words['on_false'][systemLang], 'false'] ]), 'CONDITION'); this.appendDummyInput('ACK_CONDITION') .appendField(Blockly.Words['on_ack'][systemLang]) .appendField(new Blockly.FieldDropdown([ [Blockly.Words['on_ack_any'][systemLang], ''], [Blockly.Words['on_ack_true'][systemLang], 'true'], [Blockly.Words['on_ack_false'][systemLang], 'false'] ]), 'ACK_CONDITION'); if (input) { this.inputList.push(input); } else { this.appendStatementInput('STATEMENT') .setCheck(null) } } }; Blockly.JavaScript['on_ext'] = function(block) { var dropdown_condition = block.getFieldValue('CONDITION'); var statements_name = Blockly.JavaScript.statementToCode(block, 'STATEMENT'); var ack_condition = block.getFieldValue('ACK_CONDITION'); var val; if (dropdown_condition === 'true' || dropdown_condition === 'false') { val = 'val: ' + dropdown_condition; } else { val = 'change: "' + dropdown_condition + '"'; } var oids = []; var firstID; for (var n = 0; n < block.itemCount_; n++) { var id = Blockly.JavaScript.valueToCode(block, 'OID' + n, Blockly.JavaScript.ORDER_COMMA); if (id) { firstID = id; id = id.replace(/\./g, '\\\\.').replace(/\(/g, '\\\\(').replace(/\)/g, '\\\\)').replace(/\[/g, '\\\\['); if (oids.indexOf(id) === -1) oids.push(id); } } var oid; if (oids.length === 1) { oid = firstID; } else { oid = 'new RegExp(' + (oids.join(' + "|" + ') || '') + ')'; } var code = 'on({id: ' + oid + ', ' + val + (ack_condition ? ', ack: ' + ack_condition : '') + '}, function (obj) {\n ' + (oids.length === 1 ? 'var value = obj.state.val;\n var oldValue = obj.oldState.val;\n' : '') + statements_name + '});\n'; return code; }; // --- ON ----------------------------------------------------------- Blockly.Trigger.blocks['on'] = '' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ''; Blockly.Blocks['on'] = { init: function() { this.appendDummyInput() .appendField(Blockly.Words['on'][systemLang]); this.appendDummyInput('OID') .appendField(new Blockly.FieldOID('Object ID', main.initSelectId(), main.objects), 'OID'); this.appendDummyInput('CONDITION') .appendField(new Blockly.FieldDropdown([ [Blockly.Words['on_onchange'][systemLang], 'ne'], [Blockly.Words['on_any'][systemLang], 'any'], [Blockly.Words['on_gt'][systemLang], 'gt'], [Blockly.Words['on_ge'][systemLang], 'ge'], [Blockly.Words['on_lt'][systemLang], 'lt'], [Blockly.Words['on_le'][systemLang], 'le'], [Blockly.Words['on_true'][systemLang], 'true'], [Blockly.Words['on_false'][systemLang], 'false'] ]), 'CONDITION'); this.appendDummyInput('ACK_CONDITION') .appendField(Blockly.Words['on_ack'][systemLang]) .appendField(new Blockly.FieldDropdown([ [Blockly.Words['on_ack_any'][systemLang], ''], [Blockly.Words['on_ack_true'][systemLang], 'true'], [Blockly.Words['on_ack_false'][systemLang], 'false'] ]), 'ACK_CONDITION'); this.appendStatementInput('STATEMENT') .setCheck(null); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setInputsInline(false); this.setColour(Blockly.Trigger.HUE); this.setTooltip(Blockly.Words['on_tooltip'][systemLang]); this.setHelpUrl(getHelp('on_help')); } }; Blockly.JavaScript['on'] = function(block) { var value_objectid = block.getFieldValue('OID'); var dropdown_condition = block.getFieldValue('CONDITION'); var ack_condition = block.getFieldValue('ACK_CONDITION'); var statements_name = Blockly.JavaScript.statementToCode(block, 'STATEMENT'); var objectname = main.objects[value_objectid] && main.objects[value_objectid].common && main.objects[value_objectid].common.name ? main.objects[value_objectid].common.name : ''; Blockly.Msg.VARIABLES_DEFAULT_NAME = 'value'; var val; if (dropdown_condition === 'true' || dropdown_condition === 'false') { val = 'val: ' + dropdown_condition; } else { val = 'change: "' + dropdown_condition + '"'; } var code = 'on({id: "' + value_objectid + '"' + (objectname ? '/*' + objectname + '*/' : '') + ', ' + val + (ack_condition ? ', ack: ' + ack_condition : '') + '}, function (obj) {\n var value = obj.state.val;\n var oldValue = obj.oldState.val;\n' + statements_name + '});\n'; return code; }; // --- get info about event ----------------------------------------------------------- Blockly.Trigger.blocks['on_source'] = '' + ' ' + ' ' + ''; Blockly.Blocks['on_source'] = { /** * Block for conditionally returning a value from a procedure. * @this Blockly.Block */ init: function() { this.appendDummyInput('ATTR') .appendField(new Blockly.FieldDropdown([ [Blockly.Words['on_source_id'][systemLang], 'id'], [Blockly.Words['on_source_name'][systemLang], 'common.name'], [Blockly.Words['on_source_desc'][systemLang], 'common.desc'], [Blockly.Words['on_source_channel_id'][systemLang], 'channelId'], [Blockly.Words['on_source_channel_name'][systemLang], 'channelName'], [Blockly.Words['on_source_device_id'][systemLang], 'deviceId'], [Blockly.Words['on_source_device_name'][systemLang], 'deviceName'], [Blockly.Words['on_source_state_val'][systemLang], 'state.val'], [Blockly.Words['on_source_state_ts'][systemLang], 'state.ts'], [Blockly.Words['on_source_state_q'][systemLang], 'state.q'], [Blockly.Words['on_source_state_from'][systemLang], 'state.from'], [Blockly.Words['on_source_state_ack'][systemLang], 'state.ack'], [Blockly.Words['on_source_state_lc'][systemLang], 'state.lc'], [Blockly.Words['on_source_oldstate_val'][systemLang], 'oldState.val'], [Blockly.Words['on_source_oldstate_ts'][systemLang], 'oldState.ts'], [Blockly.Words['on_source_oldstate_q'][systemLang], 'oldState.q'], [Blockly.Words['on_source_oldstate_from'][systemLang], 'oldState.from'], [Blockly.Words['on_source_oldstate_ack'][systemLang], 'oldState.ack'], [Blockly.Words['on_source_oldstate_lc'][systemLang], 'oldState.lc'] ]), 'ATTR'); this.setInputsInline(true); this.setOutput(true); this.setColour(Blockly.Trigger.HUE); this.setTooltip(Blockly.Words['on_source_tooltip'][systemLang]); this.setHelpUrl(getHelp('on_help')); }, /** * Called whenever anything on the workspace changes. * Add warning if this flow block is not nested inside a loop. * @param {!Blockly.Events.Abstract} e Change event. * @this Blockly.Block */ onchange: function(e) { var legal = false; // Is the block nested in a trigger? var block = this; do { if (this.FUNCTION_TYPES.indexOf(block.type) !== -1) { legal = true; break; } block = block.getSurroundParent(); } while (block); if (legal) { this.setWarningText(null); } else { this.setWarningText(Blockly.Words['on_source_warning'][systemLang]); } }, /** * List of block types that are functions and thus do not need warnings. * To add a new function type add this to your code: * Blockly.Blocks['procedures_ifreturn'].FUNCTION_TYPES.push('custom_func'); */ FUNCTION_TYPES: ['on', 'on_ext'] }; Blockly.JavaScript['on_source'] = function(block) { var attr = block.getFieldValue('ATTR'); var parts = attr.split('.'); if (parts.length > 1) { attr = '(obj.' + parts[0] + ' ? obj.' + attr + ' : "")'; } else { attr = 'obj.' + attr; } return [attr, Blockly.JavaScript.ORDER_ATOMIC]; }; // --- SCHEDULE ----------------------------------------------------------- Blockly.Trigger.blocks['schedule'] = '' + ' ' //+ ' ' //+ ' test' //+ ' ' + ' ' + ' ' + ' ' + ''; Blockly.Blocks['schedule'] = { init: function() { this.appendDummyInput() .appendField(Blockly.Words['schedule'][systemLang]); this.appendDummyInput('SCHEDULE') .appendField(new Blockly.FieldCRON('* * * * *'), 'SCHEDULE'); this.appendStatementInput('STATEMENT') .setCheck(null); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setInputsInline(false); this.setColour(Blockly.Trigger.HUE); this.setTooltip(Blockly.Words['schedule_tooltip'][systemLang]); this.setHelpUrl(getHelp('schedule_help')); } }; Blockly.JavaScript['schedule'] = function(block) { var schedule = block.getFieldValue('SCHEDULE'); var statements_name = Blockly.JavaScript.statementToCode(block, 'STATEMENT'); return 'schedule("' + schedule +'", function () {\n' + statements_name + '});\n'; }; // --- ASTRO ----------------------------------------------------------- Blockly.Trigger.blocks['astro'] = '' + ' ' //+ ' ' //+ ' test' //+ ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ''; Blockly.Blocks['astro'] = { init: function() { this.appendDummyInput() .appendField(Blockly.Words['astro'][systemLang]); this.appendDummyInput("TYPE") .appendField(new Blockly.FieldDropdown([ [Blockly.Words['astro_sunriseText'][systemLang], "sunrise"], [Blockly.Words['astro_sunriseEndText'][systemLang], "sunriseEnd"], [Blockly.Words['astro_goldenHourEndText'][systemLang], "goldenHourEnd"], [Blockly.Words['astro_solarNoonText'][systemLang], "solarNoon"], [Blockly.Words['astro_goldenHourText'][systemLang], "goldenHour"], [Blockly.Words['astro_sunsetStartText'][systemLang], "sunsetStart"], [Blockly.Words['astro_sunsetText'][systemLang], "sunset"], [Blockly.Words['astro_duskText'][systemLang], "dusk"], [Blockly.Words['astro_nauticalDuskText'][systemLang], "nauticalDusk"], [Blockly.Words['astro_nightText'][systemLang], "night"], [Blockly.Words['astro_nightEndText'][systemLang], "nightEnd"], [Blockly.Words['astro_nauticalDawnText'][systemLang], "nauticalDawn"], [Blockly.Words['astro_dawnText'][systemLang], "dawn"], [Blockly.Words['astro_nadirText'][systemLang], "nadir"] ]), 'TYPE'); this.appendDummyInput() .appendField(Blockly.Words['astro_offset'][systemLang]); this.appendDummyInput("OFFSET") .appendField(new Blockly.FieldTextInput("0"), "OFFSET"); this.appendDummyInput() .appendField(Blockly.Words['astro_minutes'][systemLang]); this.appendStatementInput('STATEMENT') .setCheck(null); this.setInputsInline(true); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setColour(Blockly.Trigger.HUE); this.setTooltip(Blockly.Words['astro_tooltip'][systemLang]); this.setHelpUrl(getHelp('astro_help')); } }; Blockly.JavaScript['astro'] = function(block) { var astrotype = block.getFieldValue('TYPE'); var offset = parseInt(block.getFieldValue('OFFSET'), 10); var statements_name = Blockly.JavaScript.statementToCode(block, 'STATEMENT'); return 'schedule({astro: "' + astrotype + '", shift: ' + offset + '}, function () {\n' + statements_name + '});\n'; }; // --- set named schedule ----------------------------------------------------------- Blockly.Trigger.blocks['schedule_create'] = '' + ' ' + ' ' + ' ' + ' ' + ' * * * * *' + ' ' + ' ' + ' ' + ' ' + ''; /** * Ensure two identically-named procedures don't exist. * @param {string} name Proposed procedure name. * @param {!Blockly.Block} block Block to disambiguate. * @return {string} Non-colliding name. */ Blockly.Trigger.findLegalName = function(name, block) { if (block.isInFlyout) { // Flyouts can have multiple procedures called 'do something'. return name; } while (!Blockly.Trigger.isLegalName_(name, block.workspace, block)) { // Collision with another procedure. var r = name.match(/^(.*?)(\d+)$/); if (!r) { name += '2'; } else { name = r[1] + (parseInt(r[2], 10) + 1); } } return name; }; /** * Does this procedure have a legal name? Illegal names include names of * procedures already defined. * @param {string} name The questionable name. * @param {!Blockly.Workspace} workspace The workspace to scan for collisions. * @param {Blockly.Block=} opt_exclude Optional block to exclude from * comparisons (one doesn't want to collide with oneself). * @return {boolean} True if the name is legal. * @private */ Blockly.Trigger.isLegalName_ = function(name, workspace, opt_exclude) { var blocks = workspace.getAllBlocks(); // Iterate through every block and check the name. for (var i = 0; i < blocks.length; i++) { if (blocks[i] == opt_exclude) { continue; } if (blocks[i].isSchedule_) { var blockName = blocks[i].getFieldValue('NAME'); if (Blockly.Names.equals(blockName, name)) { return false; } } } return true; }; /** * Rename a procedure. Called by the editable field. * @param {string} name The proposed new name. * @return {string} The accepted name. * @this {!Blockly.Field} */ Blockly.Trigger.rename = function (name) { // Strip leading and trailing whitespace. Beyond this, all names are legal. name = name.replace(/^[\s\xa0]+|[\s\xa0]+$/g, ''); return Blockly.Trigger.findLegalName(name, this.sourceBlock_); }; Blockly.Blocks['schedule_create'] = { init: function() { var nameField = new Blockly.FieldTextInput( Blockly.Trigger.findLegalName('schedule', this), Blockly.Trigger.rename); nameField.setSpellcheck(false); this.appendDummyInput('NAME') .appendField(Blockly.Words['schedule_create'][systemLang]) .appendField(nameField, 'NAME'); this.appendValueInput('SCHEDULE') .appendField(Blockly.Words['schedule_text'][systemLang]); this.appendStatementInput('STATEMENT') .setCheck(null); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setInputsInline(false); this.setColour(Blockly.Trigger.HUE); this.setTooltip(Blockly.Words['schedule_create_tooltip'][systemLang]); this.setHelpUrl(getHelp('schedule_create_help')); }, isSchedule_: true, getVars: function () { return [this.getFieldValue('NAME')]; } }; Blockly.JavaScript['schedule_create'] = function(block) { var name = block.getFieldValue('NAME'); var schedule = Blockly.JavaScript.valueToCode(block, 'SCHEDULE', Blockly.JavaScript.ORDER_ATOMIC); var statements_name = Blockly.JavaScript.statementToCode(block, 'STATEMENT'); return name + ' = schedule(' + schedule + ', function () {\n' + statements_name + '});\n'; }; // --- clearSchedule ----------------------------------------------------------- Blockly.Trigger.getAllSchedules = function (workspace) { var blocks = workspace.getAllBlocks(); var result = []; // Iterate through every block and check the name. for (var i = 0; i < blocks.length; i++) { if (blocks[i].isSchedule_) { result.push([blocks[i].getFieldValue('NAME'), blocks[i].getFieldValue('NAME')]); } } if (!result.length) result.push(['', '']); return result; }; Blockly.Trigger.blocks['schedule_clear'] = '' + ' ' + ' ' + ''; Blockly.Blocks['schedule_clear'] = { init: function() { this.appendDummyInput('NAME') .appendField(Blockly.Words['schedule_clear'][systemLang]) .appendField(new Blockly.FieldDropdown(function () { return Blockly.Trigger.getAllSchedules(scripts.blocklyWorkspace); }), 'NAME'); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setInputsInline(true); this.setColour(Blockly.Trigger.HUE); this.setTooltip(Blockly.Words['schedule_clear_tooltip'][systemLang]); this.setHelpUrl(getHelp('schedule_clear_help')); } }; Blockly.JavaScript['schedule_clear'] = function(block) { var name = block.getFieldValue('NAME'); return '(function () {if (' + name + ') {clearSchedule(' + name + '); ' + name + ' = null;}})();\n'; }; // --- CRON dialog -------------------------------------------------- Blockly.Trigger.blocks['field_cron'] = '' + ' ' + ' ' + ''; Blockly.Blocks['field_cron'] = { // Checkbox. init: function() { this.appendDummyInput() .appendField(Blockly.Words['field_cron_CRON'][systemLang]); this.appendDummyInput() .appendField(new Blockly.FieldCRON('* * * * *'), 'CRON'); this.setInputsInline(true); this.setColour(Blockly.Trigger.HUE); this.setOutput(true, 'String'); this.setTooltip(Blockly.Words['field_cron_tooltip'][systemLang]); } }; Blockly.JavaScript['field_cron'] = function(block) { var oid = block.getFieldValue('CRON'); return ['\'' + oid + '\'', Blockly.JavaScript.ORDER_ATOMIC] }; // --- CRON builder -------------------------------------------------- Blockly.Trigger.blocks['cron_builder'] = '' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ' ' + ''; Blockly.Blocks['cron_builder'] = { // Checkbox. init: function() { this.appendDummyInput() .appendField(Blockly.Words['cron_builder_CRON'][systemLang]); this.appendDummyInput('LINE') .appendField(Blockly.Words['cron_builder_line'][systemLang]) .appendField(new Blockly.FieldCheckbox('FALSE', function (option) { this.sourceBlock_.setInputsInline(option == true); }), 'LINE'); var _input = this.appendValueInput('DOW') .appendField(Blockly.Words['cron_builder_dow'][systemLang]); var _shadow = this.workspace.newBlock('text'); _shadow.setShadow(true); _shadow.setFieldValue('*', 'TEXT'); _shadow.outputConnection.connect(_input.connection); _input = this.appendValueInput('MONTHS') .appendField(Blockly.Words['cron_builder_month'][systemLang]); _shadow = this.workspace.newBlock('text'); _shadow.setShadow(true); _shadow.setFieldValue('*', 'TEXT'); _shadow.outputConnection.connect(_input.connection); _input = this.appendValueInput('DAYS') .appendField(Blockly.Words['cron_builder_day'][systemLang]); _shadow = this.workspace.newBlock('text'); _shadow.setShadow(true); _shadow.setFieldValue('*', 'TEXT'); _shadow.outputConnection.connect(_input.connection); _input = this.appendValueInput('HOURS') .appendField(Blockly.Words['cron_builder_hour'][systemLang]); _shadow = this.workspace.newBlock('text'); _shadow.setShadow(true); _shadow.setFieldValue('*', 'TEXT'); _shadow.outputConnection.connect(_input.connection); _input = this.appendValueInput('MINUTES') .appendField(Blockly.Words['cron_builder_minutes'][systemLang]); _shadow = this.workspace.newBlock('text'); _shadow.setShadow(true); _shadow.setFieldValue('*', 'TEXT'); _shadow.outputConnection.connect(_input.connection); this.appendDummyInput('WITH_SECONDS') .appendField(Blockly.Words['cron_builder_with_seconds'][systemLang]) .appendField(new Blockly.FieldCheckbox('FALSE', function (option) { var withSeconds = (option == true); this.sourceBlock_.updateShape_(withSeconds); }), 'WITH_SECONDS'); this.seconds_ = false; this.as_line_ = false; this.setInputsInline(this.as_line_); this.setColour(Blockly.Trigger.HUE); this.setOutput(true, 'String'); this.setTooltip(Blockly.Words['field_cron_tooltip'][systemLang]); }, /** * Create XML to represent number of text inputs. * @return {!Element} XML storage element. * @this Blockly.Block */ mutationToDom: function () { var container = document.createElement('mutation'); container.setAttribute('seconds', this.seconds_); container.setAttribute('as_line', this.as_line_); return container; }, /** * Parse XML to restore the text inputs. * @param {!Element} xmlElement XML storage element. * @this Blockly.Block */ domToMutation: function (xmlElement) { this.seconds_ = xmlElement.getAttribute('seconds') === 'true'; this.as_line_ = xmlElement.getAttribute('as_line') === 'true'; this.setInputsInline(this.as_line_); this.updateShape_(this.seconds_); }, updateShape_: function(withSeconds) { this.seconds_ = withSeconds; // Add or remove a statement Input. var inputExists = this.getInput('SECONDS'); if (withSeconds) { if (!inputExists) { var _input = this.appendValueInput('SECONDS'); _input.appendField(Blockly.Words['cron_builder_seconds'][systemLang]); var _shadow = this.workspace.newBlock('text'); _shadow.setShadow(true); _shadow.setFieldValue('*', 'TEXT'); _shadow.outputConnection.connect(_input.connection); _shadow.initSvg(); _shadow.render(); } } else if (inputExists) { this.removeInput('SECONDS'); } } }; Blockly.JavaScript['cron_builder'] = function(block) { var dow = Blockly.JavaScript.valueToCode(block, 'DOW', Blockly.JavaScript.ORDER_ATOMIC); var months = Blockly.JavaScript.valueToCode(block, 'MONTHS', Blockly.JavaScript.ORDER_ATOMIC); var days = Blockly.JavaScript.valueToCode(block, 'DAYS', Blockly.JavaScript.ORDER_ATOMIC); var hours = Blockly.JavaScript.valueToCode(block, 'HOURS', Blockly.JavaScript.ORDER_ATOMIC); var minutes = Blockly.JavaScript.valueToCode(block, 'MINUTES', Blockly.JavaScript.ORDER_ATOMIC); var seconds = Blockly.JavaScript.valueToCode(block, 'SECONDS', Blockly.JavaScript.ORDER_ATOMIC); var withSeconds = block.getFieldValue('WITH_SECONDS'); var code = ((withSeconds === 'TRUE') ? seconds + '.trim() + \' \' + ' : '') + minutes + '.trim() + \' \' + ' + hours + '.trim() + \' \' + ' + days + '.trim() + \' \' + ' + months + '.trim() + \' \' + ' + dow + '.trim()'; return [code, Blockly.JavaScript.ORDER_ATOMIC] };