Skip to content

Instantly share code, notes, and snippets.

@0gust1
Last active September 16, 2023 16:49
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0gust1/260638bd34a434e7f3dd to your computer and use it in GitHub Desktop.
Save 0gust1/260638bd34a434e7f3dd to your computer and use it in GitHub Desktop.
Footnotes to sidenote, and maybe links to sidenotes ?
/**
* Generate sidenotes using footnotes from Multimarkdown generated content
* Idea and principle borrowed from Adrew Clark : http://acdlite.github.io/jquery.sidenotes/ and https://github.com/acdlite/jquery.sidenotes
*
* This script : - gather footnotes in the passed container selector
* - insert the sidenotes in the current text, according to screen size :
* - on big screens insert the sidenote *before* the anchor
* - on medium screens, insert the sidenote *after* the anchor
/**
* Gather footnotes and build an array of "sidenotes" ready to be inserted in DOM ?
* Not used ATM
* @param {String} selector for the container to processfootnotes
*/
var processFootNotesToSideNotes = function processFootNotesToSideNotes(rootSel){
var footNotes = document.querySelectorAll(rootSel+' .footnotes ol li'),
sidenotes = [],
i = 1; //Note numbering
//Each footnote
Array.prototype.forEach.call(footNotes,function(note){
//console.log('test');
//var docFragment = document.createDocumentFragment();
var noteNode = document.createElement('aside');
var id = note.id.replace('fn:','');
noteNode.classList.add('footnote');
noteNode.setAttribute('data-ref',i);
//Append footnote childrens to the sidenote
Array.prototype.forEach.call(note.childNodes,function(noteChild){
noteNode.appendChild(noteChild.cloneNode(true));
});
var sidenote = {};
sidenote.id= id;
sidenote.node = noteNode;
sidenote.num = i;
sidenotes.push(sidenote);
i++;
});
return sidenotes;
};
/**
*Render sidenotes for large screens : "Sidenotes"
*/
var renderSideNotesLarge = function renderSideNotesLarge(sidenotes){
//place sidenotes into the DOM, just before the anchor ref.
//remove any previously rendered infocards and/or hide original footnotes
};
/**
*Render sidenotes for medium screens : "InfoCards"
*/
var renderSideNotesMedium = function renderSideNotesMedium(sidenotes){
//place sidenotes into the DOM, just after the anchor ref.
//remove any previously rendered sidenotes and/or hide original footnotes
};
/**
*Render sidenotes for medium screens : "classic footnotes"
*/
var renderSideNotesSmall = function renderSideNotesSmall(sidenotes){
//basically, let the original footnotes appear again
//hide/remove any previously inserted sidenotes or infocards
};
/**
* Generate sidenotes using footnotes from Multimarkdown generated content
* Idea and principle borrowed from Adrew Clark : http://acdlite.github.io/jquery.sidenotes/ and https://github.com/acdlite/jquery.sidenotes
*
* This script : - gather footnotes in the current container
* - insert the sidenotes in the current text, according to screen size :
* - on big screens insert the sidenote *before* the anchor
* - on medium screens, insert the sidenote *after* the anchor
*
* TODO : parametrize selector for footnotes
* : parametrize classes and tags generated
* : bind a resize event to replace sidenotes when screen size changes
*
* @param {String} selector for the container to process
*/
var processFootNotes = function processFootNotes(rootSel){
var footNotes = document.querySelectorAll(rootSel+' .footnotes ol li');
console.log(footNotes);
var i = 1; //Note numbering
//Each footnote
Array.prototype.forEach.call(footNotes,function(note){
//console.log('test');
//var docFragment = document.createDocumentFragment();
var noteNode = document.createElement('aside');
var id = note.id.replace('fn:','');
//noteNode.id = id;
noteNode.classList.add('footnote');
noteNode.setAttribute('data-ref',i);
//Append footnote childrens to the sidenote
Array.prototype.forEach.call(note.childNodes,function(noteChild){
noteNode.appendChild(noteChild.cloneNode(true));
});
console.log(noteNode.innerHTML);
//append the sidenote along the pointing anchor
var anchor = document.getElementById('fnref:'+id);
//get the anchor parent element (a <p>)
var anchorParent = anchor.parentElement.parentElement;
/* big screens */
//insert before : wide screen
anchorParent.insertBefore(noteNode, anchor.parentElement);
/* medium screens */
//insert after : medium screen
//anchorParent.insertBefore(noteNode, anchor.nextSibling);
/* small screens */
//no need for JS, just hide the sidenotes and show th footnotes via media queries
i++;
});
};
//module.exports = processFootNotes;
@0gust1
Copy link
Author

0gust1 commented Feb 21, 2015

bon, c'est vraiment le debut du truc... c'est vraiment pas sec. Pour l'instant, seule la fonction processFootNotes fonctionne et me sert à tester. J'ai créé un repo (quasi vide pour l'instant) :
https://github.com/0gust1/md-vanilla-sidenotes

Je m'inspire de http://acdlite.github.io/jquery.sidenotes/ , mais souhaite me passer de jQuery, et faire quelque chose de plus léger (il y a de très bonnes idées dans le truc de départ, mais aussi d'autres choses plus accessoires).

Quelques jours après avoir commencé à écrire les première lignes de JS, ce lien a tourné sur twitter et résume bien pourquoi tout ceci m'intéresse : https://medium.com/de-correspondent/links-are-broken-these-three-alternatives-have-improved-our-readers-reading-experience-796c302c8930

Le point de départ est un document HTML comportant des "footnotes" balisées un peu de cette façon :

<p> du contenu, du blabla, de la prose, etc...
<a href="#fn:66572" id="fnref:66572" title="see footnote" class="footnote">[1]</a>
.... encore du contenu, du contenu, du contenu
</p>
<!-- encore du contenu -->
<div class="footnotes">
<hr />
<ol>
    <li id="fn:66572">
        <p>
        un deux trois
        <a href="http://seenthis.net">http://seenthis.net</a>
        </p>
        <p>
        Un second paragraphe
        <img src="" alt="une image">
        blah blah
        <a href="#fnref:66572" title="return to article" class="reversefootnote">&#160;&#8617;</a>
        </p>
    </li>
</ol>
</div>

Voici les problématiques auxquelles je réfléchis :

  1. gestion du "responsive" et du style
  2. performance (utilisation de DocFragment, si possible)
  3. packaging (bower, npm, rien ?)

1 : responsive et stylage :

Grosso modo : stylage : gérer le maximum de choses en CSS (plutôt responsabilité de l'implémenteur) : media queries et/ou classes CSS différentes selon le type de sidenotes (sidenotes, infocards ou footnotes).

Par contre, une partie du comportement "responsive" est à gérer par JS. On a 3 états possibles :

  • écran large, mode "sidenotes" : les sidenotes sont insérées avant l'ancre de la note. ça me plait moyen, mais pour la mise en forme, c'est beaucoup plus facile à gérer (float:left/right + marge négative pour aligner le bloc avec l'ancre).
  • écran medium, mode "info cards" : les sidenotes sont inséres après l'ancre de la note.
  • petit écran, mode "footnotes" : c'est simple, on fait réapparaitre les footnotes originelles.

Il faut donc 3 fonctions qui seront exécutées en fonction des "passages de breakpoints" détectés et bien sûr de la taille d'écran au chargement de la page.
Sur la page de démo du plugin jquery dont je m'inspire ( http://acdlite.github.io/jquery.sidenotes/ ), l'auteur utilise http://responsejs.com/.

Bref, il nous faut quelque chose capable d'executer des fonctions JS en fonction de la taille de la fenêtre du navigateur.

2 : performance :

J'ai l'impression que l'idéal serait de ne pas se refarcir des requêtes dans le DOM (pour aller chercher le contenu et l'insérer aux bon endroits) à chaque passage de "breakpoint". Je pensais éventuellement maintenir en mémoire une structure de données contenant les notes, qui serait passée en paramètres aux fonctions de placement dans le DOM (c'est ce que j'ai commencé avec la fonction processFootNotesToSideNotes).

Si possible, j'essaierais bien d'utiliser les docFragments, qui apportent beaucoup en performance en cas d'insertions multiples dans le DOM.

3 : Packaging

Mon coeur balance. J'aime les modules CommonJs, mais du coup je crois que ça implique que l'implémenteur passe par browserify. J'ai vu sur le net des tentatives de faire des genre de modules universels (http://dontkry.com/posts/code/browserify-and-the-universal-module-definition.html) mais franchement, c'est pas beau...

A propos de l'idée de david `bgk (https://larlet.fr/david/stream/2015/02/13/)

C'est vraiment pas éloigné de ce que je cherche à faire, et l'idée du prefetch des liens fait rêver...
En ajoutant les serviceworkers ou un genre de build on est "presque" (manque le push) sur quelque chose qui pourrait faire du commentaire décentralisé ?

@davidbgk
Copy link

Quelques réflexions en vrac :

  • pour le responsive, je ne suis pas sûr que cela soit pertinent de rétablir les footnotes pour les petits écrans, au contraire c'est sous cette contrainte que je n'ai pas envie de faire des aller-retours mais d'avoir de l'info contextuelle
  • pour les performances aux passages de breakpoints, il faut bien voir que ça ne concerne quasi que les développeurs, les utilisateurs ne s'amusent pas trop à redimensionner leurs fenêtres ;)
  • pour le packaging il me semble que l'on peut proposer l'ensemble des solutions les plus populaires mais je suis très naïf là-dessus
  • pour les commentaires décentralisés, il manque la notion d'invalidation du cache mais ça peut se travailler <3 Voir à ce sujet http://jakearchibald.com/2014/offline-cookbook/

@0gust1
Copy link
Author

0gust1 commented Feb 28, 2015

Merci davidbgk.

  1. Oui, carrement, je crois que j'était fatigué ^^ J'aurais aimé tester néanmoins (avec différents volumes de contenu, et de notes).
  2. Je ne fais pas partie de ce genre de dev-front / webdesigners ;) Je pensais surtout au passage portrait / paysage sur tablette et mobile.
  3. Faire plusieurs "builds" ? À creuser.
  4. J'adore ce genre d'idées, malheureusement, techniquement, je suis trop lent, pas assez doué et je manque de temps pour le moment pour bidouiller des trucs.

Merci pour ton retour, ça aide. Je vais essayer d'avancer dessus ce week-end.

@0gust1
Copy link
Author

0gust1 commented Mar 3, 2015

Bon, j'ai avancé. ça commence à prendre forme.

cf : https://github.com/0gust1/md-vanilla-sidenotes

Là, je commence à réfléchir sur la meilleur façon d'organiser le code pour offrir le maximum d'extensibilité (par rapport à ton idée, par exemple).

Je continue dans les issues du repo. Merci encore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment