diff --git a/web/pgadmin/browser/register_browser_preferences.py b/web/pgadmin/browser/register_browser_preferences.py
index 009f1c1..bb5da06 100644
--- a/web/pgadmin/browser/register_browser_preferences.py
+++ b/web/pgadmin/browser/register_browser_preferences.py
@@ -387,3 +387,18 @@ def register_browser_preferences(self):
category_label=gettext('Keyboard shortcuts'),
fields=fields
)
+
+ self.preference.register(
+ 'keyboard_shortcuts',
+ 'add_grid_row',
+ gettext('Add grid row'),
+ 'keyboardshortcut',
+ {
+ 'alt': False,
+ 'shift': True,
+ 'control': True,
+ 'key': {'key_code': 65, 'char': 'a'}
+ },
+ category_label=gettext('Keyboard shortcuts'),
+ fields=fields
+ )
diff --git a/web/pgadmin/browser/static/js/keyboard.js b/web/pgadmin/browser/static/js/keyboard.js
index 9ad59b6..b50d025 100644
--- a/web/pgadmin/browser/static/js/keyboard.js
+++ b/web/pgadmin/browser/static/js/keyboard.js
@@ -41,6 +41,7 @@ _.extend(pgBrowser.keyboardNavigation, {
'direct_debugging': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'direct_debugging').value),
'drop_multiple_objects': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'grid_menu_drop_multiple').value),
'drop_cascade_multiple_objects': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'grid_menu_drop_cascade_multiple').value),
+ 'add_grid_row': commonUtils.parseShortcutValue(pgBrowser.get_preference('browser', 'add_grid_row').value),
};
this.shortcutMethods = {
@@ -61,6 +62,7 @@ _.extend(pgBrowser.keyboardNavigation, {
'bindDirectDebugging': {'shortcuts': this.keyboardShortcut.direct_debugging}, // Sub menu - Direct Debugging
'bindDropMultipleObjects': {'shortcuts': this.keyboardShortcut.drop_multiple_objects}, // Grid Menu Drop Multiple
'bindDropCascadeMultipleObjects': {'shortcuts': this.keyboardShortcut.drop_cascade_multiple_objects}, // Grid Menu Drop Cascade Multiple
+ 'bindAddGridRow': {'shortcuts': this.keyboardShortcut.add_grid_row}, // Subnode Grid Add Row
};
this.bindShortcuts();
}
@@ -330,6 +332,12 @@ _.extend(pgBrowser.keyboardNavigation, {
$('button.delete_multiple_cascade').click();
}
},
+ bindAddGridRow: function() {
+ let subNode = $(document.activeElement).closest('.object.subnode');
+ if($(subNode).length) {
+ $(subNode).find('.add').click();
+ }
+ },
isPropertyPanelVisible: function() {
let isPanelVisible = false;
_.each(pgAdmin.Browser.docker.findPanels(), (panel) => {
diff --git a/web/pgadmin/static/js/backform.pgadmin.js b/web/pgadmin/static/js/backform.pgadmin.js
index b97fc38..156430d 100644
--- a/web/pgadmin/static/js/backform.pgadmin.js
+++ b/web/pgadmin/static/js/backform.pgadmin.js
@@ -10,8 +10,10 @@
define([
'sources/gettext', 'underscore', 'underscore.string', 'jquery',
'backbone', 'backform', 'backgrid', 'codemirror', 'sources/sqleditor_utils',
+ 'sources/keyboard_shortcuts',
'spectrum', 'pgadmin.backgrid', 'select2', 'bootstrap.toggle',
-], function(gettext, _, S, $, Backbone, Backform, Backgrid, CodeMirror, SqlEditorUtils) {
+], function(gettext, _, S, $, Backbone, Backform, Backgrid, CodeMirror,
+ SqlEditorUtils, keyboardShortcuts) {
var pgAdmin = (window.pgAdmin = window.pgAdmin || {}),
pgBrowser = pgAdmin.Browser;
@@ -1269,6 +1271,13 @@ define([
var $dialog = gridBody.append(subNodeGrid);
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ let addBtn = $dialog.find('.add');
+ // Add title to the buttons
+ $(addBtn)
+ .attr('title',
+ keyboardShortcuts.shortcut_title(gettext('Add new row'),preferences.add_grid_row));
+
// Add button callback
if (!(data.disabled || data.canAdd == false)) {
$dialog.find('button.add').first().on('click',(e) => {
@@ -1554,6 +1563,14 @@ define([
var $dialog = gridBody.append(subNodeGrid);
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ let addBtn = $dialog.find('.add');
+ // Add title to the buttons
+ $(addBtn)
+ .attr('title',
+ keyboardShortcuts.shortcut_title(gettext('Add new row'),preferences.add_grid_row));
+
+
// Add button callback
$dialog.find('button.add').on('click',(e) => {
e.preventDefault();
diff --git a/web/pgadmin/static/js/backgrid.pgadmin.js b/web/pgadmin/static/js/backgrid.pgadmin.js
index c804609..86cc35c 100644
--- a/web/pgadmin/static/js/backgrid.pgadmin.js
+++ b/web/pgadmin/static/js/backgrid.pgadmin.js
@@ -9,15 +9,18 @@
define([
'sources/gettext', 'underscore', 'jquery', 'backbone', 'backform', 'backgrid', 'alertify',
- 'moment', 'bignumber', 'bootstrap.datetimepicker', 'backgrid.filter',
- 'bootstrap.toggle',
+ 'moment', 'bignumber', 'sources/utils', 'sources/keyboard_shortcuts',
+ 'bootstrap.datetimepicker', 'backgrid.filter', 'bootstrap.toggle',
], function(
- gettext, _, $, Backbone, Backform, Backgrid, Alertify, moment, BigNumber
+ gettext, _, $, Backbone, Backform, Backgrid, Alertify, moment, BigNumber,
+ commonUtils, keyboardShortcuts
) {
/*
* Add mechanism in backgrid to render different types of cells in
* same column;
*/
+ let pgAdmin = (window.pgAdmin = window.pgAdmin || {}),
+ pgBrowser = pgAdmin.Browser;
// Add new property cellFunction in Backgrid.Column.
_.extend(Backgrid.Column.prototype.defaults, {
@@ -37,6 +40,18 @@ define([
},
});
+ // bind shortcut in cell edit mode
+ _.extend(Backgrid.InputCellEditor.prototype.events, {
+ 'keydown': function(e) {
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ if(keyboardShortcuts.validateShortcutKeys(preferences.add_grid_row,e)) {
+ pgBrowser.keyboardNavigation.bindAddGridRow();
+ } else {
+ Backgrid.InputCellEditor.prototype.saveOrCancel.apply(this, arguments);
+ }
+ },
+ });
+
/* Overriding backgrid sort method.
* As we are getting numeric, integer values as string
* from server side, but on client side javascript truncates
@@ -189,7 +204,7 @@ define([
var ObjectCellEditor = Backgrid.Extension.ObjectCellEditor = Backgrid.CellEditor.extend({
modalTemplate: _.template([
- '
',
+ '
',
].join('\n')),
@@ -235,6 +250,18 @@ define([
tabPanelClassName: function() {
return 'sub-node-form col-sm-12';
},
+ events: {
+ 'keydown': function (event) {
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ if(keyboardShortcuts.validateShortcutKeys(preferences.add_grid_row,event)) {
+ pgBrowser.keyboardNavigation.bindAddGridRow();
+ } else if(keyboardShortcuts.validateShortcutKeys(preferences.save_grid_row,event)) {
+ pgBrowser.keyboardNavigation.bindSaveGridRow();
+ } else if(keyboardShortcuts.validateShortcutKeys(preferences.refresh_grid,event)) {
+ pgBrowser.keyboardNavigation.bindRefreshGrid();
+ }
+ },
+ },
});
this.objectView.render();
@@ -315,12 +342,18 @@ define([
editorOptions['el'] = $(this.el);
editorOptions['columns_length'] = this.column.collection.length;
- editorOptions['el'].attr('tabindex', 1);
+ editorOptions['el'].attr('tabindex', 0);
this.listenTo(this.model, 'backgrid:edit', function(model, column, cell, editor) {
if (column.get('name') == this.column.get('name'))
editor.extendWithOptions(editorOptions);
});
+ // Listen for Tab key, open subnode dialog on space key
+ this.$el.on('keydown', function(e) {
+ if (e.keyCode == 32) {
+ $(this).click();
+ }
+ });
},
enterEditMode: function() {
// Notify that we are about to enter in edit mode for current cell.
@@ -342,6 +375,10 @@ define([
this.$el.html(
'
'
);
+ let body = $(this.$el).parents()[1],
+ container = $(body).find('.tab-content:first > .tab-pane.active:first');
+ commonUtils.findAndSetFocus(container);
+ pgBrowser.keyboardNavigation.getDialogTabNavigator($(body).find('.subnode-dialog'));
this.model.trigger(
'pg-sub-node:opened', this.model, this
);
@@ -362,14 +399,16 @@ define([
return this;
},
exitEditMode: function() {
- var index = $(this.currentEditor.objectView.el)
- .find('.nav-tabs > .active > a[data-toggle="tab"]').first()
- .data('tabIndex');
- Backgrid.Cell.prototype.exitEditMode.apply(this, arguments);
- this.model.trigger(
- 'pg-sub-node:closed', this, index
- );
- this.grabFocus = true;
+ if(!_.isUndefined(this.currentEditor) || !_.isEmpty(this.currentEditor)) {
+ var index = $(this.currentEditor.objectView.el)
+ .find('.nav-tabs > .active > a[data-toggle="tab"]').first()
+ .data('tabIndex');
+ Backgrid.Cell.prototype.exitEditMode.apply(this, arguments);
+ this.model.trigger(
+ 'pg-sub-node:closed', this, index
+ );
+ this.grabFocus = true;
+ }
},
events: {
'click': function(e) {
@@ -382,6 +421,17 @@ define([
}
e.preventDefault();
},
+ 'keydown': function(e) {
+ var model = this.model;
+ var column = this.column;
+ var command = new Backgrid.Command(e);
+
+ if (command.moveLeft()) {
+ setTimeout(function() {
+ model.trigger('backgrid:edited', model, column, command);
+ }, 20);
+ }
+ },
},
});
@@ -413,7 +463,16 @@ define([
delete_title,
delete_msg,
function() {
+ let tbody = that.el.closest('tbody');
that.model.collection.remove(that.model);
+ let row = $(tbody).find('tr');
+ if(row.length > 0) {
+ // set focus to first tr
+ row.first().children()[0].focus();
+ } else {
+ // set focus to add button
+ $(tbody).closest('.subnode').find('.add').focus();
+ }
},
function() {
return true;
@@ -427,12 +486,54 @@ define([
);
}
},
+ exitEditMode: function() {
+ this.$el.removeClass('editor');
+ },
initialize: function() {
Backgrid.Cell.prototype.initialize.apply(this, arguments);
},
render: function() {
+ var self = this;
this.$el.empty();
+ $(this.$el).attr('tabindex', 0);
this.$el.html('
');
+ // Listen for Tab/Shift-Tab key
+ this.$el.on('keydown', function(e) {
+ // with keyboard navigation on space key, mark row for deletion
+ if (e.keyCode == 32) {
+ self.$el.click();
+ }
+ var gotoCell;
+ if (e.keyCode == 9 || e.keyCode == 16) {
+ // go to Next Cell & if Shift is also pressed go to Previous Cell
+ gotoCell = e.shiftKey ? self.$el.prev() : self.$el.next();
+ }
+
+ if (gotoCell) {
+ let command = new Backgrid.Command({
+ key: 'Tab',
+ keyCode: 9,
+ which: 9,
+ shiftKey: e.shiftKey,
+ });
+ setTimeout(function() {
+ // When we have Editable Cell
+ if (gotoCell.hasClass('editable')) {
+ e.preventDefault();
+ e.stopPropagation();
+ self.model.trigger('backgrid:edited', self.model,
+ self.column, command);
+ }
+ else {
+ // When we have Non-Editable Cell
+ self.model.trigger('backgrid:edited', self.model,
+ self.column, command);
+ }
+ }, 20);
+ }
+ });
+
+
this.delegateEvents();
return this;
},
@@ -488,6 +589,7 @@ define([
'change input': 'onChange',
'keyup': 'toggleSwitch',
'blur input': 'exitEditMode',
+ 'keydown': 'onKeyDown',
},
toggleSwitch: function(e) {
@@ -497,6 +599,13 @@ define([
}
},
+ onKeyDown: function(e) {
+ let preferences = pgBrowser.get_preferences_for_module('browser');
+ if(keyboardShortcuts.validateShortcutKeys(preferences.add_grid_row,e)) {
+ pgBrowser.keyboardNavigation.bindAddGridRow();
+ }
+ },
+
onChange: function() {
var model = this.model,
column = this.column,
@@ -553,7 +662,11 @@ define([
});
setTimeout(function() {
// When we have Editable Cell
- if (gotoCell.hasClass('editable')) {
+ if (gotoCell.hasClass('editable') && gotoCell.hasClass('edit-cell')) {
+ e.preventDefault();
+ e.stopPropagation();
+ gotoCell.trigger('focus');
+ } else if (gotoCell.hasClass('editable')) {
e.preventDefault();
e.stopPropagation();
self.model.trigger('backgrid:edited', self.model,
@@ -608,8 +721,7 @@ define([
},
saveOrCancel: function (e) {
- var model = this.model;
- var column = this.column;
+ var self = this;
var command = new Backgrid.Command(e);
var blurred = e.type === 'blur';
@@ -617,10 +729,32 @@ define([
if (command.moveUp() || command.moveDown() || command.moveLeft() || command.moveRight() ||
command.save() || blurred) {
- this.exitEditMode();
- e.preventDefault();
- e.stopPropagation();
- model.trigger('backgrid:edited', model, column, command);
+ let gotoCell;
+ // go to Next Cell & if Shift is also pressed go to Previous Cell
+ gotoCell = e.shiftKey ? self.$el.prev() : self.$el.next();
+
+ if (gotoCell) {
+ let command = new Backgrid.Command({
+ key: 'Tab',
+ keyCode: 9,
+ which: 9,
+ shiftKey: e.shiftKey,
+ });
+ setTimeout(function() {
+ // When we have Editable Cell
+ if (gotoCell.hasClass('editable')) {
+ e.preventDefault();
+ e.stopPropagation();
+ self.model.trigger('backgrid:edited', self.model,
+ self.column, command);
+ }
+ else {
+ // When we have Non-Editable Cell
+ self.model.trigger('backgrid:edited', self.model,
+ self.column, command);
+ }
+ }, 20);
+ }
}
},
events: {
diff --git a/web/pgadmin/static/js/dialog_tab_navigator.js b/web/pgadmin/static/js/dialog_tab_navigator.js
index 4472172..37bff6b 100644
--- a/web/pgadmin/static/js/dialog_tab_navigator.js
+++ b/web/pgadmin/static/js/dialog_tab_navigator.js
@@ -46,13 +46,13 @@ class dialogTabNavigator {
if(childTabData) {
var res = this.navigate(shortcut, childTabData.childTab,
- childTabData.childTabPane);
+ childTabData.childTabPane, event);
if (!res) {
- this.navigate(shortcut, this.tabs, currentTabPane);
+ this.navigate(shortcut, this.tabs, currentTabPane, event);
}
} else {
- this.navigate(shortcut, this.tabs, currentTabPane);
+ this.navigate(shortcut, this.tabs, currentTabPane, event);
}
}
@@ -73,16 +73,16 @@ class dialogTabNavigator {
return null;
}
- navigate(shortcut, tabs, tab_pane) {
+ navigate(shortcut, tabs, tab_pane, event) {
if(shortcut == this.dialogTabBackward) {
- return this.navigateBackward(tabs, tab_pane);
+ return this.navigateBackward(tabs, tab_pane, event);
}else if (shortcut == this.dialogTabForward) {
- return this.navigateForward(tabs, tab_pane);
+ return this.navigateForward(tabs, tab_pane, event);
}
return false;
}
- navigateBackward(tabs, tab_pane) {
+ navigateBackward(tabs, tab_pane, event) {
var self = this,
nextTabPane,
innerTabContainer,
@@ -105,6 +105,7 @@ class dialogTabNavigator {
self.tabSwitching = false;
}, 200);
+ event.stopPropagation();
return true;
}
@@ -112,7 +113,7 @@ class dialogTabNavigator {
return false;
}
- navigateForward(tabs, tab_pane) {
+ navigateForward(tabs, tab_pane, event) {
var self = this,
nextTabPane,
innerTabContainer,
@@ -135,6 +136,8 @@ class dialogTabNavigator {
self.tabSwitching = false;
}, 200);
+ event.stopPropagation();
+
return true;
}
this.tabSwitching = false;
diff --git a/web/pgadmin/static/scss/_backgrid.overrides.scss b/web/pgadmin/static/scss/_backgrid.overrides.scss
index b0b7475..41266eb 100644
--- a/web/pgadmin/static/scss/_backgrid.overrides.scss
+++ b/web/pgadmin/static/scss/_backgrid.overrides.scss
@@ -288,6 +288,10 @@ table.backgrid {
background-color: $color-bg-theme !important;
}
+ & td.edit-cell.editor:focus {
+ outline: $input-focus-border-color auto 5px !important;
+ }
+
tr.editor-row {
background-color: $color-gray-light !important;
& > td {
diff --git a/web/pgadmin/static/scss/_pgadmin.style.scss b/web/pgadmin/static/scss/_pgadmin.style.scss
index f5a8877..8f1e248 100644
--- a/web/pgadmin/static/scss/_pgadmin.style.scss
+++ b/web/pgadmin/static/scss/_pgadmin.style.scss
@@ -729,10 +729,17 @@ table tr th {
padding: 0;
}
& button:focus {
- outline: none;
+ outline: $input-focus-border-color auto 5px !important;
}
}
+table tr td {
+ td.edit-cell:focus,
+ td.delete-cell:focus,
+ td.string-cell:focus {
+ outline: $input-focus-border-color auto 5px !important;
+ }
+}
.privilege_label{
font-size: 10px!important;
diff --git a/web/pgadmin/static/vendor/backgrid/backgrid.js b/web/pgadmin/static/vendor/backgrid/backgrid.js
index 963ddca..1b3173b 100644
--- a/web/pgadmin/static/vendor/backgrid/backgrid.js
+++ b/web/pgadmin/static/vendor/backgrid/backgrid.js
@@ -8,32 +8,35 @@
//////////////////////////////////////////////////////////////
/*!
- backgrid
- http://github.com/wyuenho/backgrid
+ backgrid 0.3.8
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2014 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2017 Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
-(function (factory) {
+(function (root, factory) {
- // CommonJS
- if (typeof exports == "object") {
- module.exports = factory(module.exports,
- require("underscore"),
- require("backbone"));
- }
- // Browser
- else factory(this, this._, this.Backbone);
-}(function (root, _, Backbone) {
+ if (typeof define === "function" && define.amd) {
+ // AMD (+ global for extensions)
+ define(["underscore", "backbone"], function (_, Backbone) {
+ return (root.Backgrid = factory(_, Backbone));
+ });
+ } else if (typeof exports === "object") {
+ // CommonJS
+ module.exports = factory(require("underscore"), require("backbone"));
+ } else {
+ // Browser
+ root.Backgrid = factory(root._, root.Backbone);
+ }}(this, function (_, Backbone) {
"use strict";
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -72,7 +75,7 @@ function lpad(str, length, padstr) {
var $ = Backbone.$;
-var Backgrid = root.Backgrid = {
+var Backgrid = {
Extension: {},
@@ -180,9 +183,9 @@ _.extend(Command.prototype, {
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -285,7 +288,7 @@ _.extend(NumberFormatter.prototype, {
fromRaw: function (number, model) {
if (_.isNull(number) || _.isUndefined(number)) return '';
- number = number.toFixed(~~this.decimals);
+ number = parseFloat(number).toFixed(~~this.decimals);
var parts = number.split('.');
var integerPart = parts[0];
@@ -625,9 +628,9 @@ _.extend(SelectFormatter.prototype, {
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -825,7 +828,8 @@ var Cell = Backgrid.Cell = Backbone.View.extend({
/** @property */
events: {
- "click": "enterEditMode"
+ "click": "enterEditMode",
+ "focus": "onFocus"
},
/**
@@ -873,9 +877,16 @@ var Cell = Backgrid.Cell = Backbone.View.extend({
}
});
- if (Backgrid.callByNeed(column.editable(), column, model)) $el.addClass("editable");
- if (Backgrid.callByNeed(column.sortable(), column, model)) $el.addClass("sortable");
- if (Backgrid.callByNeed(column.renderable(), column, model)) $el.addClass("renderable");
+ this.updateStateClassesMaybe();
+ },
+
+ updateStateClassesMaybe: function () {
+ var model = this.model;
+ var column = this.column;
+ var $el = this.$el;
+ $el.toggleClass("editable", Backgrid.callByNeed(column.editable(), column, model));
+ $el.toggleClass("sortable", Backgrid.callByNeed(column.sortable(), column, model));
+ $el.toggleClass("renderable", Backgrid.callByNeed(column.renderable(), column, model));
},
/**
@@ -883,9 +894,18 @@ var Cell = Backgrid.Cell = Backbone.View.extend({
model's raw value for this cell's column.
*/
render: function () {
- this.$el.empty();
+ var $el = this.$el;
+ $el.empty();
var model = this.model;
- this.$el.text(this.formatter.fromRaw(model.get(this.column.get("name")), model));
+ var columnName = this.column.get("name");
+ $el.text(this.formatter.fromRaw(model.get(columnName), model));
+ $el.addClass(columnName);
+ if(this.$el.hasClass('string-cell')) {
+ if(Backgrid.callByNeed(this.column.editable(), this.column, this.model)) {
+ $el.attr('tabindex', 0);
+ }
+ }
+ this.updateStateClassesMaybe();
this.delegateEvents();
return this;
},
@@ -935,6 +955,12 @@ var Cell = Backgrid.Cell = Backbone.View.extend({
}
},
+ onFocus: function (e) {
+ if(e.keyCode == 9 && $(this).hasClass('string-cell') && $(this).hasClass('editable')) {
+ $(this).click();
+ }
+ },
+
/**
Put an `error` CSS class on the table cell.
*/
@@ -1408,7 +1434,15 @@ var SelectCellEditor = Backgrid.SelectCellEditor = CellEditor.extend({
},
/** @property {function(Object, ?Object=): string} template */
- template: _.template('', null, {variable: null}),
+ template: _.template(
+ '',
+ null,
+ {
+ variable : null,
+ evaluate : /<%([\s\S]+?)%>/g,
+ interpolate : /<%=([\s\S]+?)%>/g,
+ escape : /<%-([\s\S]+?)%>/g
+ }),
setOptionValues: function (optionValues) {
this.optionValues = optionValues;
@@ -1651,9 +1685,9 @@ var SelectCell = Backgrid.SelectCell = Cell.extend({
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -1706,19 +1740,20 @@ var Column = Backgrid.Column = Backbone.Model.extend({
this column is sortable. If the value is a string, a method will the same
name will be looked up from the column instance to determine whether the
column should be sortable. The method's signature must be `function
- (Backgrid.Column, Backbone.Model): boolean`.
+ (Backbone.Model): boolean`. The function's context is the column instance.
@cfg {boolean|string|function(): boolean} [defaults.editable=true] Whether
this column is editable. If the value is a string, a method will the same
name will be looked up from the column instance to determine whether the
column should be editable. The method's signature must be `function
- (Backgrid.Column, Backbone.Model): boolean`.
+ (Backbone.Model): boolean`. The function's context is the column instance.
@cfg {boolean|string|function(): boolean} [defaults.renderable=true]
Whether this column is renderable. If the value is a string, a method will
the same name will be looked up from the column instance to determine
whether the column should be renderable. The method's signature must be
- `function (Backrid.Column, Backbone.Model): boolean`.
+ `function (Backbone.Model): boolean`. The function's context is the column
+ instance.
@cfg {Backgrid.CellFormatter | Object | string} [defaults.formatter] The
formatter to use to convert between raw model values and user input.
@@ -1824,24 +1859,33 @@ var Column = Backgrid.Column = Backbone.Model.extend({
}
/**
+ If you cannot always determine whether a column should be sortable before
+ the grid get initialized, you can override this method.
+
@member Backgrid.Column
@protected
@method sortable
- @return {function(Backgrid.Column, Backbone.Model): boolean | boolean}
+ @return {function(Backbone.Model): boolean | boolean}
*/
/**
+ If you cannot always determine whether a column should be editable before
+ the grid get initialized, you can override this method.
+
@member Backgrid.Column
@protected
@method editable
- @return {function(Backgrid.Column, Backbone.Model): boolean | boolean}
+ @return {function(Backbone.Model): boolean | boolean}
*/
/**
+ If you cannot always determine whether a column should be renderable before
+ the grid get initialized, you can override this method.
+
@member Backgrid.Column
@protected
@method renderable
- @return {function(Backgrid.Column, Backbone.Model): boolean | boolean}
+ @return {function(Backbone.Model): boolean | boolean}
*/
});
@@ -1871,9 +1915,9 @@ var Columns = Backgrid.Columns = Backbone.Collection.extend({
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -2020,7 +2064,9 @@ var EmptyRow = Backgrid.EmptyRow = Backbone.View.extend({
var td = document.createElement("td");
td.setAttribute("colspan", this.columns.length);
- td.appendChild(document.createTextNode(_.result(this, "emptyText")));
+ var span = document.createElement("span");
+ span.innerHTML = _.result(this, "emptyText");
+ td.appendChild(span);
this.el.className = "empty";
this.el.appendChild(td);
@@ -2031,9 +2077,9 @@ var EmptyRow = Backgrid.EmptyRow = Backbone.View.extend({
/*
backgrid
- http://github.com/wyuenho/backgrid
+ http://github.com/cloudflare/backgrid
- Copyright (c) 2013 Jimmy Yuen Ho Wong and contributors
+ Copyright (c) 2013-present Cloudflare, Inc. and contributors
Licensed under the MIT license.
*/
@@ -2052,7 +2098,7 @@ var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({
/** @property */
events: {
- "click a": "onClick"
+ "click button": "onClick"
},
/**
@@ -2087,12 +2133,12 @@ var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({
if (Backgrid.callByNeed(column.sortable(), column, collection)) $el.addClass("sortable");
if (Backgrid.callByNeed(column.renderable(), column, collection)) $el.addClass("renderable");
- this.listenTo(collection.fullCollection || collection, "sort", this.removeCellDirection);
+ this.listenTo(collection.fullCollection || collection, "backgrid:sorted", this.removeCellDirection);
},
/**
- Event handler for the collection's `sort` event. Removes all the CSS
- direction classes.
+ Event handler for the collection's `backgrid:sorted` event. Removes
+ all the CSS direction classes.
*/
removeCellDirection: function () {
this.$el.removeClass("ascending").removeClass("descending");
@@ -2151,7 +2197,7 @@ var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({
var sortable = Backgrid.callByNeed(column.sortable(), column, this.collection);
var label;
if(sortable){
- label = $("").text(column.get("label")).append("");
+ label = $("