Merge branch 'master' into gh-pages
1
.gitignore
vendored
@ -3,3 +3,4 @@ sandbox/*
|
||||
.*.swp
|
||||
.*.swo
|
||||
_site/*
|
||||
node_modules/*
|
||||
|
||||
@ -33,7 +33,11 @@ Note that the demos and documentation utilize the [jekyll templating
|
||||
system][jekyll] and to use them *locally* you will need to build them using
|
||||
jekyll. Once installed, all you need to do from the command line is run jekyll:
|
||||
|
||||
jekyll
|
||||
jekyll serve
|
||||
|
||||
or if you're actively developing and want auto-reloading:
|
||||
|
||||
jekyll serve --watch
|
||||
|
||||
[jekyll]: https://github.com/mojombo/jekyll
|
||||
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
pygments: true
|
||||
auto: true
|
||||
highlighter: pygments
|
||||
markdown: kramdown
|
||||
|
||||
title: Recline Data Explorer and Library
|
||||
|
||||
@ -14,7 +14,8 @@ dataset.fetch();
|
||||
|
||||
// show the data for illustrations sake
|
||||
var grid = new recline.View.SlickGrid({
|
||||
model: dataset
|
||||
model: dataset,
|
||||
el: $('#my-online-csv')
|
||||
});
|
||||
$('#my-online-csv').append(grid.el);
|
||||
grid.visible = true;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<link rel="stylesheet" href="{{page.root}}vendor/leaflet/0.4.4/leaflet.css">
|
||||
<link rel="stylesheet" href="{{page.root}}vendor/leaflet/0.7.3/leaflet.css">
|
||||
<!--[if lte IE 8]>
|
||||
<link rel="stylesheet" href="{{page.root}}vendor/leaflet/0.4.4/leaflet.ie.css" />
|
||||
<link rel="stylesheet" href="{{page.root}}vendor/leaflet/0.7.3/leaflet.ie.css" />
|
||||
<![endif]-->
|
||||
<link rel="stylesheet" href="{{page.root}}vendor/leaflet.markercluster/MarkerCluster.css">
|
||||
<link rel="stylesheet" href="{{page.root}}vendor/leaflet.markercluster/MarkerCluster.Default.css">
|
||||
@ -31,7 +31,7 @@
|
||||
<![endif]-->
|
||||
<script type="text/javascript" src="{{page.root}}vendor/flot/jquery.flot.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/flot/jquery.flot.time.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/leaflet/0.4.4/leaflet.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/leaflet/0.7.3/leaflet.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/leaflet.markercluster/leaflet.markercluster.js"></script>
|
||||
<script type="text/javascript" src="{{page.root}}vendor/slickgrid/2.0.1/jquery-ui-1.8.16.custom.min.js"></script>
|
||||
<script src="{{page.root}}vendor/slickgrid/2.0.1/jquery.event.drag-2.2.js"></script>
|
||||
|
||||
7
_includes/views-list.html
Normal file
@ -0,0 +1,7 @@
|
||||
* <a href="{{page.root}}/docs/src/view.grid.html">Grid (simple)</a>
|
||||
* <a href="{{page.root}}/docs/src/view.slickgrid.html">Grid (SlickGrid)</a>
|
||||
* <a href="{{page.root}}/docs/src/view.map.html">Map</a>
|
||||
* <a href="https://github.com/NuCivic/recline.view.choroplethmap.js">Choropleth Map</a>
|
||||
* <a href="{{page.root}}/docs/src/view.graph.html">Graph</a>
|
||||
* <a href="{{page.root}}/docs/src/view.timeline.html">Timeline</a>
|
||||
* <a href="{{page.root}}/docs/src/view.multiview.html">Multiview (combines views)</a>
|
||||
@ -66,11 +66,20 @@ a:hover {
|
||||
font-weight:400;
|
||||
letter-spacing:-1px;
|
||||
line-height: 32px;
|
||||
text-shadow: none !important;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.navbar .nav > li > a {
|
||||
padding: 15px 10px;
|
||||
font-size: 13px;
|
||||
text-shadow: none !important;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.navbar .nav > li > a:focus,
|
||||
.navbar .nav > li > a:hover {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.navbar .divider-vertical {
|
||||
@ -212,3 +221,6 @@ section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#my-online-csv {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
@ -77,7 +77,7 @@ var createMultiView = function(dataset, state) {
|
||||
enabledAddRow: true,
|
||||
// Enable support for row delete
|
||||
enabledDelRow: true,
|
||||
// Enable support for row Reoder
|
||||
// Enable support for row ReOrder
|
||||
enableReOrderRow:true,
|
||||
autoEdit: false,
|
||||
enableCellNavigation: true
|
||||
|
||||
283
dist/recline.js
vendored
@ -3066,37 +3066,7 @@ this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
"use strict";
|
||||
// Add new grid Control to display a new row add menu bouton
|
||||
// It display a simple side-bar menu ,for user to add new
|
||||
// row to grid
|
||||
|
||||
my.GridControl= Backbone.View.extend({
|
||||
className: "recline-row-add",
|
||||
// Template for row edit menu , change it if you don't love
|
||||
template: '<h1><a href="#" class="recline-row-add btn">Add row</a></h1>',
|
||||
|
||||
initialize: function(options){
|
||||
var self = this;
|
||||
_.bindAll(this, 'render');
|
||||
this.state = new recline.Model.ObjectState();
|
||||
this.render();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
this.$el.html(this.template)
|
||||
},
|
||||
|
||||
events : {
|
||||
"click .recline-row-add" : "addNewRow"
|
||||
},
|
||||
|
||||
addNewRow : function(e){
|
||||
e.preventDefault()
|
||||
this.state.trigger("change")
|
||||
}
|
||||
}
|
||||
);
|
||||
// ## SlickGrid Dataset View
|
||||
//
|
||||
// Provides a tabular view on a Dataset, based on SlickGrid.
|
||||
@ -3117,7 +3087,11 @@ this.recline.View = this.recline.View || {};
|
||||
// state: {
|
||||
// gridOptions: {
|
||||
// editable: true,
|
||||
// enableAddRows: true
|
||||
// enableAddRow: true
|
||||
// // Enable support for row delete
|
||||
// enabledDelRow: true,
|
||||
// // Enable support for row Reorder
|
||||
// enableReOrderRow:true,
|
||||
// ...
|
||||
// },
|
||||
// columnsEditor: [
|
||||
@ -3131,10 +3105,10 @@ my.SlickGrid = Backbone.View.extend({
|
||||
initialize: function(modelEtc) {
|
||||
var self = this;
|
||||
this.$el.addClass('recline-slickgrid');
|
||||
|
||||
|
||||
// Template for row delete menu , change it if you don't love
|
||||
this.templates = {
|
||||
"deleterow" : '<a href="#" class="recline-row-delete btn" title="Delete row">X</a>'
|
||||
"deleterow" : '<a href="#" class="recline-row-delete btn" title="Delete row">X</a>'
|
||||
};
|
||||
|
||||
_.bindAll(this, 'render', 'onRecordChanged');
|
||||
@ -3156,15 +3130,16 @@ my.SlickGrid = Backbone.View.extend({
|
||||
|
||||
//add menu for new row , check if enableAddRow is set to true or not set
|
||||
if(this.state.get("gridOptions")
|
||||
&& this.state.get("gridOptions").enabledAddRow != undefined
|
||||
&& this.state.get("gridOptions").enabledAddRow != undefined
|
||||
&& this.state.get("gridOptions").enabledAddRow == true ){
|
||||
this.editor = new my.GridControl()
|
||||
this.elSidebar = this.editor.$el
|
||||
this.listenTo(this.editor.state, 'change', function(){
|
||||
this.model.records.add(new recline.Model.Record())
|
||||
this.listenTo(this.editor.state, 'change', function(){
|
||||
this.model.records.add(new recline.Model.Record())
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onRecordChanged: function(record) {
|
||||
// Ignore if the grid is not yet drawn
|
||||
if (!this.grid) {
|
||||
@ -3176,7 +3151,8 @@ my.SlickGrid = Backbone.View.extend({
|
||||
this.grid.getData().updateItem(record, row_index);
|
||||
this.grid.render();
|
||||
},
|
||||
render: function() {
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
var options = _.extend({
|
||||
enableCellNavigation: true,
|
||||
@ -3188,43 +3164,40 @@ my.SlickGrid = Backbone.View.extend({
|
||||
|
||||
// We need all columns, even the hidden ones, to show on the column picker
|
||||
var columns = [];
|
||||
|
||||
// custom formatter as default one escapes html
|
||||
// plus this way we distinguish between rendering/formatting and computed value (so e.g. sort still works ...)
|
||||
// row = row index, cell = cell index, value = value, columnDef = column definition, dataContext = full row values
|
||||
var formatter = function(row, cell, value, columnDef, dataContext) {
|
||||
if(columnDef.id == "del"){
|
||||
return self.templates.deleterow
|
||||
}
|
||||
var field = self.model.fields.get(columnDef.id);
|
||||
}
|
||||
var field = self.model.fields.get(columnDef.id);
|
||||
if (field.renderer) {
|
||||
return field.renderer(value, field, dataContext);
|
||||
}else {
|
||||
} else {
|
||||
return value
|
||||
}
|
||||
};
|
||||
|
||||
// we need to be sure that user is entering a valid input , for exemple if
|
||||
// field is date type and field.format ='YY-MM-DD', we should be sure that
|
||||
// user enter a correct value
|
||||
var validator = function(field){
|
||||
return function(value){
|
||||
if(field.type == "date" && isNaN(Date.parse(value))){
|
||||
return {
|
||||
valid: false,
|
||||
msg: "A date is required, check field field-date-format"};
|
||||
}else {
|
||||
return {valid: true, msg :null }
|
||||
}
|
||||
}
|
||||
var validator = function(field) {
|
||||
return function(value){
|
||||
if (field.type == "date" && isNaN(Date.parse(value))){
|
||||
return {
|
||||
valid: false,
|
||||
msg: "A date is required, check field field-date-format"
|
||||
};
|
||||
} else {
|
||||
return {valid: true, msg :null }
|
||||
}
|
||||
}
|
||||
};
|
||||
//Add row delete support, check if enableReOrderRow is set to true , by
|
||||
//default it is set to false
|
||||
// state: {
|
||||
// gridOptions: {
|
||||
// enableReOrderRow: true,
|
||||
// },
|
||||
if(this.state.get("gridOptions")
|
||||
&& this.state.get("gridOptions").enableReOrderRow != undefined
|
||||
&& this.state.get("gridOptions").enableReOrderRow == true ){
|
||||
|
||||
// Add column for row reorder support
|
||||
if (this.state.get("gridOptions") && this.state.get("gridOptions").enableReOrderRow == true) {
|
||||
columns.push({
|
||||
id: "#",
|
||||
name: "",
|
||||
@ -3235,15 +3208,8 @@ my.SlickGrid = Backbone.View.extend({
|
||||
cssClass: "recline-cell-reorder"
|
||||
})
|
||||
}
|
||||
//Add row delete support, check if enabledDelRow is set to true , by
|
||||
//default it is set to false
|
||||
// state: {
|
||||
// gridOptions: {
|
||||
// enabledDelRow: true,
|
||||
// },
|
||||
if(this.state.get("gridOptions")
|
||||
&& this.state.get("gridOptions").enabledDelRow != undefined
|
||||
&& this.state.get("gridOptions").enabledDelRow == true ){
|
||||
// Add column for row delete support
|
||||
if (this.state.get("gridOptions") && this.state.get("gridOptions").enabledDelRow == true) {
|
||||
columns.push({
|
||||
id: 'del',
|
||||
name: '',
|
||||
@ -3254,6 +3220,7 @@ my.SlickGrid = Backbone.View.extend({
|
||||
validator:validator
|
||||
})
|
||||
}
|
||||
|
||||
_.each(this.model.fields.toJSON(),function(field){
|
||||
var column = {
|
||||
id: field.id,
|
||||
@ -3315,16 +3282,17 @@ my.SlickGrid = Backbone.View.extend({
|
||||
}
|
||||
}
|
||||
columns = columns.concat(tempHiddenColumns);
|
||||
|
||||
// Transform a model object into a row
|
||||
function toRow(m) {
|
||||
var row = {};
|
||||
self.model.fields.each(function(field){
|
||||
var render = "";
|
||||
self.model.fields.each(function(field) {
|
||||
var render = "";
|
||||
//when adding row from slickgrid the field value is undefined
|
||||
if(!_.isUndefined(m.getFieldValueUnrendered(field))){
|
||||
render =m.getFieldValueUnrendered(field)
|
||||
}
|
||||
row[field.id] = render
|
||||
if(!_.isUndefined(m.getFieldValueUnrendered(field))){
|
||||
render =m.getFieldValueUnrendered(field)
|
||||
}
|
||||
row[field.id] = render
|
||||
});
|
||||
return row;
|
||||
}
|
||||
@ -3347,7 +3315,6 @@ my.SlickGrid = Backbone.View.extend({
|
||||
rows[i] = toRow(m);
|
||||
models[i] = m;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
var data = new RowSet();
|
||||
@ -3365,70 +3332,9 @@ my.SlickGrid = Backbone.View.extend({
|
||||
this.grid.setSortColumn(column, sortAsc);
|
||||
}
|
||||
|
||||
|
||||
/* Row reordering support based on
|
||||
https://github.com/mleibman/SlickGrid/blob/gh-pages/examples/example9-row-reordering.html
|
||||
|
||||
*/
|
||||
self.grid.setSelectionModel(new Slick.RowSelectionModel());
|
||||
|
||||
var moveRowsPlugin = new Slick.RowMoveManager({
|
||||
cancelEditOnDrag: true
|
||||
});
|
||||
|
||||
moveRowsPlugin.onBeforeMoveRows.subscribe(function (e, data) {
|
||||
for (var i = 0; i < data.rows.length; i++) {
|
||||
// no point in moving before or after itself
|
||||
if (data.rows[i] == data.insertBefore || data.rows[i] == data.insertBefore - 1) {
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
moveRowsPlugin.onMoveRows.subscribe(function (e, args) {
|
||||
|
||||
var extractedRows = [], left, right;
|
||||
var rows = args.rows;
|
||||
var insertBefore = args.insertBefore;
|
||||
|
||||
var data = self.model.records.toJSON()
|
||||
left = data.slice(0, insertBefore);
|
||||
right= data.slice(insertBefore, data.length);
|
||||
|
||||
rows.sort(function(a,b) { return a-b; });
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
extractedRows.push(data[rows[i]]);
|
||||
}
|
||||
|
||||
rows.reverse();
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
if (row < insertBefore) {
|
||||
left.splice(row, 1);
|
||||
} else {
|
||||
right.splice(row - insertBefore, 1);
|
||||
}
|
||||
}
|
||||
|
||||
data = left.concat(extractedRows.concat(right));
|
||||
var selectedRows = [];
|
||||
for (var i = 0; i < rows.length; i++)
|
||||
selectedRows.push(left.length + i);
|
||||
|
||||
self.model.records.reset(data)
|
||||
|
||||
});
|
||||
//register The plugin to handle row Reorder
|
||||
if(this.state.get("gridOptions")
|
||||
&& this.state.get("gridOptions").enableReOrderRow != undefined
|
||||
&& this.state.get("gridOptions").enableReOrderRow == true ){
|
||||
self.grid.registerPlugin(moveRowsPlugin);
|
||||
if (this.state.get("gridOptions") && this.state.get("gridOptions").enableReOrderRow) {
|
||||
this._setupRowReordering();
|
||||
}
|
||||
/* end row reordering support*/
|
||||
|
||||
this._slickHandler.subscribe(this.grid.onSort, function(e, args){
|
||||
var order = (args.sortAsc) ? 'asc':'desc';
|
||||
@ -3475,7 +3381,7 @@ my.SlickGrid = Backbone.View.extend({
|
||||
// that handle row Reoder.
|
||||
var cell =0
|
||||
if(self.state.get("gridOptions")
|
||||
&& self.state.get("gridOptions").enableReOrderRow != undefined
|
||||
&& self.state.get("gridOptions").enableReOrderRow != undefined
|
||||
&& self.state.get("gridOptions").enableReOrderRow == true ){
|
||||
cell =1
|
||||
}
|
||||
@ -3495,7 +3401,67 @@ my.SlickGrid = Backbone.View.extend({
|
||||
self.rendered = false;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// Row reordering support based on
|
||||
// https://github.com/mleibman/SlickGrid/blob/gh-pages/examples/example9-row-reordering.html
|
||||
_setupRowReordering: function() {
|
||||
var self = this;
|
||||
self.grid.setSelectionModel(new Slick.RowSelectionModel());
|
||||
|
||||
var moveRowsPlugin = new Slick.RowMoveManager({
|
||||
cancelEditOnDrag: true
|
||||
});
|
||||
|
||||
moveRowsPlugin.onBeforeMoveRows.subscribe(function (e, data) {
|
||||
for (var i = 0; i < data.rows.length; i++) {
|
||||
// no point in moving before or after itself
|
||||
if (data.rows[i] == data.insertBefore || data.rows[i] == data.insertBefore - 1) {
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
moveRowsPlugin.onMoveRows.subscribe(function (e, args) {
|
||||
var extractedRows = [], left, right;
|
||||
var rows = args.rows;
|
||||
var insertBefore = args.insertBefore;
|
||||
|
||||
var data = self.model.records.toJSON()
|
||||
left = data.slice(0, insertBefore);
|
||||
right= data.slice(insertBefore, data.length);
|
||||
|
||||
rows.sort(function(a,b) { return a-b; });
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
extractedRows.push(data[rows[i]]);
|
||||
}
|
||||
|
||||
rows.reverse();
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
if (row < insertBefore) {
|
||||
left.splice(row, 1);
|
||||
} else {
|
||||
right.splice(row - insertBefore, 1);
|
||||
}
|
||||
}
|
||||
|
||||
data = left.concat(extractedRows.concat(right));
|
||||
var selectedRows = [];
|
||||
for (var i = 0; i < rows.length; i++)
|
||||
selectedRows.push(left.length + i);
|
||||
|
||||
self.model.records.reset(data)
|
||||
|
||||
});
|
||||
//register The plugin to handle row Reorder
|
||||
if(this.state.get("gridOptions") && this.state.get("gridOptions").enableReOrderRow) {
|
||||
self.grid.registerPlugin(moveRowsPlugin);
|
||||
}
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
@ -3521,6 +3487,36 @@ my.SlickGrid = Backbone.View.extend({
|
||||
}
|
||||
});
|
||||
|
||||
// Add new grid Control to display a new row add menu bouton
|
||||
// It display a simple side-bar menu ,for user to add new
|
||||
// row to grid
|
||||
my.GridControl= Backbone.View.extend({
|
||||
className: "recline-row-add",
|
||||
// Template for row edit menu , change it if you don't love
|
||||
template: '<h1><a href="#" class="recline-row-add btn">Add row</a></h1>',
|
||||
|
||||
initialize: function(options){
|
||||
var self = this;
|
||||
_.bindAll(this, 'render');
|
||||
this.state = new recline.Model.ObjectState();
|
||||
this.render();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
this.$el.html(this.template)
|
||||
},
|
||||
|
||||
events : {
|
||||
"click .recline-row-add" : "addNewRow"
|
||||
},
|
||||
|
||||
addNewRow : function(e){
|
||||
e.preventDefault()
|
||||
this.state.trigger("change")
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery, recline.View);
|
||||
|
||||
/*
|
||||
@ -3639,7 +3635,14 @@ my.SlickGrid = Backbone.View.extend({
|
||||
}
|
||||
|
||||
// Slick.Controls.ColumnPicker
|
||||
$.extend(true, window, { Slick:{ Controls:{ ColumnPicker:SlickColumnPicker }}});
|
||||
$.extend(true, window, {
|
||||
Slick: {
|
||||
Controls: {
|
||||
ColumnPicker: SlickColumnPicker
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
|
||||
/*jshint multistr:true */
|
||||
|
||||
52
docs/tutorial-grids.markdown
Normal file
@ -0,0 +1,52 @@
|
||||
---
|
||||
layout: container
|
||||
title: Grids - Advanced use of grids in Recline - Tutorial
|
||||
recline-deps: true
|
||||
root: ../
|
||||
---
|
||||
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
Doing More with Grids
|
||||
<br />
|
||||
<small>This tutorial goes beyond the <a href="tutorial-views.html">basic
|
||||
views tutorial</a> and shows you how to do more with grids</small>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
### How much can I do with a simple grid view
|
||||
|
||||
### Benefits of SlickGrid
|
||||
What does Recline give you out of the box, what does SlickGrid have built in and how to use it (reference to stuff below).
|
||||
|
||||
### Preparing your page
|
||||
|
||||
See the instructions in the [basic views tutorial](tutorial-views.html).
|
||||
|
||||
### Creating a Dataset
|
||||
|
||||
Just like in the main tutorial, here's some example data We are going to work with:
|
||||
|
||||
{% highlight javascript %}
|
||||
{% include data.js %}
|
||||
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>
|
||||
|
||||
### Accessing SlickGrid features
|
||||
Show how we can customize SlickGrid grid "normally" - i.e. you can get access to underlying grid and tweak it as you want.
|
||||
|
||||
Suggest we demonstrate using this example: https://github.com/mleibman/SlickGrid/blob/gh-pages/examples/example-plugin-headermenu.html
|
||||
|
||||
Idea here is: we don't want to mimic all that slickgrid can do through recline interface - just let people do it directly themselves ...
|
||||
|
||||
|
||||
|
||||
50
docs/tutorial-timelines.markdown
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
layout: container
|
||||
title: Timelines - Advanced use of timelines in Recline - Tutorial
|
||||
recline-deps: true
|
||||
root: ../
|
||||
---
|
||||
|
||||
<div class="page-header">
|
||||
<h1>
|
||||
Doing More with Timelines
|
||||
<br />
|
||||
<small>This tutorial goes beyond the <a href="tutorial-views.html">basic
|
||||
views tutorial</a> and shows you how to do more with timelines</small>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
### Preparing your page
|
||||
|
||||
See the instructions in the [basic views tutorial](tutorial-views.html).
|
||||
|
||||
### Creating a Dataset
|
||||
|
||||
Just like in the main tutorial, here's some example data We are going to work with:
|
||||
|
||||
{% highlight javascript %}
|
||||
{% include data.js %}
|
||||
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>
|
||||
|
||||
### Underlying library and Recline extensions
|
||||
|
||||
|
||||
|
||||
### Handling dates
|
||||
|
||||
|
||||
|
||||
### Customizing the rendering
|
||||
|
||||
|
||||
|
||||
@ -9,10 +9,14 @@ root: ../
|
||||
<h1>
|
||||
Views Tutorial
|
||||
<br />
|
||||
<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>
|
||||
<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, map and timeline to display it.</small>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
### Views
|
||||
|
||||
Views display Recline datasets in different ways. This page covers the interesting built-in views. For a full list of views including extensions outside of the Recline.js core, see the [list of currently available views]({{page.root}}docs/views.html#dataset-views-currently-available).
|
||||
|
||||
### Preparing your page
|
||||
|
||||
Before writing any code with Recline, you need to do the following preparation steps on your page:
|
||||
@ -37,7 +41,7 @@ Before writing any code with Recline, you need to do the following preparation s
|
||||
<script type="text/javascript" src="vendor/slickgrid/2.0.1/slick.grid.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/memory.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 %}
|
||||
@ -62,11 +66,17 @@ We can now create a recline Dataset object (and memory backend) from this raw da
|
||||
var dataset = new recline.Model.Dataset({
|
||||
records: data
|
||||
});
|
||||
{% endhighlight %}
|
||||
|
||||
//Depending on the view, it may be important to set the date type
|
||||
dataset.fields.models[1].attributes.type = 'date';
|
||||
{% endhighlight %}
|
||||
|
||||
### Setting up the Grid
|
||||
|
||||
<div class="alert alert-info">
|
||||
The source code along with all dependencies for the grid part of the tutorial can be found at <a href="https://github.com/mattfullerton/recline-view-slickgrid-demo">this GitHub repository</a>. See it in action via <a href="http://mattfullerton.github.io/recline-view-slickgrid-demo/">GitHub Pages</a>.
|
||||
Although it's not demonstrated here, you can also use the simpler Grid view without SlickGrid. Source code along with all dependencies for that can be found at <a href="https://github.com/mattfullerton/recline-view-grid-demo">this GitHub repository</a>. Demo on <a href="http://mattfullerton.github.io/recline-view-grid-demo/">GitHub Pages</a>.
|
||||
</div>
|
||||
|
||||
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 CSS and JS dependencies in addition to those above:
|
||||
|
||||
@ -81,7 +91,7 @@ Let's create a data grid view to display the dataset we have just created. We'r
|
||||
<script type="text/javascript" src="vendor/slickgrid/2.0.1/plugins/slick.rowselectionmodel.js"></script>
|
||||
<script type="text/javascript" src="vendor/slickgrid/2.0.1/plugins/slick.rowmovemanager.js"></script>
|
||||
|
||||
<!-- Recline -->
|
||||
<!-- Recline (only needed when NOT including the combined JS file as shown above) -->
|
||||
<script type="text/javascript" src="src/view.slickgrid.js"></script>
|
||||
{% endhighlight %}
|
||||
|
||||
@ -123,6 +133,10 @@ grid.render();
|
||||
|
||||
### Creating a Graph
|
||||
|
||||
<div class="alert alert-info">
|
||||
The source code along with all dependencies for the graph part of the tutorial can be found at <a href="https://github.com/mattfullerton/recline-view-graph-demo">this GitHub repository</a>. See it in action via <a href="http://mattfullerton.github.io/recline-view-graph-demo/">GitHub Pages</a>.
|
||||
</div>
|
||||
|
||||
Let's create a graph view to display a line graph for this dataset.
|
||||
|
||||
First, add the additional dependencies for this view. These are the Flot
|
||||
@ -140,6 +154,8 @@ library and the Recline Flot Graph view:
|
||||
|
||||
<script type="text/javascript" src="vendor/flot/jquery.flot.js"></script>
|
||||
<script type="text/javascript" src="vendor/flot/jquery.flot.time.js"></script>
|
||||
|
||||
<!-- Recline (only needed when NOT including the combined JS file as shown above) -->
|
||||
<script type="text/javascript" src="src/view.graph.js"></script>
|
||||
{% endhighlight %}
|
||||
|
||||
@ -164,8 +180,9 @@ var $el = $('#mygraph');
|
||||
var graph = new recline.View.Graph({
|
||||
model: dataset,
|
||||
state: {
|
||||
graphType: "lines-and-points",
|
||||
group: "date",
|
||||
series: ["x", "z"]
|
||||
series: ["y", "z"]
|
||||
}
|
||||
});
|
||||
$el.append(graph.el);
|
||||
@ -173,17 +190,18 @@ graph.render();
|
||||
graph.redraw();
|
||||
{% endhighlight %}
|
||||
|
||||
The result is the following graph:
|
||||
For the axis date formatting to work, it is crucial that the date type is set for that field as shown in the code concerning the dataset above. The result is the following graph:
|
||||
|
||||
<div id="mygraph" style="margin-bottom: 30px;"> </div>
|
||||
|
||||
<script type="text/javascript">
|
||||
dataset.fields.models[1].attributes.type = 'date';
|
||||
var $el = $('#mygraph');
|
||||
var graph = new recline.View.Graph({
|
||||
model: dataset,
|
||||
state: {
|
||||
graphType: "lines-and-points",
|
||||
group: "x",
|
||||
group: "date",
|
||||
series: ["y", "z"]
|
||||
}
|
||||
});
|
||||
@ -194,6 +212,10 @@ graph.redraw();
|
||||
|
||||
### Creating a Map
|
||||
|
||||
<div class="alert alert-info">
|
||||
The source code along with all dependencies for the map part of the tutorial can be found at <a href="https://github.com/mattfullerton/recline-view-map-demo">this GitHub repository</a>. See it in action via <a href="http://mattfullerton.github.io/recline-view-map-demo/">GitHub Pages</a>.
|
||||
</div>
|
||||
|
||||
Now, let's create a map of this dataset using the lon/lat information which is
|
||||
present on these data points.
|
||||
|
||||
@ -202,9 +224,9 @@ library and the Recline Map view:
|
||||
|
||||
{% highlight html %}
|
||||
<!-- css -->
|
||||
<link rel="stylesheet" href="vendor/leaflet/0.4.4/leaflet.css">
|
||||
<link rel="stylesheet" href="vendor/leaflet/0.7.3/leaflet.css">
|
||||
<!--[if lte IE 8]>
|
||||
<link rel="stylesheet" href="vendor/leaflet/0.4.4/leaflet.ie.css" />
|
||||
<link rel="stylesheet" href="vendor/leaflet/0.7.3/leaflet.ie.css" />
|
||||
<![endif]-->
|
||||
<link rel="stylesheet" href="vendor/leaflet.markercluster/MarkerCluster.css">
|
||||
<link rel="stylesheet" href="vendor/leaflet.markercluster/MarkerCluster.Default.css">
|
||||
@ -214,8 +236,10 @@ library and the Recline Map view:
|
||||
<link rel="stylesheet" href="css/map.css">
|
||||
|
||||
<!-- javascript -->
|
||||
<script type="text/javascript" src="vendor/leaflet/0.4.4/leaflet.js"></script>
|
||||
<script type="text/javascript" src="vendor/leaflet/0.7.3/leaflet.js"></script>
|
||||
<script type="text/javascript" src="vendor/leaflet.markercluster/leaflet.markercluster.js"></script>
|
||||
|
||||
<!-- Recline (only needed when NOT including the combined JS file as shown above) -->
|
||||
<script type="text/javascript" src="src/view-map.js"></script>
|
||||
{% endhighlight %}
|
||||
|
||||
@ -250,6 +274,10 @@ map.render();
|
||||
|
||||
### Creating a Timeline
|
||||
|
||||
<div class="alert alert-info">
|
||||
The source code along with all dependencies for the map part of the tutorial can be found at <a href="https://github.com/mattfullerton/recline-view-timeline-demo">this GitHub repository</a>. See it in action via <a href="http://mattfullerton.github.io/recline-view-timeline-demo/">GitHub Pages</a>.
|
||||
</div>
|
||||
|
||||
Now, let's create a timeline for this dataset using the date information which is
|
||||
present on these data points.
|
||||
|
||||
@ -258,6 +286,7 @@ First, add the additional dependencies for the timeline view. The timeline is bu
|
||||
{% highlight html %}
|
||||
<!-- css -->
|
||||
<link rel="stylesheet" href="vendor/timeline/css/timeline.css">
|
||||
<link rel="stylesheet" href="css/map.css">
|
||||
|
||||
<!-- javascript -->
|
||||
<script type="text/javascript" src="vendor/moment/2.0.0/moment.js"></script>
|
||||
|
||||
@ -44,14 +44,13 @@ root: ../
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3>Views – Grids, Maps, Graphs and More!</h3>
|
||||
<h3>Views – visualize data</h3>
|
||||
<hr />
|
||||
|
||||
<div class="tutorials">
|
||||
<div class="row">
|
||||
<div class="span4">
|
||||
<div class="well">
|
||||
<h4><a href="tutorial-views.html">Views Quickstart - Grids, Graphs and Maps</a></h4>
|
||||
<h4><a href="tutorial-views.html">Views Quickstart - Grids, Graphs, Maps & Timelines</a></h4>
|
||||
</div>
|
||||
</div>
|
||||
<div class="span4">
|
||||
|
||||
@ -16,6 +16,9 @@ views they have a pointer to a model (or a collection) and have an associated
|
||||
DOM-style element (usually this element will be bound into the page at some
|
||||
point).
|
||||
|
||||
<div class="alert alert-info">Looking for quickstart tutorial rather than reference documentation? See the <a href="tutorial-views.html">Views Tutorial</a>.</div>
|
||||
|
||||
|
||||
Views provided by core Recline are crudely divided into two types:
|
||||
|
||||
* Dataset Views: a View intended for displaying a recline.Model.Dataset in some
|
||||
@ -25,6 +28,9 @@ Views provided by core Recline are crudely divided into two types:
|
||||
which both provide a way for editing (a part of) a `recline.Model.Query`
|
||||
associated to a Dataset.
|
||||
|
||||
## Dataset Views currently available
|
||||
{% include views-list.html %}
|
||||
|
||||
## Dataset View
|
||||
|
||||
These views are just Backbone views with a few additional conventions:
|
||||
|
||||
@ -19,9 +19,9 @@ title: Home
|
||||
and allows you to connect them with your data in seconds.
|
||||
</p>
|
||||
<p class="links">
|
||||
<a href="docs/" class="btn btn-large">Documentation »</a>
|
||||
<a href="docs/tutorials.html" class="btn btn-large">Tutorials »</a>
|
||||
<a href="demos/" class="btn btn-large">Demos »</a>
|
||||
<a href="docs/" class="btn">Documentation »</a>
|
||||
<a href="docs/tutorials.html" class="btn">Tutorials »</a>
|
||||
<a href="demos/" class="btn">Demos »</a>
|
||||
</p>
|
||||
|
||||
<h3 style="color: white; margin-top: 40px;">Get started fast</h3>
|
||||
|
||||
12
package.json
@ -26,11 +26,9 @@
|
||||
},
|
||||
"lib" : "src",
|
||||
"main" : "dist/recline.js",
|
||||
"repositories": [
|
||||
{
|
||||
"type": "git",
|
||||
"url": "http://github.com/okfn/recline.git",
|
||||
"path": "src"
|
||||
}
|
||||
]
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/okfn/recline.git",
|
||||
"path": "src"
|
||||
}
|
||||
}
|
||||
|
||||
@ -318,7 +318,7 @@ my.Map = Backbone.View.extend({
|
||||
|
||||
_.each(docs,function(doc){
|
||||
for (var key in self.features._layers){
|
||||
if (self.features._layers[key].feature.properties.cid == doc.cid){
|
||||
if (self.features._layers[key].feature.geometry.properties.cid == doc.cid){
|
||||
self.features.removeLayer(self.features._layers[key]);
|
||||
}
|
||||
}
|
||||
@ -337,7 +337,7 @@ my.Map = Backbone.View.extend({
|
||||
var dms = coord.split(/[^-?\.\d\w]+/);
|
||||
var deg = 0; var m = 0;
|
||||
var toDeg = [1, 60, 3600]; // conversion factors for Deg, min, sec
|
||||
var i;
|
||||
var i;
|
||||
for (i = 0; i < dms.length; ++i) {
|
||||
if (isNaN(parseFloat(dms[i]))) {
|
||||
continue;
|
||||
@ -461,8 +461,8 @@ my.Map = Backbone.View.extend({
|
||||
var self = this;
|
||||
this.map = new L.Map(this.$map.get(0));
|
||||
|
||||
var mapUrl = "//otile{s}-s.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png";
|
||||
var osmAttribution = 'Map data © 2011 OpenStreetMap contributors, Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="//developer.mapquest.com/content/osm/mq_logo.png">';
|
||||
var mapUrl = "http://otile{s}-s.mqcdn.com/tiles/1.0.0/osm/{z}/{x}/{y}.png";
|
||||
var osmAttribution = 'Map data © 2011 OpenStreetMap contributors, Tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a> <img src="http://developer.mapquest.com/content/osm/mq_logo.png">';
|
||||
var bg = new L.TileLayer(mapUrl, {maxZoom: 18, attribution: osmAttribution ,subdomains: '1234'});
|
||||
this.map.addLayer(bg);
|
||||
|
||||
@ -670,4 +670,3 @@ my.MapMenu = Backbone.View.extend({
|
||||
});
|
||||
|
||||
})(jQuery, recline.View);
|
||||
|
||||
|
||||
@ -5,37 +5,7 @@ this.recline.View = this.recline.View || {};
|
||||
|
||||
(function($, my) {
|
||||
"use strict";
|
||||
// Add new grid Control to display a new row add menu bouton
|
||||
// It display a simple side-bar menu ,for user to add new
|
||||
// row to grid
|
||||
|
||||
my.GridControl= Backbone.View.extend({
|
||||
className: "recline-row-add",
|
||||
// Template for row edit menu , change it if you don't love
|
||||
template: '<h1><a href="#" class="recline-row-add btn">Add row</a></h1>',
|
||||
|
||||
initialize: function(options){
|
||||
var self = this;
|
||||
_.bindAll(this, 'render');
|
||||
this.state = new recline.Model.ObjectState();
|
||||
this.render();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
this.$el.html(this.template)
|
||||
},
|
||||
|
||||
events : {
|
||||
"click .recline-row-add" : "addNewRow"
|
||||
},
|
||||
|
||||
addNewRow : function(e){
|
||||
e.preventDefault()
|
||||
this.state.trigger("change")
|
||||
}
|
||||
}
|
||||
);
|
||||
// ## SlickGrid Dataset View
|
||||
//
|
||||
// Provides a tabular view on a Dataset, based on SlickGrid.
|
||||
@ -56,7 +26,11 @@ this.recline.View = this.recline.View || {};
|
||||
// state: {
|
||||
// gridOptions: {
|
||||
// editable: true,
|
||||
// enableAddRows: true
|
||||
// enableAddRow: true
|
||||
// // Enable support for row delete
|
||||
// enabledDelRow: true,
|
||||
// // Enable support for row Reorder
|
||||
// enableReOrderRow:true,
|
||||
// ...
|
||||
// },
|
||||
// columnsEditor: [
|
||||
@ -70,10 +44,10 @@ my.SlickGrid = Backbone.View.extend({
|
||||
initialize: function(modelEtc) {
|
||||
var self = this;
|
||||
this.$el.addClass('recline-slickgrid');
|
||||
|
||||
|
||||
// Template for row delete menu , change it if you don't love
|
||||
this.templates = {
|
||||
"deleterow" : '<a href="#" class="recline-row-delete btn" title="Delete row">X</a>'
|
||||
"deleterow" : '<a href="#" class="recline-row-delete btn" title="Delete row">X</a>'
|
||||
};
|
||||
|
||||
_.bindAll(this, 'render', 'onRecordChanged');
|
||||
@ -95,15 +69,16 @@ my.SlickGrid = Backbone.View.extend({
|
||||
|
||||
//add menu for new row , check if enableAddRow is set to true or not set
|
||||
if(this.state.get("gridOptions")
|
||||
&& this.state.get("gridOptions").enabledAddRow != undefined
|
||||
&& this.state.get("gridOptions").enabledAddRow != undefined
|
||||
&& this.state.get("gridOptions").enabledAddRow == true ){
|
||||
this.editor = new my.GridControl()
|
||||
this.elSidebar = this.editor.$el
|
||||
this.listenTo(this.editor.state, 'change', function(){
|
||||
this.model.records.add(new recline.Model.Record())
|
||||
this.listenTo(this.editor.state, 'change', function(){
|
||||
this.model.records.add(new recline.Model.Record())
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onRecordChanged: function(record) {
|
||||
// Ignore if the grid is not yet drawn
|
||||
if (!this.grid) {
|
||||
@ -115,7 +90,8 @@ my.SlickGrid = Backbone.View.extend({
|
||||
this.grid.getData().updateItem(record, row_index);
|
||||
this.grid.render();
|
||||
},
|
||||
render: function() {
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
var options = _.extend({
|
||||
enableCellNavigation: true,
|
||||
@ -127,43 +103,40 @@ my.SlickGrid = Backbone.View.extend({
|
||||
|
||||
// We need all columns, even the hidden ones, to show on the column picker
|
||||
var columns = [];
|
||||
|
||||
// custom formatter as default one escapes html
|
||||
// plus this way we distinguish between rendering/formatting and computed value (so e.g. sort still works ...)
|
||||
// row = row index, cell = cell index, value = value, columnDef = column definition, dataContext = full row values
|
||||
var formatter = function(row, cell, value, columnDef, dataContext) {
|
||||
if(columnDef.id == "del"){
|
||||
return self.templates.deleterow
|
||||
}
|
||||
var field = self.model.fields.get(columnDef.id);
|
||||
}
|
||||
var field = self.model.fields.get(columnDef.id);
|
||||
if (field.renderer) {
|
||||
return field.renderer(value, field, dataContext);
|
||||
}else {
|
||||
} else {
|
||||
return value
|
||||
}
|
||||
};
|
||||
|
||||
// we need to be sure that user is entering a valid input , for exemple if
|
||||
// field is date type and field.format ='YY-MM-DD', we should be sure that
|
||||
// user enter a correct value
|
||||
var validator = function(field){
|
||||
return function(value){
|
||||
if(field.type == "date" && isNaN(Date.parse(value))){
|
||||
return {
|
||||
valid: false,
|
||||
msg: "A date is required, check field field-date-format"};
|
||||
}else {
|
||||
return {valid: true, msg :null }
|
||||
}
|
||||
}
|
||||
var validator = function(field) {
|
||||
return function(value){
|
||||
if (field.type == "date" && isNaN(Date.parse(value))){
|
||||
return {
|
||||
valid: false,
|
||||
msg: "A date is required, check field field-date-format"
|
||||
};
|
||||
} else {
|
||||
return {valid: true, msg :null }
|
||||
}
|
||||
}
|
||||
};
|
||||
//Add row delete support, check if enableReOrderRow is set to true , by
|
||||
//default it is set to false
|
||||
// state: {
|
||||
// gridOptions: {
|
||||
// enableReOrderRow: true,
|
||||
// },
|
||||
if(this.state.get("gridOptions")
|
||||
&& this.state.get("gridOptions").enableReOrderRow != undefined
|
||||
&& this.state.get("gridOptions").enableReOrderRow == true ){
|
||||
|
||||
// Add column for row reorder support
|
||||
if (this.state.get("gridOptions") && this.state.get("gridOptions").enableReOrderRow == true) {
|
||||
columns.push({
|
||||
id: "#",
|
||||
name: "",
|
||||
@ -174,15 +147,8 @@ my.SlickGrid = Backbone.View.extend({
|
||||
cssClass: "recline-cell-reorder"
|
||||
})
|
||||
}
|
||||
//Add row delete support, check if enabledDelRow is set to true , by
|
||||
//default it is set to false
|
||||
// state: {
|
||||
// gridOptions: {
|
||||
// enabledDelRow: true,
|
||||
// },
|
||||
if(this.state.get("gridOptions")
|
||||
&& this.state.get("gridOptions").enabledDelRow != undefined
|
||||
&& this.state.get("gridOptions").enabledDelRow == true ){
|
||||
// Add column for row delete support
|
||||
if (this.state.get("gridOptions") && this.state.get("gridOptions").enabledDelRow == true) {
|
||||
columns.push({
|
||||
id: 'del',
|
||||
name: '',
|
||||
@ -193,6 +159,7 @@ my.SlickGrid = Backbone.View.extend({
|
||||
validator:validator
|
||||
})
|
||||
}
|
||||
|
||||
_.each(this.model.fields.toJSON(),function(field){
|
||||
var column = {
|
||||
id: field.id,
|
||||
@ -254,16 +221,17 @@ my.SlickGrid = Backbone.View.extend({
|
||||
}
|
||||
}
|
||||
columns = columns.concat(tempHiddenColumns);
|
||||
|
||||
// Transform a model object into a row
|
||||
function toRow(m) {
|
||||
var row = {};
|
||||
self.model.fields.each(function(field){
|
||||
var render = "";
|
||||
self.model.fields.each(function(field) {
|
||||
var render = "";
|
||||
//when adding row from slickgrid the field value is undefined
|
||||
if(!_.isUndefined(m.getFieldValueUnrendered(field))){
|
||||
render =m.getFieldValueUnrendered(field)
|
||||
}
|
||||
row[field.id] = render
|
||||
if(!_.isUndefined(m.getFieldValueUnrendered(field))){
|
||||
render =m.getFieldValueUnrendered(field)
|
||||
}
|
||||
row[field.id] = render
|
||||
});
|
||||
return row;
|
||||
}
|
||||
@ -286,7 +254,6 @@ my.SlickGrid = Backbone.View.extend({
|
||||
rows[i] = toRow(m);
|
||||
models[i] = m;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
var data = new RowSet();
|
||||
@ -304,70 +271,9 @@ my.SlickGrid = Backbone.View.extend({
|
||||
this.grid.setSortColumn(column, sortAsc);
|
||||
}
|
||||
|
||||
|
||||
/* Row reordering support based on
|
||||
https://github.com/mleibman/SlickGrid/blob/gh-pages/examples/example9-row-reordering.html
|
||||
|
||||
*/
|
||||
self.grid.setSelectionModel(new Slick.RowSelectionModel());
|
||||
|
||||
var moveRowsPlugin = new Slick.RowMoveManager({
|
||||
cancelEditOnDrag: true
|
||||
});
|
||||
|
||||
moveRowsPlugin.onBeforeMoveRows.subscribe(function (e, data) {
|
||||
for (var i = 0; i < data.rows.length; i++) {
|
||||
// no point in moving before or after itself
|
||||
if (data.rows[i] == data.insertBefore || data.rows[i] == data.insertBefore - 1) {
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
moveRowsPlugin.onMoveRows.subscribe(function (e, args) {
|
||||
|
||||
var extractedRows = [], left, right;
|
||||
var rows = args.rows;
|
||||
var insertBefore = args.insertBefore;
|
||||
|
||||
var data = self.model.records.toJSON()
|
||||
left = data.slice(0, insertBefore);
|
||||
right= data.slice(insertBefore, data.length);
|
||||
|
||||
rows.sort(function(a,b) { return a-b; });
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
extractedRows.push(data[rows[i]]);
|
||||
}
|
||||
|
||||
rows.reverse();
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
if (row < insertBefore) {
|
||||
left.splice(row, 1);
|
||||
} else {
|
||||
right.splice(row - insertBefore, 1);
|
||||
}
|
||||
}
|
||||
|
||||
data = left.concat(extractedRows.concat(right));
|
||||
var selectedRows = [];
|
||||
for (var i = 0; i < rows.length; i++)
|
||||
selectedRows.push(left.length + i);
|
||||
|
||||
self.model.records.reset(data)
|
||||
|
||||
});
|
||||
//register The plugin to handle row Reorder
|
||||
if(this.state.get("gridOptions")
|
||||
&& this.state.get("gridOptions").enableReOrderRow != undefined
|
||||
&& this.state.get("gridOptions").enableReOrderRow == true ){
|
||||
self.grid.registerPlugin(moveRowsPlugin);
|
||||
if (this.state.get("gridOptions") && this.state.get("gridOptions").enableReOrderRow) {
|
||||
this._setupRowReordering();
|
||||
}
|
||||
/* end row reordering support*/
|
||||
|
||||
this._slickHandler.subscribe(this.grid.onSort, function(e, args){
|
||||
var order = (args.sortAsc) ? 'asc':'desc';
|
||||
@ -414,7 +320,7 @@ my.SlickGrid = Backbone.View.extend({
|
||||
// that handle row Reoder.
|
||||
var cell =0
|
||||
if(self.state.get("gridOptions")
|
||||
&& self.state.get("gridOptions").enableReOrderRow != undefined
|
||||
&& self.state.get("gridOptions").enableReOrderRow != undefined
|
||||
&& self.state.get("gridOptions").enableReOrderRow == true ){
|
||||
cell =1
|
||||
}
|
||||
@ -434,7 +340,67 @@ my.SlickGrid = Backbone.View.extend({
|
||||
self.rendered = false;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
// Row reordering support based on
|
||||
// https://github.com/mleibman/SlickGrid/blob/gh-pages/examples/example9-row-reordering.html
|
||||
_setupRowReordering: function() {
|
||||
var self = this;
|
||||
self.grid.setSelectionModel(new Slick.RowSelectionModel());
|
||||
|
||||
var moveRowsPlugin = new Slick.RowMoveManager({
|
||||
cancelEditOnDrag: true
|
||||
});
|
||||
|
||||
moveRowsPlugin.onBeforeMoveRows.subscribe(function (e, data) {
|
||||
for (var i = 0; i < data.rows.length; i++) {
|
||||
// no point in moving before or after itself
|
||||
if (data.rows[i] == data.insertBefore || data.rows[i] == data.insertBefore - 1) {
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
moveRowsPlugin.onMoveRows.subscribe(function (e, args) {
|
||||
var extractedRows = [], left, right;
|
||||
var rows = args.rows;
|
||||
var insertBefore = args.insertBefore;
|
||||
|
||||
var data = self.model.records.toJSON()
|
||||
left = data.slice(0, insertBefore);
|
||||
right= data.slice(insertBefore, data.length);
|
||||
|
||||
rows.sort(function(a,b) { return a-b; });
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
extractedRows.push(data[rows[i]]);
|
||||
}
|
||||
|
||||
rows.reverse();
|
||||
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
if (row < insertBefore) {
|
||||
left.splice(row, 1);
|
||||
} else {
|
||||
right.splice(row - insertBefore, 1);
|
||||
}
|
||||
}
|
||||
|
||||
data = left.concat(extractedRows.concat(right));
|
||||
var selectedRows = [];
|
||||
for (var i = 0; i < rows.length; i++)
|
||||
selectedRows.push(left.length + i);
|
||||
|
||||
self.model.records.reset(data)
|
||||
|
||||
});
|
||||
//register The plugin to handle row Reorder
|
||||
if(this.state.get("gridOptions") && this.state.get("gridOptions").enableReOrderRow) {
|
||||
self.grid.registerPlugin(moveRowsPlugin);
|
||||
}
|
||||
},
|
||||
|
||||
remove: function () {
|
||||
@ -460,6 +426,36 @@ my.SlickGrid = Backbone.View.extend({
|
||||
}
|
||||
});
|
||||
|
||||
// Add new grid Control to display a new row add menu bouton
|
||||
// It display a simple side-bar menu ,for user to add new
|
||||
// row to grid
|
||||
my.GridControl= Backbone.View.extend({
|
||||
className: "recline-row-add",
|
||||
// Template for row edit menu , change it if you don't love
|
||||
template: '<h1><a href="#" class="recline-row-add btn">Add row</a></h1>',
|
||||
|
||||
initialize: function(options){
|
||||
var self = this;
|
||||
_.bindAll(this, 'render');
|
||||
this.state = new recline.Model.ObjectState();
|
||||
this.render();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
this.$el.html(this.template)
|
||||
},
|
||||
|
||||
events : {
|
||||
"click .recline-row-add" : "addNewRow"
|
||||
},
|
||||
|
||||
addNewRow : function(e){
|
||||
e.preventDefault()
|
||||
this.state.trigger("change")
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery, recline.View);
|
||||
|
||||
/*
|
||||
@ -578,6 +574,13 @@ my.SlickGrid = Backbone.View.extend({
|
||||
}
|
||||
|
||||
// Slick.Controls.ColumnPicker
|
||||
$.extend(true, window, { Slick:{ Controls:{ ColumnPicker:SlickColumnPicker }}});
|
||||
$.extend(true, window, {
|
||||
Slick: {
|
||||
Controls: {
|
||||
ColumnPicker: SlickColumnPicker
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
|
||||
|
||||
@ -99,7 +99,8 @@ my.Timeline = Backbone.View.extend({
|
||||
"startDate": start,
|
||||
"endDate": end,
|
||||
"headline": String(record.get('title') || ''),
|
||||
"text": record.get('description') || record.summary()
|
||||
"text": record.get('description') || record.summary(),
|
||||
"tag": record.get('tags')
|
||||
};
|
||||
return tlEntry;
|
||||
} else {
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
<link rel="stylesheet" href="../css/timeline.css" type="text/css" media="screen" />
|
||||
<style type="text/css">.recline-timeline { height: 400px; }</style>
|
||||
<link rel="stylesheet" href="../css/flot.css">
|
||||
<link rel="stylesheet" href="../vendor/leaflet/0.4.4/leaflet.css">
|
||||
<link rel="stylesheet" href="../vendor/leaflet/0.7.3/leaflet.css">
|
||||
<link rel="stylesheet" href="../vendor/leaflet.markercluster/MarkerCluster.css">
|
||||
<link rel="stylesheet" href="../vendor/leaflet.markercluster/MarkerCluster.Default.css">
|
||||
<link rel="stylesheet" href="../css/map.css">
|
||||
@ -21,7 +21,7 @@
|
||||
<script type="text/javascript" src="../vendor/bootstrap/2.3.2/bootstrap.js"></script>
|
||||
<script type="text/javascript" src="../vendor/flot/jquery.flot.js"></script>
|
||||
<script type="text/javascript" src="../vendor/flot/jquery.flot.time.js"></script>
|
||||
<script type="text/javascript" src="../vendor/leaflet/0.4.4/leaflet-src.js"></script>
|
||||
<script type="text/javascript" src="../vendor/leaflet/0.7.3/leaflet-src.js"></script>
|
||||
<script type="text/javascript" src="../vendor/leaflet.markercluster/leaflet.markercluster.js"></script>
|
||||
<script type="text/javascript" src="../vendor/slickgrid/2.0.1/jquery-ui-1.8.16.custom.min.js"></script>
|
||||
<script type="text/javascript" src="../vendor/slickgrid/2.0.1/jquery.event.drag-2.0.min.js"></script>
|
||||
@ -52,12 +52,11 @@
|
||||
<script type="text/javascript" src="../src/model.js"></script>
|
||||
<script type="text/javascript" src="../src/backend.memory.js"></script>
|
||||
<script type="text/javascript" src="../src/backend.dataproxy.js"></script>
|
||||
<script type="text/javascript" src="../src/backend.csv.js"></script>
|
||||
<script type="text/javascript" src="http://okfnlabs.org/csv.js/csv.js"></script>
|
||||
|
||||
<script type="text/javascript" src="model.test.js"></script>
|
||||
<script type="text/javascript" src="backend.memory.test.js"></script>
|
||||
<script type="text/javascript" src="backend.dataproxy.test.js"></script>
|
||||
<script type="text/javascript" src="backend.csv.test.js"></script>
|
||||
|
||||
<!-- views and view tests -->
|
||||
<script type="text/javascript" src="../src/view.grid.js"></script>
|
||||
|
||||
@ -202,6 +202,8 @@ test('query with plain object', function () {
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: this has a dependency on the external csv backend
|
||||
// May want to refactor or remove (?)
|
||||
test('fetch without and with explicit fields', function () {
|
||||
var dataset = new recline.Model.Dataset({
|
||||
backend: 'csv',
|
||||
|
||||
@ -20,6 +20,7 @@ test('extract dates and timelineJSON', function () {
|
||||
'date': [
|
||||
{
|
||||
'startDate': '2012,03,20',
|
||||
'tag': undefined,
|
||||
'endDate': null,
|
||||
'headline': '1',
|
||||
'text': '<div class="recline-record-summary"><div class="Date"><strong>Date</strong>: 2012-03-20</div><div class="title"><strong>title</strong>: 1</div></div>'
|
||||
@ -28,6 +29,7 @@ test('extract dates and timelineJSON', function () {
|
||||
'startDate': '2012,03,25',
|
||||
'endDate': null,
|
||||
'headline': '2',
|
||||
'tag': undefined,
|
||||
'text': '<div class="recline-record-summary"><div class="Date"><strong>Date</strong>: 2012-03-25</div><div class="title"><strong>title</strong>: 2</div></div>'
|
||||
}
|
||||
]
|
||||
|
||||
BIN
vendor/leaflet/0.4.4/images/layers.png
vendored
|
Before Width: | Height: | Size: 3.9 KiB |
BIN
vendor/leaflet/0.4.4/images/marker-icon.png
vendored
|
Before Width: | Height: | Size: 2.5 KiB |
BIN
vendor/leaflet/0.4.4/images/marker-shadow.png
vendored
|
Before Width: | Height: | Size: 1.6 KiB |
BIN
vendor/leaflet/0.4.4/images/zoom-in.png
vendored
|
Before Width: | Height: | Size: 963 B |
BIN
vendor/leaflet/0.4.4/images/zoom-out.png
vendored
|
Before Width: | Height: | Size: 959 B |
7638
vendor/leaflet/0.4.4/leaflet-src.js
vendored
379
vendor/leaflet/0.4.4/leaflet.css
vendored
@ -1,379 +0,0 @@
|
||||
/* required styles */
|
||||
|
||||
.leaflet-map-pane,
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow,
|
||||
.leaflet-tile-pane,
|
||||
.leaflet-overlay-pane,
|
||||
.leaflet-shadow-pane,
|
||||
.leaflet-marker-pane,
|
||||
.leaflet-popup-pane,
|
||||
.leaflet-overlay-pane svg,
|
||||
.leaflet-zoom-box,
|
||||
.leaflet-image-layer,
|
||||
.leaflet-layer { /* TODO optimize classes */
|
||||
position: absolute;
|
||||
}
|
||||
.leaflet-container {
|
||||
overflow: hidden;
|
||||
outline: 0;
|
||||
}
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
display: block;
|
||||
}
|
||||
.leaflet-clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
.leaflet-dragging, .leaflet-dragging .leaflet-clickable {
|
||||
cursor: move;
|
||||
}
|
||||
.leaflet-container img {
|
||||
/* map is broken in FF if you have max-width: 100% on tiles */
|
||||
max-width: none !important;
|
||||
}
|
||||
.leaflet-container img.leaflet-image-layer {
|
||||
/* stupid Android 2 doesn't understand "max-width: none" properly */
|
||||
max-width: 15000px !important;
|
||||
}
|
||||
|
||||
.leaflet-tile-pane { z-index: 2; }
|
||||
.leaflet-objects-pane { z-index: 3; }
|
||||
.leaflet-overlay-pane { z-index: 4; }
|
||||
.leaflet-shadow-pane { z-index: 5; }
|
||||
.leaflet-marker-pane { z-index: 6; }
|
||||
.leaflet-popup-pane { z-index: 7; }
|
||||
|
||||
.leaflet-tile {
|
||||
filter: inherit;
|
||||
visibility: hidden;
|
||||
}
|
||||
.leaflet-tile-loaded {
|
||||
visibility: inherit;
|
||||
}
|
||||
|
||||
.leaflet-zoom-box {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* Leaflet controls */
|
||||
|
||||
.leaflet-control {
|
||||
position: relative;
|
||||
z-index: 7;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.leaflet-top,
|
||||
.leaflet-bottom {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
}
|
||||
.leaflet-top {
|
||||
top: 0;
|
||||
}
|
||||
.leaflet-right {
|
||||
right: 0;
|
||||
}
|
||||
.leaflet-bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
.leaflet-left {
|
||||
left: 0;
|
||||
}
|
||||
.leaflet-control {
|
||||
float: left;
|
||||
clear: both;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
float: right;
|
||||
}
|
||||
.leaflet-top .leaflet-control {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.leaflet-left .leaflet-control {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.leaflet-control-zoom {
|
||||
-moz-border-radius: 7px;
|
||||
-webkit-border-radius: 7px;
|
||||
border-radius: 7px;
|
||||
}
|
||||
.leaflet-control-zoom {
|
||||
padding: 5px;
|
||||
background: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.leaflet-control-zoom a {
|
||||
background-color: rgba(255, 255, 255, 0.75);
|
||||
}
|
||||
.leaflet-control-zoom a, .leaflet-control-layers a {
|
||||
background-position: 50% 50%;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
}
|
||||
.leaflet-control-zoom a {
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
}
|
||||
.leaflet-control-zoom a:hover {
|
||||
background-color: #fff;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-zoom a {
|
||||
width: 27px;
|
||||
height: 27px;
|
||||
}
|
||||
.leaflet-control-zoom-in {
|
||||
background-image: url(images/zoom-in.png);
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.leaflet-control-zoom-out {
|
||||
background-image: url(images/zoom-out.png);
|
||||
}
|
||||
|
||||
.leaflet-control-layers {
|
||||
box-shadow: 0 1px 7px #999;
|
||||
background: #f8f8f9;
|
||||
-moz-border-radius: 8px;
|
||||
-webkit-border-radius: 8px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.leaflet-control-layers a {
|
||||
background-image: url(images/layers.png);
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers a {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
.leaflet-control-layers .leaflet-control-layers-list,
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
|
||||
display: none;
|
||||
}
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-list {
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
.leaflet-control-layers-expanded {
|
||||
padding: 6px 10px 6px 6px;
|
||||
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
color: #333;
|
||||
background: #fff;
|
||||
}
|
||||
.leaflet-control-layers input {
|
||||
margin-top: 2px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
.leaflet-control-layers label {
|
||||
display: block;
|
||||
}
|
||||
.leaflet-control-layers-separator {
|
||||
height: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
margin: 5px -10px 5px -6px;
|
||||
}
|
||||
|
||||
.leaflet-container .leaflet-control-attribution {
|
||||
background-color: rgba(255, 255, 255, 0.7);
|
||||
box-shadow: 0 0 5px #bbb;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.leaflet-control-attribution,
|
||||
.leaflet-control-scale-line {
|
||||
padding: 0 5px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.leaflet-container .leaflet-control-attribution,
|
||||
.leaflet-container .leaflet-control-scale {
|
||||
font: 11px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.leaflet-left .leaflet-control-scale {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control-scale {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.leaflet-control-scale-line {
|
||||
border: 2px solid #777;
|
||||
border-top: none;
|
||||
color: black;
|
||||
line-height: 1;
|
||||
font-size: 10px;
|
||||
padding-bottom: 2px;
|
||||
text-shadow: 1px 1px 1px #fff;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child) {
|
||||
border-top: 2px solid #777;
|
||||
padding-top: 1px;
|
||||
border-bottom: none;
|
||||
margin-top: -2px;
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
|
||||
border-bottom: 2px solid #777;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-attribution, .leaflet-touch .leaflet-control-layers {
|
||||
box-shadow: none;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers {
|
||||
border: 5px solid #bbb;
|
||||
}
|
||||
|
||||
|
||||
/* Zoom and fade animations */
|
||||
|
||||
.leaflet-fade-anim .leaflet-tile, .leaflet-fade-anim .leaflet-popup {
|
||||
opacity: 0;
|
||||
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
-moz-transition: opacity 0.2s linear;
|
||||
-o-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
.leaflet-fade-anim .leaflet-tile-loaded, .leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-zoom-animated {
|
||||
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0.25,0.1,0.25,0.75);
|
||||
-moz-transition: -moz-transform 0.25s cubic-bezier(0.25,0.1,0.25,0.75);
|
||||
-o-transition: -o-transform 0.25s cubic-bezier(0.25,0.1,0.25,0.75);
|
||||
transition: transform 0.25s cubic-bezier(0.25,0.1,0.25,0.75);
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-tile,
|
||||
.leaflet-pan-anim .leaflet-tile,
|
||||
.leaflet-touching .leaflet-zoom-animated {
|
||||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
-o-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-zoom-hide {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
|
||||
/* Popup layout */
|
||||
|
||||
.leaflet-popup {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
}
|
||||
.leaflet-popup-content-wrapper {
|
||||
padding: 1px;
|
||||
text-align: left;
|
||||
}
|
||||
.leaflet-popup-content {
|
||||
margin: 14px 20px;
|
||||
}
|
||||
.leaflet-popup-tip-container {
|
||||
margin: 0 auto;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.leaflet-popup-tip {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
padding: 1px;
|
||||
|
||||
margin: -8px auto 0;
|
||||
|
||||
-moz-transform: rotate(45deg);
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
-o-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 4px 5px 0 0;
|
||||
text-align: center;
|
||||
width: 18px;
|
||||
height: 14px;
|
||||
font: 16px/14px Tahoma, Verdana, sans-serif;
|
||||
color: #c3c3c3;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button:hover {
|
||||
color: #999;
|
||||
}
|
||||
.leaflet-popup-content p {
|
||||
margin: 18px 0;
|
||||
}
|
||||
.leaflet-popup-scrolled {
|
||||
overflow: auto;
|
||||
border-bottom: 1px solid #ddd;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
|
||||
/* Visual appearance */
|
||||
|
||||
.leaflet-container {
|
||||
background: #ddd;
|
||||
}
|
||||
.leaflet-container a {
|
||||
color: #0078A8;
|
||||
}
|
||||
.leaflet-container a.leaflet-active {
|
||||
outline: 2px solid orange;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
border: 2px dotted #05f;
|
||||
background: white;
|
||||
opacity: 0.5;
|
||||
}
|
||||
.leaflet-div-icon {
|
||||
background: #fff;
|
||||
border: 1px solid #666;
|
||||
}
|
||||
.leaflet-editing-icon {
|
||||
border-radius: 2px;
|
||||
}
|
||||
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
|
||||
background: white;
|
||||
|
||||
box-shadow: 0 3px 10px #888;
|
||||
-moz-box-shadow: 0 3px 10px #888;
|
||||
-webkit-box-shadow: 0 3px 14px #999;
|
||||
}
|
||||
.leaflet-popup-content-wrapper {
|
||||
-moz-border-radius: 20px;
|
||||
-webkit-border-radius: 20px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
.leaflet-popup-content {
|
||||
font: 12px/1.4 "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
}
|
||||
44
vendor/leaflet/0.4.4/leaflet.ie.css
vendored
@ -1,44 +0,0 @@
|
||||
.leaflet-vml-shape {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
.lvml {
|
||||
behavior: url(#default#VML);
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.leaflet-control {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.leaflet-popup-tip {
|
||||
width: 21px;
|
||||
_width: 27px;
|
||||
margin: 0 auto;
|
||||
_margin-top: -3px;
|
||||
|
||||
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
|
||||
}
|
||||
.leaflet-popup-tip-container {
|
||||
margin-top: -1px;
|
||||
}
|
||||
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
|
||||
border: 1px solid #bbb;
|
||||
}
|
||||
|
||||
.leaflet-control-zoom {
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#3F000000',EndColorStr='#3F000000');
|
||||
}
|
||||
.leaflet-control-zoom a {
|
||||
background-color: #eee;
|
||||
}
|
||||
.leaflet-control-zoom a:hover {
|
||||
background-color: #fff;
|
||||
}
|
||||
.leaflet-control-layers-toggle {
|
||||
}
|
||||
.leaflet-control-attribution, .leaflet-control-layers {
|
||||
background: white;
|
||||
}
|
||||
6
vendor/leaflet/0.4.4/leaflet.js
vendored
BIN
vendor/leaflet/0.7.3/images/layers-2x.png
vendored
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
vendor/leaflet/0.7.3/images/layers.png
vendored
Normal file
|
After Width: | Height: | Size: 1.5 KiB |
BIN
vendor/leaflet/0.7.3/images/marker-icon-2x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
vendor/leaflet/0.7.3/images/marker-icon.png
vendored
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
vendor/leaflet/0.7.3/images/marker-shadow.png
vendored
Normal file
|
After Width: | Height: | Size: 797 B |
9180
vendor/leaflet/0.7.3/leaflet-src.js
vendored
Normal file
478
vendor/leaflet/0.7.3/leaflet.css
vendored
Normal file
@ -0,0 +1,478 @@
|
||||
/* required styles */
|
||||
|
||||
.leaflet-map-pane,
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow,
|
||||
.leaflet-tile-pane,
|
||||
.leaflet-tile-container,
|
||||
.leaflet-overlay-pane,
|
||||
.leaflet-shadow-pane,
|
||||
.leaflet-marker-pane,
|
||||
.leaflet-popup-pane,
|
||||
.leaflet-overlay-pane svg,
|
||||
.leaflet-zoom-box,
|
||||
.leaflet-image-layer,
|
||||
.leaflet-layer {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.leaflet-container {
|
||||
overflow: hidden;
|
||||
-ms-touch-action: none;
|
||||
}
|
||||
.leaflet-tile,
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
.leaflet-marker-icon,
|
||||
.leaflet-marker-shadow {
|
||||
display: block;
|
||||
}
|
||||
/* map is broken in FF if you have max-width: 100% on tiles */
|
||||
.leaflet-container img {
|
||||
max-width: none !important;
|
||||
}
|
||||
/* stupid Android 2 doesn't understand "max-width: none" properly */
|
||||
.leaflet-container img.leaflet-image-layer {
|
||||
max-width: 15000px !important;
|
||||
}
|
||||
.leaflet-tile {
|
||||
filter: inherit;
|
||||
visibility: hidden;
|
||||
}
|
||||
.leaflet-tile-loaded {
|
||||
visibility: inherit;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
|
||||
.leaflet-overlay-pane svg {
|
||||
-moz-user-select: none;
|
||||
}
|
||||
|
||||
.leaflet-tile-pane { z-index: 2; }
|
||||
.leaflet-objects-pane { z-index: 3; }
|
||||
.leaflet-overlay-pane { z-index: 4; }
|
||||
.leaflet-shadow-pane { z-index: 5; }
|
||||
.leaflet-marker-pane { z-index: 6; }
|
||||
.leaflet-popup-pane { z-index: 7; }
|
||||
|
||||
.leaflet-vml-shape {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
}
|
||||
.lvml {
|
||||
behavior: url(#default#VML);
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
|
||||
/* control positioning */
|
||||
|
||||
.leaflet-control {
|
||||
position: relative;
|
||||
z-index: 7;
|
||||
pointer-events: auto;
|
||||
}
|
||||
.leaflet-top,
|
||||
.leaflet-bottom {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
pointer-events: none;
|
||||
}
|
||||
.leaflet-top {
|
||||
top: 0;
|
||||
}
|
||||
.leaflet-right {
|
||||
right: 0;
|
||||
}
|
||||
.leaflet-bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
.leaflet-left {
|
||||
left: 0;
|
||||
}
|
||||
.leaflet-control {
|
||||
float: left;
|
||||
clear: both;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
float: right;
|
||||
}
|
||||
.leaflet-top .leaflet-control {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.leaflet-left .leaflet-control {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.leaflet-right .leaflet-control {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
|
||||
/* zoom and fade animations */
|
||||
|
||||
.leaflet-fade-anim .leaflet-tile,
|
||||
.leaflet-fade-anim .leaflet-popup {
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.2s linear;
|
||||
-moz-transition: opacity 0.2s linear;
|
||||
-o-transition: opacity 0.2s linear;
|
||||
transition: opacity 0.2s linear;
|
||||
}
|
||||
.leaflet-fade-anim .leaflet-tile-loaded,
|
||||
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-zoom-animated {
|
||||
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
-o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
|
||||
}
|
||||
.leaflet-zoom-anim .leaflet-tile,
|
||||
.leaflet-pan-anim .leaflet-tile,
|
||||
.leaflet-touching .leaflet-zoom-animated {
|
||||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
-o-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.leaflet-zoom-anim .leaflet-zoom-hide {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
|
||||
/* cursors */
|
||||
|
||||
.leaflet-clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
.leaflet-container {
|
||||
cursor: -webkit-grab;
|
||||
cursor: -moz-grab;
|
||||
}
|
||||
.leaflet-popup-pane,
|
||||
.leaflet-control {
|
||||
cursor: auto;
|
||||
}
|
||||
.leaflet-dragging .leaflet-container,
|
||||
.leaflet-dragging .leaflet-clickable {
|
||||
cursor: move;
|
||||
cursor: -webkit-grabbing;
|
||||
cursor: -moz-grabbing;
|
||||
}
|
||||
|
||||
|
||||
/* visual tweaks */
|
||||
|
||||
.leaflet-container {
|
||||
background: #ddd;
|
||||
outline: 0;
|
||||
}
|
||||
.leaflet-container a {
|
||||
color: #0078A8;
|
||||
}
|
||||
.leaflet-container a.leaflet-active {
|
||||
outline: 2px solid orange;
|
||||
}
|
||||
.leaflet-zoom-box {
|
||||
border: 2px dotted #38f;
|
||||
background: rgba(255,255,255,0.5);
|
||||
}
|
||||
|
||||
|
||||
/* general typography */
|
||||
.leaflet-container {
|
||||
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
|
||||
/* general toolbar styles */
|
||||
|
||||
.leaflet-bar {
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
|
||||
border-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a,
|
||||
.leaflet-bar a:hover {
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #ccc;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
display: block;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
}
|
||||
.leaflet-bar a,
|
||||
.leaflet-control-layers-toggle {
|
||||
background-position: 50% 50%;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
}
|
||||
.leaflet-bar a:hover {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
.leaflet-bar a:first-child {
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
.leaflet-bar a:last-child {
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
border-bottom: none;
|
||||
}
|
||||
.leaflet-bar a.leaflet-disabled {
|
||||
cursor: default;
|
||||
background-color: #f4f4f4;
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-bar a {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
|
||||
/* zoom control */
|
||||
|
||||
.leaflet-control-zoom-in,
|
||||
.leaflet-control-zoom-out {
|
||||
font: bold 18px 'Lucida Console', Monaco, monospace;
|
||||
text-indent: 1px;
|
||||
}
|
||||
.leaflet-control-zoom-out {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-zoom-in {
|
||||
font-size: 22px;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-zoom-out {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
|
||||
/* layers control */
|
||||
|
||||
.leaflet-control-layers {
|
||||
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
|
||||
background: #fff;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.leaflet-control-layers-toggle {
|
||||
background-image: url(images/layers.png);
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
.leaflet-retina .leaflet-control-layers-toggle {
|
||||
background-image: url(images/layers-2x.png);
|
||||
background-size: 26px 26px;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers-toggle {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
.leaflet-control-layers .leaflet-control-layers-list,
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
|
||||
display: none;
|
||||
}
|
||||
.leaflet-control-layers-expanded .leaflet-control-layers-list {
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
.leaflet-control-layers-expanded {
|
||||
padding: 6px 10px 6px 6px;
|
||||
color: #333;
|
||||
background: #fff;
|
||||
}
|
||||
.leaflet-control-layers-selector {
|
||||
margin-top: 2px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
.leaflet-control-layers label {
|
||||
display: block;
|
||||
}
|
||||
.leaflet-control-layers-separator {
|
||||
height: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
margin: 5px -10px 5px -6px;
|
||||
}
|
||||
|
||||
|
||||
/* attribution and scale controls */
|
||||
|
||||
.leaflet-container .leaflet-control-attribution {
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
margin: 0;
|
||||
}
|
||||
.leaflet-control-attribution,
|
||||
.leaflet-control-scale-line {
|
||||
padding: 0 5px;
|
||||
color: #333;
|
||||
}
|
||||
.leaflet-control-attribution a {
|
||||
text-decoration: none;
|
||||
}
|
||||
.leaflet-control-attribution a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.leaflet-container .leaflet-control-attribution,
|
||||
.leaflet-container .leaflet-control-scale {
|
||||
font-size: 11px;
|
||||
}
|
||||
.leaflet-left .leaflet-control-scale {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.leaflet-bottom .leaflet-control-scale {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.leaflet-control-scale-line {
|
||||
border: 2px solid #777;
|
||||
border-top: none;
|
||||
line-height: 1.1;
|
||||
padding: 2px 5px 1px;
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child) {
|
||||
border-top: 2px solid #777;
|
||||
border-bottom: none;
|
||||
margin-top: -2px;
|
||||
}
|
||||
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
|
||||
border-bottom: 2px solid #777;
|
||||
}
|
||||
|
||||
.leaflet-touch .leaflet-control-attribution,
|
||||
.leaflet-touch .leaflet-control-layers,
|
||||
.leaflet-touch .leaflet-bar {
|
||||
box-shadow: none;
|
||||
}
|
||||
.leaflet-touch .leaflet-control-layers,
|
||||
.leaflet-touch .leaflet-bar {
|
||||
border: 2px solid rgba(0,0,0,0.2);
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
|
||||
/* popup */
|
||||
|
||||
.leaflet-popup {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
}
|
||||
.leaflet-popup-content-wrapper {
|
||||
padding: 1px;
|
||||
text-align: left;
|
||||
border-radius: 12px;
|
||||
}
|
||||
.leaflet-popup-content {
|
||||
margin: 13px 19px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.leaflet-popup-content p {
|
||||
margin: 18px 0;
|
||||
}
|
||||
.leaflet-popup-tip-container {
|
||||
margin: 0 auto;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.leaflet-popup-tip {
|
||||
width: 17px;
|
||||
height: 17px;
|
||||
padding: 1px;
|
||||
|
||||
margin: -10px auto 0;
|
||||
|
||||
-webkit-transform: rotate(45deg);
|
||||
-moz-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
-o-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.leaflet-popup-content-wrapper,
|
||||
.leaflet-popup-tip {
|
||||
background: white;
|
||||
|
||||
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: 4px 4px 0 0;
|
||||
text-align: center;
|
||||
width: 18px;
|
||||
height: 14px;
|
||||
font: 16px/14px Tahoma, Verdana, sans-serif;
|
||||
color: #c3c3c3;
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
background: transparent;
|
||||
}
|
||||
.leaflet-container a.leaflet-popup-close-button:hover {
|
||||
color: #999;
|
||||
}
|
||||
.leaflet-popup-scrolled {
|
||||
overflow: auto;
|
||||
border-bottom: 1px solid #ddd;
|
||||
border-top: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.leaflet-oldie .leaflet-popup-content-wrapper {
|
||||
zoom: 1;
|
||||
}
|
||||
.leaflet-oldie .leaflet-popup-tip {
|
||||
width: 24px;
|
||||
margin: 0 auto;
|
||||
|
||||
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
|
||||
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
|
||||
}
|
||||
.leaflet-oldie .leaflet-popup-tip-container {
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.leaflet-oldie .leaflet-control-zoom,
|
||||
.leaflet-oldie .leaflet-control-layers,
|
||||
.leaflet-oldie .leaflet-popup-content-wrapper,
|
||||
.leaflet-oldie .leaflet-popup-tip {
|
||||
border: 1px solid #999;
|
||||
}
|
||||
|
||||
|
||||
/* div icon */
|
||||
|
||||
.leaflet-div-icon {
|
||||
background: #fff;
|
||||
border: 1px solid #666;
|
||||
}
|
||||