Étiquette : JavaScript

Vincent Lecomte
[JS] Récupérer le contenu d’un éditeur tinyMCE

[JS] Récupérer le contenu d’un éditeur tinyMCE

Si vous ne connaissez pas encore tinyMCE, il s’agit d’un éditeur WYSIWYG que vous pouvez intégrer à vos sites. Il est notamment très connu grâce à son utilisation dans WordPress. L’édition Community est gratuite mais il existe également des offres avec support et plugins premium.

Pour une raison ou une autre vous souhaitez peut-être récupérer le contenu d’un éditeur initialisé avant de l’envoyer au serveur. Cela est évidemment possible ! Bien que cet article serve avant tout de mémo il va également vous aider à ne pas plonger dans les méandres de l’énorme documentation de la librairie. Voyons ensemble comment procéder.

Obtenir l’instance d’éditeur

Il faut tout d’abord récupérer l’éditeur souhaité avec la méthode tinymce.get(). Celle-ci reçoit une chaine de caractères représentant l’identifiant du champ qui a servi pour l’initialisation de tinyMCE.

Supposons que vous partiez d’un champ de type textarea, avec l’attribut “id” contenant simplement “myTinyEditor” :

var med = tinymce.get('myTinyEditor');

Cela renverra l’instance de l’éditeur, sinon null s’il n’a pas encore été initialisé.

Récupérer le contenu de l’éditeur

Sur l’instance de l’éditeur que vous venez de récupérer, il suffit d’utiliser getContent() pour retourner le contenu au format “brut” (donc en HTML, qui est généré par tinyMCE).

var contHtml = med.getContent();

Remarque: si le champ est vide, c’est bien une chaine vide que vous obtiendrez.

Vous savez désormais comment récupérer le contenu d’un éditeur tinyMCE, bravo !

A lire également…

[JS] Personnaliser la liste de styles dans tinyMCE

Dans l’éditeur tinyMCE, lorsqu’on choisit de dérouler le menu de sélection du format, on dispose d’éléments par défaut comme les en-têtes (h1 à h6), l’alignement ou bien même la mise en forme classique comme le “gras”, “souligné” ou “italique”. Ce menu peut être personnalisé de différentes manières. La méthode la plus simple reste de redéfinir […]

0 commentaire

Sources

Tout est bien décrit dans la documentation de référence.

[JS] Retour sur le rendu d’une page avec PDF.js

[JS] Retour sur le rendu d’une page avec PDF.js

Il y a déjà un moment nous abordions le fait de pouvoir afficher une page de PDF sous forme d’image grâce à la librairie PDF.js. Les différentes mises à jour de celle-ci ont conduit à ce que certains appels soient désormais dépréciés, bien que toujours fonctionnels.

Voici le nouveau code que nous pouvons utiliser :

pdfjsLib.getDocument(
{
	data : ao_pdfData
})
.promise.then(function(dPdf)
{
	dPdf.getPage(ai_num).then(function(page)
	{
		var canvas = document.createElement('canvas');
		canvas.id = as_id + '-page-' + ai_num;
		canvas.className = 'f-canvas';

		var vContext = canvas.getContext('2d');
		var vViewport = page.getViewport({
			scale: af_scale2,
			rotation: 0
		});
		
		canvas.height = vViewport.height;
		canvas.width = vViewport.width;

		var renderContext = {
			canvasContext: vContext,
			viewport: vViewport
		};
		
		page.cleanupAfterRender = true;
		
		var renderTask = page.render(
			renderContext
		);
		
		renderTask.promise.then(function()
		{
			if (canvas.msToBlob) 
			{
				$('#' + img_id).attr("src", 
					canvas.toDataURL(
						"image/jpeg", 0.85
					)
				);
			}
			else
			{
				canvas.toBlob(function(blob) 
				{
					let img = new Image();
					img.onload = function() { 
						URL.revokeObjectURL(img.src); 
					}; 
					img.src = URL.createObjectURL(blob);
					$('#' + img_id).attr("src", 
						img.src
					);
				}, "image/jpg", 0.85);
			}
		})
	});
});

Quelques détails concernant ce code :

  • On charge toujours le document en passant en paramètre les données qui auront été décodées à l’aide de la méthode atob(). On aura passé le contenu du PDF sous forme de chaine de caractères en Base64.
  • Petite différence : on appelle la méthode then() sur un objet “promise”. Même modification pour la tâche de rendu (variable “renderTask”).
  • La variable “viewport” est toujours initialisée avec getViewport() mais on passe un objet contenant les paramètres.
    • scale : l’échelle permettant de définir le zoom (ex: 1,5)
    • rotation : indique la rotation du document (0 = position initiale)
  • On définit toujours la hauteur et la largeur du canevas avec les valeurs du viewport.
  • On ajoute une petite option qui permet d’indiquer que la page doit être libérée et nettoyée après son rendu.
  • Petite nouveauté : l’utilisation de la méthode toBlob() dans les navigateurs qui supportent cela. Notez que si la méthode “msToBlob” existe alors on va plutôt appeler toDataUrl() pour la compatibilité avec IE.
    • On peut également déterminer le type de l’image.
    • On peut aussi indiquer la compression (ex : 0.85, 1 étant la qualité la plus élevée).

Grâce à ces modifications vous n’obtiendrez plus de message dans la console indiquant du code deprecated.

N’hésitez pas à partager votre expérience ou à suggérer des améliorations pour ce code !

[JS] Prism, une alternative à SyntaxHighlighter

[JS] Prism, une alternative à SyntaxHighlighter

En guise d’alternative au très bon SyntaxHighlighter développé par Alex Gorbatchev (voir le site ici) mais qui n’est malheureusement plus mis à jour, on peut utiliser Prism.js.

Il offre la coloration syntaxique pour afficher du code de manière à ce qu’il soit lisible par les utilisateurs. Il se veut intuitif et extensible car il est possible d’ajouter assez facilement des langages à ceux déjà pris en charge. On peut même basculer entre différents thèmes. La librairie est utilisée par de nombreux sites tels que React ou même Drupal.

Pour l’utiliser sur Blogger comme c’est mon cas, il faut importer les scripts et styles de base. Et pour cela il faut modifier le thème du blog. Depuis le tableau de bord de votre blog choisissez Thème puis cliquez sur Modifier le code HTML.

Juste avant l’élément fermant head du thème, il faut inclure les feuilles de style.

<link href='https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/themes/prism.css' rel='stylesheet'/>
<link href='https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/plugins/line-numbers/prism-line-numbers.css' rel='stylesheet'/>

De même qu’il faut inclure le script et l’autoloader avant la fermeture de l’élément body. On y ajoute aussi les différents plugins que l’on veut utiliser. Les éléments obligatoires sont prism-core et prism-autoloader.

<script src='https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/components/prism-core.min.js'/>
<script src='https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/plugins/autoloader/prism-autoloader.min.js'/>
<script src='https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/plugins/line-numbers/prism-line-numbers.min.js'/>

Ensuite on peut commencer à utiliser les blocs de code. Il faut utiliser les balises pre et code. La seconde prendra une classe qui sera le langage du code que l’on veut formater. La liste complète est disponible sur le site officiel. La classe peut être language-* ou lang-*, l’astérisque étant remplacée par le bon code pioché dans la liste.

<pre>
<code class="lang-html">
<!-- Code qu'on veut formater -->
</code>
</pre>

Il faut faire attention car il faut échapper les caractères du code à formater, sinon il sera évidemment interprété (très important donc si on veut afficher du HTML au lecteur).

Pour éviter de le faire à la main utilisez plutôt l’outil en ligne Quick Escape Tool.Petit truc supplémentaire avant de nous quitter : afin d’utiliser le plugin line-numbers (destiné à afficher les numéros de ligne) que nous avons importé dans le second exemple ci-dessus, il vous suffira d’ajouter la classe “line-numbers” à l’élément ouvrant pre. N’hésitez pas à consulter le site officiel : vous y découvrirez de nombreux plugins ainsi que des tutoriels.

Bon développement !

Prismjs.com

[JS] Afficher un PDF en image avec pdf.js

[JS] Afficher un PDF en image avec pdf.js

Il existe plusieurs méthodes en Java pour transformer un PDF (ou une partie seulement) en image côté serveur, afin de renvoyer le résultat au client, pour qu’il ne lui reste plus qu’à l’afficher. La première qui vient à l’esprit est Apache PDFBox. D’autres comme IcePDF ou JPedal font bien le job aussi, mais sont souvent payantes. De plus, le traitement peut évidemment vite devenir lourd pour le serveur si de nombreuses requêtes sont effectuées par plusieurs utilisateurs.

On peut imaginer laisser le client faire le boulot, en utilisant la librairie pdf.js, qui est sous licence Apache. Elle permet de visualiser des documents PDF dans une page web mais aussi de les transformer en image ce qui nous intéresse ici.

L’idée de l’exemple qui suit est de transformer une page donnée en image. Après ajout du script principal dans l’élément head, on va créer une fonction qui recevra plusieurs paramètres tels que les données du fichier PDF (sous forme de chaine encodée en Base64), le numéro de page à transformer, un ID pour la création du canvas, une valeur pour l’échelle du rendu, et l’identifiant de l’élément img qui recevra le résultat.

PDFJS.getDocument({data : atob(ao_pdfData)})
    .then(function(ao_pdf) 
{
 ao_pdf.getPage(ai_num).then(function(ao_page) 
 {
  var lo_canvas = document.createElement('canvas');
  lo_canvas.id = as_idd + '-page-' + ai_num;
  lo_canvas.className = 'f-canvas';

  var lo_context = lo_canvas.getContext('2d');
  var lo_viewport = ao_page.getViewport(af_scale2);
  lo_canvas.height = lo_viewport.height;
  lo_canvas.width = lo_viewport.width;
  
  var lo_renderContext = {
   canvasContext: lo_context,
   viewport: lo_viewport
  };

  ao_page.render(lo_renderContext).then(function()
  {
   $('#' + as_imageId)
     .attr("src", lo_canvas.toDataURL());
  });
 });
});

La fonction PDFJS.getDocument() reçoit en paramètre les données, décodées par la fonction JavaScript atob().

Une fois le document chargé, on va demander à récupérer la page dont le numéro est passé en paramètre. Une fois que cela est fait on exécute une fonction pour traiter les données de cette fameuse page. On crée un élément canvas temporaire, qu’on pourra stocker – ou pas – dans la page. On récupère aussi le contexte de dessin de ce canvas.

On récupère le viewport en indiquant l’échelle (ex : 1.5f). On définit ensuite la hauteur et la largeur du canvas avec les valeurs du viewport.

On crée ensuite un objet qui contiendra le contexte de dessin et le viewport. Ceux-ci seront passés à la fonction render() qui est une fonction de l’objet page. Lorsque le rendu est terminé, on peut récupérer la source de l’image depuis le canvas, grâce à la fonction toDataURL() de ce dernier.

[JS] JQuery – Mémo #2 – Requête AJAX

[JS] JQuery – Mémo #2 – Requête AJAX

JQuery vous permet d’effectuer facilement des requêtes AJAX. Par exemple:

$.ajax({
 type : "POST",
 url : "URL_A_APPELER",
 data : {
  param1: val_param1,
  param2: val_param2,
  // ...
 }
})
.done(function(data)
{
})
.fail(function(jqXHR, responseHtml, url)
{
});

Dans l’exemple on spécifie le type de requête, l’URL appelée, et les données envoyées. La fonction done() est exécutée lorsque la réponse est positive. L’objet “data” est alors un objet qui peut contenir du HTML notamment. La fonction fail() est exécutée quand la réponse du serveur est une erreur ou quand l’appel a échoué.

Dans JQuery 3, il ne faut plus utiliser les méthodes callback suivantes : error(), success() et complete().

La documentation officielle décrit les paramètres supplémentaires et l’utilisation des méthodes callback. Par exemple, on peut passer un objet dans “data” à la place des différents paramètres. Au niveau des options, on peut notamment spécifier async: false, pour forcer l’attente de la réponse. Les possibilités sont nombreuses.

[JS] Des infobulles avec Tooltipster 4

[JS] Des infobulles avec Tooltipster 4

Tooltipster est un script permettant d’afficher des infobulles modernes, bien plus “user-friendly” que ce que proposent les navigateurs. Il nécessite JQuery pour fonctionner (attention que sous IE9 avec JQuery version 1.8, cela ne fonctionnera tout simplement pas!)

Pour le télécharger, rendez-vous sur le site officiel (ici : http://iamceege.github.io/tooltipster/) et cliquez sur le bouton “Download“. Le sous-répertoire “dist” contient deux dossiers essentiels :

  • js : contient le script (format normal et format minified)
  • css : contient les feuilles de style (format normal et format minified) ainsi que les thèmes par défaut.

Il faudra ensuite l’inclure à la page :

<link rel="stylesheet" type="text/css" href="/tooltipster/css/tooltipster.bundle.css" /> 
<script type="text/javascript" src="/tooltipster/js/tooltipster.bundle.js"></script> 
<script type="text/javascript" src="https://code.jquery.com/jquery-x.xx.x.min.js"></script>

Après chargement du script, dans notre page nous allons placer des attributs “title” sur les éléments pour lesquels on veut avoir une infobulle. On va aussi leur assigner une classe, “tooltip“, mais on peut choisir un autre nom.

<img id="imgTest" src="test.jpg" class="tooltip" title="Le texte du tooltip" />

Lors du chargement de la page on doit initialiser les bulles.

<script>
     $(document).ready(function() {
          $('.tooltip').tooltipster();
     });
</script>

Par défaut la fonction tooltipster() ne reçoit aucun paramètre. Elle utilisera donc les options par défaut définies dans le fichier .js du script.

On peut notamment définir :

  • contentAsHTML : par défaut à false. Il est conseillé de stocker un objet JQuery dans le contenu. Sinon on peut passer la valeur à true et passer du texte au format HTML en appelant la méthode tooltipster().
  • delay : en millisecondes, délai après ouverture. On peut spécifier un
    tableau (par ex : [100, 2000]) ce qui correspondra alors au temps avant
    ouverture et au délai avant fermeture automatique).
  • position : attention aussi à la position ; seules 4 sont supportées (top, left, right et bottom). Dans les anciennes versions il existait plusieurs combinaisons mais cela a été supprimé.
  • theme : on peut définir un ou plusieurs thèmes à charger. Il faudra penser à charger les CSS quand cela s’applique.

Exemple de feuille de style dans le dossier “csspluginssideTipthemes” :

On peut aussi appeler la méthode tooltipster() en lui passant des options. Utile quand l’élément pour lequel on veut spécifier du texte, n’en a pas à la base.

$(SELECTOR).tooltipster({ 
	content: 'texte à placer', 
	maxWidth: 200 
});

Parmi les options que l’on peut spécifier il y a également divers événements, ce qui permet par exemple d’afficher un contenu récupéré grâce à une requête AJAX.

$(SELECTOR).tooltipster({ 
	delay: [200, 2000], 
	content: 'Chargement...', 
	functionBefore: function(instance, helper) 
	{ 
		if ($(helper.origin).data('ajax') !== 'loaded') 
		{
			$.ajax({ 
				type: 'POST', 
				url: 'action.php?param=', 
				success: function(data) 
				{
					instance.content(data); 
					$(helper.origin).data('ajax', 'loaded'); 
				}
			}); 
		} 
	} 
});

Ce qu’on a fait :

  • Appel de la fonction tooltipster().
  • On passe les différents arguments ; tout d’abord le délai (delay).
  • Ensuite on spécifie le contenu par défaut à afficher pendant l’appel AJAX (content).
  • Enfin on ajoute “functionBefore” : elle reçoit deux paramètres (instance et helper).
    • helper.origin : élément HTML sur lequel on définit le tooltip.
    • instance : objet Tooltipster qui appelle la fonction de callback.
    • La condition permet de savoir si l’élément a déjà été chargé ou pas (car on définit une donnée nommée “ajax” avec la valeur “loaded” une fois l’appel effectué).

Si un tooltip est déjà chargé, on peut effectuer diverses manipulations comme changer son contenu ou même le désactiver. On appelle la fonction tooltipster() avec comme premier argument, un nom de méthode (voir documentation). Les arguments suivants dépendent de la méthode appelée.

Exemple :

$(SELECTOR).tooltipster('content', 'nouveau contenu');

A noter que toute la documentation est disponible à l’adresse mentionnée au début de cet article.

[JS] Personnaliser la liste de styles dans tinyMCE

[JS] Personnaliser la liste de styles dans tinyMCE

Dans l’éditeur tinyMCE, lorsqu’on choisit de dérouler le menu de sélection du format, on dispose d’éléments par défaut comme les en-têtes (h1 à h6), l’alignement ou bien même la mise en forme classique comme le “gras”, “souligné” ou “italique”.

Ce menu peut être personnalisé de différentes manières. La méthode la plus simple reste de redéfinir les styles dans la méthode d’initialisation de l’éditeur. Dans notre cas cela écrasera les valeurs par défaut pour n’afficher que ce qu’on désire.

tinymce.init(
{
 // ...

 toolbar : [ "bold italic underline | styleselect" ]
 style_formats: [
  {title: 'Blocks', items: [
     {title: 'Paragraph', block: 'p'}
  ]},  
  {title: 'Headers', items: [
     {title: 'Header 1', block: 'h1'},
     {title: 'Header 2', block: 'h2'},
     {title: 'Header 3', block: 'h3'},
     {title: 'Header 4', block: 'h4'},
     {title: 'Header 5', block: 'h5'},
     {title: 'Header 6', block: 'h6'}
  ]},     
 ],
 
 // ...
});

Le fait de modifier le contenu de “style_formats” affecte la liste déroulante qui s’affiche quand on ajoute l’option “styleselect” dans la barre d’outils (cfr. paramètre “toolbar“). Vous constaterez également qu’il est possible de créer plusieurs niveaux (ce qui permet visuellement d’obtenir des sous-menus).

Le paramètre “title” est évidemment essentiel. On y met le texte qui sera affiché à l’utilisateur. Il sera automatiquement traduit en fonction de la langue choisie dans la configuration. Les fichiers de langue sont stockés dans un sous-dossier du répertoire de tinyMCE.

Les autres paramètres qu’on peut définir sont :

  • inline : indique le nom de balise inline qui sera utilisé comme conteneur.
  • block : indique le type de balise block qui sera utilisé comme conteneur.
  • selector : indique à quel élément cela peut s’appliquer.
  • classes : indique les classes à associer au résultat.
  • styles : pour générer du CSS pour l’élément

Des exemples sont disponibles dans la documentation officielle.

A lire aussi : content formatting

[Sécurité] Quel site fabrique de la cryptomonnaie?

[Sécurité] Quel site fabrique de la cryptomonnaie?

Il y a peu j’avais pu constater que certains sites (notamment des sites proposant du téléchargement illégal) utilisaient le moteur JavaScript du navigateur pour miner de la crypto-monnaie. C’est une pratique qui semble devenir… monnaie courante – pardon pour le jeu de mots – afin de générer des revenus. Cela vise à remplacer les bannières publicitaires. Le minage n’est pas toujours avantageux puisqu’il peut utiliser pas mal de ressources CPU de votre machine. Korben met en avant un site web intéressant pour vérifier où ce principe est appliqué. Il s’agit de Whoismining?

Saisissez l’adresse du site internet à vérifier et cliquez sur “Check“. Le résultat indique la méthode de fabrication, en analysant le script utilisé (ex : jsecoin, coinhive.com, etc). Vous pourrez donc savoir quels sont les coquins qui font craquer votre machine. Si vous êtes totalement contre cette pratique il n’est pas inutile d’employer des extensions comme Noscript. Cela bloquera l’exécution de ces scripts et donc, votre ordinateur restera tranquille !

Edition du 4 décembre 2017 : il semblerait que certains scripts ouvrent une fenêtre de votre navigateur en arrière-plan en positionnant celle-ci derrière la barre de tâches. Si la transparence est activée, vous pouvez facilement la repérer.

Sources

Korben

[JS] Recharger un TA tinyMCE après appel AJAX

[JS] Recharger un TA tinyMCE après appel AJAX

Pas plus tard qu’aujourd’hui j’ai été confronté à un petit problème de rafraichissement de mes champs textarea pour lesquels j’utilise l’éditeur tinyMCE 4, un éditeur WYSIWYG permettant de saisir du texte et de le transformer en code HTML.

En effet, après un appel AJAX qui ajoutait des éléments textarea dans mon code, je rappelais la fonction tinymce.init(). Sauf qu’il n’y avait alors que les nouveaux champs qui étaient chargés…

Pour que cela fonctionne, j’ai simplement ajouté ceci, à la fin d’un appel AJAX ayant abouti à la création des nouveaux champs :

function f_initMce() 
{ 
	// C'est cette ligne qui a été ajoutée :-) 
	tinymce.EditorManager.editors = []; 
	
	// Et là on initialise. 
	tinymce.init( {
		// General options. 
		selector : "textarea.myMceClass", 
		theme : "modern",
		plugins : "mucharactercount wordcount paste", ... 
	}); 
}

Et voilà : tous les éléments textarea sont alors transformés même après l’appel qui effectue l’ajout de nouveaux champs dans ma page.

Edit du 18/10/2017 : attention car cela peut poser quelques problèmes à d’autres niveaux, il vaut mieux supprimer proprement chacun des éditeurs avec la méthode remove. En cas d’exception englober dans un try/catch.

Exemple :

$('textarea').each(function() 
{ 
	var ed = tinymce.get($(this).attr('id'));
	if (ed != null) 
	{
		try 
		{ 
			tinymce.remove(ed); 
		} 
		catch (ex) 
		{ 
			delete tinymce.EditorManager.editors[ 
				$(this).attr('id')
			]; 
		} 
	} 
});

N’hésitez pas à réagir si cela ne vous parait pas correct ou si vous avez d’autres effets de bord que je n’aurais pas détecté.

[JS] JQuery – Mémo #1 – Sélecteurs

[JS] JQuery – Mémo #1 – Sélecteurs

Coché et sélectionné

On utilisera le sélecteur “:checked“. Exemple :

if($('#monChampId').is(':checked')) 
{ 
  ... 
}

A noter qu’on pourra utiliser “:selected” pour des listes déroulantes, dans la méthode find par exemple, ou directement comme sélecteur.

$("#maComboId option:selected").text();

Récupération du parent (méthode)

$('#formTest').parent()

Récupère le parent du niveau direct inférieur. On peut aussi spécifier un filtre en tant que paramètre de la fonction, pour s’assurer de la nature du parent choisi.

Sélection par classe

var champ = $('.classe1');

Sélection par ID

var champ = $('#idChamp');

Sélection de champs sur l’attribut name

$('element[name="VALUE"]')

On peut notamment utiliser :

  • ^= : commence par.
  • $= : termine par.
  • *= : contient.

La recherche peut être effectuée sur d’autres attributs (ex : id, type).

Traitement appliqué à X éléments

Utiliser la fonction find sur le parent (par exemple, un formulaire).

$('#formTest').find(
	'input[type=text].classe1, select.classe2'
)
.each(function() 
{ 
	// Traitement des champs 
	// (utiliser $(this) pour le champ parcouru). 
});

On peut envisager d’utiliser des sélecteurs qui contrôlent l’état.

$('#formTest').find(
	'select.classe2:visible:disabled, 
	input[type=radio]:not(:disabled)'
)
.each(function() { ... });

Ou même recherche sur un enfant…

$('#formTest').find(
	'div.classe1 > input[type=text]'
)
.each(function() { ... });

En savoir plus…

Les sélecteurs