Mots-clé : html

JavaScript : comment surcharger console.log()

J’avais besoin de décaler mes log pour voir rapidement si j’étais, ou pas, à l’intérieur d’une fonction.

Eh oui, après plusieurs années, même si on peut faire des points d’arrêt, JavaScript est là pour répondre à des événements utilisateurs et autres… donc il ne faut souvent pas arrêter pendant l’exécution ou la visualisation d’une page Web… on n’a toujours pas d’autre choix que de faire le bon console.log() des familles qui fait que le développement est extrêmement ralenti…

Je me suis donc crée les fonctions log_in(), log() et log_out().
Ainsi, quand j’entre dans une fonction, j’appelle log_in(), et tous mes log() dans cette fonction seront décalés, ce qui fait que je vois immédiatement où sont appelés mes logs ! Ensuite, ne pas oublier de faire un log_out().

let logLevel = 0;
let log = function () {
    let args = Array.from(arguments);
    if (logLevel > 0) {
        args = [Array(logLevel).fill(' ').join('')].concat(args);
    }
    console.log.apply(null, args);
};
let log_in = function () {
    log.apply(null, arguments);
    logLevel++;
}, log_out = function (s) {
    if (logLevel>0) {
        logLevel--;
    }
    log.apply(null, arguments);
};

Django : faire des pages d’erreur sur mesure (404, 500, etc.)

Lorsque vous voulez faire des pages d’erreur sur mesure, c’est très simple… une fois que vous savez !
En effet, la documentation n’est pas très claire…

Voici un résumé de mon expérience, pour faire des pages d’erreur sur mesure (404, 500, etc.).
Il faut d’abord savoir que les erreurs sont des fonctions appelées (= vous ne pouvez pas le faire via les vues génériques).
Ensuite, la documentation donne un exemple, mais ce n’est pas assez.
Grâce aux raccourcis de Django, vous avez la fonction render() à laquelle vous pouvez passer un template et un contexte (= donc des variables).
Je me suis servi de cela pour créer un dictionnaire qui contient les erreurs, et les passer dans dans le contexte avec la clé title et content.


Voici le code des vues qui affiche une erreur « proprement » :

from django.shortcuts import render
from django.utils.translation import gettext_lazy as _
VIEW_ERRORS = {
    404: {'title': _("404 - Page not found"),
          'content': _("A 404 Not found error indicates..."), },
    500: {'title': _("Internal error"),
          'content': _("A 500 Internal error means..."), },
    403: {'title': _("Permission denied"),
          'content': _("A 403 Forbidden error means ..."), },
    400: {'title': _("Bad request"),
          'content': _("A 400 Bad request error means ..."), }, }
def error_view_handler(request, exception, status):
    return render(request, template_name='errors.html', status=status,
                  context={'error': exception, 'status': status,
                           'title': VIEW_ERRORS[status]['title'],
                           'content': VIEW_ERRORS[status]['content']})
def error_404_view_handler(request, exception=None):
    return error_view_handler(request, exception, 404)
def error_500_view_handler(request, exception=None):
    return error_view_handler(request, exception, 500)
def error_403_view_handler(request, exception=None):
    return error_view_handler(request, exception, 403)
def error_400_view_handler(request, exception=None):
    return error_view_handler(request, exception, 400)


Une fois les vues faites, il faut aller dans la déclaration principale de vos vues. Donc le fichier urls.py qui est la racine de votre projet. Si vous mettez le code ailleurs, il sera ignoré.

Dedans, déclarez vos fonctions qui gèrent les erreurs :

handler404 = 'app.views.errors.error_404_view_handler'
handler500 = 'app.views.errors.error_500_view_handler'
handler403 = 'app.views.errors.error_403_view_handler'
handler400 = 'app.views.errors.error_400_view_handler'

Et enfin, dans vos templates, créez un fichier errors.html dans lequel vous pouvez construire votre page HTML qui gère l’erreur « proprement », avec, en plus dans le contexte, les variables {{ title }} et {{ content }} qui affichent respectivement le titre et le détail de l’erreur.

Maintenant, comment, en mode « développement », tester ces pages ? Dans la pratique vous ne pouvez pas, car en mode développement, une erreur affiche les informations de déboguage, et pas vos pages !
La solution : faire une URL qui « simule » l’erreur. Exemple avec 404 : vous ajouter dans vos urls : path('404/', error_404_view_handler), et puis d’afficher votre URL adéquate, soit http://localhost:8000/404/ et vous verrez l’erreur !

Bootstrap : classes utilitaires

Vous allez peut-être trouver du code qui ressemble à cela :
<p class="mb-0">Texte dans un paragraphe</p>

Bootstrap >= 4 a mis en place plein de possibilités pour faire du padding et des marges « responsives ».
Elles fonctionnent pour tous les breakpoints :

  • xs (<=576px)
  • sm (>=576px)
  • md (>=768px)
  • lg (>=992px)
  • xl (>=1200px)

<p class="{propriété}{côtés}-{taille}">texte</p>

propriété :

  • m – les marges
  • p – le padding

côtés :

  • tmargin-top or padding-top
  • bmargin-bottom or padding-bottom
  • lmargin-left or padding-left
  • rmargin-right or padding-right
  • x*-left and *-right
  • y*-top and *-bottom
  • blank – les 4 côtés à la fois

taille :

  • 0 – supprimer les marges ou mettre le padding à 0
  • 1 – $spacer *0.25
  • 2 – $spacer *0.5
  • 3 – $spacer
  • 4 – $spacer *1.5
  • 5 – $spacer *3
  • auto – margin à auto

Exemple : cocktails

Pour avoir la moyenne

Lorsqu’on vient sur le site :

  • Si on n’est pas connecté, afficher le formulaire de connexion
  • Si on est connecté :
    • Appel AJAX #1 : aller demander la liste des cocktails et l’afficher
    • Appel AJAX #2 : lorsqu’on clique sur un cocktail, aller chercher le détail de ce cocktail et l’afficher

Pour dépasser un peu la moyenne

  • Formulaire de connexion
  • Gestion des erreurs / avertissements de base (avertissement si mot de passe trop court, erreur si login existant etc)

Pour dépasser largement moyenne

Possibilité de créer des cocktails


Créer un ingrédient

Appel AJAX simple à faire, nous l’avons vu en cours : envoi d’un formulaire :


Créer une unité

Appel AJAX simple à faire, nous l’avons vu en cours : envoi d’un formulaire :


Créer un cocktail

Le seul appel AJAX complexe à faire, voici l’interface utilisateur, à vous d’écrire le code JavaScript qui va derrière :

Pour avoir la note maximale

  • Ecrire tout correctement, parfaitement indenté (tous les éditeurs modernes vous font l’indentation automatique, servez-vous en !)
  • Tout écrire sous forme de classe (dans le cas de ce projet Cocktails, classe Ingredient, classe Unite, etc)
  • Tout séparer dans des fichiers selon cette organisation : un fichier JavaScript par classe, le nom du fichier = le nom de la classe en minuscule (dans le cas de ce projet Cocktails, classe ingredient.js, classe unite.js, etc)
  • Ecriture complète en ECMA6(plus de var, que des let, fonctions de la forme () = >{} etc)
  • Callbacks avancés avec gestion des closures

Javascript et jQuery : comment créer un svg dynamiquement

Saviez vous qu’il était impossible de créer un élément svg dynamiquement comme ceci :

var $('<svg />'); ?

Moi non. Après avoir cherché pendant pas mal de temps j’ai enfin réussi à faire un code qui génère un svg et ça fonctionne :

var mySvg = document.createElementNS("http://www.w3.org/2000/svg", "svg"),
    div_svg = $('#mondiv');

mySvg.setAttribute("version", "1.2");
mySvg.setAttribute("baseProfile", "tiny");
mySvg.setAttribute('viewBox', '0 0 100 100');
mySvg.setAttribute('preserveAspectRatio', 'xMinYMin');
div_svg[0].appendChild(mySvg); /* (!) [0] = élément DOM "pur" */
var c = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
c.setAttribute('points', '0,45 25,1 75,1 99,45 75,90 25,90');
c.setAttribute('style', 'fill:blue;stroke:red;stroke-width:1');
$(mySvg).append(c);

Et voilà vous avez enfin un exemple qui fonctionne !

Django : créer un checkbox multiple choice avec bootstrap

Je me sers de cet habillage ici.

C’est, en gros, une « surcharge » de bootstrap avec quelques composants en plus.

Seulement j’aurais aimé avoir une sélection de plusieurs choix = cases à cocher qui soit « compatible » avec cet habillage.
Je n’aurais jamais cru que c’était aussi simple.
En fait Django a généralisé plein d’affichages HTML à tel point qu’il suffit de faire du pas à pas et de regarder ce qu’il fait pour comprendre.
Même le rendu par « item » de chaque « Renderer » est surchargeable. Donc voici le code qui prend… 10 lignes, et qui réhabille totalement le rendu des cases à cocher :

from django.forms import CheckboxSelectMultiple
from django.forms.widgets import ChoiceFieldRenderer, \
    CheckboxChoiceInput

class BootstrapChoiceFieldRenderer(ChoiceFieldRenderer):
    choice_input_class = CheckboxChoiceInput
    outer_html = '<div{id_attr}>{content}</div>'
    inner_html = '<div class="checkbox">'
                 '{choice_value}{sub_widgets}'
                 '</div>'

class CheckboxSelectMultipleBootstrap(CheckboxSelectMultiple):
    renderer = BootstrapChoiceFieldRenderer

Le tag <blink> : il est né à partir d’une bonne cuite. Histoire vraie.

Vous ne me croiriez pas si j’étais le seul à le dire, mais le tag blink qui fait clignoter le texte de manière affreuse et agressive, est né d’une grosse fête entre ingénieurs, qui, bien échaudés par quelques verres, se sont marrés en pensant à une idée stupide.

L’histoire tout en langue de Shakespeare ici.

ExtJs autoLoad et store : howto / comment faire

Si vous ne connaissez pas ExtJs, c’est « à peine » du JavaScript, « à peine » utilisé par IBM, et plein d’autres « petites » entreprises 😉 .

Très puissant mais il manque parfois d’exemple.

En voici un pratique que j’ai eu du mal à mettre en place : pourtant c’est du classique de chez classique.

Je veux ouvrir un onglet qui charge automatiquement des informations de base de données : un onglet dans lequel il y a les informations d’un dossier : nom, prénom, date de naissance, etc.

Assez classique.

Mais disons… que je veux en faire le moins possible. Avec ExtJs, c’est très simple. Enfin simple… après avoir bien cherché !

En fait, l’astuce est qu’il faut appeler la fonction autoLoad, pour que le chargement soit automatique, et avant même d’afficher l’onglet.

Dans mon cas, je voulais afficher Homme ou Femme dans un combo. Donc il fallait avant même d’afficher l’onglet, qu’il précharge le truc dans un magasin de données = store.