Compare commits

...

21 Commits

Author SHA1 Message Date
Andros Fenollosa
79735380e7
Merge pull request #5 from tanrax/dependabot/npm_and_yarn/path-parse-1.0.7
Bump path-parse from 1.0.6 to 1.0.7
2022-02-25 19:34:50 +01:00
Andros Fenollosa
32e756ee6e
Merge pull request #4 from tanrax/dependabot/npm_and_yarn/hosted-git-info-2.8.9
Bump hosted-git-info from 2.8.8 to 2.8.9
2022-02-25 19:34:38 +01:00
Andros Fenollosa
86897b193a
Merge pull request #3 from tanrax/dependabot/npm_and_yarn/y18n-3.2.2
Bump y18n from 3.2.1 to 3.2.2
2022-02-25 19:34:28 +01:00
dependabot[bot]
26f5397544
Bump path-parse from 1.0.6 to 1.0.7
Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7.
- [Release notes](https://github.com/jbgutierrez/path-parse/releases)
- [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7)

---
updated-dependencies:
- dependency-name: path-parse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-08-12 16:35:33 +00:00
dependabot[bot]
f22109f427
Bump hosted-git-info from 2.8.8 to 2.8.9
Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.8.8 to 2.8.9.
- [Release notes](https://github.com/npm/hosted-git-info/releases)
- [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md)
- [Commits](https://github.com/npm/hosted-git-info/compare/v2.8.8...v2.8.9)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-11 20:30:06 +00:00
dependabot[bot]
f3f5f8893c
Bump y18n from 3.2.1 to 3.2.2
Bumps [y18n](https://github.com/yargs/y18n) from 3.2.1 to 3.2.2.
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot[bot] <support@github.com>
2021-03-31 12:38:25 +00:00
Andros Fenollosa
406d9a7ef6
Update FUNDING.yml 2021-02-15 11:54:01 +01:00
Andros Fenollosa
e57d19fb84 Update CDNs 2020-12-22 11:08:54 +01:00
Andros Fenollosa
136dc60db0 Add is-scroll-up. Update test. Update version 1.5.0 2020-12-22 11:00:48 +01:00
Andros Fenollosa
2b9eedbdd0
Merge pull request #2 from tanrax/dependabot/npm_and_yarn/ini-1.3.8
Bump ini from 1.3.5 to 1.3.8
2020-12-14 13:34:41 +01:00
dependabot[bot]
2b66cd672b
Bump ini from 1.3.5 to 1.3.8
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-12 23:59:25 +00:00
Andros Fenollosa
fbe4aabdf9
Create FUNDING.yml 2020-11-03 22:48:42 +01:00
Andros Fenollosa
d90d907629
Update README.md 2020-11-03 10:18:55 +01:00
Andros Fenollosa
5d1a61e714
Update README.md 2020-08-03 17:20:33 +02:00
Andros Fenollosa
e3e100c437 Update version 1.4.0 2020-08-03 17:03:02 +02:00
Andros Fenollosa
b9bb0d694b Optimize visible with observables 2020-08-03 17:02:50 +02:00
Andros Fenollosa
e02334b46e Order code 2020-08-03 16:43:12 +02:00
Andros Fenollosa
a6efdf85d4
Update README.md 2020-07-23 09:04:22 +02:00
Andros Fenollosa
b306334ca5
Update README.md 2020-07-22 20:27:42 +02:00
Andros Fenollosa
e8cbe46659
Remove old code 2020-07-22 20:27:10 +02:00
Andros Fenollosa
ea2e148395
Update README.md 2020-07-22 20:09:56 +02:00
14 changed files with 464 additions and 293 deletions

2
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,2 @@
github: tanrax
ko_fi: androsfenollosa

View File

@ -12,7 +12,7 @@
<article class="open"></article> <article class="open"></article>
``` ```
Simple utility to **avoid writing Javascript** when working with **classes**. It only takes up **3.2Kb**! Simple utility to **avoid writing Javascript** when working with **classes**. It only takes up **3.8Kb**!
- Simplifies the **click**. - Simplifies the **click**.
@ -40,7 +40,7 @@ Simple utility to **avoid writing Javascript** when working with **classes**. It
Add to your `<head>` the following tag. Add to your `<head>` the following tag.
```html ```html
<script src="https://cdn.jsdelivr.net/gh/tanrax/FFNM@v1.3.0/dist/ffnm.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/tanrax/FFNM@1.5.0/dist/ffnm.min.js" integrity="sha384-qlI8XJcMcJMh52x4w9HA9ItB8KmW6pKaJXijVQFl6UvT1nGCH+U6Y7sbbc11HkCH" crossorigin="anonymous"></script>
``` ```
### Examples ### Examples
@ -114,6 +114,21 @@ Add to your `<head>` the following tag.
<nav is-scroll-down="class:remove('show')"></nav> <nav is-scroll-down="class:remove('show')"></nav>
``` ```
#### Scroll top
##### Add the class `show` to `nav` when the scroll is top of the page.
```html
<nav is-scroll-top="class:add('show')"></nav>
```
##### Remove the `show` class from `nav` when the scroll top of the page.
```html
<nav is-scroll-top="class:remove('show')"></nav>
```
#### Hover #### Hover
##### Add the class `show` to `div` when hover. ##### Add the class `show` to `div` when hover.
@ -138,7 +153,7 @@ Add to your `<head>` the following tag.
```html ```html
<div is-hover="class:toggle('show', '#button')"></div> <div is-hover="class:toggle('show', '#button')"></div>
<button id="button">Hi</div> <button id="button">Hi</button>
``` ```
#### Visible #### Visible
@ -165,7 +180,7 @@ Add to your `<head>` the following tag.
```html ```html
<div is-visible="class:toggle('show', '#button')"></div> <div is-visible="class:toggle('show', '#button')"></div>
<button id="button">Hi</div> <button id="button">Hi</button>
``` ```
#### Not visible #### Not visible
@ -195,8 +210,6 @@ Add to your `<head>` the following tag.
<input id="name"> <input id="name">
``` ```
--- ---
## Spanish/Español ## Spanish/Español
@ -206,7 +219,7 @@ Add to your `<head>` the following tag.
Añade a tu `<head>` la siguiente etiqueta. Añade a tu `<head>` la siguiente etiqueta.
```html ```html
<script src="https://cdn.jsdelivr.net/gh/tanrax/FFNM@v1.3.0/dist/ffnm.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/tanrax/FFNM@1.5.0/dist/ffnm.min.js" integrity="sha384-qlI8XJcMcJMh52x4w9HA9ItB8KmW6pKaJXijVQFl6UvT1nGCH+U6Y7sbbc11HkCH" crossorigin="anonymous"></script>
``` ```
### Ejemplos de uso ### Ejemplos de uso
@ -280,6 +293,20 @@ Añade a tu `<head>` la siguiente etiqueta.
<nav is-scroll-down="class:remove('show')"></nav> <nav is-scroll-down="class:remove('show')"></nav>
``` ```
#### Scroll esta arriba de la pagina (principio)
##### Añadir la clase `show` al selector `nav` cuando el scroll esta al inicio.
```html
<nav is-scroll-top="class:add('show')"></nav>
```
##### Quitar la clase `show` al selector `nav` cuando el scroll esta al inicio.
```html
<nav is-scroll-top="class:remove('show')"></nav>
```
#### Hover #### Hover
##### Añade la clase `show` al `div` cuando sea hover. ##### Añade la clase `show` al `div` cuando sea hover.
@ -304,9 +331,64 @@ Añade a tu `<head>` la siguiente etiqueta.
```html ```html
<div is-hover="class:toggle('show', '#button')"></div> <div is-hover="class:toggle('show', '#button')"></div>
<button id="button">Hi</div> <button id="button">Hi</button>
``` ```
#### Visible
##### Añade la clase `ver` en el `div` cuando es visible.
```html
<div is-visible="class:add('ver')"></div>
```
##### Quita la clase `ver` en el `div` cuando es visible.
```html
<div is-visible="class:remove('ver')"></div>
```
##### Intercambia la clase `ver` cuando el `div` es visible.
```html
<div is-visible="class:toggle('ver')"></div>
```
##### Añade la clase `ver` en `#boton` cuando el `div` es visible.
```html
<div is-visible="class:toggle('ver', '#boton')"></div>
<button id="boton">Hi</button>
```
#### No visible
##### Añade la clase `ver` en el `div` cuando no es visible.
```html
<div is-not-visible="class:add('ver')"></div>
```
##### Quita la clase `ver` en el `div` cuando no es visible.
```html
<div is-not-visible="class:remove('ver')"></div>
```
##### Intercambia la clase `ver` cuando el `div` no es visible.
```html
<div is-not-visible="class:toggle('ver')"></div>
```
##### Añade la clase `ver` en `#boton` cuando el `div` no es visible.
```html
<div is-not-visible="class:toggle('ver', '#boton')"></div>
<button id="boton">Hi</button>
```
--- ---
## Development ## Development

2
dist/ffnm.min.js vendored
View File

@ -1,2 +1,2 @@
document.addEventListener("DOMContentLoaded",()=>{const e={class:["add","remove","toggle"]};let t=[],s=void 0;function i(e,t){let s=e.getAttribute(t),i=RegExp("^(\\w+):").exec(s)[1],c=RegExp(":(\\w+)\\(").exec(s)[1],a=RegExp("\\('(\\w[_-\\w0-9]+)',?").exec(s)[1],o=RegExp(", ?'([.#i\\w][_-\\w0-9]+)'\\)");return{functionParent:i,functionChild:c,value:a,target:null!==o.exec(s)?o.exec(s)[1]:void 0}}function c(e){return[...t].filter(t=>t.hasAttribute(e))}function a(e){let t=e.getBoundingClientRect();return t.top>=0&&t.left>=0&&t.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&t.right<=(window.innerWidth||document.documentElement.clientWidth)}t=[],["is-click","is-scroll-up","is-scroll-down","is-hover","is-view","is-visible","is-not-visible"].map(s=>[...document.querySelectorAll(`[${s}]`)].map(i=>{let c=Object.keys(e).map(t=>e[t].map(e=>RegExp(`^${t}:${e}\\('.+'(, ?'[.#i\\w][_-\\w0-9]+')?\\)$`).test(i.getAttribute(s))).some(e=>e)).every(e=>e);return c?t.push(i):(console.error("FFNM: Bad syntax"),console.error(i)),c}).every(e=>e)).every(e=>e),c("is-click").forEach(e=>{let t=i(e,"is-click");switch(t.functionParent){case"class":[...document.querySelectorAll(t.target)].concat(void 0===t.target?e:void 0).forEach(s=>{void 0!==s&&e.addEventListener("click",()=>{switch(t.functionChild){case"add":s.classList.add(t.value);break;case"remove":s.classList.remove(t.value);break;case"toggle":s.classList.toggle(t.value)}})})}}),function(){let e=c("is-scroll-down"),t=c("is-scroll-up");window.addEventListener("scroll",()=>{let c=window.pageYOffset||document.documentElement.scrollTop;e.forEach(e=>{if(c>s){let t=i(e,"is-scroll-down");switch(t.functionParent){case"class":switch(t.functionChild){case"add":e.classList.add(t.value);break;case"remove":e.classList.remove(t.value)}}}}),t.forEach(e=>{if(c<=s){let t=i(e,"is-scroll-up");switch(t.functionParent){case"class":switch(t.functionChild){case"add":e.classList.add(t.value);break;case"remove":e.classList.remove(t.value)}}}}),s=c<=0?0:c},!1)}(),c("is-hover").forEach(e=>{let t=i(e,"is-hover");switch(t.functionParent){case"class":[...document.querySelectorAll(t.target)].concat(void 0===t.target?e:void 0).forEach(s=>{if(void 0!==s)switch(t.functionChild){case"add":e.addEventListener("mouseenter",()=>{s.classList.add(t.value)}),e.addEventListener("mouseout",()=>{s.classList.remove(t.value)});break;case"remove":e.addEventListener("mouseenter",()=>{s.classList.remove(t.value)}),e.addEventListener("mouseout",()=>{s.classList.add(t.value)});break;case"toggle":e.addEventListener("mouseenter",()=>{s.classList.toggle(t.value)}),e.addEventListener("mouseout",()=>{s.classList.toggle(t.value)})}})}}),function(){let e=c("is-visible"),t=c("is-not-visible");window.addEventListener("scroll",()=>{e.forEach(e=>{if(a(e)){let t=i(e,"is-visible");switch(t.functionParent){case"class":switch(t.functionChild){case"add":e.classList.add(t.value);break;case"remove":e.classList.remove(t.value)}}}}),t.forEach(e=>{if(!a(e)){let t=i(e,"is-not-visible");switch(t.functionParent){case"class":switch(t.functionChild){case"add":e.classList.add(t.value),console.log("date");break;case"remove":e.classList.remove(t.value)}}}})},!1)}()}); const EVENTS=["is-click","is-scroll-up","is-scroll-down","is-scroll-top","is-hover","is-visible","is-not-visible"],FUNCTION_TREE={class:["add","remove","toggle"]};let elementsValidates=[],lastScrollTop=void 0;function validateSyntax(){return elementsValidates=[],EVENTS.map(e=>[...document.querySelectorAll(`[${e}]`)].map(t=>{let s=Object.keys(FUNCTION_TREE).map(s=>FUNCTION_TREE[s].map(a=>RegExp(`^${s}:${a}\\('.+'(, ?'[.#i\\w][_-\\w0-9]+')?\\)$`).test(t.getAttribute(e))).some(e=>e)).every(e=>e);return s?elementsValidates.push(t):(console.error("FFNM: Bad syntax"),console.error(t)),s}).every(e=>e)).every(e=>e)}function splitParams(e,t){let s=e.getAttribute(t),a=RegExp("^(\\w+):").exec(s)[1],l=RegExp(":(\\w+)\\(").exec(s)[1],i=RegExp("\\('(\\w[_-\\w0-9]+)',?").exec(s)[1],c=RegExp(", ?'([.#i\\w][_-\\w0-9]+)'\\)");return{functionParent:a,functionChild:l,value:i,target:null!==c.exec(s)?c.exec(s)[1]:void 0}}function getElementsValidatesByEvent(e){return[...elementsValidates].filter(t=>t.hasAttribute(e))}function addEventClick(){return getElementsValidatesByEvent("is-click").forEach(e=>{let t=splitParams(e,"is-click");switch(t.functionParent){case"class":[...document.querySelectorAll(t.target)].concat(void 0===t.target?e:void 0).forEach(s=>{void 0!==s&&e.addEventListener("click",()=>{switch(t.functionChild){case"add":s.classList.add(t.value);break;case"remove":s.classList.remove(t.value);break;case"toggle":s.classList.toggle(t.value)}})})}})}function addEventScroll(){let e=getElementsValidatesByEvent("is-scroll-down"),t=getElementsValidatesByEvent("is-scroll-up"),s=getElementsValidatesByEvent("is-scroll-top");window.addEventListener("scroll",()=>{let a=window.pageYOffset||document.documentElement.scrollTop;e.forEach(e=>{if(a>lastScrollTop){let t=splitParams(e,"is-scroll-down");switch(t.functionParent){case"class":switch(t.functionChild){case"add":e.classList.add(t.value);break;case"remove":e.classList.remove(t.value)}}}}),t.forEach(e=>{if(a<=lastScrollTop){let t=splitParams(e,"is-scroll-up");switch(t.functionParent){case"class":switch(t.functionChild){case"add":e.classList.add(t.value);break;case"remove":e.classList.remove(t.value)}}}}),lastScrollTop=a<=0?0:a,s.forEach(e=>{let t=splitParams(e,"is-scroll-top");if(a<=0)switch(t.functionParent){case"class":switch(t.functionChild){case"add":e.classList.add(t.value);break;case"remove":e.classList.remove(t.value)}}else switch(t.functionParent){case"class":switch(t.functionChild){case"add":e.classList.remove(t.value);break;case"remove":e.classList.add(t.value)}}})},!1)}function addEventHover(){return getElementsValidatesByEvent("is-hover").forEach(e=>{let t=splitParams(e,"is-hover");switch(t.functionParent){case"class":[...document.querySelectorAll(t.target)].concat(void 0===t.target?e:void 0).forEach(s=>{if(void 0!==s)switch(t.functionChild){case"add":e.addEventListener("mouseenter",()=>{s.classList.add(t.value)}),e.addEventListener("mouseout",()=>{s.classList.remove(t.value)});break;case"remove":e.addEventListener("mouseenter",()=>{s.classList.remove(t.value)}),e.addEventListener("mouseout",()=>{s.classList.add(t.value)});break;case"toggle":e.addEventListener("mouseenter",()=>{s.classList.toggle(t.value)}),e.addEventListener("mouseout",()=>{s.classList.toggle(t.value)})}})}})}function addEventVisible(){let e=getElementsValidatesByEvent("is-visible"),t=getElementsValidatesByEvent("is-not-visible");const s=new IntersectionObserver(e=>{e.forEach(e=>{let t=e.target;if(e.isIntersecting){let e=splitParams(t,"is-visible");switch(e.functionParent){case"class":switch(e.functionChild){case"add":t.classList.add(e.value);break;case"remove":t.classList.remove(e.value)}}}})});e.forEach(e=>{s.observe(e)});const a=new IntersectionObserver(e=>{e.forEach(e=>{let t=e.target;if(!e.isIntersecting){let e=splitParams(t,"is-not-visible");switch(e.functionParent){case"class":switch(e.functionChild){case"add":t.classList.add(e.value);break;case"remove":t.classList.remove(e.value)}}}})});t.forEach(e=>{a.observe(e)})}document.addEventListener("DOMContentLoaded",()=>{validateSyntax(),addEventClick(),addEventScroll(),addEventHover(),addEventVisible()});
//# sourceMappingURL=ffnm.min.js.map //# sourceMappingURL=ffnm.min.js.map

View File

@ -19,7 +19,15 @@ const DIST_JS = 'ffnm.min.js';
// JS concat + sourcemaps + babel + min // JS concat + sourcemaps + babel + min
function js(cb) { function js(cb) {
return src([SRC_PATH + 'core.js']) return src([
SRC_PATH + 'globals.js',
SRC_PATH + 'syntax.js',
SRC_PATH + 'events/click.js',
SRC_PATH + 'events/scroll.js',
SRC_PATH + 'events/hover.js',
SRC_PATH + 'events/visible.js',
SRC_PATH + 'core.js'
])
.pipe(sourcemaps.init()) .pipe(sourcemaps.init())
.pipe(concat(DIST_JS)) .pipe(concat(DIST_JS))
.pipe(uglify()) .pipe(uglify())
@ -37,7 +45,7 @@ const build = series(js);
// gulp dev // gulp dev
exports.dev = function () { exports.dev = function () {
build(); build();
watch(SRC_PATH + '*.js', js); watch(SRC_PATH + '**/*.js', js);
} }
// gulp // gulp

26
package-lock.json generated
View File

@ -1,6 +1,6 @@
{ {
"name": "ffnm", "name": "ffnm",
"version": "1.0.0", "version": "1.5.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@ -1327,9 +1327,9 @@
} }
}, },
"hosted-git-info": { "hosted-git-info": {
"version": "2.8.8", "version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==" "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="
}, },
"inflight": { "inflight": {
"version": "1.0.6", "version": "1.0.6",
@ -1346,9 +1346,9 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
}, },
"interpret": { "interpret": {
"version": "1.4.0", "version": "1.4.0",
@ -2006,9 +2006,9 @@
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
}, },
"path-parse": { "path-parse": {
"version": "1.0.6", "version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
}, },
"path-root": { "path-root": {
"version": "0.1.1", "version": "0.1.1",
@ -2899,9 +2899,9 @@
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
}, },
"y18n": { "y18n": {
"version": "3.2.1", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz",
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ=="
}, },
"yargs": { "yargs": {
"version": "7.1.1", "version": "7.1.1",

View File

@ -1,6 +1,6 @@
{ {
"name": "ffnm", "name": "ffnm",
"version": "1.3.0", "version": "1.5.0",
"description": "Simple plugin to avoid writing Javascript in trivial tasks.", "description": "Simple plugin to avoid writing Javascript in trivial tasks.",
"main": "gulpfile.js", "main": "gulpfile.js",
"dependencies": { "dependencies": {

View File

@ -1,279 +1,15 @@
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
//===
// VARIABLES
//===
const EVENTS = ['is-click', 'is-scroll-up', 'is-scroll-down', 'is-hover', 'is-view', 'is-visible', 'is-not-visible'];
const FUNCTION_TREE = {
'class': ['add', 'remove', 'toggle']
};
let elementsValidates = [];
let lastScrollTop = undefined;
//===
// FUNCTIONS
//===
/**
* Method that validates syntax and reports.
* return - Bool
*/
function validateSyntax() {
elementsValidates = [];
// Check all event syntax
return EVENTS.map((event) => {
// Check element FUNCTION_TREE
return [...document.querySelectorAll(`[${event}]`)].map((element) => {
// Check KEY FUNCTION_TREE
let checked = Object.keys(FUNCTION_TREE).map((key) => {
// Check METHODS FUNCTION_TREE
return FUNCTION_TREE[key].map((method) => {
return RegExp(`^${key}:${method}\\('.+'(, ?'[.#i\\w][_-\\w0-9]+')?\\)$`).test(element.getAttribute(event));
}).some(method => method);
}).every(key => key);
if(checked) {
// Save element validate
elementsValidates.push(element);
} else {
// Notify error
console.error('FFNM: Bad syntax');
console.error(element);
}
return checked;
}).every(item => item);
}).every(event => event);
}
/**
* Method return params
* return JSON - {'functionParent': '', 'functionChild': '', 'value': '', 'target': ''}
* example - is-click="class:add('show', '#menu')"
* return {'functionParent': 'class', 'functionChild': 'add', 'value': 'show', 'target': '#menu'}
*/
function splitParams(element, attribute) {
let params = element.getAttribute(attribute);
let functionParent = RegExp("^(\\w+):").exec(params)[1];
let functionChild = RegExp(":(\\w+)\\(").exec(params)[1];
let value = RegExp("\\(\'(\\w[_-\\w0-9]+)\',?").exec(params)[1];
let resultTarget = RegExp(", ?\'([.#i\\w][_-\\w0-9]+)\'\\)");
let target = resultTarget.exec(params) !== null ? resultTarget.exec(params)[1] : undefined;
return {'functionParent': functionParent, 'functionChild': functionChild, 'value': value, 'target': target};
}
/**
* Method that returns all validated elements filtered by an event
* return Array
*/
function getElementsValidatesByEvent(nameEvent) {
return [...elementsValidates].filter(element => {
return element.hasAttribute(nameEvent);
});
}
/**
* Method add events is-click
* return void
*/
function addEventClick() {
let eventClick = 'is-click';
return getElementsValidatesByEvent(eventClick).forEach((element) => {
let params = splitParams(element, eventClick);
switch(params.functionParent) {
case 'class':
[...document.querySelectorAll(params.target)].concat(params.target === undefined ? element : undefined).forEach((item) => {
if (item !== undefined) {
element.addEventListener('click', () => {
switch(params.functionChild) {
case 'add':
item.classList.add(params.value);
break;
case 'remove':
item.classList.remove(params.value);
break;
case 'toggle':
item.classList.toggle(params.value);
break;
}
});
}
});
break;
}
});
}
/**
* Method add events is-scroll
* return void
*/
function addEventScroll() {
let eventScrollDown = 'is-scroll-down';
let eventScrollUp = 'is-scroll-up';
let elementsDown = getElementsValidatesByEvent(eventScrollDown);
let elementsUp = getElementsValidatesByEvent(eventScrollUp);
window.addEventListener("scroll", () => {
let posScroll = window.pageYOffset || document.documentElement.scrollTop;
// Scroll down
elementsDown.forEach((element) => {
if (posScroll > lastScrollTop) {
let params = splitParams(element, eventScrollDown);
switch(params.functionParent) {
case 'class':
switch(params.functionChild) {
case 'add':
element.classList.add(params.value);
break;
case 'remove':
element.classList.remove(params.value);
break;
}
break;
}
}
});
// Scroll up
elementsUp.forEach((element) => {
if (posScroll <= lastScrollTop) {
let params = splitParams(element, eventScrollUp);
switch(params.functionParent) {
case 'class':
switch(params.functionChild) {
case 'add':
element.classList.add(params.value);
break;
case 'remove':
element.classList.remove(params.value);
break;
}
break;
}
}
});
lastScrollTop = posScroll <= 0 ? 0 : posScroll; // For Mobile or negative scrolling
}, false);
}
/**
* Method add events is-hover
* return void
*/
function addEventHover() {
let eventHover = 'is-hover';
return getElementsValidatesByEvent(eventHover).forEach((element) => {
let params = splitParams(element, eventHover);
switch(params.functionParent) {
case 'class':
[...document.querySelectorAll(params.target)].concat(params.target === undefined ? element : undefined).forEach((item) => {
if (item !== undefined) {
// Enter
switch(params.functionChild) {
case 'add':
// Enter
element.addEventListener('mouseenter', () => {
item.classList.add(params.value);
});
// Out
element.addEventListener('mouseout', () => {
item.classList.remove(params.value);
});
break;
case 'remove':
// Enter
element.addEventListener('mouseenter', () => {
item.classList.remove(params.value);
});
// Out
element.addEventListener('mouseout', () => {
item.classList.add(params.value);
});
break;
case 'toggle':
// Enter
element.addEventListener('mouseenter', () => {
item.classList.toggle(params.value);
});
// Out
element.addEventListener('mouseout', () => {
item.classList.toggle(params.value);
});
break;
}
}
});
break;
}
});
}
/**
* Method that checks if an element is visible in the viewport
* return bool
*/
function isInViewport (element) {
let distance = element.getBoundingClientRect();
return distance.top >= 0 &&
distance.left >= 0 &&
distance.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
distance.right <= (window.innerWidth || document.documentElement.clientWidth);
};
/**
* Method that manages the events is-visible and is-not-visible
* return void
*/
function addEventVisible() {
let eventVisible = 'is-visible';
let eventNotVisible = 'is-not-visible';
let elementsVisibles = getElementsValidatesByEvent(eventVisible);
let elementsNotVisibles = getElementsValidatesByEvent(eventNotVisible);
window.addEventListener("scroll", () => {
// Visible
elementsVisibles.forEach((element) => {
if (isInViewport(element)) {
let params = splitParams(element, eventVisible);
switch(params.functionParent) {
case 'class':
switch(params.functionChild) {
case 'add':
element.classList.add(params.value);
break;
case 'remove':
element.classList.remove(params.value);
break;
}
break;
}
}
});
// Not visible
elementsNotVisibles.forEach((element) => {
if (!isInViewport(element)) {
let params = splitParams(element, eventNotVisible);
switch(params.functionParent) {
case 'class':
switch(params.functionChild) {
case 'add':
element.classList.add(params.value);
console.log('date')
break;
case 'remove':
element.classList.remove(params.value);
break;
}
break;
}
}
});
}, false);
}
//=== //===
// INIT // INIT
//=== //===
// Syntax
validateSyntax(); validateSyntax();
// Events
addEventClick(); addEventClick();
addEventScroll(); addEventScroll();
addEventHover(); addEventHover();
addEventVisible(); addEventVisible();
}); });

36
src/events/click.js Normal file
View File

@ -0,0 +1,36 @@
//===
// FUNCTIONS
//===
/**
* Method add events is-click
* return void
*/
function addEventClick() {
let eventClick = 'is-click';
return getElementsValidatesByEvent(eventClick).forEach((element) => {
let params = splitParams(element, eventClick);
switch(params.functionParent) {
case 'class':
[...document.querySelectorAll(params.target)].concat(params.target === undefined ? element : undefined).forEach((item) => {
if (item !== undefined) {
element.addEventListener('click', () => {
switch(params.functionChild) {
case 'add':
item.classList.add(params.value);
break;
case 'remove':
item.classList.remove(params.value);
break;
case 'toggle':
item.classList.toggle(params.value);
break;
}
});
}
});
break;
}
});
}

57
src/events/hover.js Normal file
View File

@ -0,0 +1,57 @@
//===
// FUNCTIONS
//===
/**
* Method add events is-hover
* return void
*/
function addEventHover() {
let eventHover = 'is-hover';
return getElementsValidatesByEvent(eventHover).forEach((element) => {
let params = splitParams(element, eventHover);
switch(params.functionParent) {
case 'class':
[...document.querySelectorAll(params.target)].concat(params.target === undefined ? element : undefined).forEach((item) => {
if (item !== undefined) {
// Enter
switch(params.functionChild) {
case 'add':
// Enter
element.addEventListener('mouseenter', () => {
item.classList.add(params.value);
});
// Out
element.addEventListener('mouseout', () => {
item.classList.remove(params.value);
});
break;
case 'remove':
// Enter
element.addEventListener('mouseenter', () => {
item.classList.remove(params.value);
});
// Out
element.addEventListener('mouseout', () => {
item.classList.add(params.value);
});
break;
case 'toggle':
// Enter
element.addEventListener('mouseenter', () => {
item.classList.toggle(params.value);
});
// Out
element.addEventListener('mouseout', () => {
item.classList.toggle(params.value);
});
break;
}
}
});
break;
}
});
}

93
src/events/scroll.js Normal file
View File

@ -0,0 +1,93 @@
//===
// FUNCTIONS
//===
/**
* Method add events is-scroll
* return void
*/
function addEventScroll() {
const eventScrollDown = 'is-scroll-down';
const eventScrollUp = 'is-scroll-up';
const eventScrollTop = 'is-scroll-top';
let elementsDown = getElementsValidatesByEvent(eventScrollDown);
let elementsUp = getElementsValidatesByEvent(eventScrollUp);
let elementsTop = getElementsValidatesByEvent(eventScrollTop);
window.addEventListener("scroll", () => {
let posScroll = window.pageYOffset || document.documentElement.scrollTop;
// Scroll down - is-scroll-down
elementsDown.forEach((element) => {
if (posScroll > lastScrollTop) {
let params = splitParams(element, eventScrollDown);
switch(params.functionParent) {
case 'class':
switch(params.functionChild) {
case 'add':
element.classList.add(params.value);
break;
case 'remove':
element.classList.remove(params.value);
break;
}
break;
}
}
});
// Scroll up - is-scroll-up
elementsUp.forEach((element) => {
if (posScroll <= lastScrollTop) {
let params = splitParams(element, eventScrollUp);
switch(params.functionParent) {
case 'class':
switch(params.functionChild) {
case 'add':
element.classList.add(params.value);
break;
case 'remove':
element.classList.remove(params.value);
break;
}
break;
}
}
});
lastScrollTop = posScroll <= 0 ? 0 : posScroll; // For Mobile or negative scrolling
// Scroll top - is-scroll-top
elementsTop.forEach((element) => {
let params = splitParams(element, eventScrollTop);
if (posScroll <= 0) {
switch(params.functionParent) {
case 'class':
switch(params.functionChild) {
case 'add':
element.classList.add(params.value);
break;
case 'remove':
element.classList.remove(params.value);
break;
}
break;
}
} else {
switch(params.functionParent) {
case 'class':
switch(params.functionChild) {
case 'add':
element.classList.remove(params.value);
break;
case 'remove':
element.classList.add(params.value);
break;
}
break;
}
}
});
}, false);
}

69
src/events/visible.js Normal file
View File

@ -0,0 +1,69 @@
//===
// FUNCTIONS
//===
/**
* Method that manages the events is-visible and is-not-visible
* return void
*/
function addEventVisible() {
let eventVisible = 'is-visible';
let eventNotVisible = 'is-not-visible';
let elementsVisibles = getElementsValidatesByEvent(eventVisible);
let elementsNotVisibles = getElementsValidatesByEvent(eventNotVisible);
// Visible
const onIntersectionVisible = (entries) => {
entries.forEach((entry) => {
let element = entry.target;
if (entry.isIntersecting) {
let params = splitParams(element, eventVisible);
switch(params.functionParent) {
case 'class':
switch(params.functionChild) {
case 'add':
element.classList.add(params.value);
break;
case 'remove':
element.classList.remove(params.value);
break;
}
break;
}
}
});
};
const observerVisible = new IntersectionObserver(onIntersectionVisible);
elementsVisibles.forEach((element) => {
observerVisible.observe(element);
});
// Not visible
const onIntersectionNotVisible = (entries) => {
entries.forEach((entry) => {
let element = entry.target;
if (!entry.isIntersecting) {
let params = splitParams(element, eventNotVisible);
switch(params.functionParent) {
case 'class':
switch(params.functionChild) {
case 'add':
element.classList.add(params.value);
break;
case 'remove':
element.classList.remove(params.value);
break;
}
break;
}
}
});
};
const observerNotVisible = new IntersectionObserver(onIntersectionNotVisible);
elementsNotVisibles.forEach((element) => {
observerNotVisible.observe(element);
});
}

10
src/globals.js Normal file
View File

@ -0,0 +1,10 @@
//===
// VARIABLES
//===
const EVENTS = ['is-click', 'is-scroll-up', 'is-scroll-down', 'is-scroll-top', 'is-hover', 'is-visible', 'is-not-visible'];
const FUNCTION_TREE = {
'class': ['add', 'remove', 'toggle']
};
let elementsValidates = [];
let lastScrollTop = undefined;

61
src/syntax.js Normal file
View File

@ -0,0 +1,61 @@
//===
// FUNCTIONS
//===
/**
* Method that validates syntax and reports.
* return - Bool
*/
function validateSyntax() {
elementsValidates = [];
// Check all event syntax
return EVENTS.map((event) => {
// Check element FUNCTION_TREE
return [...document.querySelectorAll(`[${event}]`)].map((element) => {
// Check KEY FUNCTION_TREE
let checked = Object.keys(FUNCTION_TREE).map((key) => {
// Check METHODS FUNCTION_TREE
return FUNCTION_TREE[key].map((method) => {
return RegExp(`^${key}:${method}\\('.+'(, ?'[.#i\\w][_-\\w0-9]+')?\\)$`).test(element.getAttribute(event));
}).some(method => method);
}).every(key => key);
if(checked) {
// Save element validate
elementsValidates.push(element);
} else {
// Notify error
console.error('FFNM: Bad syntax');
console.error(element);
}
return checked;
}).every(item => item);
}).every(event => event);
}
/**
* Method return params
* return JSON - {'functionParent': '', 'functionChild': '', 'value': '', 'target': ''}
* example - is-click="class:add('show', '#menu')"
* return {'functionParent': 'class', 'functionChild': 'add', 'value': 'show', 'target': '#menu'}
*/
function splitParams(element, attribute) {
let params = element.getAttribute(attribute);
let functionParent = RegExp("^(\\w+):").exec(params)[1];
let functionChild = RegExp(":(\\w+)\\(").exec(params)[1];
let value = RegExp("\\(\'(\\w[_-\\w0-9]+)\',?").exec(params)[1];
let resultTarget = RegExp(", ?\'([.#i\\w][_-\\w0-9]+)\'\\)");
let target = resultTarget.exec(params) !== null ? resultTarget.exec(params)[1] : undefined;
return {'functionParent': functionParent, 'functionChild': functionChild, 'value': value, 'target': target};
}
/**
* Method that returns all validated elements filtered by an event
* return Array
*/
function getElementsValidatesByEvent(nameEvent) {
return [...elementsValidates].filter(element => {
return element.hasAttribute(nameEvent);
});
}

View File

@ -15,6 +15,22 @@
transition: 1s; transition: 1s;
transform: translateY(10rem); transform: translateY(10rem);
} }
.top {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 5rem;
color: white;
background: red;
transition: 1s;
transform: translateY(-10rem);
display: flex;
justify-content: center;
align-items: center;
}
.show { .show {
transform: translateY(0); transform: translateY(0);
} }
@ -22,6 +38,7 @@
</head> </head>
<body> <body>
<nav is-scroll-down="class:remove('show')" is-scroll-up="class:add('show')" class="nav" id="nav">Mi nav</nav> <nav is-scroll-down="class:remove('show')" is-scroll-up="class:add('show')" class="nav" id="nav">Mi nav</nav>
<div is-scroll-top="class:add('show')" class="top show">You is top page</div>
<p is-scroll-down="class:toggle('ala')"> <p is-scroll-down="class:toggle('ala')">
Ullamcorper morbi tincidunt ornare massa, eget egestas purus viverra accumsan in nisl nisi, scelerisque eu ultrices. Sapien et ligula ullamcorper malesuada proin libero nunc, consequat interdum varius sit amet, mattis. Ullamcorper morbi tincidunt ornare massa, eget egestas purus viverra accumsan in nisl nisi, scelerisque eu ultrices. Sapien et ligula ullamcorper malesuada proin libero nunc, consequat interdum varius sit amet, mattis.
</p> </p>