From 821edb7e2233d508201c665d167443f45deef267 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Thu, 22 Aug 2019 13:55:41 -0700 Subject: [PATCH] Changed Checkbox Field to New Configuration Paradigm (#2876) * Moved checkbox field to new configuration paradigm. --- core/field_checkbox.js | 52 ++++++++++++++++++++++++++---- tests/mocha/field_checkbox_test.js | 51 +++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 6 deletions(-) diff --git a/core/field_checkbox.js b/core/field_checkbox.js index 7f4ec4caf..353dfc8e7 100644 --- a/core/field_checkbox.js +++ b/core/field_checkbox.js @@ -42,16 +42,31 @@ goog.require('Blockly.utils.Size'); * changes to the field's value. Takes in a value ('TRUE' or 'FALSE') & * returns a validated value ('TRUE' or 'FALSE'), or null to abort the * change. + * @param {Object=} opt_config A map of options used to configure the field. + * See the [field creation documentation]{@link https://developers.google.com/blockly/guides/create-custom-blocks/fields/built-in-fields/checkbox#creation} + * for a list of properties this parameter supports. * @extends {Blockly.Field} * @constructor */ -Blockly.FieldCheckbox = function(opt_value, opt_validator) { +Blockly.FieldCheckbox = function(opt_value, opt_validator, opt_config) { opt_value = this.doClassValidation_(opt_value); if (opt_value === null) { opt_value = 'FALSE'; } - Blockly.FieldCheckbox.superClass_.constructor.call(this, opt_value, opt_validator); + Blockly.FieldCheckbox.superClass_.constructor.call( + this, opt_value, opt_validator, opt_config); + this.size_.width = Blockly.FieldCheckbox.WIDTH; + + /** + * Character for the check mark. Used to apply a different check mark + * character to individual fields. + * @type {?string} + * @private + */ + this.checkChar_ = null; + + this.configure_(opt_config); }; goog.inherits(Blockly.FieldCheckbox, Blockly.Field); @@ -63,7 +78,7 @@ goog.inherits(Blockly.FieldCheckbox, Blockly.Field); * @nocollapse */ Blockly.FieldCheckbox.fromJson = function(options) { - return new Blockly.FieldCheckbox(options['checked']); + return new Blockly.FieldCheckbox(options['checked'], null, options); }; /** @@ -74,7 +89,7 @@ Blockly.FieldCheckbox.fromJson = function(options) { Blockly.FieldCheckbox.WIDTH = 15; /** - * Character for the checkmark. + * Default character for the checkmark. * @type {string} * @const */ @@ -116,6 +131,19 @@ Blockly.FieldCheckbox.prototype.CURSOR = 'default'; */ Blockly.FieldCheckbox.prototype.isDirty_ = false; +/** + * Configure the field based on the given map of options. + * @param {Object} opt_config A map of options to configure the field based on. + * @private + */ +Blockly.FieldCheckbox.prototype.configure_ = function(opt_config) { + if (opt_config) { + if (opt_config['checkCharacter']) { + this.checkChar_ = opt_config['checkCharacter']; + } + } +}; + /** * Create the block UI for this checkbox. * @package @@ -127,11 +155,23 @@ Blockly.FieldCheckbox.prototype.initView = function() { this.textElement_.setAttribute('y', Blockly.FieldCheckbox.CHECK_Y_OFFSET); Blockly.utils.dom.addClass(this.textElement_, 'blocklyCheckbox'); - var textNode = document.createTextNode(Blockly.FieldCheckbox.CHECK_CHAR); - this.textElement_.appendChild(textNode); + this.textContent_.nodeValue = + this.checkChar_ || Blockly.FieldCheckbox.CHECK_CHAR; this.textElement_.style.display = this.value_ ? 'block' : 'none'; }; +/** + * Set the character used for the check mark. + * @param {?string} character The character to use for the check mark, or + * null to use the default. + */ +Blockly.FieldCheckbox.prototype.setCheckCharacter = function(character) { + this.checkChar_ = character; + if (this.textContent_) { + this.textContent_.nodeValue = character || Blockly.FieldCheckbox.CHECK_CHAR; + } +}; + /** * Toggle the state of the checkbox on click. * @protected diff --git a/tests/mocha/field_checkbox_test.js b/tests/mocha/field_checkbox_test.js index 8ef2f322d..42fb6d466 100644 --- a/tests/mocha/field_checkbox_test.js +++ b/tests/mocha/field_checkbox_test.js @@ -182,4 +182,55 @@ suite('Checkbox Fields', function() { }); }); }); + suite('Customizations', function() { + suite('Check Character', function() { + function assertCharacter(field, char) { + field.fieldGroup_ = Blockly.utils.dom.createSvgElement('g', {}, null); + field.initView(); + chai.assert(field.textContent_.nodeValue, char); + } + test('Constant', function() { + var checkChar = Blockly.FieldCheckbox.CHECK_CHAR; + // Note: Developers shouldn't actually do this. IMO they should change + // the file and then recompile. But this is fine for testing. + Blockly.FieldCheckbox.CHECK_CHAR = '\u2661'; + var field = new Blockly.FieldCheckbox(true); + assertCharacter(field, '\u2661'); + Blockly.FieldCheckbox.CHECK_CHAR = checkChar; + }); + test('JS Constructor', function() { + var field = new Blockly.FieldCheckbox(true, null, { + checkCharacter: '\u2661' + }); + assertCharacter(field, '\u2661'); + }); + test('JSON Definition', function() { + var field = Blockly.FieldCheckbox.fromJson({ + checkCharacter: '\u2661' + }); + assertCharacter(field, '\u2661'); + }); + test('setCheckCharacter', function() { + var field = new Blockly.FieldCheckbox(); + assertCharacter(field, Blockly.FieldCheckbox.CHECK_CHAR); + field.setCheckCharacter('\u2661'); + // Don't call assertCharacter b/c we don't want to re-initialize. + chai.assert.equal(field.textContent_.nodeValue, '\u2661'); + }); + test('setCheckCharacter Before Init', function() { + var field = new Blockly.FieldCheckbox(); + field.setCheckCharacter('\u2661'); + assertCharacter(field, '\u2661'); + }); + test('Remove Custom Character', function() { + var field = new Blockly.FieldCheckbox(true, null, { + 'checkCharacter': '\u2661' + }); + assertCharacter(field, '\u2661'); + field.setCheckCharacter(null); + chai.assert(field.textContent_.nodeValue, + Blockly.FieldCheckbox.CHECK_CHAR); + }); + }); + }); });