Skip to content

Commit d55d9cb

Browse files
committed
Attempt to work around the IE/Edge bug where getComputedTextLength() throws an exception when the SVG node is not visible. This workaround forces a re-render, which in turn, forces a re-calculation of the node width once a block is inserted into the workspace SVG. This workaround is only executed on IE and Edge. See https://groups.google.com/forum/#!topic/blockly/T8IR4t4xAIY for the initial discussion of this issue.
1 parent 10108cc commit d55d9cb

File tree

3 files changed

+49
-13
lines changed

3 files changed

+49
-13
lines changed

core/block_render_svg.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ goog.provide('Blockly.BlockSvg.render');
2929

3030
goog.require('Blockly.BlockSvg');
3131

32+
goog.require('goog.userAgent');
33+
3234

3335
// UI constants for rendering blocks.
3436
/**
@@ -314,6 +316,13 @@ Blockly.BlockSvg.prototype.renderFields_ =
314316
if (!root) {
315317
continue;
316318
}
319+
320+
// Force a width re-calculation on IE and Edge to get around the issue
321+
// described in Blockly.Field.getCachedWidth
322+
if (goog.userAgent.IE || goog.userAgent.EDGE) {
323+
field.updateWidth();
324+
}
325+
317326
if (this.RTL) {
318327
cursorX -= field.renderSep + field.renderWidth;
319328
root.setAttribute('transform',

core/field.js

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,15 @@ Blockly.Field.prototype.render_ = function() {
295295
var textNode = document.createTextNode(this.getDisplayText_());
296296
this.textElement_.appendChild(textNode);
297297

298+
this.updateWidth();
299+
};
300+
301+
/**
302+
* Updates thw width of the field. This calls getCachedWidth which won't cache
303+
* the approximated width on IE/Edge when `getComputedTextLength` fails. Once
304+
* it eventually does succeed, the result will be cached.
305+
**/
306+
Blockly.Field.prototype.updateWidth = function() {
298307
var width = Blockly.Field.getCachedWidth(this.textElement_);
299308
if (this.borderRect_) {
300309
this.borderRect_.setAttribute('width',
@@ -306,24 +315,36 @@ Blockly.Field.prototype.render_ = function() {
306315
/**
307316
* Gets the width of a text element, caching it in the process.
308317
* @param {!Element} textElement An SVG 'text' element.
309-
* @retur {number} Width of element.
318+
* @return {number} Width of element.
310319
*/
311320
Blockly.Field.getCachedWidth = function(textElement) {
312321
var key = textElement.textContent + '\n' + textElement.className.baseVal;
313-
if (Blockly.Field.cacheWidths_ && Blockly.Field.cacheWidths_[key]) {
314-
var width = Blockly.Field.cacheWidths_[key];
315-
} else {
316-
try {
317-
var width = textElement.getComputedTextLength();
318-
} catch (e) {
319-
// MSIE 11 is known to throw "Unexpected call to method or property
320-
// access." if Blockly is hidden.
321-
var width = textElement.textContent.length * 8;
322-
}
323-
if (Blockly.Field.cacheWidths_) {
324-
Blockly.Field.cacheWidths_[key] = width;
322+
var width;
323+
324+
// Return the cached width if it exists.
325+
if (Blockly.Field.cacheWidths_) {
326+
width = Blockly.Field.cacheWidths_[key];
327+
if (width) {
328+
return width;
325329
}
326330
}
331+
332+
// Attempt to compute fetch the width of the SVG text element.
333+
try {
334+
width = textElement.getComputedTextLength();
335+
} catch (e) {
336+
// MSIE 11 and Edge are known to throw "Unexpected call to method or
337+
// property access." if the block is hidden. Instead, use an
338+
// approximation and do not cache the result. At some later point in time
339+
// when the block is inserted into the visible DOM, this method will be
340+
// called again and, at that point in time, will not throw an exception.
341+
return textElement.textContent.length * 8;
342+
}
343+
344+
// Cache the computed width and return.
345+
if (Blockly.Field.cacheWidths_) {
346+
Blockly.Field.cacheWidths_[key] = width;
347+
}
327348
return width;
328349
};
329350

core/xml.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ goog.provide('Blockly.Xml');
2828

2929
goog.require('goog.asserts');
3030
goog.require('goog.dom');
31+
goog.require('goog.userAgent');
3132

3233

3334
/**
@@ -367,6 +368,11 @@ Blockly.Xml.domToBlock = function(xmlBlock, workspace) {
367368
setTimeout(function() {
368369
if (topBlock.workspace) { // Check that the block hasn't been deleted.
369370
topBlock.setConnectionsHidden(false);
371+
// Force a render on IE and Edge to get around the issue described in
372+
// Blockly.Field.getCachedWidth
373+
if (goog.userAgent.IE || goog.userAgent.EDGE) {
374+
topBlock.render();
375+
}
370376
}
371377
}, 1);
372378
topBlock.updateDisabled();

0 commit comments

Comments
 (0)