Merge pull request #969 from anandpdoshi/slickgrid-2-2
Updated to SlickGrid v2.2, which fixes scroll issue for > 1000 records
|
Before Width: | Height: | Size: 625 B After Width: | Height: | Size: 572 B |
|
Before Width: | Height: | Size: 240 B After Width: | Height: | Size: 128 B |
|
Before Width: | Height: | Size: 240 B After Width: | Height: | Size: 128 B |
|
Before Width: | Height: | Size: 631 B After Width: | Height: | Size: 578 B |
|
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 241 B |
|
Before Width: | Height: | Size: 347 B After Width: | Height: | Size: 279 B |
|
Before Width: | Height: | Size: 207 B After Width: | Height: | Size: 154 B |
|
Before Width: | Height: | Size: 209 B After Width: | Height: | Size: 156 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 510 B After Width: | Height: | Size: 345 B |
|
Before Width: | Height: | Size: 163 B After Width: | Height: | Size: 105 B |
|
Before Width: | Height: | Size: 161 B After Width: | Height: | Size: 107 B |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 592 B After Width: | Height: | Size: 537 B |
|
Before Width: | Height: | Size: 537 B After Width: | Height: | Size: 484 B |
|
|
@ -1,45 +1,80 @@
|
|||
(function ($) {
|
||||
// register namespace
|
||||
// Register namespace
|
||||
$.extend(true, window, {
|
||||
"Slick": {
|
||||
"AutoTooltips": AutoTooltips
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* AutoTooltips plugin to show/hide tooltips when columns are too narrow to fit content.
|
||||
* @constructor
|
||||
* @param {boolean} [options.enableForCells=true] - Enable tooltip for grid cells
|
||||
* @param {boolean} [options.enableForHeaderCells=false] - Enable tooltip for header cells
|
||||
* @param {number} [options.maxToolTipLength=null] - The maximum length for a tooltip
|
||||
*/
|
||||
function AutoTooltips(options) {
|
||||
var _grid;
|
||||
var _self = this;
|
||||
var _defaults = {
|
||||
enableForCells: true,
|
||||
enableForHeaderCells: false,
|
||||
maxToolTipLength: null
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initialize plugin.
|
||||
*/
|
||||
function init(grid) {
|
||||
options = $.extend(true, {}, _defaults, options);
|
||||
_grid = grid;
|
||||
_grid.onMouseEnter.subscribe(handleMouseEnter);
|
||||
if (options.enableForCells) _grid.onMouseEnter.subscribe(handleMouseEnter);
|
||||
if (options.enableForHeaderCells) _grid.onHeaderMouseEnter.subscribe(handleHeaderMouseEnter);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Destroy plugin.
|
||||
*/
|
||||
function destroy() {
|
||||
_grid.onMouseEnter.unsubscribe(handleMouseEnter);
|
||||
if (options.enableForCells) _grid.onMouseEnter.unsubscribe(handleMouseEnter);
|
||||
if (options.enableForHeaderCells) _grid.onHeaderMouseEnter.unsubscribe(handleHeaderMouseEnter);
|
||||
}
|
||||
|
||||
function handleMouseEnter(e, args) {
|
||||
|
||||
/**
|
||||
* Handle mouse entering grid cell to add/remove tooltip.
|
||||
* @param {jQuery.Event} e - The event
|
||||
*/
|
||||
function handleMouseEnter(e) {
|
||||
var cell = _grid.getCellFromEvent(e);
|
||||
if (cell) {
|
||||
var node = _grid.getCellNode(cell.row, cell.cell);
|
||||
if ($(node).innerWidth() < node.scrollWidth) {
|
||||
var text = $.trim($(node).text());
|
||||
var $node = $(_grid.getCellNode(cell.row, cell.cell));
|
||||
var text;
|
||||
if ($node.innerWidth() < $node[0].scrollWidth) {
|
||||
text = $.trim($node.text());
|
||||
if (options.maxToolTipLength && text.length > options.maxToolTipLength) {
|
||||
text = text.substr(0, options.maxToolTipLength - 3) + "...";
|
||||
}
|
||||
$(node).attr("title", text);
|
||||
} else {
|
||||
$(node).attr("title", "");
|
||||
text = "";
|
||||
}
|
||||
$node.attr("title", text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle mouse entering header cell to add/remove tooltip.
|
||||
* @param {jQuery.Event} e - The event
|
||||
* @param {object} args.column - The column definition
|
||||
*/
|
||||
function handleHeaderMouseEnter(e, args) {
|
||||
var column = args.column,
|
||||
$node = $(e.target).closest(".slick-header-column");
|
||||
if (!column.toolTip) {
|
||||
$node.attr("title", ($node.innerWidth() < $node[0].scrollWidth) ? column.name : "");
|
||||
}
|
||||
}
|
||||
|
||||
// Public API
|
||||
$.extend(this, {
|
||||
"init": init,
|
||||
"destroy": destroy
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
function CellRangeDecorator(grid, options) {
|
||||
var _elem;
|
||||
var _defaults = {
|
||||
selectionCssClass: 'slick-range-decorator',
|
||||
selectionCss: {
|
||||
"zIndex": "9999",
|
||||
"border": "2px dashed red"
|
||||
|
|
@ -32,6 +33,7 @@
|
|||
function show(range) {
|
||||
if (!_elem) {
|
||||
_elem = $("<div></div>", {css: options.selectionCss})
|
||||
.addClass(options.selectionCssClass)
|
||||
.css("position", "absolute")
|
||||
.appendTo(grid.getCanvasNode());
|
||||
}
|
||||
|
|
@ -61,4 +63,4 @@
|
|||
"hide": hide
|
||||
});
|
||||
}
|
||||
})(jQuery);
|
||||
})(jQuery);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@
|
|||
return;
|
||||
}
|
||||
|
||||
_grid.focus();
|
||||
|
||||
var start = _grid.getCellFromPoint(
|
||||
dd.startX - $(_canvas).offset().left,
|
||||
dd.startY - $(_canvas).offset().top);
|
||||
|
|
|
|||
|
|
@ -82,6 +82,13 @@
|
|||
}
|
||||
|
||||
function handleKeyDown(e) {
|
||||
/***
|
||||
* Кey codes
|
||||
* 37 left
|
||||
* 38 up
|
||||
* 39 right
|
||||
* 40 down
|
||||
*/
|
||||
var ranges, last;
|
||||
var active = _grid.getActiveCell();
|
||||
|
||||
|
|
@ -119,8 +126,10 @@
|
|||
var new_last = new Slick.Range(active.row, active.cell, active.row + dirRow*dRow, active.cell + dirCell*dCell);
|
||||
if (removeInvalidRanges([new_last]).length) {
|
||||
ranges.push(new_last);
|
||||
_grid.scrollRowIntoView(dirRow > 0 ? new_last.toRow : new_last.fromRow);
|
||||
_grid.scrollCellIntoView(new_last.fromRow, dirCell > 0 ? new_last.toCell : new_last.fromCell);
|
||||
var viewRow = dirRow > 0 ? new_last.toRow : new_last.fromRow;
|
||||
var viewCell = dirCell > 0 ? new_last.toCell : new_last.fromCell;
|
||||
_grid.scrollRowIntoView(viewRow);
|
||||
_grid.scrollCellIntoView(viewRow, viewCell);
|
||||
}
|
||||
else
|
||||
ranges.push(last);
|
||||
|
|
@ -142,4 +151,4 @@
|
|||
"onSelectedRangesChanged": new Slick.Event()
|
||||
});
|
||||
}
|
||||
})(jQuery);
|
||||
})(jQuery);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
.slick-column-name {
|
||||
.slick-column-name,
|
||||
.slick-sort-indicator {
|
||||
/**
|
||||
* This makes all "float:right" elements after it that spill over to the next line
|
||||
* display way below the lower boundary of the column thus hiding them.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
width: 14px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: left center;
|
||||
background-image: url(../images/down.gif);
|
||||
cursor: pointer;
|
||||
|
||||
display: none;
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@
|
|||
var _handler = new Slick.EventHandler();
|
||||
var _defaults = {
|
||||
buttonCssClass: null,
|
||||
buttonImage: "../images/down.gif"
|
||||
buttonImage: null
|
||||
};
|
||||
var $menu;
|
||||
var $activeHeaderColumn;
|
||||
|
|
@ -182,7 +182,7 @@
|
|||
|
||||
if (!$menu) {
|
||||
$menu = $("<div class='slick-header-menu'></div>")
|
||||
.appendTo(document.body);
|
||||
.appendTo(_grid.getContainerNode());
|
||||
}
|
||||
$menu.empty();
|
||||
|
||||
|
|
@ -225,14 +225,17 @@
|
|||
|
||||
// Position the menu.
|
||||
$menu
|
||||
.css("top", $(this).offset().top + $(this).height())
|
||||
.css("left", $(this).offset().left);
|
||||
.offset({ top: $(this).offset().top + $(this).height(), left: $(this).offset().left });
|
||||
|
||||
|
||||
// Mark the header as active to keep the highlighting.
|
||||
$activeHeaderColumn = $menuButton.closest(".slick-header-column");
|
||||
$activeHeaderColumn
|
||||
.addClass("slick-header-column-active");
|
||||
|
||||
// Stop propagation so that it doesn't register as a header click event.
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -269,4 +272,4 @@
|
|||
"onCommand": new Slick.Event()
|
||||
});
|
||||
}
|
||||
})(jQuery);
|
||||
})(jQuery);
|
||||
|
|
|
|||
|
|
@ -134,34 +134,34 @@
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!_grid.getOptions().multiSelect || (
|
||||
!e.ctrlKey && !e.shiftKey && !e.metaKey)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var selection = rangesToRows(_ranges);
|
||||
var idx = $.inArray(cell.row, selection);
|
||||
|
||||
if (!e.ctrlKey && !e.shiftKey && !e.metaKey) {
|
||||
return false;
|
||||
}
|
||||
else if (_grid.getOptions().multiSelect) {
|
||||
if (idx === -1 && (e.ctrlKey || e.metaKey)) {
|
||||
selection.push(cell.row);
|
||||
_grid.setActiveCell(cell.row, cell.cell);
|
||||
} else if (idx !== -1 && (e.ctrlKey || e.metaKey)) {
|
||||
selection = $.grep(selection, function (o, i) {
|
||||
return (o !== cell.row);
|
||||
});
|
||||
_grid.setActiveCell(cell.row, cell.cell);
|
||||
} else if (selection.length && e.shiftKey) {
|
||||
var last = selection.pop();
|
||||
var from = Math.min(cell.row, last);
|
||||
var to = Math.max(cell.row, last);
|
||||
selection = [];
|
||||
for (var i = from; i <= to; i++) {
|
||||
if (i !== last) {
|
||||
selection.push(i);
|
||||
}
|
||||
if (idx === -1 && (e.ctrlKey || e.metaKey)) {
|
||||
selection.push(cell.row);
|
||||
_grid.setActiveCell(cell.row, cell.cell);
|
||||
} else if (idx !== -1 && (e.ctrlKey || e.metaKey)) {
|
||||
selection = $.grep(selection, function (o, i) {
|
||||
return (o !== cell.row);
|
||||
});
|
||||
_grid.setActiveCell(cell.row, cell.cell);
|
||||
} else if (selection.length && e.shiftKey) {
|
||||
var last = selection.pop();
|
||||
var from = Math.min(cell.row, last);
|
||||
var to = Math.max(cell.row, last);
|
||||
selection = [];
|
||||
for (var i = from; i <= to; i++) {
|
||||
if (i !== last) {
|
||||
selection.push(i);
|
||||
}
|
||||
selection.push(last);
|
||||
_grid.setActiveCell(cell.row, cell.cell);
|
||||
}
|
||||
selection.push(last);
|
||||
_grid.setActiveCell(cell.row, cell.cell);
|
||||
}
|
||||
|
||||
_ranges = rowsToRanges(selection);
|
||||
|
|
|
|||
|
|
@ -6,16 +6,17 @@ classes should alter those!
|
|||
*/
|
||||
|
||||
.slick-header-columns {
|
||||
background-color: #f2f2f2;
|
||||
background: url('images/header-columns-bg.gif') repeat-x center bottom;
|
||||
border-bottom: 1px solid silver;
|
||||
}
|
||||
|
||||
.slick-header-column {
|
||||
background: url('images/header-columns-bg.gif') repeat-x center bottom;
|
||||
border-right: 1px solid silver;
|
||||
}
|
||||
|
||||
.slick-header-column:hover, .slick-header-column-active {
|
||||
background-color: #f5f5f5;
|
||||
background: white url('images/header-columns-over-bg.gif') repeat-x center bottom;
|
||||
}
|
||||
|
||||
.slick-headerrow {
|
||||
|
|
@ -45,10 +46,8 @@ classes should alter those!
|
|||
}
|
||||
|
||||
.slick-cell {
|
||||
padding: 1px 4px 0px 5px;
|
||||
border-top: 0px;
|
||||
border-left: 0px;
|
||||
border-right: 1px solid silver;
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
.slick-group {
|
||||
|
|
@ -62,11 +61,11 @@ classes should alter those!
|
|||
}
|
||||
|
||||
.slick-group-toggle.expanded {
|
||||
background: url(../frappe/js/lib/slickgrid/images/collapse.gif) no-repeat center center;
|
||||
background: url(images/collapse.gif) no-repeat center center;
|
||||
}
|
||||
|
||||
.slick-group-toggle.collapsed {
|
||||
background: url(../frappe/js/lib/slickgrid/images/expand.gif) no-repeat center center;
|
||||
background: url(images/expand.gif) no-repeat center center;
|
||||
}
|
||||
|
||||
.slick-group-totals {
|
||||
|
|
@ -74,6 +73,10 @@ classes should alter those!
|
|||
background: white;
|
||||
}
|
||||
|
||||
.slick-cell.selected {
|
||||
background-color: beige;
|
||||
}
|
||||
|
||||
.slick-cell.active {
|
||||
border-color: gray;
|
||||
border-style: solid;
|
||||
|
|
@ -83,18 +86,10 @@ classes should alter those!
|
|||
background: silver !important;
|
||||
}
|
||||
|
||||
.slick-row[row$="1"], .slick-row[row$="3"], .slick-row[row$="5"], .slick-row[row$="7"], .slick-row[row$="9"] {
|
||||
.slick-row.odd {
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
.slick-row.odd .slick-cell {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.slick-cell.selected {
|
||||
background-color: beige !important;
|
||||
}
|
||||
|
||||
.slick-row.ui-state-active {
|
||||
background: #F5F7D7;
|
||||
}
|
||||
|
|
@ -106,195 +101,18 @@ classes should alter those!
|
|||
|
||||
.slick-cell.invalid {
|
||||
border-color: red;
|
||||
-moz-animation-duration: 0.2s;
|
||||
-webkit-animation-duration: 0.2s;
|
||||
-moz-animation-name: slickgrid-invalid-hilite;
|
||||
-webkit-animation-name: slickgrid-invalid-hilite;
|
||||
}
|
||||
|
||||
.grid-header {
|
||||
border: 1px solid gray;
|
||||
border-bottom: 0;
|
||||
border-top: 0;
|
||||
background: url('../lib/js/lib/slickgrid/images/header-bg.gif') repeat-x center top;
|
||||
color: black;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
@-moz-keyframes slickgrid-invalid-hilite {
|
||||
from { box-shadow: 0 0 6px red; }
|
||||
to { box-shadow: none; }
|
||||
}
|
||||
|
||||
.grid-header label {
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
margin: auto auto auto 6px;
|
||||
}
|
||||
|
||||
.grid-header .ui-icon {
|
||||
margin: 4px 4px auto 6px;
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.grid-header .ui-icon.ui-state-hover {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.grid-header #txtSearch {
|
||||
margin: 0 4px 0 4px;
|
||||
padding: 2px 2px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border: 1px solid silver;
|
||||
}
|
||||
|
||||
.options-panel {
|
||||
-moz-border-radius: 6px;
|
||||
-webkit-border-radius: 6px;
|
||||
border: 1px solid silver;
|
||||
background: #f0f0f0;
|
||||
padding: 4px;
|
||||
margin-bottom: 20px;
|
||||
width: 320px;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 650px;
|
||||
}
|
||||
|
||||
/* Individual cell styles */
|
||||
.slick-cell.task-name {
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.slick-cell.task-percent {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.slick-cell.cell-move-handle {
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
border-right: solid gray;
|
||||
|
||||
background: #efefef;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.cell-move-handle:hover {
|
||||
background: #b6b9bd;
|
||||
}
|
||||
|
||||
.slick-row.selected .cell-move-handle {
|
||||
background: #D5DC8D;
|
||||
}
|
||||
|
||||
.slick-row .cell-actions {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.slick-row.complete {
|
||||
background-color: #DFD;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.percent-complete-bar {
|
||||
display: inline-block;
|
||||
height: 6px;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
}
|
||||
|
||||
/* Slick.Editors.Text, Slick.Editors.Date */
|
||||
input.editor-text {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
outline: 0;
|
||||
padding: 0;
|
||||
|
||||
}
|
||||
|
||||
.ui-datepicker-trigger {
|
||||
margin-top: 2px;
|
||||
padding: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
/* Slick.Editors.PercentComplete */
|
||||
input.editor-percentcomplete {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
background: transparent;
|
||||
outline: 0;
|
||||
padding: 0;
|
||||
|
||||
float: left;
|
||||
}
|
||||
|
||||
.editor-percentcomplete-picker {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 100%;
|
||||
background: url("../lib/js/lib/slickgrid/images/pencil.gif") no-repeat center center;
|
||||
overflow: visible;
|
||||
z-index: 1000;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.editor-percentcomplete-helper {
|
||||
border: 0 solid gray;
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
left: -9px;
|
||||
background: url("../lib/js/lib/slickgrid/images/editor-helper-bg.gif") no-repeat top left;
|
||||
padding-left: 9px;
|
||||
|
||||
width: 120px;
|
||||
height: 140px;
|
||||
display: none;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.editor-percentcomplete-wrapper {
|
||||
background: beige;
|
||||
padding: 20px 8px;
|
||||
|
||||
width: 100%;
|
||||
height: 98px;
|
||||
border: 1px solid gray;
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.editor-percentcomplete-buttons {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.editor-percentcomplete-buttons button {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.editor-percentcomplete-slider {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.editor-percentcomplete-picker:hover .editor-percentcomplete-helper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.editor-percentcomplete-helper:hover {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Slick.Editors.YesNoSelect */
|
||||
select.editor-yesno {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Slick.Editors.Checkbox */
|
||||
input.editor-checkbox {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
@-webkit-keyframes slickgrid-invalid-hilite {
|
||||
from { box-shadow: 0 0 6px red; }
|
||||
to { box-shadow: none; }
|
||||
}
|
||||
11
frappe/public/js/lib/slickgrid/slick.core.js
vendored
|
|
@ -348,7 +348,8 @@
|
|||
Group.prototype.equals = function (group) {
|
||||
return this.value === group.value &&
|
||||
this.count === group.count &&
|
||||
this.collapsed === group.collapsed;
|
||||
this.collapsed === group.collapsed &&
|
||||
this.title === group.title;
|
||||
};
|
||||
|
||||
/***
|
||||
|
|
@ -369,6 +370,14 @@
|
|||
* @type {Group}
|
||||
*/
|
||||
this.group = null;
|
||||
|
||||
/***
|
||||
* Whether the totals have been fully initialized / calculated.
|
||||
* Will be set to false for lazy-calculated group totals.
|
||||
* @param initialized
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.initialized = false;
|
||||
}
|
||||
|
||||
GroupTotals.prototype = new NonDataItem();
|
||||
|
|
|
|||
175
frappe/public/js/lib/slickgrid/slick.dataview.js
vendored
|
|
@ -60,7 +60,8 @@
|
|||
aggregateCollapsed: false,
|
||||
aggregateChildGroups: false,
|
||||
collapsed: false,
|
||||
displayTotalsRow: true
|
||||
displayTotalsRow: true,
|
||||
lazyTotalsCalculation: false
|
||||
};
|
||||
var groupingInfos = [];
|
||||
var groups = [];
|
||||
|
|
@ -266,7 +267,7 @@
|
|||
*/
|
||||
function setAggregators(groupAggregators, includeCollapsed) {
|
||||
if (!groupingInfos.length) {
|
||||
throw new Error("At least must setGrouping must be specified before calling setAggregators().");
|
||||
throw new Error("At least one grouping must be specified before calling setAggregators().");
|
||||
}
|
||||
|
||||
groupingInfos[0].aggregators = groupAggregators;
|
||||
|
|
@ -304,7 +305,7 @@
|
|||
function mapIdsToRows(idArray) {
|
||||
var rows = [];
|
||||
ensureRowsByIdCache();
|
||||
for (var i = 0; i < idArray.length; i++) {
|
||||
for (var i = 0, l = idArray.length; i < l; i++) {
|
||||
var row = rowsById[idArray[i]];
|
||||
if (row != null) {
|
||||
rows[rows.length] = row;
|
||||
|
|
@ -315,7 +316,7 @@
|
|||
|
||||
function mapRowsToIds(rowArray) {
|
||||
var ids = [];
|
||||
for (var i = 0; i < rowArray.length; i++) {
|
||||
for (var i = 0, l = rowArray.length; i < l; i++) {
|
||||
if (rowArray[i] < rows.length) {
|
||||
ids[ids.length] = rows[rowArray[i]][idProperty];
|
||||
}
|
||||
|
|
@ -363,7 +364,22 @@
|
|||
}
|
||||
|
||||
function getItem(i) {
|
||||
return rows[i];
|
||||
var item = rows[i];
|
||||
|
||||
// if this is a group row, make sure totals are calculated and update the title
|
||||
if (item && item.__group && item.totals && !item.totals.initialized) {
|
||||
var gi = groupingInfos[item.level];
|
||||
if (!gi.displayTotalsRow) {
|
||||
calculateTotals(item.totals);
|
||||
item.title = gi.formatter ? gi.formatter(item) : item.value;
|
||||
}
|
||||
}
|
||||
// if this is a totals row, make sure it's calculated
|
||||
else if (item && item.__groupTotals && !item.initialized) {
|
||||
calculateTotals(item);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
function getItemMetadata(i) {
|
||||
|
|
@ -372,7 +388,7 @@
|
|||
return null;
|
||||
}
|
||||
|
||||
// overrides for setGrouping rows
|
||||
// overrides for grouping rows
|
||||
if (item.__group) {
|
||||
return options.groupItemMetadataProvider.getGroupRowMetadata(item);
|
||||
}
|
||||
|
|
@ -421,7 +437,7 @@
|
|||
* @param varArgs Either a Slick.Group's "groupingKey" property, or a
|
||||
* variable argument list of grouping values denoting a unique path to the row. For
|
||||
* example, calling collapseGroup('high', '10%') will collapse the '10%' subgroup of
|
||||
* the 'high' setGrouping.
|
||||
* the 'high' group.
|
||||
*/
|
||||
function collapseGroup(varArgs) {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
|
|
@ -437,7 +453,7 @@
|
|||
* @param varArgs Either a Slick.Group's "groupingKey" property, or a
|
||||
* variable argument list of grouping values denoting a unique path to the row. For
|
||||
* example, calling expandGroup('high', '10%') will expand the '10%' subgroup of
|
||||
* the 'high' setGrouping.
|
||||
* the 'high' group.
|
||||
*/
|
||||
function expandGroup(varArgs) {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
|
|
@ -457,7 +473,7 @@
|
|||
var group;
|
||||
var val;
|
||||
var groups = [];
|
||||
var groupsByVal = [];
|
||||
var groupsByVal = {};
|
||||
var r;
|
||||
var level = parentGroup ? parentGroup.level + 1 : 0;
|
||||
var gi = groupingInfos[level];
|
||||
|
|
@ -503,27 +519,50 @@
|
|||
return groups;
|
||||
}
|
||||
|
||||
// TODO: lazy totals calculation
|
||||
function calculateGroupTotals(group) {
|
||||
// TODO: try moving iterating over groups into compiled accumulator
|
||||
function calculateTotals(totals) {
|
||||
var group = totals.group;
|
||||
var gi = groupingInfos[group.level];
|
||||
var isLeafLevel = (group.level == groupingInfos.length);
|
||||
var totals = new Slick.GroupTotals();
|
||||
var agg, idx = gi.aggregators.length;
|
||||
|
||||
if (!isLeafLevel && gi.aggregateChildGroups) {
|
||||
// make sure all the subgroups are calculated
|
||||
var i = group.groups.length;
|
||||
while (i--) {
|
||||
if (!group.groups[i].initialized) {
|
||||
calculateTotals(group.groups[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (idx--) {
|
||||
agg = gi.aggregators[idx];
|
||||
agg.init();
|
||||
gi.compiledAccumulators[idx].call(agg,
|
||||
(!isLeafLevel && gi.aggregateChildGroups) ? group.groups : group.rows);
|
||||
if (!isLeafLevel && gi.aggregateChildGroups) {
|
||||
gi.compiledAccumulators[idx].call(agg, group.groups);
|
||||
} else {
|
||||
gi.compiledAccumulators[idx].call(agg, group.rows);
|
||||
}
|
||||
agg.storeResult(totals);
|
||||
}
|
||||
totals.group = group;
|
||||
group.totals = totals;
|
||||
totals.initialized = true;
|
||||
}
|
||||
|
||||
function calculateTotals(groups, level) {
|
||||
function addGroupTotals(group) {
|
||||
var gi = groupingInfos[group.level];
|
||||
var totals = new Slick.GroupTotals();
|
||||
totals.group = group;
|
||||
group.totals = totals;
|
||||
if (!gi.lazyTotalsCalculation) {
|
||||
calculateTotals(totals);
|
||||
}
|
||||
}
|
||||
|
||||
function addTotals(groups, level) {
|
||||
level = level || 0;
|
||||
var gi = groupingInfos[level];
|
||||
var groupCollapsed = gi.collapsed;
|
||||
var toggledGroups = toggledGroupsByLevel[level];
|
||||
var idx = groups.length, g;
|
||||
while (idx--) {
|
||||
g = groups[idx];
|
||||
|
|
@ -532,38 +571,20 @@
|
|||
continue;
|
||||
}
|
||||
|
||||
// Do a depth-first aggregation so that parent setGrouping aggregators can access subgroup totals.
|
||||
// Do a depth-first aggregation so that parent group aggregators can access subgroup totals.
|
||||
if (g.groups) {
|
||||
calculateTotals(g.groups, level + 1);
|
||||
addTotals(g.groups, level + 1);
|
||||
}
|
||||
|
||||
if (gi.aggregators.length && (
|
||||
gi.aggregateEmpty || g.rows.length || (g.groups && g.groups.length))) {
|
||||
calculateGroupTotals(g);
|
||||
addGroupTotals(g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function finalizeGroups(groups, level) {
|
||||
level = level || 0;
|
||||
var gi = groupingInfos[level];
|
||||
var groupCollapsed = gi.collapsed;
|
||||
var toggledGroups = toggledGroupsByLevel[level];
|
||||
var idx = groups.length, g;
|
||||
while (idx--) {
|
||||
g = groups[idx];
|
||||
g.collapsed = groupCollapsed ^ toggledGroups[g.groupingKey];
|
||||
g.title = gi.formatter ? gi.formatter(g) : g.value;
|
||||
|
||||
if (g.groups) {
|
||||
finalizeGroups(g.groups, level + 1);
|
||||
// Let the non-leaf setGrouping rows get garbage-collected.
|
||||
// They may have been used by aggregates that go over all of the descendants,
|
||||
// but at this point they are no longer needed.
|
||||
g.rows = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function flattenGroupedRows(groups, level) {
|
||||
level = level || 0;
|
||||
|
|
@ -613,10 +634,10 @@
|
|||
var filterInfo = getFunctionInfo(filter);
|
||||
|
||||
var filterBody = filterInfo.body
|
||||
.replace(/return false[;}]/gi, "{ continue _coreloop; }")
|
||||
.replace(/return true[;}]/gi, "{ _retval[_idx++] = $item$; continue _coreloop; }")
|
||||
.replace(/return ([^;}]+?);/gi,
|
||||
"{ if ($1) { _retval[_idx++] = $item$; }; continue _coreloop; }");
|
||||
.replace(/return false\s*([;}]|$)/gi, "{ continue _coreloop; }$1")
|
||||
.replace(/return true\s*([;}]|$)/gi, "{ _retval[_idx++] = $item$; continue _coreloop; }$1")
|
||||
.replace(/return ([^;}]+?)\s*([;}]|$)/gi,
|
||||
"{ if ($1) { _retval[_idx++] = $item$; }; continue _coreloop; }$2");
|
||||
|
||||
// This preserves the function template code after JS compression,
|
||||
// so that replace() commands still work as expected.
|
||||
|
|
@ -645,10 +666,10 @@
|
|||
var filterInfo = getFunctionInfo(filter);
|
||||
|
||||
var filterBody = filterInfo.body
|
||||
.replace(/return false[;}]/gi, "{ continue _coreloop; }")
|
||||
.replace(/return true[;}]/gi, "{ _cache[_i] = true;_retval[_idx++] = $item$; continue _coreloop; }")
|
||||
.replace(/return ([^;}]+?);/gi,
|
||||
"{ if ((_cache[_i] = $1)) { _retval[_idx++] = $item$; }; continue _coreloop; }");
|
||||
.replace(/return false\s*([;}]|$)/gi, "{ continue _coreloop; }$1")
|
||||
.replace(/return true\s*([;}]|$)/gi, "{ _cache[_i] = true;_retval[_idx++] = $item$; continue _coreloop; }$1")
|
||||
.replace(/return ([^;}]+?)\s*([;}]|$)/gi,
|
||||
"{ if ((_cache[_i] = $1)) { _retval[_idx++] = $item$; }; continue _coreloop; }$2");
|
||||
|
||||
// This preserves the function template code after JS compression,
|
||||
// so that replace() commands still work as expected.
|
||||
|
|
@ -793,8 +814,7 @@
|
|||
if (groupingInfos.length) {
|
||||
groups = extractGroups(newRows);
|
||||
if (groups.length) {
|
||||
calculateTotals(groups);
|
||||
finalizeGroups(groups);
|
||||
addTotals(groups);
|
||||
newRows = flattenGroupedRows(groups);
|
||||
}
|
||||
}
|
||||
|
|
@ -838,17 +858,50 @@
|
|||
}
|
||||
}
|
||||
|
||||
function syncGridSelection(grid, preserveHidden) {
|
||||
/***
|
||||
* Wires the grid and the DataView together to keep row selection tied to item ids.
|
||||
* This is useful since, without it, the grid only knows about rows, so if the items
|
||||
* move around, the same rows stay selected instead of the selection moving along
|
||||
* with the items.
|
||||
*
|
||||
* NOTE: This doesn't work with cell selection model.
|
||||
*
|
||||
* @param grid {Slick.Grid} The grid to sync selection with.
|
||||
* @param preserveHidden {Boolean} Whether to keep selected items that go out of the
|
||||
* view due to them getting filtered out.
|
||||
* @param preserveHiddenOnSelectionChange {Boolean} Whether to keep selected items
|
||||
* that are currently out of the view (see preserveHidden) as selected when selection
|
||||
* changes.
|
||||
* @return {Slick.Event} An event that notifies when an internal list of selected row ids
|
||||
* changes. This is useful since, in combination with the above two options, it allows
|
||||
* access to the full list selected row ids, and not just the ones visible to the grid.
|
||||
* @method syncGridSelection
|
||||
*/
|
||||
function syncGridSelection(grid, preserveHidden, preserveHiddenOnSelectionChange) {
|
||||
var self = this;
|
||||
var selectedRowIds = self.mapRowsToIds(grid.getSelectedRows());;
|
||||
var inHandler;
|
||||
var selectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
|
||||
var onSelectedRowIdsChanged = new Slick.Event();
|
||||
|
||||
function setSelectedRowIds(rowIds) {
|
||||
if (selectedRowIds.join(",") == rowIds.join(",")) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectedRowIds = rowIds;
|
||||
|
||||
onSelectedRowIdsChanged.notify({
|
||||
"grid": grid,
|
||||
"ids": selectedRowIds
|
||||
}, new Slick.EventData(), self);
|
||||
}
|
||||
|
||||
function update() {
|
||||
if (selectedRowIds.length > 0) {
|
||||
inHandler = true;
|
||||
var selectedRows = self.mapIdsToRows(selectedRowIds);
|
||||
if (!preserveHidden) {
|
||||
selectedRowIds = self.mapRowsToIds(selectedRows);
|
||||
setSelectedRowIds(self.mapRowsToIds(selectedRows));
|
||||
}
|
||||
grid.setSelectedRows(selectedRows);
|
||||
inHandler = false;
|
||||
|
|
@ -857,12 +910,22 @@
|
|||
|
||||
grid.onSelectedRowsChanged.subscribe(function(e, args) {
|
||||
if (inHandler) { return; }
|
||||
selectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
|
||||
var newSelectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
|
||||
if (!preserveHiddenOnSelectionChange || !grid.getOptions().multiSelect) {
|
||||
setSelectedRowIds(newSelectedRowIds);
|
||||
} else {
|
||||
// keep the ones that are hidden
|
||||
var existing = $.grep(selectedRowIds, function(id) { return self.getRowById(id) === undefined; });
|
||||
// add the newly selected ones
|
||||
setSelectedRowIds(existing.concat(newSelectedRowIds));
|
||||
}
|
||||
});
|
||||
|
||||
this.onRowsChanged.subscribe(update);
|
||||
|
||||
this.onRowCountChanged.subscribe(update);
|
||||
|
||||
return onSelectedRowIdsChanged;
|
||||
}
|
||||
|
||||
function syncGridCellCssStyles(grid, key) {
|
||||
|
|
@ -910,7 +973,7 @@
|
|||
this.onRowCountChanged.subscribe(update);
|
||||
}
|
||||
|
||||
return {
|
||||
$.extend(this, {
|
||||
// methods
|
||||
"beginUpdate": beginUpdate,
|
||||
"endUpdate": endUpdate,
|
||||
|
|
@ -956,7 +1019,7 @@
|
|||
"onRowCountChanged": onRowCountChanged,
|
||||
"onRowsChanged": onRowsChanged,
|
||||
"onPagingInfoChanged": onPagingInfoChanged
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function AvgAggregator(field) {
|
||||
|
|
|
|||
|
|
@ -304,14 +304,14 @@
|
|||
this.loadValue = function (item) {
|
||||
defaultValue = !!item[args.column.field];
|
||||
if (defaultValue) {
|
||||
$select.attr("checked", "checked");
|
||||
$select.prop('checked', true);
|
||||
} else {
|
||||
$select.removeAttr("checked");
|
||||
$select.prop('checked', false);
|
||||
}
|
||||
};
|
||||
|
||||
this.serializeValue = function () {
|
||||
return !!$select.attr("checked");
|
||||
return $select.prop('checked');
|
||||
};
|
||||
|
||||
this.applyValue = function (item, state) {
|
||||
|
|
|
|||
59
frappe/public/js/lib/slickgrid/slick.formatters.js
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/***
|
||||
* Contains basic SlickGrid formatters.
|
||||
*
|
||||
* NOTE: These are merely examples. You will most likely need to implement something more
|
||||
* robust/extensible/localizable/etc. for your use!
|
||||
*
|
||||
* @module Formatters
|
||||
* @namespace Slick
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
// register namespace
|
||||
$.extend(true, window, {
|
||||
"Slick": {
|
||||
"Formatters": {
|
||||
"PercentComplete": PercentCompleteFormatter,
|
||||
"PercentCompleteBar": PercentCompleteBarFormatter,
|
||||
"YesNo": YesNoFormatter,
|
||||
"Checkmark": CheckmarkFormatter
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function PercentCompleteFormatter(row, cell, value, columnDef, dataContext) {
|
||||
if (value == null || value === "") {
|
||||
return "-";
|
||||
} else if (value < 50) {
|
||||
return "<span style='color:red;font-weight:bold;'>" + value + "%</span>";
|
||||
} else {
|
||||
return "<span style='color:green'>" + value + "%</span>";
|
||||
}
|
||||
}
|
||||
|
||||
function PercentCompleteBarFormatter(row, cell, value, columnDef, dataContext) {
|
||||
if (value == null || value === "") {
|
||||
return "";
|
||||
}
|
||||
|
||||
var color;
|
||||
|
||||
if (value < 30) {
|
||||
color = "red";
|
||||
} else if (value < 70) {
|
||||
color = "silver";
|
||||
} else {
|
||||
color = "green";
|
||||
}
|
||||
|
||||
return "<span class='percent-complete-bar' style='background:" + color + ";width:" + value + "%'></span>";
|
||||
}
|
||||
|
||||
function YesNoFormatter(row, cell, value, columnDef, dataContext) {
|
||||
return value ? "Yes" : "No";
|
||||
}
|
||||
|
||||
function CheckmarkFormatter(row, cell, value, columnDef, dataContext) {
|
||||
return value ? "<img src='../images/tick.png'>" : "";
|
||||
}
|
||||
})(jQuery);
|
||||
|
|
@ -48,6 +48,8 @@ classes should alter those!
|
|||
width: 8px;
|
||||
height: 5px;
|
||||
margin-left: 4px;
|
||||
margin-top: 6px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.slick-sort-indicator-desc {
|
||||
|
|
|
|||
265
frappe/public/js/lib/slickgrid/slick.grid.js
vendored
|
|
@ -1,13 +1,13 @@
|
|||
/**
|
||||
* @license
|
||||
* (c) 2009-2012 Michael Leibman
|
||||
* (c) 2009-2013 Michael Leibman
|
||||
* michael{dot}leibman{at}gmail{dot}com
|
||||
* http://github.com/mleibman/slickgrid
|
||||
*
|
||||
* Distributed under MIT license.
|
||||
* All rights reserved.
|
||||
*
|
||||
* SlickGrid v2.1
|
||||
* SlickGrid v2.2
|
||||
*
|
||||
* NOTES:
|
||||
* Cell/row DOM manipulations are done directly bypassing jQuery's DOM manipulation methods.
|
||||
|
|
@ -85,7 +85,8 @@ if (typeof Slick === "undefined") {
|
|||
fullWidthRows: false,
|
||||
multiColumnSort: false,
|
||||
defaultFormatter: defaultFormatter,
|
||||
forceSyncScrolling: false
|
||||
forceSyncScrolling: false,
|
||||
addNewRowCssClass: "new-row"
|
||||
};
|
||||
|
||||
var columnDefaults = {
|
||||
|
|
@ -133,7 +134,6 @@ if (typeof Slick === "undefined") {
|
|||
var headerColumnWidthDiff = 0, headerColumnHeightDiff = 0, // border+padding
|
||||
cellWidthDiff = 0, cellHeightDiff = 0;
|
||||
var absoluteColumnMinWidth;
|
||||
var numberOfRows = 0;
|
||||
|
||||
var tabbingDirection = 1;
|
||||
var activePosX;
|
||||
|
|
@ -177,6 +177,11 @@ if (typeof Slick === "undefined") {
|
|||
var counter_rows_rendered = 0;
|
||||
var counter_rows_removed = 0;
|
||||
|
||||
// These two variables work around a bug with inertial scrolling in Webkit/Blink on Mac.
|
||||
// See http://crbug.com/312427.
|
||||
var rowNodeFromLastMouseWheelEvent; // this node must not be deleted while inertial scrolling
|
||||
var zombieRowNodeFromLastMouseWheelEvent; // node that was hidden instead of getting deleted
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Initialization
|
||||
|
|
@ -299,6 +304,7 @@ if (typeof Slick === "undefined") {
|
|||
$container
|
||||
.bind("resize.slickgrid", resizeCanvas);
|
||||
$viewport
|
||||
//.bind("click", handleClick)
|
||||
.bind("scroll", handleScroll);
|
||||
$headerScroller
|
||||
.bind("contextmenu", handleHeaderContextMenu)
|
||||
|
|
@ -320,6 +326,12 @@ if (typeof Slick === "undefined") {
|
|||
.bind("dragend", handleDragEnd)
|
||||
.delegate(".slick-cell", "mouseenter", handleMouseEnter)
|
||||
.delegate(".slick-cell", "mouseleave", handleMouseLeave);
|
||||
|
||||
// Work around http://crbug.com/312427.
|
||||
if (navigator.userAgent.toLowerCase().match(/webkit/) &&
|
||||
navigator.userAgent.toLowerCase().match(/macintosh/)) {
|
||||
$canvas.bind("mousewheel", handleMouseWheel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -547,9 +559,10 @@ if (typeof Slick === "undefined") {
|
|||
for (var i = 0; i < columns.length; i++) {
|
||||
var m = columns[i];
|
||||
|
||||
var header = $("<div class='ui-state-default slick-header-column' id='" + uid + m.id + "' />")
|
||||
var header = $("<div class='ui-state-default slick-header-column' />")
|
||||
.html("<span class='slick-column-name'>" + m.name + "</span>")
|
||||
.width(m.width - headerColumnWidthDiff)
|
||||
.attr("id", "" + uid + m.id)
|
||||
.attr("title", m.toolTip || "")
|
||||
.data("column", m)
|
||||
.addClass(m.headerCssClass || "")
|
||||
|
|
@ -666,8 +679,8 @@ if (typeof Slick === "undefined") {
|
|||
tolerance: "intersection",
|
||||
helper: "clone",
|
||||
placeholder: "slick-sortable-placeholder ui-state-default slick-header-column",
|
||||
forcePlaceholderSize: true,
|
||||
start: function (e, ui) {
|
||||
ui.placeholder.width(ui.helper.outerWidth() - headerColumnWidthDiff);
|
||||
$(ui.helper).addClass("slick-header-column-active");
|
||||
},
|
||||
beforeStop: function (e, ui) {
|
||||
|
|
@ -878,23 +891,27 @@ if (typeof Slick === "undefined") {
|
|||
|
||||
el = $("<div class='ui-state-default slick-header-column' style='visibility:hidden'>-</div>").appendTo($headers);
|
||||
headerColumnWidthDiff = headerColumnHeightDiff = 0;
|
||||
$.each(h, function (n, val) {
|
||||
headerColumnWidthDiff += parseFloat(el.css(val)) || 0;
|
||||
});
|
||||
$.each(v, function (n, val) {
|
||||
headerColumnHeightDiff += parseFloat(el.css(val)) || 0;
|
||||
});
|
||||
if (el.css("box-sizing") != "border-box" && el.css("-moz-box-sizing") != "border-box" && el.css("-webkit-box-sizing") != "border-box") {
|
||||
$.each(h, function (n, val) {
|
||||
headerColumnWidthDiff += parseFloat(el.css(val)) || 0;
|
||||
});
|
||||
$.each(v, function (n, val) {
|
||||
headerColumnHeightDiff += parseFloat(el.css(val)) || 0;
|
||||
});
|
||||
}
|
||||
el.remove();
|
||||
|
||||
var r = $("<div class='slick-row' />").appendTo($canvas);
|
||||
el = $("<div class='slick-cell' id='' style='visibility:hidden'>-</div>").appendTo(r);
|
||||
cellWidthDiff = cellHeightDiff = 0;
|
||||
$.each(h, function (n, val) {
|
||||
cellWidthDiff += parseFloat(el.css(val)) || 0;
|
||||
});
|
||||
$.each(v, function (n, val) {
|
||||
cellHeightDiff += parseFloat(el.css(val)) || 0;
|
||||
});
|
||||
if (el.css("box-sizing") != "border-box" && el.css("-moz-box-sizing") != "border-box" && el.css("-webkit-box-sizing") != "border-box") {
|
||||
$.each(h, function (n, val) {
|
||||
cellWidthDiff += parseFloat(el.css(val)) || 0;
|
||||
});
|
||||
$.each(v, function (n, val) {
|
||||
cellHeightDiff += parseFloat(el.css(val)) || 0;
|
||||
});
|
||||
}
|
||||
r.remove();
|
||||
|
||||
absoluteColumnMinWidth = Math.max(headerColumnWidthDiff, cellWidthDiff);
|
||||
|
|
@ -975,8 +992,8 @@ if (typeof Slick === "undefined") {
|
|||
unregisterPlugin(plugins[i]);
|
||||
}
|
||||
|
||||
if (options.enableColumnReorder && $headers.sortable) {
|
||||
$headers.sortable("destroy");
|
||||
if (options.enableColumnReorder) {
|
||||
$headers.filter(":ui-sortable").sortable("destroy");
|
||||
}
|
||||
|
||||
unbindAncestorScrollEvents();
|
||||
|
|
@ -1044,7 +1061,7 @@ if (typeof Slick === "undefined") {
|
|||
shrinkLeeway -= shrinkSize;
|
||||
widths[i] -= shrinkSize;
|
||||
}
|
||||
if (prevTotal == total) { // avoid infinite loop
|
||||
if (prevTotal <= total) { // avoid infinite loop
|
||||
break;
|
||||
}
|
||||
prevTotal = total;
|
||||
|
|
@ -1056,14 +1073,18 @@ if (typeof Slick === "undefined") {
|
|||
var growProportion = availWidth / total;
|
||||
for (i = 0; i < columns.length && total < availWidth; i++) {
|
||||
c = columns[i];
|
||||
if (!c.resizable || c.maxWidth <= c.width) {
|
||||
continue;
|
||||
var currentWidth = widths[i];
|
||||
var growSize;
|
||||
|
||||
if (!c.resizable || c.maxWidth <= currentWidth) {
|
||||
growSize = 0;
|
||||
} else {
|
||||
growSize = Math.min(Math.floor(growProportion * currentWidth) - currentWidth, (c.maxWidth - currentWidth) || 1000000) || 1;
|
||||
}
|
||||
var growSize = Math.min(Math.floor(growProportion * c.width) - c.width, (c.maxWidth - c.width) || 1000000) || 1;
|
||||
total += growSize;
|
||||
widths[i] += growSize;
|
||||
}
|
||||
if (prevTotal == total) { // avoid infinite loop
|
||||
if (prevTotal >= total) { // avoid infinite loop
|
||||
break;
|
||||
}
|
||||
prevTotal = total;
|
||||
|
|
@ -1257,6 +1278,10 @@ if (typeof Slick === "undefined") {
|
|||
}
|
||||
}
|
||||
|
||||
function getDataLengthIncludingAddNew() {
|
||||
return getDataLength() + (options.enableAddRow ? 1 : 0);
|
||||
}
|
||||
|
||||
function getDataItem(i) {
|
||||
if (data.getItem) {
|
||||
return data.getItem(i);
|
||||
|
|
@ -1291,6 +1316,10 @@ if (typeof Slick === "undefined") {
|
|||
}
|
||||
}
|
||||
|
||||
function getContainerNode() {
|
||||
return $container.get(0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Rendering / Scrolling
|
||||
|
||||
|
|
@ -1330,7 +1359,7 @@ if (typeof Slick === "undefined") {
|
|||
if (value == null) {
|
||||
return "";
|
||||
} else {
|
||||
return value.toString().replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
|
||||
return (value + "").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1371,14 +1400,18 @@ if (typeof Slick === "undefined") {
|
|||
return item[columnDef.field];
|
||||
}
|
||||
|
||||
function appendRowHtml(stringArray, row, range) {
|
||||
function appendRowHtml(stringArray, row, range, dataLength) {
|
||||
var d = getDataItem(row);
|
||||
var dataLoading = row < getDataLength() && !d;
|
||||
var dataLoading = row < dataLength && !d;
|
||||
var rowCss = "slick-row" +
|
||||
(dataLoading ? " loading" : "") +
|
||||
(row === activeRow ? " active" : "") +
|
||||
(row % 2 == 1 ? " odd" : " even");
|
||||
|
||||
if (!d) {
|
||||
rowCss += " " + options.addNewRowCssClass;
|
||||
}
|
||||
|
||||
var metadata = data.getItemMetadata && data.getItemMetadata(row);
|
||||
|
||||
if (metadata && metadata.cssClasses) {
|
||||
|
|
@ -1406,7 +1439,7 @@ if (typeof Slick === "undefined") {
|
|||
break;
|
||||
}
|
||||
|
||||
appendCellHtml(stringArray, row, i, colspan);
|
||||
appendCellHtml(stringArray, row, i, colspan, d);
|
||||
}
|
||||
|
||||
if (colspan > 1) {
|
||||
|
|
@ -1417,9 +1450,8 @@ if (typeof Slick === "undefined") {
|
|||
stringArray.push("</div>");
|
||||
}
|
||||
|
||||
function appendCellHtml(stringArray, row, cell, colspan) {
|
||||
function appendCellHtml(stringArray, row, cell, colspan, item) {
|
||||
var m = columns[cell];
|
||||
var d = getDataItem(row);
|
||||
var cellCss = "slick-cell l" + cell + " r" + Math.min(columns.length - 1, cell + colspan - 1) +
|
||||
(m.cssClass ? " " + m.cssClass : "");
|
||||
if (row === activeRow && cell === activeCell) {
|
||||
|
|
@ -1436,9 +1468,9 @@ if (typeof Slick === "undefined") {
|
|||
stringArray.push("<div class='" + cellCss + "'>");
|
||||
|
||||
// if there is a corresponding row (if not, this is the Add New row or this data hasn't been loaded yet)
|
||||
if (d) {
|
||||
var value = getDataItemValueForColumn(d, m);
|
||||
stringArray.push(getFormatter(row, m)(row, cell, value, m, d));
|
||||
if (item) {
|
||||
var value = getDataItemValueForColumn(item, m);
|
||||
stringArray.push(getFormatter(row, m)(row, cell, value, m, item));
|
||||
}
|
||||
|
||||
stringArray.push("</div>");
|
||||
|
|
@ -1476,7 +1508,14 @@ if (typeof Slick === "undefined") {
|
|||
if (!cacheEntry) {
|
||||
return;
|
||||
}
|
||||
$canvas[0].removeChild(cacheEntry.rowNode);
|
||||
|
||||
if (rowNodeFromLastMouseWheelEvent == cacheEntry.rowNode) {
|
||||
cacheEntry.rowNode.style.display = 'none';
|
||||
zombieRowNodeFromLastMouseWheelEvent = rowNodeFromLastMouseWheelEvent;
|
||||
} else {
|
||||
$canvas[0].removeChild(cacheEntry.rowNode);
|
||||
}
|
||||
|
||||
delete rowsCache[row];
|
||||
delete postProcessedRows[row];
|
||||
renderedRows--;
|
||||
|
|
@ -1526,6 +1565,8 @@ if (typeof Slick === "undefined") {
|
|||
|
||||
ensureCellNodesInRowsCache(row);
|
||||
|
||||
var d = getDataItem(row);
|
||||
|
||||
for (var columnIdx in cacheEntry.cellNodesByColumnIdx) {
|
||||
if (!cacheEntry.cellNodesByColumnIdx.hasOwnProperty(columnIdx)) {
|
||||
continue;
|
||||
|
|
@ -1533,7 +1574,6 @@ if (typeof Slick === "undefined") {
|
|||
|
||||
columnIdx = columnIdx | 0;
|
||||
var m = columns[columnIdx],
|
||||
d = getDataItem(row),
|
||||
node = cacheEntry.cellNodesByColumnIdx[columnIdx];
|
||||
|
||||
if (row === activeRow && columnIdx === activeCell && currentEditor) {
|
||||
|
|
@ -1560,7 +1600,7 @@ if (typeof Slick === "undefined") {
|
|||
function resizeCanvas() {
|
||||
if (!initialized) { return; }
|
||||
if (options.autoHeight) {
|
||||
viewportH = options.rowHeight * (getDataLength() + (options.enableAddRow ? 1 : 0));
|
||||
viewportH = options.rowHeight * getDataLengthIncludingAddNew();
|
||||
} else {
|
||||
viewportH = getViewportHeight();
|
||||
}
|
||||
|
|
@ -1577,22 +1617,27 @@ if (typeof Slick === "undefined") {
|
|||
|
||||
updateRowCount();
|
||||
handleScroll();
|
||||
// Since the width has changed, force the render() to reevaluate virtually rendered cells.
|
||||
lastRenderedScrollLeft = -1;
|
||||
render();
|
||||
}
|
||||
|
||||
function updateRowCount() {
|
||||
if (!initialized) { return; }
|
||||
numberOfRows = getDataLength() +
|
||||
(options.enableAddRow ? 1 : 0) +
|
||||
|
||||
var dataLengthIncludingAddNew = getDataLengthIncludingAddNew();
|
||||
var numberOfRows = dataLengthIncludingAddNew +
|
||||
(options.leaveSpaceForNewRows ? numVisibleRows - 1 : 0);
|
||||
|
||||
var oldViewportHasVScroll = viewportHasVScroll;
|
||||
// with autoHeight, we do not need to accommodate the vertical scroll bar
|
||||
viewportHasVScroll = !options.autoHeight && (numberOfRows * options.rowHeight > viewportH);
|
||||
|
||||
makeActiveCellNormal();
|
||||
|
||||
// remove the rows that are now outside of the data range
|
||||
// this helps avoid redundant calls to .removeRow() when the size of the data decreased by thousands of rows
|
||||
var l = options.enableAddRow ? getDataLength() : getDataLength() - 1;
|
||||
var l = dataLengthIncludingAddNew - 1;
|
||||
for (var i in rowsCache) {
|
||||
if (i >= l) {
|
||||
removeRowFromCache(i);
|
||||
|
|
@ -1678,7 +1723,7 @@ if (typeof Slick === "undefined") {
|
|||
}
|
||||
|
||||
range.top = Math.max(0, range.top);
|
||||
range.bottom = Math.min(options.enableAddRow ? getDataLength() : getDataLength() - 1, range.bottom);
|
||||
range.bottom = Math.min(getDataLengthIncludingAddNew() - 1, range.bottom);
|
||||
|
||||
range.leftPx -= viewportW;
|
||||
range.rightPx += viewportW;
|
||||
|
|
@ -1747,7 +1792,7 @@ if (typeof Slick === "undefined") {
|
|||
var totalCellsAdded = 0;
|
||||
var colspan;
|
||||
|
||||
for (var row = range.top; row <= range.bottom; row++) {
|
||||
for (var row = range.top, btm = range.bottom; row <= btm; row++) {
|
||||
cacheEntry = rowsCache[row];
|
||||
if (!cacheEntry) {
|
||||
continue;
|
||||
|
|
@ -1764,6 +1809,8 @@ if (typeof Slick === "undefined") {
|
|||
var metadata = data.getItemMetadata && data.getItemMetadata(row);
|
||||
metadata = metadata && metadata.columns;
|
||||
|
||||
var d = getDataItem(row);
|
||||
|
||||
// TODO: shorten this loop (index? heuristics? binary search?)
|
||||
for (var i = 0, ii = columns.length; i < ii; i++) {
|
||||
// Cells to the right are outside the range.
|
||||
|
|
@ -1787,7 +1834,7 @@ if (typeof Slick === "undefined") {
|
|||
}
|
||||
|
||||
if (columnPosRight[Math.min(ii - 1, i + colspan - 1)] > range.leftPx) {
|
||||
appendCellHtml(stringArray, row, i, colspan);
|
||||
appendCellHtml(stringArray, row, i, colspan, d);
|
||||
cellsAdded++;
|
||||
}
|
||||
|
||||
|
|
@ -1824,9 +1871,10 @@ if (typeof Slick === "undefined") {
|
|||
var parentNode = $canvas[0],
|
||||
stringArray = [],
|
||||
rows = [],
|
||||
needToReselectCell = false;
|
||||
needToReselectCell = false,
|
||||
dataLength = getDataLength();
|
||||
|
||||
for (var i = range.top; i <= range.bottom; i++) {
|
||||
for (var i = range.top, ii = range.bottom; i <= ii; i++) {
|
||||
if (rowsCache[i]) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -1851,7 +1899,7 @@ if (typeof Slick === "undefined") {
|
|||
"cellRenderQueue": []
|
||||
};
|
||||
|
||||
appendRowHtml(stringArray, i, range);
|
||||
appendRowHtml(stringArray, i, range, dataLength);
|
||||
if (activeCellNode && activeRow === i) {
|
||||
needToReselectCell = true;
|
||||
}
|
||||
|
|
@ -1910,7 +1958,7 @@ if (typeof Slick === "undefined") {
|
|||
renderRows(rendered);
|
||||
|
||||
postProcessFromRow = visible.top;
|
||||
postProcessToRow = Math.min(options.enableAddRow ? getDataLength() : getDataLength() - 1, visible.bottom);
|
||||
postProcessToRow = Math.min(getDataLengthIncludingAddNew() - 1, visible.bottom);
|
||||
startPostProcessing();
|
||||
|
||||
lastRenderedScrollTop = scrollTop;
|
||||
|
|
@ -1982,10 +2030,11 @@ if (typeof Slick === "undefined") {
|
|||
}
|
||||
|
||||
function asyncPostProcessRows() {
|
||||
var dataLength = getDataLength();
|
||||
while (postProcessFromRow <= postProcessToRow) {
|
||||
var row = (vScrollDir >= 0) ? postProcessFromRow++ : postProcessToRow--;
|
||||
var cacheEntry = rowsCache[row];
|
||||
if (!cacheEntry || row >= getDataLength()) {
|
||||
if (!cacheEntry || row >= dataLength) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -2106,6 +2155,17 @@ if (typeof Slick === "undefined") {
|
|||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Interactivity
|
||||
|
||||
function handleMouseWheel(e) {
|
||||
var rowNode = $(e.target).closest(".slick-row")[0];
|
||||
if (rowNode != rowNodeFromLastMouseWheelEvent) {
|
||||
if (zombieRowNodeFromLastMouseWheelEvent && zombieRowNodeFromLastMouseWheelEvent != rowNode) {
|
||||
$canvas[0].removeChild(zombieRowNodeFromLastMouseWheelEvent);
|
||||
zombieRowNodeFromLastMouseWheelEvent = null;
|
||||
}
|
||||
rowNodeFromLastMouseWheelEvent = rowNode;
|
||||
}
|
||||
}
|
||||
|
||||
function handleDragInit(e, dd) {
|
||||
var cell = getCellFromEvent(e);
|
||||
if (!cell || !cellExists(cell.row, cell.cell)) {
|
||||
|
|
@ -2155,6 +2215,12 @@ if (typeof Slick === "undefined") {
|
|||
return; // no editing mode to cancel, allow bubbling and default processing (exit without cancelling the event)
|
||||
}
|
||||
cancelEditAndSetFocus();
|
||||
} else if (e.which == 34) {
|
||||
navigatePageDown();
|
||||
handled = true;
|
||||
} else if (e.which == 33) {
|
||||
navigatePageUp();
|
||||
handled = true;
|
||||
} else if (e.which == 37) {
|
||||
handled = navigateLeft();
|
||||
} else if (e.which == 39) {
|
||||
|
|
@ -2205,7 +2271,8 @@ if (typeof Slick === "undefined") {
|
|||
if (!currentEditor) {
|
||||
// if this click resulted in some cell child node getting focus,
|
||||
// don't steal it back - keyboard events will still bubble up
|
||||
if (e.target != document.activeElement) {
|
||||
// IE9+ seems to default DIVs to tabIndex=0 instead of -1, so check for cell clicks directly.
|
||||
if (e.target != document.activeElement || $(e.target).hasClass("slick-cell")) {
|
||||
setFocus();
|
||||
}
|
||||
}
|
||||
|
|
@ -2223,7 +2290,7 @@ if (typeof Slick === "undefined") {
|
|||
if ((activeCell != cell.cell || activeRow != cell.row) && canCellBeActive(cell.row, cell.cell)) {
|
||||
if (!getEditorLock().isActive() || getEditorLock().commitCurrentEdit()) {
|
||||
scrollRowIntoView(cell.row, false);
|
||||
setActiveCellInternal(getCellNode(cell.row, cell.cell), (cell.row === getDataLength()) || options.autoEdit);
|
||||
setActiveCellInternal(getCellNode(cell.row, cell.cell));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2406,7 +2473,7 @@ if (typeof Slick === "undefined") {
|
|||
}
|
||||
}
|
||||
|
||||
function setActiveCellInternal(newCell, editMode) {
|
||||
function setActiveCellInternal(newCell, opt_editMode) {
|
||||
if (activeCellNode !== null) {
|
||||
makeActiveCellNormal();
|
||||
$(activeCellNode).removeClass("active");
|
||||
|
|
@ -2422,10 +2489,14 @@ if (typeof Slick === "undefined") {
|
|||
activeRow = getRowFromNode(activeCellNode.parentNode);
|
||||
activeCell = activePosX = getCellFromNode(activeCellNode);
|
||||
|
||||
if (opt_editMode == null) {
|
||||
opt_editMode = (activeRow == getDataLength()) || options.autoEdit;
|
||||
}
|
||||
|
||||
$(activeCellNode).addClass("active");
|
||||
$(rowsCache[activeRow].rowNode).addClass("active");
|
||||
|
||||
if (options.editable && editMode && isCellPotentiallyEditable(activeRow, activeCell)) {
|
||||
if (options.editable && opt_editMode && isCellPotentiallyEditable(activeRow, activeCell)) {
|
||||
clearTimeout(h_editorLoader);
|
||||
|
||||
if (options.asyncEditorLoading) {
|
||||
|
|
@ -2447,7 +2518,10 @@ if (typeof Slick === "undefined") {
|
|||
|
||||
function clearTextSelection() {
|
||||
if (document.selection && document.selection.empty) {
|
||||
document.selection.empty();
|
||||
try {
|
||||
//IE fails here if selected element is not in dom
|
||||
document.selection.empty();
|
||||
} catch (e) { }
|
||||
} else if (window.getSelection) {
|
||||
var sel = window.getSelection();
|
||||
if (sel && sel.removeAllRanges) {
|
||||
|
|
@ -2457,13 +2531,14 @@ if (typeof Slick === "undefined") {
|
|||
}
|
||||
|
||||
function isCellPotentiallyEditable(row, cell) {
|
||||
var dataLength = getDataLength();
|
||||
// is the data for this row loaded?
|
||||
if (row < getDataLength() && !getDataItem(row)) {
|
||||
if (row < dataLength && !getDataItem(row)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// are we in the Add New row? can we create new from this cell?
|
||||
if (columns[cell].cannotTriggerInsert && row >= getDataLength()) {
|
||||
if (columns[cell].cannotTriggerInsert && row >= dataLength) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2489,7 +2564,7 @@ if (typeof Slick === "undefined") {
|
|||
if (d) {
|
||||
var column = columns[activeCell];
|
||||
var formatter = getFormatter(activeRow, column);
|
||||
activeCellNode.innerHTML = formatter(activeRow, activeCell, getDataItemValueForColumn(d, column), column, getDataItem(activeRow));
|
||||
activeCellNode.innerHTML = formatter(activeRow, activeCell, getDataItemValueForColumn(d, column), column, d);
|
||||
invalidatePostProcessingResults(activeRow);
|
||||
}
|
||||
}
|
||||
|
|
@ -2680,6 +2755,47 @@ if (typeof Slick === "undefined") {
|
|||
render();
|
||||
}
|
||||
|
||||
function scrollPage(dir) {
|
||||
var deltaRows = dir * numVisibleRows;
|
||||
scrollTo((getRowFromPosition(scrollTop) + deltaRows) * options.rowHeight);
|
||||
render();
|
||||
|
||||
if (options.enableCellNavigation && activeRow != null) {
|
||||
var row = activeRow + deltaRows;
|
||||
var dataLengthIncludingAddNew = getDataLengthIncludingAddNew();
|
||||
if (row >= dataLengthIncludingAddNew) {
|
||||
row = dataLengthIncludingAddNew - 1;
|
||||
}
|
||||
if (row < 0) {
|
||||
row = 0;
|
||||
}
|
||||
|
||||
var cell = 0, prevCell = null;
|
||||
var prevActivePosX = activePosX;
|
||||
while (cell <= activePosX) {
|
||||
if (canCellBeActive(row, cell)) {
|
||||
prevCell = cell;
|
||||
}
|
||||
cell += getColspan(row, cell);
|
||||
}
|
||||
|
||||
if (prevCell !== null) {
|
||||
setActiveCellInternal(getCellNode(row, prevCell));
|
||||
activePosX = prevActivePosX;
|
||||
} else {
|
||||
resetActiveCell();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function navigatePageDown() {
|
||||
scrollPage(1);
|
||||
}
|
||||
|
||||
function navigatePageUp() {
|
||||
scrollPage(-1);
|
||||
}
|
||||
|
||||
function getColspan(row, cell) {
|
||||
var metadata = data.getItemMetadata && data.getItemMetadata(row);
|
||||
if (!metadata || !metadata.columns) {
|
||||
|
|
@ -2770,8 +2886,9 @@ if (typeof Slick === "undefined") {
|
|||
|
||||
function gotoDown(row, cell, posX) {
|
||||
var prevCell;
|
||||
var dataLengthIncludingAddNew = getDataLengthIncludingAddNew();
|
||||
while (true) {
|
||||
if (++row >= getDataLength() + (options.enableAddRow ? 1 : 0)) {
|
||||
if (++row >= dataLengthIncludingAddNew) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -2832,7 +2949,8 @@ if (typeof Slick === "undefined") {
|
|||
}
|
||||
|
||||
var firstFocusableCell = null;
|
||||
while (++row < getDataLength() + (options.enableAddRow ? 1 : 0)) {
|
||||
var dataLengthIncludingAddNew = getDataLengthIncludingAddNew();
|
||||
while (++row < dataLengthIncludingAddNew) {
|
||||
firstFocusableCell = findFirstFocusableCell(row);
|
||||
if (firstFocusableCell !== null) {
|
||||
return {
|
||||
|
|
@ -2847,7 +2965,7 @@ if (typeof Slick === "undefined") {
|
|||
|
||||
function gotoPrev(row, cell, posX) {
|
||||
if (row == null && cell == null) {
|
||||
row = getDataLength() + (options.enableAddRow ? 1 : 0) - 1;
|
||||
row = getDataLengthIncludingAddNew() - 1;
|
||||
cell = posX = columns.length - 1;
|
||||
if (canCellBeActive(row, cell)) {
|
||||
return {
|
||||
|
|
@ -2947,11 +3065,11 @@ if (typeof Slick === "undefined") {
|
|||
if (pos) {
|
||||
var isAddNewRow = (pos.row == getDataLength());
|
||||
scrollCellIntoView(pos.row, pos.cell, !isAddNewRow);
|
||||
setActiveCellInternal(getCellNode(pos.row, pos.cell), isAddNewRow || options.autoEdit);
|
||||
setActiveCellInternal(getCellNode(pos.row, pos.cell));
|
||||
activePosX = pos.posX;
|
||||
return true;
|
||||
} else {
|
||||
setActiveCellInternal(getCellNode(activeRow, activeCell), (activeRow == getDataLength()) || options.autoEdit);
|
||||
setActiveCellInternal(getCellNode(activeRow, activeCell));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -2979,7 +3097,7 @@ if (typeof Slick === "undefined") {
|
|||
}
|
||||
|
||||
function canCellBeActive(row, cell) {
|
||||
if (!options.enableCellNavigation || row >= getDataLength() + (options.enableAddRow ? 1 : 0) ||
|
||||
if (!options.enableCellNavigation || row >= getDataLengthIncludingAddNew() ||
|
||||
row < 0 || cell >= columns.length || cell < 0) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -3064,10 +3182,20 @@ if (typeof Slick === "undefined") {
|
|||
execute: function () {
|
||||
this.editor.applyValue(item, this.serializedValue);
|
||||
updateRow(this.row);
|
||||
trigger(self.onCellChange, {
|
||||
row: activeRow,
|
||||
cell: activeCell,
|
||||
item: item
|
||||
});
|
||||
},
|
||||
undo: function () {
|
||||
this.editor.applyValue(item, this.prevSerializedValue);
|
||||
updateRow(this.row);
|
||||
trigger(self.onCellChange, {
|
||||
row: activeRow,
|
||||
cell: activeCell,
|
||||
item: item
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -3079,11 +3207,6 @@ if (typeof Slick === "undefined") {
|
|||
makeActiveCellNormal();
|
||||
}
|
||||
|
||||
trigger(self.onCellChange, {
|
||||
row: activeRow,
|
||||
cell: activeCell,
|
||||
item: item
|
||||
});
|
||||
} else {
|
||||
var newItem = {};
|
||||
currentEditor.applyValue(newItem, currentEditor.serializeValue());
|
||||
|
|
@ -3094,9 +3217,10 @@ if (typeof Slick === "undefined") {
|
|||
// check whether the lock has been re-acquired by event handlers
|
||||
return !getEditorLock().isActive();
|
||||
} else {
|
||||
// TODO: remove and put in onValidationError handlers in examples
|
||||
// Re-add the CSS class to trigger transitions, if any.
|
||||
$(activeCellNode).removeClass("invalid");
|
||||
$(activeCellNode).width(); // force layout
|
||||
$(activeCellNode).addClass("invalid");
|
||||
$(activeCellNode).stop(true, true).effect("highlight", {color: "red"}, 300);
|
||||
|
||||
trigger(self.onValidationError, {
|
||||
editor: currentEditor,
|
||||
|
|
@ -3232,6 +3356,7 @@ if (typeof Slick === "undefined") {
|
|||
"setSelectionModel": setSelectionModel,
|
||||
"getSelectedRows": getSelectedRows,
|
||||
"setSelectedRows": setSelectedRows,
|
||||
"getContainerNode": getContainerNode,
|
||||
|
||||
"render": render,
|
||||
"invalidate": invalidate,
|
||||
|
|
@ -3269,6 +3394,8 @@ if (typeof Slick === "undefined") {
|
|||
"navigateDown": navigateDown,
|
||||
"navigateLeft": navigateLeft,
|
||||
"navigateRight": navigateRight,
|
||||
"navigatePageUp": navigatePageUp,
|
||||
"navigatePageDown": navigatePageDown,
|
||||
"gotoCell": gotoCell,
|
||||
"getTopPanel": getTopPanel,
|
||||
"setTopPanelVisibility": setTopPanelVisibility,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,9 @@
|
|||
toggleCssClass: "slick-group-toggle",
|
||||
toggleExpandedCssClass: "expanded",
|
||||
toggleCollapsedCssClass: "collapsed",
|
||||
enableExpandCollapse: true
|
||||
enableExpandCollapse: true,
|
||||
groupFormatter: defaultGroupCellFormatter,
|
||||
totalsFormatter: defaultTotalsCellFormatter
|
||||
};
|
||||
|
||||
options = $.extend(true, {}, _defaults, options);
|
||||
|
|
@ -77,6 +79,12 @@
|
|||
function handleGridClick(e, args) {
|
||||
var item = this.getDataItem(args.row);
|
||||
if (item && item instanceof Slick.Group && $(e.target).hasClass(options.toggleCssClass)) {
|
||||
var range = _grid.getRenderedRange();
|
||||
this.getData().setRefreshHints({
|
||||
ignoreDiffsBefore: range.top,
|
||||
ignoreDiffsAfter: range.bottom
|
||||
});
|
||||
|
||||
if (item.collapsed) {
|
||||
this.getData().expandGroup(item.groupingKey);
|
||||
} else {
|
||||
|
|
@ -95,6 +103,12 @@
|
|||
if (activeCell) {
|
||||
var item = this.getDataItem(activeCell.row);
|
||||
if (item && item instanceof Slick.Group) {
|
||||
var range = _grid.getRenderedRange();
|
||||
this.getData().setRefreshHints({
|
||||
ignoreDiffsBefore: range.top,
|
||||
ignoreDiffsAfter: range.bottom
|
||||
});
|
||||
|
||||
if (item.collapsed) {
|
||||
this.getData().expandGroup(item.groupingKey);
|
||||
} else {
|
||||
|
|
@ -116,7 +130,7 @@
|
|||
columns: {
|
||||
0: {
|
||||
colspan: "*",
|
||||
formatter: defaultGroupCellFormatter,
|
||||
formatter: options.groupFormatter,
|
||||
editor: null
|
||||
}
|
||||
}
|
||||
|
|
@ -128,7 +142,7 @@
|
|||
selectable: false,
|
||||
focusable: options.totalsFocusable,
|
||||
cssClasses: options.totalsCssClass,
|
||||
formatter: defaultTotalsCellFormatter,
|
||||
formatter: options.totalsFormatter,
|
||||
editor: null
|
||||
};
|
||||
}
|
||||
|
|
|
|||
173
frappe/public/js/lib/slickgrid/slick.remotemodel.js
vendored
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
(function ($) {
|
||||
/***
|
||||
* A sample AJAX data store implementation.
|
||||
* Right now, it's hooked up to load Hackernews stories, but can
|
||||
* easily be extended to support any JSONP-compatible backend that accepts paging parameters.
|
||||
*/
|
||||
function RemoteModel() {
|
||||
// private
|
||||
var PAGESIZE = 50;
|
||||
var data = {length: 0};
|
||||
var searchstr = "";
|
||||
var sortcol = null;
|
||||
var sortdir = 1;
|
||||
var h_request = null;
|
||||
var req = null; // ajax request
|
||||
|
||||
// events
|
||||
var onDataLoading = new Slick.Event();
|
||||
var onDataLoaded = new Slick.Event();
|
||||
|
||||
|
||||
function init() {
|
||||
}
|
||||
|
||||
|
||||
function isDataLoaded(from, to) {
|
||||
for (var i = from; i <= to; i++) {
|
||||
if (data[i] == undefined || data[i] == null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
function clear() {
|
||||
for (var key in data) {
|
||||
delete data[key];
|
||||
}
|
||||
data.length = 0;
|
||||
}
|
||||
|
||||
|
||||
function ensureData(from, to) {
|
||||
if (req) {
|
||||
req.abort();
|
||||
for (var i = req.fromPage; i <= req.toPage; i++)
|
||||
data[i * PAGESIZE] = undefined;
|
||||
}
|
||||
|
||||
if (from < 0) {
|
||||
from = 0;
|
||||
}
|
||||
|
||||
if (data.length > 0) {
|
||||
to = Math.min(to, data.length - 1);
|
||||
}
|
||||
|
||||
var fromPage = Math.floor(from / PAGESIZE);
|
||||
var toPage = Math.floor(to / PAGESIZE);
|
||||
|
||||
while (data[fromPage * PAGESIZE] !== undefined && fromPage < toPage)
|
||||
fromPage++;
|
||||
|
||||
while (data[toPage * PAGESIZE] !== undefined && fromPage < toPage)
|
||||
toPage--;
|
||||
|
||||
if (fromPage > toPage || ((fromPage == toPage) && data[fromPage * PAGESIZE] !== undefined)) {
|
||||
// TODO: look-ahead
|
||||
onDataLoaded.notify({from: from, to: to});
|
||||
return;
|
||||
}
|
||||
|
||||
var url = "http://api.thriftdb.com/api.hnsearch.com/items/_search?filter[fields][type][]=submission&q=" + searchstr + "&start=" + (fromPage * PAGESIZE) + "&limit=" + (((toPage - fromPage) * PAGESIZE) + PAGESIZE);
|
||||
|
||||
if (sortcol != null) {
|
||||
url += ("&sortby=" + sortcol + ((sortdir > 0) ? "+asc" : "+desc"));
|
||||
}
|
||||
|
||||
if (h_request != null) {
|
||||
clearTimeout(h_request);
|
||||
}
|
||||
|
||||
h_request = setTimeout(function () {
|
||||
for (var i = fromPage; i <= toPage; i++)
|
||||
data[i * PAGESIZE] = null; // null indicates a 'requested but not available yet'
|
||||
|
||||
onDataLoading.notify({from: from, to: to});
|
||||
|
||||
req = $.jsonp({
|
||||
url: url,
|
||||
callbackParameter: "callback",
|
||||
cache: true,
|
||||
success: onSuccess,
|
||||
error: function () {
|
||||
onError(fromPage, toPage)
|
||||
}
|
||||
});
|
||||
req.fromPage = fromPage;
|
||||
req.toPage = toPage;
|
||||
}, 50);
|
||||
}
|
||||
|
||||
|
||||
function onError(fromPage, toPage) {
|
||||
alert("error loading pages " + fromPage + " to " + toPage);
|
||||
}
|
||||
|
||||
function onSuccess(resp) {
|
||||
var from = resp.request.start, to = from + resp.results.length;
|
||||
data.length = Math.min(parseInt(resp.hits),1000); // limitation of the API
|
||||
|
||||
for (var i = 0; i < resp.results.length; i++) {
|
||||
var item = resp.results[i].item;
|
||||
|
||||
// Old IE versions can't parse ISO dates, so change to universally-supported format.
|
||||
item.create_ts = item.create_ts.replace(/^(\d+)-(\d+)-(\d+)T(\d+:\d+:\d+)Z$/, "$2/$3/$1 $4 UTC");
|
||||
item.create_ts = new Date(item.create_ts);
|
||||
|
||||
data[from + i] = item;
|
||||
data[from + i].index = from + i;
|
||||
}
|
||||
|
||||
req = null;
|
||||
|
||||
onDataLoaded.notify({from: from, to: to});
|
||||
}
|
||||
|
||||
|
||||
function reloadData(from, to) {
|
||||
for (var i = from; i <= to; i++)
|
||||
delete data[i];
|
||||
|
||||
ensureData(from, to);
|
||||
}
|
||||
|
||||
|
||||
function setSort(column, dir) {
|
||||
sortcol = column;
|
||||
sortdir = dir;
|
||||
clear();
|
||||
}
|
||||
|
||||
function setSearch(str) {
|
||||
searchstr = str;
|
||||
clear();
|
||||
}
|
||||
|
||||
|
||||
init();
|
||||
|
||||
return {
|
||||
// properties
|
||||
"data": data,
|
||||
|
||||
// methods
|
||||
"clear": clear,
|
||||
"isDataLoaded": isDataLoaded,
|
||||
"ensureData": ensureData,
|
||||
"reloadData": reloadData,
|
||||
"setSort": setSort,
|
||||
"setSearch": setSearch,
|
||||
|
||||
// events
|
||||
"onDataLoading": onDataLoading,
|
||||
"onDataLoaded": onDataLoaded
|
||||
};
|
||||
}
|
||||
|
||||
// Slick.Data.RemoteModel
|
||||
$.extend(true, window, { Slick: { Data: { RemoteModel: RemoteModel }}});
|
||||
})(jQuery);
|
||||