diff --git a/core/field.js b/core/field.js index 7f637445d..6739e435e 100644 --- a/core/field.js +++ b/core/field.js @@ -51,15 +51,38 @@ goog.require('Blockly.utils.style'); * @constructor */ Blockly.Field = function(value, opt_validator, opt_config) { + /** + * A generic value possessed by the field. + * Should generally be non-null, only null when the field is created. + * @type {*} + * @protected + */ + this.value_ = null; + + /** + * Validation function called when user edits an editable field. + * @type {Function} + * @protected + */ + this.validator_ = null; + + /** + * Used to cache the field's tooltip value if setTooltip is called when the + * field is not yet initialized. Is *not* guaranteed to be accurate. + * @type {string|Function|!Element} + * @private + */ + this.tooltip_ = null; + /** * The size of the area rendered by the field. - * @type {Blockly.utils.Size} + * @type {!Blockly.utils.Size} * @protected */ this.size_ = new Blockly.utils.Size(0, 0); + opt_config && this.configure_(opt_config); this.setValue(value); - this.setValidator(opt_validator); - this.configure_(opt_config); + opt_validator && this.setValidator(opt_validator); }; /** @@ -117,22 +140,6 @@ Blockly.Field.prototype.disposed = false; */ Blockly.Field.prototype.maxDisplayLength = 50; -/** - * A generic value possessed by the field. - * Should generally be non-null, only null when the field is created. - * @type {*} - * @protected - */ -Blockly.Field.prototype.value_ = null; - -/** - * Used to cache the field's tooltip value if setTooltip is called when the - * field is not yet initialized. Is *not* guaranteed to be accurate. - * @type {?string} - * @private - */ -Blockly.Field.prototype.tooltip_ = null; - /** * Block this field is attached to. Starts as null, then set in init. * @type {Blockly.Block} @@ -143,7 +150,7 @@ Blockly.Field.prototype.sourceBlock_ = null; /** * Does this block need to be re-rendered? * @type {boolean} - * @private + * @protected */ Blockly.Field.prototype.isDirty_ = true; @@ -154,16 +161,9 @@ Blockly.Field.prototype.isDirty_ = true; */ Blockly.Field.prototype.visible_ = true; -/** - * Validation function called when user edits an editable field. - * @type {Function} - * @protected - */ -Blockly.Field.prototype.validator_ = null; - /** * The element the click handler is bound to. - * @type {!Element} + * @type {Element} * @private */ Blockly.Field.prototype.clickTarget_ = null; @@ -203,20 +203,17 @@ Blockly.Field.prototype.EDITABLE = true; Blockly.Field.prototype.SERIALIZABLE = false; /** - * Configure the field based on the given map of options. - * @param {Object} opt_config The map of options to configure the field - * based on. - * @private + * Process the configuration map passed to the field. + * @param {!Object} config A map of options used to configure the field. See + * the individual field's documentation for a list of properties this + * parameter supports. + * @protected */ -Blockly.Field.prototype.configure_ = function(opt_config) { - if (!opt_config) { - return; - } - - var tooltip = opt_config['tooltip']; +Blockly.Field.prototype.configure_ = function(config) { + var tooltip = config['tooltip']; if (typeof tooltip == 'string') { tooltip = Blockly.utils.replaceMessageReferences( - opt_config['tooltip']); + config['tooltip']); } tooltip && this.setTooltip(tooltip); @@ -274,6 +271,14 @@ Blockly.Field.prototype.initView = function() { this.createTextElement_(); }; +/** + * Initializes the model of the field after it has been installed on a block. + * No-op by default. + * @package + */ +Blockly.Field.prototype.initModel = function() { +}; + /** * Create a field border rect element. Not to be overridden by subclasses. * Instead modify the result of the function inside initView, or create a @@ -327,14 +332,6 @@ Blockly.Field.prototype.bindEvents_ = function() { this.getClickTarget_(), 'mousedown', this, this.onMouseDown_); }; -/** - * Initializes the model of the field after it has been installed on a block. - * No-op by default. - * @package - */ -Blockly.Field.prototype.initModel = function() { -}; - /** * Sets the field's value based on the given XML element. Should only be * called by Blockly.Xml. @@ -772,14 +769,18 @@ Blockly.Field.prototype.getValue = function() { /** * Used to validate a value. Returns input by default. Can be overridden by * subclasses, see FieldDropdown. - * @param {*} newValue The value to be validated. + * @param {*=} opt_newValue The value to be validated. * @return {*} The validated value, same as input by default. * @protected + * @suppress {deprecated} */ -Blockly.Field.prototype.doClassValidation_ = function(newValue) { +Blockly.Field.prototype.doClassValidation_ = function(opt_newValue) { + if (opt_newValue === null || opt_newValue === undefined) { + return null; + } // For backwards compatibility. - newValue = this.classValidator(newValue); - return newValue; + opt_newValue = this.classValidator(/** @type {string} */ (opt_newValue)); + return opt_newValue; }; /** diff --git a/core/field_angle.js b/core/field_angle.js index cd65d3d5a..af5e3dc4d 100644 --- a/core/field_angle.js +++ b/core/field_angle.js @@ -46,12 +46,8 @@ goog.require('Blockly.utils.userAgent'); * @constructor */ Blockly.FieldAngle = function(opt_value, opt_validator) { - opt_value = this.doClassValidation_(opt_value); - if (opt_value === null) { - opt_value = 0; - } Blockly.FieldAngle.superClass_.constructor.call( - this, opt_value, opt_validator); + this, opt_value || 0, opt_validator); }; Blockly.utils.object.inherits(Blockly.FieldAngle, Blockly.FieldTextInput); @@ -373,7 +369,7 @@ Blockly.FieldAngle.prototype.onHtmlInputKeyDown_ = function(e) { /** * Ensure that the input value is a valid angle. - * @param {string|number=} opt_newValue The input value. + * @param {*=} opt_newValue The input value. * @return {?number} A valid angle, or null if invalid. * @protected * @override diff --git a/core/field_checkbox.js b/core/field_checkbox.js index b71d6b0c1..5d3c0ecdd 100644 --- a/core/field_checkbox.js +++ b/core/field_checkbox.js @@ -50,15 +50,6 @@ goog.require('Blockly.utils.Size'); * @constructor */ 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, opt_config); - - this.size_.width = Blockly.FieldCheckbox.WIDTH; - /** * Character for the check mark. Used to apply a different check mark * character to individual fields. @@ -67,7 +58,14 @@ Blockly.FieldCheckbox = function(opt_value, opt_validator, opt_config) { */ this.checkChar_ = null; - this.configure_(opt_config); + if (opt_value == null) { + opt_value = 'FALSE'; + } + Blockly.FieldCheckbox.superClass_.constructor.call( + this, opt_value, opt_validator, opt_config); + + this.size_.width = Blockly.FieldCheckbox.WIDTH; + }; Blockly.utils.object.inherits(Blockly.FieldCheckbox, Blockly.Field); @@ -128,20 +126,19 @@ Blockly.FieldCheckbox.prototype.CURSOR = 'default'; * rendered. Checkbox fields are statically sized, and only need to be * rendered at initialization. * @type {boolean} - * @private + * @protected */ 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. + * @param {!Object} 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']; - } +Blockly.FieldCheckbox.prototype.configure_ = function(config) { + Blockly.FieldCheckbox.superClass_.configure_.call(this, config); + if (config['checkCharacter']) { + this.checkChar_ = config['checkCharacter']; } }; @@ -183,7 +180,7 @@ Blockly.FieldCheckbox.prototype.showEditor_ = function() { /** * Ensure that the input value is valid ('TRUE' or 'FALSE'). - * @param {string|boolean=} opt_newValue The input value. + * @param {*=} opt_newValue The input value. * @return {?string} A valid value ('TRUE' or 'FALSE), or null if invalid. * @protected */ @@ -220,10 +217,10 @@ Blockly.FieldCheckbox.prototype.getValue = function() { /** * Get the boolean value of this field. - * @return {string} The boolean value of this field. + * @return {boolean} The boolean value of this field. */ Blockly.FieldCheckbox.prototype.getValueBoolean = function() { - return this.value_; + return /** @type {boolean} */ (this.value_); }; /** diff --git a/core/field_colour.js b/core/field_colour.js index b8d2d0b91..3a05fbb70 100644 --- a/core/field_colour.js +++ b/core/field_colour.js @@ -53,14 +53,18 @@ goog.require('Blockly.utils.Size'); * @constructor */ Blockly.FieldColour = function(opt_value, opt_validator, opt_config) { - opt_value = this.doClassValidation_(opt_value); - if (opt_value === null) { - opt_value = Blockly.FieldColour.COLOURS[0]; - } Blockly.FieldColour.superClass_.constructor.call( - this, opt_value, opt_validator, opt_config); + this, opt_value || Blockly.FieldColour.COLOURS[0], + opt_validator, opt_config); - this.configure_(opt_config); + /** + * The size of the area rendered by the field. + * @type {Blockly.utils.Size} + * @protected + * @override + */ + this.size_ = new Blockly.utils.Size(Blockly.FieldColour.DEFAULT_WIDTH, + Blockly.FieldColour.DEFAULT_HEIGHT); }; Blockly.utils.object.inherits(Blockly.FieldColour, Blockly.Field); @@ -109,7 +113,7 @@ Blockly.FieldColour.prototype.CURSOR = 'default'; * rendered. Colour fields are statically sized, and only need to be * rendered at initialization. * @type {boolean} - * @private + * @protected */ Blockly.FieldColour.prototype.isDirty_ = false; @@ -153,19 +157,17 @@ Blockly.FieldColour.prototype.DROPDOWN_BACKGROUND_COLOUR = 'white'; /** * Configure the field based on the given map of options. - * @param {Object} opt_config A map of options to configure the field based on. + * @param {!Object} config A map of options to configure the field based on. * @private */ -Blockly.FieldColour.prototype.configure_ = function(opt_config) { - if (!opt_config) { - return; +Blockly.FieldColour.prototype.configure_ = function(config) { + Blockly.FieldColour.superClass_.configure_.call(this, config); + if (config['colourOptions']) { + this.colours_ = config['colourOptions']; + this.titles_ = config['colourTitles']; } - - if (opt_config['colourOptions']) { - this.setColours(opt_config['colourOptions'], opt_config['colourTitles']); - } - if (opt_config['columns']) { - this.setColumns(opt_config['columns']); + if (config['columns']) { + this.columns_ = config['columns']; } }; @@ -174,8 +176,6 @@ Blockly.FieldColour.prototype.configure_ = function(opt_config) { * @package */ Blockly.FieldColour.prototype.initView = function() { - this.size_ = new Blockly.utils.Size(Blockly.FieldColour.DEFAULT_WIDTH, - Blockly.FieldColour.DEFAULT_HEIGHT); this.createBorderRect_(); this.borderRect_.style['fillOpacity'] = 1; this.borderRect_.style.fill = this.value_; @@ -183,7 +183,7 @@ Blockly.FieldColour.prototype.initView = function() { /** * Ensure that the input value is a valid colour. - * @param {string=} opt_newValue The input value. + * @param {*=} opt_newValue The input value. * @return {?string} A valid colour, or null if invalid. * @protected */ @@ -211,7 +211,7 @@ Blockly.FieldColour.prototype.doValueUpdate_ = function(newValue) { * @return {string} Text representing the value of this field. */ Blockly.FieldColour.prototype.getText = function() { - var colour = this.value_; + var colour = /** @type {string} */ (this.value_); // Try to use #rgb format if possible, rather than #rrggbb. if (/^#(.)\1(.)\2(.)\3$/.test(colour)) { colour = '#' + colour[1] + colour[3] + colour[5]; diff --git a/core/field_date.js b/core/field_date.js index aaf1fe72c..88b5f2548 100644 --- a/core/field_date.js +++ b/core/field_date.js @@ -52,12 +52,8 @@ goog.require('goog.ui.DatePicker'); * @constructor */ Blockly.FieldDate = function(opt_value, opt_validator) { - opt_value = this.doClassValidation_(opt_value); - if (!opt_value) { - opt_value = new goog.date.Date().toIsoString(true); - } Blockly.FieldDate.superClass_.constructor.call(this, - opt_value, opt_validator); + opt_value || new goog.date.Date().toIsoString(true), opt_validator); }; Blockly.utils.object.inherits(Blockly.FieldDate, Blockly.Field); @@ -103,7 +99,7 @@ Blockly.FieldDate.prototype.DROPDOWN_BACKGROUND_COLOUR = 'white'; /** * Ensure that the input value is a valid date. - * @param {string=} opt_newValue The input value. + * @param {*=} opt_newValue The input value. * @return {?string} A valid date, or null if invalid. * @protected */ diff --git a/core/field_dropdown.js b/core/field_dropdown.js index 1271952e8..45ce9bf91 100644 --- a/core/field_dropdown.js +++ b/core/field_dropdown.js @@ -59,11 +59,14 @@ Blockly.FieldDropdown = function(menuGenerator, opt_validator) { Blockly.FieldDropdown.validateOptions_(menuGenerator); } + /** + * An array of options for a dropdown list, + * or a function which generates these options. + * @type {(!Array.|!Function)} + * @protected + */ this.menuGenerator_ = menuGenerator; - this.trimOptions_(); - var firstTuple = this.getOptions()[0]; - /** * The currently selected index. A value of -1 indicates no option * has been selected. @@ -72,10 +75,20 @@ Blockly.FieldDropdown = function(menuGenerator, opt_validator) { */ this.selectedIndex_ = -1; + this.trimOptions_(); + var firstTuple = this.getOptions()[0]; + // Call parent's constructor. Blockly.FieldDropdown.superClass_.constructor.call(this, firstTuple[1], opt_validator); + /** + * SVG image element if currently selected option is an image, or null. + * @type {SVGElement} + * @private + */ + this.imageElement_ = null; + /** * A reference to the currently selected menu item. * @type {Blockly.MenuItem} @@ -154,13 +167,6 @@ Blockly.FieldDropdown.ARROW_CHAR = */ Blockly.FieldDropdown.prototype.CURSOR = 'default'; -/** - * SVG image element if currently selected option is an image, or null. - * @type {SVGElement} - * @private - */ -Blockly.FieldDropdown.prototype.imageElement_ = null; - /** * Create the block UI for this dropdown. * @package @@ -430,7 +436,7 @@ Blockly.FieldDropdown.prototype.getOptions = function() { /** * Ensure that the input value is a valid language-neutral option. - * @param {string=} opt_newValue The input value. + * @param {*=} opt_newValue The input value. * @return {?string} A valid language-neutral option, or null if invalid. * @protected */ @@ -452,7 +458,7 @@ Blockly.FieldDropdown.prototype.doClassValidation_ = function(opt_newValue) { } return null; } - return opt_newValue; + return /** @type {string} */ (opt_newValue); }; /** diff --git a/core/field_image.js b/core/field_image.js index ea42ddb10..de0860748 100644 --- a/core/field_image.js +++ b/core/field_image.js @@ -48,7 +48,6 @@ goog.require('Blockly.utils.Size'); */ Blockly.FieldImage = function(src, width, height, opt_alt, opt_onClick, opt_flipRtl) { - this.sourceBlock_ = null; if (!src) { throw Error('Src value of an image field is required'); @@ -66,10 +65,13 @@ Blockly.FieldImage = function(src, width, height, throw Error('Height and width values of an image field must be greater' + ' than 0.'); } - // Store the image height, since it is different from the field height. + + /** + * Store the image height, since it is different from the field height. + * @type {number} + * @private + */ this.imageHeight_ = imageHeight; - this.size_ = new Blockly.utils.Size(imageWidth, - imageHeight + Blockly.FieldImage.Y_PADDING); /** * Whether to flip this image in RTL. @@ -85,11 +87,21 @@ Blockly.FieldImage = function(src, width, height, */ this.altText_ = opt_alt || ''; - this.setValue(src || ''); - if (typeof opt_onClick == 'function') { this.clickHandler_ = opt_onClick; } + + Blockly.FieldImage.superClass_.constructor.call( + this, src || '', null); + + /** + * The size of the area rendered by the field. + * @type {Blockly.utils.Size} + * @protected + * @override + */ + this.size_ = new Blockly.utils.Size(imageWidth, + imageHeight + Blockly.FieldImage.Y_PADDING); }; Blockly.utils.object.inherits(Blockly.FieldImage, Blockly.Field); @@ -133,7 +145,7 @@ Blockly.FieldImage.prototype.EDITABLE = false; * rendered. Image fields are statically sized, and only need to be * rendered at initialization. * @type {boolean} - * @private + * @protected */ Blockly.FieldImage.prototype.isDirty_ = false; @@ -151,12 +163,12 @@ Blockly.FieldImage.prototype.initView = function() { }, this.fieldGroup_); this.imageElement_.setAttributeNS(Blockly.utils.dom.XLINK_NS, - 'xlink:href', this.value_); + 'xlink:href', /** @type {string} */ (this.value_)); }; /** * Ensure that the input value (the source URL) is a string. - * @param {string=} opt_newValue The input value. + * @param {*=} opt_newValue The input value. * @return {?string} A string, or null if invalid. * @protected */ diff --git a/core/field_label.js b/core/field_label.js index 1e416c4d0..3b8bde5f6 100644 --- a/core/field_label.js +++ b/core/field_label.js @@ -44,13 +44,26 @@ goog.require('Blockly.utils.Size'); * @constructor */ Blockly.FieldLabel = function(opt_value, opt_class) { - this.size_ = new Blockly.utils.Size(0, Blockly.Field.TEXT_DEFAULT_HEIGHT); - this.class_ = opt_class; - opt_value = this.doClassValidation_(opt_value); - if (opt_value === null) { + /** + * The html class name to use for this field. + * @type {?string} + * @private + */ + this.class_ = opt_class || null; + + if (opt_value == null) { opt_value = ''; } - this.setValue(opt_value); + Blockly.FieldLabel.superClass_.constructor.call( + this, opt_value, null); + + /** + * The size of the area rendered by the field. + * @type {Blockly.utils.Size} + * @protected + * @override + */ + this.size_ = new Blockly.utils.Size(0, Blockly.Field.TEXT_DEFAULT_HEIGHT); }; Blockly.utils.object.inherits(Blockly.FieldLabel, Blockly.Field); @@ -90,7 +103,7 @@ Blockly.FieldLabel.prototype.initView = function() { /** * Ensure that the input value casts to a valid string. - * @param {string=} opt_newValue The input value. + * @param {*=} opt_newValue The input value. * @return {?string} A valid string, or null if invalid. * @protected */ diff --git a/core/field_number.js b/core/field_number.js index 65024937a..def30ed74 100644 --- a/core/field_number.js +++ b/core/field_number.js @@ -46,13 +46,32 @@ goog.require('Blockly.utils.object'); */ Blockly.FieldNumber = function(opt_value, opt_min, opt_max, opt_precision, opt_validator) { - this.setConstraints(opt_min, opt_max, opt_precision); - opt_value = this.doClassValidation_(opt_value); - if (opt_value === null) { - opt_value = 0; - } + + /** + * The minimum value constraint. + * @type {number} + * @protected + */ + this.min_ = -Infinity; + + /** + * The maximum value constraint. + * @type {number} + * @protected + */ + this.max_ = Infinity; + + /** + * The precision constraint for the value. + * @type {number} + * @protected + */ + this.precision_ = 0; + Blockly.FieldNumber.superClass_.constructor.call( - this, opt_value, opt_validator); + this, opt_value || 0, opt_validator); + + this.setConstraints(opt_min, opt_max, opt_precision); }; Blockly.utils.object.inherits(Blockly.FieldNumber, Blockly.FieldTextInput); @@ -90,28 +109,34 @@ Blockly.FieldNumber.prototype.SERIALIZABLE = true; */ Blockly.FieldNumber.prototype.setConstraints = function(min, max, precision) { precision = Number(precision); - this.precision_ = isNaN(precision) ? 0 : precision; + if (!isNaN(precision)) { + this.precision_ = precision; + } var precisionString = this.precision_.toString(); var decimalIndex = precisionString.indexOf('.'); this.fractionalDigits_ = (decimalIndex == -1) ? -1 : precisionString.length - (decimalIndex + 1); min = Number(min); - this.min_ = isNaN(min) ? -Infinity : min; + if (!isNaN(min)) { + this.min_ = min; + } max = Number(max); - this.max_ = isNaN(max) ? Infinity : max; + if (!isNaN(max)) { + this.max_ = max; + } this.setValue(this.getValue()); }; /** * Ensure that the input value is a valid number (must fulfill the * constraints placed on the field). - * @param {string|number=} opt_newValue The input value. + * @param {*=} opt_newValue The input value. * @return {?number} A valid number, or null if invalid. * @protected * @override */ Blockly.FieldNumber.prototype.doClassValidation_ = function(opt_newValue) { - if (opt_newValue === null || opt_newValue === undefined) { + if (opt_newValue === null) { return null; } // Clean up text. @@ -142,7 +167,7 @@ Blockly.FieldNumber.prototype.doClassValidation_ = function(opt_newValue) { /** * Create the number input editor widget. - * @return {!HTMLInputElement} The newly created number input editor. + * @return {!HTMLElement} The newly created number input editor. * @protected * @override */ diff --git a/core/field_textinput.js b/core/field_textinput.js index 37f9d3667..3a556d262 100644 --- a/core/field_textinput.js +++ b/core/field_textinput.js @@ -51,12 +51,11 @@ goog.require('Blockly.utils.userAgent'); * @constructor */ Blockly.FieldTextInput = function(opt_value, opt_validator) { - opt_value = this.doClassValidation_(opt_value); - if (opt_value === null) { + if (opt_value == null) { opt_value = ''; } - Blockly.FieldTextInput.superClass_.constructor.call(this, opt_value, - opt_validator); + Blockly.FieldTextInput.superClass_.constructor.call(this, + opt_value, opt_validator); }; Blockly.utils.object.inherits(Blockly.FieldTextInput, Blockly.Field); @@ -92,7 +91,8 @@ Blockly.FieldTextInput.prototype.SERIALIZABLE = true; Blockly.FieldTextInput.FONTSIZE = 11; /** - * Pixel size of input border radius. Should match blocklyText's border-radius in CSS. + * Pixel size of input border radius. + * Should match blocklyText's border-radius in CSS. */ Blockly.FieldTextInput.BORDERRADIUS = 4; @@ -109,8 +109,8 @@ Blockly.FieldTextInput.prototype.spellcheck_ = true; /** * Ensure that the input value casts to a valid string. - * @param {string=} opt_newValue The input value. - * @return {?string} A valid string, or null if invalid. + * @param {*=} opt_newValue The input value. + * @return {*} A valid string, or null if invalid. * @protected */ Blockly.FieldTextInput.prototype.doClassValidation_ = function(opt_newValue) { diff --git a/core/field_variable.js b/core/field_variable.js index d03edc651..766a5c36d 100644 --- a/core/field_variable.js +++ b/core/field_variable.js @@ -59,12 +59,19 @@ Blockly.FieldVariable = function(varname, opt_validator, opt_variableTypes, // The FieldDropdown constructor would call setValue, which might create a // spurious variable. Just do the relevant parts of the constructor. this.menuGenerator_ = Blockly.FieldVariable.dropdownCreate; - this.size_ = new Blockly.utils.Size(0, Blockly.BlockSvg.MIN_BLOCK_Y); opt_validator && this.setValidator(opt_validator); this.defaultVariableName = varname || ''; this.setTypes_(opt_variableTypes, opt_defaultType); this.value_ = null; + + /** + * The size of the area rendered by the field. + * @type {Blockly.utils.Size} + * @protected + * @override + */ + this.size_ = new Blockly.utils.Size(0, Blockly.BlockSvg.MIN_BLOCK_Y); }; Blockly.utils.object.inherits(Blockly.FieldVariable, Blockly.FieldDropdown); @@ -224,11 +231,15 @@ Blockly.FieldVariable.prototype.getValidator = function() { /** * Ensure that the id belongs to a valid variable of an allowed type. - * @param {string} newId The id of the new variable to set. + * @param {*=} opt_newValue The id of the new variable to set. * @return {?string} The validated id, or null if invalid. * @protected */ -Blockly.FieldVariable.prototype.doClassValidation_ = function(newId) { +Blockly.FieldVariable.prototype.doClassValidation_ = function(opt_newValue) { + if (opt_newValue === null) { + return null; + } + var newId = /** @type {string} */ (opt_newValue); var variable = Blockly.Variables.getVariable(this.workspace_, newId); if (!variable) { console.warn('Variable id doesn\'t point to a real variable! ' + diff --git a/demos/custom-fields/turtle/field_turtle.js b/demos/custom-fields/turtle/field_turtle.js index 7e77542e1..41c93c21e 100644 --- a/demos/custom-fields/turtle/field_turtle.js +++ b/demos/custom-fields/turtle/field_turtle.js @@ -48,24 +48,21 @@ CustomFields.FieldTurtle = function( // The turtle field contains an object as its value, so we need to compile // the parameters into an object. var value = {}; - value.pattern = opt_pattern; - value.hat = opt_hat; - value.turtleName = opt_turtleName; - - var valid = this.doClassValidation_(value); - if (valid === null) { - // See the doClassValidation_ function for information on the - // cachedValidatedValue_ property. - value = this.cachedValidatedValue_; - value.pattern = value.pattern || CustomFields.FieldTurtle.PATTERNS[0]; - value.hat = value.hat || CustomFields.FieldTurtle.HATS[0]; - value.turtleName = value.turtleName || CustomFields.FieldTurtle.NAMES[0]; - } // Else the original value is fine. + value.pattern = opt_pattern || CustomFields.FieldTurtle.PATTERNS[0]; + value.hat = opt_hat || CustomFields.FieldTurtle.HATS[0]; + value.turtleName = opt_turtleName || CustomFields.FieldTurtle.NAMES[0]; // A field constructor should always call its parent constructor, because // that helps keep the code organized and DRY. CustomFields.FieldTurtle.superClass_.constructor.call( this, value, opt_validator); + + /** + * The size of the area rendered by the field. + * @type {Blockly.utils.Size} + * @protected + * @override + */ this.size_ = new Blockly.utils.Size(0, 0); }; Blockly.utils.object.inherits(CustomFields.FieldTurtle, Blockly.Field); diff --git a/tests/blocks/test_blocks.js b/tests/blocks/test_blocks.js index d5d9097ce..f8aa6c050 100644 --- a/tests/blocks/test_blocks.js +++ b/tests/blocks/test_blocks.js @@ -988,55 +988,6 @@ Blockly.Blocks['test_validators_colour_red_null'] = { } }; -Blockly.Blocks['test_validators_date_null'] = { - init: function() { - this.appendDummyInput() - .appendField("always null") - .appendField(new Blockly.FieldDate("2020-02-20", this.validate), "INPUT"); - this.setColour(230); - this.setCommentText('All input validates to null (invalid). This means' + - ' the field value should not change.'); - }, - - validate: function(newValue) { - // We should be able to expect validators to like their initial values. - if (newValue != '2020-02-20') { - return null; - } - } -}; -Blockly.Blocks['test_validators_date_force_20s'] = { - init: function() { - this.appendDummyInput() - .appendField("force day 20s") - .appendField(new Blockly.FieldDate("2020-02-20", this.validate), "INPUT"); - this.setColour(230); - this.setCommentText('The input\'s date will change to always be in the' + - ' 20s.'); - }, - - validate: function(newValue) { - return newValue.substr(0, 8) + '2' + newValue.substr(9, 1); - } -}; -Blockly.Blocks['test_validators_date_20s_null'] = { - init: function() { - this.appendDummyInput() - .appendField("not 20s -> null") - .appendField(new Blockly.FieldDate("2020-02-20", this.validate), "INPUT"); - this.setColour(230); - this.setCommentText('If the input is not in the 20s, the input will' + - ' validate to null (invalid). Otherwise it will return the input value.'); - }, - - validate: function(newValue) { - if (newValue.charAt(8) != '2') { - return null; - } - return newValue; - } -}; - Blockly.Blocks['test_validators_dropdown_null'] = { init: function() { this.appendDummyInput() diff --git a/tests/mocha/field_angle_test.js b/tests/mocha/field_angle_test.js index d86a6b365..86236145c 100644 --- a/tests/mocha/field_angle_test.js +++ b/tests/mocha/field_angle_test.js @@ -39,10 +39,6 @@ suite('Angle Fields', function() { var angleField = new Blockly.FieldAngle(undefined); assertValueDefault(angleField); }); - test('Non-Parsable String', function() { - var angleField = new Blockly.FieldAngle('bad'); - assertValueDefault(angleField); - }); test('NaN', function() { var angleField = new Blockly.FieldAngle(NaN); assertValueDefault(angleField); @@ -67,14 +63,6 @@ suite('Angle Fields', function() { var angleField = new Blockly.FieldAngle(362); assertValue(angleField, 2); }); - test('Infinity', function() { - var angleField = new Blockly.FieldAngle(Infinity); - assertValueDefault(angleField); - }); - test('Negative Infinity String', function() { - var angleField = new Blockly.FieldAngle('-Infinity'); - assertValueDefault(angleField); - }); }); suite('fromJson', function() { test('Empty', function() { @@ -85,10 +73,6 @@ suite('Angle Fields', function() { var angleField = Blockly.FieldAngle.fromJson({ angle:undefined }); assertValueDefault(angleField); }); - test('Non-Parsable String', function() { - var angleField = Blockly.FieldAngle.fromJson({ angle:'bad' }); - assertValueDefault(angleField); - }); test('NaN', function() { var angleField = Blockly.FieldAngle.fromJson({ angle:NaN }); assertValueDefault(angleField); @@ -113,14 +97,6 @@ suite('Angle Fields', function() { var angleField = Blockly.FieldAngle.fromJson({ angle:362 }); assertValue(angleField, 2); }); - test('Infinity', function() { - var angleField = Blockly.FieldAngle.fromJson({ angle:Infinity }); - assertValueDefault(angleField); - }); - test('Negative Infinity String', function() { - var angleField = Blockly.FieldAngle.fromJson({ angle:'-Infinity' }); - assertValueDefault(angleField); - }); }); suite('setValue', function() { suite('Empty -> New Value', function() { diff --git a/tests/mocha/field_checkbox_test.js b/tests/mocha/field_checkbox_test.js index 42fb6d466..a39e7bcdd 100644 --- a/tests/mocha/field_checkbox_test.js +++ b/tests/mocha/field_checkbox_test.js @@ -37,10 +37,6 @@ suite('Checkbox Fields', function() { var checkboxField = new Blockly.FieldCheckbox(undefined); assertValueDefault(checkboxField); }); - test('Non-Parsable String', function() { - var checkboxField = new Blockly.FieldCheckbox('bad'); - assertValueDefault(checkboxField); - }); test('True', function() { var checkboxField = new Blockly.FieldCheckbox(true); assertValue(checkboxField, 'TRUE', 'true'); @@ -67,10 +63,6 @@ suite('Checkbox Fields', function() { var checkboxField = Blockly.FieldCheckbox.fromJson({ checked: undefined}); assertValueDefault(checkboxField); }); - test('Non-Parsable String', function() { - var checkboxField = Blockly.FieldCheckbox.fromJson({ checked: 'bad'}); - assertValueDefault(checkboxField); - }); test('True', function() { var checkboxField = Blockly.FieldCheckbox.fromJson({ checked: true}); assertValue(checkboxField, 'TRUE', 'true'); diff --git a/tests/mocha/field_colour_test.js b/tests/mocha/field_colour_test.js index 8d48da0d3..a567746a4 100644 --- a/tests/mocha/field_colour_test.js +++ b/tests/mocha/field_colour_test.js @@ -53,10 +53,6 @@ suite('Colour Fields', function() { var colourField = new Blockly.FieldColour(undefined); assertValueDefault(colourField); }); - test('Non-Parsable String', function() { - var colourField = new Blockly.FieldColour('not_a_colour'); - assertValueDefault(colourField); - }); test('#AAAAAA', function() { var colourField = new Blockly.FieldColour('#AAAAAA'); assertValue(colourField, '#aaaaaa', '#aaa'); @@ -107,11 +103,6 @@ suite('Colour Fields', function() { var colourField = new Blockly.FieldColour.fromJson({ colour:undefined }); assertValueDefault(colourField); }); - test('Non-Parsable String', function() { - var colourField = new Blockly.FieldColour.fromJson( - { colour:'not_a_colour' }); - assertValueDefault(colourField); - }); test('#AAAAAA', function() { var colourField = Blockly.FieldColour.fromJson({ colour: '#AAAAAA' }); assertValue(colourField, '#aaaaaa', '#aaa'); diff --git a/tests/mocha/field_number_test.js b/tests/mocha/field_number_test.js index 95ff1b3dd..1bce8ffcb 100644 --- a/tests/mocha/field_number_test.js +++ b/tests/mocha/field_number_test.js @@ -59,10 +59,6 @@ suite('Number Fields', function() { var numberField = createNumberFieldSameValuesConstructor(undefined); assertNumberFieldDefault(numberField); }); - test('Non-Parsable String', function() { - var numberField = createNumberFieldSameValuesConstructor('bad'); - assertNumberFieldDefault(numberField); - }); test('NaN', function() { var numberField = createNumberFieldSameValuesConstructor(NaN); assertNumberFieldDefault(numberField); @@ -101,10 +97,6 @@ suite('Number Fields', function() { var numberField = createNumberFieldSameValuesJson(undefined); assertNumberFieldDefault(numberField); }); - test('Non-Parsable String', function() { - var numberField = createNumberFieldSameValuesJson('bad'); - assertNumberFieldDefault(numberField); - }); test('NaN', function() { var numberField = createNumberFieldSameValuesJson(NaN); assertNumberFieldDefault(numberField); diff --git a/tests/mocha/procedures_test.js b/tests/mocha/procedures_test.js index 1b5850f31..800521b04 100644 --- a/tests/mocha/procedures_test.js +++ b/tests/mocha/procedures_test.js @@ -19,7 +19,7 @@ */ goog.require('Blockly.Blocks.procedures'); -goog.require('Blockly.Msg.en'); +goog.require('Blockly.Msg'); suite('Procedures', function() { setup(function() { diff --git a/tests/playground.html b/tests/playground.html index 237c5d31b..ad8c60252 100644 --- a/tests/playground.html +++ b/tests/playground.html @@ -1443,13 +1443,6 @@ h1 { - - - - - - -