cyrilleinvalides/choupas/www/admin/editor/scripts/richTextarea.js

506 lines
14 KiB
JavaScript
Executable File

/*
richTextarea {
methodes {
constructeur : crée l'objet
addToHistory : ajoute la valeur courante du champ à l'historique
historyNext : va à la prochaine valeur dans l'historique relativement à la courante.
historyBack ; va à la precedente valeur relativement à la courante.
insert(str) : insere la chaine str à la position du curseur ou à la fin de la selection
checkKeysAction : verifie si une action a été definie pour la combinaison de touche.
addShortKey(ctrl, alt, shift, key) : ajoute un raccourci clavier ou le remplaçe si existant ;)
}
proprietes {
scrollPos : position du scroll à backup avant la perte du focus
cursorStartPos : position de debut de selection ou curseur à backup avant la perte du focus
cursorEndPos : position de fin de selection ou curseur à backup avant la perte du focus
history : tableau de chaine, historique des valeurs successive du textarea
cursorHistory : tableau d'entiers, historique des positions successive du curseur
scrollHistory : tableau d'entiers, historique des positions successive du scroll
currentInHistory : position actuelle au sein de l'historique
keysAction : tableau de touche de raccourcis. Il est de la forme :
keysAction[ctrlKey][altKey][shiftKey][keyCode] = functtion {};
}
evenements {
onvaluechange : evenement declancher à la modification du champs, preferable à onchange.
}
raccourcis {
CTRL + Z : annuler derniere action
CTRL + Y : refaire action
CTRL + D : dupliquer la ligne ou la selection courante
TAB : insert une tabulation
RETURN : saut à la ligne en ajoutant les tabulation de debut de ligne selon le contexte.
HOME : retour au debut de la ligne, ou au debut apres les indentations.
CTRL + M : ouvre un prompt et cherche l'expression retournée.
CTRL + SHIT + M : cherche la prochaine occurence entrée dans le prompt
CTRL + / : ouvre un prompt et va à la ligne indiquee.
ALT + P : indique la ligne.
}
}
*/
/*************************************************************************************************/
/* Modification de l'objet window pour ne pas provoquer de conflits entre les raccourcis clavier */
/*************************************************************************************************/
/*
window.keysAction = new Array();
var wkA = window.keysAction;
for(var i = 0; i < 2; i++) {
wkA[i] = new Array();
for(var j = 0; j < 2; j++) {
wkA[i][j] = new Array();
for(var k = 0; k < 2; k++) {
wkA[i][j][k] = new Array(0);
}
}
}
window.checkKeysAction = function (e) {
var ctrl = 0;
var alt = 0;
var shift = 0;
var keyCode = 0;
var kA = this.keysAction;
if (e.ctrlKey) var ctrl = 1;
if (e.altKey) var alt = 1;
if (e.shiftKey) var shift = 1;
if (e.keyCode) var keyCode = e.keyCode;
if ( !kA ||
!kA[ctrl] ||
!kA[ctrl][alt] ||
!kA[ctrl][alt][shift] ||
!kA[ctrl][alt][shift][keyCode]
) {
return true;
} else {
e.preventDefault();
e.returnValue = false;
return false;
}
};
window.addEventListener('keydown', window.checkKeysAction, true);
*/
/*****************************************************/
/* Fonction de création des instance de richTextarea */
/*****************************************************/
function richTextarea (span) {
/* Creation de l'element DOM */
var rTa = document.createElement('textarea');
/**************************************/
/* definition des nouvelle proprietes */
/**************************************/
rTa.scrollPos = 0;
rTa.cursorStartPos = 0;
rTa.cursorEndPos = 0;
rTa.history = new Array();
rTa.scrollHistory = new Array();
rTa.cursorHistory = new Array();
rTa.currentInHistory = 0;
rTa.keysAction = new Array();
rTa.lookForMatches = new Array();
rTa.lookForPos = 0;
rTa.lookForCursorPos = 0;
rTa.lookForExp = '';
/********************************************/
/* declaration de l'evenement onvaluechange */
/********************************************/
rTa.onvaluechange = null;
/************************************************************************/
/* affectation de la structure "à la xPath" pour les raccourcis clavier */
/************************************************************************/
var kA = rTa.keysAction;
for(var i = 0; i < 2; i++) {
kA[i] = new Array();
for(var j = 0; j < 2; j++) {
kA[i][j] = new Array();
for(var k = 0; k < 2; k++) {
kA[i][j][k] = new Array(0);
}
}
}
/******************************************/
/* initialisation des ctrl + z / ctrl + y */
/******************************************/
rTa.history[0] = '';
rTa.scrollHistory[0] = 0;
rTa.cursorHistory[0] = 0;
/****************************/
/* affectation des methodes */
/****************************/
/* historique */
rTa.addToHistory = function () {
if (this.history[this.currentInHistory] == this.value) return false;
this.currentInHistory++;
var cI = this.currentInHistory;
while ( cI < this.history.length - 1 ) this.history.pop();
this.history[cI] = this.value;
this.cursorHistory[cI] = this.selectionStart;
this.scrollHistory[cI] = this.scrollTop;
return true;
};
rTa.historyNext = function () {
if ( this.currentInHistory < (this.history.length - 1) ) this.currentInHistory++;
var cI = this.currentInHistory;
var sR = this.cursorHistory[cI];
this.value = this.history[cI];
this.scrollTop = this.scrollHistory[cI];
this.setSelectionRange(sR, sR);
return true;
};
rTa.historyBack = function () {
if ( this.currentInHistory > 0 ) this.currentInHistory--;
var cI = this.currentInHistory;
var sR = this.cursorHistory[cI];
this.value = this.history[cI];
this.scrollTop = this.scrollHistory[cI];
this.setSelectionRange(sR, sR);
return true;
};
/* insertion dans le champ */
rTa.insert = function (str, pos) {
var start = pos?pos:this.selectionStart;
var end = pos?pos:this.selectionEnd;
var scrollPos = this.scrollTop;
var lg = str.length;
this.value = this.value.substring(0, end) + str + this.value.substring(end);
this.setSelectionRange(start + lg, end + lg);
this.addToHistory();
this.scrollTop = scrollPos;
this.focus();
return true;
};
rTa.replace = function (str, near, next) {
var start = near || this.selectionStart;
var end = next || this.selectionEnd;
var scrollPos = this.scrollTop;
this.value = this.value.substring(0, start) + str + this.value.substring(end);
this.setSelectionRange(start, start + str.length);
this.addToHistory();
this.scrollTop = scrollPos;
}
/**** BEGIN WOP ****/
/*
rTa.inserto = function (str, pos) {
var start = pos || this.selectionStart;
var trueStart = this.selectionStart;
var end = this.selectionEnd;
var scrollPos = this.scrollTop;
this.value = this.value.substring(0, start) + str + this.value.substring(start);
this.setSelectionRange(trueStart, end);
this.addToHistory();
this.scrollTop = scrollPos;
return true;
}
*/
/**** END WOP ****/
/* Execute la fonction liée à un raccourcis clavier */
rTa.checkKeysAction = function (e) {
var ctrl = 0;
var alt = 0;
var shift = 0;
var keyCode = 0;
var kA = this.keysAction;
if (e.ctrlKey) var ctrl = 1;
if (e.altKey) var alt = 1;
if (e.shiftKey) var shift = 1;
if (e.keyCode) var keyCode = e.keyCode;
if ( !kA ||
!kA[ctrl] ||
!kA[ctrl][alt] ||
!kA[ctrl][alt][shift] ||
!kA[ctrl][alt][shift][keyCode]
) return false;
e.preventDefault();
return kA[ctrl][alt][shift][keyCode](e);
};
/* Ajoute un raccourcis clavier */
rTa.addShortKey = function (ctrl, alt, shift, key, action) {
rTa.keysAction[ctrl][alt][shift][key] = action;
//window.keysAction[ctrl][alt][shift][key] = 1; // Bloque le raccourcis de browser au passage ;)
};
/******************************/
/* affectation des evenements */
/******************************/
rTa.onblurev = function () {
this.cursorStartPos = this.selectionStart;
this.cursorEndPos = this.selectionEnd;
};
rTa.onfocusev = function () {
this.scrollTop = this.scrollPos;
this.setSelectionRange(this.cursorStartPos, this.cursorEndPos);
};
rTa.onkeydownev = function (event) {
if (this.value != this.valueBefore) {
this.addToHistory();
this.valueBefore = this.value;
}
return !this.checkKeysAction(event);
};
rTa.onkeyupev = function (event) {
if ( this.value != this.valueBefore && !this.historyNavigate ) this.addToHistory();
if ( this.value != this.valueBefore && this.onvaluechange ) this.onvaluechange(event);
this.historyNavigate = false;
this.valueBefore = this.value;
//span.innerText = this.getPos();
};
rTa.onwheel = function () {
this.scrollPos = this.scrollTop;
}
rTa.addEventListener('blur', rTa.onblurev, false);
rTa.addEventListener('focus', rTa.onfocusev, false);
rTa.addEventListener('keydown', rTa.onkeydownev, false);
rTa.addEventListener('keyup', rTa.onkeyupev, false);
rTa.addEventListener('scroll', rTa.onwheel, false);
/*******************************************************/
/* definition des fonction pour les raccourcis de base */
/*******************************************************/
rTa.enter = function (e) { //touche entrer
var lignes = rTa.value.substring(0, rTa.selectionStart).split("\n");
var ligne = lignes[lignes.length - 1];
var exp = /^[\t *]*/g;
var tab = ligne.match(exp);
return rTa.insert("\n" + tab);
};
rTa.duplicate = function (e) { //touche CTRL + D
var st = rTa.selectionStart;
var en = rTa.selectionEnd;
if (st == en) {
var lignes = rTa.value.substring(0, st).split("\n");
var et = rTa.value.substring(st).split("\n");
var endligne = '';
if (et[0]) endligne = et[0];
var ligne = endligne + "\n" + lignes[lignes.length - 1];
} else {
var ligne = rTa.value.substring(st, en);
}
rTa.scrollTop += 20 * ((ligne.match("\n")?ligne.match("\n").length:0.5));
return rTa.insert(ligne);
};
rTa.undo = function (e) { //touche CTRL + Z
return rTa.historyBack();
};
rTa.redo = function (e) { //touche CTRL + Y
return rTa.historyNext();
};
rTa.tab = function (e) { //touche TAB
return rTa.insert("\t");
};
/**** BEGIN WOP **** /
rTa.tabo = function(e) {
if (rTa.selectionStart == rTa.selectionEnd) return rTa.insert("\t");
var count = rTa.value.substring(rTa.selectionStart, rTa.selectionEnd).split("\n");
var ret = true;
var pos = 0;
var tot = 0;
for ( var i = 1; i < count.length - 1; i++) {
pos = rTa.selectionStart + tot;
alert(pos);
tot += count[i].length + 1;
ret = ret && rTa.inserto("\t", pos);
}
return ret;
}
/**/
rTa.taba = function () {
var start = rTa.selectionStart;
var end = rTa.selectionEnd;
if (start == end) return rTa.insert("\t");
return rTa.replace(rTa.value.substring(start, end).replace(/\n/g, "\n\t"));
}
/**** END WOP ****/
rTa.startPos = function (e) { // HOME
var sS = rTa.selectionStart;
var lignes = rTa.value.substring(0, sS).split("\n");
var endligne = rTa.value.substring(sS).split("\n")[0];
var ligne = lignes[lignes.length - 1];
var exp = /^[\t|| ]*/g;
var nP = 0;
if (ligne.length == 0) {
var tmp = endligne.match(exp)?endligne.match(exp)[0].length:0;
nP = sS + tmp;
} else {
nP = sS - ligne.length;
}
rTa.setSelectionRange(nP, nP);
return true;
}
rTa.goTo = function (e) { // CTRL + / aller à la ligne numreo ...
var line = prompt("Aller à la ligne numéro : ");
if (!line) return true;
var z = rTa.value;
var lines = z.split("\n");
var k = 0;
for (var i = 0; i < line - 1; i++) {
k += lines[i].length + 1;
}
a = lines[line - 1].length;
rTa.scrollTop = rTa.scrollHeight * (line / lines.length) - 100;
rTa.setSelectionRange(k, k + a);
return true;
}
rTa.find = function () { // CTRL + M cherche la regex ...
rTa.lookForExp = prompt("Rechercher l'expression suivante : ", rTa.lookForExp);
var expi = new RegExp(rTa.lookForExp, 'g');
rTa.lookForMatches = rTa.value.match(expi);
rTa.lookForPos = 0;
rTa.lookForCursorPos = 0;
rTa.findNext();
return true;
}
rTa.findNext = function () { // CTRL + SHIFT + M cherche la regex suivante.
if (!rTa.lookForMatches || !rTa.lookForMatches.length) {
alert('Pas de correspondances trouvées');
return false;
}
if (rTa.lookForPos >= rTa.lookForMatches.length) {
alert('Fin du document, retour au debut');
rTa.lookForPos = 0;
rTa.lookForCursorPos = 0;
}
var mt = rTa.lookForMatches[rTa.lookForPos];
var st = rTa.value.indexOf(mt, rTa.lookForCursorPos);
var x = rTa.value.substring(0, st).split("\n").length;
var y = rTa.value.split("\n").length;
rTa.scrollTop = rTa.scrollHeight * (x / y) - 100;
rTa.setSelectionRange(st, st + mt.length);
rTa.lookForCursorPos = st + 1;
rTa.focus();
rTa.lookForPos++;
return true;
}
rTa.getPos = function () {
var a = rTa.value.substring(0, rTa.selectionStart).match(/\n/g);
if (!a)
a = 0;
else
a = a.length;
return a;
}
rTa.alertPos = function () {
alert(this.getPos());
}
/********************************/
/* ajout des raccourcis de base */
/********************************/
// CTRL ALT SHIFT KeyCode
rTa.addShortKey(1, 1, 0, 90, rTa.undo); // CTRL + ALT + Z
rTa.addShortKey(1, 1, 0, 89, rTa.redo); // CTRL + ALT + Y
rTa.addShortKey(1, 0, 0, 68, rTa.duplicate); // CTRL + D
rTa.addShortKey(0, 0, 0, 9, rTa.taba); // TAB
rTa.addShortKey(0, 0, 0, 13, rTa.enter); // RETURN
rTa.addShortKey(0, 0, 0, 36, rTa.startPos); // HOME
/* rTa.addShortKey(1, 0, 0, 191, rTa.goTo); // CTRL + / ou CTRL + : sous windows
rTa.addShortKey(1, 0, 0, 59, rTa.goTo); // CTRL + / ou CTRL + : sous ubunutu kde4 */
rTa.addShortKey(1, 0, 0, 77, rTa.find); // CTRL + M rechercher
rTa.addShortKey(1, 0, 1, 77, rTa.findNext); // CTRL + SHIFT + M rechercher suivant
rTa.addShortKey(1, 1, 0, 80, rTa.alertPos); // ALT + P : indique la ligne
return rTa;
}