## The rewrite of TableKit.Editable module for Prototype 1.6.0
// based on version 1.2.1 (2007-03-11)
// http://www.millstream.com.au/view/code/tablekit/
// (original code below)
TableKit.Editable = {
AjaxURL: '',
init: function(element, url){
this.table = $(element)
this.url = url
Event.observe(this.table.tBodies[0], 'click', this.editCell.bindAsEventListener(this))
},
editCell: function(event) {
var cell = event.findElement('td')
if (cell.hasClassName('editing')) return
var header = cell.getHeaderCell(this.table)
if (header.hasClassName('noedit')) return
var editable = new TableKit.Editable.CellEditor({ url: this.url });
editable.edit(cell, cell.parentNode.id, header.id);
}
};
TableKit.Editable.CellEditor = Class.create({
initialize: function(options) {
this.options = Object.extend({
showSubmit : true,
submitText : 'OK',
showCancel : true,
cancelText : 'Cancel',
url : null,
ajaxOptions : null
}, options || {});
},
edit: function(cell, id, field) {
this.cell = cell = $(cell);
this.id = id
this.field = field
cell.addClassName('editing')
this.form = new Element('form',
{ method: 'post', action: (this.options.url || TableKit.Editable.AjaxURL) })
this.form.observe('submit', this.submit.bindAsEventListener(this))
this.originalValue = cell.getTextContent()
cell.update(this.form)
this.generateInput()
if (this.options.showCancel) {
this.cancelButton = new Element('a', { href: '#' }).update(this.options.cancelText)
this.cancelButton.observe('click', this.cancel.bindAsEventListener(this))
this.form.insert(' ').insert(this.cancelButton)
}
},
generateInput: function() {
var input = new Element('input', { name: 'value', type: 'text' })
this.form.appendChild(input)
input.setValue(this.originalValue).activate()
},
update: function(value) {
this.cell.removeClassName('editing').update(value)
},
cancel: function(e) {
e.stop()
this.update(this.originalValue)
},
submit : function(e) {
e.stop()
this.cancelButton.hide()
this.form.request({
parameters: {
id: this.id,
field: this.field,
cell: this.cell.getCellIndex(),
row: this.cell.getRowIndex()
},
onComplete: this.callback.bind(this)
})
this.form.disable()
},
callback: function(ajax) {
this.update(ajax.responseText)
}
})
/** Useful DOM extensions **/
Element.addMethods('table', {
getHeaderRow: function(table) {
table = $(table)
return Element.extend((table.tHead ? table.tHead : table).rows[0])
}
})
Element.addMethods('td', {
getHeaderCell: function(cell, table) {
cell = $(cell)
var header = ($(table) || cell.up('table')).getHeaderRow()
return Element.extend(header.cells[cell.getCellIndex()])
}
})
Element.addMethods($w('td th'), {
// investigate: needed?
getCellIndex: function(cell) {
cell = $(cell)
if (Object.isNumber(cell.cellIndex)) return cell.cellIndex
var row = cell.parentNode
for (var i = 0; row.cells[i] != cell; i++);
return i
},
getRowIndex: function(cell) {
cell = $(cell)
var row = cell.parentNode
if (Object.isNumber(row.rowIndex)) return row.rowIndex
var tbody = row.parentNode
for (var i = 0; tbody.rows[i] != row; i++);
if (cell.tagName.toUpperCase() == 'TD' && tbody.tagName.toUpperCase() != 'TBODY') i--
return i
},
getTextContent: function(cell) {
cell = $(cell)
return Object.isUndefined(cell.textContent) ? cell.innerText : cell.textContent
}
})
## Original TableKit.Editable
/*
*
* Copyright (c) 2007 Andrew Tetlaw & Millstream Web Software
* http://www.millstream.com.au/view/code/tablekit/
* Version: 1.2.1 2007-03-11
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
* *
*/
TableKit.Editable = {
init : function(elm, options){
var table = $(elm);
if(table.tagName !== "TABLE") {return;}
TableKit.register(table,Object.extend(options || {},{editable:true}));
Event.observe(table.tBodies[0], 'click', TableKit.Editable._editCell);
},
_editCell : function(e) {
e = TableKit.e(e);
var cell = Event.findElement(e,'td');
TableKit.Editable.editCell(null, cell);
},
editCell : function(table, index, cindex) {
var cell, row;
if(typeof index === 'number') {
if(!table || (table.tagName && table.tagName !== "TABLE")) {return;}
table = $(table);
index = Math.min(table.tBodies[0].rows.length, index);
index = Math.max(1, index);
index -= 1;
cindex = Math.min(table.rows[0].cells.length, cindex);
cindex = Math.max(1, cindex);
cindex -= 1;
row = $(table.tBodies[0].rows[index]);
cell = $(row.cells[cindex]);
} else {
cell = $(index);
table = (table && table.tagName && table.tagName !== "TABLE") ? $(table) : cell.up('table');
row = cell.up('tr');
}
var op = TableKit.option('noEditClass', table.id);
if(cell.hasClassName(op.noEditClass)) {return;}
var head = $(TableKit.getHeaderCells(table, cell)[TableKit.getCellIndex(cell)]);
if(head.hasClassName(op.noEditClass)) {return;}
TableKit.registerCell(cell);
var data = TableKit.cells[cell.id];
if(data.active) {return;}
data.htmlContent = cell.innerHTML;
var ftype = TableKit.Editable.types['text-input'];
if(head.id && TableKit.Editable.types[head.id]) {
ftype = TableKit.Editable.types[head.id];
} else {
var n = head.classNames().detect(function(n){
return (TableKit.Editable.types[n]) ? true : false;
});
ftype = n ? TableKit.Editable.types[n] : ftype;
}
ftype.edit(cell);
data.active = true;
},
types : {},
addCellEditor : function(o) {
if(o && o.name) { TableKit.Editable.types[o.name] = o; }
}
};
TableKit.Editable.CellEditor = Class.create();
TableKit.Editable.CellEditor.prototype = {
initialize : function(name, options){
this.name = name;
this.options = Object.extend({
element : 'input',
attributes : {name : 'value', type : 'text'},
selectOptions : [],
showSubmit : true,
submitText : 'OK',
showCancel : true,
cancelText : 'Cancel',
ajaxURI : null,
ajaxOptions : null
}, options || {});
},
edit : function(cell) {
cell = $(cell);
var op = this.options;
var table = cell.up('table');
var form = $(document.createElement("form"));
form.id = cell.id + '-form';
form.addClassName(TableKit.option('formClassName', table.id)[0]);
form.onsubmit = this._submit.bindAsEventListener(this);
var field = document.createElement(op.element);
$H(op.attributes).each(function(v){
field[v.key] = v.value;
});
switch(op.element) {
case 'input':
case 'textarea':
field.value = TableKit.getCellText(cell);
break;
case 'select':
var txt = TableKit.getCellText(cell);
$A(op.selectOptions).each(function(v){
field.options[field.options.length] = new Option(v[0], v[1]);
if(txt === v[1]) {
field.options[field.options.length-1].selected = 'selected';
}
});
break;
}
form.appendChild(field);
if(op.element === 'textarea') {
form.appendChild(document.createElement("br"));
}
if(op.showSubmit) {
var okButton = document.createElement("input");
okButton.type = "submit";
okButton.value = op.submitText;
okButton.className = 'editor_ok_button';
form.appendChild(okButton);
}
if(op.showCancel) {
var cancelLink = document.createElement("a");
cancelLink.href = "#";
cancelLink.appendChild(document.createTextNode(op.cancelText));
cancelLink.onclick = this._cancel.bindAsEventListener(this);
cancelLink.className = 'editor_cancel';
form.appendChild(cancelLink);
}
cell.innerHTML = '';
cell.appendChild(form);
},
_submit : function(e) {
var cell = Event.findElement(e,'td');
var form = Event.findElement(e,'form');
Event.stop(e);
this.submit(cell,form);
},
submit : function(cell, form) {
var op = this.options;
form = form ? form : cell.down('form');
var head = $(TableKit.getHeaderCells(null, cell)[TableKit.getCellIndex(cell)]);
var row = cell.up('tr');
var table = cell.up('table');
var s = '&row=' + (TableKit.getRowIndex(row)+1) + '&cell=' + (TableKit.getCellIndex(cell)+1) + '&id=' + row.id + '&field=' + head.id + '&' + Form.serialize(form);
this.ajax = new Ajax.Updater(cell, op.ajaxURI || TableKit.option('editAjaxURI', table.id)[0], Object.extend(op.ajaxOptions || TableKit.option('editAjaxOptions', table.id)[0], {
postBody : s,
onComplete : function() {
var data = TableKit.cells[cell.id];
data.active = false;
data.refresh = true; // mark cell cache for refreshing, in case cell contents has changed and sorting is applied
}
}));
},
_cancel : function(e) {
var cell = Event.findElement(e,'td');
Event.stop(e);
this.cancel(cell);
},
cancel : function(cell) {
this.ajax = null;
var data = TableKit.cells[cell.id];
cell.innerHTML = data.htmlContent;
data.htmlContent = '';
data.active = false;
},
ajax : null
};
TableKit.Editable.textInput = function(n,attributes) {
TableKit.Editable.addCellEditor(new TableKit.Editable.CellEditor(n, {
element : 'input',
attributes : Object.extend({name : 'value', type : 'text'}, attributes||{})
}));
};
TableKit.Editable.textInput('text-input');
TableKit.Editable.multiLineInput = function(n,attributes) {
TableKit.Editable.addCellEditor(new TableKit.Editable.CellEditor(n, {
element : 'textarea',
attributes : Object.extend({name : 'value', rows : '5', cols : '20'}, attributes||{})
}));
};
TableKit.Editable.multiLineInput('multi-line-input');
TableKit.Editable.selectInput = function(n,attributes,selectOptions) {
TableKit.Editable.addCellEditor(new TableKit.Editable.CellEditor(n, {
element : 'select',
attributes : Object.extend({name : 'value'}, attributes||{}),
'selectOptions' : selectOptions
}));
};