Skip to content

Commit

Permalink
Finished implementing a simple table entry. Refs [#228 state:resolved].
Browse files Browse the repository at this point in the history
  • Loading branch information
gaspard committed Oct 23, 2008
1 parent a6b9efc commit 7706f02
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 65 deletions.
57 changes: 51 additions & 6 deletions app/controllers/nodes_controller.rb
Expand Up @@ -71,8 +71,26 @@ def zafu
end
end

# Get cell text
def cell_edit
# get table
table = get_table_from_json(@node, params[:attr])
# get row/cell
table_data = table[1]

if row = table_data[params[:row].to_i]
if cell = row[params[:cell].to_i]
render :text => cell
else
' '
end
else
' '
end
end

# Ajax table editor
def table_edit
def cell_update
# get table
table = get_table_from_json(@node, params[:attr])
# get row/cell
Expand All @@ -85,21 +103,48 @@ def table_edit
@node.update_attributes(params[:attr] => table.to_json)
end
else
puts "NEW COLUMN: #{table.inspect}"
# new column
@node.errors.add(params[:attr], 'Cell outside of table range.')
end
else
puts "NEW ROW: #{table.inspect}"
# new row
@node.errors.add(params[:attr], 'Row outside of table range.')
end

respond_to do |format|
format.html { render :inline => @node.errors.empty? ? params[:value] : error_messages_for(@node) }
format.html { render :inline => @node.errors.empty? ? "<%= zazen(params[:value], :no_p => true) %>" : error_messages_for(@node) }
end
rescue JSON::ParserError
render :inline => _('could not save value (bad attribute)')
end

# Ajax table add row/column
def table_update
# get table
@table = get_table_from_json(@node, params[:attr])
# get row/cell
table_data = @table[1]

if params[:add] == 'row'
table_data << table_data[0].map { ' ' }
elsif params[:add] == 'column'
table_data.each do |row|
row << ' '
end
elsif params[:remove] == 'row' && table_data.size > 2
table_data.pop
elsif params[:remove] == 'column' && table_data[0].size > 1
table_data.each do |row|
row.pop
end
else
# reorder ...
end

@node.update_attributes(params[:attr] => @table.to_json)

rescue JSON::ParserError
render :inline => _('could not save value (bad attribute)')
end

# This method is called when an element is dropped on a node.
def drop
set = params[:set]
Expand Down
30 changes: 25 additions & 5 deletions app/helpers/application_helper.rb
Expand Up @@ -317,6 +317,7 @@ def flash_messages(opts={})
def zazen(text, opt={})
return '' unless text
opt = {:images=>true, :pretty_code=>true, :output=>'html'}.merge(opt)
no_p = opt.delete(:no_p)
img = opt[:images]
if opt[:limit]
opt[:limit] -= 1 unless opt[:limit] <= 0
Expand All @@ -326,7 +327,12 @@ def zazen(text, opt={})
end
end
opt[:node] ||= @node
ZazenParser.new(text,:helper=>self).render(opt)
res = ZazenParser.new(text,:helper=>self).render(opt)
if no_p && !text.include?("\n")
res.gsub(%r{\A<p>|</p>\Z},'')
else
res
end
end

# TODO: test
Expand Down Expand Up @@ -548,8 +554,9 @@ def make_gallery(ids=[], opts={})

# Create a table from an attribute
def make_table(opts)
style, node, attribute, title, images, table = opts[:style], opts[:node], opts[:attribute], opts[:title], opts[:images], opts[:table]
case style.sub('.', '')
style, node, attribute, title, table = opts[:style], opts[:node], opts[:attribute], opts[:title], opts[:table]
attribute = "d_#{attribute}" unless ['v_', 'd_'].include?(attribute[0..1])
case (style || '').sub('.', '')
when ">"
prefix = "<div class='img_right'>"
suffix = "</div>"
Expand All @@ -560,10 +567,23 @@ def make_table(opts)
prefix = "<div class='img_center'>"
suffix = "</div>"
else
prefix = suffix = ""
prefix = ''
suffix = ''
end

if node.can_write?
prefix << "<div class='table_add'>"
prefix << link_to_remote("<img src='/images/column_add.png' alt='#{_('add column')}'/>",
:url => "/nodes/#{node.zip}/table_update?add=column&attr=#{attribute}")
prefix << link_to_remote("<img src='/images/column_delete.png' alt='#{_('add column')}'/>",
:url => "/nodes/#{node.zip}/table_update?remove=column&attr=#{attribute}")
prefix << link_to_remote("<img src='/images/row_add.png' alt='#{_('add column')}'/>",
:url => "/nodes/#{node.zip}/table_update?add=row&attr=#{attribute}")
prefix << link_to_remote("<img src='/images/row_delete.png' alt='#{_('add column')}'/>",
:url => "/nodes/#{node.zip}/table_update?remove=row&attr=#{attribute}")
prefix << "</div>"
end

attribute = "d_#{attribute}" unless ['v_', 'd_'].include?(attribute[0..1])
table ||= get_table_from_json(node, attribute)

prefix + render_to_string( :partial=>'nodes/table', :locals=>{:table=>table, :node=>node, :attribute=>attribute}) + suffix
Expand Down
6 changes: 3 additions & 3 deletions app/views/nodes/_table.rhtml
@@ -1,13 +1,13 @@
<table id='<%= node.zip %>_<%= attribute %>' class='editable'>
<table id='<%= node.zip %>_<%= attribute %>'<%= node.can_write? ? " class='editable'" : '' %>>
<tr>
<% table[1][0].each do |heading| -%>
<% table[1][0].each do |heading| -%>
<th><%= heading %></th>
<% end -%>
</tr>
<% table[1][1..-1].each do |row| -%>
<tr>
<% row.each do |td| -%>
<td><%= td %></td>
<td><%= zazen(td.to_s, :no_p => true) %></td>
<% end -%>
</tr>
<% end -%>
Expand Down
7 changes: 7 additions & 0 deletions app/views/nodes/table_update.rjs
@@ -0,0 +1,7 @@
dom_id = "#{@node.zip}_#{params[:attr]}"
if @node.errors.empty?
page.replace dom_id, :partial => "table", :locals =>{:table => @table, :node => @node, :attribute => params[:attr]}
page << "TableKit.reloadTable('#{dom_id}');"
else
page.replace_html dom_id, error_messages_for(@node)
end
2 changes: 1 addition & 1 deletion config/routes.rb
Expand Up @@ -20,7 +20,7 @@
:member => { :import => :post, :export => :get, :save_text => :put,
:order => :any, :clear_order => :any,
:zafu => :get, :drop => :put, :attribute => :get,
:table_edit => :post } do |nodes|
:cell_update => :post, :table_update => :post, :cell_edit => :get } do |nodes|
nodes.resources :versions,
:name_prefix => nil,
:member => { :edit => :get,
Expand Down
4 changes: 3 additions & 1 deletion db/init/base/skins/default/style.css
Expand Up @@ -2,6 +2,7 @@ body { background: #eee; color:#444; line-height:21px; font-size:14px; font-fami
a { text-decoration:none; color:#2F31D5;}
a.wiki { color:inherit; border-bottom:1px dotted blue;}
.zazen a:hover, #footer a:hover { border-bottom:1px solid blue;}
.table_add a:hover { border:0;}
input { padding:3px 4px;}

#header, #container, #footer, #top { width:800px; border:1px solid #555; border-width:0 1px 1px; margin:0 auto; background:white; padding:100px 21px;}
Expand Down Expand Up @@ -29,6 +30,7 @@ ol { padding-left:14px;}

.summary { font-style:italic;}
.zazen h1, .zazen h2, .zazen h3, .zazen h4, .zazen p, .zazen ol, .zazen ul { margin:21px 0;}
.zazen table p, .zazen table ol, .zazen table ul { margin-top:0; margin-bottom:0;}
h1, h2, h3 { color:black;}
h1 { font-size:28px; line-height:42px; font-weight:bold; color:black;}
h2 { font-size:21px; line-height:42px;}
Expand Down Expand Up @@ -75,4 +77,4 @@ h2 { font-size:21px; line-height:42px;}
/* tables */

.zazen td, .zazen th { border:1px solid #555; padding:0 6px;}
.zazen th { background: #555; color:white; text-align:center;}
.zazen th { background: #555; color:white; text-align:center;}
Binary file added public/images/column_add.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/column_delete.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/row_add.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/row_delete.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 48 additions & 25 deletions public/javascripts/tablekit.js
Expand Up @@ -153,8 +153,8 @@ Object.extend(TableKit, {
options : {
autoLoad : true,
stripe : true,
sortable : true,
resizable : true,
sortable : false,
resizable : false,
editable : true,
rowEvenClass : 'roweven',
rowOddClass : 'rowodd',
Expand Down Expand Up @@ -733,10 +733,14 @@ TableKit.Editable = {
if(table.tagName !== "TABLE") {return;}
TableKit.register(table,Object.extend(options || {},{editable:true}));
Event.observe(table.tBodies[0], 'click', TableKit.Editable._editCell);
Event.observe(table.tHead, 'click', TableKit.Editable._editCell);
},
_editCell : function(e) {
e = TableKit.e(e);
var cell = Event.findElement(e,'td');
var cell = Event.findElement(e,'td') || Event.findElement(e,'th');
if (Event.findElement(e,'a')) {
return false;
}
if(cell) {
TableKit.Editable.editCell(null, cell, null, e);
} else {
Expand All @@ -757,7 +761,7 @@ TableKit.Editable = {
row = $(table.tBodies[0].rows[index]);
cell = $(row.cells[cindex]);
} else {
cell = $(event ? Event.findElement(event, 'td') : index);
cell = $(event ? (Event.findElement(event, 'td') || Event.findElement(event, 'th')) : index);
table = (table && table.tagName && table.tagName !== "TABLE") ? $(table) : cell.up('table');
row = cell.up('tr');
}
Expand All @@ -770,13 +774,13 @@ TableKit.Editable = {
var data = TableKit.getCellData(cell);
if(data.active) {return;}
data.htmlContent = cell.innerHTML;
var ftype = TableKit.Editable.getCellEditor(null,null,head);
var ftype = TableKit.Editable.getCellEditor(cell,null,head,event);
ftype.edit(cell, event);
data.active = true;
},
getCellEditor : function(cell, table, head) {
getCellEditor : function(cell, table, head, event) {
var head = head ? head : $(TableKit.getHeaderCells(table, cell)[TableKit.getCellIndex(cell)]);
var ftype = TableKit.Editable.types['multi-line-input'];
var ftype = (head !== cell && event && (event.shiftKey || cell.select('p')[0])) ? TableKit.Editable.types['multi-line-input'] : TableKit.Editable.types['text-input'];
if(head.id && TableKit.Editable.types[head.id]) {
ftype = TableKit.Editable.types[head.id];
} else {
Expand Down Expand Up @@ -810,27 +814,47 @@ TableKit.Editable.CellEditor.prototype = {
}, options || {});
},
edit : function(cell) {
this.getCellText(cell);
},
getCellText : function(cell) {
if(!cell) { return ""; }
var row = cell.up('tr');
var table = cell.up('table');
var dom_id = table.id;
var attr = dom_id.replace(/^\d+_/,'');
var node_id = dom_id.match(/^\d+/);
var url = '/nodes/' + node_id + '/cell_edit?row=' + TableKit.getRowIndex(row) + '&cell=' + TableKit.getCellIndex(cell) + '&attr=' + attr;
var editor = this;
new Ajax.Request(url, {
method:'get',
onSuccess: function(transport) {
var data = transport.responseText;
editor.showForm(cell,data);
}});
},
showForm : function(cell, txt) {
cell = $(cell);

var op = this.options;
var element = txt.match(/\n/) ? 'textarea' : op.element;
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);
var field = document.createElement(element);
$H(op.attributes).each(function(v){
field[v.key] = v.value;
});
switch(op.element) {
switch(element) {
case 'input':
case 'textarea':
field.value = TableKit.getCellText(cell);
field.value = txt;
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]) {
Expand All @@ -840,29 +864,28 @@ TableKit.Editable.CellEditor.prototype = {
break;
}
form.appendChild(field);
if(op.element === 'textarea') {
if(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);
}
//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);
form.focusFirstElement();
},
_submit : function(e) {
var cell = Event.findElement(e,'td');
var cell = Event.findElement(e,'td') || Event.findElement(e,'th');
var form = Event.findElement(e,'form');
Event.stop(e);
this.submit(cell,form);
Expand All @@ -877,7 +900,7 @@ TableKit.Editable.CellEditor.prototype = {
var attr = dom_id.replace(/^\d+_/,'');
var node_id = dom_id.match(/^\d+/);
var s = '&row=' + TableKit.getRowIndex(row) + '&cell=' + TableKit.getCellIndex(cell) + '&attr=' + attr + '&' + Form.serialize(form);
this.ajax = new Ajax.Updater(cell, '/nodes/' + node_id + '/table_edit', Object.extend(op.ajaxOptions || TableKit.option('editAjaxOptions', table.id)[0], {
this.ajax = new Ajax.Updater(cell, '/nodes/' + node_id + '/cell_update', Object.extend(op.ajaxOptions || TableKit.option('editAjaxOptions', table.id)[0], {
postBody : s,
onComplete : function() {
var data = TableKit.getCellData(cell);
Expand All @@ -887,7 +910,7 @@ TableKit.Editable.CellEditor.prototype = {
}));
},
_cancel : function(e) {
var cell = Event.findElement(e,'td');
var cell = Event.findElement(e,'td') || Event.findElement(e,'th');
Event.stop(e);
this.cancel(cell);
},
Expand Down
7 changes: 6 additions & 1 deletion public/stylesheets/zena.css
Expand Up @@ -62,4 +62,9 @@ padding:5px; border:1px solid #714D3D; text-align:left; color:#444; z-index:9999
#dev li img { border:0; }
#dev li li { clear:both;}
#dev li table { display:none;}
#dev:hover table { display:block;}
#dev:hover table { display:block;}

/* table js */
.zazen .table_add a { visibility:hidden; padding:0 5px; text-decoration:none;}
.zazen .table_add img { border:0;}
.zazen .table_add:hover a { visibility:visible;}

0 comments on commit 7706f02

Please sign in to comment.