Merge pull request #878 from groklearning/fix-ie-edge-block-text-width

Work around the IE/Edge `getComputedTextLength()` block sizing bug
This commit is contained in:
Rachel Fenichel
2017-01-27 09:39:29 -08:00
committed by GitHub
3 changed files with 49 additions and 13 deletions

View File

@@ -29,6 +29,8 @@ goog.provide('Blockly.BlockSvg.render');
goog.require('Blockly.BlockSvg');
goog.require('goog.userAgent');
// UI constants for rendering blocks.
/**
@@ -314,6 +316,13 @@ Blockly.BlockSvg.prototype.renderFields_ =
if (!root) {
continue;
}
// Force a width re-calculation on IE and Edge to get around the issue
// described in Blockly.Field.getCachedWidth
if (goog.userAgent.IE || goog.userAgent.EDGE) {
field.updateWidth();
}
if (this.RTL) {
cursorX -= field.renderSep + field.renderWidth;
root.setAttribute('transform',

View File

@@ -295,6 +295,15 @@ Blockly.Field.prototype.render_ = function() {
var textNode = document.createTextNode(this.getDisplayText_());
this.textElement_.appendChild(textNode);
this.updateWidth();
};
/**
* Updates thw width of the field. This calls getCachedWidth which won't cache
* the approximated width on IE/Edge when `getComputedTextLength` fails. Once
* it eventually does succeed, the result will be cached.
**/
Blockly.Field.prototype.updateWidth = function() {
var width = Blockly.Field.getCachedWidth(this.textElement_);
if (this.borderRect_) {
this.borderRect_.setAttribute('width',
@@ -306,24 +315,36 @@ Blockly.Field.prototype.render_ = function() {
/**
* Gets the width of a text element, caching it in the process.
* @param {!Element} textElement An SVG 'text' element.
* @retur {number} Width of element.
* @return {number} Width of element.
*/
Blockly.Field.getCachedWidth = function(textElement) {
var key = textElement.textContent + '\n' + textElement.className.baseVal;
if (Blockly.Field.cacheWidths_ && Blockly.Field.cacheWidths_[key]) {
var width = Blockly.Field.cacheWidths_[key];
} else {
try {
var width = textElement.getComputedTextLength();
} catch (e) {
// MSIE 11 is known to throw "Unexpected call to method or property
// access." if Blockly is hidden.
var width = textElement.textContent.length * 8;
}
if (Blockly.Field.cacheWidths_) {
Blockly.Field.cacheWidths_[key] = width;
var width;
// Return the cached width if it exists.
if (Blockly.Field.cacheWidths_) {
width = Blockly.Field.cacheWidths_[key];
if (width) {
return width;
}
}
// Attempt to compute fetch the width of the SVG text element.
try {
width = textElement.getComputedTextLength();
} catch (e) {
// MSIE 11 and Edge are known to throw "Unexpected call to method or
// property access." if the block is hidden. Instead, use an
// approximation and do not cache the result. At some later point in time
// when the block is inserted into the visible DOM, this method will be
// called again and, at that point in time, will not throw an exception.
return textElement.textContent.length * 8;
}
// Cache the computed width and return.
if (Blockly.Field.cacheWidths_) {
Blockly.Field.cacheWidths_[key] = width;
}
return width;
};

View File

@@ -28,6 +28,7 @@ goog.provide('Blockly.Xml');
goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.userAgent');
/**
@@ -367,6 +368,11 @@ Blockly.Xml.domToBlock = function(xmlBlock, workspace) {
setTimeout(function() {
if (topBlock.workspace) { // Check that the block hasn't been deleted.
topBlock.setConnectionsHidden(false);
// Force a render on IE and Edge to get around the issue described in
// Blockly.Field.getCachedWidth
if (goog.userAgent.IE || goog.userAgent.EDGE) {
topBlock.render();
}
}
}, 1);
topBlock.updateDisabled();