14 Commits

Author SHA1 Message Date
4b01ca94bb Fix dash 2020-07-17 17:50:20 +02:00
91338f9185 Update README.md 2020-07-17 16:29:34 +02:00
0284ebc9c4 Update README.md 2020-07-17 16:25:00 +02:00
3aa327bad6 Update README.md 2020-07-17 12:12:22 +02:00
a30f4023d2 Fix regex check 2020-07-17 12:12:02 +02:00
ae1c78da16 Add hover 2020-07-17 11:11:53 +02:00
37820b5bb4 Fix images 2020-07-16 11:30:47 +02:00
2c306485d4 Update README.md 2020-07-16 11:23:05 +02:00
605a4463b6 Update media 2020-07-16 11:15:38 +02:00
cd75682160 Delete example.png 2020-07-16 11:09:17 +02:00
facde1d9db Update README.md 2020-07-16 01:12:36 +02:00
ef3388ee5e Update validate.html 2020-07-16 01:08:13 +02:00
9aff506298 Update README.md 2020-07-16 01:06:48 +02:00
dd5377d732 Optional second param 2020-07-16 00:58:17 +02:00
16 changed files with 194 additions and 39 deletions

120
README.md
View File

@ -1,8 +1,20 @@
# FFNM (Front-End for the next master) # FFNM (Front-End for the next master)
![example](media/example.png) ``` html
<button i-click="class:add('press')">open</button>
```
👇 🖱 **Click!** 👇
``` html
<button class="press" i-click="class:add('press')">open</button>
```
Simple utility to **avoid writing Javascript** when working with **classes**. It only takes up **1Kb**! Simple utility to **avoid writing Javascript** when working with **classes**. It only takes up **2Kb**!
- Simplifies the **click**.
- Simplifies the **scroll**.
- Simplifies **hover**.
## DEMOS ## DEMOS
@ -22,29 +34,50 @@ 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.0.0/dist/ffnm.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/tanrax/FFNM@v1.2.2/dist/ffnm.min.js"></script>
``` ```
### Examples ### Examples
#### Click #### Click
##### Add the class `press` to `button` when the button is pressed.
```html
<button i-click="class:add('press')">open</button>
```
##### Remove the class `press` to `button` when the button is pressed.
```html
<button i-click="class:remove('press')">close</button>
```
##### Switch the classs `show` to `button` when the button is pressed.
```html
<button i-click="class:toggle('show')">view</button>
```
##### Add the class `show` to the `#nav` selector when the button is pressed. ##### Add the class `show` to the `#nav` selector when the button is pressed.
```html ```html
<button i-click="class:add('show', '#nav')">open</button> <button i-click="class:add('show', '#nav')">open</button>
<nav id="nav"></nav>
``` ```
##### Remove the `show` class from the `#nav` selector when the button is pressed. ##### Remove the `show` class from the `#nav` selector when the button is pressed.
```html ```html
<button i-click="class:remove('show', '#nav')">close</button> <button i-click="class:remove('show', '#nav')">close</button>
<nav id="nav" class="show"></nav>
``` ```
##### Switch the `show` class to the `#nav` selector when the button is pressed. ##### Switch the `show` class to the `#nav` selector when the button is pressed.
```html ```html
<button i-click="class:toggle('show', '#nav')">view</button> <button i-click="class:toggle('show', '#nav')">view</button>
<nav id="nav" class="show"></nav>
``` ```
#### Scroll up #### Scroll up
@ -75,27 +108,34 @@ Add to your `<head>` the following tag.
<nav i-scroll-down="class:remove('show')"></nav> <nav i-scroll-down="class:remove('show')"></nav>
``` ```
#### Hover
#### Classes without events ##### Add the class `show` to `div` when hover.
##### Add the class `show` to the `#nav` selector ```html
<div i-hover="class:add('show')"></div>
```javascript
class:add('show', '#nav')
``` ```
##### Remove the `show` class from the `#nav` selector ##### Remove the `show` class from `div` when hover.
```javascript ```html
class:remove('show', '#nav') <div i-hover="class:remove('show')"></div>
``` ```
##### Switch the class `show` to the `#nav` selector ##### Toggle the `show` class from `div` when hover.
```javascript ```html
class:toggle('show', '#nav') <div i-hover="class:toggle('show')"></div>
``` ```
##### Add the class `show` to `#button` when `div` hover.
```html
<div i-hover="class:toggle('show', '#button')"></div>
<button id="button">Hi</div>
```
--- ---
## Spanish/Español ## Spanish/Español
@ -105,29 +145,50 @@ class:toggle('show', '#nav')
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.0.0/ffnm.min.js"></script> <script src="https://cdn.jsdelivr.net/gh/tanrax/FFNM@v1.2.2/dist/ffnm.min.js"></script>
``` ```
### Ejemplos de uso ### Ejemplos de uso
#### Clic #### Clic
##### Añadir la clase `apretado` a `button` cuando sea pulsado.
```html
<button i-click="class:add('apretado')">Apreta</button>
```
##### Quitar la clase `apretado` a `button` cuando sea pulsado.
```html
<button i-click="class:remove('apretado')">cerrar</button>
```
##### Intercambiar la clase `apretado` a `button` cuando sea pulsado.
```html
<button i-click="class:toggle('apretado')">ver</button>
```
##### Añadir la clase `show` al selector `#menu` cuando sea pulsado el botón. ##### Añadir la clase `show` al selector `#menu` cuando sea pulsado el botón.
```html ```html
<button i-click="class:add('show', '#menu')">abrir</button> <button i-click="class:add('show', '#menu')">abrir</button>
<nav id="menu"></nav>
``` ```
##### Quitar la clase `show` al selector `#menu` cuando sea pulsado el botón. ##### Quitar la clase `show` al selector `#menu` cuando sea pulsado el botón.
```html ```html
<button i-click="class:remove('show', '#menu')">cerrar</button> <button i-click="class:remove('show', '#menu')">cerrar</button>
<nav id="menu" class="show"></nav>
``` ```
##### Intercambiar la clase `show` al selector `#menu` cuando sea pulsado el botón. ##### Intercambiar la clase `show` al selector `#menu` cuando sea pulsado el botón.
```html ```html
<button i-click="class:toggle('show', '#menu')">ver</button> <button i-click="class:toggle('show', '#menu')">ver</button>
<nav id="menu" class="show"></nav>
``` ```
#### Subir scroll #### Subir scroll
@ -158,26 +219,33 @@ Añade a tu `<head>` la siguiente etiqueta.
<nav i-scroll-down="class:remove('show')"></nav> <nav i-scroll-down="class:remove('show')"></nav>
``` ```
#### Hover
#### Clases sin eventos ##### Añade la clase `show` al `div` cuando sea hover.
##### Añadir la clase `show` al selector `#menu` ```html
<div i-hover="class:add('show')"></div>
```javascript
class:add('show', '#menu')
``` ```
##### Quitar la clase `show` al selector `#menu` ##### Quita la clase `show` al `div` cuando sea hover.
```javascript ```html
class:remove('show', '#menu') <div i-hover="class:remove('show')"></div>
``` ```
##### Intercambiar la clase `show` al selector `#menu` ##### Intercambia la clase `show` al `div` cuando sea hover.
```javascript ```html
class:toggle('show', '#menu') <div i-hover="class:toggle('show')"></div>
``` ```
##### Añade la clase `show` a `#button` cuando `div` sea hover.
```html
<div i-hover="class:toggle('show', '#button')"></div>
<button id="button">Hi</div>
```
--- ---
## Development ## Development

2
dist/ffnm.min.js vendored
View File

@ -1,2 +1,2 @@
document.addEventListener("DOMContentLoaded",()=>{const e={class:["add","remove","toggle"]};let c=[],t=void 0;function l(e,c){let t=e.getAttribute(c),l=RegExp("^(\\w+):").exec(t)[1],s=RegExp(":(\\w+)\\(").exec(t)[1],a=RegExp("\\('(\\w+)',").exec(t),o=null!==a?a.exec(t)[1]:void 0,r=RegExp(", *'([#,.,a-zA-Z]\\w*)'\\)").exec(t);return{functionParent:l,functionChild:s,value:o,target:null!==r?r.exec(t)[1]:void 0}}c=[],["i-click","i-scroll-up","i-scroll-down"].map(t=>[...document.querySelectorAll(`[${t}]`)].map(l=>{let s=Object.keys(e).map(c=>e[c].map(e=>RegExp(`^${c}:${e}\\('\\w+', *'[#,.,a-zA-Z]\\w*'\\)$`).test(l.getAttribute(t))).some(e=>e)).every(e=>e);return s?c.push(l):(console.error("FFNM: Bad syntax"),console.error(l)),s}).every(e=>e)).every(e=>e),[...document.querySelectorAll("[i-click]")].forEach(e=>{let c=l(e,"i-click");switch(c.functionParent){case"class":[...document.querySelectorAll(c.target)].forEach(t=>{e.addEventListener("click",()=>{switch(c.functionChild){case"add":t.classList.add(c.value);break;case"remove":t.classList.remove(c.value);break;case"toggle":t.classList.toggle(c.value)}})})}}),window.addEventListener("scroll",()=>{let e=window.pageYOffset||document.documentElement.scrollTop;[...document.querySelectorAll("[i-scroll-down]")].forEach(c=>{if(e>t){let e=l(c,"i-scroll-down");switch(e.functionParent){case"class":switch(e.functionChild){case"add":c.classList.add(e.value);break;case"remove":c.classList.remove(e.value)}}}}),[...document.querySelectorAll("[i-scroll-up]")].forEach(c=>{if(e<=t){let e=l(c,"i-scroll-up");switch(e.functionParent){case"class":switch(e.functionChild){case"add":c.classList.add(e.value);break;case"remove":c.classList.remove(e.value)}}}}),t=e<=0?0:e},!1)}); document.addEventListener("DOMContentLoaded",()=>{const e={class:["add","remove","toggle"]};let t=[],c=void 0;function s(e,t){let c=e.getAttribute(t),s=RegExp("^(\\w+):").exec(c)[1],a=RegExp(":(\\w+)\\(").exec(c)[1],l=RegExp("\\('(\\w[_-\\w0-9]+)',?").exec(c)[1],o=RegExp(", ?'([.#i\\w][_-\\w0-9]+)'\\)");return{functionParent:s,functionChild:a,value:l,target:null!==o.exec(c)?o.exec(c)[1]:void 0}}t=[],["i-click","i-scroll-up","i-scroll-down","i-hover"].map(c=>[...document.querySelectorAll(`[${c}]`)].map(s=>{let a=Object.keys(e).map(t=>e[t].map(e=>RegExp(`^${t}:${e}\\('.+'(, ?'[.#i\\w][_-\\w0-9]+')?\\)$`).test(s.getAttribute(c))).some(e=>e)).every(e=>e);return a?t.push(s):(console.error("FFNM: Bad syntax"),console.error(s)),a}).every(e=>e)).every(e=>e),[...document.querySelectorAll("[i-click]")].forEach(e=>{let t=s(e,"i-click");switch(t.functionParent){case"class":[...document.querySelectorAll(t.target)].concat(void 0===t.target?e:void 0).forEach(c=>{void 0!==c&&e.addEventListener("click",()=>{switch(t.functionChild){case"add":c.classList.add(t.value);break;case"remove":c.classList.remove(t.value);break;case"toggle":c.classList.toggle(t.value)}})})}}),window.addEventListener("scroll",()=>{let e=window.pageYOffset||document.documentElement.scrollTop;[...document.querySelectorAll("[i-scroll-down]")].forEach(t=>{if(e>c){let e=s(t,"i-scroll-down");switch(e.functionParent){case"class":switch(e.functionChild){case"add":t.classList.add(e.value);break;case"remove":t.classList.remove(e.value)}}}}),[...document.querySelectorAll("[i-scroll-up]")].forEach(t=>{if(e<=c){let e=s(t,"i-scroll-up");switch(e.functionParent){case"class":switch(e.functionChild){case"add":t.classList.add(e.value);break;case"remove":t.classList.remove(e.value)}}}}),c=e<=0?0:e},!1),[...document.querySelectorAll("[i-hover]")].forEach(e=>{let t=s(e,"i-hover");switch(t.functionParent){case"class":[...document.querySelectorAll(t.target)].concat(void 0===t.target?e:void 0).forEach(c=>{if(void 0!==c)switch(t.functionChild){case"add":e.addEventListener("mouseenter",()=>{c.classList.add(t.value)}),e.addEventListener("mouseout",()=>{c.classList.remove(t.value)});break;case"remove":e.addEventListener("mouseenter",()=>{c.classList.remove(t.value)}),e.addEventListener("mouseout",()=>{c.classList.add(t.value)});break;case"toggle":e.addEventListener("mouseenter",()=>{c.classList.toggle(t.value)}),e.addEventListener("mouseout",()=>{c.classList.toggle(t.value)})}})}})});
//# sourceMappingURL=ffnm.min.js.map //# sourceMappingURL=ffnm.min.js.map

1
media/carbon-config.json Normal file
View File

@ -0,0 +1 @@
{"paddingVertical":"56px","paddingHorizontal":"56px","backgroundImage":null,"backgroundImageSelection":null,"backgroundMode":"color","backgroundColor":"rgba(171,184,195,0)","dropShadow":true,"dropShadowOffsetY":"20px","dropShadowBlurRadius":"68px","theme":"monokai","windowTheme":"none","language":"htmlmixed","fontFamily":"Hack","fontSize":"14px","lineHeight":"133%","windowControls":true,"widthAdjustment":true,"lineNumbers":false,"firstLineNumber":1,"exportSize":"2x","watermark":false,"squaredImage":false,"hiddenCharacters":false,"name":"","width":680}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

BIN
media/other-click.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
media/other-clicked.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
media/scroll-down.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
media/scroll-up.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
media/scroll.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
media/self-click.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
media/self-clicked.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -3,7 +3,7 @@ document.addEventListener('DOMContentLoaded', () => {
//=== //===
// VARIABLES // VARIABLES
//=== //===
const EVENTS = ['i-click', 'i-scroll-up', 'i-scroll-down']; const EVENTS = ['i-click', 'i-scroll-up', 'i-scroll-down', 'i-hover'];
const FUNCTION_TREE = { const FUNCTION_TREE = {
'class': ['add', 'remove', 'toggle'] 'class': ['add', 'remove', 'toggle']
}; };
@ -28,7 +28,7 @@ document.addEventListener('DOMContentLoaded', () => {
let checked = Object.keys(FUNCTION_TREE).map((key) => { let checked = Object.keys(FUNCTION_TREE).map((key) => {
// Check METHODS FUNCTION_TREE // Check METHODS FUNCTION_TREE
return FUNCTION_TREE[key].map((method) => { return FUNCTION_TREE[key].map((method) => {
return RegExp(`^${key}:${method}\\('\\w+', *'[#,.,a-zA-Z]\\w*'\\)$`).test(element.getAttribute(event)); return RegExp(`^${key}:${method}\\('.+'(, ?'[.#i\\w][_-\\w0-9]+')?\\)$`).test(element.getAttribute(event));
}).some(method => method); }).some(method => method);
}).every(key => key); }).every(key => key);
if(checked) { if(checked) {
@ -52,12 +52,11 @@ document.addEventListener('DOMContentLoaded', () => {
*/ */
function splitParams(element, attribute) { function splitParams(element, attribute) {
let params = element.getAttribute(attribute); let params = element.getAttribute(attribute);
let functionParent = RegExp(`^(\\w+):`).exec(params)[1]; let functionParent = RegExp("^(\\w+):").exec(params)[1];
let functionChild = RegExp(`:(\\w+)\\(`).exec(params)[1]; let functionChild = RegExp(":(\\w+)\\(").exec(params)[1];
let resultValue = RegExp(`\\(\'(\\w+)\',`).exec(params); let value = RegExp("\\(\'(\\w[_-\\w0-9]+)\',?").exec(params)[1];
let value = resultValue !== null ? resultValue.exec(params)[1] : undefined; let resultTarget = RegExp(", ?\'([.#i\\w][_-\\w0-9]+)\'\\)");
let resultTarget = RegExp(`, *\'([#,.,a-zA-Z]\\w*)\'\\)`).exec(params); let target = resultTarget.exec(params) !== null ? resultTarget.exec(params)[1] : undefined;
let target = resultTarget !== null ? resultTarget.exec(params)[1] : undefined;
return {'functionParent': functionParent, 'functionChild': functionChild, 'value': value, 'target': target}; return {'functionParent': functionParent, 'functionChild': functionChild, 'value': value, 'target': target};
} }
@ -71,7 +70,8 @@ document.addEventListener('DOMContentLoaded', () => {
let params = splitParams(element, eventClick); let params = splitParams(element, eventClick);
switch(params.functionParent) { switch(params.functionParent) {
case 'class': case 'class':
[...document.querySelectorAll(params.target)].forEach((item) => { [...document.querySelectorAll(params.target)].concat(params.target === undefined ? element : undefined).forEach((item) => {
if (item !== undefined) {
element.addEventListener('click', () => { element.addEventListener('click', () => {
switch(params.functionChild) { switch(params.functionChild) {
case 'add': case 'add':
@ -85,6 +85,7 @@ document.addEventListener('DOMContentLoaded', () => {
break; break;
} }
}); });
}
}); });
break; break;
} }
@ -140,10 +141,64 @@ document.addEventListener('DOMContentLoaded', () => {
}, false); }, false);
} }
/**
* Method add events i-hover
* return void
*/
function addEventHover() {
let eventHover = 'i-hover';
return [...document.querySelectorAll(`[${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;
}
});
}
//=== //===
// INIT // INIT
//=== //===
validateSyntax(); validateSyntax();
addEventClick(); addEventClick();
addEventScroll(); addEventScroll();
addEventHover();
}); });

View File

@ -21,7 +21,7 @@
</style> </style>
</head> </head>
<body> <body>
<nav class="nav" id="nav">Mi nav</nav> <nav class="nav" id="nav" i-click="class:remove('show')">Mi nav</nav>
<button i-click="class:add('show', '#nav')">add</button> <button i-click="class:add('show', '#nav')">add</button>
<button i-click="class:remove('show', '#nav')">remove</button> <button i-click="class:remove('show', '#nav')">remove</button>
<button i-click="class:toggle('show', '#nav')">toggle</button> <button i-click="class:toggle('show', '#nav')">toggle</button>

31
test/i-hover.html Normal file
View File

@ -0,0 +1,31 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<title>Test i-hover</title>
<script src="../dist/ffnm.min.js"></script>
<style>
.uppercase {
text-transform: uppercase;
}
</style>
</head>
<body>
<p i-hover="class:add('uppercase', '.text__1--hover')">Place the cursor over this text</p>
<p class="text__1--hover">
Quisque id diam vel quam elementum pulvinar etiam non quam?
</p>
<p class="text__1--hover">
Ac, feugiat sed lectus vestibulum mattis ullamcorper velit sed ullamcorper.
</p>
<p class="text__1--hover" i-hover="class:add('uppercase')">
Nunc aliquet bibendum enim, facilisis gravida neque convallis a cras.
</p>
<p class="text__1--hover">
Orci phasellus egestas tellus rutrum tellus pellentesque eu tincidunt tortor.
</p>
<p class="text__1--hover">
Volutpat consequat, mauris nunc congue nisi, vitae suscipit tellus mauris.
</p>
</body>
</html>

View File

@ -22,7 +22,7 @@
</head> </head>
<body> <body>
<nav i-scroll-down="class:remove('show')" i-scroll-up="class:add('show')" class="nav" id="nav">Mi nav</nav> <nav i-scroll-down="class:remove('show')" i-scroll-up="class:add('show')" class="nav" id="nav">Mi nav</nav>
<p i-scroll-down="class:toggle('ala', 'p')"> <p i-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>
<p> <p>

View File

@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
<title>Test syntax</title> <title>Test syntax</title>
<script src="../dist/FFNM.min.js"></script> <script src="../dist/ffnm.min.js"></script>
</head> </head>
<body> <body>
<!-- Class with ID --> <!-- Class with ID -->