mirror of
https://github.com/scratchfoundation/scratch-blocks.git
synced 2025-08-28 22:10:31 -04:00
Implement field_number stub and num-pad on mobile (#293)
* Implement basic field_number type * Add whole number and positive number * Remove bad arguments for showEditor_ * Basic implementation and styling of num-pad * Remove virtual keyboards; add selection and read-only * Add editing for the number pad * Add backspace button to number pad * Fix text padding for font-weight and extra magic * Don't show decimal point for integers * Re-update default WeDo numbers * Refactor and improve documentation of field_number
This commit is contained in:
parent
b90cae0960
commit
50ff6e4654
14 changed files with 408 additions and 35 deletions
|
@ -1143,8 +1143,8 @@ Blockly.Block.prototype.jsonInit=function(a){goog.asserts.assert(void 0==a.outpu
|
|||
a.previousStatement);void 0!==a.nextStatement&&this.setNextStatement(!0,a.nextStatement);void 0!==a.tooltip&&this.setTooltip(a.tooltip);void 0!==a.helpUrl&&this.setHelpUrl(a.helpUrl)};
|
||||
Blockly.Block.prototype.interpolate_=function(a,b,c){var d=Blockly.tokenizeInterpolation(a),e=[],f=0;a=[];for(var g=0;g<d.length;g++){var h=d[g];"number"==typeof h?(goog.asserts.assert(0<h&&h<=b.length,'Message index "%s" out of range.',h),goog.asserts.assert(!e[h],'Message index "%s" duplicated.',h),e[h]=!0,f++,a.push(b[h-1])):(h=h.trim())&&a.push(h)}goog.asserts.assert(f==b.length,"Message does not reference all %s arg(s).",b.length);!a.length||"string"!=typeof a[a.length-1]&&0!=a[a.length-1].type.indexOf("field_")||
|
||||
(b={type:"input_dummy"},c&&(b.align=c),a.push(b));c={LEFT:Blockly.ALIGN_LEFT,RIGHT:Blockly.ALIGN_RIGHT,CENTRE:Blockly.ALIGN_CENTRE};d=[];for(g=0;g<a.length;g++)if(e=a[g],"string"==typeof e)d.push([e,void 0]);else{b=f=null;do switch(h=!1,e.type){case "input_value":b=this.appendValueInput(e.name);break;case "input_statement":b=this.appendStatementInput(e.name);break;case "input_dummy":b=this.appendDummyInput(e.name);break;case "field_label":f=new Blockly.FieldLabel(e.text,e["class"]);break;case "field_input":f=
|
||||
new Blockly.FieldTextInput(e.text);"boolean"==typeof e.spellcheck&&f.setSpellcheck(e.spellcheck);break;case "field_angle":f=new Blockly.FieldAngle(e.angle);break;case "field_checkbox":f=new Blockly.FieldCheckbox(e.checked?"TRUE":"FALSE");break;case "field_colour":f=new Blockly.FieldColour(e.colour);break;case "field_variable":f=new Blockly.FieldVariable(e.variable);break;case "field_dropdown":f=new Blockly.FieldDropdown(e.options);break;case "field_iconmenu":f=new Blockly.FieldIconMenu(e.options);
|
||||
break;case "field_image":f=new Blockly.FieldImage(e.src,e.width,e.height,e.alt,e.flip_rtl);break;case "field_date":if(Blockly.FieldDate){f=new Blockly.FieldDate(e.date);break}default:e.alt&&(e=e.alt,h=!0)}while(h);if(f)d.push([f,e.name]);else if(b){e.check&&b.setCheck(e.check);e.align&&b.setAlign(c[e.align]);for(e=0;e<d.length;e++)b.appendField(d[e][0],d[e][1]);d.length=0}}};
|
||||
new Blockly.FieldTextInput(e.text);"boolean"==typeof e.spellcheck&&f.setSpellcheck(e.spellcheck);break;case "field_angle":f=new Blockly.FieldAngle(e.angle);break;case "field_number":f=new Blockly.FieldNumber(e.number,null,e.precision,e.min,e.max);break;case "field_checkbox":f=new Blockly.FieldCheckbox(e.checked?"TRUE":"FALSE");break;case "field_colour":f=new Blockly.FieldColour(e.colour);break;case "field_variable":f=new Blockly.FieldVariable(e.variable);break;case "field_dropdown":f=new Blockly.FieldDropdown(e.options);
|
||||
break;case "field_iconmenu":f=new Blockly.FieldIconMenu(e.options);break;case "field_image":f=new Blockly.FieldImage(e.src,e.width,e.height,e.alt,e.flip_rtl);break;case "field_date":if(Blockly.FieldDate){f=new Blockly.FieldDate(e.date);break}default:e.alt&&(e=e.alt,h=!0)}while(h);if(f)d.push([f,e.name]);else if(b){e.check&&b.setCheck(e.check);e.align&&b.setAlign(c[e.align]);for(e=0;e<d.length;e++)b.appendField(d[e][0],d[e][1]);d.length=0}}};
|
||||
Blockly.Block.prototype.appendInput_=function(a,b){var c=null;if(a==Blockly.INPUT_VALUE||a==Blockly.NEXT_STATEMENT)c=new Blockly.Connection(this,a);c=new Blockly.Input(a,b,this,c);this.inputList.push(c);return c};
|
||||
Blockly.Block.prototype.moveInputBefore=function(a,b){if(a!=b){for(var c=-1,d=b?-1:this.inputList.length,e=0,f;f=this.inputList[e];e++)if(f.name==a){if(c=e,-1!=d)break}else if(b&&f.name==b&&(d=e,-1!=c))break;goog.asserts.assert(-1!=c,'Named input "%s" not found.',a);goog.asserts.assert(-1!=d,'Reference input "%s" not found.',b);this.moveNumberedInputBefore(c,d)}};
|
||||
Blockly.Block.prototype.moveNumberedInputBefore=function(a,b){goog.asserts.assert(a!=b,"Can't move input to itself.");goog.asserts.assert(a<this.inputList.length,"Input index "+a+" out of bounds.");goog.asserts.assert(b<=this.inputList.length,"Reference input "+b+" out of bounds.");var c=this.inputList[a];this.inputList.splice(a,1);a<b&&b--;this.inputList.splice(b,0,c)};
|
||||
|
@ -1278,7 +1278,8 @@ Blockly.FieldAngle.prototype.onMouseMove=function(a){var b=this.gauge_.ownerSVGE
|
|||
b,this.setValue(b),this.validate_(),this.resizeEditor_())};Blockly.FieldAngle.prototype.setText=function(a){Blockly.FieldAngle.superClass_.setText.call(this,a);this.textElement_&&(this.updateGraph_(),this.sourceBlock_.RTL?this.textElement_.insertBefore(this.symbol_,this.textElement_.firstChild):this.textElement_.appendChild(this.symbol_),this.size_.width=0)};
|
||||
Blockly.FieldAngle.prototype.updateGraph_=function(){if(this.gauge_){var a=Number(this.getText())+Blockly.FieldAngle.OFFSET,b=goog.math.toRadians(a),a=["M ",Blockly.FieldAngle.HALF,",",Blockly.FieldAngle.HALF],c=Blockly.FieldAngle.HALF,d=Blockly.FieldAngle.HALF;if(!isNaN(b)){var e=goog.math.toRadians(Blockly.FieldAngle.OFFSET),f=Math.cos(e)*Blockly.FieldAngle.RADIUS,g=Math.sin(e)*-Blockly.FieldAngle.RADIUS;Blockly.FieldAngle.CLOCKWISE&&(b=2*e-b);c+=Math.cos(b)*Blockly.FieldAngle.RADIUS;d-=Math.sin(b)*
|
||||
Blockly.FieldAngle.RADIUS;b=Math.abs(Math.floor((b-e)/Math.PI)%2);Blockly.FieldAngle.CLOCKWISE&&(b=1-b);a.push(" l ",f,",",g," A ",Blockly.FieldAngle.RADIUS,",",Blockly.FieldAngle.RADIUS," 0 ",b," ",Number(Blockly.FieldAngle.CLOCKWISE)," ",c,",",d," z")}this.gauge_.setAttribute("d",a.join(""));this.line_.setAttribute("x2",c);this.line_.setAttribute("y2",d)}};
|
||||
Blockly.FieldAngle.angleValidator=function(a){a=Blockly.FieldTextInput.numberValidator(a);null!==a&&(a%=360,0>a&&(a+=360),a>Blockly.FieldAngle.WRAP&&(a-=360),a=String(a));return a};Blockly.FieldCheckbox=function(a,b){Blockly.FieldCheckbox.superClass_.constructor.call(this,"",b);this.setValue(a)};goog.inherits(Blockly.FieldCheckbox,Blockly.Field);Blockly.FieldCheckbox.CHECK_CHAR="\u2713";Blockly.FieldCheckbox.prototype.CURSOR="default";
|
||||
Blockly.FieldAngle.angleValidator=function(a){a=Blockly.FieldTextInput.numberValidator(a);null!==a&&(a%=360,0>a&&(a+=360),a>Blockly.FieldAngle.WRAP&&(a-=360),a=String(a));return a};Blockly.FieldNumber=function(a,b,c,d,e){this.precision_=c;this.min_=d;this.max_=e;Blockly.FieldNumber.superClass_.constructor.call(this,a,b)};goog.inherits(Blockly.FieldNumber,Blockly.FieldTextInput);Blockly.FieldNumber.prototype.setValidator=function(a){Blockly.FieldNumber.superClass_.setValidator.call(this,a?function(b){var c=a.call(this,b),d;null===c?d=c:(void 0===c&&(c=b),d=Blockly.FieldNumber.numberValidator.call(this,c),void 0===d&&(d=c));return d===b?void 0:d}:Blockly.FieldNumber.numberValidator)};
|
||||
Blockly.FieldNumber.prototype.showEditor_=function(){Blockly.FieldNumber.superClass_.showEditor_.call(this,goog.userAgent.MOBILE||goog.userAgent.ANDROID||goog.userAgent.IPAD)};Blockly.FieldNumber.numberValidator=function(a){a=Blockly.FieldTextInput.numberValidator(a);null!==a&&(a=Math.min(this.min,Math.max(a,this.max_)),a=a.toFixed(this.precision_),a=parseFloat(a),a=String(a));return a};Blockly.FieldCheckbox=function(a,b){Blockly.FieldCheckbox.superClass_.constructor.call(this,"",b);this.setValue(a)};goog.inherits(Blockly.FieldCheckbox,Blockly.Field);Blockly.FieldCheckbox.CHECK_CHAR="\u2713";Blockly.FieldCheckbox.prototype.CURSOR="default";
|
||||
Blockly.FieldCheckbox.prototype.init=function(a){this.sourceBlock_||(Blockly.FieldCheckbox.superClass_.init.call(this,a),this.checkElement_=Blockly.createSvgElement("text",{"class":"blocklyText blocklyCheckbox",x:-3,y:14},this.fieldGroup_),a=document.createTextNode(Blockly.FieldCheckbox.CHECK_CHAR),this.checkElement_.appendChild(a),this.checkElement_.style.display=this.state_?"block":"none")};Blockly.FieldCheckbox.prototype.getValue=function(){return String(this.state_).toUpperCase()};
|
||||
Blockly.FieldCheckbox.prototype.setValue=function(a){a="TRUE"==a;this.state_!==a&&(this.sourceBlock_&&Blockly.Events.isEnabled()&&Blockly.Events.fire(new Blockly.Events.Change(this.sourceBlock_,"field",this.name,this.state_,a)),this.state_=a,this.checkElement_&&(this.checkElement_.style.display=a?"block":"none"))};Blockly.FieldCheckbox.prototype.showEditor_=function(){var a=!this.state_;if(this.sourceBlock_&&this.validator_){var b=this.validator_(a);void 0!==b&&(a=b)}null!==a&&this.setValue(String(a).toUpperCase())};Blockly.FieldColour=function(a,b){Blockly.FieldColour.superClass_.constructor.call(this,a,b);this.setText(Blockly.Field.NBSP+Blockly.Field.NBSP+Blockly.Field.NBSP)};goog.inherits(Blockly.FieldColour,Blockly.Field);Blockly.FieldColour.prototype.colours_=null;Blockly.FieldColour.prototype.columns_=0;Blockly.FieldColour.prototype.init=function(a){Blockly.FieldColour.superClass_.init.call(this,a);this.borderRect_&&(this.borderRect_.style.fillOpacity=1);this.setValue(this.getValue())};
|
||||
Blockly.FieldColour.prototype.CURSOR="default";Blockly.FieldColour.prototype.dispose=function(){Blockly.WidgetDiv.hideIfOwner(this);Blockly.FieldColour.superClass_.dispose.call(this)};Blockly.FieldColour.prototype.getValue=function(){return this.colour_};
|
||||
|
|
|
@ -1143,8 +1143,8 @@ Blockly.Block.prototype.jsonInit=function(a){goog.asserts.assert(void 0==a.outpu
|
|||
a.previousStatement);void 0!==a.nextStatement&&this.setNextStatement(!0,a.nextStatement);void 0!==a.tooltip&&this.setTooltip(a.tooltip);void 0!==a.helpUrl&&this.setHelpUrl(a.helpUrl)};
|
||||
Blockly.Block.prototype.interpolate_=function(a,b,c){var d=Blockly.tokenizeInterpolation(a),e=[],f=0;a=[];for(var g=0;g<d.length;g++){var h=d[g];"number"==typeof h?(goog.asserts.assert(0<h&&h<=b.length,'Message index "%s" out of range.',h),goog.asserts.assert(!e[h],'Message index "%s" duplicated.',h),e[h]=!0,f++,a.push(b[h-1])):(h=h.trim())&&a.push(h)}goog.asserts.assert(f==b.length,"Message does not reference all %s arg(s).",b.length);!a.length||"string"!=typeof a[a.length-1]&&0!=a[a.length-1].type.indexOf("field_")||
|
||||
(b={type:"input_dummy"},c&&(b.align=c),a.push(b));c={LEFT:Blockly.ALIGN_LEFT,RIGHT:Blockly.ALIGN_RIGHT,CENTRE:Blockly.ALIGN_CENTRE};d=[];for(g=0;g<a.length;g++)if(e=a[g],"string"==typeof e)d.push([e,void 0]);else{b=f=null;do switch(h=!1,e.type){case "input_value":b=this.appendValueInput(e.name);break;case "input_statement":b=this.appendStatementInput(e.name);break;case "input_dummy":b=this.appendDummyInput(e.name);break;case "field_label":f=new Blockly.FieldLabel(e.text,e["class"]);break;case "field_input":f=
|
||||
new Blockly.FieldTextInput(e.text);"boolean"==typeof e.spellcheck&&f.setSpellcheck(e.spellcheck);break;case "field_angle":f=new Blockly.FieldAngle(e.angle);break;case "field_checkbox":f=new Blockly.FieldCheckbox(e.checked?"TRUE":"FALSE");break;case "field_colour":f=new Blockly.FieldColour(e.colour);break;case "field_variable":f=new Blockly.FieldVariable(e.variable);break;case "field_dropdown":f=new Blockly.FieldDropdown(e.options);break;case "field_iconmenu":f=new Blockly.FieldIconMenu(e.options);
|
||||
break;case "field_image":f=new Blockly.FieldImage(e.src,e.width,e.height,e.alt,e.flip_rtl);break;case "field_date":if(Blockly.FieldDate){f=new Blockly.FieldDate(e.date);break}default:e.alt&&(e=e.alt,h=!0)}while(h);if(f)d.push([f,e.name]);else if(b){e.check&&b.setCheck(e.check);e.align&&b.setAlign(c[e.align]);for(e=0;e<d.length;e++)b.appendField(d[e][0],d[e][1]);d.length=0}}};
|
||||
new Blockly.FieldTextInput(e.text);"boolean"==typeof e.spellcheck&&f.setSpellcheck(e.spellcheck);break;case "field_angle":f=new Blockly.FieldAngle(e.angle);break;case "field_number":f=new Blockly.FieldNumber(e.number,null,e.precision,e.min,e.max);break;case "field_checkbox":f=new Blockly.FieldCheckbox(e.checked?"TRUE":"FALSE");break;case "field_colour":f=new Blockly.FieldColour(e.colour);break;case "field_variable":f=new Blockly.FieldVariable(e.variable);break;case "field_dropdown":f=new Blockly.FieldDropdown(e.options);
|
||||
break;case "field_iconmenu":f=new Blockly.FieldIconMenu(e.options);break;case "field_image":f=new Blockly.FieldImage(e.src,e.width,e.height,e.alt,e.flip_rtl);break;case "field_date":if(Blockly.FieldDate){f=new Blockly.FieldDate(e.date);break}default:e.alt&&(e=e.alt,h=!0)}while(h);if(f)d.push([f,e.name]);else if(b){e.check&&b.setCheck(e.check);e.align&&b.setAlign(c[e.align]);for(e=0;e<d.length;e++)b.appendField(d[e][0],d[e][1]);d.length=0}}};
|
||||
Blockly.Block.prototype.appendInput_=function(a,b){var c=null;if(a==Blockly.INPUT_VALUE||a==Blockly.NEXT_STATEMENT)c=new Blockly.Connection(this,a);c=new Blockly.Input(a,b,this,c);this.inputList.push(c);return c};
|
||||
Blockly.Block.prototype.moveInputBefore=function(a,b){if(a!=b){for(var c=-1,d=b?-1:this.inputList.length,e=0,f;f=this.inputList[e];e++)if(f.name==a){if(c=e,-1!=d)break}else if(b&&f.name==b&&(d=e,-1!=c))break;goog.asserts.assert(-1!=c,'Named input "%s" not found.',a);goog.asserts.assert(-1!=d,'Reference input "%s" not found.',b);this.moveNumberedInputBefore(c,d)}};
|
||||
Blockly.Block.prototype.moveNumberedInputBefore=function(a,b){goog.asserts.assert(a!=b,"Can't move input to itself.");goog.asserts.assert(a<this.inputList.length,"Input index "+a+" out of bounds.");goog.asserts.assert(b<=this.inputList.length,"Reference input "+b+" out of bounds.");var c=this.inputList[a];this.inputList.splice(a,1);a<b&&b--;this.inputList.splice(b,0,c)};
|
||||
|
@ -1277,7 +1277,8 @@ Blockly.FieldAngle.prototype.onMouseMove=function(a){var b=this.gauge_.ownerSVGE
|
|||
b,this.setValue(b),this.validate_(),this.resizeEditor_())};Blockly.FieldAngle.prototype.setText=function(a){Blockly.FieldAngle.superClass_.setText.call(this,a);this.textElement_&&(this.updateGraph_(),this.sourceBlock_.RTL?this.textElement_.insertBefore(this.symbol_,this.textElement_.firstChild):this.textElement_.appendChild(this.symbol_),this.size_.width=0)};
|
||||
Blockly.FieldAngle.prototype.updateGraph_=function(){if(this.gauge_){var a=Number(this.getText())+Blockly.FieldAngle.OFFSET,b=goog.math.toRadians(a),a=["M ",Blockly.FieldAngle.HALF,",",Blockly.FieldAngle.HALF],c=Blockly.FieldAngle.HALF,d=Blockly.FieldAngle.HALF;if(!isNaN(b)){var e=goog.math.toRadians(Blockly.FieldAngle.OFFSET),f=Math.cos(e)*Blockly.FieldAngle.RADIUS,g=Math.sin(e)*-Blockly.FieldAngle.RADIUS;Blockly.FieldAngle.CLOCKWISE&&(b=2*e-b);c+=Math.cos(b)*Blockly.FieldAngle.RADIUS;d-=Math.sin(b)*
|
||||
Blockly.FieldAngle.RADIUS;b=Math.abs(Math.floor((b-e)/Math.PI)%2);Blockly.FieldAngle.CLOCKWISE&&(b=1-b);a.push(" l ",f,",",g," A ",Blockly.FieldAngle.RADIUS,",",Blockly.FieldAngle.RADIUS," 0 ",b," ",Number(Blockly.FieldAngle.CLOCKWISE)," ",c,",",d," z")}this.gauge_.setAttribute("d",a.join(""));this.line_.setAttribute("x2",c);this.line_.setAttribute("y2",d)}};
|
||||
Blockly.FieldAngle.angleValidator=function(a){a=Blockly.FieldTextInput.numberValidator(a);null!==a&&(a%=360,0>a&&(a+=360),a>Blockly.FieldAngle.WRAP&&(a-=360),a=String(a));return a};Blockly.FieldCheckbox=function(a,b){Blockly.FieldCheckbox.superClass_.constructor.call(this,"",b);this.setValue(a)};goog.inherits(Blockly.FieldCheckbox,Blockly.Field);Blockly.FieldCheckbox.CHECK_CHAR="\u2713";Blockly.FieldCheckbox.prototype.CURSOR="default";
|
||||
Blockly.FieldAngle.angleValidator=function(a){a=Blockly.FieldTextInput.numberValidator(a);null!==a&&(a%=360,0>a&&(a+=360),a>Blockly.FieldAngle.WRAP&&(a-=360),a=String(a));return a};Blockly.FieldNumber=function(a,b,c,d,e){this.precision_=c;this.min_=d;this.max_=e;Blockly.FieldNumber.superClass_.constructor.call(this,a,b)};goog.inherits(Blockly.FieldNumber,Blockly.FieldTextInput);Blockly.FieldNumber.prototype.setValidator=function(a){Blockly.FieldNumber.superClass_.setValidator.call(this,a?function(b){var c=a.call(this,b),d;null===c?d=c:(void 0===c&&(c=b),d=Blockly.FieldNumber.numberValidator.call(this,c),void 0===d&&(d=c));return d===b?void 0:d}:Blockly.FieldNumber.numberValidator)};
|
||||
Blockly.FieldNumber.prototype.showEditor_=function(){Blockly.FieldNumber.superClass_.showEditor_.call(this,goog.userAgent.MOBILE||goog.userAgent.ANDROID||goog.userAgent.IPAD)};Blockly.FieldNumber.numberValidator=function(a){a=Blockly.FieldTextInput.numberValidator(a);null!==a&&(a=Math.min(this.min,Math.max(a,this.max_)),a=a.toFixed(this.precision_),a=parseFloat(a),a=String(a));return a};Blockly.FieldCheckbox=function(a,b){Blockly.FieldCheckbox.superClass_.constructor.call(this,"",b);this.setValue(a)};goog.inherits(Blockly.FieldCheckbox,Blockly.Field);Blockly.FieldCheckbox.CHECK_CHAR="\u2713";Blockly.FieldCheckbox.prototype.CURSOR="default";
|
||||
Blockly.FieldCheckbox.prototype.init=function(a){this.sourceBlock_||(Blockly.FieldCheckbox.superClass_.init.call(this,a),this.checkElement_=Blockly.createSvgElement("text",{"class":"blocklyText blocklyCheckbox",x:-3,y:14},this.fieldGroup_),a=document.createTextNode(Blockly.FieldCheckbox.CHECK_CHAR),this.checkElement_.appendChild(a),this.checkElement_.style.display=this.state_?"block":"none")};Blockly.FieldCheckbox.prototype.getValue=function(){return String(this.state_).toUpperCase()};
|
||||
Blockly.FieldCheckbox.prototype.setValue=function(a){a="TRUE"==a;this.state_!==a&&(this.sourceBlock_&&Blockly.Events.isEnabled()&&Blockly.Events.fire(new Blockly.Events.Change(this.sourceBlock_,"field",this.name,this.state_,a)),this.state_=a,this.checkElement_&&(this.checkElement_.style.display=a?"block":"none"))};Blockly.FieldCheckbox.prototype.showEditor_=function(){var a=!this.state_;if(this.sourceBlock_&&this.validator_){var b=this.validator_(a);void 0!==b&&(a=b)}null!==a&&this.setValue(String(a).toUpperCase())};Blockly.FieldColour=function(a,b){Blockly.FieldColour.superClass_.constructor.call(this,a,b);this.setText(Blockly.Field.NBSP+Blockly.Field.NBSP+Blockly.Field.NBSP)};goog.inherits(Blockly.FieldColour,Blockly.Field);Blockly.FieldColour.prototype.colours_=null;Blockly.FieldColour.prototype.columns_=0;Blockly.FieldColour.prototype.init=function(a){Blockly.FieldColour.superClass_.init.call(this,a);this.borderRect_&&(this.borderRect_.style.fillOpacity=1);this.setValue(this.getValue())};
|
||||
Blockly.FieldColour.prototype.CURSOR="default";Blockly.FieldColour.prototype.dispose=function(){Blockly.WidgetDiv.hideIfOwner(this);Blockly.FieldColour.superClass_.dispose.call(this)};Blockly.FieldColour.prototype.getValue=function(){return this.colour_};
|
||||
|
|
|
@ -41,7 +41,7 @@ window.BLOCKLY_BOOT = function() {
|
|||
goog.addDependency("../../../" + dir + "/core/block.js", ['Blockly.Block'], ['Blockly.Blocks', 'Blockly.Colours', 'Blockly.Comment', 'Blockly.Connection', 'Blockly.Input', 'Blockly.Mutator', 'Blockly.Warning', 'Blockly.Workspace', 'Blockly.Xml', 'goog.array', 'goog.asserts', 'goog.math.Coordinate', 'goog.string']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_render_svg_horizontal.js", ['Blockly.BlockSvg.render'], ['Blockly.BlockSvg']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_svg.js", ['Blockly.BlockSvg'], ['Blockly.Block', 'Blockly.ContextMenu', 'goog.Timer', 'goog.asserts', 'goog.dom', 'goog.math.Coordinate', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/blockly.js", ['Blockly'], ['Blockly.BlockSvg.render', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldIconMenu', 'Blockly.FieldImage', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.Generator', 'Blockly.Msg', 'Blockly.Procedures', 'Blockly.Toolbox', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.constants', 'Blockly.inject', 'Blockly.utils', 'goog.color', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/blockly.js", ['Blockly'], ['Blockly.BlockSvg.render', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.FieldAngle', 'Blockly.FieldNumber', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldIconMenu', 'Blockly.FieldImage', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.Generator', 'Blockly.Msg', 'Blockly.Procedures', 'Blockly.Toolbox', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.constants', 'Blockly.inject', 'Blockly.utils', 'goog.color', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/blocks.js", ['Blockly.Blocks'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/bubble.js", ['Blockly.Bubble'], ['Blockly.Workspace', 'goog.dom', 'goog.math', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/colours.js", ['Blockly.Colours'], []);
|
||||
|
@ -63,6 +63,7 @@ goog.addDependency("../../../" + dir + "/core/field_dropdown.js", ['Blockly.Fiel
|
|||
goog.addDependency("../../../" + dir + "/core/field_iconmenu.js", ['Blockly.FieldIconMenu'], ['Blockly.DropDownDiv']);
|
||||
goog.addDependency("../../../" + dir + "/core/field_image.js", ['Blockly.FieldImage'], ['Blockly.Field', 'goog.dom', 'goog.math.Size', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/field_label.js", ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.Tooltip', 'goog.dom', 'goog.math.Size']);
|
||||
goog.addDependency("../../../" + dir + "/core/field_number.js", ['Blockly.FieldNumber'], ['Blockly.FieldTextInput', 'goog.math', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/field_textinput.js", ['Blockly.FieldTextInput'], ['Blockly.BlockSvg.render', 'Blockly.Colours', 'Blockly.Field', 'Blockly.Msg', 'Blockly.utils', 'goog.asserts', 'goog.dom', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/field_variable.js", ['Blockly.FieldVariable'], ['Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.Variables', 'goog.string']);
|
||||
goog.addDependency("../../../" + dir + "/core/flyout.js", ['Blockly.Flyout'], ['Blockly.Block', 'Blockly.Comment', 'Blockly.WorkspaceSvg', 'goog.dom', 'goog.events', 'goog.math.Rect', 'goog.userAgent']);
|
||||
|
@ -1611,6 +1612,7 @@ goog.require('Blockly.FieldDropdown');
|
|||
goog.require('Blockly.FieldIconMenu');
|
||||
goog.require('Blockly.FieldImage');
|
||||
goog.require('Blockly.FieldLabel');
|
||||
goog.require('Blockly.FieldNumber');
|
||||
goog.require('Blockly.FieldTextInput');
|
||||
goog.require('Blockly.FieldVariable');
|
||||
goog.require('Blockly.Flyout');
|
||||
|
|
|
@ -41,7 +41,7 @@ window.BLOCKLY_BOOT = function() {
|
|||
goog.addDependency("../../../" + dir + "/core/block.js", ['Blockly.Block'], ['Blockly.Blocks', 'Blockly.Colours', 'Blockly.Comment', 'Blockly.Connection', 'Blockly.Input', 'Blockly.Mutator', 'Blockly.Warning', 'Blockly.Workspace', 'Blockly.Xml', 'goog.array', 'goog.asserts', 'goog.math.Coordinate', 'goog.string']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_render_svg_vertical.js", ['Blockly.BlockSvg.render'], ['Blockly.BlockSvg']);
|
||||
goog.addDependency("../../../" + dir + "/core/block_svg.js", ['Blockly.BlockSvg'], ['Blockly.Block', 'Blockly.ContextMenu', 'goog.Timer', 'goog.asserts', 'goog.dom', 'goog.math.Coordinate', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/blockly.js", ['Blockly'], ['Blockly.BlockSvg.render', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.FieldAngle', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldIconMenu', 'Blockly.FieldImage', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.Generator', 'Blockly.Msg', 'Blockly.Procedures', 'Blockly.Toolbox', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.constants', 'Blockly.inject', 'Blockly.utils', 'goog.color', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/blockly.js", ['Blockly'], ['Blockly.BlockSvg.render', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.FieldAngle', 'Blockly.FieldNumber', 'Blockly.FieldCheckbox', 'Blockly.FieldColour', 'Blockly.FieldDropdown', 'Blockly.FieldIconMenu', 'Blockly.FieldImage', 'Blockly.FieldTextInput', 'Blockly.FieldVariable', 'Blockly.Generator', 'Blockly.Msg', 'Blockly.Procedures', 'Blockly.Toolbox', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.constants', 'Blockly.inject', 'Blockly.utils', 'goog.color', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/blocks.js", ['Blockly.Blocks'], []);
|
||||
goog.addDependency("../../../" + dir + "/core/bubble.js", ['Blockly.Bubble'], ['Blockly.Workspace', 'goog.dom', 'goog.math', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/colours.js", ['Blockly.Colours'], []);
|
||||
|
@ -63,6 +63,7 @@ goog.addDependency("../../../" + dir + "/core/field_dropdown.js", ['Blockly.Fiel
|
|||
goog.addDependency("../../../" + dir + "/core/field_iconmenu.js", ['Blockly.FieldIconMenu'], ['Blockly.DropDownDiv']);
|
||||
goog.addDependency("../../../" + dir + "/core/field_image.js", ['Blockly.FieldImage'], ['Blockly.Field', 'goog.dom', 'goog.math.Size', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/field_label.js", ['Blockly.FieldLabel'], ['Blockly.Field', 'Blockly.Tooltip', 'goog.dom', 'goog.math.Size']);
|
||||
goog.addDependency("../../../" + dir + "/core/field_number.js", ['Blockly.FieldNumber'], ['Blockly.FieldTextInput', 'goog.math', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/field_textinput.js", ['Blockly.FieldTextInput'], ['Blockly.BlockSvg.render', 'Blockly.Colours', 'Blockly.Field', 'Blockly.Msg', 'Blockly.utils', 'goog.asserts', 'goog.dom', 'goog.userAgent']);
|
||||
goog.addDependency("../../../" + dir + "/core/field_variable.js", ['Blockly.FieldVariable'], ['Blockly.FieldDropdown', 'Blockly.Msg', 'Blockly.Variables', 'goog.string']);
|
||||
goog.addDependency("../../../" + dir + "/core/flyout.js", ['Blockly.Flyout'], ['Blockly.Block', 'Blockly.Comment', 'Blockly.WorkspaceSvg', 'goog.dom', 'goog.events', 'goog.math.Rect', 'goog.userAgent']);
|
||||
|
@ -1611,6 +1612,7 @@ goog.require('Blockly.FieldDropdown');
|
|||
goog.require('Blockly.FieldIconMenu');
|
||||
goog.require('Blockly.FieldImage');
|
||||
goog.require('Blockly.FieldLabel');
|
||||
goog.require('Blockly.FieldNumber');
|
||||
goog.require('Blockly.FieldTextInput');
|
||||
goog.require('Blockly.FieldVariable');
|
||||
goog.require('Blockly.Flyout');
|
||||
|
|
|
@ -45,8 +45,8 @@ Blockly.Blocks['math_number'] = {
|
|||
this.setHelpUrl(Blockly.Msg.MATH_NUMBER_HELPURL);
|
||||
this.setColour(Blockly.Blocks.math.HUE);
|
||||
this.appendDummyInput()
|
||||
.appendField(new Blockly.FieldTextInput('0',
|
||||
Blockly.FieldTextInput.numberValidator), 'NUM');
|
||||
.appendField(new Blockly.FieldNumber('0',
|
||||
Blockly.FieldTextInput.numberValidator, 20, -Infinity, Infinity), 'NUM');
|
||||
this.setOutput(true, 'Number');
|
||||
// Assign 'this' to a variable for use in the tooltip closure below.
|
||||
var thisBlock = this;
|
||||
|
@ -58,6 +58,36 @@ Blockly.Blocks['math_number'] = {
|
|||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_whole_number'] = {
|
||||
/**
|
||||
* Block for whole number value, with min of 0 and max Infinity, precision 0.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.MATH_NUMBER_HELPURL);
|
||||
this.setColour(Blockly.Blocks.math.HUE);
|
||||
this.appendDummyInput()
|
||||
.appendField(new Blockly.FieldNumber('0',
|
||||
Blockly.FieldNumber.numberValidator, 0, 0, Infinity), 'NUM');
|
||||
this.setOutput(true, 'Number');
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_positive_number'] = {
|
||||
/**
|
||||
* Block for positive number value, with min of 0 and max Infinity, precision 20.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.MATH_NUMBER_HELPURL);
|
||||
this.setColour(Blockly.Blocks.math.HUE);
|
||||
this.appendDummyInput()
|
||||
.appendField(new Blockly.FieldNumber('0',
|
||||
Blockly.FieldNumber.numberValidator, 20, 0, Infinity), 'NUM');
|
||||
this.setOutput(true, 'Number');
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_arithmetic'] = {
|
||||
/**
|
||||
* Block for basic arithmetic operator.
|
||||
|
|
|
@ -1184,6 +1184,10 @@ Blockly.Block.prototype.interpolate_ = function(message, args, lastDummyAlign) {
|
|||
case 'field_angle':
|
||||
field = new Blockly.FieldAngle(element['angle']);
|
||||
break;
|
||||
case 'field_number':
|
||||
field = new Blockly.FieldNumber(element['number'], null,
|
||||
element['precision'], element['min'], element['max']);
|
||||
break;
|
||||
case 'field_checkbox':
|
||||
field = new Blockly.FieldCheckbox(
|
||||
element['checked'] ? 'TRUE' : 'FALSE');
|
||||
|
|
|
@ -31,6 +31,7 @@ goog.require('Blockly.BlockSvg.render');
|
|||
goog.require('Blockly.DropDownDiv');
|
||||
goog.require('Blockly.Events');
|
||||
goog.require('Blockly.FieldAngle');
|
||||
goog.require('Blockly.FieldNumber');
|
||||
goog.require('Blockly.FieldCheckbox');
|
||||
goog.require('Blockly.FieldColour');
|
||||
// Date picker commented out since it increases footprint by 60%.
|
||||
|
|
|
@ -65,5 +65,9 @@ Blockly.Colours = {
|
|||
"stackGlowOpacity": 1,
|
||||
// CSS colours: support RGBA
|
||||
"fieldShadow": "rgba(0,0,0,0.1)",
|
||||
"dropDownShadow": "rgba(0, 0, 0, .3)"
|
||||
"dropDownShadow": "rgba(0, 0, 0, .3)",
|
||||
"numPadBackground": "#547AB2",
|
||||
"numPadBorder": "#435F91",
|
||||
"numPadActiveBackground": "#435F91",
|
||||
"numPadText": "#FFFFFF"
|
||||
};
|
||||
|
|
36
core/css.js
36
core/css.js
|
@ -269,6 +269,36 @@ Blockly.Css.CONTENT = [
|
|||
'margin: 4px;',
|
||||
'}',
|
||||
|
||||
'.blocklyNumPadButton {',
|
||||
'display: inline-block;',
|
||||
'float: left;',
|
||||
'padding: 0;',
|
||||
'width: 48px;',
|
||||
'height: 48px;',
|
||||
'margin: 4px;',
|
||||
'border-radius: 4px;',
|
||||
'background: $colour_numPadBackground;',
|
||||
'color: $colour_numPadText;',
|
||||
'outline: none;',
|
||||
'border: 1px solid $colour_numPadBorder;',
|
||||
'cursor: pointer;',
|
||||
'font-weight: 600;',
|
||||
'font-family: sans-serif;',
|
||||
'font-size: 12pt;',
|
||||
'-webkit-tap-highlight-color: rgba(0,0,0,0);',
|
||||
'}',
|
||||
|
||||
'.blocklyNumPadButton > img {',
|
||||
'margin-top: 10%;',
|
||||
'width: 80%;',
|
||||
'height: 80%;',
|
||||
'}',
|
||||
|
||||
'.blocklyNumPadButton:active {',
|
||||
'background: $colour_numPadActiveBackground;',
|
||||
'-webkit-tap-highlight-color: rgba(0,0,0,0);',
|
||||
'}',
|
||||
|
||||
'.arrowTop {',
|
||||
'border-top: 1px solid;',
|
||||
'border-left: 1px solid;',
|
||||
|
@ -325,6 +355,8 @@ Blockly.Css.CONTENT = [
|
|||
'font-family: sans-serif;',
|
||||
'font-size: 12pt;',
|
||||
'font-weight: 600;',
|
||||
'-webkit-touch-callout: default;',
|
||||
'-webkit-user-select: text;',
|
||||
'}',
|
||||
|
||||
'.blocklyTextTruncated {',
|
||||
|
@ -508,6 +540,10 @@ Blockly.Css.CONTENT = [
|
|||
'padding: 0 !important;',
|
||||
'}',
|
||||
|
||||
'.blocklyDropDownNumPad {',
|
||||
'background-color: $colour_numPadBackground;',
|
||||
'}',
|
||||
|
||||
/* Override the default Closure URL. */
|
||||
'.blocklyWidgetDiv .goog-option-selected .goog-menuitem-checkbox,',
|
||||
'.blocklyWidgetDiv .goog-option-selected .goog-menuitem-icon {',
|
||||
|
|
|
@ -274,6 +274,9 @@ Blockly.FieldIconMenu.prototype.buttonClick_ = function(e) {
|
|||
Blockly.DropDownDiv.hide();
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for when the drop-down is hidden.
|
||||
*/
|
||||
Blockly.FieldIconMenu.prototype.onHide_ = function() {
|
||||
// Reset the button colour and clear accessibility properties
|
||||
// Only attempt to do this reset if sourceBlock_ is not disposed.
|
||||
|
|
287
core/field_number.js
Normal file
287
core/field_number.js
Normal file
|
@ -0,0 +1,287 @@
|
|||
/**
|
||||
* @license
|
||||
* Visual Blocks Editor
|
||||
*
|
||||
* Copyright 2016 Massachusetts Institute of Technology
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Field for numbers. Includes validator and numpad on touch.
|
||||
* @author tmickel@mit.edu (Tim Mickel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.FieldNumber');
|
||||
|
||||
goog.require('Blockly.FieldTextInput');
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.userAgent');
|
||||
|
||||
|
||||
/**
|
||||
* Class for an editable number field.
|
||||
* @param {string} text The initial content of the field.
|
||||
* @param {Function=} opt_validator An optional function that is called
|
||||
* to validate any constraints on what the user entered. Takes the new
|
||||
* text as an argument and returns the accepted text or null to abort
|
||||
* the change.
|
||||
* @param {number} precision Precision of the decimal value (negative power of 10).
|
||||
* @param {number} min Minimum value of the number.
|
||||
* @param {number} max Maximum value of the number.
|
||||
* @extends {Blockly.FieldTextInput}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.FieldNumber = function(text, opt_validator, precision, min, max) {
|
||||
this.precision_ = precision;
|
||||
this.min_ = min;
|
||||
this.max_ = max;
|
||||
Blockly.FieldNumber.superClass_.constructor.call(this, text, opt_validator);
|
||||
};
|
||||
goog.inherits(Blockly.FieldNumber, Blockly.FieldTextInput);
|
||||
|
||||
/**
|
||||
* Fixed width of the num-pad drop-down, in px.
|
||||
* @type {number}
|
||||
* @const
|
||||
*/
|
||||
Blockly.FieldNumber.DROPDOWN_WIDTH = 168;
|
||||
|
||||
/**
|
||||
* Extra padding to add between the block and the num-pad drop-down, in px.
|
||||
* @type {number}
|
||||
* @const
|
||||
*/
|
||||
Blockly.FieldNumber.DROPDOWN_Y_PADDING = 8;
|
||||
|
||||
/**
|
||||
* Buttons for the num-pad, in order from the top left.
|
||||
* Values are strings of the number or symbol will be added to the field text
|
||||
* when the button is pressed.
|
||||
* @type {Array.<string>}
|
||||
* @const
|
||||
*/
|
||||
// Calculator order
|
||||
Blockly.FieldNumber.NUMPAD_BUTTONS = ['7', '8', '9', '4', '5', '6', '1', '2', '3', '.', '0'];
|
||||
|
||||
/**
|
||||
* Src for the delete icon to be shown on the num-pad.
|
||||
* @type {string}
|
||||
* @const
|
||||
*/
|
||||
Blockly.FieldNumber.NUMPAD_DELETE_ICON = 'data:image/svg+xml;utf8,' +
|
||||
'<svg ' +
|
||||
'xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">' +
|
||||
'<path d="M28.89,11.45H16.79a2.86,2.86,0,0,0-2,.84L9.09,1' +
|
||||
'8a2.85,2.85,0,0,0,0,4l5.69,5.69a2.86,2.86,0,0,0,2,.84h12' +
|
||||
'.1a2.86,2.86,0,0,0,2.86-2.86V14.31A2.86,2.86,0,0,0,28.89' +
|
||||
',11.45ZM27.15,22.73a1,1,0,0,1,0,1.41,1,1,0,0,1-.71.3,1,1' +
|
||||
',0,0,1-.71-0.3L23,21.41l-2.73,2.73a1,1,0,0,1-1.41,0,1,1,' +
|
||||
'0,0,1,0-1.41L21.59,20l-2.73-2.73a1,1,0,0,1,0-1.41,1,1,0,' +
|
||||
'0,1,1.41,0L23,18.59l2.73-2.73a1,1,0,1,1,1.42,1.41L24.42,20Z" fill="' +
|
||||
Blockly.Colours.numPadText + '"/></svg>';
|
||||
|
||||
/**
|
||||
* Currently active field during an edit.
|
||||
* Used to give a reference to the num-pad button callbacks.
|
||||
* @type {?FieldNumber}
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldNumber.activeField_ = null;
|
||||
|
||||
/**
|
||||
* Sets a new change handler for angle field.
|
||||
* @param {Function} handler New change handler, or null.
|
||||
*/
|
||||
Blockly.FieldNumber.prototype.setValidator = function(handler) {
|
||||
var wrappedHandler;
|
||||
if (handler) {
|
||||
// Wrap the user's change handler together with the number validator.
|
||||
// This is copied entirely from FieldAngle.
|
||||
wrappedHandler = function(value) {
|
||||
var v1 = handler.call(this, value);
|
||||
var v2;
|
||||
if (v1 === null) {
|
||||
v2 = v1;
|
||||
} else {
|
||||
if (v1 === undefined) {
|
||||
v1 = value;
|
||||
}
|
||||
v2 = Blockly.FieldNumber.numberValidator.call(this, v1);
|
||||
if (v2 === undefined) {
|
||||
v2 = v1;
|
||||
}
|
||||
}
|
||||
return v2 === value ? undefined : v2;
|
||||
};
|
||||
} else {
|
||||
wrappedHandler = Blockly.FieldNumber.numberValidator;
|
||||
}
|
||||
Blockly.FieldNumber.superClass_.setValidator.call(this, wrappedHandler);
|
||||
};
|
||||
|
||||
/**
|
||||
* Show the inline free-text editor on top of the text and the num-pad if appropriate.
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldNumber.prototype.showEditor_ = function() {
|
||||
Blockly.FieldNumber.activeField_ = this;
|
||||
// Do not focus on mobile devices so we can show the num-pad
|
||||
var showNumPad =
|
||||
goog.userAgent.MOBILE || goog.userAgent.ANDROID || goog.userAgent.IPAD;
|
||||
Blockly.FieldNumber.superClass_.showEditor_.call(this, false, showNumPad);
|
||||
|
||||
// Show a numeric keypad in the drop-down on touch
|
||||
if (showNumPad) {
|
||||
this.showNumPad_();
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.FieldNumber.prototype.showNumPad_ = function() {
|
||||
// If there is an existing drop-down someone else owns, hide it immediately and clear it.
|
||||
Blockly.DropDownDiv.hideWithoutAnimation();
|
||||
Blockly.DropDownDiv.clearContent();
|
||||
|
||||
var contentDiv = Blockly.DropDownDiv.getContentDiv();
|
||||
|
||||
// Accessibility properties
|
||||
contentDiv.setAttribute('role', 'menu');
|
||||
contentDiv.setAttribute('aria-haspopup', 'true');
|
||||
|
||||
// Add numeric keypad buttons
|
||||
var buttons = Blockly.FieldNumber.NUMPAD_BUTTONS;
|
||||
for (var i = 0, buttonText; buttonText = buttons[i]; i++) {
|
||||
var button = document.createElement('button');
|
||||
button.setAttribute('role', 'menuitem');
|
||||
button.setAttribute('class', 'blocklyNumPadButton');
|
||||
button.title = buttonText;
|
||||
button.innerHTML = buttonText;
|
||||
// Num-pad only reacts on touch devices
|
||||
button.ontouchstart = Blockly.FieldNumber.numPadButtonTouch_;
|
||||
if (buttonText == '.' && this.precision_ == 0) {
|
||||
// Don't show the decimal point for inputs that must be round numbers
|
||||
button.setAttribute('style', 'visibility: hidden');
|
||||
}
|
||||
contentDiv.appendChild(button);
|
||||
}
|
||||
// Add erase button to the end
|
||||
var eraseButton = document.createElement('button');
|
||||
eraseButton.setAttribute('role', 'menuitem');
|
||||
eraseButton.setAttribute('class', 'blocklyNumPadButton');
|
||||
eraseButton.title = 'Delete';
|
||||
var eraseImage = document.createElement('img');
|
||||
eraseImage.src = Blockly.FieldNumber.NUMPAD_DELETE_ICON;
|
||||
eraseButton.appendChild(eraseImage);
|
||||
// Num-pad only reacts on touch devices
|
||||
eraseButton.ontouchstart = Blockly.FieldNumber.numPadEraseButtonTouch_;
|
||||
contentDiv.appendChild(eraseButton);
|
||||
|
||||
// Set colour and size of drop-down
|
||||
Blockly.DropDownDiv.setColour(Blockly.Colours.numPadBackground, Blockly.Colours.numPadBorder);
|
||||
contentDiv.style.width = Blockly.FieldNumber.DROPDOWN_WIDTH + 'px';
|
||||
|
||||
// Calculate positioning for the drop-down
|
||||
// sourceBlock_ is the rendered shadow field input box
|
||||
var scale = this.sourceBlock_.workspace.scale;
|
||||
var bBox = this.sourceBlock_.getHeightWidth();
|
||||
bBox.width *= scale;
|
||||
bBox.height *= scale;
|
||||
var position = this.getAbsoluteXY_();
|
||||
// If we can fit it, render below the shadow block
|
||||
var primaryX = position.x + bBox.width / 2;
|
||||
var primaryY = position.y + bBox.height + Blockly.FieldNumber.DROPDOWN_Y_PADDING;
|
||||
// If we can't fit it, render above the entire parent block
|
||||
var secondaryX = primaryX;
|
||||
var secondaryY = position.y - (Blockly.BlockSvg.MIN_BLOCK_Y * scale) - (Blockly.BlockSvg.FIELD_Y_OFFSET * scale);
|
||||
|
||||
Blockly.DropDownDiv.setBoundsElement(this.sourceBlock_.workspace.getParentSvg().parentNode);
|
||||
Blockly.DropDownDiv.show(this, primaryX, primaryY, secondaryX, secondaryY, this.onHide_.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Call for when a num-pad button is touched.
|
||||
* Determine what the user is inputting, and update the text field appropriately.
|
||||
*/
|
||||
Blockly.FieldNumber.numPadButtonTouch_ = function() {
|
||||
// String of the button (e.g., '7')
|
||||
var spliceValue = this.innerHTML;
|
||||
// Old value of the text field
|
||||
var oldValue = Blockly.FieldTextInput.htmlInput_.value;
|
||||
// Determine the selected portion of the text field
|
||||
var selectionStart = Blockly.FieldTextInput.htmlInput_.selectionStart;
|
||||
var selectionEnd = Blockly.FieldTextInput.htmlInput_.selectionEnd;
|
||||
// Splice in the new value
|
||||
var newValue = oldValue.slice(0, selectionStart) + spliceValue + oldValue.slice(selectionEnd);
|
||||
// Updates the display. The actual setValue occurs when the field is stopped editing.
|
||||
Blockly.FieldTextInput.htmlInput_.value = Blockly.FieldTextInput.htmlInput_.defaultValue = newValue;
|
||||
// Resize and scroll the text field appropriately
|
||||
Blockly.FieldNumber.superClass_.resizeEditor_.call(Blockly.FieldNumber.activeField_);
|
||||
Blockly.FieldTextInput.htmlInput_.setSelectionRange(newValue.length, newValue.length);
|
||||
Blockly.FieldTextInput.htmlInput_.scrollLeft = Blockly.FieldTextInput.htmlInput_.scrollWidth;
|
||||
};
|
||||
|
||||
/**
|
||||
* Call for when the num-pad erase button is touched.
|
||||
* Determine what the user is asking to erase, and erase it.
|
||||
*/
|
||||
Blockly.FieldNumber.numPadEraseButtonTouch_ = function() {
|
||||
// Old value of the text field
|
||||
var oldValue = Blockly.FieldTextInput.htmlInput_.value;
|
||||
// Determine what is selected to erase (if anything)
|
||||
var selectionStart = Blockly.FieldTextInput.htmlInput_.selectionStart;
|
||||
var selectionEnd = Blockly.FieldTextInput.htmlInput_.selectionEnd;
|
||||
// Cut out anything that was previously selected
|
||||
var newValue = oldValue.slice(0, selectionStart) + oldValue.slice(selectionEnd);
|
||||
if (selectionEnd - selectionStart == 0) { // Length of selection == 0
|
||||
// Delete the last character if nothing was selected
|
||||
newValue = oldValue.slice(0, selectionStart - 1) + oldValue.slice(selectionStart);
|
||||
}
|
||||
// Update the display to show erased value.
|
||||
Blockly.FieldTextInput.htmlInput_.value = Blockly.FieldTextInput.htmlInput_.defaultValue = newValue;
|
||||
// Resize and scroll the text field appropriately
|
||||
Blockly.FieldNumber.superClass_.resizeEditor_.call(Blockly.FieldNumber.activeField_);
|
||||
Blockly.FieldTextInput.htmlInput_.setSelectionRange(newValue.length, newValue.length);
|
||||
Blockly.FieldTextInput.htmlInput_.scrollLeft = Blockly.FieldTextInput.htmlInput_.scrollWidth;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for when the drop-down is hidden.
|
||||
*/
|
||||
Blockly.FieldNumber.prototype.onHide_ = function() {
|
||||
// Clear accessibility properties
|
||||
Blockly.DropDownDiv.content_.removeAttribute('role');
|
||||
Blockly.DropDownDiv.content_.removeAttribute('aria-haspopup');
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensure that only a number may be entered with the properties of this field.
|
||||
* @param {string} text The user's text.
|
||||
* @return {?string} A string representing a valid angle, or null if invalid.
|
||||
*/
|
||||
Blockly.FieldNumber.numberValidator = function(text) {
|
||||
var n = Blockly.FieldTextInput.numberValidator(text);
|
||||
if (n !== null) {
|
||||
// string -> float
|
||||
n = parseFloat(n);
|
||||
// Keep within min and max
|
||||
n = Math.min(Math.max(n, this.min_), this.max_);
|
||||
// Update float precision (returns a string)
|
||||
n = n.toFixed(this.precision_);
|
||||
// Parse to a float and back to string to remove trailing decimals
|
||||
n = parseFloat(n);
|
||||
n = String(n);
|
||||
}
|
||||
return n;
|
||||
};
|
|
@ -70,7 +70,13 @@ Blockly.FieldTextInput.ANIMATION_TIME = 0.25;
|
|||
/**
|
||||
* Padding to use for text measurement for the field during editing, in px.
|
||||
*/
|
||||
Blockly.FieldTextInput.TEXT_MEASURE_PADDING_MAGIC = 35;
|
||||
Blockly.FieldTextInput.TEXT_MEASURE_PADDING_MAGIC = 45;
|
||||
|
||||
/**
|
||||
* Numeric field types.
|
||||
* Scratch-specific property to ensure the border radius is set correctly for these types.
|
||||
*/
|
||||
Blockly.FieldTextInput.NUMERIC_FIELD_TYPES = ['math_number', 'math_positive_number', 'math_whole_number'];
|
||||
|
||||
/**
|
||||
* Mouse cursor style when over the hotspot that initiates the editor.
|
||||
|
@ -123,25 +129,14 @@ Blockly.FieldTextInput.prototype.setSpellcheck = function(check) {
|
|||
* Show the inline free-text editor on top of the text.
|
||||
* @param {boolean=} opt_quietInput True if editor should be created without
|
||||
* focus. Defaults to false.
|
||||
* @param {boolean=} opt_readOnly True if editor should be created with HTML
|
||||
* input set to read-only, to prevent virtual keyboards.
|
||||
* @private
|
||||
*/
|
||||
Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput) {
|
||||
Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput, opt_readOnly) {
|
||||
this.workspace_ = this.sourceBlock_.workspace;
|
||||
var quietInput = opt_quietInput || false;
|
||||
if (!quietInput && (goog.userAgent.MOBILE || goog.userAgent.ANDROID ||
|
||||
goog.userAgent.IPAD)) {
|
||||
// Mobile browsers have issues with in-line textareas (focus & keyboards).
|
||||
var newValue = window.prompt(Blockly.Msg.CHANGE_VALUE_TITLE, this.text_);
|
||||
if (this.sourceBlock_ && this.validator_) {
|
||||
var override = this.validator_(newValue);
|
||||
if (override !== undefined) {
|
||||
newValue = override;
|
||||
}
|
||||
}
|
||||
this.setValue(newValue);
|
||||
return;
|
||||
}
|
||||
|
||||
var readOnly = opt_readOnly || false;
|
||||
Blockly.WidgetDiv.show(this, this.sourceBlock_.RTL,
|
||||
this.widgetDispose_(), this.widgetDisposeAnimationFinished_(),
|
||||
Blockly.FieldTextInput.ANIMATION_TIME);
|
||||
|
@ -151,6 +146,9 @@ Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput) {
|
|||
// Create the input.
|
||||
var htmlInput = goog.dom.createDom('input', 'blocklyHtmlInput');
|
||||
htmlInput.setAttribute('spellcheck', this.spellcheck_);
|
||||
if (readOnly) {
|
||||
htmlInput.setAttribute('readonly', 'true');
|
||||
}
|
||||
/** @type {!HTMLInputElement} */
|
||||
Blockly.FieldTextInput.htmlInput_ = htmlInput;
|
||||
div.appendChild(htmlInput);
|
||||
|
@ -162,6 +160,8 @@ Blockly.FieldTextInput.prototype.showEditor_ = function(opt_quietInput) {
|
|||
if (!quietInput) {
|
||||
htmlInput.focus();
|
||||
htmlInput.select();
|
||||
// For iOS only
|
||||
htmlInput.setSelectionRange(0, 99999);
|
||||
}
|
||||
|
||||
// Bind to keydown -- trap Enter without IME and Esc to hide.
|
||||
|
@ -259,6 +259,7 @@ Blockly.FieldTextInput.prototype.resizeEditor_ = function() {
|
|||
var textWidth = Blockly.measureText(
|
||||
Blockly.FieldTextInput.htmlInput_.style.fontSize,
|
||||
Blockly.FieldTextInput.htmlInput_.style.fontFamily,
|
||||
Blockly.FieldTextInput.htmlInput_.style.fontWeight,
|
||||
Blockly.FieldTextInput.htmlInput_.value
|
||||
);
|
||||
// Size drawn in the canvas needs padding and scaling
|
||||
|
@ -318,7 +319,7 @@ Blockly.FieldTextInput.prototype.resizeEditor_ = function() {
|
|||
* @return {Number} Border radius in px.
|
||||
*/
|
||||
Blockly.Field.prototype.getBorderRadius = function() {
|
||||
if (this.sourceBlock_.type === 'math_number') {
|
||||
if (Blockly.FieldTextInput.NUMERIC_FIELD_TYPES.indexOf(this.sourceBlock_.type) > -1) {
|
||||
return Blockly.BlockSvg.NUMBER_FIELD_CORNER_RADIUS;
|
||||
} else {
|
||||
return Blockly.BlockSvg.TEXT_FIELD_CORNER_RADIUS;
|
||||
|
|
|
@ -641,12 +641,13 @@ Blockly.genUid.soup_ = '!#%()*+,-./:;=?@[]^_`{|}~' +
|
|||
* Measure some text using a canvas in-memory.
|
||||
* @param {string} fontSize E.g., '10pt'
|
||||
* @param {string} fontFamily E.g., 'Arial'
|
||||
* @param {string} fontWeight E.g., '600'
|
||||
* @param {string} text The actual text to measure
|
||||
* @return {number} Width of the text in px.
|
||||
*/
|
||||
Blockly.measureText = function(fontSize, fontFamily, text) {
|
||||
Blockly.measureText = function(fontSize, fontFamily, fontWeight, text) {
|
||||
var canvas = document.createElement('canvas');
|
||||
var context = canvas.getContext('2d');
|
||||
context.font = fontSize + fontFamily;
|
||||
context.font = fontWeight + ' ' + fontSize + ' ' + fontFamily;
|
||||
return context.measureText(text).width;
|
||||
};
|
||||
|
|
|
@ -205,7 +205,7 @@ function spaghetti(n) {
|
|||
var spaghettiXml = [
|
||||
' <block type="control_repeat">',
|
||||
' <value name="TIMES">',
|
||||
' <shadow type="math_number">',
|
||||
' <shadow type="math_whole_number">',
|
||||
' <field name="NUM">10</field>',
|
||||
' </shadow>',
|
||||
' </value>',
|
||||
|
@ -284,7 +284,7 @@ h1 {
|
|||
<block type="control_forever"></block>
|
||||
<block type="control_repeat">
|
||||
<value name="TIMES">
|
||||
<shadow type="math_number">
|
||||
<shadow type="math_whole_number">
|
||||
<field name="NUM">4</field>
|
||||
</shadow>
|
||||
</value>
|
||||
|
@ -292,7 +292,7 @@ h1 {
|
|||
<block type="control_stop"></block>
|
||||
<block type="control_wait">
|
||||
<value name="DURATION">
|
||||
<shadow type="math_number">
|
||||
<shadow type="math_positive_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
|
@ -309,14 +309,14 @@ h1 {
|
|||
</block>
|
||||
<block type="wedo_motorclockwise">
|
||||
<value name="DURATION">
|
||||
<shadow type="math_number">
|
||||
<shadow type="math_positive_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
</block>
|
||||
<block type="wedo_motorcounterclockwise">
|
||||
<value name="DURATION">
|
||||
<shadow type="math_number">
|
||||
<shadow type="math_positive_number">
|
||||
<field name="NUM">1</field>
|
||||
</shadow>
|
||||
</value>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue