Import from CSV into HandsOnTable and Export to CSV from HandsOnTable - handsontable

I am using http://handsontable.com/ as one of the widgets for showing prices for my project, I could not find export and import from CSV feature in their API or FAQ.
Has anyone implemented or know about it ?

Yup, that comment links you to the explanation on how to do it, and here is my implementation of it for anyone that wants to just reuse code. There are a few enhancements beyond the basic CSV exporting like the escaping of spaces and special characters, as well as apostrophes. It also sets the column headers if they exist so remove that line if you don't have column headers.
The relevant code assuming you have a button with id=export-csv:
function parseRow(infoArray, index, csvContent) {
var sizeData = _.size(hot1.getData());
if (index < sizeData - 1) {
dataString = "";
_.each(infoArray, function(col, i) {
dataString += _.contains(col, ",") ? "\"" + col + "\"" : col;
dataString += i < _.size(infoArray) - 1 ? "," : "";
})
csvContent += index < sizeData - 2 ? dataString + "\n" : dataString;
}
return csvContent;
}
/**
* Export to CSV button
*/
var exportCsv = $("#export-csv")[0];
if (exportCsv) {
Handsontable.Dom.addEvent(exportCsv, "mouseup", function(e) {
exportCsv.blur(); // jquery ui hackfix
var csvContent = "data:text/csv;charset=utf-8,";
csvContent = parseRow(colHeaders, 0, csvContent); // comment this out to remove column headers
_.each(hot1.getData(), function(infoArray, index) {
csvContent = parseRow(infoArray, index, csvContent);
});
var encodedUri = encodeURI(csvContent);
var link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", $("h1").text() + ".csv");
link.click();
})
}
Hope it helps!

Related

ImportXML "post_name" from an article, having trouble finding proper XPath

I've been having trouble finding the proper or accurate Xpath for google sheets ImportXML.
Article in question:
https://www.digitaltrends.com/news/this-is-what-a-birthday-party-on-the-iss-looks-like/
Result i'm looking for:
'post_name': 'this-is-what-a-birthday-party-on-the-iss-looks-like'
Using the "copy full XPath feature in Chrome Inspect feature, i'm getting:
/html/head/script[43]/text()
Which does not work with Google Sheet's ImportXML feature. Can someone guide me through how will i be able to pull this section of the site?
EDIT: I'm trying to retrieve anything within these parameters such as "post name, post title, post id." [View Source1
The page is built in javascript on the client side, not the server side. It is therefore impossible to retrieve information with the IMPORTXML function. You need to read what is included in the script ...
function extract(){
var url='https://www.digitaltrends.com/news/this-is-what-a-birthday-party-on-the-iss-looks-like/'
var source = UrlFetchApp.fetch(url).getContentText()
var data = source.split('<script>')
//Logger.log(data[3])
info = "'post_name" + data[3].split('post_name')[1].split(',')[0]
Logger.log(info)
}
Now if you want to retrieve all the information contained in the JSON
function extract(){
var url='https://www.digitaltrends.com/news/this-is-what-a-birthday-party-on-the-iss-looks-like/'
var source = UrlFetchApp.fetch(url).getContentText()
var data = source.split('<script>')
//Logger.log(data[3])
info = data[3].replace(/(\t)/gm,"").replace(/(\n)/gm,"").replace(/(')/gm,"\"").replace(/(: )/gm,":")
info = info.split('({')[1].split(',});}')[0]
//Logger.log(info)
var myData = JSON.parse('{' + info + '}')
getPairs(eval(myData),'myData')
}
function getPairs(obj,id) {
const regex = new RegExp('[^0-9]+');
const fullPath = true
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet()
for (let p in obj) {
var newid = (regex.test(p)) ? id + '.' + p : id + '[' + p + ']';
if (obj[p]!=null){
if (typeof obj[p] != 'object' && typeof obj[p] != 'function'){
sheet.appendRow([fullPath?newid:p, obj[p]]);
}
if (typeof obj[p] == 'object') {
getPairs( obj[p], newid );
}
}
}
}

is my if statement doing what i think its doing?

Here I have tis function that is querying data and returning it to me and im putting that data in to html elements to make a post.my if statement at the bottom is where im having a bit of problem i trying to only apply my comment window once to the new clones once they have been pushed over to the new div called story board, i believe im telling my if statement that if the class already exists in that new clone then do nothing else apply it there.. to seee what i am talking about...here is my test domain...http://subdomain.jason-c.com/
sign in is "kio" pass is the same and when you hit publish on the stories, everytime a nw one hits it will apply comment box to a post in the storyboard window that already has a comment text area. what am i doing wrong.
function publishWindowHandler(){
var query = new Parse.Query('Post');
console.log(currentUser);
query.equalTo("User", currentUser);
query.include("User");
query.descending("createdAt")
console.log(user.get('username'));
query.find({
success:function(results){
document.getElementById("publishCenter").textContent = "";
for(var i =0; i < results.length; i++){
var userPost = results[i];
//console.log(userPost.get("User") + " / " + userPost.get("Author") + " / " + userPost.get("Story") + " / " + userPost.get("objectId"));
var authorTitle = document.createElement("p");
var newPost = document.createElement("P");
var title = document.createElement("P");
var userLabel = document.createElement("p");
var postId = userPost.id;
var postBtn = document.createElement("INPUT");
postBtn.className ="publishBtn";
postBtn.id ="publishBtn";
postBtn.setAttribute("Type", "button");
postBtn.setAttribute("value", "Publish");
title.textContent = "Story: " + userPost.get("Title");
authorTitle.textContent = "Author: " + userPost.get("Author");
newPost.textContent = userPost.get("Story");
userLabel.textContent = "Published by: " +userPost.get("User").get ("username");
var postWrapper = document.createElement("DIV");
postWrapper.className = "postWrapper";
postWrapper.id = postId;
document.getElementById("publishCenter").appendChild(postWrapper);
postWrapper.appendChild(title);
postWrapper.appendChild(authorTitle);
postWrapper.appendChild(newPost);
postWrapper.appendChild(userLabel);
postWrapper.appendChild(postBtn);
postBtn.addEventListener("click", publicViewHandler);
function publicViewHandler(){
$(this).parent(".postWrapper").clone().appendTo(".storyBoard");
function testWindow(){
if($(publicBoard).children().hasClass(".commentWindow")){
}
else
{
$(".storyBoard").children().append(commentWindow);
}
}
testWindow();
}
}
}
})
}
According to the documentation, jquery hasClass doesn't need '.' prefixing the passed in class name.
https://api.jquery.com/hasclass/
Try removing that and see if that get's you anywhere.
Also, where is the variable commentWindow defined? Is it global?
var myClone = $(this).parent().clone(true);
myClone.appendTo(".storyBoard");
console.log(publicBoard);
console.log("hello",$(this));
console.log($(publicBoard).find('.postWrapper').find("commentWindow"));
myClone.append($(commentWindow).clone());
this is what i ended up doing to solve my issue took me a while and a little help from a friend.

Add Column Sort Index To Column Headers For Multi Column Sort

Is there anyway through a header template or anything else to put index markers into the column headers? For example if I have a grid with a bunch a columns and the user clicks on the "Name" column and then the "City" column.
I would like to put a "1" next to "Name" and a "2" next to "City" to indicate the sort order.
When using Headertemplates, there is an issue with not being able to capture the event for "just before column headers are rendered." I have the following dataBinding event that still does what you want :
dataBinding: function(e){
var sortArray = $("#grid").data("kendoGrid").dataSource.sort();
if(sortArray)
{
for(var i = 0;i < sortArray.length; i++)
{
$("#grid th[data-field=" + sortArray[i].field + "] .k-link").html("(" + (i+1) + ")" + sortArray[i].field );
}
var sortedColumns = sortArray.map(function(o){return o.field});
var columns = $("#grid").data("kendoGrid").columns;
for (i in columns)
{
if(sortedColumns.indexOf(columns[i].field) == -1)
$("#grid th[data-field=" + columns[i].field + "] .k-link").html(columns[i].field );
}
}
}
The following is the Kendo dojo link : http://dojo.telerik.com/eneH/4
A simpler solution, similar to above
$('.field_sort_number').remove();
var sort_v = gridDataSource.sort();
if (sort_v)
for (i = 0; i < sort_v.length; ++i) {
$('th[data-field="' + sort_v[i].field + '"] a[class="k-link"]').append('<sub class="field_sort_number">' + (i + 1) + '</sub>');
}

Footable fine filtering

I have this code to have a select field filter through a Footable. It works but it's straining more results than needed. Example: "Article in National Journal" option is filtering rows with both "Article in National Journal" and "Article in International Journal". How can I make it more precise? Thank you.
jQuery(function () {
jQuery('#projectos').footable().bind('footable_filtering', function (e) {
var selected = jQuery('.filter-status').find(':selected').text();
if (selected && selected.length > 0) {
e.filter += (e.filter && e.filter.length > 0) ? ' ' + selected : selected;
e.clear = !e.filter;
}
});
jQuery('.clear-filter').click(function (e) {
e.preventDefault();
jQuery('.filter-status').val('');
jQuery('#projectos').trigger('footable_clear_filter');
});
jQuery('.filter-status').change(function (e) {
e.preventDefault();
jQuery('#projectos').trigger('footable_filter', {filter: jQuery('#filter').val()});
});
});
When Footable filters, it uses the entire text from the whole row and it uses indexof() to test. You can see this in footable.filter.js in the filterFunction function.
I had to do 3 things to solve the problem.
Replace window.footable.options.filter.filterFunction with my own function
Do a per column match instead of the whole row. Depending on the HTML in your row, the spaces between the columns could be lost causing the first word of a column to concatenate with the last word of the previous column.
Use a regex match instead of indexof(). This allows you to match a whole word. As an example, if you us indexof() for "be" in "Don't be evil, because that's not good" will return 6 and 15 even though 15 is the beginning of a completely different word.
Here's the function: (I'm sure there are loads of improvements. Feel free to edit...)
window.footable.options.filter.filterFunction = function(index) {
var $t = $(this),
$table = $t.parents('table:first'),
filter = $table.data('current-filter').toUpperCase(),
columns = $t.find('td');
var regEx = new RegExp("\\b" + filter + "\\b");
var result = false;
for (i = 0; i < columns.length; i++) {
var text = $(columns[i]).text();
result = regEx.test(text.toUpperCase());
if (result === true)
break;
if (!$table.data('filter-text-only')) {
text = $(columns[i]).data("value");
if (text)
result = regEx.test(text.toString().toUpperCase());
}
if (result === true)
break;
}
return result;
};
You can find a plunk here: http://plnkr.co/edit/P2DWDtyHP3xmoUIcvgDe

Applying rules in Telerik MVC Grid Filter

I'm using Telerik MVC Grid, and need to apply filter rules below, but it seems only apply to the first two column, and ignore all the rest of the columns.
Here JS Code : ( assume grid is $("#grid").data("tgrid") )
function extTelerikGridFilter(grid, value) {
if (!$.isArray(grid.columns)) throw "Error : First Parameter accept only array.";
var colLength = grid.columns.length - 1;
var filterText = "";
var tempArr = new Array();
for (var i = 0; i < grid.columns.length; i++) {
filterText = filterText + "substringof({0},'{1}')".replace("{0}", grid.columns[i].member).replace("{1}", value);
if (colLength > 0) {
filterText = filterText + "~or~";
colLength = colLength - 1;
}
}
console.log(filterText);
grid.filter(filterText);
}
Result of console.log(filterText) :
substringof(Doc_No,'Opriyandi')~or~substringof(Type,'Opriyandi')~or~substringof(Request_By,'Opriyandi')~or~substringof(Request_Date,'Opriyandi')~or~substringof(Department,'Opriyandi')~or~substringof(Plant,'Opriyandi')~or~substringof(Description,'Opriyandi')~or~substringof(IT_Support,'Opriyandi')~or~substringof(Status,'Opriyandi')
Look before and after applying the filters in attachment.
Is this some kind of bug or perhaps i did something wrong.. Thank You.
*Using Telerik MVC 2011.3.1229
*Please ask me if you need additional information regarding my issue. :)
Attachment :
- BeforeApplyingFilter.png
- AfterApplyingFilter
I had this problem too. After some experiments, I found that we should bracket every expression starting from the head.
So, your filter string would look like this:
(((((((((substringof(Doc_No,'Opriyandi'))~or~substringof(Type,'Opriyandi'))~or~substringof(Request_By,'Opriyandi'))~or~substringof(Request_Date,'Opriyandi'))~or~substringof(Department,'Opriyandi'))~or~substringof(Plant,'Opriyandi'))~or~substringof(Description,'Opriyandi'))~or~substringof(IT_Support,'Opriyandi'))~or~substringof(Status,'Opriyandi'))
You can modify your code:
..
for (var i = 0; i < grid.columns.length; i++) {
--> filterText = "(" + filterText + "substringof({0},'{1}')".replace("{0}", grid.columns[i].member).replace("{1}", value) + ")"; <--
if (colLength > 0) {
filterText = filterText + "~or~";
colLength = colLength - 1;
}
..
PS I'm using 2011.3.1306
PS2 I wrote the article about custom filtering - please see link.

Resources