diff --git a/README.md b/README.md index 3791de5b..12f3b9ac 100755 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ See CONTRIBUTING.md. * [AdriĆ Mercader](http://amercader.net/) * [Dominik Moritz](https://github.com/domoritz) * [Friedrich Lindenberg](http://pudo.org/) +* [Alioune Dia](http://https://github.com/aliounedia) +* [kielni](https://github.com/kielni) * And [many more](https://github.com/okfn/recline/graphs/contributors) ## Changelog @@ -36,7 +38,7 @@ See CONTRIBUTING.md. [v0.6 milestone](https://github.com/okfn/recline/issues?milestone=5) Possible breaking changes - +* Support for row/add/delete/Reorder for recline slickGrid check `_includes/recline-deps.html` for slcikGrid plugins required #396 * Many backends moved to their own repositories #314 * Updated Leaflet to latest version 0.4.4 #220 * Added marker clustering in map view to handle a large number of markers diff --git a/_includes/recline-deps.html b/_includes/recline-deps.html index 2f4b241a..7e26d98e 100644 --- a/_includes/recline-deps.html +++ b/_includes/recline-deps.html @@ -20,11 +20,12 @@ - + + - + @@ -33,8 +34,20 @@ + + + - + + + + + + + + + + - + {% if page.recline-deps %} {% include recline-deps.html %} {% endif %} - + diff --git a/css/flot.css b/css/flot.css index cf203cda..57adc9f0 100644 --- a/css/flot.css +++ b/css/flot.css @@ -19,8 +19,8 @@ #recline-flot-tooltip { position: absolute; - background-color: #FEE !important; - color: #000000 !important; - opacity: 0.8 !important; - border: 1px solid #fdd !important; + background-color: #FEE; + color: #000000; + opacity: 0.8; + border: 1px solid #fdd; } diff --git a/css/multiview.css b/css/multiview.css index 6837e7c2..02c4b704 100644 --- a/css/multiview.css +++ b/css/multiview.css @@ -67,6 +67,10 @@ vertical-align: top; } +.header .recline-query-editor label { + display:none; +} + /********************************************************** * Pager *********************************************************/ @@ -78,6 +82,10 @@ margin-left: 20px; } +.header .recline-pager .pagination label { + display:none; +} + .header .recline-pager .pagination input { width: 30px; height: 18px; diff --git a/css/slickgrid.css b/css/slickgrid.css index 848a5659..5d1835a3 100644 --- a/css/slickgrid.css +++ b/css/slickgrid.css @@ -173,3 +173,12 @@ classes should alter those! line-height: 13px; } +.recline-cell-reorder { + font-size: 12px; + padding: 2px; + width: 22px; + height: 14px; + line-height: 13px; + cursor: move; + background: url("../images/drag-handle.png") no-repeat center center; +} diff --git a/demos/multiview/app.js b/demos/multiview/app.js index 929337c5..806c9a96 100755 --- a/demos/multiview/app.js +++ b/demos/multiview/app.js @@ -1,73 +1,69 @@ jQuery(function($) { - window.dataExplorer = null; + window.multiView = null; window.explorerDiv = $('.data-explorer-here'); - // This is some fancy stuff to allow configuring the multiview from - // parameters in the query string - // - // For more on state see the view documentation. - var state = recline.View.parseQueryString(decodeURIComponent(window.location.search)); - if (state) { - _.each(state, function(value, key) { - try { - value = JSON.parse(value); - } catch(e) {} - state[key] = value; - }); - } else { - state.url = 'demo'; - } - var dataset = null; - if (state.dataset || state.url) { - var datasetInfo = _.extend({ - url: state.url, - backend: state.backend - }, - state.dataset - ); - dataset = new recline.Model.Dataset(datasetInfo); - } else { - dataset = new recline.Model.Dataset({ - records: [ - {id: 0, date: '2011-01-01', x: 1, y: 2, z: 3, country: 'DE', title: 'first', lat:52.56, lon:13.40}, - {id: 1, date: '2011-02-02', x: 2, y: 4, z: 24, country: 'UK', title: 'second', lat:54.97, lon:-1.60}, - {id: 2, date: '2011-03-03', x: 3, y: 6, z: 9, country: 'US', title: 'third', lat:40.00, lon:-75.5}, - {id: 3, date: '2011-04-04', x: 4, y: 8, z: 6, country: 'UK', title: 'fourth', lat:57.27, lon:-6.20}, - {id: 4, date: '2011-05-04', x: 5, y: 10, z: 15, country: 'UK', title: 'fifth', lat:51.58, lon:0}, - {id: 5, date: '2011-06-02', x: 6, y: 12, z: 18, country: 'DE', title: 'sixth', lat:51.04, lon:7.9} - ], - // let's be really explicit about fields - // Plus take opportunity to set date to be a date field and set some labels - fields: [ - {id: 'id'}, - {id: 'date', type: 'date'}, - {id: 'x', type: 'number'}, - {id: 'y', type: 'number'}, - {id: 'z', type: 'number'}, - {id: 'country', 'label': 'Country'}, - {id: 'title', 'label': 'Title'}, - {id: 'lat'}, - {id: 'lon'} - ] - }); - } - createExplorer(dataset, state); + // create the demo dataset + var dataset = createDemoDataset(); + // now create the multiview + // this is rather more elaborate than the minimum as we configure the + // MultiView in various ways (see function below) + window.multiview = createMultiView(dataset); + + // last, we'll demonstrate binding to changes in the dataset + // this will print out a summary of each change onto the page in the + // changelog section + dataset.records.bind('all', function(name, obj) { + var $info = $('
'); + $info.html(name + ': ' + JSON.stringify(obj.toJSON())); + $('.changelog').append($info); + $('.changelog').show(); + }); }); +// create standard demo dataset +function createDemoDataset() { + var dataset = new recline.Model.Dataset({ + records: [ + {id: 0, date: '2011-01-01', x: 1, y: 2, z: 3, country: 'DE', title: 'first', lat:52.56, lon:13.40}, + {id: 1, date: '2011-02-02', x: 2, y: 4, z: 24, country: 'UK', title: 'second', lat:54.97, lon:-1.60}, + {id: 2, date: '2011-03-03', x: 3, y: 6, z: 9, country: 'US', title: 'third', lat:40.00, lon:-75.5}, + {id: 3, date: '2011-04-04', x: 4, y: 8, z: 6, country: 'UK', title: 'fourth', lat:57.27, lon:-6.20}, + {id: 4, date: '2011-05-04', x: 5, y: 10, z: 15, country: 'UK', title: 'fifth', lat:51.58, lon:0}, + {id: 5, date: '2011-06-02', x: 6, y: 12, z: 18, country: 'DE', title: 'sixth', lat:51.04, lon:7.9} + ], + // let's be really explicit about fields + // Plus take opportunity to set date to be a date field and set some labels + fields: [ + {id: 'id'}, + {id: 'date', type: 'date'}, + {id: 'x', type: 'number'}, + {id: 'y', type: 'number'}, + {id: 'z', type: 'number'}, + {id: 'country', 'label': 'Country'}, + {id: 'title', 'label': 'Title'}, + {id: 'lat'}, + {id: 'lon'} + ] + }); + return dataset; +} -// make Explorer creation / initialization in a function so we can call it -// again and again -var createExplorer = function(dataset, state) { - // remove existing data explorer view +// make MultivView +// +// creation / initialization in a function so we can call it again and again +var createMultiView = function(dataset, state) { + // remove existing multiview if present var reload = false; - if (window.dataExplorer) { - window.dataExplorer.remove(); + if (window.multiView) { + window.multiView.remove(); + window.multiView = null; reload = true; } - window.dataExplorer = null; + var $el = $(''); $el.appendTo(window.explorerDiv); + // customize the subviews for the MultiView var views = [ { id: 'grid', @@ -77,8 +73,12 @@ var createExplorer = function(dataset, state) { state: { gridOptions: { editable: true, + // Enable support for row add enabledAddRow: true, - enabledDelRow: true, + // Enable support for row delete + enabledDelRow: true, + // Enable support for row Reoder + enableReOrderRow:true, autoEdit: false, enableCellNavigation: true }, @@ -106,11 +106,12 @@ var createExplorer = function(dataset, state) { } ]; - window.dataExplorer = new recline.View.MultiView({ + var multiView = new recline.View.MultiView({ model: dataset, el: $el, state: state, views: views }); + return multiView; } diff --git a/demos/multiview/index.html b/demos/multiview/index.html index e33203a7..4028fa3a 100644 --- a/demos/multiview/index.html +++ b/demos/multiview/index.html @@ -7,14 +7,24 @@ root: ../../ +
-// var myExplorer = new model.recline.MultiView({
+// var myExplorer = new recline.View.MultiView({
// model: {{recline.Model.Dataset instance}}
// el: {{an existing dom element}}
// views: {{dataset views}}
@@ -79,10 +79,10 @@ this.recline.View = this.recline.View || {};
// special as it includes config of many of the subviews.
//
//
-// state = {
+// var state = {
// query: {dataset query state - see dataset.queryState object}
-// view-{id1}: {view-state for this view}
-// view-{id2}: {view-state for }
+// 'view-{id1}': {view-state for this view}
+// 'view-{id2}': {view-state for }
// ...
// // Explorer
// currentView: id of current view (defaults to first view if not specified)
@@ -248,6 +248,9 @@ my.MultiView = Backbone.View.extend({
// the main views
_.each(this.pageViews, function(view, pageName) {
view.view.render();
+ if (view.view.redraw) {
+ view.view.redraw();
+ }
$dataViewContainer.append(view.view.el);
if (view.view.elSidebar) {
$dataSidebar.append(view.view.elSidebar);
diff --git a/src/view.slickgrid.js b/src/view.slickgrid.js
index f9a9e385..25ca1579 100644
--- a/src/view.slickgrid.js
+++ b/src/view.slickgrid.js
@@ -155,11 +155,35 @@ my.SlickGrid = Backbone.View.extend({
}
}
};
- //Add row delete support , check if enableDelRow is set to true or not set
+ //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 ){
+ columns.push({
+ id: "#",
+ name: "",
+ width: 22,
+ behavior: "selectAndMove",
+ selectable: false,
+ resizable: false,
+ 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 ){
- columns.push({
+ columns.push({
id: 'del',
name: '',
field: 'del',
@@ -167,7 +191,8 @@ my.SlickGrid = Backbone.View.extend({
width: 38,
formatter: formatter,
validator:validator
- })}
+ })
+ }
_.each(this.model.fields.toJSON(),function(field){
var column = {
id: field.id,
@@ -279,6 +304,71 @@ 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);
+ }
+ /* end row reordering support*/
+
this._slickHandler.subscribe(this.grid.onSort, function(e, args){
var order = (args.sortAsc) ? 'asc':'desc';
var sort = [{
@@ -287,11 +377,11 @@ my.SlickGrid = Backbone.View.extend({
}];
self.model.query({sort: sort});
});
-
+
this._slickHandler.subscribe(this.grid.onColumnsReordered, function(e, args){
self.state.set({columnsOrder: _.pluck(self.grid.getColumns(),'id')});
});
-
+
this.grid.onColumnsResized.subscribe(function(e, args){
var columns = args.grid.getColumns();
var defaultColumnWidth = args.grid.getOptions().defaultColumnWidth;
@@ -316,16 +406,26 @@ my.SlickGrid = Backbone.View.extend({
this._slickHandler.subscribe(this.grid.onClick,function(e, args){
//try catch , because this fail in qunit , but no
//error on browser.
- try{e.preventDefault()}catch(e){}
- if (args.cell == 0 && self.state.get("gridOptions").enabledDelRow == true){
- // We need to delete the associated model
- var model = data.getModel(args.row);
- model.destroy()
- }
+ try{e.preventDefault()}catch(e){}
+
+ // The cell of grid that handle row delete is The first cell (0) if
+ // The grid ReOrder is not present ie enableReOrderRow == false
+ // else it is The the second cell (1) , because The 0 is now cell
+ // that handle row Reoder.
+ var cell =0
+ if(self.state.get("gridOptions")
+ && self.state.get("gridOptions").enableReOrderRow != undefined
+ && self.state.get("gridOptions").enableReOrderRow == true ){
+ cell =1
+ }
+ if (args.cell == cell && self.state.get("gridOptions").enabledDelRow == true){
+ // We need to delete the associated model
+ var model = data.getModel(args.row);
+ model.destroy()
+ }
}) ;
var columnpicker = new Slick.Controls.ColumnPicker(columns, this.grid,
_.extend(options,{state:this.state}));
-
if (self.visible){
self.grid.init();
self.rendered = true;
@@ -333,8 +433,8 @@ my.SlickGrid = Backbone.View.extend({
// Defer rendering until the view is visible
self.rendered = false;
}
-
return this;
+
},
remove: function () {
diff --git a/src/widget.pager.js b/src/widget.pager.js
index fa112f4a..e5d81283 100644
--- a/src/widget.pager.js
+++ b/src/widget.pager.js
@@ -12,7 +12,7 @@ my.Pager = Backbone.View.extend({
\
diff --git a/src/widget.queryeditor.js b/src/widget.queryeditor.js
index 87defe0d..d6566566 100644
--- a/src/widget.queryeditor.js
+++ b/src/widget.queryeditor.js
@@ -12,7 +12,7 @@ my.QueryEditor = Backbone.View.extend({
\
diff --git a/test/built.html b/test/built.html
index 3e88af2c..f0a9f591 100644
--- a/test/built.html
+++ b/test/built.html
@@ -14,7 +14,7 @@
-
+
diff --git a/test/index.html b/test/index.html
index 87698280..16a1619d 100644
--- a/test/index.html
+++ b/test/index.html
@@ -18,14 +18,24 @@
-
+
+
+
+
+
+
+
+
+
+
+