Pastie now auto-senses if line-wrap is a bad or good idea. Feedback?
## mark a section (Learn more)
## 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 })); };
This paste will be private.
From the Design Piracy series on my blog: