espruino-web-ide
Version:
A Terminal and Graphical code Editor for Espruino JavaScript Microcontrollers
186 lines (165 loc) • 5.81 kB
JavaScript
/**
* @license
* Visual Blocks Editor
*
* Copyright 2012 Google Inc.
* https://developers.google.com/blockly/
*
* Modified by Gordon Williams (gw@pur3.co.uk) for Espruino
*
* 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 Text input field.
* @author primary.edw@gmail.com (Andrew Mee) based on work in field_textinput by fraser@google.com (Neil Fraser)
*/
'use strict';
goog.provide('Blockly.FieldTextArea');
goog.require('Blockly.Field');
goog.require('Blockly.Msg');
goog.require('goog.asserts');
goog.require('goog.userAgent');
/**
* Class for an editable text field.
* @param {string} text The initial content of the field.
* @param {Function} opt_changeHandler An optional function that is called
* to validate any constraints on what the user entered. Takes the new
* text as an argument and returns either the accepted text, a replacement
* text, or null to abort the change.
* @extends {Blockly.Field}
* @constructor
*/
Blockly.FieldTextArea = function(text, opt_changeHandler) {
Blockly.FieldTextArea.superClass_.constructor.call(this, text);
this.changeHandler_ = opt_changeHandler;
};
goog.inherits(Blockly.FieldTextArea, Blockly.FieldTextInput);
/**
* Clone this FieldTextArea.
* @return {!Blockly.FieldTextArea} The result of calling the constructor again
* with the current values of the arguments used during construction.
*/
Blockly.FieldTextArea.prototype.clone = function() {
return new Blockly.FieldTextArea(this.getText(), this.changeHandler_);
};
/**
* Mouse cursor style when over the hotspot that initiates the editor.
*/
Blockly.FieldTextArea.prototype.CURSOR = 'text';
/**
* Close the input widget if this input is being deleted.
*/
Blockly.FieldTextArea.prototype.dispose = function() {
Blockly.WidgetDiv.hideIfOwner(this);
Blockly.FieldTextArea.superClass_.dispose.call(this);
};
/**
* Get the text from this field as displayed on screen. May differ from getText
* due to ellipsis, and other formatting.
* @return {string} Currently displayed text.
* @private
*/
Blockly.FieldTextArea.prototype.getDisplayText_ = function() {
var text = this.text_;
if (!text) {
// Prevent the field from disappearing if empty.
return Blockly.Field.NBSP;
}
text = text.split("\n").map(function(text) {
if (text.length > this.maxDisplayLength) {
// Truncate displayed string and add an ellipsis ('...').
text = text.substring(0, this.maxDisplayLength - 2) + '\u2026';
}
// Replace whitespace with non-breaking spaces so the text doesn't collapse - keep newline.
text = text.replace(/\s/g, Blockly.Field.NBSP);
return text;
}.bind(this)).join("\n");
if (this.sourceBlock_.RTL) {
// The SVG is LTR, force text to be RTL.
text += '\u200F';
}
return text;
};
/**
* Draws the border with the correct width.
* Saves the computed width in a property.
* @private
*/
Blockly.FieldTextArea.prototype.render_ = function() {
if (!this.visible_) {
this.size_.width = 0;
return;
}
// Replace the text.
var textElement = this.textElement_;
goog.dom.removeChildren(/** @type {!Element} */ (textElement));
var txt = this.getDisplayText_();
var y = 0;
var yoffset = 14; // 12.5 is hard-coded in Blockly.Field
var txtLines = txt.split("\n");
txtLines.forEach(function(t) {
Blockly.utils.createSvgElement('tspan', {x:0,y:y+yoffset}, textElement)
.appendChild(document.createTextNode(t));
y += 20;
});
if (txtLines.length==0) y+=20;
// set up widths
this.size_.width = this.textElement_.getBBox().width + 5;
this.size_.height= y + (Blockly.BlockSvg.SEP_SPACE_Y+5) ;
if (this.borderRect_) {
this.borderRect_.setAttribute('width',
this.size_.width + Blockly.BlockSvg.SEP_SPACE_X);
this.borderRect_.setAttribute('height',
this.size_.height - (Blockly.BlockSvg.SEP_SPACE_Y+5));
}
};
/**
* Create and show a text input editor that sits directly over the text input.
* @param {boolean} quietInput True if editor should be created without
* focus.
* @private
*/
Blockly.FieldTextArea.prototype.showInlineEditor_ = function(quietInput) {
Blockly.WidgetDiv.show(this, this.sourceBlock_.RTL, this.widgetDispose_());
var div = Blockly.WidgetDiv.DIV;
// Create the input.
var htmlInput =
goog.dom.createDom("TEXTAREA", 'blocklyHtmlInput');
htmlInput.setAttribute('spellcheck', this.spellcheck_);
var fontSize =
(Blockly.FieldTextInput.FONTSIZE * this.workspace_.scale) + 'pt';
div.style.fontSize = fontSize;
htmlInput.style.fontSize = fontSize;
htmlInput.style.marginTop="2px"; // hack so we don't have to change resizeEditor_
Blockly.FieldTextInput.htmlInput_ = htmlInput;
div.appendChild(htmlInput);
htmlInput.value = htmlInput.defaultValue = this.text_;
htmlInput.oldValue_ = null;
this.validate_();
this.resizeEditor_();
if (!quietInput) {
htmlInput.focus();
htmlInput.select();
}
this.bindEvents_(htmlInput);
};
/**
* Handle key down to the editor.
* @param {!Event} e Keyboard event.
* @private
*/
Blockly.FieldTextArea.prototype.onHtmlInputKeyDown_ = function(e) {
var enterKey = 13
if (e.keyCode == enterKey) return;
Blockly.FieldTextInput.prototype.onHtmlInputKeyDown_.call(this, e);
};