Boutons pour textarea
30 septembre, 2005
- extensible : ajouter une fonctionnalité supplémentaire se fait par l’ajout de méthode à un objet.
- configurable : la définition de boutons et de sets de boutons se fait via une variable globale.
- non intrusif : un simple appel du script suffit à appliquer les améliorations sur les textareas de la page en fonction de leur class. {{{usage}}}
- appeler le script via <script>, dans <head> ou <body>.
- configurer le script via la variable ENHANCETEXTAREAS_CLASSES_ENHANCERS, un tableau de la forme ‘className’ => liste de definitions de boutons associés. Les boutons se definissent par une chaine ‘label|methode|arg1|arg2|etc’.
Tout textarea ayant pour classe l’une des clefs du tableau ENHANCETEXTAREAS_CLASSES_ENHANCERS se verra pourvu des boutons qu’elle définit. Seule la première classe trouvée sera prise en compte.
{{{principe}}}
Ce script est orienté objet. Pour chaque textarea à améliorer est créé un objet {{textareaEnhancer}} disposant d’une référence interne à l’objet DOM pour sa manipulation. Ces objets sont référencés par l’{{id}} du textarea dans le tableau global textareaEnhancers Des objets buttonSet et buttonSetItem sont également créés, ainsi qu’un
Les boutons se voient associés un evenement au clic, qui n’est autre que l’appel d’une methode de l’objet textareaEnhancer via le tableau textareaEnhancers.
Ce script nécessite la création d’attributs id automatiques aux textareas qui n’en seraient pas pourvus.
{{{méthodes disponibles}}}
- {{tagSelection}}(string before, string after): ajoute les arguments autour du texte selectionné.
- {{htmlTag}}(string tagName, [string attributeName, string attributeValue, string askMessage]…) : ajoute une balise html autour du texte selectionné. Au dela du premier, des triplets d’arguments sont attendus
- {{undoContentChange}}(void) : annule le dernier changement de contenu via newcontent
- {{newContent}}(string content): modifie le contenu du textarea
- {{swapView}}(void) : masque/affiche le textarea
{{{extensions potentielles}}}
- nettoyage du contenu via des expressions régulieres (suppression des balises)
- previsualisation du contenu en mode html (ce qui nécessite de construire un sous-arbre DOM a partir d’un noeud texte)
- verification orthographique
- etc
{{{code source}}}
/*
enhances textareas with buttons to tag their contents
creates 1 js textareaEnhancer object per textarea
*/
/* objects and methods
*/
// button constructor
function buttonSetItem(buttonSet,buttonDef) {
// referencing parent objects
this.buttonSet=buttonSet;
this.textareaEnhancer=this.buttonSet.textareaEnhancer;
// methods
this.setLabel=buttonSetItem_setLabel;
this.setBehavior=buttonSetItem_setBehavior;
// creating HTML DOM button
this.dom=document.createElement('input');
this.dom.setAttribute('type','button');
// referencing self in DOM object
this.dom.enhancer=this;
// parsing def
var def=buttonDef.split('|');
var label=def.shift();
var textareaEnhancerMethod=def.shift();
var args=def;
// autosetting
this.setLabel(label);
this.setBehavior(textareaEnhancerMethod,args);
}
function buttonSetItem_setLabel(label) {
return this.dom.setAttribute('value',label);
}
function buttonSetItem_setBehavior(textareaEnhancerMethod,args) {
var id=this.buttonSet.textareaEnhancer.id;
eval("var behavior=function() { return textareaEnhancers['"+id+"']."+textareaEnhancerMethod+"('"+args.join("','")+"');}");
this.dom.onclick=behavior;
return true;
}
// buttonSet constructor
function buttonSet(textareaEnhancer,bSetDef) {
// referencing parent object
this.textareaEnhancer=textareaEnhancer;
containerElement='div';
// creating HTML DOM button set
this.dom=document.createElement(containerElement);
this.dom.setAttribute('class','button-set');
// creating and appending buttons
this.buttons=new Array();
for (var i=0; i
bDef=bSetDef[i];
// alert(bDef['label']);
// button=textareaCreateButton(textarea,bDef);
var bt=new buttonSetItem(this,bDef);
this.buttons[i]=bt;
// appending button dom to self dom
this.dom.appendChild(bt.dom);
}
// alert('created buttonSet for textarea '+this.textareaEnhancer.id);
}
// textareaEnhancer constructor
function textareaEnhancer(textarea_ref, buttonSetDef) {
// properties
this.dom=textarea_ref;
this.id=textarea_ref.id;
// previous content array for undos
this.previousContents=new Array;
// show|preview|hide
this.view='show';
// methods
this.newContent=textareaEnhancer_newContent;
// action methods
this.tagSelection=textareaEnhancer_tagSelection;
this.undoContentChange=textareaEnhancer_undoContentChange;
this.swapView=textareaEnhancer_swapView;
this.htmlTag=textareaEnhancer_htmlTag;
this.insererLien=textareaEnhancer_insererLien;
// creating button set
this.buttonSet=new buttonSet(this,buttonSetDef);
// this.buttonSet.textareaEnhancer=this;
// appending button set dom to self dom
this.dom.parentNode.insertBefore(this.buttonSet.dom,this.dom);
}
function textareaEnhancer_newContent(content) {
this.previousContents.push(this.dom.value);
this.dom.value=content;
}
/* methodes "actions" des boutons
*/
function textareaEnhancer_tagSelection(before,after) {
//var before=args[0];
//var after=args[1];
var txtarea=this.dom;
var selLength = txtarea.textLength;
var selStart = txtarea.selectionStart;
var selEnd = txtarea.selectionEnd;
if (selEnd == 1 || selEnd == 2)
selEnd = selLength;
var s1 = (txtarea.value).substring(0,selStart);
var s2 = (txtarea.value).substring(selStart, selEnd)
var s3 = (txtarea.value).substring(selEnd, selLength);
//txtarea.value = s1 + before + s2 + after + s3;
this.newContent(s1 + before + s2 + after + s3);
return true;
}
// args : tagName [, attributeName, attributeValue, attributeAskMessage]*
function textareaEnhancer_htmlTag(tagName) {
var attributes='';
for (var i=1; i
// attributeName
attributeName=arguments[i]; i++;
attributeValue=arguments[i]?arguments[i]:''; i++;
askMessage=arguments[i]?arguments[i]:'';// i++;
if (askMessage)
attributeValue=window.prompt(askMessage,attributeValue);
if (attributeValue)
attributes=attributes+' '+attributeName+'="'+attributeValue+'"';
}
//alert(args);
var before='<'+tagName+attributes+'>';
var after=''+tagName+'>';
return this.tagSelection(before,after);
}
function textareaEnhancer_insererLien() {
var url=window.prompt('url ?','http://');
if (!url) return false;
var ext=window.confirm('Ouvrir dans une nouvelle fenetre ?');
var targ=ext?' target="_blank"':'';
var before='';
var after='';
return this.tagSelection(before,after);
}
function textareaEnhancer_undoContentChange() {
if (this.previousContents.length>0) {
this.dom.value=this.previousContents.pop();
return true;
} else {
alert("dernier niveau d'annulation");
return false;
}
}
function textareaEnhancer_swapView() {
switch(this.view) {
case 'show':
this.dom.setAttribute('style','display: none;');
this.view='hide';
break;
case 'hide':
default:
this.dom.setAttribute('style','display: block;');
this.view='show';
break;
}
}
/*function textareaEnhancer_showPreview() {
if (!this.previewDiv) {
this.previewDiv=document.createElement('div');
}
this.previewValue=document.createTextNode(this.dom.value);
this.previewDiv.appendChild(this.previewValue);
this.dom.append
}*/
/*function tagTextareaSelection(textareaId,textBefore,textAfter) {
alert(textareaId);
txtarea=document.getElementById(textareaId);
var selLength = txtarea.textLength;
var selStart = txtarea.selectionStart;
var selEnd = txtarea.selectionEnd;
if (selEnd == 1 || selEnd == 2)
selEnd = selLength;
var s1 = (txtarea.value).substring(0,selStart);
var s2 = (txtarea.value).substring(selStart, selEnd)
var s3 = (txtarea.value).substring(selEnd, selLength);
txtarea.value = s1 + open + s2 + close + s3;
return true;
}*/
/* generic functions required
*/
if (!window.autoIds) {
// auto id applying
function autoIds(tagName) {
tags=document.getElementsByTagName(tagName);
for (f=0; f
tag=tags[f];
if (!tag.id) {
newId=tagName+'_'+f;
//alert(newId);
tag.id=newId;
}
}
}
}
if (!window.hasClass) {
function hasClass(obj,cName) {
return new RegExp('\\b'+cName+'\\b').test(obj.className);
}
}
// addEvent
if (!window.addEvent) {
function addEvent(obj, evType, fn){
if (obj.addEventListener){
obj.addEventListener(evType, fn, false);
return true;
} else if (obj.attachEvent){
var r = obj.attachEvent("on"+evType, fn);
return r;
} else {
return false;
}
}
}
/* applying script
*/
var textareaEnhancers=new Array();
function summonTextareaEnhancers() {
// setting auto ids if necessary
autoIds('textarea');
// detecting all textareas
var textareas=document.getElementsByTagName('textarea');
//alert('detected '+forms.length+' forms');
for (f=0; f
var textarea=textareas[f];
var id=textarea.id;
classes=textarea.getAttribute('class');// alert(classes);
classes=classes.split(' ');
// searching for first class triggering an enhancer
var enhancerDef;
for (var g=0; g
className=classes[g];
if (ENHANCETEXTAREAS_CLASSES_ENHANCERS[className]) {
// found
var tEnhancer=new textareaEnhancer(textarea,ENHANCETEXTAREAS_CLASSES_ENHANCERS[className]);
// adding object to global array
textareaEnhancers[id]=tEnhancer;
break;
}
}
}
}
addEvent(window,'load',summonTextareaEnhancers);
Les Gobelins
27 septembre, 2005
Ici un descriptif de l’école.
L’étrange Tim Burton
26 septembre, 2005
Ici une description du projet.
{{{Equipe}}}
[Promotion ARM2 2001->article10]
- [Olivier Cazagou->auteur7] : Graphisme
- feu Thomas-Mary Delest : Développement Flash/Director
- [Lisa-Joan Etcheberry->auteur5] : Développement Director
- [Adrien Menielle->auteur8] : Vidéo
Assistant Réalisateur Multimedia
26 septembre, 2005
Formation disparue avec la bulle Internet de 2001… Ici une description de la formation.
La Compagnie Noire
26 septembre, 2005
Le narrateur est le medecin et annaliste de la Compagnie noire, dernière compagnie franche de Khatovar. Il s’agit d’une troupe de mercenaires se déplaçant au gré des contrats, et ce depuis tellement longtemps que pas mal d’annales ont été perdues et qu’ils ont tous oublié ce que pouvait bien être Khatovar…
Enfin bref, c’est des durs à cuire, une belle brochette de salauds, usant de la fourberie et de la ruse presque aussi souvent que de l’épée. Voilà qu’au terme d’un contrat foireux, ils se retrouvent engagés presque à leur insu au service de la Dame, impératrice regnant sur un empire immense d’une main de fer.
A coté de la Dame, Dark Vador c’est un toréro en collants roses. Son mari, le Dominateur, regnait autrefois sur un empire encore plus grand et implacable, mais il est encore pris au piège du tombeau où on l’a enfermé vivant, 400 ans auparavant. La Dame elle, s’en est echappé, et a pris soin de l’y laisser croupir. Mais elle en a profité pour récupérer les 10 Asservis, de très puissants sorciers que le Dominateur avait plié à sa volonté.
C’est l’un de ces asservis, Volesprit, qui a engagé la Compagnie Noire comme son armée personnelle. La bataille fait rage entre l’empire de la Dame et les rebelles de la Rose Blanche, ainsi nommé en mémoire de la stratège qui avait autrefois réussi à renverser le dominateur. Mais les luttes de pouvoir sévissent aussi entre les asservis, car le sortilège les asservissant à la Dame ne les empêche pas de se friter entre eux, et ils ne s’en privent pas…
Dead Man
26 septembre, 2005
Dead Man, 1995, écrit et réalisé par Jim Jarmusch. Avec Johnny Depp, Gary Farmer, Iggy Pop…
Porté graphiquement par le noir et blanc, par la bande son magnifique de Neil Young, ce film est beau. A vrai dire, c’est presque un clip long métrage. On le traverse comme dans un tunnel hors de la réalité.
Certains ont vu en Dead Man l’histoire d’un homme mort, Johnny Depp, alias William Blake, tué au début du film et qui balade sa carcasse dans l’Ouest Américain du dix-neuvième siècle, celui de la fameuse frontière sans cesse repoussée par les pionniers. Ayant pris le train jusqu’à la ville de Machine, le terminus, sur un malentendu, il encaisse par hasard une balle dans la poitrine, puis est recueilli par un Indien sang-mêlé qui se fait appeler Personne. Personne voit en lui la réincarnation du poète William Blake, qu’il admire depuis son voyage forcé en Angleterre.
Que la balle lui ait ou non été fatale, je ne vois pas en lui le mort qui donne son titre au film. Ce qui est mort, c’est l’humanité de l’Occident, dont la sauvagerie sans fard tache la pellicule du début à la fin et lui donne son étrangeté. Des hordes barbares ont déferlé sur le continent Américain, y ont anéanti toute civilisation pour y semer leur chaos. En contraste, le cultivé Personne vagabonde avec son protégé dans les ruines de sa terre. Il y voit dans William Blake le fantôme de l’humanité de l’Occident, cette part qu’il a aimé et intégré, et delà de son admiration pour le poète disparu, il place dans sa supposé réincarnation l’espoir d’une vengeance, d’une victoire de la civilisation sur la barbarie. Ce dernier, finalement aussi dérouté que Personne par l’absurdité du monde des blancs, accepte d’écrire sa nouvelle poésie de poudre et de sang.
Mais les morts s’entassent inutilement dans un combat perdu d’avance.
…
lire [une critique sur mouton-rebelle->http://www.mouton-rebelle.com/Dead-man.html]
Le maître des Illusions
26 septembre, 2005
Voici le prologue. Je ne pense pas qu’une critique soit plus efficace pour vous donner envie de le lire.
La neige fondait dans la montagne et Bunny était mort depuis plusieurs semaines quand nous avons fini par comprendre la gravité de notre situation. Il était mort depuis dix jours quand on l’a trouvé, vous savez. Ce fut l’une des plus grandes chasses à l’homme de l’histoire du Vermont – la police fédérale, le FBI, même un hélicoptère de l’armée; l’université a fermé, l’usine de teinture de Hampden s’est arretée, des gens sont venus du New Hampshire, du nord de l’état de New York et même de Boston.Il est difficile de croire que le modeste plan de Henry ait pu si bien marcher malgré ces evenements imprévus. Nous n’avions pas eu l’intention de cacher le corps là où on ne l’aurait pas retrouvé. En fait, nous ne l’avions pas du tout caché, mais simplement laissé là où il était tombé dans l’espoir qu’un passant infortuné tomberait dessus avant qu’on ait même remarqué son absence. L’histoire se racontait d’elle même, simple et évdiente : les cailloux instables, le corps au fond du ravin avec le cou cassé, les traces boueuses des talons glissant vers le bas; un accident de randonnée, ni plus ni moins, et ç’aurait pu en rester là, quelques larmes et une petite cérémonie, sans la neige qui est tombé cette nuit là elle l’a recouvert, et dix jours plus tard, quand le dégel a fini par venir, la police fédérale, le FBI et les sauveteurs de la ville ont tous vu qu’ils avaient marché à l’endroit de son corps jusqu’à ce que la neige soit tassée comme de la glace.
Il est difficile de croire qu’il y ait eu un tel tapage à propos d’un acte dont j’étais partiellement responsable, encore plus difficile de croire que j’ai pu traverser tout cela – les caméras, les uniformes, les foules noires grouillant sur le mont Cataract comme des fourmis dans un bol de sucre – sans être le moins du monde soupçonné. Mais le traverser était une chose; en sortir, malheureusement, s’est avéré très différent, et bien que j’ai cru un moment avoir quitté à jamais ce ravin lors d’un après midi d’avril, il y a bien longtemps, je n’en suis plus tellement certain. Maintenant que les sauveteurs sont partis, que la vie autour de moi a retrouvé son calme, je me suis rendu compte que si pendant des années j’ai pu imaginer que j’étais ailleurs, en réalité j’y étais resté tout ce temps : là haut, près des ornières boueuses dans l’herbe nouvelle, là où le ciel s’assombrit au dessus des fleurs frémissantes des pommiers et où on sent déjà dans l’air le premier frisson de la neige qui va tomber à la nuit.
« Qu’est ce que vous faites ici ? » a dit Bunny, surpris, quand il nous a trouvé tous les cinq en train de l’attendre.
« Oh, on cherche des fougères », a dit Henry.Après que nous avons chuchoté dans les broussailes – un dernier regard au corps et tout autour, pas de clefs tombées par terre, de lunettes perdues, tout le monde a tout ? – et que nous sommes repartis en file indienne dans la forêt, j’ai jeté un coup d’oeil à travers les branches qui se redressaient pour refermer la piste derrière moi. Bien que je me souvienne de notre retour et des premiers flocons de neige isolés qui flottaient au bas des pins, de m’être enfourné avec soulagement dans la voiture et d’avoir pris la route comme une famille en vacances, avec Henry qui conduisait mâchoires serrées dans les nids de poule et nous autres penchés sur les sièges en train de parler comme des enfants, bien que je ne me souvienne que trop bien de la longue et terrible nuit qui nous attendait et des jours longs et terribles qui ont suivi, je n’ai qu’a regarder en arrière pour que toutes ces années s’effacent et que je le revoie derrière moi, ce ravin, vert et noir à travers les branches, une image qui ne me quittera jamais. Je suppose qu’à un autre moment de ma vie j’aurais pu avoir bien d’autres histoires en réserve, mais maintenant il n’y en a plus qu’une. C’est la seule histoire que je serais jamais capable de raconter.
Listes de selection pour champ texte
25 septembre, 2005
Ce script permet d’utiliser des listes de selection pour définir la valeur de champs texte. C’est utile lorsque vous voulez suggérer des valeurs tout en laissant libre choix à l’utilisateur. {{{Usage}}}
Appeler simplement le script dans la page. Tout élément {{select}} ayant une {{id}} de la forme {machinchose_selector} se comportera comme le selecteur de l’élément input ayant l’id {machinchose}.
{{{Dépendance}}}
Nécessite également l’appel de [cssFunctions->1]
{{{code source}}}
/*
this script auto-detect all select fields with class 'selector' and id like something_selector,
associates it with the text field with id 'something' so that onchange value of the select is applied to the text field
http://fredbird.org
License : public domain
*/
// copy value of objectFrom to objectTo
function copyValue(objectFrom,idObjectTo) {
objectTo=document.getElementById(idObjectTo);
if (!objectTo) return false;
objectTo.value=objectFrom.value;
return true;
}
function selectorValueToTarget(selector) {
var reg=new RegExp("(_selector)");
target_id=selector.id.replace(reg,'');
if (targetElement=document.getElementById(target_id)) {
targetElement.value=selector.value;
}
}
function selectorLabelToTarget(selector) {
var reg=new RegExp("(_selector)");
target_id=selector.id.replace(reg,'');
if (targetElement=document.getElementById(target_id)) {
// getting selected option label
// alert(selector.selectedIndex);
option=selector.options[selector.selectedIndex];
// alert (option.text);
targetElement.value=option.text;
}
}
// detects pairs selector // target within a form
function setSelectors(form) {
// value selectors
selects=getElementsByClassName('selector',document,'select');
for (var f=0; f
selector.onchange=function() {selectorValueToTarget(this); return false;}
}
// label selectors
selects=getElementsByClassName('label-selector',document,'select');
for (var f=0; f
selector.onchange=function() {selectorLabelToTarget(this); return false;}
}
}
/* detects all selectors and set their behavior
*/
/*function setSelectors() {
//alert('setSelectors !');
forms=document.getElementsByTagName('form');
for (var f=0; f
}
}*/
// applying to page
if (!window.addEvent) {
function addEvent(obj, evType, fn){
if (obj.addEventListener){
obj.addEventListener(evType, fn, false);
return true;
} else if (obj.attachEvent){
var r = obj.attachEvent("on"+evType, fn);
return r;
} else {
return false;
}
}
}
addEvent(window,'load',setSelectors);
Fonctions CSS javascript
25 septembre, 2005
Voici quelques fonctions javascript pour manipuler les propriétés CSS. C’est à dire, les attributs class et id des objets du DOM. – bool hasClass(DOM obj, string className)
- bool hasClasses(DOM obj, array classes)
- bool addClass(DOM obj, string className)
- bool removeClass(DOM obj, string className)
- bool swapClasses(DOM obj, string class1, string class2)
- bool switchClass(DOM obj, string to, string from)
- array getElementsByClassName(string className, [DOM container],[string tag])
/* CSS-related javascript functions
by Fred Bird http://fredbird.org
License : Public Domain
file version 16/09/2005 09:30:45
*/
/* has the DOM object a certain class ?
obj = DOM object, cName = a class name
*/
function hasClass(obj,cName) {
return new RegExp('\\b'+cName+'\\b').test(obj.className);
}
/* has the DOM object a set of classes ?
obj = DOM object, classes=array of class names
*/
function hasClasses(obj,classes) {
for (f=0; f<classes.length; f++) {
if (!hasClass(obj,classes[i])) return false;
}
return true;
}
/* add a class to a DOM object if necessary
obj = DOM object, cName = a class name
*/
function addClass(obj,cName) {
if (!hasClass(obj,cName)) {
obj.className+=obj.className?' '+cName:cName;
}
return true;
}
/* removes a class from a DOM object
obj = DOM object, cName = a class name
*/
function removeClass(obj,cName) {
if (!hasClass(obj,cName)) return false;
var rep=obj.className.match(' '+cName)?' '+cName:cName;
obj.className=obj.className.replace(rep,'');
return true;
}
/* swap two classes for a DOM object, whatever provided order
*/
function swapClasses(obj,class1,class2) {
if (hasClass(obj,class1)) {
removeClass(obj,class1);
addClass(obj,class2);
return true;
}
if (hasClass(obj,class2)) {
removeClass(obj,class2);
addClass(obj,class1);
return true;
}
return false;
}
/* sets class 'to' to the DOM object obj, removes class 'from' if necessary
*/
function switchClass(obj,to,from) {
if (hasClass(obj,from)) removeClass(obj,from);
addClass(obj,to);
return true;
}
/* returns an array of DOM objects having the provided class name
within object 'container' and with tag name 'tag'
some code from http://www.webmasterworld.com/forum91/1757.htm (unbugged)
*/
function getElementsByClassName(className,container,tag) {
// default container to document
container=container||document;
// default tag to *
tag=tag||'*';
// listing container descendants
var all = container.all||container.getElementsByTagName(tag);
var found=new Array();
// searching for targets
for (f=0; f<all.length; f++) {
var el=all[f];
if (hasClass(all[f],className)) {
found.push(all[f]);
}
}
return found;
}