I'm looking for a excel like table for my app then at my search I saw this Handsontable but one also of my requirements is groupings on the table.
Is it possible at Handsontable a ful length row like this?
I'm not sure what you mean by 'full length row' but a couple of options that may help you are:
Rendering custom html
This allows you to manipulate both the headers and cells. Example:
var $container = $("#example2");
$container.handsontable({
colHeaders: function (col) {
switch (col) {
case 0: //First column header
return "<b>Bold</b> and <em>Beautiful</em>";
case 1: //Second column header
var txt = "Some <input type='checkbox' class='checker' ";
txt += isChecked ? 'checked="checked"' : '';
txt += "> checkbox";
return txt;
}
}
});
or
Column stretching
This lets you stretch a column to fill the row to a 'full length row'. Example option to stretch the last column:
stretchH: 'last'
I think what your looking at is merging cells. It exists two different ways to merge cells with HandsonTable.
You can either directly specify the merges you want in the options:
hot = new Handsontable(container, {
data: myData,
rowHeaders: true,
colHeaders: true,
contextMenu: true,
mergeCells: [
{row: 0, col: 0, rowspan: 1, colspan: 4}, // for description
{row: 3, col: 4, rowspan: 2, colspan: 2}, // any other merges
{row: 5, col: 6, rowspan: 3, colspan: 3}
]
});
or create an array with all the merges and give it later to the table:
var mergeArr = new Array();
var descriptionMerge = {
row : 0,
col : 0,
rowspan : 1,
colspan : 4
}
mergeArr.push(descritpionMerge);
hot = new Handsontable(container, {
data: myData,
rowHeaders: true,
colHeaders: true,
contextMenu: true,
mergeCells: mergeArr
});
row: starting row of the merge.
col: starting col of the merge.
rowspan: number of rows that will be merged from the starting row.
colspan: number of cols that will be merged from the starting col.
In your case, you want a full length row, so you need to merge cells in this way :
{row: yourStartingRow, col: yourStartingCol, rowspan: 1, colspan: lengthOfYourTable}
HandsonTable documentation: http://docs.handsontable.com/0.15.1/demo-merge-cells.html
Bonus: If you want to center the text in your merged cells, just use the className : "htMiddle" option.
http://docs.handsontable.com/0.17.0/demo-alignment.html
If you want to group headers, you can used the nested headers to do this:
The code uses the "NestedHeaders" tag like so:
var example1 = document.getElementById('example1');
var hot = new Handsontable(example1, {
data: Handsontable.helper.createSpreadsheetData(5,10),
colHeaders: true,
rowHeaders: true,
nestedHeaders: [
['A', {label: 'B', colspan: 8}, 'C'],
['D', {label: 'E', colspan: 4}, {label: 'F', colspan: 4}, 'G'],
['H', {label: 'I', colspan: 2}, {label: 'J', colspan: 2}, {label: 'K', colspan: 2}, {label: 'L', colspan: 2}, 'M'],
['N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W']
]
});
See more on the handsontable documentation
Related
I am looking for a way to display the numeric value 0 in a dropdown list that also includes placeholder text when the cell is empty. Currently, if 0 is selected the placeholder text shows through. I'm hoping for a built-in option and I'd like to avoid casting the number to string and back if I can (that would tear up my current validation scheme). The following example is modified from the HandsOnTable dropdown docs. The 'Chassis Color' column contains the issue.
jsfiddle:
https://jsfiddle.net/y3pL0vjq/
snippet:
function getCarData() {
return [
["Tesla", 2017, "black", "black"],
["Nissan", 2018, "blue", "blue"],
["Chrysler", 2019, "yellow", "black"],
["Volvo", 2020, "white", "gray"]
];
}
var
container = document.getElementById('example1'),
hot;
hot = new Handsontable(container, {
data: getCarData(),
colHeaders: ['Car', 'Year', 'Chassis color', 'Bumper color'],
columns: [
{},
{type: 'numeric'},
{
type: 'dropdown',
placeholder: "blah",
source: [null, 0, 1, 2, 3]
},
{
type: 'dropdown',
source: ['yellow', 'red', 'orange', 'green', 'blue', 'gray', 'black', 'white']
}
]
});
The best way I found to handle this dropdown list of numbers is to omit the "type" attribute and specify the editor and validator as 'autocomplete. Then make a custom renderer to merge the NumericRenderer functionality with the autocomplete dropdown list.
To finalize the similar look and feel of the native dropdown function, you then add "strict: true" and "filter: false", as explained in the dropdown docs.
Internally, cell {type: "dropdown"} is equivalent to cell {type: "autocomplete", strict: true, filter: false}.
Dropdown Docs
Example:
function getCarData() {
return [
["Tesla", 2017, null, "black"],
["Nissan", 2018, 0, "blue"],
["Chrysler", 2019, 1, "black"],
["Volvo", 2020, 2, "gray"]
];
}
var
container = document.getElementById('example1'),
hot;
function myRenderer(instance, td, row, col, prop, value, cellProperties) {
Handsontable.renderers.NumericRenderer.apply(this, arguments);
td.innerHTML += '<div class="htAutocompleteArrow">▼</div>'
}
hot = new Handsontable(container, {
data: getCarData(),
colHeaders: ['Car', 'Year', 'Chassis color', 'Bumper color'],
columns: [
{},
{type: 'numeric'},
{
editor: 'autocomplete',
validator: 'autocomplete',
renderer: myRenderer,
strict: true,
filter: false,
placeholder: "blah",
source: [null, 0, 1, 2, 3]
},
{
type: 'dropdown',
source: ['yellow', 'red', 'orange', 'green', 'blue', 'gray', 'black', 'white']
}
]
});
trying to figure out dc.js scatter plot and getting hung up on structuring the inital data for it I think
var data = [
{ category: 'A', processVersion: 6},
{ category: 'A', processVersion: 6},
{ category: 'A', processVersion: 8},
{ category: 'A', processVersion: 7},
{ category: 'A', processVersion: 6},
{ category: 'A', processVersion: 7},
{ category: 'A', processVersion: 6},
{ category: 'A', processVersion: 7},
{ category: 'B', processVersion: 6},
{ category: 'B', processVersion: 8},
{ category: 'B', processVersion: 8},
{ category: 'B', processVersion: 7},
{ category: 'B', processVersion: 8}
];
var cf = crossfilter(data);
var dim = cf.dimension(function(d){ return [d.category, d.processVersion]; });
var grp = dim.group();
var scatterChart = dc.scatterPlot("#scatter-chart");
scatterChart
.width(500)
.height(300)
.margins({
top: 10,
right: 20,
bottom: 30,
left: 40
})
.dimension(dim)
.group(grp)
.x(d3.scale.linear().domain[0, 10]) // for each process version
.y(d3.scale.linear().domain[0, 10]) // want count of records where categorys are like
.renderHorizontalGridLines(true)
.renderVerticalGridLines(true)
.symbolSize(30)
.highlightedSize(8)
scatterchart.render();
What I want is to have the y as a count of each record that shares a given category per a given service version(x axis). So I have tried getting a count function into the initial dimesion array, or processing the data before hand which seems unnecessary because I am guessing there is a proper way to do that in crossfilter? the group result should have a key = [5, 3, "A"] I think where [0] is the processVersion, [1] is the count, etc.
Appreciate the assistance.
I am using https://github.com/Mottie/Keyboard to enter inputs in the Handsontable. I call keyboard on 'afterSelectionEnd' on text editor element which has class 'handsontableInput' and it appears just below cell.
When I have single table on page, it works perfectly.
But when there are multiple tables on page, result is different. Here are Steps to reproduce the problem
function keyboard()
{
$('.handsontableInput').keyboard
({
layout: 'custom',
customLayout: {
'default' : [
'a s d f g h j k',
'a s d f g h j k',
'a s d f g h j k'
],
},
})
.getkeyboard().reveal();
}
$(document).ready(function () {
function getData() {
return [
["", "Kia", "Nissan", "Toyota", "Honda"], ["2008", 10, 11, 12, 13], ["2009", 20, 11, 14, 13], ["2010", 30, 15, 12, 13]];
}
var container1 = document.getElementById('example1');
var container2 = document.getElementById('example2');
var hot1 = Handsontable(container1, {
data: getData(),
startRows: 5,
startCols: 5,
minRows: 5,
minCols: 5,
maxRows: 10,
maxCols: 10,
rowHeaders: true,
colHeaders: true,
minSpareRows: 1,
contextMenu: true,
comments: true,
cell: [{
row: 1,
col: 1,
comment: "Test comment"
}, {
row: 2,
col: 2,
comment: "Sample"
}],
afterSelectionEnd : function (instance,col,row,td){
this.getActiveEditor().beginEditing();
keyboard();
},
});
var hot2 = Handsontable(container2, {
data: getData(),
startRows: 5,
startCols: 5,
minRows: 5,
minCols: 5,
maxRows: 10,
maxCols: 10,
rowHeaders: true,
colHeaders: true,
minSpareRows: 1,
contextMenu: true,
comments: true,
cell: [{
row: 1,
col: 1,
comment: "Test comment"
}, {
row: 2,
col: 2,
comment: "Sample"
}],
afterSelectionEnd : function (instance,col,row,td){
this.getActiveEditor().beginEditing();
keyboard();
},
});
})
Please refer jsfiddle http://jsfiddle.net/yd0fucct/5/ to reproduce problem.
I have also posted Issue on Handsontable Github page
Click on the cell of first table, keyboard appears below cell which is good
Click on the cell of second table. Result : keyboard appears in left top of page
Again click in the same cell of second table. Result : Keyboard appears just below cell which is good
Expected behavior : When user clicks on cell of second table first time ( step 2 ), it should appear immediately below it.
Please guide to solve this problem.
When we click the second table first the issue does not occur. It happens only when we click the above table first.
Refer this GitHub issue for solution
var lastInput;
function keyboard() {
var kb,
$input = $(':focus');
if ($input.length) {
lastInput = $input;
// close the last keyboard
kb = lastInput.getkeyboard();
if (kb) {
kb.close(true);
}
if (!$input.hasClass('.ui-keyboard-input')) {
$input.keyboard({
usePreview: false,
initialFocus: false,
layout: 'num'
});
}
$input.getkeyboard().reveal();
}
}
Using the last version of DataTable (1.10.9) and the scroller widget (1.3.0), I can't make it work with this simple piece of code:
var data = [{'a': 'a', 'b': 'b'}, {'a': 'c', 'b': 'd'}];
var columns = [{'title': 'a', 'data': 'a'}, {'title': 'b', 'data': 'b'}];
$("#mytable").DataTable({
"processing" : true,
"filter": false,
"orderClasses": false,
"ordering": false,
data: data,
deferRender: false,
scrollY: 400,
scrollCollapse: true,
scroller: {
loadingIndicator: true
},
dom: "rtiS",
columns: columns,
});
As a result, I have an empty table with message "Showing NaN to -Infinity of 2 entries". WIthout the scroller widget, it is working fine (but I need it).
What did I miss?
I found the reason => I apply DataTable from an ajax response that also insert the table into the DOM.
Calling the JS in a $(document).ready causes the bug.
Using a setTimeout avoids the bug ...
I am trying to build a bar chart where 1st series represent the revenue and the next three represent different kind of expenses. So 1st series to be a single bar and the rest three series as stacked bar. Here is my code for the same.
var s0 = [15, 17, 19, 21];
var s1 = [2, 6, 7, 10];
var s2 = [7, 5, 3, 4];
var s3 = [14, 9, 3, 8];
var ticks = ['May', 'June', 'July', 'August'];
var plot3 = $.jqplot('chart1', [s0, s1, s2, s3], {
stackSeries: true,
animate: true,
seriesDefaults: {
renderer: $.jqplot.BarRenderer,
pointLabels: {
show: true,
},
rendererOptions: {
fillToZero: true,
barMargin: 30,
barWidth: 50,
barPadding: 5,
barDirection: 'vertical'
},
},
series: [
{
disableStack: true,
label: 'Revenue'
},
{label: 'Expense1'}, {label: 'Expense2'}, {label: 'Expense3'}
],
axesDefaults: {
tickRenderer: $.jqplot.CanvasAxisTickRenderer,
tickOptions: {
fontSize: '13pt'
}
},
axes: {
xaxis: {
renderer: $.jqplot.CategoryAxisRenderer,
ticks: ticks
},
yaxis: {
}
},
legend: {
show: true,
location: 'e',
placement: 'outside'
}
});
I have addded disableStack: true for the first series to exclude it from the stack but the chart still considers it as a part of the stack. Here is the output of my code.
Is there a way to fix this ? Thanks.
Yes. It is the order of the series you pass as argument that is not correct.
BEFORE the stacked series
AFTER the single bar series
and not viceversa...
So you have to move the first series as the last argument...
var plot3 = $.jqplot('chart', [s1, s2, s3, s0], {
and then you need to set the disableStack property on 'true' for the last series...
series: [
{label: 'Expense1'}, {label: 'Expense2'}, {label: 'Expense3',label: 'Revenue', disableStack: true}
],
...and you need to adjust the margins, widts and padding of the columns
as you prefer...