fix: adding and removing css classes that contained spaces (#6455)

* fix: adding CSS classes

* fix: removing css classes

* fix: add a test for multiple icon classes

* chore: format
This commit is contained in:
Beka Westberg
2022-09-28 15:51:17 -07:00
committed by GitHub
parent f678531389
commit 8530e6d537
26 changed files with 146 additions and 99 deletions

View File

@@ -778,10 +778,10 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg,
(group as AnyDuringMigration).translate_ = '';
(group as AnyDuringMigration).skew_ = '';
common.draggingConnections.push(...this.getConnections_(true));
this.svgGroup_.classList.add('blocklyDragging');
dom.addClass(this.svgGroup_, 'blocklyDragging');
} else {
common.draggingConnections.length = 0;
this.svgGroup_.classList.remove('blocklyDragging');
dom.removeClass(this.svgGroup_, 'blocklyDragging');
}
// Recurse through all blocks attached under this one.
for (let i = 0; i < this.childBlocks_.length; i++) {

View File

@@ -17,6 +17,7 @@ import type {BlockSvg} from './block_svg.js';
import * as browserEvents from './browser_events.js';
import * as clipboard from './clipboard.js';
import {config} from './config.js';
import * as dom from './utils/dom.js';
import type {ContextMenuOption, LegacyContextMenuOption} from './contextmenu_registry.js';
import * as eventUtils from './events/utils.js';
import {Menu} from './menu.js';
@@ -179,7 +180,7 @@ function createWidget_(menu: Menu) {
throw Error('Attempting to create a context menu when widget div is null');
}
const menuDom = menu.render(div);
menuDom.classList.add('blocklyContextMenu');
dom.addClass(menuDom, 'blocklyContextMenu');
// Prevent system context menu when right-clicking a Blockly context menu.
browserEvents.conditionalBind(
(menuDom as EventTarget), 'contextmenu', null, haltPropagation);

View File

@@ -15,6 +15,7 @@ goog.declareModuleId('Blockly.dropDownDiv');
import type {BlockSvg} from './block_svg.js';
import * as common from './common.js';
import * as dom from './utils/dom.js';
import type {Field} from './field.js';
import * as math from './utils/math.js';
import {Rect} from './utils/rect.js';
@@ -138,10 +139,10 @@ export function createDom() {
// Handle focusin/out events to add a visual indicator when
// a child is focused or blurred.
div.addEventListener('focusin', function() {
div.classList.add('blocklyFocused');
dom.addClass(div, 'blocklyFocused');
});
div.addEventListener('focusout', function() {
div.classList.remove('blocklyFocused');
dom.removeClass(div, 'blocklyFocused');
});
}
@@ -311,10 +312,10 @@ export function show(
renderedClassName = mainWorkspace.getRenderer().getClassName();
themeClassName = mainWorkspace.getTheme().getClassName();
if (renderedClassName) {
div.classList.add(renderedClassName);
dom.addClass(div, renderedClassName);
}
if (themeClassName) {
div.classList.add(themeClassName);
dom.addClass(div, themeClassName);
}
// When we change `translate` multiple times in close succession,
@@ -595,11 +596,11 @@ export function hideWithoutAnimation() {
owner = null;
if (renderedClassName) {
div.classList.remove(renderedClassName);
dom.removeClass(div, renderedClassName);
renderedClassName = '';
}
if (themeClassName) {
div.classList.remove(themeClassName);
dom.removeClass(div, themeClassName);
themeClassName = '';
}
(common.getMainWorkspace() as WorkspaceSvg).markFocused();

View File

@@ -492,12 +492,12 @@ export abstract class Field implements IASTNodeLocationSvg,
return;
}
if (this.enabled_ && this.sourceBlock_.isEditable()) {
group.classList.add('blocklyEditableText');
group.classList.remove('blocklyNonEditableText');
dom.addClass(group, 'blocklyEditableText');
dom.removeClass(group, 'blocklyNonEditableText');
group.style.cursor = this.CURSOR;
} else {
group.classList.add('blocklyNonEditableText');
group.classList.remove('blocklyEditableText');
dom.addClass(group, 'blocklyNonEditableText');
dom.removeClass(group, 'blocklyEditableText');
group.style.cursor = '';
}
}

View File

@@ -15,6 +15,7 @@ goog.declareModuleId('Blockly.FieldCheckbox');
// Unused import preserved for side-effects. Remove if unneeded.
import './events/events_block_change.js';
import * as dom from './utils/dom.js';
import {FieldConfig, Field} from './field.js';
import * as fieldRegistry from './field_registry.js';
import type {Sentinel} from './utils/sentinel.js';
@@ -111,7 +112,7 @@ export class FieldCheckbox extends Field {
override initView() {
super.initView();
this.textElement_.classList.add('blocklyCheckbox');
dom.addClass(this.textElement_, 'blocklyCheckbox');
this.textElement_.style.display = this.value_ ? 'block' : 'none';
}

View File

@@ -18,6 +18,7 @@ import './events/events_block_change.js';
import {BlockSvg} from './block_svg.js';
import * as browserEvents from './browser_events.js';
import * as Css from './css.js';
import * as dom from './utils/dom.js';
import * as dropDownDiv from './dropdowndiv.js';
import {FieldConfig, Field} from './field.js';
import * as fieldRegistry from './field_registry.js';
@@ -438,7 +439,7 @@ export class FieldColour extends Field {
(this.picker_ as AnyDuringMigration)!.blur();
const highlighted = this.getHighlighted_();
if (highlighted) {
highlighted.classList.remove('blocklyColourHighlighted');
dom.removeClass(highlighted, 'blocklyColourHighlighted');
}
}
@@ -473,10 +474,10 @@ export class FieldColour extends Field {
// Unhighlight the current item.
const highlighted = this.getHighlighted_();
if (highlighted) {
highlighted.classList.remove('blocklyColourHighlighted');
dom.removeClass(highlighted, 'blocklyColourHighlighted');
}
// Highlight new item.
cell.classList.add('blocklyColourHighlighted');
dom.addClass(cell, 'blocklyColourHighlighted');
// Set new highlighted index.
this.highlightedIndex_ = index;

View File

@@ -205,7 +205,7 @@ export class FieldDropdown extends Field {
}
if (this.borderRect_) {
this.borderRect_.classList.add('blocklyDropdownRect');
dom.addClass(this.borderRect_, 'blocklyDropdownRect');
}
}
@@ -276,7 +276,7 @@ export class FieldDropdown extends Field {
dropDownDiv.clearContent();
// Element gets created in render.
const menuElement = this.menu_!.render(dropDownDiv.getContentDiv());
menuElement.classList.add('blocklyDropdownMenu');
dom.addClass(menuElement, 'blocklyDropdownMenu');
if (this.getConstants()!.FIELD_DROPDOWN_COLOURED_DIV) {
const primaryColour = this.sourceBlock_.isShadow() ?
@@ -608,7 +608,7 @@ export class FieldDropdown extends Field {
private renderSelectedText_() {
// Retrieves the selected option to display through getText_.
this.textContent_.nodeValue = this.getDisplayText_();
this.textElement_.classList.add('blocklyDropdownText');
dom.addClass(this.textElement_, 'blocklyDropdownText');
this.textElement_.setAttribute('text-anchor', 'start');
// Height and width include the border rect.

View File

@@ -13,6 +13,7 @@
import * as goog from '../closure/goog/goog.js';
goog.declareModuleId('Blockly.FieldLabel');
import * as dom from './utils/dom.js';
import {FieldConfig, Field} from './field.js';
import * as fieldRegistry from './field_registry.js';
import * as parsing from './utils/parsing.js';
@@ -75,7 +76,7 @@ export class FieldLabel extends Field {
override initView() {
this.createTextElement_();
if (this.class_) {
this.textElement_.classList.add(this.class_);
dom.addClass(this.textElement_, this.class_);
}
}
@@ -101,10 +102,10 @@ export class FieldLabel extends Field {
setClass(cssClass: string|null) {
if (this.textElement_) {
if (this.class_) {
this.textElement_.classList.remove(this.class_);
dom.removeClass(this.textElement_, this.class_);
}
if (cssClass) {
this.textElement_.classList.add(cssClass);
dom.addClass(this.textElement_, cssClass);
}
}
this.class_ = cssClass;

View File

@@ -239,9 +239,9 @@ export class FieldMultilineInput extends FieldTextInput {
if (this.isBeingEdited_) {
const htmlInput = this.htmlInput_ as HTMLElement;
if (this.isOverflowedY_) {
htmlInput.classList.add('blocklyHtmlTextAreaInputOverflowedY');
dom.addClass(htmlInput, 'blocklyHtmlTextAreaInputOverflowedY');
} else {
htmlInput.classList.remove('blocklyHtmlTextAreaInputOverflowedY');
dom.removeClass(htmlInput, 'blocklyHtmlTextAreaInputOverflowedY');
}
}
@@ -258,10 +258,10 @@ export class FieldMultilineInput extends FieldTextInput {
}
const htmlInput = this.htmlInput_ as HTMLElement;
if (!this.isTextValid_) {
htmlInput.classList.add('blocklyInvalidInput');
dom.addClass(htmlInput, 'blocklyInvalidInput');
aria.setState(htmlInput, aria.State.INVALID, true);
} else {
htmlInput.classList.remove('blocklyInvalidInput');
dom.removeClass(htmlInput, 'blocklyInvalidInput');
aria.setState(htmlInput, aria.State.INVALID, false);
}
}

View File

@@ -18,6 +18,7 @@ import './events/events_block_change.js';
import type {BlockSvg} from './block_svg.js';
import * as browserEvents from './browser_events.js';
import * as dialog from './dialog.js';
import * as dom from './utils/dom.js';
import * as dropDownDiv from './dropdowndiv.js';
import * as eventUtils from './events/utils.js';
import {FieldConfig, Field} from './field.js';
@@ -244,10 +245,10 @@ export class FieldTextInput extends Field {
this.resizeEditor_();
const htmlInput = this.htmlInput_ as HTMLElement;
if (!this.isTextValid_) {
htmlInput.classList.add('blocklyInvalidInput');
dom.addClass(htmlInput, 'blocklyInvalidInput');
aria.setState(htmlInput, aria.State.INVALID, true);
} else {
htmlInput.classList.remove('blocklyInvalidInput');
dom.removeClass(htmlInput, 'blocklyInvalidInput');
aria.setState(htmlInput, aria.State.INVALID, false);
}
}
@@ -331,7 +332,7 @@ export class FieldTextInput extends Field {
eventUtils.setGroup(true);
const div = WidgetDiv.getDiv();
this.getClickTarget_().classList.add('editing');
dom.addClass(this.getClickTarget_(), 'editing');
const htmlInput = (document.createElement('input'));
htmlInput.className = 'blocklyHtmlInput';
@@ -400,7 +401,7 @@ export class FieldTextInput extends Field {
style.boxShadow = '';
this.htmlInput_ = null;
this.getClickTarget_().classList.remove('editing');
dom.removeClass(this.getClickTarget_(), 'editing');
}
/**

View File

@@ -69,7 +69,7 @@ export abstract class Icon {
this.iconGroup_ =
dom.createSvgElement(Svg.G, {'class': 'blocklyIconGroup'});
if (this.getBlock().isInFlyout) {
this.iconGroup_.classList.add('blocklyIconGroupReadonly');
dom.addClass(this.iconGroup_, 'blocklyIconGroupReadonly');
}
this.drawIcon_(this.iconGroup_);

View File

@@ -172,11 +172,11 @@ function createMainWorkspace(
const injectionDiv = mainWorkspace.getInjectionDiv();
const rendererClassName = mainWorkspace.getRenderer().getClassName();
if (rendererClassName) {
injectionDiv.classList.add(rendererClassName);
dom.addClass(injectionDiv, rendererClassName);
}
const themeClassName = mainWorkspace.getTheme().getClassName();
if (themeClassName) {
injectionDiv.classList.add(themeClassName);
dom.addClass(injectionDiv, themeClassName);
}
if (!wsOptions.hasCategories && wsOptions.languageTree) {

View File

@@ -16,6 +16,7 @@ import * as browserEvents from './browser_events.js';
import type {MenuItem} from './menuitem.js';
import * as aria from './utils/aria.js';
import {Coordinate} from './utils/coordinate.js';
import * as dom from './utils/dom.js';
import {KeyCodes} from './utils/keycodes.js';
import type {Size} from './utils/size.js';
import * as style from './utils/style.js';
@@ -137,7 +138,7 @@ export class Menu {
const el = this.getElement();
if (el) {
el.focus({preventScroll: true});
el.classList.add('blocklyFocused');
dom.addClass(el, 'blocklyFocused');
}
}
@@ -146,7 +147,7 @@ export class Menu {
const el = this.getElement();
if (el) {
el.blur();
el.classList.remove('blocklyFocused');
dom.removeClass(el, 'blocklyFocused');
}
}

View File

@@ -13,6 +13,7 @@ import * as goog from '../closure/goog/goog.js';
goog.declareModuleId('Blockly.MenuItem');
import * as aria from './utils/aria.js';
import * as dom from './utils/dom.js';
import * as idGenerator from './utils/idgenerator.js';
@@ -195,11 +196,11 @@ export class MenuItem {
const name = 'blocklyMenuItemHighlight';
const nameDep = 'goog-menuitem-highlight';
if (highlight) {
el.classList.add(name);
el.classList.add(nameDep);
dom.addClass(el, name);
dom.addClass(el, nameDep);
} else {
el.classList.remove(name);
el.classList.remove(nameDep);
dom.removeClass(el, name);
dom.removeClass(el, nameDep);
}
}
}

View File

@@ -238,13 +238,13 @@ export class Mutator extends Icon {
if (!this.getBlock().isInFlyout) {
if (this.getBlock().isEditable()) {
if (this.iconGroup_) {
this.iconGroup_.classList.remove('blocklyIconGroupReadonly');
dom.removeClass(this.iconGroup_, 'blocklyIconGroupReadonly');
}
} else {
// Close any mutator bubble. Icon is not clickable.
this.setVisible(false);
if (this.iconGroup_) {
this.iconGroup_.classList.add('blocklyIconGroupReadonly');
dom.addClass(this.iconGroup_, 'blocklyIconGroupReadonly');
}
}
}

View File

@@ -170,9 +170,9 @@ export class PathObject implements IPathObject {
return;
}
if (add) {
this.svgRoot.classList.add(className);
dom.addClass(this.svgRoot, className);
} else {
this.svgRoot.classList.remove(className);
dom.removeClass(this.svgRoot, className);
}
}

View File

@@ -15,6 +15,7 @@ goog.declareModuleId('Blockly.ThemeManager');
import type {Theme} from './theme.js';
import * as arrayUtils from './utils/array.js';
import * as dom from './utils/dom.js';
import type {Workspace} from './workspace.js';
import type {WorkspaceSvg} from './workspace_svg.js';
@@ -62,12 +63,12 @@ export class ThemeManager {
if (prevTheme) {
const oldClassName = prevTheme.getClassName();
if (oldClassName) {
injectionDiv.classList.remove(oldClassName);
dom.removeClass(injectionDiv, oldClassName);
}
}
const newClassName = this.theme.getClassName();
if (newClassName) {
injectionDiv.classList.add(newClassName);
dom.addClass(injectionDiv, newClassName);
}
}

View File

@@ -219,7 +219,7 @@ export class ToolboxCategory extends ToolboxItem implements
const container = document.createElement('div');
const className = this.cssConfig_['container'];
if (className) {
container.classList.add(className);
dom.addClass(container, className);
}
return container;
}
@@ -234,7 +234,7 @@ export class ToolboxCategory extends ToolboxItem implements
const rowDiv = document.createElement('div');
const className = this.cssConfig_['row'];
if (className) {
rowDiv.classList.add(className);
dom.addClass(rowDiv, className);
}
const nestedPadding =
`${ToolboxCategory.nestedPadding * this.getLevel()}px`;
@@ -253,7 +253,7 @@ export class ToolboxCategory extends ToolboxItem implements
const contentsContainer = document.createElement('div');
const className = this.cssConfig_['rowcontentcontainer'];
if (className) {
contentsContainer.classList.add(className);
dom.addClass(contentsContainer, className);
}
return contentsContainer;
}
@@ -268,7 +268,7 @@ export class ToolboxCategory extends ToolboxItem implements
if (!this.parentToolbox_.isHorizontal()) {
const className = this.cssConfig_['icon'];
if (className) {
toolboxIcon.classList.add(className);
dom.addClass(toolboxIcon, className);
}
}
@@ -289,7 +289,7 @@ export class ToolboxCategory extends ToolboxItem implements
toolboxLabel.textContent = name;
const className = this.cssConfig_['label'];
if (className) {
toolboxLabel.classList.add(className);
dom.addClass(toolboxLabel, className);
}
return toolboxLabel;
}
@@ -420,7 +420,7 @@ export class ToolboxCategory extends ToolboxItem implements
}
const className = this.cssConfig_['openicon'];
if (className) {
iconDiv.classList.add(className);
dom.addClass(iconDiv, className);
}
}
@@ -439,7 +439,7 @@ export class ToolboxCategory extends ToolboxItem implements
}
const className = this.cssConfig_['closedicon'];
if (className) {
iconDiv.classList.add(className);
dom.addClass(iconDiv, className);
}
}
@@ -527,12 +527,12 @@ export class ToolboxCategory extends ToolboxItem implements
this.parseColour_(ToolboxCategory.defaultBackgroundColour);
this.rowDiv_.style.backgroundColor = this.colour_ || defaultColour;
if (className) {
this.rowDiv_.classList.add(className);
dom.addClass(this.rowDiv_, className);
}
} else {
this.rowDiv_.style.backgroundColor = '';
if (className) {
this.rowDiv_.classList.remove(className);
dom.removeClass(this.rowDiv_, className);
}
}
aria.setState(this.htmlDiv_ as Element, aria.State.SELECTED, isSelected);

View File

@@ -17,6 +17,7 @@ import type {IToolbox} from '../interfaces/i_toolbox.js';
import type {IToolboxItem} from '../interfaces/i_toolbox_item.js';
import * as registry from '../registry.js';
import * as aria from '../utils/aria.js';
import * as dom from '../utils/dom.js';
import * as toolbox from '../utils/toolbox.js';
import {ToolboxCategory} from './category.js';
@@ -142,7 +143,7 @@ export class CollapsibleToolboxCategory extends ToolboxCategory implements
if (!this.parentToolbox_.isHorizontal()) {
const className = (this.cssConfig_ as AnyDuringMigration)['icon'];
if (className) {
toolboxIcon.classList.add(className);
dom.addClass(toolboxIcon, className);
}
toolboxIcon.style.visibility = 'visible';
}
@@ -162,7 +163,7 @@ export class CollapsibleToolboxCategory extends ToolboxCategory implements
const contentsContainer = document.createElement('div');
const className = (this.cssConfig_ as AnyDuringMigration)['contents'];
if (className) {
contentsContainer.classList.add(className);
dom.addClass(contentsContainer, className);
}
for (let i = 0; i < subcategories.length; i++) {

View File

@@ -61,7 +61,7 @@ export class ToolboxSeparator extends ToolboxItem {
const container = document.createElement('div');
const className = this.cssConfig_['container'];
if (className) {
container.classList.add(className);
dom.addClass(container, className);
}
this.htmlDiv_ = container;
return container;

View File

@@ -198,8 +198,8 @@ export class Toolbox extends DeleteArea implements IAutoHideable,
protected createContainer_(): HTMLDivElement {
const toolboxContainer = (document.createElement('div'));
toolboxContainer.setAttribute('layout', this.isHorizontal() ? 'h' : 'v');
toolboxContainer.classList.add('blocklyToolboxDiv');
toolboxContainer.classList.add('blocklyNonSelectable');
dom.addClass(toolboxContainer, 'blocklyToolboxDiv');
dom.addClass(toolboxContainer, 'blocklyNonSelectable');
toolboxContainer.setAttribute('dir', this.RTL ? 'RTL' : 'LTR');
return toolboxContainer;
}
@@ -211,7 +211,7 @@ export class Toolbox extends DeleteArea implements IAutoHideable,
*/
protected createContentsContainer_(): HTMLDivElement {
const contentsContainer = (document.createElement('div'));
contentsContainer.classList.add('blocklyToolboxContents');
dom.addClass(contentsContainer, 'blocklyToolboxContents');
if (this.isHorizontal()) {
contentsContainer.style.flexDirection = 'row';
}
@@ -453,8 +453,8 @@ export class Toolbox extends DeleteArea implements IAutoHideable,
* @internal
*/
addStyle(style: string) {
if (style) {
this.HtmlDiv?.classList.add(style);
if (style && this.HtmlDiv) {
dom.addClass(this.HtmlDiv, style);
}
}
@@ -465,8 +465,8 @@ export class Toolbox extends DeleteArea implements IAutoHideable,
* @internal
*/
removeStyle(style: string) {
if (style) {
this.HtmlDiv?.classList.remove(style);
if (style && this.HtmlDiv) {
dom.removeClass(this.HtmlDiv, style);
}
}

View File

@@ -85,46 +85,49 @@ export function createSvgElement<T extends SVGElement>(
/**
* Add a CSS class to a element.
*
* Handles multiple space-separated classes for legacy reasons.
*
* @param element DOM element to add class to.
* @param className Name of class to add.
* @returns True if class was added, false if already present.
* @alias Blockly.utils.dom.addClass
*/
export function addClass(element: Element, className: string): boolean {
if (element.classList.contains(className)) {
const classNames = className.split(' ');
if (classNames.every((name) => element.classList.contains(name))) {
return false;
}
element.classList.add(className);
element.classList.add(...classNames);
return true;
}
/**
* Removes multiple calsses from an element.
* Removes multiple classes from an element.
*
* @param element DOM element to remove classes from.
* @param classNames A string of one or multiple class names for an element.
* @alias Blockly.utils.dom.removeClasses
*/
export function removeClasses(element: Element, classNames: string) {
const classList = classNames.split(' ');
for (let i = 0; i < classList.length; i++) {
element.classList.remove(classList[i]);
}
element.classList.remove(...classNames.split(' '));
}
/**
* Remove a CSS class from a element.
*
* Handles multiple space-separated classes for legacy reasons.
*
* @param element DOM element to remove class from.
* @param className Name of class to remove.
* @returns True if class was removed, false if never present.
* @alias Blockly.utils.dom.removeClass
*/
export function removeClass(element: Element, className: string): boolean {
if (!element.classList.contains(className)) {
const classNames = className.split(' ');
if (classNames.every((name) => !element.classList.contains(name))) {
return false;
}
element.classList.remove(className);
element.classList.remove(...classNames);
return true;
}

View File

@@ -15,6 +15,7 @@ import * as goog from '../closure/goog/goog.js';
goog.declareModuleId('Blockly.WidgetDiv');
import * as common from './common.js';
import * as dom from './utils/dom.js';
import type {Rect} from './utils/rect.js';
import type {Size} from './utils/size.js';
import type {WorkspaceSvg} from './workspace_svg.js';
@@ -93,10 +94,10 @@ export function show(newOwner: unknown, rtl: boolean, newDispose: () => void) {
rendererClassName = mainWorkspace.getRenderer().getClassName();
themeClassName = mainWorkspace.getTheme().getClassName();
if (rendererClassName) {
div.classList.add(rendererClassName);
dom.addClass(div, rendererClassName);
}
if (themeClassName) {
div.classList.add(themeClassName);
dom.addClass(div, themeClassName);
}
}
@@ -121,11 +122,11 @@ export function hide() {
div.textContent = '';
if (rendererClassName) {
div.classList.remove(rendererClassName);
dom.removeClass(div, rendererClassName);
rendererClassName = '';
}
if (themeClassName) {
div.classList.remove(themeClassName);
dom.removeClass(div, themeClassName);
themeClassName = '';
}
(common.getMainWorkspace() as WorkspaceSvg).markFocused();

View File

@@ -263,7 +263,7 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements
* @internal
*/
addSelect() {
this.svgGroup_.classList.add('blocklySelected');
dom.addClass(this.svgGroup_, 'blocklySelected');
this.setFocus();
}
@@ -273,7 +273,7 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements
* @internal
*/
removeSelect() {
this.svgGroup_.classList.add('blocklySelected');
dom.addClass(this.svgGroup_, 'blocklySelected');
this.blurFocus();
}
@@ -283,7 +283,7 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements
* @internal
*/
addFocus() {
this.svgGroup_.classList.add('blocklyFocused');
dom.addClass(this.svgGroup_, 'blocklyFocused');
}
/**
@@ -292,7 +292,7 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements
* @internal
*/
removeFocus() {
this.svgGroup_.classList.remove('blocklyFocused');
dom.removeClass(this.svgGroup_, 'blocklyFocused');
}
/**
@@ -473,9 +473,9 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements
*/
updateMovable() {
if (this.isMovable()) {
this.svgGroup_.classList.add('blocklyDraggable');
dom.addClass(this.svgGroup_, 'blocklyDraggable');
} else {
this.svgGroup_.classList.remove('blocklyDraggable');
dom.removeClass(this.svgGroup_, 'blocklyDraggable');
}
}
@@ -514,9 +514,9 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements
const group = this.getSvgRoot();
(group as AnyDuringMigration).translate_ = '';
(group as AnyDuringMigration).skew_ = '';
this.svgGroup_.classList.add('blocklyDragging');
dom.addClass(this.svgGroup_, 'blocklyDragging');
} else {
this.svgGroup_.classList.remove('blocklyDragging');
dom.removeClass(this.svgGroup_, 'blocklyDragging');
}
}
@@ -561,9 +561,9 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements
*/
setDeleteStyle(enable: boolean) {
if (enable) {
this.svgGroup_.classList.add('blocklyDraggingDelete');
dom.addClass(this.svgGroup_, 'blocklyDraggingDelete');
} else {
this.svgGroup_.classList.remove('blocklyDraggingDelete');
dom.removeClass(this.svgGroup_, 'blocklyDraggingDelete');
}
}
@@ -853,7 +853,9 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements
*/
private deleteMouseDown_(e: Event) {
// Highlight the delete icon.
this.deleteIconBorder_?.classList.add('blocklyDeleteIconHighlighted');
if (this.deleteIconBorder_) {
dom.addClass(this.deleteIconBorder_, 'blocklyDeleteIconHighlighted');
}
// This event has been handled. No need to bubble up to the document.
e.stopPropagation();
}
@@ -865,7 +867,9 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements
*/
private deleteMouseOut_(_e: Event) {
// Restore highlight on the delete icon.
this.deleteIconBorder_?.classList.remove('blocklyDeleteIconHighlighted');
if (this.deleteIconBorder_) {
dom.removeClass(this.deleteIconBorder_, 'blocklyDeleteIconHighlighted');
}
}
/**
@@ -1016,8 +1020,13 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements
}
this.textarea_!.focus();
this.addFocus();
this.svgRectTarget_?.classList.add('blocklyCommentTargetFocused');
this.svgHandleTarget_?.classList.add('blocklyCommentHandleTargetFocused');
if (this.svgRectTarget_) {
dom.addClass(this.svgRectTarget_, 'blocklyCommentTargetFocused');
}
if (this.svgHandleTarget_) {
dom.addClass(
this.svgHandleTarget_, 'blocklyCommentHandleTargetFocused');
}
}, 0);
}
@@ -1036,9 +1045,13 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements
this.textarea_!.blur();
this.removeFocus();
this.svgRectTarget_?.classList.remove('blocklyCommentTargetFocused');
this.svgHandleTarget_?.classList.remove(
'blocklyCommentHandleTargetFocused');
if (this.svgRectTarget_) {
dom.removeClass(this.svgRectTarget_, 'blocklyCommentTargetFocused');
}
if (this.svgHandleTarget_) {
dom.removeClass(
this.svgHandleTarget_, 'blocklyCommentHandleTargetFocused');
}
}, 0);
}

View File

@@ -2080,8 +2080,8 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg {
* @internal
*/
beginCanvasTransition() {
this.svgBlockCanvas_.classList.add('blocklyCanvasTransitioning');
this.svgBubbleCanvas_.classList.add('blocklyCanvasTransitioning');
dom.addClass(this.svgBlockCanvas_, 'blocklyCanvasTransitioning');
dom.addClass(this.svgBubbleCanvas_, 'blocklyCanvasTransitioning');
}
/**
@@ -2090,8 +2090,8 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg {
* @internal
*/
endCanvasTransition() {
this.svgBlockCanvas_.classList.remove('blocklyCanvasTransitioning');
this.svgBubbleCanvas_.classList.remove('blocklyCanvasTransitioning');
dom.removeClass(this.svgBlockCanvas_, 'blocklyCanvasTransitioning');
dom.removeClass(this.svgBubbleCanvas_, 'blocklyCanvasTransitioning');
}
/** Center the workspace. */

View File

@@ -130,6 +130,26 @@ suite('Toolbox', function() {
this.toolbox.render(jsonDef);
chai.assert.lengthOf(this.toolbox.contents_, 1);
});
test('multiple icon classes can be applied', function() {
const jsonDef = {'contents': [
{
"kind": "category",
"cssConfig": {
"icon": "customIcon customIconEvents",
},
"contents": [
{
"kind": "block",
"blockxml": '<block xmlns="http://www.w3.org/1999/xhtml" type="basic_block"><field name="TEXT">FirstCategory-FirstBlock</field></block>',
},
],
},
]};
chai.assert.doesNotThrow(() => {
this.toolbox.render(jsonDef);
});
chai.assert.lengthOf(this.toolbox.contents_, 1);
});
});
suite('onClick_', function() {