1 // Copyright (c) 2005 spinelz.org (http://script.spinelz.org/)
\r
3 // Permission is hereby granted, free of charge, to any person obtaining
\r
4 // a copy of this software and associated documentation files (the
\r
5 // "Software"), to deal in the Software without restriction, including
\r
6 // without limitation the rights to use, copy, modify, merge, publish,
\r
7 // distribute, sublicense, and/or sell copies of the Software, and to
\r
8 // permit persons to whom the Software is furnished to do so, subject to
\r
9 // the following conditions:
\r
11 // The above copyright notice and this permission notice shall be
\r
12 // included in all copies or substantial portions of the Software.
\r
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\r
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\r
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\r
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 var SelectableTable = Class.create();
\r
24 SelectableTable.classNames = {
\r
25 table: 'selectableTable_table',
\r
26 tr: 'selectableTable_tr',
\r
27 trHover: 'selectableTable_trHover',
\r
28 trSelected: 'selectableTable_trSelected'
\r
31 SelectableTable.prototype = {
\r
32 initialize: function(element) {
\r
33 this.element = $(element);
\r
34 Element.setStyle(this.element, {visibility: 'hidden'});
\r
35 var defaultOptions = {
\r
36 arrayDefaultData: [],
\r
37 flagAllowUnselect: true,
\r
38 flagInitialAllowMultiple: false,
\r
39 flagKeypressAvailable: false,
\r
40 flagKeypressDeleteAvailable: false,
\r
41 flagKeypressInsertAvailable: false,
\r
42 functionPostAdd: Prototype.emptyFunction,
\r
43 functionPostDelete: Prototype.emptyFunction,
\r
44 functionPostPressLeft: Prototype.emptyFunction,
\r
45 functionPostPressRight: Prototype.emptyFunction,
\r
46 functionPostSelect: Prototype.emptyFunction,
\r
47 functionPostUnselect: Prototype.emptyFunction,
\r
48 functionPreAdd: function() {return true;},
\r
49 functionPreDelete: function() {return true;},
\r
50 functionSubmit: Prototype.emptyFunction,
\r
51 initialSelected: null,
\r
52 prefixTrId: 'selectable_table_',
\r
53 prefixCSS: 'custom_'
\r
55 this.options = Object.extend(defaultOptions, arguments[1] || {});
\r
56 this.classNames = new CssUtil([SelectableTable.classNames, CssUtil.appendPrefix(this.options.prefixCSS, SelectableTable.classNames)]);
\r
57 this.documentListener = this.eventKeypress.bindAsEventListener(this);
\r
58 this.flagAllowMultiple = this.options.flagInitialAllowMultiple;
\r
59 this.flagAvailable = true;
\r
60 this.focused = null;
\r
61 this.lastSelected = null;
\r
63 this.selected = new Object();
\r
66 this.selectEffect(this.buildTrId(arguments[2]));
\r
68 Element.setStyle(this.element, {visibility: 'visible'});
\r
72 if(!this.flagAvailable) {return;}
\r
73 if(!this.options.functionPreAdd(this)) {return;}
\r
74 if(arguments[0] == null) {arguments[0] = this.options.arrayDefaultData;}
\r
75 if(typeof(arguments[0]) != 'string') {
\r
76 arguments = arguments[0];
\r
78 if(arguments[0] == null) {return;}
\r
80 objTr = document.createElement('tr');
\r
81 objTr.id = 'new_' + this.newNumber;
\r
82 this.buildTr(objTr);
\r
83 for(var i = 0; i < arguments.length; i++) {
\r
84 objTd = document.createElement('td');
\r
85 objTd.innerHTML = arguments[i];
\r
86 objTr.appendChild(objTd);
\r
88 this.element.tBodies[0].appendChild(objTr);
\r
90 this.options.functionPostAdd(this);
\r
94 var lines = this.element.tBodies[0].rows;
\r
95 this.classNames.addClassNames(this.element, 'table');
\r
96 Event.observe(document, 'keypress', this.documentListener);
\r
97 for(var i = 0; i < lines.length; i++) {
\r
98 this.buildTr(lines[i]);
\r
100 var selected = this.options.initialSelected
\r
102 this.selectEffect(this.buildTrId(selected));
\r
106 buildTr: function(objTr) {
\r
107 objTr.id = this.buildTrId(objTr.id);
\r
108 this.classNames.addClassNames(objTr, 'tr');
\r
109 Event.observe(objTr, 'click', this.eventClick.bindAsEventListener(this));
\r
110 Event.observe(objTr, 'dblclick', this.eventDoubleClick.bindAsEventListener(this));
\r
111 Event.observe(objTr, 'mouseout', this.eventFocusOut.bindAsEventListener(this));
\r
112 Event.observe(objTr, 'mouseover', this.eventFocusOver.bindAsEventListener(this));
\r
115 buildTrId: function(strId) {
\r
116 return this.options.prefixTrId + strId
\r
119 deleteAll: function() {
\r
120 if(!this.flagAvailable) {return;}
\r
121 if(!this.options.functionPreDelete(this)) {return;}
\r
122 for(var trId in this.selected) {
\r
123 this.element.tBodies[0].removeChild($(trId));
\r
124 delete this.selected[trId];
\r
126 this.focused = null;
\r
127 this.options.functionPostDelete(this);
\r
130 eventClick: function(event) {
\r
131 if(!this.flagAvailable) {return;}
\r
132 if(event.shiftKey) {
\r
133 this.selectOrUnselectRange(Event.findElement(event, 'tr').id);
\r
135 this.selectOrUnselect(Event.findElement(event, 'tr').id, event.ctrlKey);
\r
139 eventDoubleClick: function(event) {
\r
140 if(!this.flagAvailable) {return;}
\r
141 if(this.flagAllowMultiple) {
\r
142 this.select(Event.findElement(event, 'tr').id, false);
\r
147 eventFocusOut: function(event) {
\r
148 if(!this.flagAvailable) {return;}
\r
152 eventFocusOver: function(event) {
\r
153 if(!this.flagAvailable) {return;}
\r
154 this.focusOn(Event.findElement(event, 'tr').id);
\r
155 Event.findElement(event, 'tr').focus();
\r
158 eventKeypress: function(event) {
\r
159 if(!this.flagAvailable) {return;}
\r
160 if(!this.options.flagKeypressAvailable) {return;}
\r
161 switch(event.keyCode) {
\r
163 if(event.shiftKey) {
\r
164 this.selectOrUnselectRange(this.focused);
\r
166 this.selectOrUnselect(this.focused, event.ctrlKey);
\r
170 this.options.functionPostPressLeft(this);
\r
173 this.focusMove('up');
\r
176 this.options.functionPostPressRight(this);
\r
179 this.focusMove('down');
\r
182 if(this.options.flagKeypressInsertAvailable) {this.add();}
\r
185 if(this.options.flagKeypressDeleteAvailable) {this.deleteAll();}
\r
190 focusMove: function(direction) {
\r
191 if(!this.flagAvailable) {return;}
\r
192 if(this.focused == null) {
\r
193 this.focusOn(this.element.tBodies[0].rows[0].id);
\r
195 var rowIndex = $(this.focused).rowIndex;
\r
196 var correctionValue, flagEdge;
\r
197 switch(direction) {
\r
199 correctionValue = 1;
\r
200 flagEdge = this.isBottom(rowIndex);
\r
203 correctionValue = -1;
\r
204 flagEdge = this.isTop(rowIndex);
\r
208 this.focusOn(this.element.rows[rowIndex + correctionValue].id);
\r
213 focusOff: function() {
\r
214 if(!this.flagAvailable) {return;}
\r
215 if(this.focused != null) {
\r
216 var objTr = $(this.focused);
\r
217 this.classNames.removeClassNames(objTr, 'trHover');
\r
218 this.focused = null;
\r
222 focusOn: function(trId) {
\r
223 if(!this.flagAvailable) {return;}
\r
224 if($(trId) != null) {
\r
226 this.classNames.addClassNames($(trId), 'trHover');
\r
227 this.focused = trId;
\r
231 getSelected: function() {
\r
232 var selectedIdList = new Array();
\r
233 for(var trId in this.selected) {
\r
234 selectedIdList.push(trId.replace(this.options.prefixTrId, ''));
\r
236 return selectedIdList;
\r
239 getSelectedElement: function(id) {
\r
240 var trId = this.options.prefixTrId + id;
\r
244 isBottom: function(rowIndex) {
\r
245 return (rowIndex == this.element.rows.length - 1) ? true : false;
\r
248 isTop: function(rowIndex) {
\r
249 return (rowIndex == this.element.tBodies[0].rows[0].rowIndex) ? true : false;
\r
252 makeAvailable: function() {
\r
253 this.flagAvailable = true;
\r
256 makeMultiple: function() {
\r
257 this.flagAllowMultiple = true;
\r
260 makeSingular: function() {
\r
261 this.flagAllowMultiple = false;
\r
262 this.unselectAll();
\r
265 makeUnavailable: function() {
\r
266 this.flagAvailable = false;
\r
269 removeEventFromDocument: function() {
\r
270 Event.stopObserving(document, 'keypress', this.documentListener);
\r
273 select: function(trId, ctrl) {
\r
274 if(!this.flagAvailable) {return;}
\r
275 this.selectEffect(trId, ctrl);
\r
276 this.lastSelected = trId;
\r
277 this.options.functionPostSelect(this);
\r
278 if(!this.flagAllowMultiple) {
\r
283 selectAll: function() {
\r
284 if(!this.flagAvailable) {return;}
\r
285 if(!this.flagAllowMultiple) {return;}
\r
286 this.selected = new Object();
\r
287 var lines = this.element.tBodies[0].rows;
\r
288 for(var i = 0; i < lines.length; i++) {
\r
289 this.select(lines[i].id, true);
\r
293 selectEffect: function(trId, ctrl) {
\r
295 if(!this.flagAllowMultiple || !ctrl) {
\r
296 this.unselectAll();
\r
298 this.classNames.addClassNames($(trId), 'trSelected');
\r
299 this.selected[trId] = true;
\r
303 selectOrUnselect: function(trId, ctrl) {
\r
304 if(!this.flagAvailable) {return;}
\r
305 if(trId == null) {return;}
\r
306 if(ctrl && this.selected[trId]) {
\r
307 if(!this.flagAllowMultiple && !this.options.flagAllowUnselect) {return;}
\r
308 this.unselect(trId);
\r
310 this.select(trId, ctrl);
\r
314 selectOrUnselectRange: function(trId) {
\r
315 if(!this.flagAvailable) {return;}
\r
316 if(trId == null) {return;}
\r
317 if(this.lastSelected == null || this.lastSelected == trId) {
\r
318 this.selectOrUnselect(trId);
\r
321 var flagSelect = false;
\r
322 var lines = this.element.tBodies[0].rows;
\r
323 var lastSelected = this.lastSelected
\r
324 for(var i = 0; i < lines.length; i++) {
\r
325 if(lines[i].id == trId || lines[i].id == lastSelected) {
\r
326 flagSelect = (flagSelect) ? false : true;
\r
327 } else if(!flagSelect) {
\r
330 if(this.selected[lastSelected]) {
\r
331 this.select(lines[i].id, true);
\r
333 this.unselect(lines[i].id);
\r
338 submit: function(trId) {
\r
339 if(!this.flagAvailable) {return;}
\r
340 var selected = this.getSelected();
\r
341 this.options.functionSubmit(selected[0]);
\r
344 unselect: function(trId) {
\r
345 if(!this.flagAvailable) {return;}
\r
346 this.classNames.removeClassNames($(trId), 'trSelected');
\r
347 delete this.selected[trId];
\r
348 this.lastSelected = trId;
\r
349 this.options.functionPostUnselect(this);
\r
352 unselectAll: function() {
\r
353 if(!this.flagAvailable) {return;}
\r
354 var lines = this.element.tBodies[0].rows;
\r
355 for(var i = 0; i < lines.length; i++) {
\r
356 this.unselect(lines[i].id);
\r
361 var SelectableTableManager = Class.create();
\r
362 SelectableTableManager.prototype = {
\r
363 initialize: function() {
\r
364 this.active = null,
\r
367 activate: function(key) {
\r
369 if(this.list[key]) {
\r
370 this.list[key].makeAvailable();
\r
371 this.active = this.list[key];
\r
373 this.active = null;
\r
376 push: function(key, element) {
\r
377 this.list[key] = element;
\r
379 start: function() {
\r
381 this.active.makeAvailable();
\r
385 $H(this.list).each(
\r
388 el[1].makeUnavailable();
\r