Plan de cours JS/TW5


#21

eval.js

Sur ces bases, écrivons une nouvelle macro eval.js

:

(function(){
exports.name = "eval";
exports.params = [{name: "fun"}];
exports.run = function(fun) {
	return eval(fun);
};
})();

Nous pouvons l’utiliser ainsi :

<<eval "2+2">>
<<eval "new Date()">>
<<eval "alert('ok');">>
<<eval "var sum = new Function('a', 'b', 'return a + b');sum(10, 32)">>
<<eval "Math.E">>
<<eval "Math.pow(2,3)">>
// Jeter un dé :
<<eval "Math.floor(Math.random() * 7);">>

<<eval "
  const n = 6710859;
  function isPrime(n) { return !(Array(n+1).join(1).match(/^1?$|^(11+?)\1+$/)); }
  isPrime(13);
">>

◉ Sources :


Ce code javascript est incroyable :

<<eval "
const reject = (pred, array) => array.filter((...args) => !pred(...args));
reject(word => word.length > 4, ['Mandarine', 'Pomme', 'Cerise', 'Poire', 'Kiwi', 'Banane']); // Kiwi
">>

Voir celui-ci :

<<eval "
const sample = arr => arr[Math.floor(Math.random() * arr.length)];
sample([1,2,3,4,5,6,7,8,9,10]);
">>

et

<<eval "
const similarity = (arr, values) => arr.filter(v => values.includes(v));
similarity(['pierre','feuille', 'ciseau'], ['feuille','chifoumi', 'pierre']);
">>

Un petit dernier :

<<eval "
const take = (arr, m=1, n=m+1) => arr.slice(m-1, n);
take(['A', 'B', 'C', 'D', 'E', 'F', 'G'], 3, 6); //CDEF
">>

◉ Sources incroyables à voir impérativement : https://30secondsofcode.org/

Pour créer automatiquement 1 nouveau tiddly toutes les minutes :

<<eval "
var x = setInterval(function() {$tw.wiki.addTiddler(new $tw.Tiddler({
  title: 'Tiddly'+Math.floor(Math.random() * 70000),
  gen: 'demo'
}));}, 600000);      
">>

Je vous conseille de faire cet exercice dans un tiddlywiki de brouillon… :wink:
◉ Sources : https://github.com/Jermolene/TiddlyWiki5/issues/2025
◉ Sources : https://www.w3schools.com/jsref/met_win_settimeout.asp

image

◉ Sources : https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/eval

Afficher de 1 à N

\define compte(borne)
<<eval "
const times = (n, fn, context = undefined) => {
  let i = 1;
  while (fn.call(context, i) !== false && ++i < n+1) {}
};
var output = '';
times($borne$, i => (output += i + ' '));
output;
">>
\end
<<compte 5>>

Ici on combine à la fois les macros de tiddlywiki (avec le pragma \define ) et le code javascript. Cela ouvre évidemment énormément de possibilités.

A propos de la syntaxe ‘fonction = (params) => code;

On note que l’affectation par décomposition est doublée d’une fonction fléchée à voir dans les sources ci-dessous (c’est vraiment technique)

◉ Sources : https://github.com/30-seconds/30-seconds-of-code
◉ Affectation par décomposition : https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Opérateurs/Affecter_par_décomposition
◉ Fonction fléchée : https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Fonctions/Fonctions_fléchées


#22

Tu s raison et en plus on n’arrête pas de le dire :crazy_face:

Notre exemple "HelloWorld me paraît être un bon candidat pour débuter, et il y a beaucoup de choses à dire sur ce petit bout de code:

  • Ce n’est pas une macro mis un module => différences
  • C’est une fonction => fonctions
  • Qui produit un résultat => exports
  • … et plus encore, je prépare un topo à dessus

#23

Attention, une seule paire de guillemets puisque la fonction n’a qu’un seul paramètre (Ça j’ai bien compris ? :smiley:)

<$macrocall $name=“now” format=“0hh:0mm, DDth MMM YYYY”/>


#24

Oui, une seule paire… c’est corrigé :wink:


#25

Autre exemple de script :

(function(){
exports.name = "ToggleVisible";
exports.params = [{name: "classe"},{name: "valeur"}];
exports.run = function(classe,valeur) {
  el = document.getElementsByClassName(classe);
  for(var i=0;i<el.length;i++){
    if(valeur=="1"){
      el[i].style.visibility = "";
    }else{
      el[i].style.visibility = "hidden";
    }
  }
};
})();

qui s’utilise ainsi :

<div class="un">UN</div>
<div class="deux">DEUX</div>
<div class="trois">TROIS</div>
<<ToggleVisible "un" "1">>
<<ToggleVisible "deux" "0">>
<<ToggleVisible "trois" "1">>

et qui permet de basculer la visibilité d’un élément par sa classe. On peut noter au passage la façon d’utiliser plusieurs paramètres.


#26

Pour masquer les codes secrets :

\define masque(code,disp)
<<eval "
const mask = (cc, num = $disp$, mask = '⛔') => `${cc}`.slice(-num).padStart(`${cc}`.length, mask);
mask($code$);
">>
\end

<<masque "6815983777281892" 2>>

#27

Une couleur au hasard :

\define rndcolor()
<<eval "
const randomHexColorCode = () => {
  let n = (Math.random() * 0xfffff * 1000000).toString(16);
  return '&#35;' + n.slice(0, 8);
};
randomHexColorCode();
">>
\end
<<rndcolor>>

On pourrait aussi définir une fonction de conversion :

const RGBToHex = (r, g, b) => ((r << 16) + (g << 8) + b).toString(16).padStart(6, '0');

◉ Mine d’or : https://github.com/30-seconds/30-seconds-of-code#collaborators


#28

Créer un texte dans un <div>

\define create(str)
<<eval "
const createElement = str => {
  const el = document.createElement('div');
  el.innerHTML = str;
  return el.firstElementChild;
};
">>
$str$
\end

<<create "<div class='container'>
    <b>Hello!</b>
  </div>"
>>

#29

Requêter un paramètre de style CSS

\define style(z,q)
<<eval "
const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];
getStyle(document.querySelector('$z$'), '$q$');
">>
\end

<<style "div" "font-weight">>

On construira sur ce modèle :
const setStyle = (el, ruleName, val) => (el.style[ruleName] = val);
image


#30

Détecter le navigateur du périphérique

const detectDeviceType = () =>
  /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
    ? 'Mobile'
    : 'Desktop';

Ce code est construit ainsi :
const nomfonction = (ici pas de variables séparées par des virgules) => une expression régulière avec un test ? si vrai et : sinon.
avec const -> une constante

image
et l’appel : detectDeviceType();

Affectation directe d’un test :
image

◉ Sources : https://tiddlywiki.com/#Railroad%20Plugin


#31

Bonjour Jean-Bernard,

Quelle productivité ! :star_struck:. Je te suis bien,mais à la vitesse d’un bébé escargot !
En tout cas il me semble que nous sommes sous le bon angle d’attaque. Ça me parle !

Pour moi, cette partie du code:

  el = document.getElementsByClassName(classe);
  for(var i=0;i<el.length;i++){
    if(valeur=="1"){
      el[i].style.visibility = "";
    }else{
      el[i].style.visibility = "hidden";

c’est du pur JS ou contient-il quelque chose appartenant àTW5 ?

Si c’est du pur JS, on a toute la doc externe pour expliquer ce code et on sait bien isoler ce qui ppartient à TW5 de ce qui appartient à JS


#32

Bonjour Eric,
Tout ce qui est codé dans la

(function(){  })();

est du javascript et permet d’exposer le code dans le tiddler par une syntaxe propre à TW5 :
<<NomFonction Params...>>

Ici en (7) le comment exposer une fonction en JS :


Bien qu’écrit en JS, les 3 exports :
exports.name = “”;
exports.params = [];
exports.run = function() {}

sont nécessaires pour dialoguer avec TW5 et constitue un point d’entrée.


#33

Jean-Bernard,

Objet: Détecter le navigateur du périphérique

Comment cette fonction et son appel sont-ils intégrés à TW ?


#34

Il suffit de l’inclure dans un appel formulé ainsi :

\define detect()
<<eval """
const detectDeviceType = () =>
  /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
    ? 'Mobile'
    : 'Desktop';
detectDeviceType ();
""">>
\end

<<detect>>

#35

Dans mes tests, celui-ci est intéressant :

<div id='bbox'>
TIDDLYWIKI IS AWESOME!
</div>

<<eval """
var ele = document.querySelector('#bbox');
ele.style.color = '#FFFFFFAA';
ele.style.backgroundColor = '#3377CC99';
ele.style.padding='30px';
ele='';
""">>

#36

On peut désormais envisager tous les calculs possibles :

\define racine(r)
<<eval """
const racine=(number) => Math.pow(number, 1 / 2);
racine($r$);
""">>
\end

<<racine 25>>

#37

Compter les classes d’éléments d’un tiddler

On utilise ici la fonction document.querySelectorAll pour compter le nombre d’éléments appartenant à une classe.

\define nb_el(classe)
<<eval """
const nb_elem = (cl) => document.querySelectorAll(cl).length;
nb_elem('$classe$') ;
""">>
\end

#.titre Titre 1
##.soustitre soustitre 1
##.soustitre soustitre 2
#.titre Titre 2
##.soustitre soustitre 1
##.soustitre soustitre 2
##.soustitre soustitre 3
#.titre Titre 3
##.soustitre soustitre 1
#.titre Titre 4
##.soustitre soustitre 1
 
''<<nb_el ".titre">> titre(s) et <<nb_el ".soustitre">> soustitre(s)''

◉ Sources : https://developer.mozilla.org/fr/docs/Web/API/Document/querySelectorAll


#38

Nous pouvons ajouter des éléments sur le DOM ainsi :

\define add_html(quid)
<<eval """
const list = document.querySelector("#list");
list.insertAdjacentHTML("beforeend", `<li>$quid$</li>`);
""">>
\end

<div id="list"></div>

<<add_html "Pomme">>
<<add_html "Orange">>


#39

Trivial :

\define mois()
<<eval """
const date = Date.now();
const options = { month: "short" };
new Intl.DateTimeFormat("fr-FR", options).format(date);
""">>
\end

<<mois>>

#40

Principes d’écriture d’un code JavaScript cohérent et idiomatique

◉ Sources : https://github.com/rwaldron/idiomatic.js/tree/master/translations/fr_FR