Bonjour à tous,
J'ai créé un nouvel outil pour lequel j'aimerais quelques avis, svp.
Il s'agit d'une bibliothèque vraiment minuscule (moins de 2Ko), servant à modifier des pages HTML, en AJAX, basée sur window.fetch et orientée inversion de contrôle.
Ce que j'entends par inversion de contrôle, c'est que plutôt que de dire à l'interpréteur d'appeler une fonction en retour d'un appel AJAX, afin de lui dire que faire ensuite, on va simplement écouter la réponse du serveur et agir en fonction du contenu reçu, via des listeners.
En gros, lorsque l'utilisateur charge une page, on définit toute une série de listeners et il n'y a plus rien à faire ensuite, on n'envoie donc pas de JS avec nos réponses AJAX.
Un des avantages, c'est qu'on ne doit pas tester ce qu'on a reçu, pour savoir comment le traiter (exemple, l'utilisateur a fait une action mais le serveur répond par une box de login car sa session a expiré, a mené vers un 404, vers une erreur 500, etc.). Ici, c'est la magie des query selectors qui fait tout le boulot.
Voyons par la pratique, comme on définit un listener :
On y voit plusieurs choses :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 dispatcher.addEventListener('div.myClass', function(element, next, loaded) { // opérations sur l'élément // ... // passage au listener suivant next(); });
- 'div.myClass' : le sélecteur permettant de cibler tout élément à traiter via ce listener
- element : un élément trouvé
- next : une fonction servant à permettre aux autres listeners de faire leur traitement
- loaded : booléen indiquant s'il s'agit d'un élément loadé via la lib ou non
L'appel AJAX a été simplifié au possible... en effet, vous n'avez pas besoin de construire votre requête, il suffit de lui donner une ancre ou un formulaire et la bibliothèque se charge du reste :
Bien entendu, il serait dommage de ne pouvoir appliquer cela qu'au HTML chargé en AJAX, c'est pourquoi il est possible d'appliquer les listeners enregistrés à la page chargée, de manière tout aussi simple :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 // avec une ancre, donc envoi en GET fetcher(document.querySelector('a')) .fetch(dispatcher.dispatch); // avec un formulaire, en GET ou POST, selon la méthode renseignée sur le formulaire fetcher(document.querySelector('form')) .fetch(dispatcher.dispatch); // avec envoi des cookies fetcher(document.querySelector('form')) .credentials() // ce qui revient à appeler .credentials('same-origin') mais il est aussi possible de lui passer un 'include' pour du cross-origin .fetch(dispatcher.dispatch); // avec un ajout de header fetcher(document.querySelector('form')) .header('HeaderName', 'header value') .fetch(dispatcher.dispatch); // avec un ajout de valeur au body d'une requête POST fetcher(document.querySelector('form')) .body('fieldName', 'value') .fetch(dispatcher.dispatch);
EDIT :
Code : Sélectionner tout - Visualiser dans une fenêtre à part dispatcher.populate(document);
La gestions des ancres/formulaires ne vous suffit pas ? il vous suffit d'ajouter/surcharger des fetchers... exemple :
Voilà
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 fetcher.fetchers.button = function (button) { // fetcher.request(url, httpMethod, optionalBody) return fetcher.request(button.dataset.href, 'get'); };
À présent, la lib en question, pas encore publiée, la voici :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 void function(t){var e,n,r,o,i,s,u,c e=t.document,n=t.fetch,r=t.FormData,o=Function.bind.bind(Function.call),i=o(Array.prototype.forEach),s=o(Range.prototype.createContextualFragment,e.createRange()),u=function(t){return Object.create(t||null)},c=function(){var t,e,r,o return t=function(){},e=[],e.n=function(){e.shift(),e.length&&e.fetch()},e.fetch=function(){var o if(!e[1])return o=e[0],n(o.q.u,o.q.o).then(r.r).then(s).then(r.z).then(o.d).then(e.n)["catch"](t)},r=function(t,e,n){var r,i return r=u(o),i=u(),r.o=i,r.u=t,i.headers=u(),i.headers["X-Requested-With"]="XMLHttpRequest",i.method=e,i.body=n,r},r.r=function(t){var n return n=e[0],n.q.response=t,t.text()},r.z=function(t){var n return n=e[0],n.q.response.fragment=t,n.q},o=u(),o.body=function(t,e){return this.o.body.append(t,e),this},o.credentials=function(t){return void 0===t&&(t="same-origin"),this.o.credentials=t,this},o.fetch=function(t){var n n=u(),n.q=this,n.d=t,e.push(n),e.fetch()},o.r=function(){e[0]&&e[0].q===this&&(e.unshift(1),e.n())},o.header=function(t,e){return this.o.headers[t]=e,this},o.option=function(t,e){return this.o[t]=e,this},r}(),t.fetcher=function(){var t return t=function(e){var n return n=e.nodeName.toLowerCase(),t.fetchers[n](e)},t.request=c,t.fetchers=u(),t.fetchers.form=function(t){return c(t.action,t.method,new r(t))},t.fetchers.a=function(t){return c(t.href,"get")},t}(),t.dispatcher=function(){var t,e,n,r,o,s return t=u(),e=u(),e.addEventListener=function(n,r){return t[n]=t[n]||[],t[n].indexOf(r)<0&&t[n].push(r),e},e.dispatch=function(t){e.onTimeout(t),setTimeout(e.populate,0,t.response.fragment,!0)},e.onTimeout=function(t){if(408===t.response.status)throw t.r(),Error()},e.populate=function(e,r){var o o=[],o.c=e,o.l=r===!0,i(Object.keys(t),n,o),o.n=s.bind(o),o.n()},n=function(t){var e,n e=this,e.s=t,n=e.c.querySelectorAll(t),i(n,r,e)},r=function(e){var n n=this,n.e=e,i(t[n.s],o,n)},o=function(t){this.push([t,this.e,this.l])},s=function(){var t t=this.shift(),t&&t[0](t[1],this.n,this.l)},e}()}(this);
Partager