Merge branch 'master' into gh-pages
This commit is contained in:
commit
1503628db1
@ -1,9 +1,9 @@
|
||||
var data = [
|
||||
{id: 0, date: '2011-01-01', x: 1, y: 2, z: 3, country: 'DE', label: 'first', lat:52.56, lon:13.40},
|
||||
{id: 1, date: '2011-02-02', x: 2, y: 4, z: 24, country: 'UK', label: 'second', lat:54.97, lon:-1.60},
|
||||
{id: 2, date: '2011-03-03', x: 3, y: 6, z: 9, country: 'US', label: 'third', lat:40.00, lon:-75.5},
|
||||
{id: 3, date: '2011-04-04', x: 4, y: 8, z: 6, country: 'UK', label: 'fourth', lat:57.27, lon:-6.20},
|
||||
{id: 4, date: '2011-05-04', x: 5, y: 10, z: 15, country: 'UK', label: 'fifth', lat:51.58, lon:0},
|
||||
{id: 5, date: '2011-06-02', x: 6, y: 12, z: 18, country: 'DE', label: 'sixth', lat:51.04, lon:7.9}
|
||||
{id: 0, date: '2011-01-01', x: 1, y: 2, z: 3, country: 'DE', geo: {lat:52.56, lon:13.40} },
|
||||
{id: 1, date: '2011-02-02', x: 2, y: 4, z: 24, country: 'UK', geo: {lat:54.97, lon:-1.60}},
|
||||
{id: 2, date: '2011-03-03', x: 3, y: 6, z: 9, country: 'US', geo: {lat:40.00, lon:-75.5}},
|
||||
{id: 3, date: '2011-04-04', x: 4, y: 8, z: 6, country: 'UK', geo: {lat:57.27, lon:-6.20}},
|
||||
{id: 4, date: '2011-05-04', x: 5, y: 10, z: 15, country: 'UK', geo: {lat:51.58, lon:0}},
|
||||
{id: 5, date: '2011-06-02', x: 6, y: 12, z: 18, country: 'DE', geo: {lat:51.04, lon:7.9}}
|
||||
];
|
||||
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
// Create a dataset with a Google Docs backend and a url to the Google Doc
|
||||
var dataset = new recline.Model.Dataset({
|
||||
url: 'https://docs.google.com/spreadsheet/ccc?key=0Aon3JiuouxLUdGZPaUZsMjBxeGhfOWRlWm85MmV0UUE#gid=0'
|
||||
},
|
||||
// backend name or instance
|
||||
'gdocs'
|
||||
);
|
||||
url: 'https://docs.google.com/spreadsheet/ccc?key=0Aon3JiuouxLUdGZPaUZsMjBxeGhfOWRlWm85MmV0UUE#gid=0',
|
||||
backend: 'gdocs'
|
||||
});
|
||||
|
||||
// Optional - display the results in a grid
|
||||
// Note how we can set this up before any data has arrived
|
||||
@ -15,14 +13,9 @@ var grid = new recline.View.Grid({
|
||||
$('#my-gdocs').append(grid.el);
|
||||
|
||||
// Now do the query to the backend to load data
|
||||
dataset.fetch().done(function() {
|
||||
dataset.query().done(function(data) {
|
||||
// The grid will update automatically
|
||||
// Log some data as an example
|
||||
if (console) {
|
||||
console.log(data);
|
||||
console.log(dataset.currentDocuments);
|
||||
}
|
||||
});
|
||||
dataset.fetch().done(function(dataset) {
|
||||
if (console) {
|
||||
console.log(dataset.currentDocuments);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
24
_includes/tutorial-basics-ex-1.js
Normal file
24
_includes/tutorial-basics-ex-1.js
Normal file
@ -0,0 +1,24 @@
|
||||
// (for convenience) assume availability of jquery
|
||||
// must have div with class="ex-1"
|
||||
var $el = $('.ex-1');
|
||||
|
||||
// we will define this function display so we can reuse it below!
|
||||
function display(dataset) {
|
||||
// total number of records resulting from latest query
|
||||
$el.append('Total found: ' + dataset.recordCount + '<br />');
|
||||
$el.append('Total returned: ' + dataset.currentRecords.length);
|
||||
|
||||
$el.append('<hr />');
|
||||
|
||||
// dataset.currentRecords is a Backbone Collection of Records that resulted from latest query (hence "current")
|
||||
// Get the first record in the list - it returns an instance of the Record object
|
||||
var record = dataset.currentRecords.at(0);
|
||||
|
||||
// Use the summary helper method which produces proper html
|
||||
// You could also do record.toJSON() to get a hash of the record data
|
||||
$el.append(dataset.recordSummary(record));
|
||||
}
|
||||
|
||||
// now display our existing dataset ...
|
||||
display(dataset);
|
||||
|
||||
13
_includes/tutorial-basics-ex-2.js
Normal file
13
_includes/tutorial-basics-ex-2.js
Normal file
@ -0,0 +1,13 @@
|
||||
// must have a div with class="ex-1"
|
||||
var $el = $('.ex-2');
|
||||
|
||||
// query with text 'UK' - this will attempt to match any field for UK
|
||||
// Also limit the query to return a maximum of 2 results using the size attribute
|
||||
|
||||
// query function has asynchronous behaviour and returns a promise object
|
||||
// (even for the case of in memory data where querying in fact happens synchronously)
|
||||
// On completion the display function will be called
|
||||
dataset.query({q: 'UK', size: 2}).done(function() {
|
||||
display(dataset);
|
||||
});
|
||||
|
||||
13
_includes/tutorial-basics-ex-events.js
Normal file
13
_includes/tutorial-basics-ex-events.js
Normal file
@ -0,0 +1,13 @@
|
||||
function onChange() {
|
||||
$('.ex-events').append('Queried: ' + dataset.queryState.get('q') + '. Records matching: ' + dataset.recordCount);
|
||||
$('.ex-events').append('<br />');
|
||||
}
|
||||
|
||||
dataset.currentRecords.bind('reset', onChange);
|
||||
|
||||
dataset.query({q: 'DE'});
|
||||
dataset.query({q: 'UK'});
|
||||
dataset.query({q: 'US'});
|
||||
|
||||
dataset.unbind('reset', onChange);
|
||||
|
||||
10
_includes/tutorial-basics-ex-fields-2.js
Normal file
10
_includes/tutorial-basics-ex-fields-2.js
Normal file
@ -0,0 +1,10 @@
|
||||
var $el = $('.ex-fields-2');
|
||||
|
||||
dataset.fields.models[6] = new recline.Model.Field({
|
||||
id: 'geo',
|
||||
label: 'Location',
|
||||
type: 'geo_point'
|
||||
});
|
||||
var rec = dataset.currentRecords.at(0);
|
||||
$el.append(dataset.recordSummary(rec));
|
||||
|
||||
20
_includes/tutorial-basics-ex-fields.js
Normal file
20
_includes/tutorial-basics-ex-fields.js
Normal file
@ -0,0 +1,20 @@
|
||||
var $el = $('.ex-fields');
|
||||
|
||||
// Now list the Fields of this Dataset (these will have be automatically extracted from the data)
|
||||
$el.append('Fields: ');
|
||||
// Dataset.fields is a Backbone collection of Fields (i.e. record attributes)
|
||||
dataset.fields.each(function(field) {
|
||||
$el.append(field.id + ' || ');
|
||||
});
|
||||
|
||||
$el.append('<hr />');
|
||||
|
||||
// Show all field info
|
||||
var json = dataset.fields.toJSON();
|
||||
$el.append(
|
||||
$('<pre />')
|
||||
.append(
|
||||
JSON.stringify(json, null, 2)
|
||||
)
|
||||
);
|
||||
|
||||
@ -11,11 +11,19 @@ root: ../
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
Backends connect Dataset and Documents to data from a specific 'Backend' data
|
||||
source. They provide methods for loading and saving Datasets and individuals
|
||||
Documents as well as for bulk loading via a query API and doing bulk transforms
|
||||
on the backend.
|
||||
|
||||
Backends come in 2 flavours:
|
||||
|
||||
1. Loader backends - only implement fetch method. The data is then cached in a Memory.Store on the Dataset and interacted with there. This is best for sources which just allow you to load data or where you want to load the data once and work with it locally.
|
||||
2. Store backends - these support fetch, query and, if write-enabled, save. These are suitable where the backend contains a lot of data (infeasible to load locally - for examples a million rows) or where the backend has capabilities you want to take advantage of.
|
||||
|
||||
|
||||
# Backend API
|
||||
|
||||
Backend modules must implement the following API:
|
||||
|
||||
{% highlight javascript %}
|
||||
|
||||
@ -52,53 +52,17 @@ root: ../
|
||||
<div class="row">
|
||||
<div class="span4">
|
||||
<div class="well">
|
||||
<h4><a href="example-quickstart.html">Recline Quickstart Guide</a></h4>
|
||||
<h4><a href="tutorial-basics.html">Dataset Basics - Creating, Querying, Using</a></h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="span4">
|
||||
<div class="well">
|
||||
<h4><a href="example-backends.html">Loading from difference sources: Google Docs, Local CSV, DataHub</a></h4>
|
||||
<h4><a href="tutorial-backends.html">Backends and loading data from Google Docs, Local CSV, DataHub and more</a></h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="span4">
|
||||
<div class="well">
|
||||
<h4>Twitter Example</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="span4">
|
||||
<div class="well">
|
||||
<h4>Customing Display and Import using Fields</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="span4">
|
||||
<div class="well">
|
||||
<h4>Listening to events</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="span4">
|
||||
<div class="well">
|
||||
<h4>Setting and Getting State</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Extending Recline</h3>
|
||||
<div class="row">
|
||||
<div class="span4">
|
||||
<div class="well">
|
||||
<h4>Create a new View</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="span4">
|
||||
<div class="well">
|
||||
<h4>Create a new Backend</h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="span4">
|
||||
<div class="well">
|
||||
<h4>Create a Custom Record Object</h4>
|
||||
<h4><a href="tutorial-views.html">Views Quickstart - Grids, Graphs, Maps and more</a></h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -21,7 +21,7 @@ holding summary information about a Field (or multiple Fields).
|
||||
All the models are Backbone models, that is they extend Backbone.Model. Note,
|
||||
however that they do not 'sync' (load/save) like normal Backbone models.
|
||||
|
||||
## Dataset
|
||||
<h2 id="dataset">Dataset</h2>
|
||||
|
||||
A Dataset is *the* central object in Recline. Standard usage is:
|
||||
|
||||
@ -159,7 +159,6 @@ field's value (if any) and the current record. It's signature and behaviour is
|
||||
the same as for renderer.
|
||||
|
||||
|
||||
|
||||
<h2 id="query">Query</h2>
|
||||
|
||||
Query instances encapsulate a query to the backend (see <a
|
||||
|
||||
@ -1,26 +1,24 @@
|
||||
---
|
||||
layout: container
|
||||
title: Library - Example - Loading data from different sources using Backends
|
||||
title: Tutorial - Backends - Loading data from different sources using Backends
|
||||
recline-deps: true
|
||||
root: ../
|
||||
---
|
||||
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
Loading data from different sources using Backends
|
||||
<br />
|
||||
<small>These set of examples will show you how you can load data from different
|
||||
sources such as Google Docs or the DataHub using Recline</small>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
These set of examples will show you how you can load data from different
|
||||
sources such as Google Docs or the DataHub using Recline.
|
||||
|
||||
<div class="alert alert-info">
|
||||
<p><strong>Note</strong>: often you are loading data from a given source in
|
||||
order to display it using the various Recline views. However, you can also
|
||||
happily use this data with your own code and app and this is a very common
|
||||
use-case.</p>
|
||||
<p>Moreover, Recline is designed so you need <strong>only</strong> include the
|
||||
backend and its dependencies without needing to include any of the dependencies
|
||||
for the view portion of the Recline library.</p>
|
||||
order to load it into a Recline Dataset and display it in a View. However, you can also
|
||||
happily use a Backend to load data on its own without using any other part of the Recline library as all the Backends are designed to have no dependency on other parts of Recline.</p>
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
@ -30,20 +28,18 @@ source. They provide methods for loading and saving Datasets and individuals
|
||||
Documents as well as for bulk loading via a query API and doing bulk transforms
|
||||
on the backend.
|
||||
|
||||
You can instantiate a backend directly e.g.
|
||||
You can use a backend directly e.g.
|
||||
|
||||
{% highlight javascript %}
|
||||
var backend = recline.Backend.ElasticSearch();
|
||||
var backend = recline.Backend.ElasticSearch.fetch({url: ...});
|
||||
{% endhighlight %}
|
||||
|
||||
But more usually the backend will be created or loaded for you by Recline and all you need is provide the identifier for that Backend e.g.
|
||||
|
||||
{% highlight javascript %}
|
||||
var dataset = recline.Model.Dataset({
|
||||
...
|
||||
},
|
||||
'backend-identifier'
|
||||
);
|
||||
backend: 'backend-identifier'
|
||||
});
|
||||
{% endhighlight %}
|
||||
|
||||
<div class="alert alert-info">
|
||||
@ -53,7 +49,6 @@ How do you know the backend identifier for a given Backend? It's just the name o
|
||||
|
||||
### Included Backends
|
||||
|
||||
* [memory: Memory Backend (local data)](docs/backend/memory.html)
|
||||
* [elasticsearch: ElasticSearch Backend](docs/backend/elasticsearch.html)
|
||||
* [dataproxy: DataProxy Backend (CSV and XLS on the Web)](docs/backend/dataproxy.html)
|
||||
* [gdocs: Google Docs (Spreadsheet) Backend](docs/backend/gdocs.html)
|
||||
@ -63,7 +58,7 @@ Backend not on this list that you would like to see? It's very easy to write a n
|
||||
|
||||
## Preparing your app
|
||||
|
||||
This is as per the [quickstart](example-quickstart.html) but the set of files is much more limited if you are just using a Backend. Specifically:
|
||||
This is as per the [quickstart](tutorial-views.html) but the set of files is much more limited if you are just using a Backend. Specifically:
|
||||
|
||||
{% highlight html %}
|
||||
<!-- 3rd party dependencies -->
|
||||
@ -71,8 +66,6 @@ This is as per the [quickstart](example-quickstart.html) but the set of files is
|
||||
<script type="text/javascript" src="vendor/underscore/1.1.6/underscore.js"></script>
|
||||
<script type="text/javascript" src="vendor/backbone/0.5.1/backbone.js"></script>
|
||||
<!-- include the backend code you need e.g. here for gdocs -->
|
||||
<script type="text/javascript" src="src/backend/base.js"></script>
|
||||
<script type="text/javascript" src="src/backend/memory.js"></script>
|
||||
<script type="text/javascript" src="src/backend/gdocs.js"></script>
|
||||
|
||||
<!-- Or you can just include all of recline. -->
|
||||
@ -110,5 +103,5 @@ a bespoke chooser and a Kartograph (svg-only) map.
|
||||
## Writing your own backend
|
||||
|
||||
Writing your own backend is easy to do. Details of the required API are in the
|
||||
[Backend documentation](docs/backend/base.html).
|
||||
[Backend documentation](docs/backends.html).
|
||||
|
||||
170
docs/tutorial-basics.markdown
Normal file
170
docs/tutorial-basics.markdown
Normal file
@ -0,0 +1,170 @@
|
||||
---
|
||||
layout: container
|
||||
title: Tutorial - Dataset Basics
|
||||
recline-deps: true
|
||||
root: ../
|
||||
---
|
||||
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
Getting Started with Datasets
|
||||
<br />
|
||||
<small>This step-by-step tutorial will quickly get you started withthe central Recline object: a Dataset</small>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
## Preparations
|
||||
|
||||
1. [Download ReclineJS]({{page.root}}download.html) and relevant dependencies.
|
||||
|
||||
2. Include the core dependencies for the Dataset model
|
||||
|
||||
{% highlight html %}<!-- 3rd party dependencies -->
|
||||
<script type="text/javascript" src="vendor/jquery/1.7.1/jquery.js"></script>
|
||||
<script type="text/javascript" src="vendor/underscore/1.1.6/underscore.js"></script>
|
||||
<script type="text/javascript" src="vendor/backbone/0.5.1/backbone.js"></script>
|
||||
<!-- Recline -->
|
||||
<script type="text/javascript" src="dist/recline.js"></script>{% endhighlight %}
|
||||
|
||||
## Creating a Dataset
|
||||
|
||||
Here's the example data We are going to work with:
|
||||
|
||||
{% highlight javascript %}
|
||||
{% include data.js %}
|
||||
{% endhighlight %}
|
||||
|
||||
In this data we have 6 records / rows. Each record is a javascript object
|
||||
containing keys and values (values can be 'simple' e.g. a string or float or arrays or hashes - e.g. the geo value here).
|
||||
|
||||
<div class="alert alert-info">In this tutorial we are creating datasets with
|
||||
"local" JS data. However, Recline has a variety of Backends that make it easy
|
||||
to create Datasets from a variety of online sources and local sources including
|
||||
Google Spreadsheets, CSV files, etc. See the <a
|
||||
href="tutorial-backends.html">Backend tutorial</a> for more.</div>
|
||||
|
||||
We can now create a recline Dataset object from this raw data:
|
||||
|
||||
{% highlight javascript %}
|
||||
var dataset = new recline.Model.Dataset({
|
||||
records: data
|
||||
});
|
||||
{% endhighlight %}
|
||||
|
||||
<script type="text/javascript">
|
||||
{% include data.js %}
|
||||
var dataset = new recline.Model.Dataset({
|
||||
records: data
|
||||
});
|
||||
</script>
|
||||
|
||||
## Records, Fields and more
|
||||
|
||||
Now that we have created a Dataset, we can use it.
|
||||
|
||||
For example, let's display some information about the Dataset and its records:
|
||||
|
||||
<div class="alert alert-info">You can find out more about Dataset and Records in the <a href="models.html">reference documentation</a></div>
|
||||
|
||||
{% highlight javascript %}
|
||||
{% include tutorial-basics-ex-1.js %}
|
||||
{% endhighlight %}
|
||||
|
||||
Here's the output:
|
||||
|
||||
<div class="ex-1 well"> </div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$('.ex-1').html('');
|
||||
{% include tutorial-basics-ex-1.js %}
|
||||
</script>
|
||||
|
||||
Note how the last geo attribute just rendered as `[object Object]`. This is because the Dataset is treating that field value as a string. Let's now take a look at the Dataset fields in more detail.
|
||||
|
||||
### Fields
|
||||
|
||||
In addition to Records, a Dataset has <a href="models.html#field">Fields</a> stored in the `fields` attribute. Fields provide information about the fields/columns in the Dataset, for example their id (key name in record), label, type etc.
|
||||
|
||||
The Dataset's fields will be automatically computed from records or provided by the backend but they can also be explicitly provided and configured. Let's take a look at the fields on the dataset at present using the following code:
|
||||
|
||||
{% highlight javascript %}
|
||||
{% include tutorial-basics-ex-fields.js %}
|
||||
{% endhighlight %}
|
||||
|
||||
Running this results in the following:
|
||||
|
||||
<div class="ex-fields well"> </div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$('.ex-fields').html('');
|
||||
{% include tutorial-basics-ex-fields.js %}
|
||||
</script>
|
||||
|
||||
As can be seen all fields have the default type of 'string'. Let's change the geo field to have type geo\_point and see what affect that has on displaying of the dataset (for good measure we'll also set the label):
|
||||
|
||||
{% highlight javascript %}
|
||||
{% include tutorial-basics-ex-fields-2.js %}
|
||||
{% endhighlight %}
|
||||
|
||||
<div class="ex-fields-2 well"> </div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$('.ex-fields-2').html('');
|
||||
{% include tutorial-basics-ex-fields-2.js %}
|
||||
</script>
|
||||
|
||||
As can be seen the rendering of the field has changed. This is because the `recordSummary` method uses the Record.getFieldValue function which in turn renders a record field using the Field's renderer function. This function varies depending on the type and can also be customized (see the <a href="models.html#field">Field documentation</a>).
|
||||
|
||||
|
||||
## Querying
|
||||
|
||||
The basic thing we want to do with Datasets is query and filter them. This is very easy to do:
|
||||
|
||||
{% highlight javascript %}
|
||||
{% include tutorial-basics-ex-2.js %}
|
||||
{% endhighlight %}
|
||||
|
||||
This results in the following. Note how recordCount is now 3 (the total number of records matched by the query) but that currentRecords only contains 2 records as we restricted number of returned records using the size attribute.
|
||||
|
||||
<div class="ex-2 well"> </div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$('.ex-2').html('');
|
||||
{% include tutorial-basics-ex-2.js %}
|
||||
</script>
|
||||
|
||||
Full details of the <a href="models.html#query">query structure and its options can be found in the reference documentation</a>.
|
||||
|
||||
Also worth noting is that the last run query is stored as a <a href="models.html#query">Query instance</a> in the `queryState` attribute of the Dataset object. Modifying `queryState` will also resulting in a query being run. This is useful when building views that want to display or manage the query state (see, for example, <a href="src/widget.queryeditor.html">Query Editor</a> or <a href="src/widget.filtereditor.html">Filter Editor</a> widgets).
|
||||
|
||||
|
||||
## Listening for Events
|
||||
|
||||
Often you'll want to listen to events on Datasets and its associated objects rather than have to explicitly notify. This is easy to do thanks to the use of Backbone model objects which have a [standard set of events](http://backbonejs.org/#FAQ-events).
|
||||
|
||||
Here's an example to illustrate:
|
||||
|
||||
{% highlight javascript %}
|
||||
{% include tutorial-basics-ex-events.js %}
|
||||
{% endhighlight %}
|
||||
|
||||
<div class="ex-events well"> </div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$('.ex-events').html('');
|
||||
{% include tutorial-basics-ex-events.js %}
|
||||
</script>
|
||||
|
||||
Here's a summary of the main objects and their events:
|
||||
|
||||
* Dataset:
|
||||
|
||||
* Standard Backbone events for changes to attributes (note that this will **not** include changes to records)
|
||||
* *query:start / query:end* called at start and completion of a query
|
||||
|
||||
* Dataset.currentRecords: Backbone.Collection of "current" records (i.e. those resulting from latest query) with standard Backbone set of events: *add, reset, remove*
|
||||
|
||||
* Dataset.queryState: queryState is a Query object with standard Backbone Model set of events
|
||||
|
||||
* Dataset.fields: Backbone Collection of Fields.
|
||||
|
||||
@ -2,13 +2,14 @@
|
||||
layout: container
|
||||
title: Library - Example - Quickstart
|
||||
recline-deps: true
|
||||
root: ../
|
||||
---
|
||||
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
Recline Quickstart Guide
|
||||
Views Tutorial
|
||||
<br />
|
||||
<small>This step-by-step guide will quickly get you started with Recline basics, including creating a dataset from local data and setting up a grid, graph and map to display it.</small>
|
||||
<small>This step-by-step tutorial will quickly get you started with Recline basics, including creating a dataset from local data and setting up a grid, graph and map to display it.</small>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
@ -16,7 +17,7 @@ recline-deps: true
|
||||
|
||||
Before writing any code with Recline, you need to do the following preparation steps on your page:
|
||||
|
||||
1. [Download ReclineJS](download.html) and relevant dependencies.
|
||||
1. [Download ReclineJS]({{page.root}}download.html) and relevant dependencies.
|
||||
2. Include the relevant CSS in the head section of your document:
|
||||
{% highlight html %}
|
||||
<!-- you do not have to use bootstrap but we use it by default -->
|
||||
@ -33,16 +34,11 @@ Before writing any code with Recline, you need to do the following preparation s
|
||||
<script type="text/javascript" src="vendor/bootstrap/2.0.2/bootstrap.js"></script>
|
||||
<!-- note that we could include individual components rather than whole of recline e.g.
|
||||
<script type="text/javascript" src="src/model.js"></script>
|
||||
<script type="text/javascript" src="src/backend/base.js"></script>
|
||||
<script type="text/javascript" src="src/backend/memory.js"></script>
|
||||
<script type="text/javascript" src="src/view-grid.js"></script>
|
||||
-->
|
||||
<script type="text/javascript" src="dist/recline.js"></script>{% endhighlight %}
|
||||
|
||||
4. Create a div to hold the Recline view(s):
|
||||
{% highlight html %}
|
||||
<div id="mygrid"></div>{% endhighlight %}
|
||||
|
||||
You're now ready to start working with Recline.
|
||||
|
||||
### Creating a Dataset
|
||||
@ -60,37 +56,62 @@ no reason you cannot have objects as values allowing you to nest data.
|
||||
We can now create a recline Dataset object (and memory backend) from this raw data:
|
||||
|
||||
{% highlight javascript %}
|
||||
var dataset = recline.Backend.Memory.createDataset(data);
|
||||
var dataset = new recline.Model.Dataset({
|
||||
records: data
|
||||
});
|
||||
{% endhighlight %}
|
||||
|
||||
Note that behind the scenes Recline will create a Memory backend for this dataset as in Recline every dataset object must have a backend from which it can push and pull data. In the case of in-memory data this is a little artificial since all the data is available locally but this makes more sense for situations where one is connecting to a remote data source (and one which may contain a lot of data).
|
||||
|
||||
|
||||
### Setting up the Grid
|
||||
|
||||
Let's create a data grid view to display the dataset we have just created, binding the view to the `<div id="mygrid"></div>` we created earlier:
|
||||
|
||||
Let's create a data grid view to display the dataset we have just created. We're going to use the SlickGrid-based grid so we need the following:
|
||||
|
||||
{% highlight html %}
|
||||
<link rel="stylesheet" href="css/slickgrid.css">
|
||||
|
||||
<!-- vendor -->
|
||||
<script type="text/javascript" src="{{page.root}}vendor/slickgrid/2.0.1/jquery-ui-1.8.16.custom.min.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/slickgrid/2.0.1/jquery.event.drag-2.0.min.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/slickgrid/2.0.1/slick.grid.min.js"></script>
|
||||
|
||||
<!-- Recline -->
|
||||
<script type="text/javascript" src="src/view.slickgrid.js"></script>
|
||||
{% endhighlight %}
|
||||
|
||||
Now, let's create an HTML element to for the Grid:
|
||||
|
||||
{% highlight html %}
|
||||
<div id="mygrid" style="height: 400px"></div>
|
||||
{% endhighlight %}
|
||||
|
||||
Now let's set up the Grid:
|
||||
|
||||
{% highlight javascript %}
|
||||
var $el = $('#mygrid');
|
||||
var grid = new recline.View.Grid({
|
||||
model: dataset
|
||||
var grid = new recline.View.SlickGrid({
|
||||
model: dataset,
|
||||
el: $el
|
||||
});
|
||||
$el.append(grid.el);
|
||||
grid.visible = true;
|
||||
grid.render();
|
||||
{% endhighlight %}
|
||||
|
||||
And hey presto:
|
||||
|
||||
<div id="mygrid" class="recline-read-only" style="margin-bottom: 30px; margin-top: -20px;"> </div>
|
||||
<div id="mygrid" class="recline-read-only" style="margin-bottom: 30px; height: 200px;"> </div>
|
||||
|
||||
<script type="text/javascript">
|
||||
{% include data.js %}
|
||||
var dataset = recline.Backend.Memory.createDataset(data);
|
||||
var $el = $('#mygrid');
|
||||
var grid = new recline.View.Grid({
|
||||
model: dataset,
|
||||
var dataset = new recline.Model.Dataset({
|
||||
records: data
|
||||
});
|
||||
$el.append(grid.el);
|
||||
var $el = $('#mygrid');
|
||||
var grid = new recline.View.SlickGrid({
|
||||
model: dataset,
|
||||
el: $el
|
||||
});
|
||||
grid.visible = true;
|
||||
grid.render();
|
||||
</script>
|
||||
|
||||
@ -106,7 +127,7 @@ library and the Recline Graph view:
|
||||
|
||||
<!-- javascript -->
|
||||
<script type="text/javascript" src="vendor/jquery.flot/0.7/jquery.flot.js"></script>
|
||||
<script type="text/javascript" src="src/view-graph.js"></script>
|
||||
<script type="text/javascript" src="src/view.graph.js"></script>
|
||||
{% endhighlight %}
|
||||
|
||||
Next, create a new div for the graph:
|
||||
@ -115,35 +136,15 @@ Next, create a new div for the graph:
|
||||
<div id="mygraph"></div>
|
||||
{% endhighlight %}
|
||||
|
||||
Now let's create the graph, we will use the same dataset we had earlier:
|
||||
Now let's create the graph, we will use the same dataset we had earlier, and we will need to set the view 'state' in order to configure the graph with the column to use for the x-axis ("group") and the columns to use for the series to show ("series").
|
||||
|
||||
{% highlight javascript %}
|
||||
var $el = $('#mygraph');
|
||||
var graph = new recline.View.Graph({
|
||||
model: dataset
|
||||
});
|
||||
$el.append(grid.el);
|
||||
graph.render();
|
||||
{% endhighlight %}
|
||||
|
||||
And ... we have a graph view -- with instructions on how to use the controls to
|
||||
create a graph -- but no graph. Go ahead and play around with the controls to
|
||||
create a graph of your choosing:
|
||||
|
||||
<div id="mygraph" style="margin-bottom: 30px;"> </div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var $el = $('#mygraph');
|
||||
var graph = new recline.View.Graph({
|
||||
model: dataset
|
||||
});
|
||||
$el.append(graph.el);
|
||||
graph.render();
|
||||
</script>
|
||||
|
||||
But suppose you wanted to create a graph not a graph editor. This is
|
||||
straightforward to do -- all we need to do is set the 'state' of the graph
|
||||
view:
|
||||
<div class="alert alert-info">
|
||||
<strong>State</strong>: The concept of a state is a common feature of Recline views being an object
|
||||
which stores information about the state and configuration of a given view. You
|
||||
can read more about it in the general <a href="../docs/views.html">Views
|
||||
documentation</a> as well as the documentation of individual views such as the
|
||||
<a href="../docs/src/view.graph.html">Graph View</a>.
|
||||
</div>
|
||||
|
||||
{% highlight javascript %}
|
||||
var $el = $('#mygraph');
|
||||
@ -158,12 +159,12 @@ $el.append(graph.el);
|
||||
graph.redraw();
|
||||
{% endhighlight %}
|
||||
|
||||
We would get this rendered graph:
|
||||
The result is the following graph:
|
||||
|
||||
<div id="mygraph2" style="margin-bottom: 30px;"> </div>
|
||||
<div id="mygraph" style="margin-bottom: 30px;"> </div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var $el = $('#mygraph2');
|
||||
var $el = $('#mygraph');
|
||||
var graph = new recline.View.Graph({
|
||||
model: dataset,
|
||||
state: {
|
||||
@ -176,14 +177,6 @@ $el.append(graph.el);
|
||||
graph.redraw();
|
||||
</script>
|
||||
|
||||
<div class="alert alert-info">
|
||||
<strong>State</strong>: The concept of a state is a common feature of Recline views being an object
|
||||
which stores information about the state and configuration of a given view. You
|
||||
can read more about it in the general <a href="../docs/view.html">Views
|
||||
documentation</a> as well as the documentation of individual views such as the
|
||||
<a href="../docs/view-graph.html">Graph View</a>.
|
||||
</div>
|
||||
|
||||
### Creating a Map
|
||||
|
||||
Now, let's create a map of this dataset using the lon/lat information which is
|
||||
@ -9,9 +9,10 @@ title: Download
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
Besides the library itself, the download package contains full source code,
|
||||
unit tests, files for debugging and a build system. The production files
|
||||
(included the same way as in the code above) are in the dist folder.
|
||||
Besides the library itself, the download package contains full source
|
||||
code, unit tests, external vendor libraries and documentation. The
|
||||
production files (included the same way as in the code above) are in the
|
||||
dist folder.
|
||||
|
||||
<p><a href="https://github.com/okfn/recline/zipball/master" class="btn">Download Recline v0.5 (master)</a> (in-progress version)</p>
|
||||
|
||||
|
||||
@ -6,6 +6,9 @@ this.recline.Backend.DataProxy = this.recline.Backend.DataProxy || {};
|
||||
my.__type__ = 'dataproxy';
|
||||
// URL for the dataproxy
|
||||
my.dataproxy_url = 'http://jsonpdataproxy.appspot.com';
|
||||
// Timeout for dataproxy (after this time if no response we error)
|
||||
// Needed because use JSONP so do not receive e.g. 500 errors
|
||||
my.timeout = 5000;
|
||||
|
||||
// ## load
|
||||
//
|
||||
@ -48,12 +51,11 @@ this.recline.Backend.DataProxy = this.recline.Backend.DataProxy || {};
|
||||
// a crude way to catch those errors.
|
||||
var _wrapInTimeout = function(ourFunction) {
|
||||
var dfd = $.Deferred();
|
||||
var timeout = 5000;
|
||||
var timer = setTimeout(function() {
|
||||
dfd.reject({
|
||||
message: 'Request Error: Backend did not respond after ' + (timeout / 1000) + ' seconds'
|
||||
message: 'Request Error: Backend did not respond after ' + (my.timeout / 1000) + ' seconds'
|
||||
});
|
||||
}, timeout);
|
||||
}, my.timeout);
|
||||
ourFunction.done(function(arguments) {
|
||||
clearTimeout(timer);
|
||||
dfd.resolve(arguments);
|
||||
|
||||
36
src/model.js
36
src/model.js
@ -27,7 +27,7 @@ my.Dataset = Backbone.Model.extend({
|
||||
creates: []
|
||||
};
|
||||
this.facets = new my.FacetList();
|
||||
this.docCount = null;
|
||||
this.recordCount = null;
|
||||
this.queryState = new my.Query();
|
||||
this.queryState.bind('change', this.query);
|
||||
this.queryState.bind('facet:add', this.query);
|
||||
@ -178,7 +178,7 @@ my.Dataset = Backbone.Model.extend({
|
||||
this.trigger('query:start');
|
||||
|
||||
if (queryObj) {
|
||||
this.queryState.set(queryObj);
|
||||
this.queryState.set(queryObj, {silent: true});
|
||||
}
|
||||
var actualQuery = this.queryState.toJSON();
|
||||
|
||||
@ -197,7 +197,7 @@ my.Dataset = Backbone.Model.extend({
|
||||
|
||||
_handleQueryResult: function(queryResult) {
|
||||
var self = this;
|
||||
self.docCount = queryResult.total;
|
||||
self.recordCount = queryResult.total;
|
||||
var docs = _.map(queryResult.hits, function(hit) {
|
||||
var _doc = new my.Record(hit);
|
||||
_doc.bind('change', function(doc) {
|
||||
@ -220,11 +220,13 @@ my.Dataset = Backbone.Model.extend({
|
||||
|
||||
toTemplateJSON: function() {
|
||||
var data = this.toJSON();
|
||||
data.docCount = this.docCount;
|
||||
data.recordCount = this.recordCount;
|
||||
data.fields = this.fields.toJSON();
|
||||
return data;
|
||||
},
|
||||
|
||||
// ### getFieldsSummary
|
||||
//
|
||||
// Get a summary for each field in the form of a `Facet`.
|
||||
//
|
||||
// @return null as this is async function. Provides deferred/promise interface.
|
||||
@ -250,6 +252,19 @@ my.Dataset = Backbone.Model.extend({
|
||||
return dfd.promise();
|
||||
},
|
||||
|
||||
// ### recordSummary
|
||||
//
|
||||
// Get a simple html summary of a Dataset record in form of key/value list
|
||||
recordSummary: function(record) {
|
||||
var html = '';
|
||||
this.fields.each(function(field) {
|
||||
if (field.id != 'id') {
|
||||
html += '<div><strong span="key">' + field.get('label') + '</strong>: ' + record.getFieldValue(field) + '</div>';
|
||||
}
|
||||
});
|
||||
return html;
|
||||
},
|
||||
|
||||
// ### _backendFromString(backendString)
|
||||
//
|
||||
// See backend argument to initialize for details
|
||||
@ -344,16 +359,6 @@ my.Record = Backbone.Model.extend({
|
||||
return val;
|
||||
},
|
||||
|
||||
summary: function(fields) {
|
||||
var html = '';
|
||||
for (key in this.attributes) {
|
||||
if (key != 'id') {
|
||||
html += '<div><strong>' + key + '</strong>: '+ this.attributes[key] + '</div>';
|
||||
}
|
||||
}
|
||||
return html;
|
||||
},
|
||||
|
||||
// Override Backbone save, fetch and destroy so they do nothing
|
||||
// Instead, Dataset object that created this Record should take care of
|
||||
// handling these changes (discovery will occur via event notifications)
|
||||
@ -404,6 +409,9 @@ my.Field = Backbone.Model.extend({
|
||||
object: function(val, field, doc) {
|
||||
return JSON.stringify(val);
|
||||
},
|
||||
geo_point: function(val, field, doc) {
|
||||
return JSON.stringify(val);
|
||||
},
|
||||
'float': function(val, field, doc) {
|
||||
var format = field.get('format');
|
||||
if (format === 'percentage') {
|
||||
|
||||
@ -35,7 +35,7 @@ my.Map = Backbone.View.extend({
|
||||
// If not found, the user will need to define the fields via the editor.
|
||||
latitudeFieldNames: ['lat','latitude'],
|
||||
longitudeFieldNames: ['lon','longitude'],
|
||||
geometryFieldNames: ['geojson', 'geom','the_geom','geometry','spatial','location'],
|
||||
geometryFieldNames: ['geojson', 'geom','the_geom','geometry','spatial','location', 'geo', 'lonlat'],
|
||||
|
||||
initialize: function(options) {
|
||||
var self = this;
|
||||
|
||||
@ -83,7 +83,7 @@ my.MultiView = Backbone.View.extend({
|
||||
</div> \
|
||||
</div> \
|
||||
<div class="recline-results-info"> \
|
||||
<span class="doc-count">{{docCount}}</span> records\
|
||||
<span class="doc-count">{{recordCount}}</span> records\
|
||||
</div> \
|
||||
<div class="menu-right"> \
|
||||
<div class="btn-group" data-toggle="buttons-checkbox"> \
|
||||
@ -166,7 +166,7 @@ my.MultiView = Backbone.View.extend({
|
||||
});
|
||||
this.model.bind('query:done', function() {
|
||||
self.clearNotifications();
|
||||
self.el.find('.doc-count').text(self.model.docCount || 'Unknown');
|
||||
self.el.find('.doc-count').text(self.model.recordCount || 'Unknown');
|
||||
});
|
||||
this.model.bind('query:fail', function(error) {
|
||||
self.clearNotifications();
|
||||
|
||||
@ -11,6 +11,8 @@ this.recline.View = this.recline.View || {};
|
||||
// https://github.com/mleibman/SlickGrid
|
||||
//
|
||||
// Initialize it with a `recline.Model.Dataset`.
|
||||
//
|
||||
// NB: you need an explicit height on the element for slickgrid to work
|
||||
my.SlickGrid = Backbone.View.extend({
|
||||
tagName: "div",
|
||||
className: "recline-slickgrid",
|
||||
@ -18,6 +20,7 @@ my.SlickGrid = Backbone.View.extend({
|
||||
initialize: function(modelEtc) {
|
||||
var self = this;
|
||||
this.el = $(this.el);
|
||||
this.el.addClass('recline-slickgrid');
|
||||
_.bindAll(this, 'render');
|
||||
this.model.currentRecords.bind('add', this.render);
|
||||
this.model.currentRecords.bind('reset', this.render);
|
||||
@ -56,7 +59,6 @@ my.SlickGrid = Backbone.View.extend({
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
this.el = $(this.el);
|
||||
|
||||
var options = {
|
||||
enableCellNavigation: true,
|
||||
|
||||
@ -94,14 +94,14 @@ test('DataProxy Backend', function() {
|
||||
expect(6);
|
||||
dataset.fetch().then(function() {
|
||||
deepEqual(['__id__', 'date', 'price'], _.pluck(dataset.fields.toJSON(), 'id'));
|
||||
equal(10, dataset.docCount)
|
||||
equal(10, dataset.recordCount)
|
||||
equal(dataset.currentRecords.models[0].get('date'), "1950-01");
|
||||
// needed only if not stubbing
|
||||
// start();
|
||||
});
|
||||
|
||||
dataset.query({q: '1950-01'}).then(function() {
|
||||
equal(dataset.docCount, 1);
|
||||
equal(dataset.recordCount, 1);
|
||||
equal(dataset.currentRecords.models[0].get('price'), '34.73');
|
||||
});
|
||||
$.ajax.restore();
|
||||
|
||||
@ -280,7 +280,7 @@ test("query", function() {
|
||||
dataset.fetch().done(function(dataset) {
|
||||
deepEqual(['_created', '_last_modified', 'end', 'owner', 'start', 'title'], _.pluck(dataset.fields.toJSON(), 'id'));
|
||||
dataset.query().then(function(recList) {
|
||||
equal(3, dataset.docCount);
|
||||
equal(3, dataset.recordCount);
|
||||
equal(3, recList.length);
|
||||
equal('Note 1', recList.models[0].get('title'));
|
||||
start();
|
||||
|
||||
@ -178,7 +178,7 @@ test('basics', function () {
|
||||
dataset.fetch().then(function(datasetAgain) {
|
||||
equal(dataset.get('name'), memoryData.metadata.name);
|
||||
deepEqual(_.pluck(dataset.fields.toJSON(), 'id'), _.pluck(data.fields, 'id'));
|
||||
equal(dataset.docCount, 6);
|
||||
equal(dataset.recordCount, 6);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@ -44,13 +44,19 @@ test('Field: default renderers', function () {
|
||||
myobject: {a: 1, b: 2},
|
||||
link: 'http://abc.com/',
|
||||
link2: 'Some text then https://abc.com/',
|
||||
markdown: '### ABC'
|
||||
markdown: '### ABC',
|
||||
geopoint: [18.7, -122]
|
||||
});
|
||||
var field = new recline.Model.Field({id: 'myobject', type: 'object'});
|
||||
var out = doc.getFieldValue(field);
|
||||
var exp = '{"a":1,"b":2}';
|
||||
equal(out, exp);
|
||||
|
||||
var field = new recline.Model.Field({id: 'geopoint', type: 'geo_point'});
|
||||
var out = doc.getFieldValue(field);
|
||||
var exp = '[18.7,-122]';
|
||||
equal(out, exp);
|
||||
|
||||
var field = new recline.Model.Field({id: 'x', type: 'float', format: 'percentage'});
|
||||
var out = doc.getFieldValue(field);
|
||||
var exp = '12.3%';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user