Ajout classes pour bordure et fond standards.
[Plinn.git] / skins / ajax_scripts / growable_table.js
1 // © Benoît PIN 2006-2008
2 // http://plinn.org
3 // Licence GPL
4 //
5 //
6 // GrowableTable: functions to edit quickly table form entries.
7
8 function GrowableTable(tbody, fieldsDescription, submitExtName, skipFormManagerInit) {
9 this.fieldsDescription = fieldsDescription;
10 this.tbody = tbody;
11 this.length = tbody.getElementsByTagName('tr').length;
12 this.submitExtName = submitExtName;
13
14 var form = this.tbody.parentNode;
15 while (form.tagName != 'FORM')
16 form = form.parentNode;
17
18 var thisManager = this;
19
20 if (!skipFormManagerInit) {
21 var formManager = new FormManager(form);
22 formManager.onBeforeSubmit = function(m, e){return thisManager.onBeforeSubmit(m, e)};
23 formManager.onResponseLoad = function(req){thisManager.loadResponse(req);};
24 }
25
26 addListener(this.tbody.parentNode, 'click', function(evt){thisManager.tbodyClick(evt);});
27
28 var addButton;
29 var links = tbody.parentNode.getElementsByTagName('a');
30 for (var i=0 ; i<links.length ; i++) {
31 addButton = links[i];
32 if (addButton.name == 'addrow')
33 break;
34 }
35 this.addButton = addButton;
36 this.submittedRow = null;
37 this.editedRowInitialValues = null;
38
39
40 }
41
42 GrowableTable.prototype.tbodyClick = function(evt) {
43 var ob = getTargetedObject(evt);
44 if (ob.tagName == 'IMG') {
45 disablePropagation(evt);
46 disableDefault(evt);
47
48 var link = ob.parentNode;
49 var name = link.getAttribute('name');
50
51 if (name == 'addrow')
52 this.addRow();
53 else if (name)
54 this.removeRow(ob, name);
55 }
56 else {
57 while (ob.tagName != 'TBODY') {
58 if (ob.tagName == 'SPAN')
59 break;
60 else
61 ob = ob.parentNode;
62 }
63
64 if (ob.tagName == 'SPAN') {
65 disablePropagation(evt);
66 disableDefault(evt);
67 this.replaceRowByFields(ob);
68 }
69 }
70 };
71
72 GrowableTable.prototype.replaceRowByFields = function(ob) {
73 if (this.editedRowInitialValues)
74 return;
75 this.addButton.className = 'hidden';
76 var tr = ob;
77 while (tr.tagName != 'TR')
78 tr = tr.parentNode;
79
80 var span, cell, input, elementName, text;
81 var cells = tr.getElementsByTagName('td');
82 elementName = cells[0].getElementsByTagName('a')[0].getAttribute('name');
83
84 this.editedRowInitialValues = new Array();
85
86 for (var i=1; i < cells.length ; i++) {
87 cell = cells[i];
88 span = cell.getElementsByTagName('span')[0];
89 this.editedRowInitialValues[i-1] = span.innerHTML;
90
91 if (span.firstChild && span.firstChild.className == 'hidden_value')
92 text = span.firstChild.innerHTML;
93 else
94 text = span.innerHTML;
95
96 input = document.createElement('input');
97 with(input) {
98 type='text';
99 name=this.fieldsDescription[i-1][0];
100 size=this.fieldsDescription[i-1][1];
101 value=text;
102 }
103 cell.replaceChild(input, span);
104
105 if (i == cells.length - 1) {
106 var hiddenNameInput = document.createElement('input');
107 with (hiddenNameInput){
108 type='hidden';
109 name='row_edit' + this.submitExtName;
110 value=elementName;
111 }
112
113 var validButton = document.createElement('input');
114 with (validButton) {type = 'image'; name = 'row_edit_valid'; src = portal_url() + '/validate.gif'; alt = 'Validate'; height='16'; width='16'}
115
116 var cancelButton = document.createElement('input');
117 with (cancelButton) {type = 'image'; name = 'row_edit_cancel'; src = portal_url() + '/cancel.gif'; alt = 'Cancel';}
118
119 cell.appendChild(hiddenNameInput)
120 cell.appendChild(validButton);
121 cell.appendChild(cancelButton);
122 }
123 }
124 return tr;
125 };
126
127 GrowableTable.prototype.cancelEditRow = function(ob) {
128 var tr = ob;
129 while(tr.tagName != 'TR')
130 tr = tr.parentNode;
131
132 var cells = tr.getElementsByTagName('td');
133 var td, span, text;
134 for (var i=1 ; i < cells.length ; i++) {
135 td = cells[i];
136 while (td.firstChild)
137 td.removeChild(td.firstChild);
138
139 span = document.createElement('span');
140 td.appendChild(span);
141 span.innerHTML = this.editedRowInitialValues[i-1];
142 }
143
144 this.editedRowInitialValues = null;
145 this.addButton.className = '';
146 }
147
148 GrowableTable.prototype.onBeforeSubmit = function(m, evt) {
149 var target = getTargetedObject(evt);
150 var submitElement, form;
151
152 switch (target.tagName) {
153 case 'INPUT' :
154 submitElement = target;
155 form = target.form;
156 break;
157 case 'FORM' :
158 submitElement = m.submitButton;
159 form = target;
160 break;
161 }
162
163 switch(submitElement.name) {
164 case 'row_cancel':
165 this.cancelRow(submitElement);
166 break;
167 case 'row_edit_cancel':
168 this.cancelEditRow(submitElement);
169 return 'cancelSubmit';
170 break;
171 default :
172 var submittedRow = submitElement;
173 while(submittedRow.tagName != 'TR')
174 submittedRow = submittedRow.parentNode;
175 this.submittedRow = submittedRow;
176 return;
177 break;
178 }
179
180 return 'cancelSubmit';
181 }
182
183 GrowableTable.prototype.loadResponse = function(req) {
184 var doc = req.responseXML.documentElement;
185 switch (doc.nodeName) {
186 case 'computedField':
187 var copy = getCopyOfNode(doc.firstChild);
188 this.tbody.replaceChild(copy, this.submittedRow);
189 this.addButton.className = '';
190 this.submittedRow = null;
191 this.editedRowInitialValues = null;
192 break;
193 case 'error':
194 alert(doc.firstChild.nodeValue);
195 break;
196 }
197 }
198
199 GrowableTable.prototype.addRow = function(evt) {
200 var fieldDescription, input, fieldName, fieldSize;
201 var firstField;
202 var tr = document.createElement('tr');
203 var td = document.createElement('td');
204 var hiddenInputAddRowFlag = document.createElement('input');
205 with (hiddenInputAddRowFlag){
206 type='hidden';
207 name='row_add' + this.submitExtName;
208 value='add';
209 }
210 td.appendChild(hiddenInputAddRowFlag);
211 tr.appendChild(td);
212
213 for (var i=0 ; i < this.fieldsDescription.length ; i++) {
214 fieldDescription = this.fieldsDescription[i];
215 fieldName = fieldDescription[0];
216 fieldSize = fieldDescription[1];
217
218 td = document.createElement('td');
219 input = document.createElement('input')
220 with(input){type='text'; name=fieldName; size=fieldSize; }
221 td.appendChild(input);
222 tr.appendChild(td);
223 if (i == 0)
224 firstField = input;
225 if (i == this.fieldsDescription.length -1) {
226 var validButton = document.createElement('input');
227 with (validButton) {type = 'image'; name = 'row_valid'; src = portal_url() + '/validate.gif'; alt = 'Validate'; height='16'; width='16'}
228
229 var cancelButton = document.createElement('input');
230 with (cancelButton) {type = 'image'; name = 'row_cancel'; src = portal_url() + '/cancel.gif'; alt = 'Cancel';}
231
232 td.appendChild(validButton);
233 td.appendChild(cancelButton);
234 }
235 }
236
237 this.tbody.appendChild(tr);
238 this.length += 1;
239 firstField.focus();
240 this.addButton.className = 'hidden';
241 return tr;
242 };
243
244 GrowableTable.prototype.removeRow = function(ob, name) {
245 var tr = ob;
246 while (tr.tagName != 'TR')
247 tr = tr.parentNode;
248
249 var form = tr;
250 while (form.tagName != 'FORM')
251 form = form.parentNode;
252
253 var req = new XMLHttpRequest();
254 var thisManager = this;
255 req.onreadystatechange = function() {
256 switch (req.readyState) {
257 case 1 :
258 showProgressImage();
259 break;
260 case 4 :
261 hideProgressImage();
262 if (req.status == '200') {
263 if (req.responseXML.documentElement.tagName == 'done')
264 thisManager.tbody.removeChild(tr);
265 thisManager.onAfterRemove(name);
266 }
267 else
268 alert('Error: ' + req.status);
269 }
270 };
271
272 var url = form.action;
273 req.open("POST", url, true);
274 req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
275 req.send('name=' + name + '&rm=rm');
276 }
277
278 GrowableTable.prototype.onAfterRemove = function(name) { }
279
280 GrowableTable.prototype.cancelRow = function(element) {
281 /* element must be on the "descendant-or-self" axis of the row to remove */
282 while (element.tagName != 'TR')
283 element = element.parentNode;
284 this.tbody.removeChild(element);
285 this.addButton.className= undefined;
286 }
287
288
289 /*
290 * http://www.sitepoint.com/blogs/2006/01/17/javascript-inheritance/
291 */
292
293 // déplacé dans javascript_events_api.js
294
295 // function copyPrototype(descendant, parent) {
296 // var sConstructor = parent.toString();
297 // var aMatch = sConstructor.match( /\s*function (.*)\(/ );
298 // if ( aMatch != null ) { descendant.prototype[aMatch[1]] = parent; }
299 // for (var m in parent.prototype) {
300 // descendant.prototype[m] = parent.prototype[m];
301 // }
302 // }