mirror of
https://github.com/google/blockly.git
synced 2026-01-09 10:00:09 +01:00
chore: Remove radix from parseInt, simplify Blockly.utils.dom methods, use Unicode characters. (#6441)
* chore: remove radix from parseInt Previously any number starting with '0' would be parsed as octal if the radix was left blank. But this was changed years ago. It is no longer needed to specify a radix. * chore: 'ID' is identification 'id' is a part of Freud's brain. * Use Unicode characters instead of codes This is in line with the current style guide. * Simplify Blockly.utils.dom methods. classList add/remove/has supports SVG elements in all browsers Blockly supports (i.e. not IE).
This commit is contained in:
@@ -42,7 +42,7 @@ export abstract class Abstract {
|
||||
/** @alias Blockly.Events.Abstract */
|
||||
constructor() {
|
||||
/**
|
||||
* The event group id for the group this event belongs to. Groups define
|
||||
* The event group ID for the group this event belongs to. Groups define
|
||||
* events that should be treated as an single action from the user's
|
||||
* perspective, and should be undone together.
|
||||
*/
|
||||
|
||||
@@ -48,7 +48,7 @@ export class CommentBase extends AbstractEvent {
|
||||
this.workspaceId = this.isBlank ? '' : opt_comment!.workspace.id;
|
||||
|
||||
/**
|
||||
* The event group id for the group this event belongs to. Groups define
|
||||
* The event group ID for the group this event belongs to. Groups define
|
||||
* events that should be treated as an single action from the user's
|
||||
* perspective, and should be undone together.
|
||||
*/
|
||||
|
||||
@@ -41,10 +41,10 @@ export class Selected extends UiBase {
|
||||
opt_workspaceId?: string) {
|
||||
super(opt_workspaceId);
|
||||
|
||||
/** The id of the last selected element. */
|
||||
/** The ID of the last selected element. */
|
||||
this.oldElementId = opt_oldElementId;
|
||||
|
||||
/** The id of the selected element. */
|
||||
/** The ID of the selected element. */
|
||||
this.newElementId = opt_newElementId;
|
||||
|
||||
/** Type of this event. */
|
||||
|
||||
@@ -35,7 +35,7 @@ export class VarBase extends AbstractEvent {
|
||||
super();
|
||||
this.isBlank = typeof opt_variable === 'undefined';
|
||||
|
||||
/** The variable id for the variable this event pertains to. */
|
||||
/** The variable ID for the variable this event pertains to. */
|
||||
this.varId = this.isBlank ? '' : opt_variable!.getId();
|
||||
|
||||
/** The workspace identifier for this event. */
|
||||
|
||||
@@ -845,12 +845,12 @@ export abstract class Field implements IASTNodeLocationSvg,
|
||||
}
|
||||
if (text.length > this.maxDisplayLength) {
|
||||
// Truncate displayed string and add an ellipsis ('...').
|
||||
text = text.substring(0, this.maxDisplayLength - 2) + '\u2026';
|
||||
text = text.substring(0, this.maxDisplayLength - 2) + '…';
|
||||
}
|
||||
// Replace whitespace with non-breaking spaces so the text doesn't collapse.
|
||||
text = text.replace(/\s/g, Field.NBSP);
|
||||
if (this.sourceBlock_ && this.sourceBlock_.RTL) {
|
||||
// The SVG is LTR, force text to be RTL.
|
||||
// The SVG is LTR, force text to be RTL by adding an RLM.
|
||||
text += '\u200F';
|
||||
}
|
||||
return text;
|
||||
|
||||
@@ -201,7 +201,7 @@ export class FieldAngle extends FieldTextInput {
|
||||
// Add the degree symbol to the left of the number, even in RTL (issue
|
||||
// #2380)
|
||||
this.symbol_ = dom.createSvgElement(Svg.TSPAN, {});
|
||||
this.symbol_.appendChild(document.createTextNode('\u00B0'));
|
||||
this.symbol_.appendChild(document.createTextNode('°'));
|
||||
this.textElement_.appendChild(this.symbol_);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import type {Sentinel} from './utils/sentinel.js';
|
||||
*/
|
||||
export class FieldCheckbox extends Field {
|
||||
/** Default character for the checkmark. */
|
||||
static readonly CHECK_CHAR = '\u2713';
|
||||
static readonly CHECK_CHAR = '✓';
|
||||
private checkChar_: string;
|
||||
|
||||
/**
|
||||
|
||||
@@ -741,7 +741,7 @@ const IMAGE_Y_OFFSET = 5;
|
||||
const IMAGE_Y_PADDING: number = IMAGE_Y_OFFSET * 2;
|
||||
|
||||
/** Android can't (in 2014) display "▾", so use "▼" instead. */
|
||||
FieldDropdown.ARROW_CHAR = userAgent.ANDROID ? '\u25BC' : '\u25BE';
|
||||
FieldDropdown.ARROW_CHAR = userAgent.ANDROID ? '▼' : '▾';
|
||||
|
||||
/**
|
||||
* Validates the data structure to be processed as an options list.
|
||||
|
||||
@@ -190,7 +190,7 @@ export class FieldMultilineInput extends FieldTextInput {
|
||||
}
|
||||
}
|
||||
if (this.sourceBlock_.RTL) {
|
||||
// The SVG is LTR, force value to be RTL.
|
||||
// The SVG is LTR, force value to be RTL by adding an RLM.
|
||||
textLines += '\u200F';
|
||||
}
|
||||
return textLines;
|
||||
|
||||
@@ -801,12 +801,12 @@ export abstract class Flyout extends DeleteArea implements IFlyout {
|
||||
blockInfo: toolbox.BlockInfo, gaps: number[], defaultGap: number) {
|
||||
let gap;
|
||||
if (blockInfo['gap']) {
|
||||
gap = parseInt(blockInfo['gap'].toString(), 10);
|
||||
gap = parseInt(blockInfo['gap'].toString());
|
||||
} else if (blockInfo['blockxml']) {
|
||||
const xml = (typeof blockInfo['blockxml'] === 'string' ?
|
||||
Xml.textToDom(blockInfo['blockxml']) :
|
||||
blockInfo['blockxml']) as Element;
|
||||
gap = parseInt(xml.getAttribute('gap')!, 10);
|
||||
gap = parseInt(xml.getAttribute('gap')!);
|
||||
}
|
||||
gaps.push(!gap || isNaN(gap) ? defaultGap : gap);
|
||||
}
|
||||
@@ -826,7 +826,7 @@ export abstract class Flyout extends DeleteArea implements IFlyout {
|
||||
// <sep gap="36"></sep>
|
||||
// The default gap is 24, can be set larger or smaller.
|
||||
// This overwrites the gap attribute on the previous element.
|
||||
const newGap = parseInt(sepInfo['gap']!.toString(), 10);
|
||||
const newGap = parseInt(sepInfo['gap']!.toString());
|
||||
// Ignore gaps before the first block.
|
||||
if (!isNaN(newGap) && gaps.length > 0) {
|
||||
gaps[gaps.length - 1] = newGap;
|
||||
|
||||
@@ -22,7 +22,7 @@ goog.declareModuleId('Blockly.IComponent');
|
||||
*/
|
||||
export interface IComponent {
|
||||
/**
|
||||
* The unique id for this component that is used to register with the
|
||||
* The unique ID for this component that is used to register with the
|
||||
* ComponentManager.
|
||||
*/
|
||||
id: string;
|
||||
|
||||
@@ -122,7 +122,7 @@ export function findLegalName(name: string, block: Block): string {
|
||||
if (!r) {
|
||||
name += '2';
|
||||
} else {
|
||||
name = r[1] + (parseInt(r[2], 10) + 1);
|
||||
name = r[1] + (parseInt(r[2]) + 1);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
|
||||
@@ -107,7 +107,7 @@ export class CollapsibleToolboxCategory extends ToolboxCategory implements
|
||||
const categoryDef = itemDef as toolbox.CategoryInfo;
|
||||
// Categories that are collapsible are created using a class registered
|
||||
// under a different name.
|
||||
if (registryName.toUpperCase() == 'CATEGORY' &&
|
||||
if (registryName.toUpperCase() === 'CATEGORY' &&
|
||||
toolbox.isCategoryCollapsible(categoryDef)) {
|
||||
registryName = CollapsibleToolboxCategory.registrationName;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ export class Toolbox extends DeleteArea implements IAutoHideable,
|
||||
IKeyboardAccessible,
|
||||
IStyleable, IToolbox {
|
||||
/**
|
||||
* The unique id for this component that is used to register with the
|
||||
* The unique ID for this component that is used to register with the
|
||||
* ComponentManager.
|
||||
*/
|
||||
override id = 'toolbox';
|
||||
|
||||
@@ -43,7 +43,7 @@ export class ToolboxItem implements IToolboxItem {
|
||||
constructor(
|
||||
toolboxItemDef: toolbox.ToolboxItemInfo, parentToolbox: IToolbox,
|
||||
opt_parent?: ICollapsibleToolboxItem) {
|
||||
/** The id for the category. */
|
||||
/** The ID for the category. */
|
||||
this.id_ = (toolboxItemDef as AnyDuringMigration)['toolboxitemid'] ||
|
||||
idGenerator.getNextUniqueId();
|
||||
|
||||
|
||||
@@ -84,7 +84,6 @@ export function createSvgElement<T extends SVGElement>(
|
||||
|
||||
/**
|
||||
* Add a CSS class to a element.
|
||||
* Similar to Closure's goog.dom.classes.add, except it handles SVG elements.
|
||||
*
|
||||
* @param element DOM element to add class to.
|
||||
* @param className Name of class to add.
|
||||
@@ -92,14 +91,10 @@ export function createSvgElement<T extends SVGElement>(
|
||||
* @alias Blockly.utils.dom.addClass
|
||||
*/
|
||||
export function addClass(element: Element, className: string): boolean {
|
||||
let classes = element.getAttribute('class') || '';
|
||||
if ((' ' + classes + ' ').indexOf(' ' + className + ' ') !== -1) {
|
||||
if (element.classList.contains(className)) {
|
||||
return false;
|
||||
}
|
||||
if (classes) {
|
||||
classes += ' ';
|
||||
}
|
||||
element.setAttribute('class', classes + className);
|
||||
element.classList.add(className);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -119,7 +114,6 @@ export function removeClasses(element: Element, classNames: string) {
|
||||
|
||||
/**
|
||||
* Remove a CSS class from a element.
|
||||
* Similar to Closure's goog.dom.classes.remove, except it handles SVG elements.
|
||||
*
|
||||
* @param element DOM element to remove class from.
|
||||
* @param className Name of class to remove.
|
||||
@@ -127,28 +121,15 @@ export function removeClasses(element: Element, classNames: string) {
|
||||
* @alias Blockly.utils.dom.removeClass
|
||||
*/
|
||||
export function removeClass(element: Element, className: string): boolean {
|
||||
const classes = element.getAttribute('class');
|
||||
if ((' ' + classes + ' ').indexOf(' ' + className + ' ') === -1) {
|
||||
if (!element.classList.contains(className)) {
|
||||
return false;
|
||||
}
|
||||
const classList = classes!.split(/\s+/);
|
||||
for (let i = 0; i < classList.length; i++) {
|
||||
if (!classList[i] || classList[i] === className) {
|
||||
classList.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if (classList.length) {
|
||||
element.setAttribute('class', classList.join(' '));
|
||||
} else {
|
||||
element.removeAttribute('class');
|
||||
}
|
||||
element.classList.remove(className);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an element has the specified CSS class.
|
||||
* Similar to Closure's goog.dom.classes.has, except it handles SVG elements.
|
||||
*
|
||||
* @param element DOM element to check.
|
||||
* @param className Name of class to check.
|
||||
@@ -156,8 +137,7 @@ export function removeClass(element: Element, className: string): boolean {
|
||||
* @alias Blockly.utils.dom.hasClass
|
||||
*/
|
||||
export function hasClass(element: Element, className: string): boolean {
|
||||
const classes = element.getAttribute('class');
|
||||
return (' ' + classes + ' ').indexOf(' ' + className + ' ') !== -1;
|
||||
return element.classList.contains(className);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -52,7 +52,7 @@ let nextId = 0;
|
||||
|
||||
/**
|
||||
* Generate the next unique element IDs.
|
||||
* IDs are compatible with the HTML4 id attribute restrictions:
|
||||
* IDs are compatible with the HTML4 'id' attribute restrictions:
|
||||
* Use only ASCII letters, digits, '_', '-' and '.'
|
||||
*
|
||||
* For UUIDs use genUid (below) instead; this ID generator should
|
||||
|
||||
@@ -55,10 +55,10 @@ export function getRelativeXY(element: Element): Coordinate {
|
||||
const x = (element as any).x && element.getAttribute('x');
|
||||
const y = (element as any).y && element.getAttribute('y');
|
||||
if (x) {
|
||||
xy.x = parseInt(x, 10);
|
||||
xy.x = parseInt(x);
|
||||
}
|
||||
if (y) {
|
||||
xy.y = parseInt(y, 10);
|
||||
xy.y = parseInt(y);
|
||||
}
|
||||
// Second, check for transform="translate(...)" attribute.
|
||||
const transform = element.getAttribute('transform');
|
||||
|
||||
@@ -370,15 +370,15 @@ export class WorkspaceComment {
|
||||
return {
|
||||
id: xmlId,
|
||||
// The height of the comment in workspace units, or 100 if not specified.
|
||||
h: xmlH ? parseInt(xmlH, 10) : 100,
|
||||
h: xmlH ? parseInt(xmlH) : 100,
|
||||
// The width of the comment in workspace units, or 100 if not specified.
|
||||
w: xmlW ? parseInt(xmlW, 10) : 100,
|
||||
w: xmlW ? parseInt(xmlW) : 100,
|
||||
// The x position of the comment in workspace coordinates, or NaN if not
|
||||
// specified in the XML.
|
||||
x: xmlX ? parseInt(xmlX, 10) : NaN,
|
||||
x: xmlX ? parseInt(xmlX) : NaN,
|
||||
// The y position of the comment in workspace coordinates, or NaN if not
|
||||
// specified in the XML.
|
||||
y: xmlY ? parseInt(xmlY, 10) : NaN,
|
||||
y: xmlY ? parseInt(xmlY) : NaN,
|
||||
content: xml.textContent ?? '',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1227,10 +1227,8 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg {
|
||||
// Figure out where we want to put the canvas back. The order
|
||||
// in the is important because things are layered.
|
||||
const previousElement = this.svgBlockCanvas_.previousSibling as Element;
|
||||
const width =
|
||||
parseInt(this.getParentSvg().getAttribute('width') ?? '0', 10);
|
||||
const height =
|
||||
parseInt(this.getParentSvg().getAttribute('height') ?? '0', 10);
|
||||
const width = parseInt(this.getParentSvg().getAttribute('width') ?? '0');
|
||||
const height = parseInt(this.getParentSvg().getAttribute('height') ?? '0');
|
||||
const coord = svgMath.getRelativeXY(this.getCanvas());
|
||||
this.workspaceDragSurface_!.setContentsAndShow(
|
||||
this.getCanvas(), this.getBubbleCanvas(), previousElement, width,
|
||||
@@ -1409,11 +1407,11 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg {
|
||||
let blockY = 0;
|
||||
if (xmlBlock) {
|
||||
block = Xml.domToBlock(xmlBlock, this) as BlockSvg;
|
||||
blockX = parseInt(xmlBlock.getAttribute('x') ?? '0', 10);
|
||||
blockX = parseInt(xmlBlock.getAttribute('x') ?? '0');
|
||||
if (this.RTL) {
|
||||
blockX = -blockX;
|
||||
}
|
||||
blockY = parseInt(xmlBlock.getAttribute('y') ?? '0', 10);
|
||||
blockY = parseInt(xmlBlock.getAttribute('y') ?? '0');
|
||||
} else if (jsonBlock) {
|
||||
block = blocks.append(jsonBlock, this) as BlockSvg;
|
||||
blockX = jsonBlock['x'] || 10;
|
||||
@@ -1488,8 +1486,8 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg {
|
||||
try {
|
||||
comment = WorkspaceCommentSvg.fromXmlRendered(xmlComment, this);
|
||||
// Move the duplicate to original position.
|
||||
let commentX = parseInt(xmlComment.getAttribute('x') ?? '0', 10);
|
||||
let commentY = parseInt(xmlComment.getAttribute('y') ?? '0', 10);
|
||||
let commentX = parseInt(xmlComment.getAttribute('x') ?? '0');
|
||||
let commentY = parseInt(xmlComment.getAttribute('y') ?? '0');
|
||||
if (!isNaN(commentX) && !isNaN(commentY)) {
|
||||
if (this.RTL) {
|
||||
commentX = -commentX;
|
||||
|
||||
12
core/xml.ts
12
core/xml.ts
@@ -459,14 +459,12 @@ export function domToWorkspace(xml: Element, workspace: Workspace): string[] {
|
||||
// AnyDuringMigration because: Argument of type 'string | null' is not
|
||||
// assignable to parameter of type 'string'.
|
||||
const blockX = xmlChildElement.hasAttribute('x') ?
|
||||
parseInt(
|
||||
xmlChildElement.getAttribute('x') as AnyDuringMigration, 10) :
|
||||
parseInt(xmlChildElement.getAttribute('x') as AnyDuringMigration) :
|
||||
10;
|
||||
// AnyDuringMigration because: Argument of type 'string | null' is not
|
||||
// assignable to parameter of type 'string'.
|
||||
const blockY = xmlChildElement.hasAttribute('y') ?
|
||||
parseInt(
|
||||
xmlChildElement.getAttribute('y') as AnyDuringMigration, 10) :
|
||||
parseInt(xmlChildElement.getAttribute('y') as AnyDuringMigration) :
|
||||
10;
|
||||
if (!isNaN(blockX) && !isNaN(blockY)) {
|
||||
block.moveBy(workspace.RTL ? width - blockX : blockX, blockY);
|
||||
@@ -747,12 +745,10 @@ function applyCommentTagNodes(xmlChildren: Element[], block: Block) {
|
||||
const pinned = xmlChild.getAttribute('pinned') === 'true';
|
||||
// AnyDuringMigration because: Argument of type 'string | null' is not
|
||||
// assignable to parameter of type 'string'.
|
||||
const width =
|
||||
parseInt(xmlChild.getAttribute('w') as AnyDuringMigration, 10);
|
||||
const width = parseInt(xmlChild.getAttribute('w') as AnyDuringMigration);
|
||||
// AnyDuringMigration because: Argument of type 'string | null' is not
|
||||
// assignable to parameter of type 'string'.
|
||||
const height =
|
||||
parseInt(xmlChild.getAttribute('h') as AnyDuringMigration, 10);
|
||||
const height = parseInt(xmlChild.getAttribute('h') as AnyDuringMigration);
|
||||
|
||||
block.setCommentText(text);
|
||||
block.commentModel.pinned = pinned;
|
||||
|
||||
@@ -38,7 +38,7 @@ import type {WorkspaceSvg} from './workspace_svg.js';
|
||||
*/
|
||||
export class ZoomControls implements IPositionable {
|
||||
/**
|
||||
* The unique id for this component that is used to register with the
|
||||
* The unique ID for this component that is used to register with the
|
||||
* ComponentManager.
|
||||
*/
|
||||
id = 'zoomControls';
|
||||
|
||||
Reference in New Issue
Block a user