Linking two Handsontables - javascript

I'm trying to link two Handsontables so that the second table shows additional details for the current column in the first table. The number in the column header of the first table would be used to find the corresponding row in the second table.
Clicking on any cell in the first table should cause the corresponding row in the second table to be highlighted.
Clicking in the second table should highlight that row and move the cursor in the first table to the corresponding column.
Here's the HTML:
<div id="main" class="handsontable"></div>
<p>
<div id="index" class="handsontable"></div>
And here's the Javascript to display the tables:
$(document).ready(function () {
function getMainData() {
return [["2008", 10, 11, 12, 13], ["2009", 20, 11, 14, 13], ["2010", 30, 15, 12, 13]];
}
function getMainHeaders() {
return ["Year", 1, 2, 3, 4];
}
function getIndexData() {
return [[1, "Kia", "Korea"], [2, "Nissan", "Japan"], [3, "Toyota", "Japan"], [4, "Honda", "Japan"]];
}
function getIndexHeaders() {
return ["#", "Make", "Country"];
}
$("#main").handsontable({
data: getMainData(),
colHeaders: getMainHeaders(),
fillHandle: false,
readOnly: true
});
$("#index").handsontable({
data: getIndexData(),
colHeaders: getIndexHeaders(),
fillHandle: false,
readOnly: true
});
});
All I need is the code to link the tables! I've gone around in circles trying to make this work, but no joy.
I've got all of the above in a fiddle.
Thanks in advance for any help or suggestions.

I managed to do what you asked about (fiddle). I added this code after the initiation of the tables:
var sync = function(tab1, tab2) {
var syncSelection = function(row, col, rowEnd, colEnd) {
var sel1 = tab1.getSelected();
var sel2 = tab2.getSelected();
if (!sel2) {
tab2.selectCell(row, col, rowEnd, colEnd);
return;
}
for (var key in sel1) {
if (sel1[key] !== sel2[key]) {
tab2.selectCell(row, col, rowEnd, colEnd);
return;
}
}
};
// syncs while selecting (does not work for selecting one cell)
tab1.addHook('afterSelection', syncSelection);
// needed to sync selection of one cell
tab1.addHook('afterSelectionEnd', syncSelection);
};
var mainTable = $('#main').handsontable('getInstance');
var indexTable = $('#index').handsontable('getInstance');
sync(mainTable, indexTable);
sync(indexTable, mainTable);

Related

Select2 and Jexcel add new option to dropdown

I have this code of Jexel with Select2 where I load the default values for each jexcel row from an array and use select2 for the dropdown:
https://jsfiddle.net/ktumw528/
However I wish to know how can I populate the options from select2 with the values from var data?
Also how can I add new country to the select2 dropdown if not found when typing.
var data = [
['Spain'],
['France'],
['Germany'],
];
var customDropDown1 = {
// Methods
closeEditor : function(cell, save) {
// Get value
var txt = $(cell).find('.editor').val();
// Set visual value
$(cell).html(txt);
// Close edition
$(cell).removeClass('edition');
// Save history
return txt;
},
openEditor : function(cell) {
// Get current content
var currentValue = $(cell).text();
// Create the editor
var editor = document.createElement('select');
$(cell).html(editor);
$(editor).prop('class', 'editor');
$(editor).html('<option>Brazil</option><option>Canada</option>')
$(editor).val(currentValue);
// Create the instance of the plugin
$(editor).select2().on('select2-blur', function() {
$('#' + $.fn.jexcel.current).jexcel('closeEditor', $(cell), true);
});
},
getValue : function(cell) {
return $(cell).text();
},
setValue : function(cell, value) {
$(cell).html(value);
return true;
}
}
$('#my').jexcel({
data:data,
columns: [ { editor:customDropDown1 } ],
colHeaders: ['Country'],
colWidths: [ 300 ]
});
Any tips are welcomed :) thanks a lot!
I think you can use last version of JExcel (v4). You will have more options and more option editor.
With this new version, you can create editor with set custom value. And you have an option for dropdown for add new item
https://bossanova.uk/jexcel/v4/examples/dropdown-and-autocomplete
and this documentation : https://bossanova.uk/jsuites/dropdown-and-autocomplete/new-options
Example :
<script>
var data5 = [
[1, 'Beatles'],
[2, 'Beatles'],
[3, 'Beatles'],
[4, 'Beatles'],
];
jexcel(document.getElementById('spreadsheet5'), {
data: data5,
columns: [
{
type: 'dropdown',
title: 'Name',
width: '300px',
source: [
{ id:'1', name:'Paul' },
{ id:'2', name:'Ringo' },
{ id:'3', name:'George' },
{ id:'4', name:'John' },
],
options: { newOptions: true } // Option for add new options
},
{
type:'dropdown',
title:'Band',
width:'200px',
source: ['Beatles'],
},
],
});
<script>
otherwise if you want keep v2, i suggest use external source on var, and add new item on this variable. Because the editor is created only on open cell.

Javascript Datatable limit amount of characters shown in a cell

I am creating a DataTable in Javascript, which has the following properties:
var dtable = $('.ssdatatable').DataTable({
"lengthMenu": [[10, 25, 50, 100, 500], [10, 25, 50, 100, 500]],
"bProcessing": true,
"sDom": "TBflrtip",
"bServerSide": true,
"sAjaxSource": ajSource,
"iDisplayLength": 25,
"bJqueryUI": false,
"bAutoWidth": false,
//"bAutoLength": false,
//"bLengthChange": false,
"recordsFiltered": 0,
"sPaginationType": "full_numbers",
"bPaginate": true,
"sServerMethod": "POST",
"responsive": true,
"fixedHeader": true,
"buttons": [
'copy', 'excel', 'pdf'
],
"aoColumns": [
//columns
]
});
One of the particular columns is a Description, which has a LOT of text in it. The width of columns is fixed, however because of that, the height of my rows are blowing out of proportions, making page x10 of its intended size.
My question is: is there anything I can add inside the properties to make it show only N characters, and by hitting limit it would be something like:
|text textte...|
| Show More|
(I tried commented out options, did do me any good)
Or would I need to use some method or modify css?
Had the same problem - only I wanted to show all the text when the table is exported and thus only limit the text, when displayed. So based on this blog https://datatables.net/blog/2016-02-26, I further developed the code in order to allow the whole text to be shown when the table is exported.
In order to do so, I altered the code so text > 50 char is not removed, but instead wrapped in a span which is then hidden from CSS.
The function code looks like this:
function(data, type, row) {
if (type === 'display' && data != null) {
data = data.replace(/<(?:.|\\n)*?>/gm, '');
if(data.length > 50) {
return '<span class=\"show-ellipsis\">' + data.substr(0, 50) + '</span><span class=\"no-show\">' + data.substr(50) + '</span>';
} else {
return data;
}
} else {
return data;
}
}
Then from the CSS file you can add:
span.no-show{
display: none;
}
span.show-ellipsis:after{
content: "...";
}
given data:
var mydt = [{ a: 1, b: 2, c: 3, d: 4 }, { a: 5, b: 6, c: 7, d: 8 }, { a: 10, b: 12, c: 13, d: 14 }];
$("#tbl2").DataTable({
columnDefs: [{ targets:[0] }],
data: mydt, columns: [{ data: "a" }, { data: "b" }, { data: "c" }, { data: "d" }],
createdRow: function (row, data, c, d) {
// so for each row, I am pulling out the 2nd td
// and adding a title attribute from the
// data object associated with the row.
$(row).children(":nth-child(2)").attr("title", data.b)
},
and the rest
here is a working one in jfiddle https://jsfiddle.net/bindrid/wbpn7z57/7/ note that this one has data in a different format but it works (on the first name column)
// DataTable created the createRow hook to allow the row html to be updated after it was created.
-- row is the current row being created
-- data is the data object associated with the row.
createdRow: function (row, data, c, d) {
$(row) gets the tr in a jQuery object
$(row).children() gets all of the td's in the row
(":nth-child(2)") gets the 2nd td in the row. Note, this is 1 based value,not 0 based.
.attr is the jquery command that adds the "title" attribute to the td.
the "title" is missed name but too late now.
data.b matches the data structured used to populate the table.
The actual structure of this data structure is dependent on your data source so you would actually have to check it.
Hope this helps :)
In the below example code block:
Whereas "Targets": 2 indicates column index, "data":"description" points out column name that wanted to be manipulated. When we look at the render function, description column is limited to 100 characters length.
var dtable = $('.ssdatatable').DataTable({
"lengthMenu": [[10, 25, 50, 100, 500], [10, 25, 50, 100, 500]],
"bProcessing": true,
"sDom": "TBflrtip",
"bServerSide": true,
"sAjaxSource": ajSource,
"iDisplayLength": 25,
"bJqueryUI": false,
.....
{
"targets": 2,
"data":"description",
render: function(data, type, row, meta) {
if (type === 'display') {
data = typeof data === 'string' && data.length > 100 ? data.substring(0, 100) + '...' : data;
}
return data;
}
},
});

State Saving with individual column filtering

I am using individual column filtering in data table along with stateSave: true. To perform column filtering I am using column filter.js.
I am facing one issue If I filtered data in the column and reload the page it maintains state for table only but textbox becomes empty.
On page refresh, the state remains same for the table and for searching textbox too.
On page refresh, the textbox value should be shown, but instead of that, text box becomes empty.
Please, someone, let me know how can I maintain textbox value along with table state.
I am using this code
jQuery('#Gridtable').dataTable({
stateSave: true,
"aLengthMenu": [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, "All"]],
"iDisplayLength": 10,
}).columnFilter({
sPlaceHolder: "head:after",
aoColumns: [
{ type: "text" },
{ type: "text" },
{ type: "text" },
]
});
"stateLoaded": function stateLoadedCallback(settings, state) {
state.columns.forEach(function (column, index) {
$('#' + settings.sTableId + '-head-filter-' + index).val(column.search.search);
});
}
Just put values from your state into the fields
If you use stateSave=true DataTables option you can load it this way (in footer in my case):
stateSave: true,
stateLoadParams: function(settings, data) {
for (i = 0; i < data.columns["length"]; i++) {
let col_search_val = data.columns[i].search.search;
if (col_search_val !== "") {
$("input", $("#your-id-of-table tfoot th")[i]).val(col_search_val);
}
}
}
Cheers!
Just in case someone stumbles across this post after two years... this should be the solution to the described issue.

handsontable - custom html button at the start of every row with action on click

I have handsontable where I have added a custom button in 2nd column, on click of that I want to send the data of that row to server for processing.
so I have written a onClick function for the button. But how to pass the row index of current row to this function is something I am not able to find out.
var data = [
['', 'Kia', 'Nissan', 'Toyota', 'Honda'],
['<button onClick="edit(this)">Actual</button>', 5, 10, 12, 13],
['<button>2015</button>', 15, -11, 14, 13],
['<button>2016</button>', 20, 15, -12, 'readOnly']
],
columns: [{renderer: "html"}, {type: "text"}, {type: "text"}, {type: "text"}],
Please refer below fiddle to see the code.
http://jsfiddle.net/8cx5a3by/1/
You can use hot.getSelected(). The response is an array of 4 values. The first is the row index, the second is the column index. You could use those in your edit function. Just call on hot.getSelected() and it should give you the index assuming the click of the button doesn't stop handsontable from selecting that cell.

Creating Dynamic Pie Charts using ASP.NET

Gthompson83 gave me a great suggestion in using jqPlot, but here is my issue now...
I have the following javascript code on my page (the current data is just filler):
function CreatePie(div) {
var data = [
['Heavy Industry', 12], ['Retail', 9], ['Light Industry', 14],
['Out of home', 16], ['Commuting', 7], ['Orientation', 9]
];
var plot2 = jQuery.jqplot(div, [data],
{
seriesDefaults: {
renderer: jQuery.jqplot.PieRenderer,
rendererOptions: {
// Turn off filling of slices.
fill: false,
showDataLabels: true,
// Add a margin to seperate the slices.
sliceMargin: 4,
// stroke the slices with a little thicker line.
lineWidth: 5
}
},
legend: { show: true, location: 'e' }
}
);
}
I call the function from the asp.net code-behind page as a startup script, like so.:
string script = string.Format("CreatePie('{0}')", "chartDiv" + k,);
ClientScript.RegisterStartupScript(GetType(), "pieChart"+k,
"<script>" + script + "</script>");
The one argument passed is the div into which the chart will be placed. Now how do I pass the data variables so they can be placed in the data = [ [var1, value1], [var2, value2]...] portion of the Javascript code?
Try using jqPlot. It's javascript based solution. Use asp.net to output the data for the javascript variable.

Categories

Resources