Allow images in dropdown menus.

This commit is contained in:
Neil Fraser
2016-11-05 00:17:07 -07:00
parent 5b033e2f7b
commit 98c341bcfb
3 changed files with 215 additions and 78 deletions

View File

@@ -39,8 +39,8 @@ goog.require('goog.userAgent');
/** /**
* Class for an editable dropdown field. * Class for an editable dropdown field.
* @param {(!Array.<!Array.<string>>|!Function)} menuGenerator An array of * @param {(!Array.<!Array>|!Function)} menuGenerator An array of options
* options for a dropdown list, or a function which generates these options. * for a dropdown list, or a function which generates these options.
* @param {Function=} opt_validator A function that is executed when a new * @param {Function=} opt_validator A function that is executed when a new
* option is selected, with the newly selected value as its sole argument. * option is selected, with the newly selected value as its sole argument.
* If it returns a value, that value (which must be one of the options) will * If it returns a value, that value (which must be one of the options) will
@@ -76,12 +76,27 @@ Blockly.FieldDropdown.ARROW_CHAR = goog.userAgent.ANDROID ? '\u25BC' : '\u25BE';
Blockly.FieldDropdown.prototype.CURSOR = 'default'; Blockly.FieldDropdown.prototype.CURSOR = 'default';
/** /**
* Language-neutral currently selected string. * Language-neutral currently selected string or image object.
* @type {string} * @type {string|!Object}
* @private * @private
*/ */
Blockly.FieldDropdown.prototype.value_ = ''; Blockly.FieldDropdown.prototype.value_ = '';
/**
* SVG image element if currently selected option is an image, or null.
* @type {SVGElement}
* @private
*/
Blockly.FieldDropdown.prototype.imageElement_ = null;
/**
* Object wih src, height, width, and alt attributes if currently selected
* option is an image, or null.
* @type {Object}
* @private
*/
Blockly.FieldDropdown.prototype.imageJson_ = null;
/** /**
* Install this dropdown on a block. * Install this dropdown on a block.
*/ */
@@ -124,9 +139,16 @@ Blockly.FieldDropdown.prototype.showEditor_ = function() {
menu.setRightToLeft(this.sourceBlock_.RTL); menu.setRightToLeft(this.sourceBlock_.RTL);
var options = this.getOptions_(); var options = this.getOptions_();
for (var i = 0; i < options.length; i++) { for (var i = 0; i < options.length; i++) {
var text = options[i][0]; // Human-readable text. var content = options[i][0]; // Human-readable text or image.
var value = options[i][1]; // Language-neutral value. var value = options[i][1]; // Language-neutral value.
var menuItem = new goog.ui.MenuItem(text); if (typeof content == 'object') {
// An image, not text.
var image = new Image(content['width'], content['height']);
image.src = content['src'];
image.alt = content['alt'] || '';
content = image;
}
var menuItem = new goog.ui.MenuItem(content);
menuItem.setRightToLeft(this.sourceBlock_.RTL); menuItem.setRightToLeft(this.sourceBlock_.RTL);
menuItem.setValue(value); menuItem.setValue(value);
menuItem.setCheckable(true); menuItem.setCheckable(true);
@@ -221,7 +243,13 @@ Blockly.FieldDropdown.prototype.trimOptions_ = function() {
if (!goog.isArray(options) || options.length < 2) { if (!goog.isArray(options) || options.length < 2) {
return; return;
} }
var strings = options.map(function(t) {return t[0];}); var strings = [];
for (var i = 0; i < options.length; i++) {
var text = options[i][0];
if (typeof text == 'string') {
strings.push(text);
}
}
var shortest = Blockly.shortestStringLength(strings); var shortest = Blockly.shortestStringLength(strings);
var prefixLength = Blockly.commonWordPrefix(strings, shortest); var prefixLength = Blockly.commonWordPrefix(strings, shortest);
var suffixLength = Blockly.commonWordSuffix(strings, shortest); var suffixLength = Blockly.commonWordSuffix(strings, shortest);
@@ -242,17 +270,19 @@ Blockly.FieldDropdown.prototype.trimOptions_ = function() {
var newOptions = []; var newOptions = [];
for (var i = 0; i < options.length; i++) { for (var i = 0; i < options.length; i++) {
var text = options[i][0]; var text = options[i][0];
if (typeof text == 'string') {
var value = options[i][1]; var value = options[i][1];
text = text.substring(prefixLength, text.length - suffixLength); text = text.substring(prefixLength, text.length - suffixLength);
newOptions[i] = [text, value]; newOptions[i] = [text, value];
} }
}
this.menuGenerator_ = newOptions; this.menuGenerator_ = newOptions;
}; };
/** /**
* Return a list of the options for this dropdown. * Return a list of the options for this dropdown.
* @return {!Array.<!Array.<string>>} Array of option tuples: * @return {!Array.<!Array>} Array of option tuples:
* (human-readable text, language-neutral name). * (human-readable text or image, language-neutral name).
* @private * @private
*/ */
Blockly.FieldDropdown.prototype.getOptions_ = function() { Blockly.FieldDropdown.prototype.getOptions_ = function() {
@@ -288,7 +318,22 @@ Blockly.FieldDropdown.prototype.setValue = function(newValue) {
for (var i = 0; i < options.length; i++) { for (var i = 0; i < options.length; i++) {
// Options are tuples of human-readable text and language-neutral values. // Options are tuples of human-readable text and language-neutral values.
if (options[i][1] == newValue) { if (options[i][1] == newValue) {
this.setText(options[i][0]); var content = options[i][0];
goog.dom.removeNode(this.imageElement_);
if (typeof content == 'object') {
this.imageJson_ = content;
this.imageElement_ = Blockly.createSvgElement('image',
{'y': 5,
'height': content.height + 'px',
'width': content.width + 'px'}, this.fieldGroup_);
this.imageElement_.setAttributeNS('http://www.w3.org/1999/xlink',
'xlink:href', content.src);
this.setText(content.alt);
} else {
this.imageJson_ = null;
this.imageElement_ = null;
this.setText(content);
}
return; return;
} }
} }
@@ -306,12 +351,28 @@ Blockly.FieldDropdown.prototype.setText = function(text) {
// Update arrow's colour. // Update arrow's colour.
this.arrow_.style.fill = this.sourceBlock_.getColour(); this.arrow_.style.fill = this.sourceBlock_.getColour();
} }
if (text === null || text === this.text_) { if (text === null) {
// No change if null. // No change if null.
return; return;
} }
this.text_ = text; this.text_ = text;
if (this.imageJson_) {
if (this.textElement_) {
this.textElement_.style.display = 'none';
}
this.size_.height = Number(this.imageJson_.height) + 19;
this.render_();
} else {
if (this.textElement_) {
this.textElement_.style.display = 'block';
}
this.size_.height = Blockly.BlockSvg.MIN_BLOCK_Y;
this.updateTextNode_(); this.updateTextNode_();
}
// Unlike other editable fields, a dropdown can change height.
if (this.borderRect_) {
this.borderRect_.setAttribute('height', this.size_.height - 9);
}
if (this.textElement_) { if (this.textElement_) {
// Insert dropdown arrow. // Insert dropdown arrow.
@@ -328,6 +389,20 @@ Blockly.FieldDropdown.prototype.setText = function(text) {
} }
}; };
/**
* Draws the border with the correct width.
* @private
*/
Blockly.FieldDropdown.prototype.render_ = function() {
if (!this.imageJson_) {
Blockly.FieldDropdown.superClass_.render_.call(this);
} else if (this.visible_ && this.borderRect_) {
this.size_.width = Number(this.imageJson_.width);
this.borderRect_.setAttribute('width',
this.size_.width + Blockly.BlockSvg.SEP_SPACE_X);
}
};
/** /**
* Close the dropdown menu if this input is being deleted. * Close the dropdown menu if this input is being deleted.
*/ */

View File

@@ -318,11 +318,12 @@ Blockly.Blocks['field_dropdown'] = {
this.appendDummyInput() this.appendDummyInput()
.appendField('dropdown') .appendField('dropdown')
.appendField(new Blockly.FieldTextInput('NAME'), 'FIELDNAME'); .appendField(new Blockly.FieldTextInput('NAME'), 'FIELDNAME');
this.optionCount_ = 3; this.optionList_ = ['text', 'text', 'text'];
this.updateShape_(); this.updateShape_();
this.setPreviousStatement(true, 'Field'); this.setPreviousStatement(true, 'Field');
this.setNextStatement(true, 'Field'); this.setNextStatement(true, 'Field');
this.setMutator(new Blockly.Mutator(['field_dropdown_option'])); this.setMutator(new Blockly.Mutator(['field_dropdown_option_text',
'field_dropdown_option_image']));
this.setColour(160); this.setColour(160);
this.setTooltip('Dropdown menu with a list of options.'); this.setTooltip('Dropdown menu with a list of options.');
this.setHelpUrl('https://www.youtube.com/watch?v=s2_xaEvcVI0#t=386'); this.setHelpUrl('https://www.youtube.com/watch?v=s2_xaEvcVI0#t=386');
@@ -330,12 +331,21 @@ Blockly.Blocks['field_dropdown'] = {
mutationToDom: function(workspace) { mutationToDom: function(workspace) {
// Create XML to represent menu options. // Create XML to represent menu options.
var container = document.createElement('mutation'); var container = document.createElement('mutation');
container.setAttribute('options', this.optionCount_); container.setAttribute('options', JSON.stringify(this.optionList_));
return container; return container;
}, },
domToMutation: function(container) { domToMutation: function(container) {
// Parse XML to restore the menu options. // Parse XML to restore the menu options.
this.optionCount_ = parseInt(container.getAttribute('options'), 10); var value = JSON.parse(container.getAttribute('options'));
if (typeof value == 'number') {
// Old format from before images were added. November 2016.
this.optionList_ = [];
for (var i = 0; i < value; i++) {
this.optionList_.push('text');
}
} else {
this.optionList_ = value;
}
this.updateShape_(); this.updateShape_();
}, },
decompose: function(workspace) { decompose: function(workspace) {
@@ -343,8 +353,9 @@ Blockly.Blocks['field_dropdown'] = {
var containerBlock = workspace.newBlock('field_dropdown_container'); var containerBlock = workspace.newBlock('field_dropdown_container');
containerBlock.initSvg(); containerBlock.initSvg();
var connection = containerBlock.getInput('STACK').connection; var connection = containerBlock.getInput('STACK').connection;
for (var i = 0; i < this.optionCount_; i++) { for (var i = 0; i < this.optionList_.length; i++) {
var optionBlock = workspace.newBlock('field_dropdown_option'); var optionBlock = workspace.newBlock(
'field_dropdown_option_' + this.optionList_[i]);
optionBlock.initSvg(); optionBlock.initSvg();
connection.connect(optionBlock.previousConnection); connection.connect(optionBlock.previousConnection);
connection = optionBlock.nextConnection; connection = optionBlock.nextConnection;
@@ -355,26 +366,41 @@ Blockly.Blocks['field_dropdown'] = {
// Reconfigure this block based on the mutator dialog's components. // Reconfigure this block based on the mutator dialog's components.
var optionBlock = containerBlock.getInputTargetBlock('STACK'); var optionBlock = containerBlock.getInputTargetBlock('STACK');
// Count number of inputs. // Count number of inputs.
this.optionList_.length = 0;
var data = []; var data = [];
while (optionBlock) { while (optionBlock) {
if (optionBlock.type == 'field_dropdown_option_text') {
this.optionList_.push('text');
} else if (optionBlock.type == 'field_dropdown_option_image') {
this.optionList_.push('image');
}
data.push([optionBlock.userData_, optionBlock.cpuData_]); data.push([optionBlock.userData_, optionBlock.cpuData_]);
optionBlock = optionBlock.nextConnection && optionBlock = optionBlock.nextConnection &&
optionBlock.nextConnection.targetBlock(); optionBlock.nextConnection.targetBlock();
} }
this.optionCount_ = data.length;
this.updateShape_(); this.updateShape_();
// Restore any data. // Restore any data.
for (var i = 0; i < this.optionCount_; i++) { for (var i = 0; i < this.optionList_.length; i++) {
this.setFieldValue(data[i][0] || 'option', 'USER' + i); var userData = data[i][0];
if (userData !== undefined) {
if (typeof userData == 'string') {
this.setFieldValue(userData || 'option', 'USER' + i);
} else {
this.setFieldValue(userData.src, 'SRC' + i);
this.setFieldValue(userData.width, 'WIDTH' + i);
this.setFieldValue(userData.height, 'HEIGHT' + i);
this.setFieldValue(userData.alt, 'ALT' + i);
}
this.setFieldValue(data[i][1] || 'OPTIONNAME', 'CPU' + i); this.setFieldValue(data[i][1] || 'OPTIONNAME', 'CPU' + i);
} }
}
}, },
saveConnections: function(containerBlock) { saveConnections: function(containerBlock) {
// Store names and values for each option. // Store all data for each option.
var optionBlock = containerBlock.getInputTargetBlock('STACK'); var optionBlock = containerBlock.getInputTargetBlock('STACK');
var i = 0; var i = 0;
while (optionBlock) { while (optionBlock) {
optionBlock.userData_ = this.getFieldValue('USER' + i); optionBlock.userData_ = this.getUserData(i);
optionBlock.cpuData_ = this.getFieldValue('CPU' + i); optionBlock.cpuData_ = this.getFieldValue('CPU' + i);
i++; i++;
optionBlock = optionBlock.nextConnection && optionBlock = optionBlock.nextConnection &&
@@ -382,28 +408,61 @@ Blockly.Blocks['field_dropdown'] = {
} }
}, },
updateShape_: function() { updateShape_: function() {
// Modify this block to have the correct number of options. // Delete everything.
// Add new options. var i = 0;
for (var i = 0; i < this.optionCount_; i++) { while (this.getInput('OPTION' + i)) {
if (!this.getInput('OPTION' + i)) { this.removeInput('OPTION' + i);
this.removeInput('OPTION_IMAGE' + i, true);
i++;
}
// Rebuild block.
var src = 'https://www.gstatic.com/codesite/ph/images/star_on.gif';
for (var i = 0; i <= this.optionList_.length; i++) {
var type = this.optionList_[i];
if (type == 'text') {
this.appendDummyInput('OPTION' + i) this.appendDummyInput('OPTION' + i)
.appendField('•')
.appendField(new Blockly.FieldTextInput('option'), 'USER' + i) .appendField(new Blockly.FieldTextInput('option'), 'USER' + i)
.appendField(',') .appendField(',')
.appendField(new Blockly.FieldTextInput('OPTIONNAME'), 'CPU' + i); .appendField(new Blockly.FieldTextInput('OPTIONNAME'), 'CPU' + i);
} else if (type == 'image') {
this.appendDummyInput('OPTION' + i)
.appendField('•')
.appendField('image')
.appendField(new Blockly.FieldTextInput(src), 'SRC' + i);
this.appendDummyInput('OPTION_IMAGE' + i)
.appendField(' ')
.appendField('width')
.appendField(new Blockly.FieldNumber('15', 0, NaN, 1), 'WIDTH' + i)
.appendField('height')
.appendField(new Blockly.FieldNumber('15', 0, NaN, 1), 'HEIGHT' + i)
.appendField('alt text')
.appendField(new Blockly.FieldTextInput('*'), 'ALT' + i)
.appendField(',')
.appendField(new Blockly.FieldTextInput('OPTIONNAME'), 'CPU' + i);
} }
} }
// Remove deleted options.
while (this.getInput('OPTION' + i)) {
this.removeInput('OPTION' + i);
i++;
}
}, },
onchange: function() { onchange: function() {
if (this.workspace && this.optionCount_ < 1) { if (this.workspace && this.optionList_.length < 1) {
this.setWarningText('Drop down menu must\nhave at least one option.'); this.setWarningText('Drop down menu must\nhave at least one option.');
} else { } else {
fieldNameCheck(this); fieldNameCheck(this);
} }
},
getUserData: function(n) {
if (this.optionList_[n] == 'text') {
return this.getFieldValue('USER' + n);
}
if (this.optionList_[n] == 'image') {
return {
src: this.getFieldValue('SRC' + n),
width: Number(this.getFieldValue('WIDTH' + n)),
height: Number(this.getFieldValue('HEIGHT' + n)),
alt: this.getFieldValue('ALT' + n)
};
}
throw 'Unknown dropdown type';
} }
}; };
@@ -421,15 +480,29 @@ Blockly.Blocks['field_dropdown_container'] = {
} }
}; };
Blockly.Blocks['field_dropdown_option'] = { Blockly.Blocks['field_dropdown_option_text'] = {
// Add option. // Add text option.
init: function() { init: function() {
this.setColour(160); this.setColour(160);
this.appendDummyInput() this.appendDummyInput()
.appendField('option'); .appendField('text option');
this.setPreviousStatement(true); this.setPreviousStatement(true);
this.setNextStatement(true); this.setNextStatement(true);
this.setTooltip('Add a new option to the dropdown menu.'); this.setTooltip('Add a new text option to the dropdown menu.');
this.setHelpUrl('https://www.youtube.com/watch?v=s2_xaEvcVI0#t=386');
this.contextMenu = false;
}
};
Blockly.Blocks['field_dropdown_option_image'] = {
// Add image option.
init: function() {
this.setColour(160);
this.appendDummyInput()
.appendField('image option');
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip('Add a new image option to the dropdown menu.');
this.setHelpUrl('https://www.youtube.com/watch?v=s2_xaEvcVI0#t=386'); this.setHelpUrl('https://www.youtube.com/watch?v=s2_xaEvcVI0#t=386');
this.contextMenu = false; this.contextMenu = false;
} }

View File

@@ -278,7 +278,7 @@ FactoryUtils.formatJavaScript_ = function(blockType, rootBlock, workspace) {
// Dummy inputs don't have names. Other inputs do. // Dummy inputs don't have names. Other inputs do.
if (contentsBlock.type != 'input_dummy') { if (contentsBlock.type != 'input_dummy') {
name = name =
FactoryUtils.escapeString(contentsBlock.getFieldValue('INPUTNAME')); JSON.stringify(contentsBlock.getFieldValue('INPUTNAME'));
} }
code.push(' this.' + TYPES[contentsBlock.type] + '(' + name + ')'); code.push(' this.' + TYPES[contentsBlock.type] + '(' + name + ')');
var check = FactoryUtils.getOptTypesFrom(contentsBlock, 'TYPE'); var check = FactoryUtils.getOptTypesFrom(contentsBlock, 'TYPE');
@@ -373,13 +373,13 @@ FactoryUtils.getFieldsJs_ = function(block) {
switch (block.type) { switch (block.type) {
case 'field_static': case 'field_static':
// Result: 'hello' // Result: 'hello'
fields.push(FactoryUtils.escapeString(block.getFieldValue('TEXT'))); fields.push(JSON.stringify(block.getFieldValue('TEXT')));
break; break;
case 'field_input': case 'field_input':
// Result: new Blockly.FieldTextInput('Hello'), 'GREET' // Result: new Blockly.FieldTextInput('Hello'), 'GREET'
fields.push('new Blockly.FieldTextInput(' + fields.push('new Blockly.FieldTextInput(' +
FactoryUtils.escapeString(block.getFieldValue('TEXT')) + '), ' + JSON.stringify(block.getFieldValue('TEXT')) + '), ' +
FactoryUtils.escapeString(block.getFieldValue('FIELDNAME'))); JSON.stringify(block.getFieldValue('FIELDNAME')));
break; break;
case 'field_number': case 'field_number':
// Result: new Blockly.FieldNumber(10, 0, 100, 1), 'NUMBER' // Result: new Blockly.FieldNumber(10, 0, 100, 1), 'NUMBER'
@@ -400,63 +400,61 @@ FactoryUtils.getFieldsJs_ = function(block) {
} }
} }
fields.push('new Blockly.FieldNumber(' + args.join(', ') + '), ' + fields.push('new Blockly.FieldNumber(' + args.join(', ') + '), ' +
FactoryUtils.escapeString(block.getFieldValue('FIELDNAME'))); JSON.stringify(block.getFieldValue('FIELDNAME')));
break; break;
case 'field_angle': case 'field_angle':
// Result: new Blockly.FieldAngle(90), 'ANGLE' // Result: new Blockly.FieldAngle(90), 'ANGLE'
fields.push('new Blockly.FieldAngle(' + fields.push('new Blockly.FieldAngle(' +
parseFloat(block.getFieldValue('ANGLE')) + '), ' + parseFloat(block.getFieldValue('ANGLE')) + '), ' +
FactoryUtils.escapeString(block.getFieldValue('FIELDNAME'))); JSON.stringify(block.getFieldValue('FIELDNAME')));
break; break;
case 'field_checkbox': case 'field_checkbox':
// Result: new Blockly.FieldCheckbox('TRUE'), 'CHECK' // Result: new Blockly.FieldCheckbox('TRUE'), 'CHECK'
fields.push('new Blockly.FieldCheckbox(' + fields.push('new Blockly.FieldCheckbox(' +
FactoryUtils.escapeString(block.getFieldValue('CHECKED')) + JSON.stringify(block.getFieldValue('CHECKED')) +
'), ' + '), ' +
FactoryUtils.escapeString(block.getFieldValue('FIELDNAME'))); JSON.stringify(block.getFieldValue('FIELDNAME')));
break; break;
case 'field_colour': case 'field_colour':
// Result: new Blockly.FieldColour('#ff0000'), 'COLOUR' // Result: new Blockly.FieldColour('#ff0000'), 'COLOUR'
fields.push('new Blockly.FieldColour(' + fields.push('new Blockly.FieldColour(' +
FactoryUtils.escapeString(block.getFieldValue('COLOUR')) + JSON.stringify(block.getFieldValue('COLOUR')) +
'), ' + '), ' +
FactoryUtils.escapeString(block.getFieldValue('FIELDNAME'))); JSON.stringify(block.getFieldValue('FIELDNAME')));
break; break;
case 'field_date': case 'field_date':
// Result: new Blockly.FieldDate('2015-02-04'), 'DATE' // Result: new Blockly.FieldDate('2015-02-04'), 'DATE'
fields.push('new Blockly.FieldDate(' + fields.push('new Blockly.FieldDate(' +
FactoryUtils.escapeString(block.getFieldValue('DATE')) + '), ' + JSON.stringify(block.getFieldValue('DATE')) + '), ' +
FactoryUtils.escapeString(block.getFieldValue('FIELDNAME'))); JSON.stringify(block.getFieldValue('FIELDNAME')));
break; break;
case 'field_variable': case 'field_variable':
// Result: new Blockly.FieldVariable('item'), 'VAR' // Result: new Blockly.FieldVariable('item'), 'VAR'
var varname var varname
= FactoryUtils.escapeString(block.getFieldValue('TEXT') || null); = JSON.stringify(block.getFieldValue('TEXT') || null);
fields.push('new Blockly.FieldVariable(' + varname + '), ' + fields.push('new Blockly.FieldVariable(' + varname + '), ' +
FactoryUtils.escapeString(block.getFieldValue('FIELDNAME'))); JSON.stringify(block.getFieldValue('FIELDNAME')));
break; break;
case 'field_dropdown': case 'field_dropdown':
// Result: // Result:
// new Blockly.FieldDropdown([['yes', '1'], ['no', '0']]), 'TOGGLE' // new Blockly.FieldDropdown([['yes', '1'], ['no', '0']]), 'TOGGLE'
var options = []; var options = [];
for (var i = 0; i < block.optionCount_; i++) { for (var i = 0; i < block.optionList_.length; i++) {
options[i] = '[' + options[i] = JSON.stringify([block.getUserData(i),
FactoryUtils.escapeString(block.getFieldValue('USER' + i)) + block.getFieldValue('CPU' + i)]);
', ' +
FactoryUtils.escapeString(block.getFieldValue('CPU' + i)) + ']';
} }
if (options.length) { if (options.length) {
fields.push('new Blockly.FieldDropdown([' + fields.push('new Blockly.FieldDropdown([' +
options.join(', ') + ']), ' + options.join(', ') + ']), ' +
FactoryUtils.escapeString(block.getFieldValue('FIELDNAME'))); JSON.stringify(block.getFieldValue('FIELDNAME')));
} }
break; break;
case 'field_image': case 'field_image':
// Result: new Blockly.FieldImage('http://...', 80, 60) // Result: new Blockly.FieldImage('http://...', 80, 60, '*')
var src = FactoryUtils.escapeString(block.getFieldValue('SRC')); var src = JSON.stringify(block.getFieldValue('SRC'));
var width = Number(block.getFieldValue('WIDTH')); var width = Number(block.getFieldValue('WIDTH'));
var height = Number(block.getFieldValue('HEIGHT')); var height = Number(block.getFieldValue('HEIGHT'));
var alt = FactoryUtils.escapeString(block.getFieldValue('ALT')); var alt = JSON.stringify(block.getFieldValue('ALT'));
fields.push('new Blockly.FieldImage(' + fields.push('new Blockly.FieldImage(' +
src + ', ' + width + ', ' + height + ', ' + alt + ')'); src + ', ' + width + ', ' + height + ', ' + alt + ')');
break; break;
@@ -546,8 +544,8 @@ FactoryUtils.getFieldsJson_ = function(block) {
break; break;
case 'field_dropdown': case 'field_dropdown':
var options = []; var options = [];
for (var i = 0; i < block.optionCount_; i++) { for (var i = 0; i < block.optionList_.length; i++) {
options[i] = [block.getFieldValue('USER' + i), options[i] = [block.getUserData(i),
block.getFieldValue('CPU' + i)]; block.getFieldValue('CPU' + i)];
} }
if (options.length) { if (options.length) {
@@ -608,7 +606,7 @@ FactoryUtils.getTypesFrom_ = function(block, name) {
if (!typeBlock || typeBlock.disabled) { if (!typeBlock || typeBlock.disabled) {
types = []; types = [];
} else if (typeBlock.type == 'type_other') { } else if (typeBlock.type == 'type_other') {
types = [FactoryUtils.escapeString(typeBlock.getFieldValue('TYPE'))]; types = [JSON.stringify(typeBlock.getFieldValue('TYPE'))];
} else if (typeBlock.type == 'type_group') { } else if (typeBlock.type == 'type_group') {
types = []; types = [];
for (var n = 0; n < typeBlock.typeCount_; n++) { for (var n = 0; n < typeBlock.typeCount_; n++) {
@@ -623,20 +621,11 @@ FactoryUtils.getTypesFrom_ = function(block, name) {
hash[types[n]] = true; hash[types[n]] = true;
} }
} else { } else {
types = [FactoryUtils.escapeString(typeBlock.valueType)]; types = [JSON.stringify(typeBlock.valueType)];
} }
return types; return types;
}; };
/**
* Escape a string.
* @param {string} string String to escape.
* @return {string} Escaped string surrouned by quotes.
*/
FactoryUtils.escapeString = function(string) {
return JSON.stringify(string);
};
/** /**
* Return the uneditable container block that everything else attaches to in * Return the uneditable container block that everything else attaches to in
* given workspace. * given workspace.