Related
I use Apex Charts to make a pie chart that shows the number of seconds I worked on a project. but I want to convert those seconds into a normal format for time, like 1862 should be 00:31:02. I tried to read the documentation but didn't really understand. can someone help?
My code:
<script>
var options = {
series: <?php echo json_encode($graphSmallTotal['data']); ?>,
chart: {
height: 300,
type: 'donut',
},
dataLabels: {
enabled: false
},
theme: {
palette: 'palette2'
},
legend: {
position: "bottom",
horizontalAlign: 'left'
},
labels: <?php echo json_encode($graphSmallTotal['names']); ?>,
colors: <?php echo json_encode($graphSmallTotal['colors']); ?>,
plotOptions: {
pie: {
donut: {
labels: {
name: {
show: false
},
label: {
show: false,
fontSize: '36px',
},
total: {
show: true
}
}
}
}
}
};
var chart = new ApexCharts(document.querySelector("#byProject"), options);
chart.render();
</script>
Create custom formatter for tooltip value like this
tooltip: {
y: {
formatter: function(value) {
return new Date(value * 1000).toISOString().substr(11, 8);
}
}
},
https://apexcharts.com/docs/options/tooltip/#yformatter
I try to implement flutter chart with high_chart: ^2.0.3 library.
When come to the implement the navigator its not showing on the chart. I enable the navigator but
Chart only show like this.
navigator: {
enabled: true
},
What i looking for get like this.
I add the chart data string like this.
final String _chartData = '''{
chart: {
type: 'spline'
},
title: {
text: 'Snow depth at Vikjafjellet, Norway'
},
subtitle: {
text: 'Irregular time data in Highcharts JS'
},
navigator: {
enabled: true
},
xAxis: {
type: 'datetime',
dateTimeLabelFormats: { // don't display the dummy year
month: '%e. %b',
year: '%b'
},
title: {
text: 'Date'
}
},
yAxis: {
title: {
text: 'Snow depth (m)'
},
min: 0
},
tooltip: {
headerFormat: '<b>{series.name}</b><br>',
pointFormat: '{point.x:%e. %b}: {point.y:.2f} m'
},
plotOptions: {
spline: {
marker: {
enabled: true
}
}
},
series: [{
name: 'Winter 2007-2008',
data: [
[Date.UTC(1970, 9, 27), 0 ],
//data
]
}, {
name: 'Winter 2008-2009',
data: [
[Date.UTC(1971, 5, 7), 0 ]//data
]
}, {
name: 'Winter 2009-2010',
data: [
[Date.UTC(1970, 9, 9), 0 ],
//data
]
}],
}''';
Also i add this for the index.html file
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/series-label.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<script src="https://code.highcharts.com/stock/highstock.js"></script>
Full source code Here..
You need to load Highstock only, Highcharts is already included in Highstock:
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/stock/modules/series-label.js"></script>
<script src="https://code.highcharts.com/stock/modules/exporting.js"></script>
<script src="https://code.highcharts.com/stock/modules/export-data.js"></script>
<script src="https://code.highcharts.com/stock/modules/accessibility.js"></script>
Live demo: http://jsfiddle.net/BlackLabel/hnxvqpyj/
Docs: https://www.highcharts.com/docs/stock/understanding-highcharts-stock
I am trying to use Side Navigation component in UI5. From the below picture you can see a modal dialog, I have used side navigation to get the items in the left. when ever I select something from the list, corresponding content should be visible on the right.
Can someone please suggest me on how it can be achieved.
You will need some form of Splitter e.g. sap.ui.layout.Splitter
Take a look a this little Demo
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta http-equiv="Content-Type" content="text/html"/>
<meta charset="UTF-8">
<script src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js" id="sap-ui-bootstrap" data-sap-ui-libs="sap.m,sap.ui.layout" data-sap-ui-theme="sap_belize"></script>
<script>
var dialogModel = {
RateCategory_ID: {
id: "RateCategory_ID",
label: "Rate Category",
type: "MultiSelect",
values: [{
key: "ST",
value: "ST",
selected: true
}, {
key: "DT",
value: "DT",
selected: false
}]
},
Approval_Filter: {
id: "Approval_Filter",
label: "ApprovalFilter",
type: "SingleSelect",
values: [{
key: "Separate_Filter",
value: "Separate",
selected: true,
}, {
key: "Last_Approval_Filter",
value: "Last Approval",
selected: false
}]
}
};
var model = new sap.ui.model.json.JSONModel();
model.setData(dialogModel);
var oParentList = new sap.m.List({
mode: "SingleSelectMaster",
items: {
path: "/",
template: new sap.m.StandardListItem({
type: "Active",
title: "{label}"
})
},
selectionChange: function(event) {
var oBindingContext = event.getSource().getSelectedItem().getBindingContext();
oMembersList.setBindingContext(oBindingContext);
oSelectedItemsList.setBindingContext(oBindingContext);
oSelectedItemsList.getBinding("items").filter(new sap.ui.model.Filter("selected",sap.ui.model.FilterOperator.EQ,true));
}
});
oParentList.addEventDelegate({
onAfterRendering: function() {
// check if nothing is selected
if (this.getSelectedItem() === null) {
var items = this.getItems();
// check if there are items
if (items && items.length > 0) {
this.setSelectedItem(items[0], true);
}
}
this.fireSelectionChange();
}
}, oParentList);
var oMembersList = new sap.m.List({
mode: "{type}",
includeItemInSelection: true,
modeAnimationOn: false,
items: {
path: "values",
template: new sap.m.StandardListItem({
type: "Active",
title: "{value}",
selected: "{selected}"
})
},
selectionChange: function(event) {
var oBindingContext = event.getSource().getBindingContext();
oSelectedItemsList.setBindingContext(oBindingContext);
oSelectedItemsList.getBinding("items").filter(new sap.ui.model.Filter("selected",sap.ui.model.FilterOperator.EQ,true));
}
});
var oSelectedItemsList = new sap.m.List({
mode: "Delete",
modeAnimationOn: false,
visible: {
path: "type",
formatter: function(type) {
return type === "MultiSelect";
}
},
items: {
path: "values",
template: new sap.m.StandardListItem({
title: "{value}",
})
},
delete: function(oEvent) {
model.setProperty(oEvent.getParameters().listItem.getBindingContextPath() + "/selected", false);
oMembersList.fireSelectionChange();
}
});
var variablesVBox = new sap.m.VBox({
items: [
new sap.m.Label({
text: "Variables"
}),
new sap.m.Label({
text: ""
}),
oParentList
],
layoutData: new sap.ui.layout.SplitterLayoutData({
resizable: false
})
});
var membersVBox = new sap.m.VBox({
items: [
new sap.m.Label({
text: "Available Members"
}),
new sap.m.Label({text: ""}),
oMembersList
],
layoutData: new sap.ui.layout.SplitterLayoutData({
resizable: false
})
});
var selectedMembersVBox = new sap.m.VBox({
items: [
new sap.m.Label({
text: "Selected Members"
}),
new sap.m.Label({text: ""}),
oSelectedItemsList
],
layoutData: new sap.ui.layout.SplitterLayoutData({
resizable: false
})
});
var splitter = new sap.ui.layout.Splitter({
contentAreas: [variablesVBox, membersVBox, selectedMembersVBox]
});
splitter.setModel(model);
var okButton = new sap.m.Button({
text: "OK",
press: function(event) {
oDialog.close();
}
});
var cancelButton = new sap.m.Button({
text: "Cancel",
press: function(event) {
oDialog.close();
}
});
var oDialog = new sap.m.Dialog({
title: "Global Variables",
content: [splitter],
buttons: [okButton, cancelButton],
contentWidth: "70%",
contentHeight: "70%"
});
var oButton = new sap.m.Button({
text: "Open dialog",
press: function() {
oDialog.open();
}
}).placeAt("content");
</script>
</head>
<body class="sapUiBody">
<div id="content"></div>
</body>
</html>
sap.tnt.SideNavigation has to be placed inside sap.tnt.ToolPage in order to work properly. But the ToolPage control is meant to take the full width and height of the page, not only a part of it, like it would if placed inside Dialog. Therefore using this controls to achieve what you need is not possible.
This is a custom control created for my previous question Custom font for currency signs
I have two span elements coming next to each other. They sit in the FormattedText. The FormattedText itself sits in the HBox.
I want popover fired when user mouses over/out from the hbox. Unfortunately, as I have 2 spans this fires separately when user hovers overs them (thus showing 2 separate popovers, when in fact it should be one). My assumption is that this causes because onmouseover/out is attached to both spans under the hood. Can I restrict these events to hbox only?
sap.ui.define([
'sap/ui/core/Control',
'sap/m/FormattedText',
'sap/m/HBox',
], function (Control, FormattedText, HBox) {
return Control.extend('drex.control.TherapyCosts', {
metadata: {
properties: {
rank: {
type: 'int',
defaultValue: 0
},
},
aggregations: {
_rankedTherapyCost: {type: 'sap.m.FormattedText', multiple: false, singularName: '_rankedTherapyCost'},
_popover: {type: 'sap.m.Popover', multiple: false, singularName: '_popover'},
_hbox: {type: 'sap.m.HBox', multiple: false}
}
},
init: function () {
Control.prototype.init.apply(this, arguments);
},
onBeforeRendering: function () {
const highlighedCurrency = this.getCurrency().repeat(this.getRank());
const fadedCurrency = this.getCurrency().repeat(7 - this.getRank());
const _popover = new sap.m.Popover({
showHeader: false,
placement: 'VerticalPreferredBottom',
content: new sap.m.Text({text: 'test'})
});
this.setAggregation('_popover', _popover);
const _formattedText = new FormattedText({
htmlText:
`<span class="currencyHighlighted">${highlighedCurrency}</span>` +
`<span class="currencyFaded">${fadedCurrency}</span>`
});
this.setAggregation('_rankedTherapyCost', _formattedText);
const _hbox = new HBox(
{ items: [this.getAggregation('_rankedTherapyCost')]})
.addEventDelegate({
onmouseover: () => {
this.getAggregation('_popover').openBy(this);
},
onmouseout: () => {
this.getAggregation('_popover').close()
}
});
this.setAggregation('_hbox', _hbox)
},
renderer: function (rm, oControl) {
const _hbox = oControl.getAggregation('_hbox');
rm.write('<div');
rm.writeControlData(oControl);
rm.write('>');
rm.renderControl(_hbox);
rm.write('</div>');
}
});
});
Here is the video of the issue
https://streamable.com/fjw408
The key here is the mouseout event is triggered when the mouse moves out of any child element of the element that is listening for the event. In this case, for example, moving from the emphasised text to the faded text, you get a mouseout event when moving off the emphasised text, which closes the popup, then a mouseover event on the faded text which opens it again.
Since you opening an already open popup doesn't do anything, you only need add a line on mouseout to inspect the element that you've gone to. If it is not a child of the current element, only then close the popover.
if (!this.getDomRef().contains(e.toElement)) {
popOver.close()
}
Building on D.Seah's answer, I've added this to the JSBin. I personally don't like using onBeforeRendering and onAfterRendering like this, so I've refactored a little to construct everything on init and simply change the controls on property change. This way, you're doing less on rendering for performance reasons.
sap.ui.define([
'sap/ui/core/Control',
'sap/m/FormattedText',
], function (Control, FormattedText) {
Control.extend('TherapyCosts', {
metadata: {
properties: {
rank: {
type: 'int',
defaultValue: 0
},
currency: {
type: "string",
defaultValue: "$"
}
},
aggregations: {
_highlighted: {type: 'sap.m.FormattedText', multiple: false},
_faded: {type: 'sap.m.FormattedText', multiple: false},
_popover: {type: 'sap.m.Popover', multiple: false, singularName: '_popover'}
}
},
init: function () {
Control.prototype.init.apply(this, arguments);
this.addStyleClass('therapy-cost');
const highlight = new FormattedText();
highlight.addStyleClass("currency-highlight");
this.setAggregation('_highlighted', highlight);
const faded = new FormattedText();
faded.addStyleClass("currency-faded");
this.setAggregation('_faded', faded);
const _popover = new sap.m.Popover({
showHeader: false,
placement: 'VerticalPreferredBottom',
content: new sap.m.Text({text: 'test'})
});
this.setAggregation('_popover', _popover);
},
_changeAggr: function () {
const highlighedCurrency = this.getCurrency().repeat(this.getRank());
const highlight = this.getAggregation("_highlighted");
highlight.setHtmlText(highlighedCurrency);
const fadedCurrency = this.getCurrency().repeat(7 - this.getRank());
const faded = this.getAggregation("_faded");
faded.setHtmlText(fadedCurrency);
},
setRank: function(rank) {
if (this.getProperty("rank") !== rank) {
this.setProperty("rank", rank);
this._changeAggr();
}
},
setCurrency: function(curr) {
if (this.getProperty("currency") !== curr) {
this.setProperty("currency", curr);
this._changeAggr();
}
},
renderer: function (rm, oControl) {
rm.write('<div');
rm.writeControlData(oControl);
rm.writeClasses(oControl);
rm.writeStyles(oControl);
rm.write('>');
rm.renderControl(oControl.getAggregation('_highlighted'));
rm.renderControl(oControl.getAggregation('_faded'));
rm.write('</div>');
},
onmouseover: function (e) {
const popOver = this.getAggregation('_popover');
popOver.openBy(this);
},
onmouseout: function (e) {
if (!this.getDomRef().contains(e.toElement)) {
const popOver = this.getAggregation('_popover');
popOver.close();
}
}
});
(new TherapyCosts({
rank: 5,
currency: "£"
})).placeAt('content')
});
.therapy-cost {
display: inline-flex;
flex-direction: row;
}
.therapy-cost .currency-highlighted {
color: black;
}
.therapy-cost .currency-faded {
color: lightgrey;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
<script
src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-libs="sap.m"></script>
</head>
<body class="sapUiBody sapUiSizeCompact">
<div id='content'></div>
</body>
</html>
https://jsbin.com/gukedamemu/3/edit?css,js,output
i think you can do without the hbox; by just having two formatted text or any sapui5 controls will be ok too.
sap.ui.define([
'sap/ui/core/Control',
'sap/m/FormattedText',
], function (Control, FormattedText) {
Control.extend('TherapyCosts', {
metadata: {
properties: {
rank: {
type: 'int',
defaultValue: 0
},
currency: {
type: "string",
defaultValue: "$"
}
},
aggregations: {
_highlighted: {type: 'sap.m.FormattedText', multiple: false},
_faded: {type: 'sap.m.FormattedText', multiple: false},
_popover: {type: 'sap.m.Popover', multiple: false, singularName: '_popover'}
}
},
init: function () {
Control.prototype.init.apply(this, arguments);
this.addStyleClass('therapy-cost')
},
onBeforeRendering: function () {
const highlighedCurrency = this.getCurrency().repeat(this.getRank());
const highlight = new FormattedText({
htmlText: highlighedCurrency
});
this.setAggregation('_highlighted', highlight);
const fadedCurrency = this.getCurrency().repeat(7 - this.getRank());
const faded = new FormattedText({
htmlText: fadedCurrency
});
this.setAggregation('_faded', faded);
const _popover = new sap.m.Popover({
showHeader: false,
placement: 'VerticalPreferredBottom',
content: new sap.m.Text({text: 'test'})
});
this.setAggregation('_popover', _popover);
},
renderer: function (rm, oControl) {
rm.write('<div');
rm.writeControlData(oControl);
rm.writeClasses(oControl);
rm.writeStyles(oControl);
rm.write('>');
rm.renderControl(oControl.getAggregation('_highlighted'));
rm.renderControl(oControl.getAggregation('_faded'));
rm.write('</div>');
},
onAfterRendering: function () {
const popOver = this.getAggregation('_popover');
const highlighted = this.getAggregation("_highlighted");
highlighted.$().addClass("currency-highlighted");
highlighted.$().hover(function() {
popOver.openBy(highlighted);
}, function() {
popOver.close();
});
const faded = this.getAggregation("_faded");
faded.$().addClass("currency-faded");
},
});
(new TherapyCosts({
rank: 5
})).placeAt('content')
});
https://jsbin.com/razebuq/edit?css,js,output
I have a chart which has 4 series (Fiddle link below). Currently, it has Title1, Title2, Title3, and Title4. I want to change the different color for each title text name (Not the bar); for example, Title1 is red, Title2 is blue, Title3 is green, and Title4 is black. Is there a way to change all these titles with different colors?
https://jsfiddle.net/milacay/e4fe4hsz/21/
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Test Google Chart</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {callback: drawChart, packages: ['corechart']});
function drawChart() {
var array = [
["", "Today", "Goal"],
["Title1", 4553, 4151],
["Title2", 5560, 6150],
["Title3", 850, 920],
["Title4", 10505, 12320]
];
var data = new google.visualization.arrayToDataTable(array);
var formatTooltip = new google.visualization.NumberFormat({
pattern : '#,##0'
});
formatTooltip.format(data, 1);
formatTooltip.format(data, 2);
var formatShort = new google.visualization.NumberFormat({
pattern : 'short'
});
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
calc : function (dt, row) {
return formatShort.formatValue(dt.getValue(row, 1));
},
type : "string",
role : "annotation"
},
2, {
calc : function (dt, row) {
return formatShort.formatValue(dt.getValue(row, 2));
},
type : "string",
role : "annotation"
},
]);
var options = {
chart: {
title: ' ',
animation: {
duration: 2000,
easing: "out",
startup: true,
}
},
chartArea: {right:0
, width: "80%"
, height: "80%"
},
bar: {
groupWidth: 55 // Set the width for each bar
},
legend: {position:'top'},
hAxis: {
format: 'short',
//title: 'Month',
textStyle : {
bold: true,
fontSize: 10 // fontsize for the vAxis label.
//color: 'darkblue',
},
},
vAxis: {
format: 'short',
title: 'Progress To-Date',
gridlines: { count: 8 }
},
width:320,
height:300,
bars: 'vertical',
colors: ["lightblue", "lightgray"]
};
var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
chart.draw(view, options);
}
</script>
</head>
<body>
<div id="chart_div"></div>
</body>
</html>
if you want to change the color of the axis labels,
change those manually when the chart's 'ready' event fires,
see following working snippet...
google.charts.load('current', {
callback: drawChart,
packages: ['corechart']
});
function drawChart() {
var array = [
["", "Today", "Goal"],
["Title1", 4553, 4151],
["Title2", 5560, 6150],
["Title3", 850, 920],
["Title4", 10505, 12320]
];
var data = new google.visualization.arrayToDataTable(array);
var formatTooltip = new google.visualization.NumberFormat({
pattern : '#,##0'
});
formatTooltip.format(data, 1);
formatTooltip.format(data, 2);
var formatShort = new google.visualization.NumberFormat({
pattern : 'short'
});
var view = new google.visualization.DataView(data);
view.setColumns([0, 1, {
calc : function (dt, row) {
return formatShort.formatValue(dt.getValue(row, 1));
},
type : "string",
role : "annotation"
},
2, {
calc : function (dt, row) {
return formatShort.formatValue(dt.getValue(row, 2));
},
type : "string",
role : "annotation"
},
]);
var options = {
chart: {
title: ' ',
animation: {
duration: 2000,
easing: "out",
startup: true,
}
},
chartArea: {right:0
, width: "80%"
, height: "80%"
},
bar: {
groupWidth: 55 // Set the width for each bar
},
legend: {position:'top'},
hAxis: {
format: 'short',
//title: 'Month',
textStyle : {
bold: true,
fontSize: 10 // fontsize for the vAxis label.
//color: 'darkblue',
},
},
vAxis: {
format: 'short',
title: 'Progress To-Date',
gridlines: { count: 8 }
},
width:320,
height:300,
bars: 'vertical',
colors: ["lightblue", "lightgray"]
};
var container = document.getElementById('chart_div');
var chart = new google.visualization.ColumnChart(container);
google.visualization.events.addListener(chart, 'ready', function () {
var colorIndex = 0;
var colorPallette = ['red', 'blue', 'green', 'black'];
Array.prototype.forEach.call(container.getElementsByTagName('text'), function (label) {
if ((label.getAttribute('text-anchor') === 'middle') && (label.getAttribute('fill') !== '#404040')) {
label.setAttribute('fill', colorPallette[colorIndex]);
colorIndex++;
}
});
});
chart.draw(view, options);
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart_div"></div>
note: the label color (#404040) is used to differentiate the x-axis labels from the annotation labels...