diff --git a/src/index.ts b/src/index.ts index 1ff2245..2bf9718 100755 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import { decode } from 'he'; +import { decode, encode } from 'he'; export enum NodeType { ELEMENT_NODE = 1, @@ -503,6 +503,44 @@ export class HTMLElement extends Node { this._rawAttrs = attrs; return attrs; } + + /** + * Set an attribute value to the HTMLElement + * @param {string} key The attribute name + * @param {string} value The value to set, or null / undefined to remove an attribute + */ + setAttribute(key: string, value: string) { + //Update the attributes map + const attrs = this.attributes; + if(value===undefined || value===null) delete attrs[key]; + else attrs[key] = value+''; + //Update the raw attributes + if(this._rawAttrs) { + if(value===undefined || value===null) delete this._rawAttrs[key]; + else this._rawAttrs[key] = encode(value+''); + } + //Update rawString + this.rawAttrs = Object.keys(attrs).map(attr => attr+'='+encode(attrs[attr])).join(' '); + } + + /** + * Replace all the attributes of the HTMLElement by the provided attributes + * @param {Attributes} attributes the new attribute set + */ + setAttributes(attributes: Attributes) { + //Update the attributes map + if(this.attributes) { + Object.keys(this.attributes).forEach(key => delete this.attributes[key]); + Object.keys(attributes).forEach(key => this.attributes[key] = attributes[key]+''); + } + //Update the raw attributes map + if(this.rawAttributes) { + Object.keys(this.rawAttributes).forEach(key => delete this.rawAttributes[key]); + Object.keys(attributes).forEach(key => this.rawAttributes[key] = encode(attributes[key]+'')); + } + //Update rawString + this.rawAttrs = Object.keys(attributes).map(attr => attr+'='+encode(attributes[attr]+'')).join(' '); + } } interface MatherFunction { func: any; tagName: string; classes: string | string[]; attr_key: any; value: any; } diff --git a/test/html.js b/test/html.js index d50e7b9..519fa2f 100644 --- a/test/html.js +++ b/test/html.js @@ -316,6 +316,46 @@ describe('HTML Parser', function () { }); }); + describe('#setAttribute', function () { + it('should edit the attributes of the element', function () { + var root = parseHTML('
'); + root.firstChild.setAttribute('a', 13); + root.firstChild.attributes.should.eql({ + 'a': '13', + }); + root.firstChild.toString().should.eql(''); + }); + it('should add an attribute to the element', function () { + var root = parseHTML(''); + root.firstChild.setAttribute('b', 13); + root.firstChild.attributes.should.eql({ + 'a': '12', + 'b': '13', + }); + root.firstChild.toString().should.eql(''); + }); + it('should remove an attribute from the element', function () { + var root = parseHTML(''); + root.firstChild.setAttribute('b', null); + root.firstChild.setAttribute('c'); + root.firstChild.attributes.should.eql({ + 'a': '12', + }); + root.firstChild.toString().should.eql(''); + }); + }); + + describe('#setAttributes', function () { + it('should return attributes of the element', function () { + var root = parseHTML(''); + root.firstChild.setAttributes({c: 12}); + root.firstChild.attributes.should.eql({ + 'c': '12', + }); + root.firstChild.toString().should.eql(''); + }); + }); + describe('#querySelector()', function () { it('should return correct elements in DOM tree', function () { var root = parseHTML('