Skip to content

Commit

Permalink
refactor: use addValueToAttribute and removeValueFromAttribute utils
Browse files Browse the repository at this point in the history
  • Loading branch information
vursen committed Nov 23, 2021
1 parent 7e4cd04 commit ea59696
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 15 deletions.
9 changes: 9 additions & 0 deletions packages/field-base/src/utils.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Adds a value to an attribute containing space-delimited values.
*/
export declare function addValueToAttribute(element: HTMLElement, attr: string, value: string): void;

/**
* Removes a value from an attribute containing space-delimited values.
*/
export declare function removeValueFromAttribute(element: HTMLElement, attr: string, value: string): void;
49 changes: 49 additions & 0 deletions packages/field-base/src/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* @param {string} value
* @return {Set<string>}
*/
function deserializeAttributeValue(value) {
if (!value) {
return new Set();
}

return new Set(value.split(' '));
}

/**
* @param {Set<string>} values
* @return {string}
*/
function serializeAttributeValue(values) {
return [...values].join(' ');
}

/**
* Adds a value to an attribute containing space-delimited values.
*
* @param {HTMLElement} element
* @param {string} attr
* @param {string} value
*/
export function addValueToAttribute(element, attr, value) {
const values = deserializeAttributeValue(element.getAttribute(attr));
values.add(value);
element.setAttribute(attr, serializeAttributeValue(values));
}

/**
* Removes a value from an attribute containing space-delimited values.
*
* @param {HTMLElement} element
* @param {string} attr
* @param {string} value
*/
export function removeValueFromAttribute(element, attr, value) {
const values = deserializeAttributeValue(element.getAttribute(attr));
values.delete(value);
if (values.size === 0) {
element.removeAttribute(attr);
return;
}
element.setAttribute(attr, serializeAttributeValue(values));
}
43 changes: 43 additions & 0 deletions packages/field-base/test/utils.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { expect } from '@esm-bundle/chai';
import { addValueToAttribute, removeValueFromAttribute } from '../src/utils.js';

describe('utils', () => {
describe('addValueToAttribute', () => {
let element;

beforeEach(() => {
element = document.createElement('div');
});

it('should add a value to an attribute', () => {
addValueToAttribute(element, 'aria-labelledby', 'label-id');
expect(element.getAttribute('aria-labelledby')).to.equal('label-id');

addValueToAttribute(element, 'aria-labelledby', 'error-id');
expect(element.getAttribute('aria-labelledby')).to.equal('label-id error-id');
});

it('should not duplicate values in the attribute', () => {
addValueToAttribute(element, 'aria-labelledby', 'label-id');
addValueToAttribute(element, 'aria-labelledby', 'label-id');
expect(element.getAttribute('aria-labelledby')).to.equal('label-id');
});
});

describe('removeValueFromAttribute', () => {
let element;

beforeEach(() => {
element = document.createElement('div');
element.setAttribute('aria-labelledby', 'label-id error-id');
});

it('should remove a value from an attribute', () => {
removeValueFromAttribute(element, 'aria-labelledby', 'error-id');
expect(element.getAttribute('aria-labelledby')).to.equal('label-id');

removeValueFromAttribute(element, 'aria-labelledby', 'label-id');
expect(element.hasAttribute('aria-labelledby')).to.be.false;
});
});
});
18 changes: 3 additions & 15 deletions packages/form-layout/src/vaadin-form-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
import { FlattenedNodesObserver } from '@polymer/polymer/lib/utils/flattened-nodes-observer.js';
import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
import { addValueToAttribute, removeValueFromAttribute } from '@vaadin/field-base/src/utils.js';
import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';

/**
Expand Down Expand Up @@ -226,11 +227,7 @@ class FormItem extends ThemableMixin(PolymerElement) {
*/
__linkLabelToField(field) {
const ariaTarget = field.ariaTarget || field;

// TODO: Consider creating a helper like `addValueToAttribute`.
let ariaIds = new Set((ariaTarget.getAttribute('aria-labelledby') || '').split(' '));
ariaIds.add(this.__labelId);
ariaTarget.setAttribute('aria-labelledby', [...ariaIds].filter(Boolean).join(' '));
addValueToAttribute(ariaTarget, 'aria-labelledby', this.__labelId);
}

/**
Expand All @@ -242,16 +239,7 @@ class FormItem extends ThemableMixin(PolymerElement) {
*/
__unlinkLabelFromField(field) {
const ariaTarget = field.ariaTarget || field;

// TODO: Consider creating a helper like `removeValueFromAttribute`.
let ariaIds = new Set((ariaTarget.getAttribute('aria-labelledby') || '').split(' '));
ariaIds.delete('');
ariaIds.delete(this.__labelId);
if (ariaIds.size > 0) {
ariaTarget.setAttribute('aria-labelledby', [...ariaIds].filter(Boolean).join(' '));
} else {
ariaTarget.removeAttribute('aria-labelledby');
}
removeValueFromAttribute(ariaTarget, 'aria-labelledby', this.__labelId);
}

/** @private */
Expand Down

0 comments on commit ea59696

Please sign in to comment.