[PLUGINS] +crayons et enluminures
[ptitvelo/web/www.git] / www / plugins / enluminures_typographiques_v3 / editeur / table.js
1 /* ce code s'inspire du travail de http://www.spip-contrib.net/_courcy_
2 * il a été en grande partie ré-écrit pour :
3 * - générer une syntaxe de tableau SPIP et non HTML (l'éditeur de couleur de cellules disparaît donc aussi)
4 * - pour permettre non seulement de créer un tableau mais aussi de modifier un tableau existant
5 * - pour intégrer les éléments HTML titre et résumé de tableau
6 */
7 /******************************************
8 * FONCTIONNEMENT Général
9 *********************BUT****************************************
10 * Le but de ce script est de permettre à l'utilisateur de créer son propre
11 * tableau sans s'encombrer de la syntaxe SPIP. Si un tableau à syntaxe SPIP est
12 * sélectionné avant l'appel de l'assistant, les données sont récupérées par l'assistant.
13 * Si rien n'est sélectionné l'appel de l'assistant, un nouveau tableau est créé au point
14 * d'insertion.
15 ************Structure de donnees ***********************************
16 *
17 * Classe ihm qui gère l'interface homme-machine de l'assistant et sa construction
18 * On trouve en autres les méthodes permettant d'insérer et de supprimer lignes et colonnes
19 *
20 * Classe Cellule qui contient les informations relatives à une cellule
21 * Ses attributs sont des informations relatives a une cellule (contenu)
22 * chaque objet cellule est contenu dans le tableau lc qui est un tableau bidimensionnel de cellules
23 * ce tableau a autant d'éléments que de ligne * colonne dans le tableau
24 *
25 *
26 *******************ALGORITHME*************************************
27 * Le tableau est sauvé en mémoire dans la variable lc
28 * La fonction construit_tableau( ) de la classe ihm construit l'interface pour manipuler les données du tableau
29 * qui (re)initialisera la valeur innerHTML de <div id=tableau></div>
30 * toute modification des valeurs dans l'assistant modifie lc
31 * toute modification de l'interface (ajout/suppression de ligne/colonne) modifie lc puis appelle la fonction construit_tableau
32 * simple mais efficace+
33 *
34 * La validation des modifications déclenche construit_code_tableau qui construit le code SPIP du tableau
35 */
36
37
38 /********INITIALISATION**************/
39 //classe ihm : classe générique de gestion de tableau
40 function ihm() {
41 this.titre_t = "";
42 this.resume_t = "";
43 /* méthodes */
44 this.construit_tableau = construit_tableau;
45 this.bouton_insere_ligne = bouton_insere_ligne;
46 this.bouton_supprime_ligne = bouton_supprime_ligne;
47 this.bouton_insere_colonne = bouton_insere_colonne;
48 this.bouton_supprime_colonne = bouton_supprime_colonne;
49 this.insere_commande_ligne = insere_commande_ligne;
50 this.insere_commande_colonne = insere_commande_colonne;
51 this.insere_ligne = insere_ligne;
52 this.supprime_ligne = supprime_ligne;
53 this.insere_colonne = insere_colonne;
54 this.supprime_colonne = supprime_colonne;
55
56 /*******CONStrUIT tableAU**********/
57 function construit_tableau(){
58 var texte = "";
59 texte+="<table id='ihm' cellspacing='"+cellspacing+"'>\n";
60 for (i=0;i<nl+2;i++){//on rajoute deux lignes en plus pour l'interface
61 texte+="<tr>\n";
62 for (j=0;j<nc+2;j++){//on rajoute deux lignes en plus pour l'interface
63 var position = "" ;
64 if (i==0 && j==0) position = "coin"; //on est dans le coin on met le menu
65 if (i==0 && j>0) position = "1st_l"; //on est sur la premiere ligne on insere des colonnes
66 if (i>0 && j==0) position = "1st_c"; //on est sur la premiere colonne on insere des lignes
67 if (i==nl+1 && j>0) position = "last_l"; //on est dans la zone non éditée de la derniere ligne
68 if (i>0 && j==nc+1) position = "last_c"; //on est dans la zone non éditée la derniere colonne
69 switch (position) {
70 case "coin" : texte+="<td></td>\n"; break;
71 case "1st_l" : texte+="<td class='first_l'>"+this.insere_commande_colonne(j-1)+"</td>\n"; break;
72 case "1st_c" : texte+="<td class='first_c'>"+this.insere_commande_ligne(i-1)+"</td>\n"; break;
73 case "last_l" : texte+="<td class='last_l'></td>\n"; break;
74 case "last_c" : texte+="<td class='last_c'></td>\n"; break;
75 default: //on est dans la partie éditable du tableau
76 texte+="<td>"+ lc[i-1][j-1].insere() +"</td>\n";
77 }
78 }//fin du for j
79 texte+="</tr>";
80 }//fin du for i
81 texte+="</table>";
82 //win=window.open('');
83 //win.document.write("<textarea cols='100' rows='50'>"+texte+"</textarea>");
84 table.innerHTML=texte;//on modifie le texte de ce noeud
85 }
86 /**
87 *cette fonction crée un bouton pour l'insertion d'une ligne
88 */
89 function bouton_insere_ligne(ligne){
90 var texte = "<a href='javascript:ihm_tableau.insere_ligne("+ligne+")'><img ";
91 texte += " title='Insérer une ligne au-dessus' ";
92 texte += " alt='Insérer une ligne au-dessus' ";
93 texte += "src='"+tableau_edit_images_path+"inserer_ligne.gif' value=''></a>\n";
94 return texte;
95 }
96
97 /**
98 *cette fonction crée un bouton pour la supression d'une ligne
99 */
100 function bouton_supprime_ligne(ligne){
101 if (nl == 1) return "";
102 var texte="<a href='javascript:ihm_tableau.supprime_ligne("+ligne+")'><img ";
103 texte += " title='Supprimer cette ligne' ";
104 texte += " alt='Supprimer cette ligne' ";
105 texte += "src='"+tableau_edit_images_path+"supprimer_ligne.png' value='ligne' /></a>\n";
106 return texte;
107 }
108
109 /**
110 *cette fonction crée un bouton pour l'insertion d'une colonne
111 */
112 function bouton_insere_colonne(colonne){
113 var texte="<a href='javascript:ihm_tableau.insere_colonne("+colonne+")'> <img ";
114 texte+=" title='Insérer une colonne avant' ";
115 texte+=" alt='Insérer une colonne avant' ";
116 texte+="src='"+tableau_edit_images_path+"inserer_colonne.gif' value='colonne'></a>\n";
117 return texte;
118 }
119 /**
120 *cette fonction crée un bouton pour la supression d'une colonne
121 */
122 function bouton_supprime_colonne(colonne){
123 if (nc == 1) return "";
124 var texte="<a href='javascript:ihm_tableau.supprime_colonne("+colonne+")'><img";
125 texte+=" title='Supprimer cette colonne'";
126 texte+=" alt='Supprimer cette colonne'";
127 texte+=" src='"+tableau_edit_images_path+"supprimer_ligne.png' value='colonne' /></a>\n";
128 return texte;
129 }
130 /**
131 *cette fonction met en forme les commandes pour une ligne
132 */
133 function insere_commande_ligne(ligne){
134 var texte;
135
136 texte = this.bouton_insere_ligne(ligne);
137 if (ligne<nl){
138 texte += this.bouton_supprime_ligne(ligne);
139 }
140 return texte;
141 }
142
143 /**
144 *cette fonction met en forme les commandes pour une colonne
145 */
146 function insere_commande_colonne(colonne){
147 var texte="";
148
149 texte+= this.bouton_insere_colonne(colonne);
150 if (colonne<nc){
151 texte += this.bouton_supprime_colonne(colonne);
152 }
153 return texte;
154 }
155
156 /*********LES CALLBACKS depuis les boutons de l'IHM ****************************************/
157 function insere_ligne(num_ligne){
158 //création d'un tableau temporaire bidimensionnel de cellules
159 var lctemp = new tableau_cellules(nl+1, nc);
160
161 lctemp.insL(num_ligne); //insertion d'une ligne dans le tableau lc
162 lc=lctemp.getT(); //on a une ligne en plus
163
164 nl++;
165 this.construit_tableau();
166 }
167
168 function supprime_ligne(num_ligne){
169 //création d'un tableau temporaire bidimensionnel de cellule
170 var lctemp = new tableau_cellules(nl-1, nc);
171
172 lctemp.supL(num_ligne); //supression d'une ligne dans le tableau lc
173 lc=lctemp.getT(); //on a une ligne en moins
174
175 nl--;
176 this.construit_tableau();
177 }
178 function insere_colonne(num_colonne){
179 //création d'un tableau temporaire bidimensionnel de cellule
180 var lctemp = new tableau_cellules(nl, nc+1);
181
182 lctemp.insC(num_colonne); //insertion d'une colonne dans le tableau lc
183 lc=lctemp.getT();
184
185 nc++; //on a une ligne en plus
186 this.construit_tableau();
187 }
188 function supprime_colonne(num_colonne){
189 //création d'un tableau temporaire bidimensionnel de cellules
190 var lctemp = new tableau_cellules(nl, nc-1);
191
192 lctemp.supC(num_colonne); //supression d'une colonne dans le tableau lc
193 lc=lctemp.getT(); //on remplace le tableau lc par le tableau temp
194
195 nc--; //on a une colonne en moins
196 this.construit_tableau();
197 }
198 }
199
200 //classe cellule
201 function cellule(i,j){
202 this.l=i;
203 this.c=j;
204 this.content='';
205
206 /* les méthodes getters et setters */
207 this.setC = function(c){this.c = c}
208 this.getC = function(){return this.c}
209 this.setL = function(l){this.l = l}
210 this.getL = function(){return this.l}
211
212 /* les méthodes de la classe cellule */
213 this.insere = insere;
214
215 /* cette fonction insere une zone de texte dans la cellule */
216 function insere(){
217
218 var texte ="<textarea cols='10' rows='2'";
219 // on sauve le contenu
220 texte+=" onchange='lc[" + this.l + "][" + this.c + "].content=this.value;'>";
221 texte+=this.content;
222 texte+="</textarea> \n";
223 return texte;
224 }
225 } //fin de la classe "cellule"
226
227 function tableau_cellules(nb_l,nb_c){
228 this.t = new Array();
229 for (var i=0; i<nb_l; i++){
230 this.t[i]=new Array();
231 for (var j=0; j<nb_c; j++){
232 this.t[i][j]=new cellule(i,j);
233 }
234 }
235
236 this.getT = function(){return this.t}
237
238 this.insL = function(num_ligne) {
239 //insertion d'une ligne dans le tableau lc
240 for (var i=0;i<nl+1;i++){
241 for (var j=0;j<nc;j++){
242 if (i<num_ligne){
243 //recopiage simple
244 this.t[i][j]=lc[i][j];
245 }
246 if (i>num_ligne){
247 //on incrémente de 1
248 this.t[i][j]=lc[i-1][j];
249 this.t[i][j].setL(i);
250 }
251 }
252 }
253 }
254
255 this.supL = function(num_ligne){
256 for (i=0;i<nl-1;i++){
257 for (j=0;j<nc;j++){
258 if (i<num_ligne){
259 //recopiage simple
260 this.t[i][j]=lc[i][j];
261 }else{
262 this.t[i][j]=lc[i+1][j];
263 this.t[i][j].setL(i);
264 }
265 }
266 }
267
268 }
269
270 this.insC = function(num_colonne){
271 for (i=0;i<nl;i++){
272 for (j=0;j<nc+1;j++){
273 if (j<num_colonne){
274 //recopiage simple
275 this.t[i][j]=lc[i][j];
276 }
277 if (j>num_colonne){
278 //on incrémente de 1
279 this.t[i][j]=lc[i][j-1];
280 this.t[i][j].setC(j);
281 }
282 }
283 }
284 }
285
286 this.supC = function(num_colonne){
287 for (i=0;i<nl;i++){
288 for (j=0;j<nc-1;j++){
289 if (j<num_colonne){
290 //recopiage simple
291 this.t[i][j]=lc[i][j];
292 }else{
293 this.t[i][j]=lc[i][j+1];
294 this.t[i][j].setC(j);
295 }
296 }
297 }
298 }
299
300 }
301
302 function selection(zone){
303 this.s1 = "";
304 this.s2 = "";
305 this.s3 = "";
306 this.t_SPIP = new Array(); // les lignes du tableau SPIP
307 this.t = new Array(); // le tableau des valeurs à modifier
308 this.premiere_ligne = "";
309
310 this.avec_entete = avec_entete;
311 this.recup_caption = recup_caption;
312 this.recup_summary = recup_summary;
313 this.compte_lignes = compte_lignes;
314 this.recup_ligne = recup_ligne;
315 this.recup_cellule = recup_cellule;
316 this.contenu = contenu;
317 this.existe = existe;
318
319 var lignes = new Array(); // les lignes brutes de la zone d'édition SPIP
320 var ligne_cour = ""; // la ligne brute en cours de traitement lors de la reconstitution du tableau SPIP
321 var j=0;
322 var init_i; // début du contenu du tableau de données (1 si tableau avec entête, 0 sinon)
323
324 if ((clientVer >= 4) && is_ie && is_win)
325 {
326 var theSelection = false;
327
328 theSelection = top.opener.document.selection.createRange().text; // Get text selection
329 if (theSelection) {
330 this.s2 = theSelection;
331 } else {
332 this.s1 = top.opener.document.getElementById("text_area").value;
333 }
334 }
335 else {
336 var selLength = zone.textLength;
337 var selStart = zone.selectionStart;
338 var selEnd = zone.selectionEnd;
339
340 if (selEnd == 1 || selEnd == 2) selEnd = selLength;
341
342 // Raccourcir la selection par double-clic si dernier caractere est espace
343 if (selEnd - selStart > 0 && (zone.value).substring(selEnd-1,selEnd) == ' ') selEnd = selEnd-1;
344 this.s1 = (zone.value).substring(0,selStart);
345 this.s2 = (zone.value).substring(selStart, selEnd)
346 this.s3 = (zone.value).substring(selEnd, selLength);
347 }
348
349 lignes = this.s2.split("\n");
350
351 if (this.avec_entete()) init_i = 1;
352 for (i=init_i;i<lignes.length;i++) {
353 ligne_cour += lignes[i] + "\n";
354 if (lignes[i].match(/\|.?$/)) {
355 ligne_cour = ligne_cour.replace(/\|(left|right|center)/g, "££$1"); //pour distinguer les barres verticales des codes d'inclusion d'image et de document
356 this.t_SPIP[j++] = ligne_cour;
357 ligne_cour = "";
358 }
359 }
360 this.premiere_ligne = this.t_SPIP[0];
361
362 this.contenu();
363
364
365 function avec_entete(){
366 return (lignes[0].search(/^\|\|/) != -1); // si double pipe en tête de la première ligne(resumé)
367 }
368 function recup_caption(){
369 return lignes[0].match(/^\|\|([^\|]*)/)[1];
370 }
371 function recup_summary(){
372 return lignes[0].match(/^\|\|([^\|])*\|([^\|]*)/)[2];
373 }
374 function compte_lignes(){
375 return (this.t_SPIP.length);
376 }
377 function recup_ligne(num_ligne){
378 var ligne_encodee = this.t_SPIP[num_ligne].split("|");
379 var ligne_decodee = new Array();
380
381 for (var i=0; i<ligne_encodee.length; i++){
382 ligne_decodee[i] = ligne_encodee[i].replace(/££/g,"|");
383 }
384 return (ligne_decodee);
385 }
386 function contenu(){
387 for (var i=0; i<this.t_SPIP.length; i++){
388 this.t[i] = this.recup_ligne(i); //t est un tableau bidimensionnel avec les valeurs à modifier
389 }
390 }
391 function recup_cellule(i,j){
392 return (this.t[i][j+1] ? this.t[i][j+1] : "");
393 }
394 function existe() {return (this.s2!="")} //indique si un tableau SPIP a été sélectionné
395 }
396 var ancien_tableau;
397
398 //nombre de lignes et nombre de colonnes
399 var nl;
400 var nc;
401
402 //création d'un tableau bidimensionnel de cellules
403 var lc=new Array();
404
405 var cellspacing=0;
406
407 //noeud ou l'on va ecrire le tableau
408 var table;
409 var debug;
410
411 var ihm_tableau = new ihm();
412
413 function init(){
414 ancien_tableau = new selection(top.opener.zone_selection);
415
416 if (ancien_tableau.existe() & ancien_tableau.avec_entete()) {
417 document.getElementById("titre_t").value = ancien_tableau.recup_caption() ; //récupération du titre du tableau
418 document.getElementById("resume_t").value = ancien_tableau.recup_summary() ;//récupération du résumé du tableau
419 }
420
421 nl= (ancien_tableau.existe()) ? ancien_tableau.compte_lignes() : 3;
422 nc= (ancien_tableau.existe()) ? ancien_tableau.t[0].length - 2 : 3;
423
424 for (i=0;i<nl;i++){
425 lc[i]=new Array(); //2 lignes au depart
426 for (j=0;j<nc;j++){
427 lc[i][j]=new cellule(i,j);
428 if (ancien_tableau.existe()) lc[i][j].content = ancien_tableau.recup_cellule(i,j);
429 }
430 }
431
432 table=document.getElementById("table");
433 debug=document.getElementById("debug");
434
435 /*********CONStrUCTION DE L'INTERFACE UTILISATEUR**********************/
436 ihm_tableau.construit_tableau();
437 }
438 function d(s){debug.innerHTML+=s;}
439
440 /****génération du code SPIP du tableau ******/
441
442 function construit_code_tableau(){
443 var le_titre = document.getElementById("titre_t").value;
444 var le_resume = document.getElementById("resume_t").value;
445 var texte="";
446 var la_ligne="";
447
448 texte += "||" + le_titre + "|" + le_resume + "||\n";
449 for (var j=0;j<nc;j++){
450 //on supprime les accolades éventuelles avant de placer les accolades d'entete de tableau
451 var cont_cell = lc[0][j].content.replace(/(\{)*([^\}]*)(\})*/,"$2");
452 la_ligne += "|{{" + (cont_cell=="" ? " " : cont_cell) + "}}";
453 }
454 texte += la_ligne + "|\n";
455
456 for (i=1;i<nl;i++){
457 for (j=0;j<nc;j++) {texte += "|" + lc[i][j].content;}
458 texte += "|\n";
459 }//fin du for i
460 return texte;
461 }
462
463 /**********LES FONCTIONS DE CREATION DE L'INTERFACE**********/
464
465 function enregistre(){
466 if (ancien_tableau.existe()) {
467 if ((clientVer >= 4) && is_ie && is_win) {
468 top.opener.document.selection.createRange().text = construit_code_tableau();
469 } else {
470 top.opener.zone_selection.value = ancien_tableau.s1 + construit_code_tableau() + ancien_tableau.s3;
471 }
472 } else { //insertion d'un nouveau tableau
473 if (top.opener.zone_selection.createTextRange && top.opener.zone_selection.caretPos) { //IE
474 var caretPos = top.opener.zone_selection.caretPos;
475 caretPos.text = caretPos.text + construit_code_tableau();
476 top.opener.zone_selection.focus();
477 } else {
478 top.opener.zone_selection.value = ancien_tableau.s1 + construit_code_tableau() + ancien_tableau.s3;
479 }
480 }
481 window.close();
482 }