Skip to content

Commit

Permalink
FIRST DRAFT of expandable table
Browse files Browse the repository at this point in the history
TODO pretty up the twitter expanded template and showoff a bit
TODO WRITE TESTS oh boy - I can't believe I forgot this
  • Loading branch information
reconbot committed May 29, 2012
1 parent d502b63 commit a3c0293
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 86 deletions.
144 changes: 77 additions & 67 deletions expandable-table.js
@@ -1,87 +1,116 @@
/*global _:true, Backbone:true, $: true, BTS: true */

(function(){

BTS.ExpandableTable = BTS.GenericTable.extend({
BTS.ExpandableTable = BTS.SortableTable.extend({

// Our parents initialize will copy all the options over we just need to
// specify a few more defaults
initialize: function(opt){
BTS.GenericTable.prototype.initialize.call(this, opt);
BTS.SortableTable.prototype.initialize.call(this, opt);
_.defaults(this.opt, {
expandedView: WC.ExpandableTableRow,
expandedView: BTS.ExpandableTableRow,
keepRow: false
});
}
this.contractedViews = {};
this.expandedViews = {};
},

removeAll: function(){
_.forEach(this.contractedViews, function(m){m.off();});
_.forEach(this.expandedViews, function(m){m.off();});
this.contractedViews = {};
this.expandedViews = {};
this.rows = {}; // no need call off on this in the parent
BTS.SortableTable.prototype.removeAll.call(this);
},

remove: function(model){
var cid = model.cid;
this.contractedViews[cid].off();
this.contractedViews[cid].remove();
delete this.expandedViews[cid];

this.expandedViews[cid].off();
this.expandedViews[cid].remove();
delete this.contractedViews[cid];

BTS.SortableTable.prototype.remove.call(this, model);
},

add: function(model){
BTS.SortableTable.prototype.add.call(this, model);

var cid = model.cid;
var data = {
model: model,
col: this.col()
};

var ctd = this.contractedViews[cid] = this.rows[cid];
var exp = this.expandedViews[cid] = new this.opt.expandedView(data);

ctd.on('toggle', this.toggle, this);
ctd.on('expand', this.expand, this);
ctd.on('contract', this.contract, this);

exp.on('toggle', this.toggle, this);
exp.on('expand', this.expand, this);
exp.on('contract', this.contract, this);
},

expand: function(cid){
var dis = this.displayedRows[cid];
var exp = this.expandedRows[cid];
var row = this.rows[cid];
var exp = this.expandedViews[cid];

if(dis === exp){return;}
if(row === exp){return;}

dis.$el.after(exp.el);
this.displayedRows[cid] = exp;
row.$el.after(exp.el);
this.rows[cid] = exp;

if(!this.opt.keepRow){
dis.detach();
row.detach();
}
},

contract: function(cid){
var dis = this.displayedRows[cid];
var exp = this.expandedRows[cid];
var ctd = this.contractedViews[cid];
var exp = this.expandedViews[cid];
var row = this.rows[cid];

if(dis === row){return;}
if(row === ctd){return;}

if(!this.opt.keepRow){
dis.$el.before(row.el);
row.$el.before(ctd.el);
}
this.displayedRows[cid] = row;
this.rows[cid] = ctd;
exp.detach();

},

toggle: function(cid){
if(this.displayedRows[cid] === this.rows[cid]){
if(this.rows[cid] === this.contractedViews[cid]){
this.expand(cid);
}else{
this.contract(cid);
}
},

//todo make this work
add: function(model){
var exp = this.expandedRows[cid] = new this.opt.expandedView(data);

row.on('toggle', this.toggle, this);
row.on('expand', this.expand, this);
row.on('contract', this.contract, this);

exp.on('toggle', this.toggle, this);
exp.on('expand', this.expand, this);
exp.on('contract', this.contract, this);

this.displayedRows[cid] = this.rows[cid];
},

remove: function(model){
this.expandedRows[cid].remove();
this.expandedRows[cid].off();
delete this.expandedRows[cid];
delete this.displayedRows[cid];
},

attachAll: function(){
var dis = this.displayedRows[cid];
var exp = this.expandedRows[cid];
if(this.opt.keepRow && dis === exp){
this.collection.forEach(function(model){
var cid = model.cid;
var row = this.rows[cid];
if(this.opt.keepRow && this.expandedViews[cid] === this.rows[cid]){
this.tbody.append(this.contractedViews[cid].el);
}
this.tbody.append(row.el);
}
}, this);
}

});

BTS.ExpandableTableRow = BTS.GenericTableRow.extend({
BTS.ExpandableTableRow = BTS.SortableTableRow.extend({

template: 'expandable-table-row',
template: 'sortable-table-row',

events: {
'click .js-toggle': 'toggle',
Expand All @@ -90,28 +119,7 @@
},

initialize: function(opt){
BTS.GenericTableRow.prototype.initialize.call(opt);
},

render: function(){
var data = _.map(this.col, function(field){
var row = {};
row.className = field.className;
row.cid = this.model.cid;

if(field.render){
var value = field.field? this.model.get(field.field) : undefined;
row.html = field.render(value, this.model);
}else if(field.field){
row.text = this.model.get(field.field);
}
return row;
}, this);

var context = _.extend({}, this.context, {col:data});

this.$el.html( WC.renderMustache(this.template,context));
return this.el;
BTS.SortableTableRow.prototype.initialize.call(this, opt);
},

toggle: function(){
Expand All @@ -127,3 +135,5 @@
}

});

}.call(this));
79 changes: 64 additions & 15 deletions index.html
Expand Up @@ -15,10 +15,12 @@ <h1>Example Page for Backbone Tablesorter</h1>
</p>
</div>
</div>
<hr>
<div class="row">
<div class="span12">
Lets make a quick and easy example table. I don't even want to think about making columns, or figuring out datatypes.
Also age before alphabet.
<h2>Simple Use</h2>
Lets make a quick and easy example table. I don't even want to think about making columns, or figuring out datatypes. Also, lets display age before alphabet.
</div>
</div>
<div class="row">
<div class="span8">
Expand All @@ -42,18 +44,19 @@ <h1>Example Page for Backbone Tablesorter</h1>
<table id="ageTable"></table>
</div>
</div>
<hr>
<div class="row">
<div class="span12">
Now for something completely different. Ahead we'll make a live updating twitter search by extending the SortableList class.
<h2>Advanced use</h2>
Now for something completely different. Ahead we'll make a live updating twitter search by extending the <a href="twitter.js">SortableList class</a>.
</div>
</div>

<div class="row">
<div class="span12">
<h2>Twitter search for:</h2>
<form id="search" class="form-inline">
<form id="search" class="form-horizontal">
<fieldset>
<div class="control-group">
<label class="control-label">Twitter Search</label>
<div class="controls">
<div class="input-append">
<input class="span2" id="twitterSearch" type="text" value="backbonejs"/><input type="submit" class="btn btn-primary" value="Search"/>
Expand All @@ -65,7 +68,23 @@ <h2>Twitter search for:</h2>
<table id="twitterTable"></table>
</div>
</div>
<hr>
<div class="row">
<div class="span12">
<h2>More Advanced</h2>
<p>
Lets blow our last example out of the water. I want to extend the SortableTable() class itself. I'm sick of these single state rows, I need something more dynamic. Behold the <a href="expandable-table.js">ExpandableTable() and Expanded Views</a>
</p>
</div>
</div>
<div class="row">
<div class="span12">
<table id="expandable"></table>
</div>
</div>
</div>


<!-- Soooo many deps -->
<script type="text/javascript" src="lib/jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="lib/underscore-min.js"></script>
Expand All @@ -75,40 +94,70 @@ <h2>Twitter search for:</h2>
<script type="text/javascript" src="table.js"></script>
<script type="text/javascript" src="twitter.js"></script>
<script type="text/javascript" src="templates.js"></script>
<script type="text/javascript" src="expandable-table.js"></script>
<script type="text/javascript">
var nameTable, names = [{name:'Bill',age:42},{name:'Jeff',age:19},{name:'Maggie',age:28}];

var tweets = new TweetSearch(null,{search:$('#twitterSearch').val()});
tweets.fetch();
var twitterTable;

var expandoTable;

$(function(){

//basic
nameTable = new BTS.SortableTable({
el: $('#ageTable'),
tableClass:'table table-bordered table-striped',
collection: new BTS.SortableList(names)
});
nameTable.collection.sortBy('age');

//advanced

var twitterCol = [
{name:'User', field:'from_user', render:function(user, model){
var url = "https://twitter.com/" + user + "/status/" + model.get('id_str');
return '<a target="_blank" href="' + url + '"><img src="'+ model.get('profile_image_url') + '" /> <br>' + user + "</a>";
}},
{name:'Tweet', field:'text'},
{name:'Created', field: 'created_at'}
];

twitterTable = new BTS.SortableTable({
el: $('#twitterTable'),
collection: tweets,
tableClass:'table table-bordered table-striped',
col:[
{name:'User', field:'from_user', render:function(user, model){
var url = "https://twitter.com/" + user + "/status/" + model.get('id_str');
return '<a target="_blank" href="' + url + '"><img src="'+ model.get('profile_image_url') + '" /> <br>' + user + "</a>";
}},
{name:'Tweet', field:'text'},
{name:'Created', field: 'created_at'}
]
col:twitterCol
});

$('#search').submit(function(e){
e.preventDefault();
tweets.search = $('#twitterSearch').val();
tweets.fetch();
})
});

//Really advanced
var advancedTwitterCol = _.map(twitterCol, function(c){return _.clone(c);});
advancedTwitterCol.unshift({
name:'expand',
className: 'js-toggle',
render:function(){return '<i class="icon-random"></i>';}
});

var ExpandedTwitterRow = BTS.ExpandableTableRow.extend({
template: 'expanded-twitter-row'
});

expandoTable = new BTS.ExpandableTable({
el: $('#expandable'),
view: BTS.ExpandableTableRow,
expandedView: ExpandedTwitterRow,
collection: tweets,
col: advancedTwitterCol
});

});
</script>

Expand Down
4 changes: 2 additions & 2 deletions table.js
Expand Up @@ -112,7 +112,7 @@
template: 'sortable-table',
tableClass: false,
sortable: true,
view: BTS.GenericTableRow,
view: BTS.SortableTableRow,
col: undefined,
emptyMessage: 'No Rows to Display'
});
Expand Down Expand Up @@ -268,7 +268,7 @@

});

BTS.GenericTableRow = Backbone.View.extend({
BTS.SortableTableRow = Backbone.View.extend({

tagName: 'tr',

Expand Down
4 changes: 2 additions & 2 deletions templates.js
Expand Up @@ -25,14 +25,14 @@
// </thead>
// <tbody></tbody>

'sortable-table-row':'{{#col}}<td {{#className}}class="{{className}}"{{/className}}>{{text}}{{{html}}}</td>{{/col}}'
'sortable-table-row':'{{#col}}<td {{#className}}class="{{className}}"{{/className}}>{{text}}{{{html}}}</td>{{/col}}',
// {{#col}}
// <td {{#className}}class="{{className}}"{{/className}}>
// {{text}}
// {{{html}}}
// </td>
// {{/col}}

'expanded-twitter-row': 'GROOVY BABY!'
};


Expand Down

0 comments on commit a3c0293

Please sign in to comment.