diff --git a/web/pgadmin/static/js/slickgrid/slick.pgadmin.editors.js b/web/pgadmin/static/js/slickgrid/slick.pgadmin.editors.js index 23af4efd4..d1b92cc64 100644 --- a/web/pgadmin/static/js/slickgrid/slick.pgadmin.editors.js +++ b/web/pgadmin/static/js/slickgrid/slick.pgadmin.editors.js @@ -14,6 +14,7 @@ // Below editor will read only editors, Just to display data "ReadOnlyText": ReadOnlyTextEditor, "ReadOnlyCheckbox": ReadOnlyCheckboxEditor, + "Checkbox": CheckboxEditor, // Override editor to implement checkbox with three states "ReadOnlypgText": ReadOnlypgTextEditor, "ReadOnlyJsonText": ReadOnlyJsonTextEditor, "CustomNumber": CustomNumberEditor @@ -417,6 +418,95 @@ this.init(); } + /* Override CheckboxEditor to implement checkbox with three states. + * 1) checked=true + * 2) unchecked=false + * 3) indeterminate=null/'' + */ + function CheckboxEditor(args) { + var $select, el; + var defaultValue; + var scope = this; + + this.init = function () { + $select = $(""); + $select.appendTo(args.container); + $select.focus(); + + // The following code is taken from https://css-tricks.com/indeterminate-checkboxes/ + $select.data('checked', 0).bind("click", function (e) { + el = $(this); + switch(el.data('checked')) { + // unchecked, going indeterminate + case 0: + el.data('checked', 1); + el.prop('indeterminate', true); + break; + + // indeterminate, going checked + case 1: + el.data('checked', 2); + el.prop('indeterminate', false); + el.prop('checked', true); + break; + + // checked, going unchecked + default: + el.data('checked', 0); + el.prop('indeterminate', false); + el.prop('checked', false); + } + }); + }; + + this.destroy = function () { + $select.remove(); + }; + + this.focus = function () { + $select.focus(); + }; + + this.loadValue = function (item) { + defaultValue = item[args.column.field]; + if (_.isNull(defaultValue)) { + $select.prop('indeterminate', true); + } + else { + defaultValue = !!item[args.column.field]; + if (defaultValue) { + $select.prop('checked', true); + } else { + $select.prop('checked', false); + } + } + }; + + this.serializeValue = function () { + if ($select.prop('indeterminate')) { + return null; + } + return $select.prop('checked'); + }; + + this.applyValue = function (item, state) { + item[args.column.field] = state; + }; + + this.isValueChanged = function () { + return (this.serializeValue() !== defaultValue); + }; + + this.validate = function () { + return { + valid: true, + msg: null + }; + }; + + this.init(); + } + // JSON data type editor function ReadOnlyJsonTextEditor(args) { var $input, $wrapper; diff --git a/web/pgadmin/static/js/slickgrid/slick.pgadmin.formatters.js b/web/pgadmin/static/js/slickgrid/slick.pgadmin.formatters.js index 6e0888513..b066095e1 100644 --- a/web/pgadmin/static/js/slickgrid/slick.pgadmin.formatters.js +++ b/web/pgadmin/static/js/slickgrid/slick.pgadmin.formatters.js @@ -54,8 +54,13 @@ } function CheckmarkFormatter(row, cell, value, columnDef, dataContext) { + /* Checkbox has 3 states + * 1) checked=true + * 2) unchecked=false + * 3) indeterminate=null/'' + */ if (value == null || value === "") { - return ""; + return "[null]"; } return value ? "true" : "false"; } diff --git a/web/pgadmin/tools/sqleditor/static/css/sqleditor.css b/web/pgadmin/tools/sqleditor/static/css/sqleditor.css index c7edc43f7..5b84f6f65 100644 --- a/web/pgadmin/tools/sqleditor/static/css/sqleditor.css +++ b/web/pgadmin/tools/sqleditor/static/css/sqleditor.css @@ -394,6 +394,11 @@ input.editor-checkbox { border: 0; } +/* remove outlined border on focus */ +input.editor-checkbox:focus { + outline: none; +} + /* Override selected row color */ .sc.selected { background-color: #eeeeee !important;