DateTimeAxis - set Label to display Date + Time - apache-flex

Is there a way in flex 3 chart component to display both the date and time using horizontal DateTimeAxis?
Currently the DateTimeAxis element has an attribute dataunits which allows to set the value to any of "milliseconds|seconds|minutes|hours|days|weeks|months|years" but I want to display the label as "2009/09/15 06:00:00" which includes the day and the time too.
Here is the sample that i'm using
[Bindable]
public var deck:ArrayCollection = new ArrayCollection([
{date:"2009-09-15 06:00:00", close:42.71},
{date:"2009-09-16 06:15:00", close:42.99}
]);
public function myParseFunction(s:String):Date {
var sDate = s.substring(0,s.indexOf(" "));
var sTime = s.substring(s.indexOf(" "));
var aDate = sDate.split("-");
var aTime = sTime.split(":");
return new Date(aDate[0],(aDate[1]*1-1),aDate[2],aTime[0],aTime[1],aTime[2],0);
}
]]>
Thanks in advance.

To solve this, you have to extend the <mx:DateTimeAxis> (unfortunately).
However, it is not hard to do, and an example is posted here: http://codeznips.blogspot.com/2010/12/escape-american-date-format-in.html
You'd might have to extend the example above further by adding a formatSeconds() and set formatStringSeconds = "YYYY/MM/DD JJ:NN:SS".
Or possibly just use the existing formatStringDays and set dataUnits = "days", like this:
<mx:horizontalAxis>
<charts:FormattedDateTimeAxis
formatStringDays="YYYY/MM/DD JJ:NN:SS"
dataUnits = "days"/>
</mx:horizontalAxis>
Vegard

Related

XPages: convert DateTime value to string using browser's locale

A similar question to a previous one I asked, but the difference being that this not for direct rendering from an underlying field - it's instead part of a some SSJS.
This is for a view column which displays the result of a SSJS function, which returns HTML that gets rendered. This HTML includes a date from a DateTime field, which gets converted to text using #Text. The problem I have with this is, #Text converts dates using the locale settings of the server, not the browser.
Is there an alternative to #Text(dateValue,"D0S0") that's browser locale aware?
The most "XPagey" way to do this is to use a date/time converter. For example (using a stand-in for the computed value):
<xp:viewColumn columnName="">
<xp:this.value><![CDATA[#{javascript:
new java.util.Date()
}]]></xp:this.value>
<xp:this.converter>
<xp:convertDateTime type="both"/>
</xp:this.converter>
</xp:viewColumn>
That "convertDateTime", with its built-in formats, will respect the browser's provided locale. If you set the option in the Xsp Properties to use the browser's time zone and "Round trip", it should also respect the user's time zone.
I've managed to get round this by using DateFormat.getDateInstance. The only problem with this is it doesn't return a short date in the same format as the XPage date converter (no leading zeros and a 2-figure year). I've got round this though with some fiddling around with the string after.
Here's the full function:
function returnLocalShortDate(ndtDate) {
// Receives NotesDateTime object, Java date or string; returns localised date string in XPages short date format
importPackage(java.text);
if (#IsText(ndtDate)) { // string
var jsDate = #TextToTime(ndtDate);
} else if (ndtDate instanceof Date) { // Java date
var jsDate:Date = ndtDate;
} else if (#IsTime(ndtDate)) { // Notes date/time
var jsDate:Date = ndtDate[0].toJavaDate();
} else {
return("");
}
var strDate:String = java.text.DateFormat.getDateInstance(DateFormat.SHORT, context.getLocale()).format(jsDate);
var strYear = jsDate.getFullYear();
var strDateArray = strDate.split("/");
strDate = ('0' + strDateArray[0]).slice(-2) + '/' + ('0' + strDateArray[1]).slice(-2) + '/' + strYear;
return(strDate);
}
Actually, if you know the format you want, rather than what the user might want via their browser settings, you should use the SimpleDateFormatter class. You can supply the format in accordance with whatever pattern you want from the javadocs for that class. If you supply the NotesDocument object and the field name, this returns the date in dd-MMM-yyyy format.
function getFormattedDate ( doc:NotesDocument, fieldName:String ) {
importPackage(java.text);
var dateFormatter:java.text.SimpleDateFormat = new SimpleDateFormat("dd-MMM-yyyy");
var d:Date = new Date(#Today());
if ( doc.hasItem (fieldName) ) {
var valueVector:java.util.Vector = doc.getItemValueDateTimeArray(fieldName);
var iterator = valueVector.iterator();
while (iterator.hasNext()) {
var itemvalue = iterator.next();
if ((typeof(itemvalue)).endsWith("DateTime")) {
d = new Date(itemvalue.toJavaDate());
return dateFormatter.format(d);
}
}
} else {
return fieldName + " is not on the document"
}
}
I owe credit to Declan Lynch's blog entry on date formatting, which takes a little debugging because SSJS returns the date value as an Vector now.

How can I have a single column on a column chart using MSCharts (within an Asp.Net application)?

I'm using the following code to generate a chart:
public ActionResult GenerateChart()
{
var chart = new Chart();
chart.AntiAliasing = AntiAliasingStyles.All;
chart.TextAntiAliasingQuality = TextAntiAliasingQuality.High;
chart.Width = 500;
chart.Height = 400;
ChartArea area = new ChartArea();
area.AxisY.LabelStyle.Format = "{0:c}";
chart.ChartAreas.Add(area);
Series serie = new Series();
serie.ChartType = SeriesChartType.Column;
serie.Points.DataBindXY(data, "Year", data, "Amount");
chart.Series.Add(serie);
using (var stream = new MemoryStream())
{
chart.SaveImage(stream, ChartImageFormat.Jpeg);
return File(stream.ToArray(), "image/jpeg");
}
}
It's a simple column chart with data for a sum of amount (Y-axis) per year (X-axis).
The data variable supplied while testing the code has only 1 item. This item represents year 2015 with an amount of a little bit over 9.000 (no pun intended).
As you can see from the image generated below, despite having data for only 1 year, the chart automatically adds the previous year and the next one.
How can I show only 2015? Or at least hide those points/labels programatically? Why is it adding that information?
Thanks in advance.
Try disabling the margin on the X axis with
area.AxisX.IsMarginVisible = false;

Animation of flex Hslider / graph interaction

I currenty have an Hslider that is animated and affects the results presented in a bar graph but when I play through the values of the Hslider the animation is jumpy. by jumpy i mean it sometimes tries to go back a value before going forward. for example the slider value reaches 1963 then briefly goes back to 1962 then continues the odd time jumping back.
can anyone identify any errors in my approach...
public var anim:AnimateProperty = new AnimateProperty();
public function Startanimation():void {
anim.target = YEAR_SLIDER;
yearto = 2011 - YEAR_SLIDER.value;
anim.duration = yearto * 150;
anim.property = "value";
anim.fromValue = YEAR_SLIDER.value;
anim.toValue = 2011;
anim.end();
anim.play();
}
public function update_Application():void{
YEAR = YEAR_SLIDER.value;
GEONAME = COMBO.selectedLabel;
var data:Object = new Object();
data = {YEAR : YEAR, GEONAME : GEONAME};
graphdata.getdata(data);
graphdata.getdata_grid(data);
}
<mx:HSlider
id="YEAR_SLIDER" value="{YS_INITIAL_VALUE}"
minimum="{YS_INITIAL_VALUE}"
maximum="2011" change="update_Application()"
liveDragging="true" accessibilityEnabled="true"
snapInterval="1" currentState=""
tickInterval="10"
width="300" showDataTip="false"
borderColor="#133341"
alpha="1.0"
fillAlphas="[0.69, 0.64, 0.91, 0.91]" dataTipFormatFunction="datatip">
</mx:HSlider>
Thanks in advance...
Solved...//
For anyone else having this issue, it seemed to be the amount of data I was returning to the graph. Once I cleaned up my select statement to return only the specific columns needed and also created an index on the table the animation was smooth.

Refresh a BarChart after adding a BarSeries

first question here.
I have a BarChart showing several normal bars and a BarSeries, like this:
<mx:BarChart id="barchart" dataProvider="{model.myList}" type="clustered">
<mx:horizontalAxis>
<mx:LinearAxis autoAdjust="true"/>
</mx:horizontalAxis>
<mx:verticalAxis>
<mx:CategoryAxis categoryField="name"/>
</mx:verticalAxis>
<mx:series>
<mx:BarSeries dataProvider="{model.myList}" xField="myValue"/>
</mx:series>
</mx:BarChart>
When a user clicks on a button, i need to calculate some values, put them on the "myCalculatedValue" and add another BarSeries as a comparison. I'm doing this:
var barSerie:BarSeries = new BarSeries();
barSerie.dataProvider = model.myList;
barSerie.xField = "myCalculatedValue";
barchart.series.push(barSerie);
But the BarChart does not change at all. Is there some way to refresh the chart after adding the new BarSeries?
The short answer is to use this code:
var barSerie:BarSeries = new BarSeries();
barSerie.dataProvider = model.myList;
barSerie.xField = "myCalculatedValue";
var allSeries:Array = barchart.series;
allSeries.push(barSerie);
barchart.series = allSeries;
The LONG answer, to give you an understanding of how this works:
The way flex knows when to refresh a ui component that is data backed, such as a chart, is on the function set dataProvider property, or equivalent (in this case series).
Here is the code from mx.charts.chartClasses.ChartBase:
public function set series(value:Array /* of Series */):void
{
value = value == null ? [] : value;
_userSeries = value;
var n:int = value.length;
for (var i:int = 0; i < n; ++i)
{
if (value[i] is Series)
{
(value[i] as Series).owner = this;
}
}
invalidateSeries();
invalidateData();
legendDataChanged();
}
Notice that the relevant "invalidate" methods are called at the end of the set method.
If you say barChart.series.push(x), the set series method is never called, only the getter. Therefore in order to force the chart to know there was a change to the series, you need to assign a new value to the series.
It is worth pointing out that even assigning the series to itself will cause an invalidate, although it isn't good coding
barChart.series = barChart.series
Flex is communicating with the server remotely, correct? You probably need to make another explicit call to the app controller that is housing flex.

flex chart columnseries not visible

I have a flex chart that I'm trying to build via actionscript dynamically. For test purposes I came up with the following data structure and code:
Bindable]
public var columnDat:Array=
[{signalID:"SCL", point2:100},
{signalID:"SCL", point2:50},
{signalID:"SCL", point2:30},
{signalID:"SCL", point2:60},
{signalID:"SCL", point2:220},
{signalID:"SCL", point2:140},
{signalID:"SCL", point2:280}];
public function makeDummyChart(genericChart:CartesianChart, genericLegend:Legend, chartPanel:ChartPanel):void {
var renderers:ArrayCollection = new ArrayCollection();
genericChart = new ColumnChart();
// Define the two axes.
var dispAxis:CategoryAxis = new CategoryAxis();
var axr:AxisRenderer = new AxisRenderer();
axr.axis = dispAxis;
renderers.addItem(axr);
var seriesList:ArrayCollection=new ArrayCollection();
// Add the series
genericChart.horizontalAxis = dispAxis;
var columnSeries:ColumnSeries = new ColumnSeries();
BindingUtils.bindProperty(columnSeries, "dataProvider", this, "columnDat");
columnSeries.xField="signalID";;
columnSeries.yField="point2";
seriesList.addItem(columnSeries);
genericChart.series = seriesList.toArray();
genericLegend.dataProvider = genericChart;
genericChart.horizontalAxisRenderers = renderers.toArray();
genericLegend.dataProvider = genericChart;
// chart panel is just the panel on the screen where chart is displayed
chartPanel.addChild(genericChart);
trace (" make dummy chart done");
}
I just get a blank chart when I run this code.
Can't test it by now, but it should be sufficient if you just assign the columnDat array to the series:
columnSeries.dataProvider = columnDat;
or to the column chart:
genericChart.dataProvider = columnDat;
First, you should probably use MXML for this stuff. It's easier.
Second, I don't think you followed the example very well. There's 2 ways of doing charts:
1) Add data to the chart data provider and have the series specify the x and y field within that data provider.
2) Don't add data to the chart and just add the data directly into series without specifying the x and y field.
Right now, you're doing a mix of both 1 and 2 and the series can't see the data because it's being filtered out, which is why it's blank. Don't set the data provider on the series, but set it on the chart instead and it should work. For further example, look at the docs.

Resources