Image Field Config (#2983)

* Added image field configuration.
This commit is contained in:
Beka Westberg
2019-09-16 11:05:32 -07:00
committed by Sam El-Husseini
parent 8b9816abcb
commit b149aabd16
3 changed files with 180 additions and 62 deletions

View File

@@ -40,32 +40,67 @@ goog.require('Blockly.utils.Size');
* @param {!(string|number)} width Width of the image.
* @param {!(string|number)} height Height of the image.
* @param {string=} opt_alt Optional alt text for when block is collapsed.
* @param {Function=} opt_onClick Optional function to be called when the image
* is clicked. If opt_onClick is defined, opt_alt must also be defined.
* @param {function(!Blockly.FieldImage)=} opt_onClick Optional function to be
* called when the image is clicked. If opt_onClick is defined, opt_alt must
* also be defined.
* @param {boolean=} opt_flipRtl Whether to flip the icon in RTL.
* @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/image#creation}
* for a list of properties this parameter supports.
* @extends {Blockly.Field}
* @constructor
*/
Blockly.FieldImage = function(src, width, height,
opt_alt, opt_onClick, opt_flipRtl) {
opt_alt, opt_onClick, opt_flipRtl, opt_config) {
// Return early.
if (!src) {
throw Error('Src value of an image field is required');
}
if (isNaN(height) || isNaN(width)) {
src = Blockly.utils.replaceMessageReferences(src);
var imageHeight = Number(Blockly.utils.replaceMessageReferences(height));
var imageWidth = Number(Blockly.utils.replaceMessageReferences(width));
if (isNaN(imageHeight) || isNaN(imageWidth)) {
throw Error('Height and width values of an image field must cast to' +
' numbers.');
}
// Ensure height and width are numbers. Strings are bad at math.
var imageHeight = Number(height);
var imageWidth = Number(width);
if (imageHeight <= 0 || imageWidth <= 0) {
throw Error('Height and width values of an image field must be greater' +
' than 0.');
}
// Initialize configurable properties.
/**
* Whether to flip this image in RTL.
* @type {boolean}
* @private
*/
this.flipRtl_ = false;
/**
* Alt text of this image.
* @type {string}
* @private
*/
this.altText_ = '';
Blockly.FieldImage.superClass_.constructor.call(
this, src || '', null, opt_config);
if (!opt_config) { // If the config wasn't passed, do old configuration.
this.flipRtl_ = !!opt_flipRtl;
this.altText_ = Blockly.utils.replaceMessageReferences(opt_alt) || '';
}
// Initialize other properties.
/**
* 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);
/**
* Store the image height, since it is different from the field height.
* @type {number}
@@ -74,34 +109,15 @@ Blockly.FieldImage = function(src, width, height,
this.imageHeight_ = imageHeight;
/**
* Whether to flip this image in RTL.
* @type {boolean}
* The function to be called when this field is clicked.
* @type {?function(!Blockly.FieldImage)}
* @private
*/
this.flipRtl_ = opt_flipRtl || false;
/**
* Alt text of this image.
* @type {string}
* @private
*/
this.altText_ = opt_alt || '';
this.clickHandler_ = null;
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);
@@ -115,13 +131,9 @@ Blockly.utils.object.inherits(Blockly.FieldImage, Blockly.Field);
* @nocollapse
*/
Blockly.FieldImage.fromJson = function(options) {
var src = Blockly.utils.replaceMessageReferences(options['src']);
var width = Number(Blockly.utils.replaceMessageReferences(options['width']));
var height =
Number(Blockly.utils.replaceMessageReferences(options['height']));
var alt = Blockly.utils.replaceMessageReferences(options['alt']);
var flipRtl = !!options['flipRtl'];
return new Blockly.FieldImage(src, width, height, alt, null, flipRtl);
return new Blockly.FieldImage(
options['src'], options['width'], options['height'],
null, null, null, options);
};
/**
@@ -149,6 +161,17 @@ Blockly.FieldImage.prototype.EDITABLE = false;
*/
Blockly.FieldImage.prototype.isDirty_ = false;
/**
* Configure the field based on the given map of options.
* @param {!Object} config A map of options to configure the field based on.
* @private
*/
Blockly.FieldImage.prototype.configure_ = function(config) {
Blockly.FieldImage.superClass_.configure_.call(this, config);
this.flipRtl_ = !!config['flipRtl'];
this.altText_ = Blockly.utils.replaceMessageReferences(config['alt']) || '';
};
/**
* Create the block UI for this image.
* @package
@@ -206,8 +229,7 @@ Blockly.FieldImage.prototype.getFlipRtl = function() {
* @public
*/
Blockly.FieldImage.prototype.setAlt = function(alt) {
if (alt === this.altText_) {
// No change.
if (alt == this.altText_) {
return;
}
this.altText_ = alt || '';
@@ -228,16 +250,16 @@ Blockly.FieldImage.prototype.showEditor_ = function() {
/**
* Set the function that is called when this image is clicked.
* @param {Function} func The function that is called when the image
* is clicked. It will receive the image field as a parameter.
* @public
* @param {?function(!Blockly.FieldImage)} func The function that is called
* when the image is clicked, or null to remove.
*/
Blockly.FieldImage.prototype.setOnClickHandler = function(func) {
this.clickHandler_ = func;
};
/**
* Use the `getText_` developer hook to override the field's text represenation.
* Use the `getText_` developer hook to override the field's text
* representation.
* Return the image alt text instead.
* @return {?string} The image alt text.
* @protected

View File

@@ -493,8 +493,10 @@ FactoryUtils.getFieldsJs_ = function(block) {
var width = Number(block.getFieldValue('WIDTH'));
var height = Number(block.getFieldValue('HEIGHT'));
var alt = JSON.stringify(block.getFieldValue('ALT'));
var flipRtl = Json.stringify(block.getFieldValue('FLIP_RTL'));
fields.push('new Blockly.FieldImage(' +
src + ', ' + width + ', ' + height + ', ' + alt + ')');
src + ', ' + width + ', ' + height +
', { alt: ' + alt + ', flipRtl: ' + flipRtl + ' })');
break;
}
}

View File

@@ -51,9 +51,6 @@ suite('Image Fields', function() {
new Blockly.FieldImage('src', 'bad', 'bad');
});
});
// Note: passing invalid an src path doesn't need to throw errors
// because the developer can see they did it incorrectly when they view
// the block.
test('With Alt', function() {
var imageField = new Blockly.FieldImage('src', 1, 1, 'alt');
assertValue(imageField, 'src', 'alt');
@@ -131,27 +128,124 @@ suite('Image Fields', function() {
assertValue(this.imageField, 'newSrc', 'alt');
});
});
suite('setAlt', function() {
suite('Alt', function() {
suite('Customizations', function() {
suite('On Click Handler', function() {
setup(function() {
this.imageField = new Blockly.FieldImage('src', 1, 1, 'alt');
this.onClick = function() {
console.log('on click');
};
});
teardown(function() {
delete this.onClick;
});
test('JS Constructor', function() {
var field = new Blockly.FieldImage('src', 10, 10, null, this.onClick);
chai.assert.equal(field.clickHandler_, this.onClick);
});
test('setOnClickHandler', function() {
var field = new Blockly.FieldImage('src', 10, 10);
field.setOnClickHandler(this.onClick);
chai.assert.equal(field.clickHandler_, this.onClick);
});
test('Remove Click Handler', function() {
var field = new Blockly.FieldImage('src', 10, 10, null, this.onClick);
field.setOnClickHandler(null);
chai.assert.equal(field.clickHandler_, null);
});
});
suite('Alt', function() {
test('JS Constructor', function() {
var field = new Blockly.FieldImage('src', 10, 10, 'alt');
chai.assert.equal(field.altText_, 'alt');
});
test('JSON Definition', function() {
var field = Blockly.FieldImage.fromJson({
src: 'src',
width: 10,
height: 10,
alt: 'alt'
});
chai.assert.equal(field.altText_, 'alt');
});
test('Deprecated - setText', function() {
var field = new Blockly.FieldImage('src', 10, 10, 'alt');
chai.assert.throws(function() {
this.imageField.setText('newAlt');
field.setText('newAlt');
});
});
test('Null', function() {
this.imageField.setAlt(null);
assertValue(this.imageField, 'src', '');
suite('SetAlt', function() {
setup(function() {
this.imageField = new Blockly.FieldImage('src', 10, 10, 'alt');
});
test('Null', function() {
this.imageField.setAlt(null);
assertValue(this.imageField, 'src', '');
});
test('Empty String', function() {
this.imageField.setAlt('');
assertValue(this.imageField, 'src', '');
});
test('Good Alt', function() {
this.imageField.setAlt('newAlt');
assertValue(this.imageField, 'src', 'newAlt');
});
});
test('Empty String', function() {
this.imageField.setAlt('');
assertValue(this.imageField, 'src', '');
test('JS Configuration - Simple', function() {
var field = new Blockly.FieldImage('src', 10, 10, null, null, null, {
alt: 'alt'
});
chai.assert.equal(field.altText_, 'alt');
});
test('Good Alt', function() {
this.imageField.setAlt('newAlt');
assertValue(this.imageField, 'src', 'newAlt');
test('JS Configuration - Ignore', function() {
var field = new Blockly.FieldImage('src', 10, 10, 'alt', null, null, {
alt: 'configAlt'
});
chai.assert.equal(field.altText_, 'configAlt');
});
test('JS Configuration - Ignore - \'\'', function() {
var field = new Blockly.FieldImage('src', 10, 10, '', null, null, {
alt: 'configAlt'
});
chai.assert.equal(field.altText_, 'configAlt');
});
test('JS Configuration - Ignore - Config \'\'', function() {
var field = new Blockly.FieldImage('src', 10, 10, 'alt', null, null, {
alt: ''
});
chai.assert.equal(field.altText_, '');
});
});
suite('Flip RTL', function() {
test('JS Constructor', function() {
var field = new Blockly.FieldImage('src', 10, 10, null, null, true);
chai.assert.isTrue(field.getFlipRtl());
});
test('JSON Definition', function() {
var field = Blockly.FieldImage.fromJson({
src: 'src',
width: 10,
height: 10,
flipRtl: true
});
chai.assert.isTrue(field.getFlipRtl());
});
test('JS Configuration - Simple', function() {
var field = new Blockly.FieldImage('src', 10, 10, null, null, null, {
flipRtl: true
});
chai.assert.isTrue(field.getFlipRtl());
});
test('JS Configuration - Ignore - True', function() {
var field = new Blockly.FieldImage('src', 10, 10, null, null, true, {
flipRtl: false
});
chai.assert.isFalse(field.getFlipRtl());
});
test('JS Configuration - Ignore - False', function() {
var field = new Blockly.FieldImage('src', 10, 10, null, null, false, {
flipRtl: true
});
chai.assert.isTrue(field.getFlipRtl());
});
});
});