Skip to content

Commit

Permalink
Merge pull request #18 from immense/releases/0.5.0
Browse files Browse the repository at this point in the history
Releases/0.5.0
  • Loading branch information
cmbankester committed Dec 18, 2014
2 parents 48335e0 + f9fea1d commit 3e9912f
Show file tree
Hide file tree
Showing 13 changed files with 354 additions and 171 deletions.
3 changes: 3 additions & 0 deletions Gruntfile.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ module.exports = (grunt) ->
# uglifyjs files
uglify:
datatable:
options:
sourceMap: true,

src: 'knockout-datatable.js'
dest: 'knockout-datatable.min.js'
}
Expand Down
34 changes: 32 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Knockout DataTable is a flexible and reusable Knockout.js view model for data ta

## Demo

Check out the [demo](http://rawgithub.com/immense/knockout-datatable/master/demo.html) to get a quick idea of how it works and how to use it.
Check out the [demo](http://rawgit.com/immense/knockout-datatable/master/demo.html) to get a quick idea of how it works and how to use it.

## Installation

Expand All @@ -14,7 +14,25 @@ Or drop the `knockout-datatable{.min}.js` file in your vendor assets javascript

## Usage

Refer to the [demo](http://rawgithub.com/immense/knockout-datatable/master/demo.html) for detailed usage instructions.
Refer to the [demo](http://rawgit.com/immense/knockout-datatable/master/demo.html) for detailed usage instructions.

### API

The following methods are available on the DataTable instance:
* `prevPage()` - go to the previous page (if not on page 1)
* `nextPage()` - go to next page (if not on last page)
* `toggleSort(field)`
- switches to ascending sort if sorted descending by `field`
- switches to descending sort if sorted ascending by `field`
- sorts ascending by `field` if not already sorted by `field`
* `gotoPage(pageNum)` - sets the current page to `pageNum`
* `pageClass(pageNum)` - returns `"active"` if `pageNum` is the current page
* `addRecord(new_record)` - pushes `new_record` onto the datatable's rows
* `removeRecord(record)` - removes `record` from the datatable's rows
* `replaceRows(new_rows_array)`
- resets the datatable's rows to `new_rows_array`
- sets the current page to `1`


## Building

Expand All @@ -26,6 +44,18 @@ npm install
grunt
```

## Contributing

1. Fork it
1. Create your feature branch (`git checkout -b my-new-feature`)
1. Commit your changes (`git commit -am 'Add some feature'`)
1. Push to the branch (`git push origin my-new-feature`)
1. Create new Pull Request

## Contributors

See [Contributors](https://github.com/immense/knockout-datatable/wiki/Contributors)

## License

Knockout DataTable is released under the MIT License. Please see the LICENSE file for details.
12 changes: 10 additions & 2 deletions bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
{
"name": "knockout-datatable",
"version": "0.4.0",
"version": "0.5.0",
"private": false,
"license": "MIT"
"license": "MIT",
"ignore": [
".gitignore",
"demo.html",
"Gruntfile.coffee",
"README.md",
"example",
"node_modules"
]
}
157 changes: 125 additions & 32 deletions demo.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<title>Knockout DataTable Demo</title>
<link rel='stylesheet' type='text/css' href='http://netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css'>
<link rel='stylesheet' type='text/css' href='http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css'>
<link rel='stylesheet' type='text/css' href='knockout-datatable.css'>
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/knockout/2.3.0/knockout-min.js'></script>
<script src='http://knockoutjs.com/downloads/knockout-3.2.0.js'></script>
<script src='knockout-datatable.min.js'></script>
<style type='text/css'>
/* yanked from bootstrap demos: http://getbootstrap.com/examples/jumbotron-narrow/ */
Expand Down Expand Up @@ -138,12 +139,33 @@
return new City(_this, row);
});
this.table = new DataTable(rows, tableOptions);
ko.applyBindings(this);
ko.applyBindings(this, document.getElementById('sorted-table'));
}

return CitiesModel;

})();

this.CitiesModelUnsorted = (function() {

function CitiesModelUnsorted() {
var rows, tableOptions,
_this = this;
tableOptions = {
recordWord: 'city',
recordWordPlural: 'cities',
perPage: 15
};
rows = citiesList.map(function(row) {
return new City(_this, row);
});
this.table = new DataTable(rows, tableOptions);
ko.applyBindings(this, document.getElementById('unsorted-table'));
}

return CitiesModelUnsorted;

})();
</script>
</head>
<body>
Expand Down Expand Up @@ -182,31 +204,43 @@ <h2>Simple example</h2>
sortDir: 'desc'
sortField: 'population'
perPage: 15
unsortedClass: 'glyphicon glyphicon-sort'
ascSortClass: 'glyphicon glyphicon-sort-by-attributes'
descSortClass: 'glyphicon glyphicon-sort-by-attributes-alt'

@table = new DataTable [], tableOptions
@table.loading true

req = $.getJSON "/api/cities"
req = new XMLHttpRequest()
req.open 'GET', '/api/cities', true

req.done (response) =>
if response.error?
alert 'Unable to retrieve cities.'
else
req.onload = =>
if req.status >= 200 and req.status < 400
response = JSON.parse req.responseText
rows = response.results.map (row) => new City @, row
@table.rows rows
@table.loading false
@table.loading false
else
alert "Error communicating with server"
@table.loading false

req.fail (jqXHR, textStatus, errorThrown) =>
alert "Unknown error: #{errorThrown}"
req.onerror = =>
alert "Error communicating with server"
@table.loading false

req.send()

ko.applyBindings @</pre>

<p>And a table, like so:</p>

<pre class="pre-scrollable">
&lt;input type="text" data-bind="value: table.filter" placeholder="Search"/&gt;
&lt;div data-bind="with: table"&gt;
&lt;div class=&quot;pull-right&quot;&gt;
&lt;strong&gt;Results per page&lt;/strong&gt;
&lt;select data-bind=&quot;options: [10,25,50], value: perPage&quot;&gt;&lt;/select&gt;
&lt;/div&gt;
&lt;input type="text" data-bind="textInput: filter" placeholder="Search"/&gt;
&lt;table class="table table-striped table-bordered"&gt;
&lt;thead&gt;
&lt;tr&gt;
Expand Down Expand Up @@ -263,18 +297,18 @@ <h2>Simple example</h2>
&lt;/div&gt;
&lt;/div&gt;
&lt;script type="text/javascript"&gt;
(function() {

$(function() {
new CitiesModel();
});

}).call(this);
document.addEventListener('DOMContentLoaded', function(){
new CitiesModel();
});
&lt;/script&gt;</pre>

<h3>Result:</h3>
<input type="text" data-bind="value: table.filter" placeholder="Search"/>
<div data-bind="with: table">
<div id="sorted-table" data-bind="with: table">
<div class="pull-right">
<strong>Results per page</strong>
<select data-bind="options: [10,25,50], value: perPage"></select>
</div>
<input type="text" data-bind="textInput: filter" placeholder="Search"/>
<table class="table table-striped table-bordered">
<thead>
<tr>
Expand Down Expand Up @@ -331,13 +365,75 @@ <h3>Result:</h3>
</div>
</div>
<script type="text/javascript">
(function() {
document.addEventListener('DOMContentLoaded', function(){
window.view = new CitiesModel();
});
</script>

$(function() {
window.view = new CitiesModel();
});

}).call(this);
<h3>Example without sorting</h3>
<div id="unsorted-table" data-bind="with: table">
<div class="pull-right">
<strong>Results per page</strong>
<select data-bind="options: [10,25,50], value: perPage"></select>
</div>
<input type="text" data-bind="textInput: filter" placeholder="Search"/>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th style="width: 34%;">
City
</th>
<th style="width: 33%;">
Country
</th>
<th style="width: 33%;">
Population
</th>
</tr>
</thead>
<tbody>
<tr data-bind="visible: showNoData">
<td colspan="3" class="aligncenter">
This table has no data.
</td>
</tr>
<tr data-bind="visible: showLoading">
<td colspan="3" class="aligncenter">
<i data-bind="css: {'icon-spin': showLoading}" class="icon-spinner"></i>
Loading data...
</td>
</tr>
<!-- ko foreach: {data: pagedRows, as: '$row'} -->
<tr>
<td data-bind="text: $row.cityName"></td>
<td data-bind="text: $row.countryName"></td>
<td data-bind="text: $row.population"></td>
</tr>
<!-- /ko -->
</tbody>
</table>
<span data-bind="text: recordsText" class="label label-info pull-right"></span>
<div data-bind="visible: pages() > 1">
<ul class="pagination">
<li data-bind="css: leftPagerClass, click: prevPage">
<a href="#">&laquo;</a>
</li>
<!-- ko foreach: {data: (new Array(pages()))} -->
<li data-bind="css: $parent.pageClass($index() + 1)">
<a href="#" data-bind="text: $index() + 1, click: $parent.gotoPage($index() + 1)"></a>
</li>
<!-- /ko -->
<li data-bind="css: rightPagerClass, click: nextPage">
<a href="#">&raquo;</a>
</li>
</ul>
</div>
</div>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function(){
window.unsorted_cities = new CitiesModelUnsorted();
});
</script>


Expand All @@ -354,10 +450,10 @@ <h2>Options</h2>
<dd>The initial sorting direction for the table. Default: <code>'asc'</code></dd>

<dt><code>sortField</code></dt>
<dd>The initial sorting column for the table. This setting is required, and the table will raise 'sortField must be supplied' error if sortfield is left unset.</dd>
<dd>The initial sorting column for the table. As of v0.5.0, this setting is optional and the order of <code>table.rows</code> will be maintained and sorting will be disabled.</dd>

<dt><code>perPage</code></dt>
<dd>Integer indicating the number of rows to be shown per page. Default: <code>Infinity</code></dd>
<dd>Integer indicating the number of rows to be shown per page. Default: <code>15</code></dd>

<dt><code>unsortedClass</code><br /><code>descSortClass</code><br /><code>ascSortClass</code></dt>
<dd>The classes given to the icons in the <code>th</code> elements indicating the direction of sorting. Set to '' if you would rather have no icons. Default: <code>''</code> for each</dd>
Expand Down Expand Up @@ -386,9 +482,6 @@ <h2>Further Usage</h2>
</dl>
</div>
</div>
<div class='footer'>
<p>&copy; Immense Networks 2013</p>
</div>
</div>
</body>
</html>
3 changes: 1 addition & 2 deletions example_view.jade → example/view.jade
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ mixin th-sortable(field)
|&nbsp;
i(data-bind="css: sortClass('#{field}')")

input(type='text', data-bind='instant: filter')

p.aligncenter.bindingloader
i.icon-spinner.icon-spin
|&nbsp;Loading...

div.cloak(data-bind='with: exampleTable')
input(type='text', data-bind='textInput: filter')
table.table.table-striped
thead
tr
Expand Down
31 changes: 15 additions & 16 deletions example_model.coffee → example/view_model.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,24 @@ class @ExampleModel
@exampleTable = new DataTable [], tableOptions
@exampleTable.loading true

req = $.getJSON "/api/rows"

req.done (response) =>
if response.error?
messenger.error 'Unable to retrieve rows.'
req = new XMLHttpRequest()
req.open 'GET', '/api/cities', true

req.onload = =>
if req.status >= 200 and req.status < 400
response = JSON.parse req.responseText
rows = response.results.map (row) => new City @, row
@table.rows rows
@table.loading false
else
rows = response.results.map (row) => new Row @, row
@exampleTable.rows rows
@exampleTable.loading false

req.fail (jqXHR, textStatus, errorThrown) =>
messenger.error "Unknown error: #{errorThrown}"
@exampleTable.loading false
alert "Error communicating with server"
@table.loading false

@filter = ko.observable ''
req.onerror = =>
alert "Error communicating with server"
@table.loading false

ko.computed =>
@exampleTable.filter @filter()
.extend throttle: 250
req.send()

ko.applyBindings @
$('.cloak').removeClass 'cloak'
Expand Down
Loading

0 comments on commit 3e9912f

Please sign in to comment.