-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migrate core/utils/dom.js to goog.module syntax #5075
Changes from all commits
042b235
563defa
1d8f6e9
da81f9b
07bd3b3
f0fc360
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,36 +16,37 @@ | |
* @name Blockly.utils.dom | ||
* @namespace | ||
*/ | ||
goog.provide('Blockly.utils.dom'); | ||
goog.module('Blockly.utils.dom'); | ||
goog.module.declareLegacyNamespace(); | ||
|
||
goog.require('Blockly.utils.Svg'); | ||
goog.require('Blockly.utils.userAgent'); | ||
const Svg = goog.require('Blockly.utils.Svg'); | ||
const userAgent = goog.require('Blockly.utils.userAgent'); | ||
|
||
|
||
/** | ||
* Required name space for SVG elements. | ||
* @const | ||
*/ | ||
Blockly.utils.dom.SVG_NS = 'http://www.w3.org/2000/svg'; | ||
const SVG_NS = 'http://www.w3.org/2000/svg'; | ||
|
||
/** | ||
* Required name space for HTML elements. | ||
* @const | ||
*/ | ||
Blockly.utils.dom.HTML_NS = 'http://www.w3.org/1999/xhtml'; | ||
const HTML_NS = 'http://www.w3.org/1999/xhtml'; | ||
|
||
/** | ||
* Required name space for XLINK elements. | ||
* @const | ||
*/ | ||
Blockly.utils.dom.XLINK_NS = 'http://www.w3.org/1999/xlink'; | ||
const XLINK_NS = 'http://www.w3.org/1999/xlink'; | ||
|
||
/** | ||
* Node type constants. | ||
* https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType | ||
* @enum {number} | ||
*/ | ||
Blockly.utils.dom.NodeType = { | ||
const NodeType = { | ||
ELEMENT_NODE: 1, | ||
TEXT_NODE: 3, | ||
COMMENT_NODE: 8, | ||
|
@@ -57,36 +58,35 @@ Blockly.utils.dom.NodeType = { | |
* @type {Object} | ||
* @private | ||
*/ | ||
Blockly.utils.dom.cacheWidths_ = null; | ||
let cacheWidths = null; | ||
|
||
/** | ||
* Number of current references to cache. | ||
* @type {number} | ||
* @private | ||
*/ | ||
Blockly.utils.dom.cacheReference_ = 0; | ||
let cacheReference = 0; | ||
|
||
/** | ||
* A HTML canvas context used for computing text width. | ||
* @type {CanvasRenderingContext2D} | ||
* @private | ||
*/ | ||
Blockly.utils.dom.canvasContext_ = null; | ||
let canvasContext = null; | ||
|
||
/** | ||
* Helper method for creating SVG elements. | ||
* @param {string|Blockly.utils.Svg<T>} name Element's tag name. | ||
* @param {string|Svg<T>} name Element's tag name. | ||
* @param {!Object} attrs Dictionary of attribute names and values. | ||
* @param {Element=} opt_parent Optional parent on which to append the element. | ||
* @return {T} Newly created SVG element. The return type is {!SVGElement} if | ||
* name is a string or a more specific type if it a member of | ||
* Blockly.utils.Svg | ||
* name is a string or a more specific type if it a member of Svg. | ||
* @template T | ||
*/ | ||
Blockly.utils.dom.createSvgElement = function(name, attrs, opt_parent) { | ||
var e = /** @type {T} */ | ||
(document.createElementNS(Blockly.utils.dom.SVG_NS, String(name))); | ||
for (var key in attrs) { | ||
const createSvgElement = function(name, attrs, opt_parent) { | ||
const e = /** @type {T} */ | ||
(document.createElementNS(SVG_NS, String(name))); | ||
for (const key in attrs) { | ||
e.setAttribute(key, attrs[key]); | ||
} | ||
// IE defines a unique attribute "runtimeStyle", it is NOT applied to | ||
|
@@ -108,8 +108,8 @@ Blockly.utils.dom.createSvgElement = function(name, attrs, opt_parent) { | |
* @param {string} className Name of class to add. | ||
* @return {boolean} True if class was added, false if already present. | ||
*/ | ||
Blockly.utils.dom.addClass = function(element, className) { | ||
var classes = element.getAttribute('class') || ''; | ||
const addClass = function(element, className) { | ||
let classes = element.getAttribute('class') || ''; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, on line 117 it gets mutated. |
||
if ((' ' + classes + ' ').indexOf(' ' + className + ' ') != -1) { | ||
return false; | ||
} | ||
|
@@ -126,11 +126,10 @@ Blockly.utils.dom.addClass = function(element, className) { | |
* @param {string} classNames A string of one or multiple class names for an | ||
* element. | ||
*/ | ||
Blockly.utils.dom.removeClasses = function(element, classNames) { | ||
var classList = classNames.split(' '); | ||
for (var i = 0; i < classList.length; i++) { | ||
var cssName = classList[i]; | ||
Blockly.utils.dom.removeClass(element, cssName); | ||
const removeClasses = function(element, classNames) { | ||
const classList = classNames.split(' '); | ||
for (let i = 0; i < classList.length; i++) { | ||
removeClass(element, classList[i]); | ||
} | ||
}; | ||
|
||
|
@@ -141,13 +140,13 @@ Blockly.utils.dom.removeClasses = function(element, classNames) { | |
* @param {string} className Name of class to remove. | ||
* @return {boolean} True if class was removed, false if never present. | ||
*/ | ||
Blockly.utils.dom.removeClass = function(element, className) { | ||
var classes = element.getAttribute('class'); | ||
const removeClass = function(element, className) { | ||
const classes = element.getAttribute('class'); | ||
if ((' ' + classes + ' ').indexOf(' ' + className + ' ') == -1) { | ||
return false; | ||
} | ||
var classList = classes.split(/\s+/); | ||
for (var i = 0; i < classList.length; i++) { | ||
const classList = classes.split(/\s+/); | ||
for (let i = 0; i < classList.length; i++) { | ||
if (!classList[i] || classList[i] == className) { | ||
classList.splice(i, 1); | ||
i--; | ||
|
@@ -168,8 +167,8 @@ Blockly.utils.dom.removeClass = function(element, className) { | |
* @param {string} className Name of class to check. | ||
* @return {boolean} True if class exists, false otherwise. | ||
*/ | ||
Blockly.utils.dom.hasClass = function(element, className) { | ||
var classes = element.getAttribute('class'); | ||
const hasClass = function(element, className) { | ||
const classes = element.getAttribute('class'); | ||
return (' ' + classes + ' ').indexOf(' ' + className + ' ') != -1; | ||
}; | ||
|
||
|
@@ -179,7 +178,7 @@ Blockly.utils.dom.hasClass = function(element, className) { | |
* @return {?Node} The node removed if removed; else, null. | ||
*/ | ||
// Copied from Closure goog.dom.removeNode | ||
Blockly.utils.dom.removeNode = function(node) { | ||
const removeNode = function(node) { | ||
return node && node.parentNode ? node.parentNode.removeChild(node) : null; | ||
}; | ||
|
||
|
@@ -189,9 +188,9 @@ Blockly.utils.dom.removeNode = function(node) { | |
* @param {!Element} newNode New element to insert. | ||
* @param {!Element} refNode Existing element to precede new node. | ||
*/ | ||
Blockly.utils.dom.insertAfter = function(newNode, refNode) { | ||
var siblingNode = refNode.nextSibling; | ||
var parentNode = refNode.parentNode; | ||
const insertAfter = function(newNode, refNode) { | ||
const siblingNode = refNode.nextSibling; | ||
const parentNode = refNode.parentNode; | ||
if (!parentNode) { | ||
throw Error('Reference node has no parent.'); | ||
} | ||
|
@@ -208,9 +207,10 @@ Blockly.utils.dom.insertAfter = function(newNode, refNode) { | |
* @param {!Node} descendant The node to test presence of. | ||
* @return {boolean} Whether the parent node contains the descendant node. | ||
*/ | ||
Blockly.utils.dom.containsNode = function(parent, descendant) { | ||
return !!(parent.compareDocumentPosition(descendant) & | ||
Blockly.utils.dom.NodeType.DOCUMENT_POSITION_CONTAINED_BY); | ||
const containsNode = function(parent, descendant) { | ||
return !!( | ||
parent.compareDocumentPosition(descendant) & | ||
NodeType.DOCUMENT_POSITION_CONTAINED_BY); | ||
}; | ||
|
||
/** | ||
|
@@ -220,7 +220,7 @@ Blockly.utils.dom.containsNode = function(parent, descendant) { | |
* @param {!Element} element Element to which the CSS transform will be applied. | ||
* @param {string} transform The value of the CSS `transform` property. | ||
*/ | ||
Blockly.utils.dom.setCssTransform = function(element, transform) { | ||
const setCssTransform = function(element, transform) { | ||
element.style['transform'] = transform; | ||
element.style['-webkit-transform'] = transform; | ||
}; | ||
|
@@ -229,21 +229,21 @@ Blockly.utils.dom.setCssTransform = function(element, transform) { | |
* Start caching text widths. Every call to this function MUST also call | ||
* stopTextWidthCache. Caches must not survive between execution threads. | ||
*/ | ||
Blockly.utils.dom.startTextWidthCache = function() { | ||
Blockly.utils.dom.cacheReference_++; | ||
if (!Blockly.utils.dom.cacheWidths_) { | ||
Blockly.utils.dom.cacheWidths_ = Object.create(null); | ||
const startTextWidthCache = function() { | ||
cacheReference++; | ||
if (!cacheWidths) { | ||
cacheWidths = Object.create(null); | ||
} | ||
}; | ||
|
||
/** | ||
* Stop caching field widths. Unless caching was already on when the | ||
* corresponding call to startTextWidthCache was made. | ||
*/ | ||
Blockly.utils.dom.stopTextWidthCache = function() { | ||
Blockly.utils.dom.cacheReference_--; | ||
if (!Blockly.utils.dom.cacheReference_) { | ||
Blockly.utils.dom.cacheWidths_ = null; | ||
const stopTextWidthCache = function() { | ||
cacheReference--; | ||
if (!cacheReference) { | ||
cacheWidths = null; | ||
} | ||
}; | ||
|
||
|
@@ -252,21 +252,21 @@ Blockly.utils.dom.stopTextWidthCache = function() { | |
* @param {!Element} textElement An SVG 'text' element. | ||
* @return {number} Width of element. | ||
*/ | ||
Blockly.utils.dom.getTextWidth = function(textElement) { | ||
var key = textElement.textContent + '\n' + textElement.className.baseVal; | ||
var width; | ||
const getTextWidth = function(textElement) { | ||
const key = textElement.textContent + '\n' + textElement.className.baseVal; | ||
let width; | ||
|
||
// Return the cached width if it exists. | ||
if (Blockly.utils.dom.cacheWidths_) { | ||
width = Blockly.utils.dom.cacheWidths_[key]; | ||
if (cacheWidths) { | ||
width = cacheWidths[key]; | ||
if (width) { | ||
return width; | ||
} | ||
} | ||
|
||
// Attempt to compute fetch the width of the SVG text element. | ||
try { | ||
if (Blockly.utils.userAgent.IE || Blockly.utils.userAgent.EDGE) { | ||
if (userAgent.IE || userAgent.EDGE) { | ||
width = textElement.getBBox().width; | ||
} else { | ||
width = textElement.getComputedTextLength(); | ||
|
@@ -280,8 +280,8 @@ Blockly.utils.dom.getTextWidth = function(textElement) { | |
} | ||
|
||
// Cache the computed width and return. | ||
if (Blockly.utils.dom.cacheWidths_) { | ||
Blockly.utils.dom.cacheWidths_[key] = width; | ||
if (cacheWidths) { | ||
cacheWidths[key] = width; | ||
} | ||
return width; | ||
}; | ||
|
@@ -296,10 +296,10 @@ Blockly.utils.dom.getTextWidth = function(textElement) { | |
* @param {string} fontFamily The font family to use. | ||
* @return {number} Width of element. | ||
*/ | ||
Blockly.utils.dom.getFastTextWidth = function(textElement, | ||
fontSize, fontWeight, fontFamily) { | ||
return Blockly.utils.dom.getFastTextWidthWithSizeString(textElement, | ||
fontSize + 'pt', fontWeight, fontFamily); | ||
const getFastTextWidth = function( | ||
textElement, fontSize, fontWeight, fontFamily) { | ||
return getFastTextWidthWithSizeString( | ||
textElement, fontSize + 'pt', fontWeight, fontFamily); | ||
}; | ||
|
||
/** | ||
|
@@ -314,41 +314,40 @@ Blockly.utils.dom.getFastTextWidth = function(textElement, | |
* @param {string} fontFamily The font family to use. | ||
* @return {number} Width of element. | ||
*/ | ||
Blockly.utils.dom.getFastTextWidthWithSizeString = function(textElement, | ||
fontSize, fontWeight, fontFamily) { | ||
var text = textElement.textContent; | ||
var key = text + '\n' + textElement.className.baseVal; | ||
var width; | ||
const getFastTextWidthWithSizeString = function( | ||
textElement, fontSize, fontWeight, fontFamily) { | ||
const text = textElement.textContent; | ||
const key = text + '\n' + textElement.className.baseVal; | ||
let width; | ||
|
||
// Return the cached width if it exists. | ||
if (Blockly.utils.dom.cacheWidths_) { | ||
width = Blockly.utils.dom.cacheWidths_[key]; | ||
if (cacheWidths) { | ||
width = cacheWidths[key]; | ||
if (width) { | ||
return width; | ||
} | ||
} | ||
|
||
if (!Blockly.utils.dom.canvasContext_) { | ||
if (!canvasContext) { | ||
// Inject the canvas element used for computing text widths. | ||
var computeCanvas = document.createElement('canvas'); | ||
const computeCanvas = document.createElement('canvas'); | ||
computeCanvas.className = 'blocklyComputeCanvas'; | ||
document.body.appendChild(computeCanvas); | ||
|
||
// Initialize the HTML canvas context and set the font. | ||
// The context font must match blocklyText's fontsize and font-family | ||
// set in CSS. | ||
Blockly.utils.dom.canvasContext_ = computeCanvas.getContext('2d'); | ||
canvasContext = computeCanvas.getContext('2d'); | ||
} | ||
// Set the desired font size and family. | ||
Blockly.utils.dom.canvasContext_.font = | ||
fontWeight + ' ' + fontSize + ' ' + fontFamily; | ||
canvasContext.font = fontWeight + ' ' + fontSize + ' ' + fontFamily; | ||
|
||
// Measure the text width using the helper canvas context. | ||
width = Blockly.utils.dom.canvasContext_.measureText(text).width; | ||
width = canvasContext.measureText(text).width; | ||
|
||
// Cache the computed width and return. | ||
if (Blockly.utils.dom.cacheWidths_) { | ||
Blockly.utils.dom.cacheWidths_[key] = width; | ||
if (cacheWidths) { | ||
cacheWidths[key] = width; | ||
} | ||
return width; | ||
}; | ||
|
@@ -361,18 +360,16 @@ Blockly.utils.dom.getFastTextWidthWithSizeString = function(textElement, | |
* @param {string} fontFamily The font family to use. | ||
* @return {{height: number, baseline: number}} Font measurements. | ||
*/ | ||
Blockly.utils.dom.measureFontMetrics = function(text, fontSize, fontWeight, | ||
fontFamily) { | ||
|
||
var span = document.createElement('span'); | ||
const measureFontMetrics = function(text, fontSize, fontWeight, fontFamily) { | ||
const span = document.createElement('span'); | ||
span.style.font = fontWeight + ' ' + fontSize + ' ' + fontFamily; | ||
span.textContent = text; | ||
|
||
var block = document.createElement('div'); | ||
const block = document.createElement('div'); | ||
block.style.width = '1px'; | ||
block.style.height = 0; | ||
|
||
var div = document.createElement('div'); | ||
const div = document.createElement('div'); | ||
div.setAttribute('style', 'position: fixed; top: 0; left: 0; display: flex;'); | ||
div.appendChild(span); | ||
div.appendChild(block); | ||
|
@@ -389,3 +386,25 @@ Blockly.utils.dom.measureFontMetrics = function(text, fontSize, fontWeight, | |
} | ||
return result; | ||
}; | ||
|
||
exports = { | ||
SVG_NS, | ||
HTML_NS, | ||
XLINK_NS, | ||
NodeType, | ||
createSvgElement, | ||
addClass, | ||
removeClasses, | ||
removeClass, | ||
hasClass, | ||
removeNode, | ||
insertAfter, | ||
containsNode, | ||
setCssTransform, | ||
startTextWidthCache, | ||
stopTextWidthCache, | ||
getTextWidth, | ||
getFastTextWidth, | ||
getFastTextWidthWithSizeString, | ||
measureFontMetrics, | ||
}; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this
let
since it is redefined every loop iteration?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, because it is redefined every iteration; it's not the same variable taking on a new value, it's a new variable entirely each time through the loop.