Wrap text on custom headers in handsontable - handsontable

Is there a way to auto wrap text on colHeaders when given colWidths? It doesn't seem to work and even manually reducing the size of the columns is prohibited.
Relevant options:
hot = new Handsontable(container, {
data: items,
startRows: 1,
minSpareRows: 1,
colHeaders: ['aaaaaaaa', 'bbbbbbb', 'cccccccccccc'],
colWidths: [50,50,50]
manualColumnResize: true,
autoWrapRow: true
}

Maybe try add some CSS into your headers:
.handsontable table thead th {
white-space: pre-line;
max-width: /* enter here your max header width */
}

Try the following CSS:
.handsontable th {
white-space: normal!important;
}
Demo and source: http://jsfiddle.net/cyancscoutrfp/hqLbg3rt/

Related

How to Show 30 days in Day View with Horizontal Scrollbar in Dhtmlx Scheduler?

I want to show 30 days in Day View Scheduler with Horizontal Scrollbar. Currently, Horizontal Scrollbar is available only for Timeline View but I want it for Day View as well as Month View.
For Timeline View with Horizontal Scrollbar code:
scheduler.createTimelineView({
name: "timeline",
x_unit: "minute",
x_date: "%H:%i",
x_step: 30,
x_size: 24*7,
x_start: 16,
x_length: 48,
y_unit: sections,
y_property: "section_id",
render: "bar",
scrollable: true,
column_width: 70,
scroll_position:new Date(2018, 0, 15) });
Please share your ideas and Sample links
Thanks in Advance
Try using Custom View. You can remove the default Day view and display your own instead, with the number of days you want to display. This can be done like this:
First in scheduler.config.header set tab "thirty_days" instead of "day":
scheduler.config.header = [
"thirty_days",
"week",
"month",
"date",
"prev",
"today",
"next"
];
The label for the view is set as in:
scheduler.locale.labels.thirty_days_tab = "Days";
Next, set the start date of the viewing interval, as well as viewing templates. It's better to create the custom view in the onTemplatesReady event handler function so that your custom view templates are ready before the scheduler is initialized:
scheduler.attachEvent("onTemplatesReady", () => {
scheduler.date.thirty_days_start = function(date) {
const ndate = new Date(date.valueOf());
ndate.setDate(Math.floor(date.getDate()/10)*10+1);
return this.date_part(ndate);
}
scheduler.date.add_thirty_days = function(date,inc) {
return scheduler.date.add(date,inc*30,"day");
}
const format = scheduler.date.date_to_str(scheduler.config.month_day);
scheduler.templates.thirty_days_date = scheduler.templates.week_date;
scheduler.templates.thirty_days_scale_date = function(date) {
return format(date);
};
});
To add horizontal scrolling to the view, you can place the scheduler inside the scrollable element and give the scheduler the width required to display all columns. You'll need to hide a default navigation panel of the scheduler and create a custom one with HTML, so it would have a correct width and won't be affected by scrolling:
scheduler.xy.nav_height = 0;
scheduler.attachEvent("onSchedulerReady", function () {
const navBar = scheduler.$container.querySelector(".dhx_cal_navline").cloneNode(true);
navBar.style.width = "100%";
document.querySelector(".custom-scheduler-header").appendChild(navBar);
document.querySelectorAll(".custom-scheduler-header .dhx_cal_tab").forEach(function (tab) {
tab.onclick = function () {
const name = tab.getAttribute("name");
const view = name.substr(0, name.length - 4);
scheduler.setCurrentView(null, view);
};
});
document.querySelector(".custom-scheduler-header .dhx_cal_prev_button").onclick = function () {
const state = scheduler.getState();
scheduler.setCurrentView(scheduler.date.add(state.date, -1, state.mode));
};
document.querySelector(".custom-scheduler-header .dhx_cal_next_button").onclick = function () {
const state = scheduler.getState();
scheduler.setCurrentView(scheduler.date.add(state.date, 1, state.mode));
};
document.querySelector(".custom-scheduler-header .dhx_cal_today_button").onclick = function () {
scheduler.setCurrentView(new Date());
};
scheduler.attachEvent("onBeforeViewChange", (oldView, oldDate, newView, newDate) => {
const innerContainer = document.getElementById("scheduler_here");
if (newView === "thirty_days") {
innerContainer.style.width = "3000px";
} else {
innerContainer.style.width = "100%";
}
return true;
});
scheduler.attachEvent("onViewChange", function (view, date) {
const dateLabel = document.querySelector(".custom-scheduler-header .dhx_cal_date");
const state = scheduler.getState();
dateLabel.innerHTML = scheduler.templates[view + "_date"](state.min_date, state.max_date);
document.querySelectorAll(".custom-scheduler-header .dhx_cal_tab").forEach(function(tab) {
tab.classList.remove("active");
});
const activeTab = document.querySelector(".custom-scheduler-header ." + view + "_tab");
if (activeTab) {
activeTab.classList.add("active");
}
});
});
Styles that you will need:
.custom-scheduler-header .dhx_cal_navline{
display: block !important;
height: 60px !important;
}
.custom-scheduler-header .dhx_cal_navline.dhx_cal_navline_flex{
display: flex !important;
}
.dhx-scheduler {
height: 100vh;
width: 100vw;
position: relative;
overflow: hidden;
background-color: #fff;
font-family: Roboto, Arial;
font-size: 14px;
}
.dhx_cal_container .dhx_cal_navline {
display: none;
}
Please see an example: https://snippet.dhtmlx.com/znd7ffiv
You may need to fix the hour scale so that it remains visible when scrolling horizontally on the calendar. I did not implement this in the example, I think that this can be done in the same way as for the navigation panel. If you need, write to me and I will send an update in a few working days.
As for the "Month" view, the approach is the same as for the "Day" view.

c3.js - hide tooltip for specific data sets

I have a c3.js chart which has 4 datasets. Is it possible to set the tooltop only to display for 1 set of data?
From the code below I only want the tooltip to display for data4.
var chart = c3.generate({
bindto: '#chart3',
data: {
//x: 'x1',
xFormat: '%d/%m/%Y %H:%M', // how the date is parsed
xs: {
'data1': 'x1',
'data2': 'x2',
'data3': 'x3',
'data4': 'x4'
},
columns: [
x1data,
y1data,
x2data,
y2data,
x3data,
y3data,
x4data,
y4data,
],
types: {
data1: 'area',
},
},
legend: {
show: false
}
});
There is the tooltip option for show:false but that disables them all.
Can it display for just 1 dataset?
The tooltip.position() function can be used to control the position of the tooltip, and we can set the tooltip position way off the canvas as a quick hack to hide it when we do not want to see it. However, I do not know how to return the default which is not documented - maybe someone else can elaborate on that.
tooltip: {
grouped: false,
position: (data, width, height, element) => {
if (data[0].id === 'data2'){ // <- change this value to suit your needs
return { top: 40, left: 0 };
}
return { top: -1000, left: 0 };
}
}
EDIT: After digging around for a solution I found that Billboard.js (a fork of C3.js on github) provides a tooltip.onshow() function that the API docs say is 'a callback that will be invoked before the tooltip is shown'. So it would appear that Billboard.js already has the a potential solution where you could intercept the data and hide the tooltip.

jqGrid grouping rows overriding "spacer" columns that I build into my grid

When I add grouping to a grid it works great other then one problem. The row which contains the grouping information is being built with a colspan for the "width" of the grid and this means it sits on top of some of the vertical columns I build into the grid to help add visual separation.
Is there a way to have this row not skip that column so I can keep a nice visual break between sections in my grid?
Update:
I add these vertical "spacers" columns by the following method procedure:
-in the jqGrid setup
beforeProcessing: function (data, status, xhr) {
//add the spaces to the returned data to allow for the blank vertical columns in the grid
for (var x = 0, length = data.rows.length; x < length; x++) {
data.rows[x].cell.splice(6, 0, "");
} //for
}, //beforeProcessing
-colmodel setup matching the cells that will contain the "space"
{ name: "empty1" ,width: 10, sortable: false, hidedlg: true, search: false, resizable: false, fixed: true, classes: 'NoHorizontalGridBorders' },
-css
.NoHorizontalGridBorders { border-bottom-color: transparent !important; background-color: White !important;}
If I understand correctly what you need you have to modify grouping lines inside of loadComplete. For example the following demo, which is modification of the demo from the answer, display the following grid
The code is very simple:
loadComplete: function () {
var $groupingHeaders = $(this).find(">tbody>tr.jqgroup");
$groupingHeaders.find(">td").addClass("noVerticalLines").attr("colspan", "1");
$groupingHeaders.append("<td class='noHorizLines noVerticalLines'> </td>" +
"<td colspan='3' class='noVerticalLines'> </td>" +
"<td class='noHorizLines noVerticalLines'> </td>" +
"<td colspan='2'> </td>");
}
where CSS on the classes noHorizLines and noVerticalLines defined as
.ui-jqgrid tr.ui-row-ltr td.noVerticalLines { border-right-color: transparent; }
.ui-jqgrid tr.ui-row-ltr td.noHorizLines { border-bottom-color: transparent; }
In the same way you can modify the above code to make some other effects (horizontal or vertical lines on the places where you wan to have it).

Setting paperSize for PDF printing in Casper

In generating PDFs in Phantom, I can set the paper size like this:
page.paperSize = {
height: '8.5in',
width: '11in',
orientation: 'landscape',
border: '0.4in'
};
then the page.render(output) function generates a PDF properly. In other words, the size is correct and it has many pages of that size.
I can't get this to work in Casper (and I'm not sure if it is supported). So for example, the following:
var casper = require('casper').create({
paperSize: {
height: '8.5in',
width: '11in',
orientation: 'landscape',
border: '0.4in'
},
logLevel: 'debug',
verbose: true
});
....this.capture('print.pdf'); ...
creates a PDF with a single, very long page. Setting viewportSize does not fix the problem.
Is there any way to access the pageSize object from within Casperjs?
You can access paperSize through casper.page.paperSize, however you will need to set this after calling casper.start(), otherwise casper.page will be equal to null.
Here's an example:
var casper = require("casper").create();
casper.start();
casper.page.paperSize = {
width: '11in',
height: '8.5in',
orientation: 'landscape',
border: '0.4in'
};
casper.thenOpen('http://www.facebook.com/', function() {
this.capture('test.pdf');
this.echo('created pdf.');
});
casper.run();

JqGrid with autocompletion cant parse data from controller to view

Last few days i was trying to get jqgrid with autocompletion fields to work, now i can get it to work with local data, but as soon as i trying to get data from my controller data didnt get parsed.
View code:
{ name: 'EanNummer', index: 'EanNummer', width: 65, sortable: true, editable: true, edittype: 'text', editoptions: {
dataInit:
function (elem) {
$(elem).autocomplete({ minLength: 0, source: '#Url.Action("GetBrands")' })
.data("autocomplete")._renderItem = function (ul, item) {
return $("<li></li>")
.data("item.autocomplete", item)
.append("<a>" + item.Id + ", " + item.Name + "</a>")
.appendTo(ul);
};
}
}
},
if instead of source: url i use source: ["c++", "java", "php", "coldfusion", "javascript", "asp", "ruby"] for example code works fine and shows up, so something must be wrong with my controller side code
Controller Code:
public JsonResult GetBrands()
{
string vendorId = "";
var username = "";
var name = System.Web.HttpContext.Current.User.Identity.Name;
var charArray = name.Split("\\".ToCharArray());
username = charArray.Last();
vendorId = service.GetVendorIdByUsername(username);
List<String> list = new List<String>();
var brands = service.getBrandsByVendor(vendorId);
var s= (from brand in brands
select new
{
Id = brand.BrandId,
Name = brand.BrandName
}).ToList();
return Json(s);
}
If you use item.Id and item.Name on the client side you should return not the List<String>. Instead of that you should returns the list of new {Id=brand.BrandId, Name=brand.BrandName}. You should just use LINQ instead of foreach:
return Json ((from brand in brands
select new {
Id = brand.BrandId,
Name = brand.BrandName
}).ToList());
UPDATED: I modified for you the demo from the answer and included jQuery UI Autocomplete support in two forms. The standard rendering:
and the custom rendering:
The Autocomplete functionality works in Advanced Searching dialog in the same way like in the Searching Toolbar:
You can download the demo from here.
The server code of the standard autocomplete is
public JsonResult GetTitleAutocomplete (string term) {
var context = new HaackOverflowEntities();
return Json ((from item in context.Questions
where item.Title.Contains (term)
select item.Title).ToList(),
JsonRequestBehavior.AllowGet);
}
It returns array of strings in JSON format. The list of Titles are filtered by term argument which will be initialized to the string typed in the input field.
The server code of the custom autocomplete is
public JsonResult GetIds (string term) {
var context = new HaackOverflowEntities();
return Json ((from item in context.Questions
where SqlFunctions.StringConvert((decimal ?)item.Id).Contains(term)
select new {
value = item.Id,
//votes = item.Votes,
title = item.Title
}).ToList (),
JsonRequestBehavior.AllowGet);
}
It uses SqlFunctions.StringConvert to be able to use LIKE in comparing of the integers. Moreover it returns the list of objects having value the title property. If you would return objects having value the lable properties the values from the lable properties will be displayed in the Autocomplete context menu and the corresponding value property will be inserted in the input field. We use custom title property instead.
The code of the client side is
searchoptions: {
dataInit: function (elem) {
$(elem).autocomplete({ source: '<%= Url.Action("GetTitleAutocomplete") %>' });
}
}
for the standard rendering and
searchoptions: {
sopt: ['eq', 'ne', 'lt', 'le', 'gt', 'ge'],
dataInit: function (elem) {
// it demonstrates custom item rendering
$(elem).autocomplete({ source: '<%= Url.Action("GetIds") %>' })
.data("autocomplete")._renderItem = function (ul, item) {
return $("<li></li>")
.data("item.autocomplete", item)
.append("<a><span style='display:inline-block;width:60px;'><b>" +
item.value + "</b></span>" + item.title + "</a>")
.appendTo(ul);
};
}
}
for the custom rendering.
Additionally I use some CSS settings:
.ui-autocomplete {
/* for IE6 which not support max-height it can be width: 350px; */
max-height: 300px;
overflow-y: auto;
/* prevent horizontal scrollbar */
overflow-x: hidden;
/* add padding to account for vertical scrollbar */
padding-right: 20px;
}
/*.ui-autocomplete.ui-menu { opacity: 0.9; }*/
.ui-autocomplete.ui-menu .ui-menu-item { font-size: 0.75em; }
.ui-autocomplete.ui-menu a.ui-state-hover { border-color: Tomato }
.ui-resizable-handle {
z-index: inherit !important;
}
You can uncomment .ui-autocomplete.ui-menu { opacity: 0.9; } setting if you want to have some small
opacity effect in the autocomplete context menu.

Resources