diff --git a/core/field.js b/core/field.js
index 54554129a..e4336819b 100644
--- a/core/field.js
+++ b/core/field.js
@@ -31,6 +31,7 @@ goog.provide('Blockly.Field');
goog.require('Blockly.Events');
goog.require('Blockly.Events.BlockChange');
goog.require('Blockly.Gesture');
+goog.require('Blockly.utils');
goog.require('Blockly.utils.dom');
goog.require('Blockly.utils.Size');
goog.require('Blockly.utils.userAgent');
@@ -44,15 +45,30 @@ goog.require('Blockly.utils.style');
* @param {Function=} opt_validator A function that is called to validate
* changes to the field's value. Takes in a value & returns a validated
* value, or null to abort the change.
+ * @param {Object=} opt_config A map of options used to configure the field. See
+ * the individual field's documentation for a list of properties this
+ * parameter supports.
* @constructor
*/
-Blockly.Field = function(value, opt_validator) {
+Blockly.Field = function(value, opt_validator, opt_config) {
/**
* The size of the area rendered by the field.
* @type {Blockly.utils.Size}
*/
this.size_ = new Blockly.utils.Size(0, 0);
+ if (opt_config) {
+ var tooltip = opt_config['tooltip'];
+ if (typeof tooltip == 'string') {
+ tooltip = Blockly.utils.replaceMessageReferences(
+ opt_config['tooltip']);
+ }
+ tooltip && this.setTooltip(tooltip);
+
+ // TODO (#2884): Possibly add CSS class config option.
+ // TODO (#2885): Possibly add cursor config option.
+ }
+
this.setValue(value);
opt_validator && this.setValidator(opt_validator);
};
diff --git a/core/field_registry.js b/core/field_registry.js
index 3bc0c549d..7556bd0d6 100644
--- a/core/field_registry.js
+++ b/core/field_registry.js
@@ -28,8 +28,6 @@
goog.provide('Blockly.fieldRegistry');
-goog.require('Blockly.utils');
-
/**
* The set of all registered fields, keyed by field type as used in the JSON
@@ -81,12 +79,5 @@ Blockly.fieldRegistry.fromJson = function(options) {
' #1584), or the registration is not being reached.');
return null;
}
-
- var field = fieldClass.fromJson(options);
- if (options['tooltip'] !== undefined) {
- var rawValue = options['tooltip'];
- var localizedText = Blockly.utils.replaceMessageReferences(rawValue);
- field.setTooltip(localizedText);
- }
- return field;
+ return fieldClass.fromJson(options);
};
diff --git a/tests/mocha/field_test.js b/tests/mocha/field_test.js
index 6d5454434..3ae3024fb 100644
--- a/tests/mocha/field_test.js
+++ b/tests/mocha/field_test.js
@@ -341,145 +341,200 @@ suite('Abstract Fields', function() {
chai.assert(this.field.doValueUpdate_.calledOnce);
});
});
- suite('setTooltip', function() {
- setup(function() {
- this.workspace = new Blockly.WorkspaceSvg({});
- this.workspace.createDom();
- });
- teardown(function() {
- this.workspace = null;
- });
- test('Before Append', function() {
- Blockly.Blocks['tooltip'] = {
- init: function() {
- var field = new Blockly.FieldTextInput('default');
- field.setTooltip('tooltip');
- this.appendDummyInput()
- .appendField(field, 'TOOLTIP');
- },
- };
- var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
- '' +
- ' ' +
- ''
- ).children[0], this.workspace);
- var field = block.getField('TOOLTIP');
- chai.assert.equal(field.getClickTarget_().tooltip, 'tooltip');
- delete Blockly.Blocks['tooltip'];
- });
- test('After Append', function() {
- Blockly.Blocks['tooltip'] = {
- init: function() {
- var field = new Blockly.FieldTextInput('default');
- this.appendDummyInput()
- .appendField(field, 'TOOLTIP');
- field.setTooltip('tooltip');
- },
- };
- var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
- '' +
- ' ' +
- ''
- ).children[0], this.workspace);
- var field = block.getField('TOOLTIP');
- chai.assert.equal(field.getClickTarget_().tooltip, 'tooltip');
- delete Blockly.Blocks['tooltip'];
- });
- test('After Block Creation', function() {
- Blockly.Blocks['tooltip'] = {
- init: function() {
- var field = new Blockly.FieldTextInput('default');
- this.appendDummyInput()
- .appendField(field, 'TOOLTIP');
- },
- };
- var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
- '' +
- ' ' +
- ''
- ).children[0], this.workspace);
- var field = block.getField('TOOLTIP');
- field.setTooltip('tooltip');
- chai.assert.equal(field.getClickTarget_().tooltip, 'tooltip');
- delete Blockly.Blocks['tooltip'];
- });
- test('Dynamic Function', function() {
- Blockly.Blocks['tooltip'] = {
- init: function() {
- var field = new Blockly.FieldTextInput('default');
- field.setTooltip(this.tooltipFunc);
- this.appendDummyInput()
- .appendField(field, 'TOOLTIP');
- },
+ suite('Customization', function() {
+ // All this field does is wrap the abstract field.
+ function CustomField(opt_config) {
+ CustomField.superClass_.constructor.call(
+ this, 'value', null, opt_config);
+ }
+ goog.inherits(CustomField, Blockly.Field);
+ CustomField.fromJson = function(options) {
+ return new CustomField(options);
+ };
- tooltipFunc: function() {
- return this.getFieldValue('TOOLTIP');
- }
- };
- var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
- '' +
- ' ' +
- ''
- ).children[0], this.workspace);
- var field = block.getField('TOOLTIP');
- chai.assert.equal(field.getClickTarget_().tooltip, block.tooltipFunc);
- delete Blockly.Blocks['tooltip'];
- });
- test('Element', function() {
- Blockly.Blocks['tooltip'] = {
- init: function() {
- var field = new Blockly.FieldTextInput('default');
- field.setTooltip(this.element);
- this.appendDummyInput()
- .appendField(field, 'TOOLTIP');
- },
- element: {
- tooltip: 'tooltip'
- }
- };
- var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
- '' +
- ' ' +
- ''
- ).children[0], this.workspace);
- var field = block.getField('TOOLTIP');
- chai.assert.equal(field.getClickTarget_().tooltip, block.element);
- delete Blockly.Blocks['tooltip'];
- });
- test('Null', function() {
- Blockly.Blocks['tooltip'] = {
- init: function() {
- var field = new Blockly.FieldTextInput('default');
- field.setTooltip(null);
- this.appendDummyInput()
- .appendField(field, 'TOOLTIP');
- },
- };
- var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
- '' +
- ' ' +
- ''
- ).children[0], this.workspace);
- var field = block.getField('TOOLTIP');
- chai.assert.equal(field.getClickTarget_().tooltip, block);
- delete Blockly.Blocks['tooltip'];
- });
- test('Undefined', function() {
- Blockly.Blocks['tooltip'] = {
- init: function() {
- var field = new Blockly.FieldTextInput('default');
- this.appendDummyInput()
- .appendField(field, 'TOOLTIP');
- },
- };
- var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
- '' +
- ' ' +
- ''
- ).children[0], this.workspace);
- var field = block.getField('TOOLTIP');
- chai.assert.equal(field.getClickTarget_().tooltip, block);
- delete Blockly.Blocks['tooltip'];
+ suite('Tooltip', function() {
+ test('JS Constructor', function() {
+ var field = new Blockly.Field('value', null, {
+ tooltip: 'test tooltip',
+ });
+ chai.assert.equal(field.tooltip_, 'test tooltip');
+ });
+ test('JS Constructor - Dynamic', function() {
+ var returnTooltip = function() {
+ return 'dynamic tooltip text';
+ };
+ var field = new Blockly.Field('value', null, {
+ tooltip: returnTooltip
+ });
+ chai.assert.equal(field.tooltip_, returnTooltip);
+ });
+ test('JSON Definition', function() {
+ var field = CustomField.fromJson({
+ tooltip: "test tooltip"
+ });
+ chai.assert.equal(field.tooltip_, 'test tooltip');
+ });
+ suite('W/ Msg References', function() {
+ setup(function() {
+ Blockly.Msg['TOOLTIP'] = 'test tooltip';
+ });
+ teardown(function() {
+ delete Blockly.Msg['TOOLTIP'];
+ });
+ test('JS Constructor', function() {
+ var field = new Blockly.Field('value', null, {
+ tooltip: '%{BKY_TOOLTIP}',
+ });
+ chai.assert.equal(field.tooltip_, 'test tooltip');
+ });
+ test('JSON Definition', function() {
+ var field = CustomField.fromJson({
+ tooltip: "%{BKY_TOOLTIP}"
+ });
+ chai.assert.equal(field.tooltip_, 'test tooltip');
+ });
+ });
+ suite('setTooltip', function() {
+ setup(function() {
+ this.workspace = new Blockly.WorkspaceSvg({});
+ this.workspace.createDom();
+ });
+ teardown(function() {
+ this.workspace = null;
+ });
+ test('Before Append', function() {
+ Blockly.Blocks['tooltip'] = {
+ init: function() {
+ var field = new Blockly.FieldTextInput('default');
+ field.setTooltip('tooltip');
+ this.appendDummyInput()
+ .appendField(field, 'TOOLTIP');
+ },
+ };
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ''
+ ).children[0], this.workspace);
+ var field = block.getField('TOOLTIP');
+ chai.assert.equal(field.getClickTarget_().tooltip, 'tooltip');
+ delete Blockly.Blocks['tooltip'];
+ });
+ test('After Append', function() {
+ Blockly.Blocks['tooltip'] = {
+ init: function() {
+ var field = new Blockly.FieldTextInput('default');
+ this.appendDummyInput()
+ .appendField(field, 'TOOLTIP');
+ field.setTooltip('tooltip');
+ },
+ };
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ''
+ ).children[0], this.workspace);
+ var field = block.getField('TOOLTIP');
+ chai.assert.equal(field.getClickTarget_().tooltip, 'tooltip');
+ delete Blockly.Blocks['tooltip'];
+ });
+ test('After Block Creation', function() {
+ Blockly.Blocks['tooltip'] = {
+ init: function() {
+ var field = new Blockly.FieldTextInput('default');
+ this.appendDummyInput()
+ .appendField(field, 'TOOLTIP');
+ },
+ };
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ''
+ ).children[0], this.workspace);
+ var field = block.getField('TOOLTIP');
+ field.setTooltip('tooltip');
+ chai.assert.equal(field.getClickTarget_().tooltip, 'tooltip');
+ delete Blockly.Blocks['tooltip'];
+ });
+ test('Dynamic Function', function() {
+ Blockly.Blocks['tooltip'] = {
+ init: function() {
+ var field = new Blockly.FieldTextInput('default');
+ field.setTooltip(this.tooltipFunc);
+ this.appendDummyInput()
+ .appendField(field, 'TOOLTIP');
+ },
+
+ tooltipFunc: function() {
+ return this.getFieldValue('TOOLTIP');
+ }
+ };
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ''
+ ).children[0], this.workspace);
+ var field = block.getField('TOOLTIP');
+ chai.assert.equal(field.getClickTarget_().tooltip, block.tooltipFunc);
+ delete Blockly.Blocks['tooltip'];
+ });
+ test('Element', function() {
+ Blockly.Blocks['tooltip'] = {
+ init: function() {
+ var field = new Blockly.FieldTextInput('default');
+ field.setTooltip(this.element);
+ this.appendDummyInput()
+ .appendField(field, 'TOOLTIP');
+ },
+ element: {
+ tooltip: 'tooltip'
+ }
+ };
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ''
+ ).children[0], this.workspace);
+ var field = block.getField('TOOLTIP');
+ chai.assert.equal(field.getClickTarget_().tooltip, block.element);
+ delete Blockly.Blocks['tooltip'];
+ });
+ test('Null', function() {
+ Blockly.Blocks['tooltip'] = {
+ init: function() {
+ var field = new Blockly.FieldTextInput('default');
+ field.setTooltip(null);
+ this.appendDummyInput()
+ .appendField(field, 'TOOLTIP');
+ },
+ };
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ''
+ ).children[0], this.workspace);
+ var field = block.getField('TOOLTIP');
+ chai.assert.equal(field.getClickTarget_().tooltip, block);
+ delete Blockly.Blocks['tooltip'];
+ });
+ test('Undefined', function() {
+ Blockly.Blocks['tooltip'] = {
+ init: function() {
+ var field = new Blockly.FieldTextInput('default');
+ this.appendDummyInput()
+ .appendField(field, 'TOOLTIP');
+ },
+ };
+ var block = Blockly.Xml.domToBlock(Blockly.Xml.textToDom(
+ '' +
+ ' ' +
+ ''
+ ).children[0], this.workspace);
+ var field = block.getField('TOOLTIP');
+ chai.assert.equal(field.getClickTarget_().tooltip, block);
+ delete Blockly.Blocks['tooltip'];
+ });
+ });
});
});
});