export class ElementSet { private s : string | object ; constructor ( s ) { if ( typeof s !== 'string' && typeof s !== 'object' ) { throw new Error ( 'Invalid selector (string | object), got: ' + s ) ; } this . s = s ; } private q ( ) { if ( typeof this . s === 'string' ) { return document . querySelectorAll ( this . s ) ; } return [ this . s ] as HTMLElement [ ] ; } each ( fn ) { const v = this . q ( ) ; if ( v . length > 0 ) { if ( v . length === 1 ) { fn ( v [ 0 ] ) ; } else { for ( let i = 0 ; i < v . length ; i ++ ) { fn ( v [ i ] ) ; } } } return this ; } get first ( ) { return this . q ( ) [ 0 ] ; } get length ( ) { return this . q ( ) . length ; } param { string } a param { string } v returns { any } attr ( a , v ? ) { if ( ! v ) { const n = this . q ( ) [ 0 ] ; return n && n . getAttribute ( a ) ; } return this . each ( i => { i . setAttribute ( a , v ) ; } ) ; } param { string } v returns { this } removeAttr ( v ) { return this . each ( i => { i . removeAttribute ( v ) ; } ) ; } param { string } s returns { any } is ( s ) { const n = this . q ( ) [ 0 ] ; if ( n ) { return n . matches ( s ) ; } return false ; } param { string } type param { EventListenerOrEventListenerObject } fn returns { this } on ( type , fn ) { return this . each ( i => { i . addEventListener ( type , fn , false ) ; } ) ; } param { string } v returns { this } addClass ( v ) { return this . each ( i => { i . classList . add ( v ) ; } ) ; } param { string } v returns { this } removeClass ( v ) { return this . each ( i => { i . classList . remove ( v ) ; } ) ; } param { string } v returns { this | string } html ( v ? ) { if ( ! v ) { const n = this . q ( ) [ 0 ] ; return n && n . innerHTML ; } return this . each ( i => { i . innerHTML = v ; } ) ; } param { string } v returns { this | string } text ( v ? ) { if ( ! v ) { const n = this . q ( ) [ 0 ] ; return n && n . textContent ; } return this . each ( i => { i . textContent = v ; } ) ; } param { InsertPosition } location param { string | HTMLElement | ElementSet } v returns { ElementSet } private insertAdjacent ( location , v ) { if ( v instanceof ElementSet ) { return this . insertAdjacent ( location , v . first ) ; } if ( v instanceof HTMLElement ) { return this . each ( i => { i . insertAdjacentElement ( location , v ) ; } ) ; } return this . each ( i => { i . insertAdjacentHTML ( location , v ) ; } ) ; } param { string | HTMLElement | ElementSet } v returns { this } insertBefore ( v ) { return this . insertAdjacent ( 'beforebegin' , v ) ; } param { string | HTMLElement | ElementSet } v returns { this } insertAfter ( v ) { return this . insertAdjacent ( 'afterend' , v ) ; } returns { this } remove ( ) { return this . each ( i => { i . remove ( ) ; } ) ; } param { number } v returns { any } width ( v ? ) { if ( ! v ) { const n = this . q ( ) [ 0 ] ; return n && n . clientWidth ; } return this . each ( i => { i . style . width = v + 'px' ; } ) ; } param { number } v returns { any } height ( v ? ) { if ( ! v ) { const n = this . q ( ) [ 0 ] ; return n && n . clientHeight ; } return this . each ( i => { i . style . height = v + 'px' ; } ) ; } } param { string | object } selector returns { ElementSet } export function $ ( selector ) { return new ElementSet ( selector ) ; } /**
 * Polyfill IE 9-11
 */ if ( ! Element . prototype . matches ) { Element . prototype . matches = ( Element . prototype as any ) . msMatchesSelector ; }