I am creating a Ploymer custom component and using Dygraph to creat a chart. I have added a pointClickCallback for the same.
But, when the chart is inside the shadow dom pointClickcallback is not working at all. Although, when I put the chart outside the custom component i.e. in the index.html, the pointClickCallback is working fine.
EDIT : highlightCallback is working properly inside shadow dom, not the pointClickCallback
Can any one tell me what might be the problem.
UPDATE
I am not sure whether this is right way of doing it but, please suggest. I am doing like below and it works for me
var self = this; // 'this' is not the window object
self.pts = null;
var g = new Dygraph(
this.$.div_g,
NoisyData, {
rollPeriod: 7,
showRoller: true,
errorBars: true,
highlightCallback: function(e, x, pts, row) {
console.log("highlightCallback --> self.pts", self.pts);
console.log("highlightCallback", pts);
self.pts = pts;
console.log("highlightCallback --> self.pts", self.pts);
},
interactionModel : {
'click' : function(e) {
console.log("click", e, self.pts);
}
},
}
);
The pointClickCallback does not go into the interactionModel but is bascially on the same level as the highlightCallback.
So your code should look like this:
var g = new Dygraph(
this.$.div_g,
NoisyData, {
rollPeriod: 7,
showRoller: true,
errorBars: true,
highlightCallback: function(e, x, pts, row) {
console.log("highlightCallback --> self.pts", self.pts);
console.log("highlightCallback", pts);
self.pts = pts;
console.log("highlightCallback --> self.pts", self.pts);
},
pointClickCallback: function(e,pt) {
console.log('Point clicked');
},
interactionModel : {
'click' : function(e) {
console.log("click", e, self.pts);
}
},
}
);
Related
I am writing tests for my SPA written using angularJS using Jasmine, the outputs for the test show up in the bottom of the html page and get partially hidden because of my page sidebar. What I want to do is show them in a specific position within the screen, I tried putting the test part within a specific div and changing the position of the div, but it does not work. I do not want to show the output of the tests in console, I want them to remain within the main page, but within a specific position of my choice. Any help is appreciated. I can provide the code segment if anyone needs to see.
Thanks
<div style="margin-left:30%;">
<script>
describe('test', function () {
beforeEach(module('myApp'));
var $controller;
beforeEach(inject(function (_$controller_) {
$controller = _$controller_;
}));
describe('deleteEntry', function () {
it('Entry should be deleted', function () {
var $scope = {};
var controller = $controller('movieCtrl', {$scope: $scope});
$scope.movies = [
{
"title": "The Shawshank Redemption",
"rank": "1",
"id": "tt0111161"
},
{
"title": "The Godfather",
"rank": "2",
"id": "tt0068646"
}
];
$scope.deleteEntry("1");
expect($scope.exists("The Shawshank Redemption")).toBe(false);
$scope.deleteEntry("2");
expect($scope.exists("The Godfather")).toBe(true);
});
});
describe('addEntry', function () {
it('Entry should be added', function () {
var $scope = {};
$scope.movies=[];
var controller = $controller('movieCtrl', {$scope: $scope});
$scope.addEntry("Testing Movie","1");
expect($scope.exists("Testing Movie")).toBe(true);
$scope.addEntry("Testing Movie Last","100");
expect($scope.exists("Testing Movie Last")).toBe(false);
});
});
});
</script>
I'm wondering is there any way to show in ChartJs (in bar chart) bars with zero value?
I mean something like this: https://jsfiddle.net/vrg5cnk5/16/, so the second bar would be just blue border on level zero.
I used already this code:
ticks: {
beginAtZero: true,
min: 0,
suggestedMin: 0
}
but I'm not surprised it didn't work.
Thanks in advance
Simply specify minBarLength in the dataset, with the minimum length in pixels the bars should have. See documentation.
Working Example:
var $chartCanvas = $('myCanvas');
var barChart = new Chart(myCanvas, {
type: 'bar',
data: {
labels: ['Accepted Answer', 'Top rated answer', 'This Answer'],
datasets:[{
data: [0, 3, 10],
minBarLength: 7, // This is the important line!
}]
},
options: {
title: {
display: true,
text: 'helpfulness of answers to this questions'
},
legend: {
display: false
}
}
});
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="myCanvas"></canvas>
After dig into the plugin system, if you using Chart.js >=2.5, you can write a plugin to achieve it. Here is an example to draw a line when data is zero.
Here is my code:
const zeroCompensation = {
renderZeroCompensation: function (chartInstance, d) {
// get postion info from _view
const view = d._view
const context = chartInstance.chart.ctx
// the view.x is the centeral point of the bar, so we need minus half width of the bar.
const startX = view.x - view.width / 2
// common canvas API, Check it out on MDN
context.beginPath();
// set line color, you can do more custom settings here.
context.strokeStyle = '#aaaaaa';
context.moveTo(startX, view.y);
// draw the line!
context.lineTo(startX + view.width, view.y);
// bam! you will see the lines.
context.stroke();
},
afterDatasetsDraw: function (chart, easing) {
// get data meta, we need the location info in _view property.
const meta = chart.getDatasetMeta(0)
// also you need get datasets to find which item is 0.
const dataSet = chart.config.data.datasets[0].data
meta.data.forEach((d, index) => {
// for the item which value is 0, reander a line.
if(dataSet[index] === 0) {
this.renderZeroCompensation(chart, d)
}
})
}
};
and here is how to add the plugin to Chart.js
var chart1 = new Chart(ctx, {
plugins: [zeroCompensation]
});
The offcial document is not clear about their plugin API, you may console.log to find what you want.
There is no way to configure chart.js to do this, but you could use a hack instead. Just set your value for the 0 bar to a really small number like 0.1.
data: [2, 0.1, 3, 1]
Here is an example forked from yours.
If you are using tooltips, then you would have to also add some logic so that the tooltip for that bar still displays a value of 0. You can do this using the label callback.
label: function(tooltipItem, data) {
var value = data.datasets[0].data[tooltipItem.index];
var label = data.labels[tooltipItem.index];
if (value === 0.1) {
value = 0;
}
return label + ': ' + value + ' %';
}
Here is an example putting it all together.
If you struggle with this, here's what I came up with. It is similar idea to Li Jinyao, but in addition, you would get click and hover events (tooltip) working for whole bar.
I value is close to 0 but negative, the bar will show on negative side of x axis - you can easily get rid of it if that's not what you want to do.
const zeroCompensation = {
id: 'zeroCompensation',
beforeDatasetsDraw: function(chart) {
const meta = chart.getDatasetMeta(0)
forEach(meta.data, d => {
const barHeight = d._view.base - d._view.y;
if(Math.abs(barHeight) < minBarHeight /* I used value 5 */) {
d._view.y = d._view.base - minBarHeight * (Math.sign(barHeight) || 1);
}
});
}};
and add it to plugins:
plugins: [zeroCompensation]
Keep in mind that this will work for values close to 0, not only 0. If you want it only for zeroes, you can change contents of if condition to:
chart.config.data.datasets[0].data[index] === 0
This is what Li Jinyao used in his answer.
Hope that helps.
Edit: I wanted to highlight that this solution works regardless of values spread. Answer marked as solution will not work as intended if there are some high values in data set - 0.1 will render same as 0 in that case.
Here is the simplest way to do this in V3 chart js
Chart.defaults.datasets.bar.minBarLength = 5;
2019 Update
This can be done easily as below.
var myChart = new Chart(ctx, {
...
options: {
...
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
);
You can find this in Chart.js documentation https://www.chartjs.org/docs/latest/
I just stumbled over this questions because I had a similar problem: The type of my Chart.js chart was 'horizontalBar' and for some datasets (where no zero values was present across the dataset) the horizontal bar did not start with 0 rather with the lowest value from the dataset.
I tried to figure out a solution and came up with following entry in the options object while creating the charts:
ticks: {
beginAtZero:true,
mirror:false,
suggestedMin: 0,
suggestedMax: 100
}
However that did not work as expected although all posts said it works that way.
After further investigation and reading of the Chart.js documentation I found the solution. The reason the further step did not work was following I found in the documentation:
However, any options specified on the x axis in a bar chart, are applied to the y axis in a horizontal bar chart.
So I just changed my options object to hold the proper configuration for the xAxes and it worked.
For those who are interested here is the the whole code I used for creating the horizontal bar chart with y-axis starting always at zero:
this.chart = new Chart(
ctx,
{
type: 'horizontalBar',
data: this.data.chartdata,
options: {
scales: {
xAxes: [{
stacked: false,
ticks: {
beginAtZero:true,
mirror:false,
suggestedMin: 0,
suggestedMax: 100
}
}],
yAxes: [{
stacked: true
}]
},
scaleBeginAtZero : true,
// important here to use () =>
// to keep the scope of this
onClick: (e) => {
var actChart : Chart = this.charts[trialId];
var element =
actChart.getElementAtEvent(e);
}
}
}
);
I extended sap.ui.core.Icon with hover event handling:
sap.ui.define(function () {
"use strict";
return sap.ui.core.Icon.extend("abc.reuseController.HoverIcon", {
metadata: {
events: {
"hover" : {}
}
},
// the hover event handler, it is called when the Button is hovered - no event registration required
onmouseover : function(evt) {
this.fireHover();
},
// add nothing, just inherit the ButtonRenderer as is
renderer: {}
});
});
The event onmouseover is never fired. I also used this extension for sap.m.Button and it works. But I need this for sap.ui.core.Icon.
I also tried this jquery example but it did not work at all.
$("testIcon").hover(function(oEvent){alert("Button" + oEvent.getSource().getId());});
Please, do you have any idea why event handler onmouseover is not called for sap.ui.core.Icon? Or can you propose some other solution?
Bellow is how I added icon to my sap.suite.ui.commons.ChartContainer:
var oFilterIcon = new HoverIcon({
tooltip : "{i18n>filter}",
src : "sap-icon://filter",
hover : function(oEvent){alert("Button" + oEvent.getSource().getId());},
});
this.byId("idChartContainer").addCustomIcon(oFilterIcon);
This is my analysis:
Your new custom Control Icon for hover is correct. If you will use it independently it will work correctly .
However, your custom control will not work as your icons are converted to sap.m.OverflowToolbarButton when you use ChartContainer.
I looked into the source code of Chart Container and below is the code:
sap.suite.ui.commons.ChartContainer.prototype._addButtonToCustomIcons = function(i) {
var I = i;
var s = I.getTooltip();
var b = new sap.m.OverflowToolbarButton({
icon: I.getSrc(),
text: s,
tooltip: s,
type: sap.m.ButtonType.Transparent,
width: "3rem",
press: [{
icon: I
}, this._onOverflowToolbarButtonPress.bind(this)]
});
this._aCustomIcons.push(b);
}
So, you Icon is not used but its properties are used. As this is standard code, your hover code of Custom icon is not passed along.
One solution will be to add the onmouseover to sap.m.OverflowToolbarButton :
sap.m.OverflowToolbarButton.prototype.onmouseover=function() {
alert('hey')
};
However, this is dangerous as all OverflowToolbarButton button start using this code and I will not recommend it.
Next solution would be to overwrite the private method:_addButtonToCustomIcons ( again not recommendred :( )
sap.suite.ui.commons.ChartContainer.prototype._addButtonToCustomIcons = function(icon) {
var oIcon = icon;
var sIconTooltip = oIcon.getTooltip();
var oButton = new sap.m.OverflowToolbarButton({
icon : oIcon.getSrc(),
text : sIconTooltip,
tooltip : sIconTooltip,
type : sap.m.ButtonType.Transparent,
width : "3rem",
press: [{icon: oIcon}, this._onOverflowToolbarButtonPress.bind(this)]
});
this._aCustomIcons.push(oButton);
//oButton.onmouseover.
oButton.onmouseover = function() {
this.fireHover();
}.bind(oIcon);
};
Let me know if this helps u. :)
I have a DataTable in which I added drag and drop support for the rows (draggableRows="true"). The problem is that wherever I click inside a row, I can drag it.
What I want is the possibility to drag the row only by a handle, the handle could be a column field with an icon at the left of the row for example (have a look at the screenshot), so if the user clicks on a row outside of the handle, there's no drag support; but if he clicks on the handle, he'll have the possibility to drag the entire row.
How could I implement this?
The source is always with you. In there you can see the makeRowsDraggable function on line 2727 in datatable.js
makeRowsDraggable: function() {
var $this = this;
this.tbody.sortable({
placeholder: 'ui-datatable-rowordering ui-state-active',
cursor: 'move',
handle: 'td,span:not(.ui-c)',
appendTo: document.body,
start: function(event, ui) {
ui.helper.css('z-index', ++PrimeFaces.zindex);
},
...
}
with a reference to the handle ('td, span:not(.ui-c)').
By overriding this function and having the handle point to a selector that explicitly refers to your handle, you can 'fix' it.
You can even make this generic by not assigning an explict string to the handle, but but looking it up on e.g. a custom pass-through attribute you define on the datatable where you put the 'string' in.
Did I mention already that the source is always with you? Good thing to remember when having further questions
Since Primefaces 6.2 p:datatable has a property rowDragSelector specifically for this purpose. See the example below:
<p:dataTable value="#{myBean.entities}" id="myTablePreferredId" rowDragSelector=".draggableHandle" draggableRows="true">
<p:ajax event="rowReorder" listener="#{myBean.onRowReorder}"/>
<p:column>
<h:outputText styleClass="fa fa-arrows-v draggableHandle" />
</p:column>
...
</p:dataTable>
For more details refer to the primefaces documentation.
My solution is the same as the solution of #Kuketje.
Here is the source code (compatible with Primefaces 6.1)
if (PrimeFaces.widget.DataTable){
PrimeFaces.widget.DataTable = PrimeFaces.widget.DataTable.extend({
makeRowsDraggable: function () {
var $this = this,
draggableHandle = '.dnd-handle'; //change to what ever selector as you like
this.tbody.sortable({
placeholder: 'ui-datatable-rowordering ui-state-active',
cursor: 'move',
handle: draggableHandle,
appendTo: document.body,
start: function (event, ui) {
ui.helper.css('z-index', ++PrimeFaces.zindex);
},
helper: function (event, ui) {
var cells = ui.children(),
helper = $('<div class="ui-datatable ui-widget"><table><tbody></tbody></table></div>'),
helperRow = ui.clone(),
helperCells = helperRow.children();
for (var i = 0; i < helperCells.length; i++) {
helperCells.eq(i).width(cells.eq(i).width());
}
helperRow.appendTo(helper.find('tbody'));
return helper;
},
update: function (event, ui) {
var fromIndex = ui.item.data('ri'),
toIndex = $this.paginator ? $this.paginator.getFirst() + ui.item.index() : ui.item.index();
$this.syncRowParity();
var options = {
source: $this.id,
process: $this.id,
params: [
{name: $this.id + '_rowreorder', value: true},
{name: $this.id + '_fromIndex', value: fromIndex},
{name: $this.id + '_toIndex', value: toIndex},
{name: this.id + '_skipChildren', value: true}
]
}
if ($this.hasBehavior('rowReorder')) {
$this.cfg.behaviors['rowReorder'].call($this, options);
}
else {
PrimeFaces.ajax.Request.handle(options);
}
},
change: function (event, ui) {
if ($this.cfg.scrollable) {
PrimeFaces.scrollInView($this.scrollBody, ui.placeholder);
}
}
});
}
});
}
The solution from Vít Suchánek is not really working. It detects the drag&drop handle only when the page is ready. After the first drag&drop interaction, it is not going to work anymore.
Another possibility is to override Primefaces's setting of handler after initialization of UI sortable:
<script type="text/javascript">
$(document).ready(function() {
var sortableRows = $(".tableWithDraggableRows > tbody");
if (sortableRows) {
sortableRows.sortable("option", "handle", ".ui-icon-arrow-4");
}
});
</script>
See http://api.jqueryui.com/sortable/#option-handle
when i click on google chart point, In tooltip it is showing 'See sample book'.
I want to control the enable and disable property on tooltip using the code.
As of now enable and disable is working with mouse over event but i want to remove this and simply enable and disable the 'see sample block' using programming.
At first point it should be disable its working fine
second point should be enable but it showing disable when mouse over it showing as enable . I need this should be happen as soon as i click the point in the graph.
My HTML code is here:
<html>
<head>
<script type="text/javascript"
src="https://www.google.com/jsapi?autoload={
'modules':[{
'name':'visualization',
'version':'1',
'packages':['corechart']
}]
}"></script>
<script type="text/javascript">
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Year', 'Sales', 'Expenses'],
['2004', 1000, 400],
['2005', 1170, 460],
['2006', 660, 1120],
['2007', 1030, 540]
]);
var options = {
title: 'Company Performance',
legend: { position: 'bottom' },
tooltip: { trigger: 'selection' }
};
var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));
chart.setAction({
id: 'sample',
text: 'See sample book',
enabled:function()
{
if (typeof(chart.getSelection) == 'undefined')
return false;
if (typeof (chart.getSelection()[0]) == 'undefined')
return false;
selection = chart.getSelection();
var ans = selection[0].row;
if(ans == 0)
{
return false;
}
else
{
return true;
}
},
action: function() {
selection = chart.getSelection();
alert(selection[0].row);
}
});
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="curve_chart" style="width: 900px; height: 500px"></div>
</body>
</html>
You can set the tooltip to HTML, this should give you more control of how it operates, and what it displays. To do this, add a tooltip column to your chart, when you're building the chart with columns and rows
data.addColumn({ type: 'string', role: 'annotation', 'p': { 'html': true } });
As you can see, we are setting the tooltip information to be html instead of SVG, and the data you want to populate into your tooltip, should be added as a row to your chart, corresponding to the column.
To modify the tooltip behaviour, you can use the options you pass to the chart, and add the isHtml to true
tooltip: { trigger: selection, isHtml: true }
To make additional changes to your tooltip, in css, you can add this line to your CSS and start overriding the default css
div.google-visualization-tooltip {
}