Astuce: Smarter than 'Ctrl+F': Linking Directly to Web Page Content - Le Hollandais Volant

En ajoutant #:~:text= à la fin d'une URL puis le texte qui apparaît quelque part sur la page, ce dernier sera surligné lorsque vous accèderez au lien, et la position de défilement placera ce texte au milieu.

Une sorte de version boostée aux hormones des classiques ancres qui ciblent les éléments avec un attribut HTML id.

Voici la syntaxe :

https://example.com/page.html#:~:text=[prefix-,]textStart[,textEnd][,-suffix]

Developer Tools secrets that shouldn’t be secrets | Christian Heilmann [MAJ]

Donc, pour résumer:

  • pour avoir le nom des variables avec leur valeur, utiliser { }: console.log({var})
  • console.warn(), console.error() et console.info() pour différencier l'aspect du message.
  • console.assert(condition,retour) pour éviter un if (condition){console.log(retour)
  • console.trace() pour remonter la pile d'appels
  • console.time('etiquette') et console.timeEnd('etiquette') pour mesurer un temps d'exécution entre deux points
  • console.group('nom'), console.groupCollapsed('nom') et console.groupEnd('nom') pour regrouper des console log()
  • console.table(array) pour présenter les données sous forme de tableau
  • console.dir(array) pour présenter hiérarchiquement un tableau
  • $(selecteur) est équivalent à document.querySelector(selecteur)
  • $$(selecteur) est équivalent à document.querySelectorAll(selecteur)

Liste complétée avec https://dev.to/alishgiri/say-no-to-consolelog-556n

Via https://lehollandaisvolant.net/?mode=links

ASTUCE Html & JS : détecter quand on sélectionne un élément d'une datalist

En bossant sur l'appli que j'utilise pour mes cours, j'ai voulu ajouter un accès rapide à un document en tapant le début du nom de dossier dans un input alimenté par une datalist.

Bien entendu, je veux éviter de devoir passer du clavier à la souris plusieurs fois : tape un bout du nom, clique pour sélectionner, appuie sur entrée pour valider...

Donc, il faudrait que la sélection et l'ouverture du document se fasse:

  • quand je tape un bout de nom et que j'appuie sur entrée (il ira chercher le premier de la liste)
  • quand je tape le début, que j'utilise les flèches pour aller chercher celui que je veux et que j'appuie sur entrée,
  • quand je tape le début et que je clique sur le nom du document qui m'intéresse.

Et là, c'est le drame

En effet, autant on peut capturer un évènement sur un input, autant ce n'est pas possible sur les option ou le datalist

Donc, il faut gruger et agissant sur les events de l'input.

Je mets ici ma solution actuelle (c'est le code que j'utilise avec mon framework js perso parce que j'ai la flemme de changer ):

<input type="text" placeholder="accès rapide à un document" list="docs_list" id="input_docs_list">
<datalist id="docs_list">
    \\ici les option qui vont bien
</datalist>

<script type="text/javascript">
    on('keydown','#input_docs_list',function(e){ // ça, c'est mon VanillaJS
        if(e.keyCode==13||!e.key){ 
            // si on a appuyé sur entrée ou que l'évènement n'est pas déclenché par une touche (donc, c'est la souris)
            window.location.replace("?"+e.target.value);
        }
    });

    on('input','#input_docs_list',function(e){
        // celui-ci est pour firefox
        if(e.inputType=='insertReplacementText'){
            window.location.replace("?"+e.data);
        }
    })
</script>

J'ai testé sous Firefox, Chromium et Edge...

Notes perso JS : usage de fetch()

Je me note ici pour une prochaine fois parce que fetch n'est pas forcément très intuitif...

2 façons d'utiliser fetch :

la plus tendance et élégante : en enchaînant les then()

fetch("index.php", { method: 'POST', body: formData })
  .then((response)=>{
        // on attend l'arrivée de la réponse et on la traite
        return response.text(); // ou response.json();
  })
  .then((text)=>{
         // on attend la fin du traitement de la réponse  et on en traite le contenu
       console.log(text);
  });

la plus lisible (?) : avec async et await

En gros, on crée une fonction asynchrone pour pouvoir utiliser les await.

const fetchAPI = async(URL) => {
    const response = await fetch(URL);  // on attend l'arrivée de la réponse 
    const data = await response.json();  // on attend la fin du traitement de la réponse
    console.log(data)
}
fetchAPI("https://jsonplaceholder.typicode.com/todos/1")

SVG images are accepted but not sanitized · Issue #38 · berthubert/trifecta · GitHub

Ménon... Mais dites-moi que c'est pas vrai...

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500">
  <circle cx="250" cy="250" r="210" fill="#fff" stroke="#000" stroke-width="8"/>
  <script type="text/javascript">alert(1);</script>
</svg>

Donc, si on colle du JS dans un SVG, le JS serait exécuté à l'affichage de l'image ?!

Je teste ci-dessous avec l'exemple donné sur la page...

omg.svg

Sur mon site, l'image s'affiche normalement sans exécuter le code... par contre, si on ouvre l'image dans un autre onglet...

Comment c'est possible de laisser un truc pareil dans la nature ?!

Via https://sebsauvage.net/links/

Astuces & liens pour HTML, JS et toussa

Petite liste tirée des RSS que je suis en ce moment.

FormData API | 12 Days of Web

Un petit résumé perso de cette page sur l'objet FormData en javascript.

Créer un objet FormData à partir d'un formulaire

let form = document.querySelector('form');
let data = new FormData(form);

Parcourir l'objet FormData

C'est un itérable, donc on le parcourt avec un for et on récupère des ['clé','valeur']

for (let entry of data) {
    console.log(entry);
}

ou

for (let [key, value] of data) {
    console.log(key);
    console.log(value);
}

parcourir les clés / les valeurs

for (let key of data.keys()) {
  console.log(key);
}

Get, set, update des valeurs

GET

Récupérer une valeur (sans rire ?!)

  • S'il y a un seul champ au nom de la clé: let title = data.get('title')
  • S'il y en a plusieurs : let titles = data.getAll('title');

SET

Ajouter une nouvelle valeur à l'objet FormData

data.set('date', '2022-12-25');

APPEND

Ajouter une valeur supplémentaire à une entrée existante (si l'entrée n'existe pas, elle est créée)

data.append('tags', 'vacations');

Divers

Tester si un champ existe

let hasID = data.has('id');

Récupérer un tableau

  • des clés : let arr = Array.from(data.keys());
  • des valeurs : let arr = Array.from(data.values());

Convertir un FormData en objet clés valeurs

Si votre FormData ne contient pas plusieurs champs ayant le même nom.

let serialized = Object.fromEntries(data);

Sinon, on paufine

let obj = {};
for (let [key, value] of data) {
    if (obj[key] !== undefined) {
        if (!Array.isArray(obj[key])) {
            obj[key] = [obj[key]];
        }
        obj[key].push(value);
    } else {
        obj[key] = value;
    }
}

Une fois converti en objet, on peut le transformer en JSON

let stringified = JSON.stringify(obj);

How can I listen for a click outside of an element in JavaScript? - 30 seconds of code

Pour écouter un click hors d'un élément, on utilise l'event delegation: on vérifie si la target de l'event correspond ou pas à l'objet qu'on veut.

  document.addEventListener('click', e => {
    if (!element.contains(e.target)) callback();
  });
};
onClickOutside('#my-element', () => console.log('Hello'));
// Will log 'Hello' whenever the user clicks outside of #my-element

How can I listen for an event only once in JavaScript? - 30 seconds of code

Tiens, je ne savais pas qu'addEventListener acceptait des paramètres en option, en particulier un { once : true} qui permet de n'exécuter la fonction attachée à l'évènement qu'une seule fois...


const listenOnce = (el, evt, fn) =>
  el.addEventListener(evt, fn, { once: true });

listenOnce(
  document.getElementById('my-btn'),
  'click',
  () => console.log('Hello!')
); // 'Hello!' will only be logged on the first click

Plugin PluXML : C'est en off, mais stylé... [Edit]

Un autre petit plugin vite-fait-sur-le-gaz comme aurait dit San Antonio: cette fois-ci, il s'agit de styler les commentaires et articles offline pour les repérer plus simplement.

icon.png offlineClass

Le plugin se contente d'ajouter une classe de votre choix (à configurer) dans la ligne de tout commentaire ou article hors ligne.

Comme pour le précédent, il injecte un JS qui ajoute la classe au tr qui contient une liste offline.

Une fois activé, configurez le plugin en lui donnant la classe à utiliser ( par exemple «offline» ) puis ajoutez votre css à votre thème.

.offline{ 
    background:rgba(255,0,0,0.2);
    color:rgb(50,0,0);
    font-style: italic;
}
.offline td{
    padding:1em 0;
}

C'est tout. Mais visuellement, c'est autre chose !

[Edit du 02-09]

J'ai ajouté la possibilité de déplacer tout item offline en début de liste quelle que soit sa date... Utile si vous avez tendance à accumuler le boulot en retard au point que certains disparaissent dans la pagination...

Pour récupérer le zip ➜ https://repo.warriordudimanche.net/ZIPFILES/offlineClass.zip

(...)

Plugin PluXML : Empêcher pluXML de virer les backslashes des articles

Ze problaim

Si tu publies des bouts de code sur pluXML, tu as sans doute remarqué que ce dernier est pour le moins psychorigide avec les antislashes: il les vire sans ménagement... pourtant, on aimerait bien qu'il conserve les regex en l'état dans un code par exemple.

Je suis pas stupide, je comprends bien qu'il s'agit là d'un souci de sécurité, mais quand même, ça fait ch***.

Le souci,c'est que pluXML filtre les antislashes dans les $_POST très très tôt dans le code, bien avant tout hook de plugin: il le fait dans le prepend.php de l'admin, ligne 43.

Ben mon con, comment tu vas faire si tu peux pas intervenir en php via un hook pour modifier le $_POST?

Ze solouchonne

Ben tu le modifies en JS dans la page article lors du submit du formulaire

En gros, on remplace les «\» par des «\» dans le chapo et le avant de submit le formulaire. C'est une méthode dont j'ai trouvé l'idée ici https://forum.pluxml.org/discussion/6960/plugin-plx-cssbackslash-pour-ledition-des-fichiers-css

Donc, j'injecte un petit script JS via le hook AdminArticleFoot et il se charge d'intervenir lorsque le navigateur a terminé de créer l'objet formData: c'est d'ailleurs cet évènement qu'on va utiliser dans addEventListener au lieu du submit habituel.

Code du script injecté

(function (){
    let chapo = document.getElementById("id_chapo");
    var content = document.getElementById("id_content");
    var form = document.getElementById("form_article");
    function saveSlashes(str){
        return str.replace(/[\\]/g, '\\$&');
    }
    form.addEventListener('formdata',function(e){
        let formData = e.formData;
        formData.set('chapo', saveSlashes(formData.get('chapo')));
        formData.set('content', saveSlashes(formData.get('content')));
    });

})();

Ze saiquiouriti ?

Niveau sécurité, le plugin n'intervient que sur la page article.php et uniquement sur les champs chapo et content du formulaire. Il ne bloque pas le plxUtils::unSlash($_POST) du prepend.php. Je pense donc qu'il n'ouvre pas de faille majeure.

Ze conclugionne

Ainsi, les antislashes de ce script tiré de l'article sur le bug de mpdération passent enfin sans problème :

Exemple de code problématique

    const PATTERNS = array(
        'arts'          => '#^\D?(\d{4,})\.(?:\w+|\d{3})(?:,\w+|,\d{3})*\.\d{3}\.\d{12}\..*\.xml$#',
        'statiques'     => '#^(\d{3,})\..*\.php$#',
        'commentaires'  => '#^_?\d{4,}\.(?:\d{10,})(?:-\d+)?\.xml$#'
    );

Le zip est à télécharger depuis mon repo : https://repo.warriordudimanche.net/ZIPFILES/ArticleBackslashesKeeper.zip

(...)

document.execCommand - Référence Web API | MDN

https://antoineboursin.fr/courses/creez-un-editeur-de-texte-wysiwyg

La vie est mal faite: je découvre document.execCommand() permettant de faire du richtext dans un élément contentEditable juste quand il est officiellement déclaré obsolète...

Bon, en même temps, sur stackoverflow, the holy baïbol, certains affirment que:

  1. oui, il est obsolète mais n'a pas d'alternative
  2. execCommand semble requis pour tout navigateur prétendant sortir sur le marché,
  3. son implémentation semble sujette à variations selon le navigateur (le fameux internet explorer syndrome de triste mémoire)
Mais merde !  Je fais quoi moi ?!
Fil RSS des articles
Caching time 0.004350 s