Plus pratique, plus rapide et bien plus simple que les éventuelles solutions classiques de test et de remplacement, les expressions régulières, popularisées par le langage Perl, sont la solution idéale pour vos manipulations de texte. Voici un exemple d’utilisation d’expression régulière pour remplacer toutes les URL dans un texte par un lien correctement formé.

Lire la suite de cet article »

Description d’une technique anti-spam, le « plus-addressing », qui a malheureusement ses limites car la plupart des sites Web ne respectent pas complètement les normes.
Vous connaissez probablement la fonctionnalité appelée « [plus-addressing->http://en.wikipedia.org/wiki/E-mail_address#Plus_.28or_Minus.29_addressing]« [[Il existe aussi le minus-addressing, qui utilise le signe moins, principalement utilisé avec le serveur mail Qmail]] qui consiste à ajouter un signe plus « + » à la suite de votre identifiant, juste avant l’arrobas, dans votre adresse email. Elle a été popularisé par [Google->http://www.google.com/] avec ses comptes [gmail->http://mail.google.com/].
Par exemple, si vous avez une adresse toto@gmail.com, vous pouvez aussi utiliser toutes les variantes du type toto+[un truc]@gmail.com car les messages arriveront dans votre boite toto@gmail.com.

Lire la suite de cet article »

Codes de réponse HTTP

9 novembre, 2005

| {{code}} | {{signification}} |
| 100 | Continue |
| 101 | Switching Protocols |
| 200 | OK |
| 201 | Created |
| 202 | Accepted |
| 203 | Non-Authoritative Information |
| 204 | No Content |
| 205 | Reset Content |
| 206 | Partial Content |
| 300 | Multiple Choices |
| 301 | Moved Permanently |
| 302 | Found |
| 303 | See Other |
| 304 | Not Modified |
| 305 | Use Proxy |
| 307 | Temporary Redirect |
| 400 | Bad Request |
| 401 | Unauthorized |
| 402 | Payment Required |
| 403 | Forbidden |
| 404 | Not Found |
| 405 | Method Not Allowed |
| 406 | Not Acceptable |
| 407 | Proxy Authentication Required |
| 408 | Request Time-out |
| 409 | Conflict |
| 410 | Gone |
| 411 | Length Required |
| 412 | Precondition Failed |
| 413 | Request Entity Too Large |
| 414 | Request-URI Too Large |
| 415 | Unsupported Media Type |
| 416 | Requested range not satisfiable |
| 417 | Expectation Failed |
| 500 | Internal Server Error |
| 501 | Not Implemented |
| 502 | Bad Gateway |
| 503 | Service Unavailable |
| 504 | Gateway Time-out |
| 505 | HTTP Version not supported |

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

contenant les boutons juste avant le <textarea>.
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='';
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);

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=selects[f];
selector.onchange=function() {selectorValueToTarget(this); return false;}
}
// label selectors
selects=getElementsByClassName('label-selector',document,'select');
for (var f=0; f selector=selects[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 pairs=detectFormSelectors(forms[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;
}

RSS | XHTML | CSS