aw-front-helpers 2.4.3 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Readme.md CHANGED
@@ -6,12 +6,13 @@ A library of functionalities for common tasks in Javascript / Sass.
6
6
  ## Table of contents
7
7
  ### Javascripts
8
8
  - **bootstraper** [See the documentation](https://gitlab.com/awstudio/front-helpers/tree/master/bootstraper/Readme.md)
9
- - maps | Allow the initialization of the Bootstraper Google Map
10
- - youtube | Allow the initialization of the Bootstraper Youtube Iframe
9
+ - Maps | Allow the initialization of the Bootstraper Google Map
10
+ - Youtube | Allow the initialization of the Bootstraper Youtube Iframe
11
11
  - **classes** [See the documentation](https://gitlab.com/awstudio/front-helpers/tree/master/classes/Readme.md)
12
- - formControl | A Javascript form validation class
13
- - globalParallax | A Parallax animation library
14
- - nearby | A librairy to animate element depending on the position of the mouse
12
+ - FormControl | A Javascript form validation class
13
+ - GParallax | A Parallax animation library
14
+ - Nearby | A librairy to animate element depending on the position of the mouse
15
+ - Sticky | A librairy to sticky an element on scroll
15
16
  - **utils** [See the documentation](https://gitlab.com/awstudio/front-helpers/tree/master/utils/Readme.md)
16
17
  - array
17
18
  - dom
@@ -2,14 +2,14 @@
2
2
 
3
3
  # Bootstraper
4
4
  ## maps
5
- - `import bootstraperMaps from 'aw-front-helpers/bootstraper/maps';` to import
6
- - `bootstraperMaps(googleKeyApi).then( initMap )` to initialize
7
- - you can specified libraries to load in second parameters `bootstraperMaps(googleKeyApi, [library, library]).then( initMap )` [Libraries](https://developers.google.com/maps/documentation/javascript/libraries)
5
+ - `import { BootstraperMaps } from 'aw-front-helpers'
6
+ - `bootstraperMaps.load('googleKeyApi', library[]).then( initMap )` to initialize
7
+ - you can specified libraries to load in second parameters [Libraries](https://developers.google.com/maps/documentation/javascript/libraries)
8
8
  - drawing
9
9
  - geometry
10
10
  - places
11
11
  - visualization
12
12
 
13
13
  ## youtube
14
- - `import bootstraperYT from 'aw-front-helpers/bootstraper/youtube';` to import
15
- - `bootstraperYT().then( initPlayer )` to initialize
14
+ - `import { BootstraperYoutube } from 'aw-front-helpers'
15
+ - `BootstraperYoutube.load().then( initPlayer )` to initialize
@@ -1,2 +1,4 @@
1
- module.exports.bootstraperMaps = require('./maps').default;
2
- module.exports.bootstraperYoutube = require('./youtube').default;
1
+ module.exports = {
2
+ bootstraperMaps: require('./maps').default,
3
+ bootstraperYoutube: require('./youtube').default
4
+ }
@@ -25,7 +25,7 @@ class bootstraperMaps {
25
25
  }
26
26
 
27
27
  _init() {
28
- let tag = document.createElement('script'),
28
+ const tag = document.createElement('script'),
29
29
  firstScriptTag = document.getElementsByTagName('script')[0],
30
30
  libs = this._libraries ? `&libraries=${this._libraries.join(',')}` : ``;
31
31
  tag.src = `https://maps.googleapis.com/maps/api/js?key=${this._googleAPIKey}${libs}&callback=onMapsReady`;
@@ -25,7 +25,7 @@ class bootstraperYoutube {
25
25
  }
26
26
 
27
27
  _init() {
28
- let tag = document.createElement('script'),
28
+ const tag = document.createElement('script'),
29
29
  firstScriptTag = document.getElementsByTagName('script')[0];
30
30
  tag.src = 'https://www.youtube.com/iframe_api';
31
31
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
package/classes/Readme.md CHANGED
@@ -4,22 +4,28 @@
4
4
  ## formControl
5
5
  Based on HTML5 basic options for inputs (required, type...).
6
6
 
7
- - `import FormControl from 'aw-front-helpers/classes/formControl';` to import
8
- - `class MyClass extends FormControl` to extend the formControl class to your class
9
- - You must define `this._parentElementClass`: Defines a wrapper with an input and an error message
7
+ - `import FormControl from 'aw-front-helpers';` to import
8
+ - `new FormControl(this._el, {options})`;
10
9
 
11
10
  ## globalParallax
12
- - `import GParallax from 'aw-front-helpers/classes/globalParallax';` to import
11
+ - `import GParallax from 'aw-front-helpers';` to import
13
12
  - `GParallax.start()` to instantiate
14
13
  - in your HTML element, you need define some atribute
15
14
  - `data-prllx-item` with option `data-speed` and `data-delta-start` (speed between 0 and 2): HTML element, moves vertically
16
15
  - `data-prllx-item-hz` with option `data-speed` and `data-delta-start` (speed between 0 and 2): HTML element, moves horizontally
17
16
  - `data-prllx-bg` with options `data-delta-start` and `data-delta-end`: defines a background-image to an element
18
17
 
19
- ## modelsManager
20
- - `import ModelsManager from 'aw-front-helpers/classes/modelsManager';` to import
21
- - `class MyModule extends ModelsManager` to extend
22
-
23
18
  ## nearby
24
- - `import nearby from 'aw-front-helpers/classes/nearby';` to import
19
+ - `import Nearby from 'aw-front-helpers';` to import
25
20
  - `new Nearby(this._el, {options})`;
21
+
22
+ ## sticky
23
+ - `import Sticky from 'aw-front-helpers';` to import
24
+ - `new Sticky({options})`;
25
+ - need to define `[data-attributes]`
26
+ - `[data-sticker-wrapper]` sticky wrapper of the element
27
+ - `[data-sticker-element]` element you want stick in the wrapper
28
+ - Options:
29
+ - `el`: specific for the querysSelector
30
+ - `breakpointDisabled` defined a disabled breakpoint
31
+ - `topHeightAdjustement` like to define an sticky overlap header
@@ -1,10 +1,6 @@
1
- import {
2
- gsap
3
- } from 'gsap/all';
1
+ import { gsap } from 'gsap/all';
4
2
  import ScrollToPlugin from 'gsap/ScrollToPlugin';
5
3
  gsap.registerPlugin(ScrollToPlugin);
6
- import create from 'dom-create-element';
7
- import getClosest from '../utils/dom/getClosest';
8
4
  import regex_email from '../utils/regex/email';
9
5
 
10
6
  const defaultOptions = {
@@ -103,27 +99,26 @@ export default class FormControl {
103
99
  }
104
100
 
105
101
  setError(element, message = null) {
106
- const parent = getClosest(element, this._options.selectorGroup);
107
- if (parent) {
108
- let error = parent.querySelector(`.${this._options.classErrorElement}`);
109
- if (!error) {
110
- error = create({
111
- selector: 'ul',
112
- styles: this._options.classErrorElement
113
- });
114
- parent.appendChild(error);
115
- }
116
- parent.classList.add(this._options.classIsError);
102
+ const parent = element.closest(this._options.selectorGroup);
103
+ if( parent === null ) return;
104
+ let error = parent.querySelector(`.${this._options.classErrorElement}`);
105
+ if (!error) {
106
+ error = Object.assign(
107
+ document.createElement('ul'), {
108
+ className: this._options.classErrorElement
109
+ });
110
+ parent.appendChild(error);
111
+ }
112
+ parent.classList.add(this._options.classIsError);
117
113
 
118
- const previousErrors = [...error.querySelectorAll('li')];
119
- for (let i = 0; i < previousErrors.length; i++) {
120
- if (previousErrors[i].innerHTML === message) return;
121
- }
122
- if (message) {
123
- const errorElement = document.createElement('li');
124
- errorElement.innerHTML = message;
125
- error.appendChild(errorElement);
126
- }
114
+ const previousErrors = [...error.querySelectorAll('li')];
115
+ for (let i = 0; i < previousErrors.length; i++) {
116
+ if (previousErrors[i].innerHTML === message) return;
117
+ }
118
+ if (message) {
119
+ const errorElement = document.createElement('li');
120
+ errorElement.innerHTML = message;
121
+ error.appendChild(errorElement);
127
122
  }
128
123
  }
129
124
 
@@ -160,7 +155,8 @@ export default class FormControl {
160
155
  /** @private */
161
156
  _removeError(el = null) {
162
157
  if (el) {
163
- const group = getClosest(el, this._options.selectorGroup);
158
+ const group = el.closest( this._options.selectorGroup );
159
+ if( group === null ) return;
164
160
  group.classList.remove(this._options.classIsError);
165
161
  const currentErrors = [...group.querySelectorAll(`.${this._options.classErrorElement}`)];
166
162
  currentErrors.forEach(error => {
@@ -181,7 +177,7 @@ export default class FormControl {
181
177
 
182
178
  /** @private */
183
179
  _checkError(el) {
184
- const group = getClosest(el, this._options.selectorGroup);
180
+ const group = el.closest(this._options.selectorGroup);
185
181
  if (group === null) return false;
186
182
  if (el.getAttribute('disabled') !== null) return false;
187
183
 
@@ -1,6 +1,5 @@
1
1
  import Symbol from 'es6-symbol';
2
2
  import EventEmitter from 'events';
3
- import raf from 'raf';
4
3
 
5
4
  // singleton
6
5
  let singleton = Symbol();
@@ -16,7 +15,6 @@ class GParallax extends EventEmitter {
16
15
  throw 'Global Parallax: Cannot construct singleton';
17
16
  }
18
17
  super();
19
- this._raf = null;
20
18
  }
21
19
 
22
20
  static getInstance() {
@@ -69,7 +67,7 @@ class GParallax extends EventEmitter {
69
67
 
70
68
  _onScroll() {
71
69
  this._vars.scrollY = window.pageYOffset;
72
- this._raf = raf(this._update);
70
+ window.requestAnimationFrame(this._update);
73
71
  }
74
72
 
75
73
  _update() {
package/classes/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  module.exports.GParallax = require('./globalParallax').default;
2
2
  module.exports.Nearby = require('./nearby').default;
3
3
  module.exports.FormControl = require('./formControl').default;
4
- module.exports.ModelsManager = require('./modelsManager').default;
4
+ module.exports.ModelsManager = require('./modelsManager').default;
5
+ module.exports.Sticky = require('./sticky').default;
package/classes/nearby.js CHANGED
@@ -29,7 +29,7 @@ const getMousePos = (e) => {
29
29
  return { x: posx, y: posy }
30
30
  };
31
31
 
32
- class Nearby {
32
+ export default class Nearby {
33
33
  constructor(el, options) {
34
34
  this.DOM = { el: el };
35
35
  this.options = options;
@@ -65,6 +65,4 @@ class Nearby {
65
65
 
66
66
  window.addEventListener('mousemove', this.mousemoveFn);
67
67
  }
68
- }
69
-
70
- export default Nearby;
68
+ }
@@ -0,0 +1,156 @@
1
+ import debounce from "debounce";
2
+ import EventEmitter from 'events';
3
+
4
+ export default class Sticky extends EventEmitter {
5
+ //________________________________________________________ constructor
6
+ // -
7
+ constructor(options = {}) {
8
+ super();
9
+ this._options = {
10
+ el: window.document,
11
+ breakpointDisabled: null,
12
+ topHeightAdjustement: 0,
13
+ ...options
14
+ };
15
+
16
+ this._isDisabled = false;
17
+ this._isSticky = false;
18
+ this._isEndSticky = false;
19
+ this._onResize = debounce(this._onResize, 200);
20
+
21
+ this._createBound();
22
+ this._grabDom();
23
+ this._addEvents();
24
+ this._onResize();
25
+ }
26
+
27
+ //________________________________________________________ public
28
+ // -
29
+ get options() {
30
+ return this._options;
31
+ }
32
+
33
+ set breakpointDisabled( breakpoint ) {
34
+ this._options.breakpointDisabled = breakpoint;
35
+ this.update();
36
+ }
37
+
38
+ set topHeightAdjustement( height ) {
39
+ this._options.topHeightAdjustement = height;
40
+ this.update();
41
+ }
42
+
43
+ update() {
44
+ this._onResize();
45
+ }
46
+
47
+ destroy() {
48
+ window.removeEventListener("scroll", this._onScrollHandler);
49
+ window.removeEventListener("resize", this._onResize);
50
+ this._dom.el.classList.remove("is-sticky", "is-sticky-end");
51
+ this._dom.el.style.top = null;
52
+ this._dom.el.style.width = null;
53
+ }
54
+
55
+ //________________________________________________________ events
56
+ // -
57
+ _onScrollHandler() {
58
+ if (this._isDisabled) return;
59
+ this._vars.scrollY = window.pageYOffset;
60
+ requestAnimationFrame(this._onScroll)
61
+ }
62
+
63
+ _onScroll() {
64
+ if (this._isDisabled) return;
65
+ const positionSticky = this._cache.containerTop - this._vars.scrollY - this._options.topHeightAdjustement;
66
+ const stickyFilter = positionSticky < 0;
67
+
68
+ const stickyBottomWrapperPage = this._vars.scrollY + this._vars.height > this._cache.wrapperTop + this._cache.wrapperHeight;
69
+ const stickyBottomElement = this._vars.scrollY + this._options.topHeightAdjustement + this._cache.containerHeight > this._cache.wrapperTop + this._cache.wrapperHeight;
70
+ const stickyEndFilter = stickyBottomWrapperPage && stickyBottomElement;
71
+ if (this._cache.wrapperHeight < this._cache.containerHeight) {
72
+ this._dom.el.classList.remove("is-sticky", "is-sticky-end");
73
+ return;
74
+ }
75
+
76
+ if (stickyFilter && !this._isSticky) {
77
+ this._isSticky = true;
78
+ this._dom.el.classList.add("is-sticky");
79
+ this._dom.el.style.top = `${this._options.topHeightAdjustement}px`;
80
+ this._dom.el.style.width = `${this._cache.containerWidth}px`;
81
+ } else if (!stickyFilter && this._isSticky) {
82
+ this._isSticky = false;
83
+ this._dom.el.style.top = null;
84
+ this._dom.el.style.width = null;
85
+ this._dom.el.classList.remove("is-sticky");
86
+ }
87
+ if (stickyEndFilter && !this._isEndSticky) {
88
+ this._isEndSticky = true;
89
+ this._dom.el.style.top = null;
90
+ this._dom.el.style.width = null;
91
+ this._dom.el.classList.add("is-sticky-end");
92
+ } else if (!stickyEndFilter && this._isEndSticky) {
93
+ this._isEndSticky = false;
94
+ this._dom.el.style.top = `${this._options.topHeightAdjustement}px`;
95
+ this._dom.el.style.width = `${this._cache.containerWidth}px`;
96
+ this._dom.el.classList.remove("is-sticky-end");
97
+ }
98
+ }
99
+
100
+ _onResize() {
101
+ if (this._options.breakpointDisabled && window.innerWidth < this._options.breakpointDisabled) {
102
+ if (!this._isDisabled) {
103
+ this._isDisabled = true;
104
+ this._dom.el.classList.remove("is-sticky", "is-sticky-end");
105
+ this._dom.el.style.top = null;
106
+ this._dom.el.style.width = null;
107
+ this.emit('disable');
108
+ }
109
+ return;
110
+ }
111
+ if (this._isDisabled) {
112
+ this._isDisabled = false;
113
+ this.emit('enable');
114
+ }
115
+
116
+ this._isSticky = false;
117
+ this._isEndSticky = false;
118
+ this._dom.el.classList.remove("is-sticky", "is-sticky-end");
119
+ this._dom.el.style.width = null;
120
+ setTimeout(() => {
121
+ const boudingWrapper = this._dom.wrapper.getBoundingClientRect();
122
+ const boudingContainer = this._dom.el.getBoundingClientRect();
123
+ this._vars = {
124
+ scrollY: window.pageYOffset || document.documentElement.scrollTop,
125
+ height: window.innerHeight || document.documentElement.clientHeight,
126
+ };
127
+ this._cache = {
128
+ windowHeight: window.innerHeight || document.documentElement.clientHeight || document.getElementsByTagName("body")[0],
129
+ containerTop: boudingContainer.top + this._vars.scrollY,
130
+ containerHeight: boudingContainer.height,
131
+ containerWidth: boudingContainer.width,
132
+ wrapperTop: boudingWrapper.top + this._vars.scrollY,
133
+ wrapperHeight: boudingWrapper.height,
134
+ };
135
+ this._onScrollHandler();
136
+ });
137
+ }
138
+ //________________________________________________________ private
139
+ // -
140
+ _createBound() {
141
+ ["_onScroll", "_onScrollHandler", "_onResize"].forEach((fn) => (this[fn] = this[fn].bind(this)));
142
+ }
143
+
144
+ _grabDom() {
145
+ this._dom = {};
146
+ this._dom.el = this._options.el.querySelector("[data-sticker-element]");
147
+ this._dom.wrapper = this._options.el.querySelector("[data-sticker-wrapper]");
148
+ }
149
+
150
+ _addEvents() {
151
+ setTimeout(() => {
152
+ window.addEventListener("scroll", this._onScrollHandler);
153
+ window.addEventListener("resize", this._onResize);
154
+ });
155
+ }
156
+ }
package/index.js CHANGED
@@ -1,7 +1,7 @@
1
- module.exports.GParallax = require('./classes/globalParallax').default;
2
- module.exports.Nearby = require('./classes/nearby').default;
3
- module.exports.FormControl = require('./classes/formControl').default;
4
- module.exports.ModelsManager = require('./classes/modelsManager').default;
5
- module.exports.utils = require('./utils');
6
- module.exports.bootstraperMaps = require('./bootstraper/maps').default;
7
- module.exports.bootstraperYoutube = require('./bootstraper/youtube').default;
1
+ export const GParallax = require('./classes/globalParallax').default;
2
+ export const Nearby = require('./classes/nearby').default;
3
+ export const FormControl = require('./classes/formControl').default;
4
+ export const Sticky = require('./classes/sticky').default;
5
+ export const BootstraperMaps = require('./bootstraper/maps').default;
6
+ export const BootstraperYoutube = require('./bootstraper/youtube').default;
7
+ export const utils = require('./utils');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aw-front-helpers",
3
- "version": "2.4.3",
3
+ "version": "2.5.1",
4
4
  "description": "Assets helpers for projects",
5
5
  "author": "Yoann Le Poupon",
6
6
  "license": "ISC",
@@ -10,10 +10,8 @@
10
10
  "url": "git@gitlab.com:awstudio/front-helpers.git"
11
11
  },
12
12
  "dependencies": {
13
- "dom-create-element": "^1.0.2",
14
13
  "es6-symbol": "^3.1.3",
15
14
  "exif-js": "^2.3.0",
16
- "gsap": "^3.5.1",
17
- "raf": "^3.4.1"
15
+ "gsap": "^3.10.4"
18
16
  }
19
17
  }
@@ -2,7 +2,8 @@
2
2
  $breakpoint-phablet: 480px !default;
3
3
  $breakpoint-tablet: 768px !default;
4
4
  $breakpoint-desktop: 1024px !default;
5
- $breakpoint-desktop-xl: 1440px !default;
5
+ $breakpoint-desktop-xl: 1280px !default;
6
+ $breakpoint-desktop-xxl: 1440px !default;
6
7
  $breakpoint-burger: 1100px !default;
7
8
 
8
9
  // ------------------------------------------------------------
@@ -19,6 +20,7 @@ $tablet-max : '#{$media-query} (max-width: #{$breakpoint-desktop - 1})';
19
20
  $tablet-only: '#{$media-query} (min-width: #{$breakpoint-tablet}) and (max-width: #{$breakpoint-desktop - 1})';
20
21
  $desktop: '#{$media-query} (min-width: #{$breakpoint-desktop})';
21
22
  $desktop-xl: '#{$media-query} (min-width: #{$breakpoint-desktop-xl})';
23
+ $desktop-xxl: '#{$media-query} (min-width: #{$breakpoint-desktop-xxl})';
22
24
  $burger-enable: '#{$media-query} (max-width: #{$breakpoint-burger - 1})';
23
25
  $burger-disable: '#{$media-query} (min-width: #{$breakpoint-burger})';
24
26
 
@@ -30,5 +32,6 @@ $burger-disable: '#{$media-query} (min-width: #{$breakpoint-burger})';
30
32
  @mixin tablet-only { @media #{$tablet-only} { @content; } }
31
33
  @mixin desktop { @media #{$desktop} { @content; } }
32
34
  @mixin desktop-xl { @media #{$desktop-xl} { @content; } }
35
+ @mixin desktop-xxl { @media #{$desktop-xxl} { @content; } }
33
36
  @mixin burger-enable { @media #{$burger-enable} { @content; } }
34
37
  @mixin burger-disable { @media #{$burger-disable} { @content; } }
@@ -4,7 +4,7 @@ $color-main: #000 !default;
4
4
 
5
5
  $wrapper-max: 1500px !default;
6
6
  $wrapper-width-sm: 95% !default;
7
- $wrapper-width-md: 90% !default;
7
+ $wrapper-width-md: 95% !default;
8
8
  $wrapper-width-lg: 90% !default;
9
9
 
10
10
  $vertical-spacing-mobile: 50px !default;
@@ -22,11 +22,9 @@ $vertical-spacing-desktop: 80px !default;
22
22
  margin-right: auto;
23
23
  width: $wrapper-width-sm;
24
24
  max-width: $wrapper-max;
25
-
26
25
  @include desktop {
27
26
  width: $wrapper-width-md;
28
27
  }
29
-
30
28
  @include desktop-xl {
31
29
  width: $wrapper-width-lg;
32
30
  }
@@ -128,19 +126,12 @@ $vertical-spacing-desktop: 80px !default;
128
126
  -webkit-font-smoothing: inherit;
129
127
  -moz-osx-font-smoothing: inherit;
130
128
  -webkit-appearance: none;
131
-
132
129
  &:not(input) {
133
130
  user-select: none;
134
131
  }
135
-
136
132
  &:hover {
137
133
  text-decoration: none;
138
134
  }
139
-
140
- &::-moz-focus-inner {
141
- border: 0;
142
- padding: 0;
143
- }
144
135
  }
145
136
 
146
137
  // -------------------------
@@ -213,8 +204,8 @@ $vertical-spacing-desktop: 80px !default;
213
204
  object-fit: cover;
214
205
  }
215
206
 
216
- @mixin loader($color: $color-main, $scale: 1) {
217
- &::after {
207
+ @mixin loader($color: $color-main, $scale: 1, $position: after) {
208
+ &::#{$position} {
218
209
  content: '';
219
210
  position: absolute;
220
211
  left: 50%;
@@ -234,7 +225,6 @@ $vertical-spacing-desktop: 80px !default;
234
225
  0% {
235
226
  transform: translateX(-50%) translateY(-50%) rotate(0deg);
236
227
  }
237
-
238
228
  100% {
239
229
  transform: translateX(-50%) translateY(-50%) rotate(360deg);
240
230
  }
@@ -0,0 +1,15 @@
1
+ [data-sticker-wrapper] {
2
+ position: relative;
3
+ }
4
+ [data-sticker-element] {
5
+ &.is-sticky {
6
+ position: fixed;
7
+ z-index: 3;
8
+ }
9
+
10
+ &.is-sticky-end {
11
+ position: absolute;
12
+ bottom: 0;
13
+ top: auto;
14
+ }
15
+ }
@@ -42,6 +42,7 @@ $breakpoint-phablet: 480px !default;
42
42
  $breakpoint-tablet: 768px !default;
43
43
  $breakpoint-desktop: 1024px !default;
44
44
  $breakpoint-desktop-xl: 1280px !default;
45
+ $breakpoint-desktop-xxl: 1440px !default;
45
46
 
46
47
  $wrapper-max: 1440px !default;
47
48
 
package/utils/Readme.md CHANGED
@@ -1,7 +1,4 @@
1
1
  ![Logo](https://www.awstudio.fr/files/logo_5bf827234607f.png)
2
2
 
3
3
  # Utils
4
- `import utils from 'aw-front-helpers/utils';` to import
5
-
6
- ## dom
7
- - `utils.dom.getClosest(element, selector)` to get a parent element
4
+ `import utils from 'aw-front-helpers/utils';` to import
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * Get the closest matching element up the DOM tree.
3
+ * @deprecated since version 2.5.0
3
4
  * @private
4
5
  * @param {Element} elem Starting element
5
6
  * @param {String} selector Selector to match against