Load Scatter (Line) graphs dynamically from JSON in iOS? - xcode
I'm new to corePlot and i'm having trouble to plot the graph(Line) dynamically from json when we select a particular row in UIPickerView.
Here,
Line graph with x-axis: Time as 02,03,04,.....
y-axis: temperature as 10,20,30,.....
UIPickerView consists of Date(s). for eg: we have 3 rows :
06-03-2015, 07-03-2015, 08-03-2015
and now if we select any particular row in UIPickerView i have to display line graph. I have done with Static data but now i'm getting trouble with dynamic data.
-(void)initialisePlot
{
// Start with some simple sanity checks before we kick off
if ( (self.hostingView == nil) || (self.graphData == nil) ) {
NSLog(#"TUTSimpleScatterPlot: Cannot initialise plot without hosting view or data.");
return;
}
if ( self.graph != nil ) {
NSLog(#"TUTSimpleScatterPlot: Graph object already exists.");
return;
}
// Create a graph object which we will use to host just one scatter plot.
CGRect frame = [self.hostingView bounds];
//CGRect frame = [self.hostingView bounds];
//CGRect frame = [self.hostingView frame];
self.graph = [[CPTXYGraph alloc] initWithFrame:frame] ;
//self.hostingView=[[CPTGraphHostingView alloc]initWithFrame:CGRectMake(0.0, 0.0, 900.0, 420.0)];
//self.graph = [[CPTXYGraph alloc] initWithFrame:self.hostingView.bounds];
// Add some padding to the graph, with more at the bottom for axis labels.
self.graph.plotAreaFrame.paddingTop = 20.0f;
self.graph.plotAreaFrame.paddingRight = 10.0f;
self.graph.plotAreaFrame.paddingBottom = 50.0f;
self.graph.plotAreaFrame.paddingLeft = 60.0f;
// Tie the graph we've created with the hosting view.
self.hostingView.hostedGraph = self.graph;
// If you want to use one of the default themes - apply that here.
[self.graph applyTheme:[CPTTheme themeNamed:kCPTDarkGradientTheme]];
// Create a line style that we will apply to the axis and data line.
CPTMutableLineStyle *lineStyle = [CPTMutableLineStyle lineStyle];
lineStyle.lineColor = [CPTColor whiteColor];
lineStyle.lineWidth = 2.0f;
// Create a text style that we will use for the axis labels.
CPTMutableTextStyle *textStyle = [CPTMutableTextStyle textStyle];
textStyle.fontName = #"Helvetica";
textStyle.fontSize = 14;
textStyle.color = [CPTColor whiteColor];
// Create the plot symbol we're going to use.
CPTPlotSymbol *plotSymbol = [CPTPlotSymbol crossPlotSymbol];
plotSymbol.lineStyle = lineStyle;
plotSymbol.size = CGSizeMake(8.0, 8.0);
// Setup some floats that represent the min/max values on our axis.
int xAxisMin = 0;
int xAxisMax = 20;
float yAxisMin = 0;
float yAxisMax = 50;
// We modify the graph's plot space to setup the axis' min / max values.
CPTXYPlotSpace *plotSpace = (CPTXYPlotSpace *)self.graph.defaultPlotSpace;
plotSpace.xRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromInt(xAxisMin) length:CPTDecimalFromInt(xAxisMax-xAxisMin)];
plotSpace.yRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(yAxisMin) length:CPTDecimalFromFloat(yAxisMax - yAxisMin)];
// Modify the graph's axis with a label, line style, etc.
CPTXYAxisSet *axisSet = (CPTXYAxisSet *)self.graph.axisSet;
axisSet.xAxis.title = #"Time";
axisSet.xAxis.titleTextStyle = textStyle;
axisSet.xAxis.titleOffset = 20;
axisSet.xAxis.axisLineStyle = lineStyle;
axisSet.xAxis.majorTickLineStyle = lineStyle;
axisSet.xAxis.minorTickLineStyle = lineStyle;
axisSet.xAxis.labelTextStyle = textStyle;
axisSet.xAxis.labelOffset = 3;
axisSet.xAxis.majorIntervalLength = CPTDecimalFromInt(2);
axisSet.xAxis.minorTicksPerInterval = 1;
axisSet.xAxis.minorTickLength = 5;
axisSet.xAxis.majorTickLength = 7;
axisSet.yAxis.title = #"Temperature";
axisSet.yAxis.titleTextStyle = textStyle;
axisSet.yAxis.titleOffset = 40.0f;
axisSet.yAxis.axisLineStyle = lineStyle;
axisSet.yAxis.majorTickLineStyle = lineStyle;
axisSet.yAxis.minorTickLineStyle = lineStyle;
axisSet.yAxis.labelTextStyle = textStyle;
axisSet.yAxis.labelOffset = 3.0f;
axisSet.yAxis.majorIntervalLength = CPTDecimalFromFloat(10.0f);
axisSet.yAxis.minorTicksPerInterval = 1;
axisSet.yAxis.minorTickLength = 5.0f;
axisSet.yAxis.majorTickLength = 7.0f;
// Add a plot to our graph and axis. We give it an identifier so that we
// could add multiple plots (data lines) to the same graph if necessary.
CPTScatterPlot *plot = [[CPTScatterPlot alloc] init] ;
plot.dataSource = self;
plot.identifier = #"mainplot";
plot.dataLineStyle = lineStyle;
plot.plotSymbol = plotSymbol;
[self.graph addPlot:plot];
}
// Delegate method that returns the number of points on the plot
-(NSUInteger)numberOfRecordsForPlot:(CPTPlot *)plot
{
if ( [plot.identifier isEqual:#"mainplot"] )
{
return [self.graphData count];
}
return 0;
}
// Delegate method that returns a single X or Y value for a given plot.
-(NSNumber *)numberForPlot:(CPTPlot *)plot field:(NSUInteger)fieldEnum recordIndex:(NSUInteger)index
{
if ( [plot.identifier isEqual:#"mainplot"] )
{
NSValue *value = [self.graphData objectAtIndex:index];
CGPoint point = [value CGPointValue];
// FieldEnum determines if we return an X or Y value.
if ( fieldEnum == CPTScatterPlotFieldX )
{
return [NSNumber numberWithInt:point.x];
}
else // Y-Axis
{
return [NSNumber numberWithFloat:point.y];
}
}
return [NSNumber numberWithFloat:0];
}
In viewDidLoad i'm calling this method as follows:
pickerData=[[NSArray alloc]initWithObjects:#"28-02-2015",#"01-03-2015",#"02-03-2015",#"03-03-2015",#"04-03-2015", nil];
NSMutableArray *data1 = [NSMutableArray array];
[data1 addObject:[NSValue valueWithCGPoint:CGPointMake(0, 0)]];
self.scatterPlot = [[TUTSimpleScatterPlot alloc] initWithHostingView:_graphHostingView andData:data1];
[self.scatterPlot initialisePlot];
pickerView datasource and delegate methods as follows with dynamic data:
#pragma mark PickerView DataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return pickerData.count;
}
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return pickerData[row];
}
#pragma mark -
#pragma mark PickerView Delegate
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
//PickerModal *pModal=[picDataArray objectAtIndex:row];
pickObj=[picDataArray objectAtIndex:row];
//result=[NSString stringWithFormat:#"%#",pickObj.picDate];
NSLog(#"time :%#",pickObj.picTime);
NSLog(#"temp :%#",pickObj.picTemperature);
for (int i=0; i<50; i++) {
int selectedRow=[self.myPickerView selectedRowInComponent:0];
if ((selectedRow=i)) {
NSMutableArray *data1 = [NSMutableArray array];
[data1 addObject:[NSValue valueWithCGPoint:CGPointMake([pickObj.picTime floatValue], [pickObj.picTemperature floatValue])]];
NSMutableArray *arr=[[NSMutableArray alloc]initWithArray:data1];
self.scatterPlot = [[TUTSimpleScatterPlot alloc] initWithHostingView:_graphHostingView andData:arr];
[self.scatterPlot initialisePlot];
}
}
[pickerView reloadComponent:0];
}
i'm parsing json data as :
-(void)retrieveData{
NSString *sensorTagID=#"UIUIA6767672345678910987654321";
NSMutableString *globalUrlString=[NSMutableString stringWithString:#"url"];
[globalUrlString appendString:[NSString stringWithFormat:#"?SensorTagID=%#",sensorTagID]];
NSLog(#"url string:%#",globalUrlString);
NSURL *url=[NSURL URLWithString:globalUrlString];
NSMutableURLRequest *globalRequest=[NSMutableURLRequest requestWithURL:[url standardizedURL]];
[globalRequest setHTTPMethod:#"GET"];
NSError *error = nil;
NSURLResponse *theResponse = [[NSURLResponse alloc]init];
//connecting to the server
NSData *data = [NSURLConnection sendSynchronousRequest:globalRequest returningResponse:&theResponse error:&error];
//NSData *data=[NSData dataWithContentsOfURL:url];
json=[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
picDataArray=[[NSMutableArray alloc]init];
for (int i=0; i<json.count; i++) {
pickDate=[[json objectAtIndex:i]valueForKey:#"Date"];
NSLog(#"date %#",pickDate);
NSArray *getEvents=[[json objectAtIndex:i]valueForKey:#"OnDateSensorValues"];
for (NSDictionary *eventsObj in getEvents) {
pickHumidity=eventsObj[#"Humidity"];
//NSLog(#"humidity %#",pickHumidity);
pickLocationHumidity=eventsObj[#"LocationHumidity"];
//NSLog(#"locHumidity %#",pickLocationHumidity);
pickLocationTemperature=eventsObj[#"LocationTemperature"];
//NSLog(#"locTemp %#",pickLocationTemperature);
pickTemperature=eventsObj[#"Temperature"];
NSLog(#"temp %#",pickTemperature);
pickTime=eventsObj[#"Time"];
NSLog(#"time %#",pickTime);
}
pickObj=[[PickerModal alloc]initWithPicDate:pickDate andPicHumidity:pickHumidity andPicLocationHumidity:pickLocationHumidity andPicLocationTemperature:pickLocationTemperature andPicTemperature:pickTemperature andPicTime:pickTime];
[picDataArray addObject:pickObj];
}
[self.myPickerView reloadComponent:0];
}
json output as follows:
[
{
"Date": "2015-02-26",
"OnDateSensorValues": [
{
"Humidity": "49",
"LocationHumidity": "49",
"LocationTemperature": "45",
"Temperature": "45",
"Time": "10"
},
{
"Humidity": "48",
"LocationHumidity": "48",
"LocationTemperature": "44",
"Temperature": "44",
"Time": "11"
},
{
"Humidity": "47",
"LocationHumidity": "47",
"LocationTemperature": "43",
"Temperature": "43",
"Time": "12"
},
{
"Humidity": "46",
"LocationHumidity": "46",
"LocationTemperature": "42",
"Temperature": "42",
"Time": "13"
},
{
"Humidity": "45",
"LocationHumidity": "45",
"LocationTemperature": "41",
"Temperature": "41",
"Time": "14"
}
]
},
{
"Date": "2015-02-27",
"OnDateSensorValues": [
{
"Humidity": "29",
"LocationHumidity": "29",
"LocationTemperature": "25",
"Temperature": "25",
"Time": "6"
},
{
"Humidity": "28",
"LocationHumidity": "28",
"LocationTemperature": "24",
"Temperature": "24",
"Time": "7"
},
{
"Humidity": "27",
"LocationHumidity": "27",
"LocationTemperature": "23",
"Temperature": "23",
"Time": "8"
},
{
"Humidity": "26",
"LocationHumidity": "26",
"LocationTemperature": "22",
"Temperature": "22",
"Time": "9"
},
{
"Humidity": "25",
"LocationHumidity": "25",
"LocationTemperature": "21",
"Temperature": "21",
"Time": "10"
}
]
},
{
"Date": "2015-02-28",
"OnDateSensorValues": [
{
"Humidity": "31",
"LocationHumidity": "31",
"LocationTemperature": "35",
"Temperature": "35",
"Time": "22"
},
{
"Humidity": "32",
"LocationHumidity": "32",
"LocationTemperature": "36",
"Temperature": "36",
"Time": "21"
},
{
"Humidity": "33",
"LocationHumidity": "33",
"LocationTemperature": "37",
"Temperature": "37",
"Time": "20"
},
{
"Humidity": "34",
"LocationHumidity": "34",
"LocationTemperature": "38",
"Temperature": "38",
"Time": "19"
},
{
"Humidity": "35",
"LocationHumidity": "35",
"LocationTemperature": "39",
"Temperature": "39",
"Time": "18"
}
]
},
{
"Date": "2015-03-01",
"OnDateSensorValues": [
{
"Humidity": "12",
"LocationHumidity": "12",
"LocationTemperature": "16",
"Temperature": "16",
"Time": "2"
},
{
"Humidity": "13",
"LocationHumidity": "13",
"LocationTemperature": "17",
"Temperature": "17",
"Time": "1"
},
{
"Humidity": "14",
"LocationHumidity": "14",
"LocationTemperature": "18",
"Temperature": "18",
"Time": "2"
},
{
"Humidity": "15",
"LocationHumidity": "15",
"LocationTemperature": "19",
"Temperature": "19",
"Time": "3"
},
{
"Humidity": "16",
"LocationHumidity": "16",
"LocationTemperature": "20",
"Temperature": "20",
"Time": "4"
}
]
},
{
"Date": "2015-03-02",
"OnDateSensorValues": [
{
"Humidity": "32",
"LocationHumidity": "32",
"LocationTemperature": "36",
"Temperature": "36",
"Time": "20"
},
{
"Humidity": "33",
"LocationHumidity": "33",
"LocationTemperature": "37",
"Temperature": "37",
"Time": "21"
},
{
"Humidity": "34",
"LocationHumidity": "34",
"LocationTemperature": "38",
"Temperature": "38",
"Time": "22"
},
{
"Humidity": "35",
"LocationHumidity": "35",
"LocationTemperature": "39",
"Temperature": "39",
"Time": "23"
},
{
"Humidity": "36",
"LocationHumidity": "36",
"LocationTemperature": "40",
"Temperature": "40",
"Time": "24"
}
]
}
]
from here i would like to take temp,time values and show on graph. But i'm able to plot only one point on the graph. How to get all time and temp values on the graph?....Please help me as i'm struggling with the concept since 1week.
Related
Laravel- How to Remove a key from collection?
I have data as below: [ { "id": "3", "title": "Boruto's Photo", "is_lottery": 1, "price": 10 }, { "id": "4", "title": "Misuki's Photo", "is_lottery": 0, "price": 20 } ] I want to filter which is is_lottery == false remove the price key from this collection. The output is: [ { "id": "3", "title": "Boruto's Photo", "is_lottery": 1, "price": 10 }, { "id": "4", "title": "Misuki's Photo", "is_lottery": 0, } ]
You can do this $json = '[ { "id": "3", "title": "Boruto\'s Photo", "is_lottery": 1, "price": 10 }, { "id": "3", "title": "Misuki\'s Photo", "is_lottery": 0, "price": 20 } ]'; $filtered = collect(json_decode($json, true))->map(function ($array) { if (!$array['is_lottery']) { unset($array['price']); } return $array; }); For native PHP you can do $data = json_decode($json, true); foreach ($data as $index => $array) { if (!$array['is_lottery']) { unset($array['price']); } $data[$index] = $array; }
$json = [ { "id": "3", "title": "Boruto's Photo", "is_lottery": 1, "price": 10 }, { "id": "4", "title": "Misuki's Photo", "is_lottery": 0, "price": 20 } ]; $filtered = collect(json_decode($json))->map(function($value, $key) { if (!$value['is_lottery']) { Arr::except($value, 'price'); } return $value; });
you can declare new variable called $newCollection as final collection. Use foreach() to iterate your collection then delete the is_lottery from collection by using unset() then push it to $newCollection, this is example how you can delete it using foreach: $newCollection = []; foreach ($photos as $key => $value) { if ($value["is_lottery"] == 0) { unset($value["price"]); } array_push($newCollection,$value); } or you can try using forget to remove it from collection (not tested) from this ref: How to unset (remove) a collection element after fetching it?
swift get currencycode from country code
I find the accepted answer to get currencycode from country code in objective c here - How to get ISOCurrencyCode from a ISOCountryCode in iphone sdk? Can someone help with the swift code to do the same ?
let components: [String: String] = [NSLocaleCountryCode: "CA"] let identifier = NSLocale.localeIdentifierFromComponents(components) let locale = NSLocale(localeIdentifier: identifier) let currencyCode = locale.objectForKey(NSLocaleCurrencyCode) print(currencyCode)
public static func convertStringCurrencyToNumber(strCurrency:String, locale:String)->Double { var formatter = NSNumberFormatter() formatter.currencyCode = locale formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle if let converted:Double = formatter.numberFromString(strCurrency)?.doubleValue { return converted }else{ return 0.0 } } Changing formatter.locale to formatter.currencyCode works as expected with the ISO 4127 Country and Currency code "USD".
Use below this return type function to get country_code:- //MARK:- GET COUNTRY CODE func getCountryPhonceCode (_ country : String) -> String { let x : [String] = ["972", "IL", "93" , "AF", "355", "AL", "213", "DZ", "1" , "AS", "376", "AD", "244", "AO", "1" , "AI", "1" , "AG", "54" , "AR", "374", "AM", "297", "AW", "61" , "AU", "43" , "AT", "994", "AZ", "1" , "BS", "973", "BH", "880", "BD", "1" , "BB", "375", "BY", "32" , "BE", "501", "BZ", "229", "BJ", "1" , "BM", "975", "BT", "387", "BA", "267", "BW", "55" , "BR", "246", "IO", "359", "BG", "226", "BF", "257", "BI", "855", "KH", "237", "CM", "1" , "CA", "238", "CV", "345", "KY", "236", "CF", "235", "TD", "56", "CL", "86", "CN", "61", "CX", "57", "CO", "269", "KM", "242", "CG", "682", "CK", "506", "CR", "385", "HR", "53" , "CU" , "537", "CY", "420", "CZ", "45" , "DK" , "253", "DJ", "1" , "DM", "1" , "DO", "593", "EC", "20" , "EG" , "503", "SV", "240", "GQ", "291", "ER", "372", "EE", "251", "ET", "298", "FO", "679", "FJ", "358", "FI", "33" , "FR", "594", "GF", "689", "PF", "241", "GA", "220", "GM", "995", "GE", "49" , "DE", "233", "GH", "350", "GI", "30" , "GR", "299", "GL", "1" , "GD", "590", "GP", "1" , "GU", "502", "GT", "224", "GN", "245", "GW", "595", "GY", "509", "HT", "504", "HN", "36" , "HU", "354", "IS", "91" , "IN", "62" , "ID", "964", "IQ", "353", "IE", "972", "IL", "39" , "IT", "1" , "JM", "81", "JP", "962", "JO", "77", "KZ", "254", "KE", "686", "KI", "965", "KW", "996", "KG", "371", "LV", "961", "LB", "266", "LS", "231", "LR", "423", "LI", "370", "LT", "352", "LU", "261", "MG", "265", "MW", "60", "MY", "960", "MV", "223", "ML", "356", "MT", "692", "MH", "596", "MQ", "222", "MR", "230", "MU", "262", "YT", "52","MX", "377", "MC", "976", "MN", "382", "ME", "1", "MS", "212", "MA", "95", "MM", "264", "NA", "674", "NR", "977", "NP", "31", "NL", "599", "AN", "687", "NC", "64", "NZ", "505", "NI", "227", "NE", "234", "NG", "683", "NU", "672", "NF", "1", "MP", "47", "NO", "968", "OM", "92", "PK", "680", "PW", "507", "PA", "675", "PG", "595", "PY", "51", "PE", "63", "PH", "48", "PL", "351", "PT", "1", "PR", "974", "QA", "40", "RO", "250", "RW", "685", "WS", "378", "SM", "966", "SA", "221", "SN", "381", "RS", "248", "SC", "232", "SL", "65", "SG", "421", "SK", "386", "SI", "677", "SB", "27", "ZA", "500", "GS", "34", "ES", "94", "LK", "249", "SD", "597", "SR", "268", "SZ", "46", "SE", "41", "CH", "992", "TJ", "66", "TH", "228", "TG", "690", "TK", "676", "TO", "1", "TT", "216", "TN", "90", "TR", "993", "TM", "1", "TC", "688", "TV", "256", "UG", "380", "UA", "971", "AE", "44", "GB", "1", "US", "598", "UY", "998", "UZ", "678", "VU", "681", "WF", "967", "YE", "260", "ZM", "263", "ZW", "591", "BO", "673", "BN", "61", "CC", "243", "CD", "225", "CI", "500", "FK", "44", "GG", "379", "VA", "852", "HK", "98", "IR", "44", "IM", "44", "JE", "850", "KP", "82", "KR", "856", "LA", "218", "LY", "853", "MO", "389", "MK", "691", "FM", "373", "MD", "258", "MZ", "970", "PS", "872", "PN", "262", "RE", "7", "RU", "590", "BL", "290", "SH", "1", "KN", "1", "LC", "590", "MF", "508", "PM", "1", "VC", "239", "ST", "252", "SO", "47", "SJ", "963","SY", "886", "TW", "255", "TZ", "670", "TL","58", "VE","84", "VN", "284", "VG", "340", "VI", "678","VU", "681","WF", "685","WS", "967","YE", "262","YT", "27","ZA", "260","ZM", "263","ZW"] var keys = [String]() var values = [String]() let whitespace = CharacterSet.decimalDigits //let range = phrase.rangeOfCharacterFromSet(whitespace) for i in x { // range will be nil if no whitespace is found if (i.rangeOfCharacter(from: whitespace) != nil) { values.append(i) } else { keys.append(i) } } let countryCodeListDict = NSDictionary(objects: values as [String], forKeys: keys as [String] as [NSCopying]) if let t: AnyObject = (countryCodeListDict as? [String : AnyObject])? [country] { return countryCodeListDict[country] as! String } else { return "" } }
Elasticsearch Scripting: updating array value
This is my document { "name": "andrew", "b": [{"x":"c1", "y": 0}, {"x":"c2", "y": 0}] } I want to find element in the array field "b" and update the entire object. I tried this script but it does not update. Any ideas? { "script": "for (item in ctx._source.b) { if (item['x'] == x_id) { item = newobj; } };", "params": { "x_id": "c1", "newobj" : {"x":"c1", "y": 4222} }, "lang":"groovy" }
Use this instead: { "script": "for (int i=0;i<ctx._source.b.size();i++) { item=ctx._source.b[i]; if (item['x'] == x_id) { ctx._source.b[i] = newobj} };", "params": { "x_id": "c1", "newobj": { "x": "c1", "y": 4222 } }, "lang": "groovy" }
How to convert hierarchical list to flat list?
Usually we convert flat list to hierarchical list but in my case I want to convert hierarchical list to flat list. I have a hierarchical list<T> and I want convert this hierarchical list into flat list<T> class. Let's say I have a below hierarchical list Parent1 --- Child1 ,F1 ----Child2, F2 ----Child2, F3 Parent2 ----Child2,F2 ----Child4,F6 Parent3 --- Child1 ,F1 I need output like below: Parent1, Child1,F1 Parent1, Child2,F2 Parent1, Child2,F3 Parent2,Child2,F2 Parent2,Child4, F6 Parent3, Child1,F1
It may not be the most optimized solution (it could be further minimized I think, and I have a more concise version - but this form is something I'm using the most) It's what I've been using public static IEnumerable<T> FlattenHierarchy<T>(this T node, Func<T, IEnumerable<T>> getChildEnumerator) { yield return node; if (getChildEnumerator(node) != null) { foreach (var child in getChildEnumerator(node)) { foreach (var childOrDescendant in child.FlattenHierarchy(getChildEnumerator)) { yield return childOrDescendant; } } } } and you can use it like folder.FlattenHierarchy(x => x.SubFolders)
Finally i got the solution: public class RNode { public string Id; public long ID; public string name; public string subTitle; public IList<RNode> children; } public class FlatObj //For Data format { public long Id; public long ParentId; public long Position; public string name; public string subTitle; } List<FlatObj> GlobalFlatObj = new List<FlatObj>(); List<long> ParentIdList = new List<long>(); long CurrentParentId=0; long CurrentPosition = 0; public List<FlatObj> FlatData(IList<RNode> HData) //Converting Heirarchical to Flat { foreach (RNode node in HData) { FlatObj ObjFlatObj = new FlatObj(); ObjFlatObj.Id = node.ID; ObjFlatObj.name = node.name; ObjFlatObj.ParentId = CurrentParentId; ObjFlatObj.Position = CurrentPosition; GlobalFlatObj.Add(ObjFlatObj); if (node.children.Count > 0) { CurrentParentId = node.ID; ParentIdList.Add(node.ID); FlatData(node.children); } CurrentPosition++; } if (ParentIdList.Count > 0) { ParentIdList.RemoveAt(ParentIdList.Count - 1); if (ParentIdList.Count > 0) CurrentParentId = ParentIdList[ParentIdList.Count - 1]; CurrentPosition = 0; } return GlobalFlatObj; } public dynamic Test(List<RNode> EmployeeHierarchy) { var HierarchyResult = FlatData(EmployeeHierarchy); //Calling return Ok(HierarchyResult); } Input: [ { "$id": "1", "ID": 1, "name": "root", "subTitle": "root", "children": [ { "$id": "2", "ID": 2, "name": "child 1", "subTitle": "child 1", "children": [ { "$id": "3", "ID": 5, "name": "grandchild", "subTitle": "grandchild", "children": [] }] }, { "$id": "4", "ID": 3, "name": "child 2", "subTitle": "child 2", "children": [] }, { "$id": "5", "ID": 4, "name": "child 3", "subTitle": "child 3", "children": [] } ] } ] Output: [ { "$id": "1", "Id": 1, "ParentId": 0, "Position": 0, "name": "root", "subTitle": null }, { "$id": "2", "Id": 2, "ParentId": 1, "Position": 0, "name": "child 1", "subTitle": null }, { "$id": "3", "Id": 5, "ParentId": 2, "Position": 0, "name": "grandchild", "subTitle": null }, { "$id": "4", "Id": 3, "ParentId": 1, "Position": 1, "name": "child 2", "subTitle": null }, { "$id": "5", "Id": 4, "ParentId": 1, "Position": 2, "name": "child 3", "subTitle": null } ]
Getting rendered date range from axis with NVD3
I'm using NVD3 to display of a number of line charts and would like to be able to get the min and max values of the xAxis currently displayed. In this case the xAxis shows time values. When toggling the visibility of lines in the chart, by clicking the legend label, the date range is changed. I've added an event handler to listen to legendClicks but how do I get my hands on the newly rendered date range?
I ended up using a custom function to find the min/max values of the x axis when clicking the legend. I wrapped the function within a $timeout in order to wait for the digest cycle to be completed to get the proper value, ie: legend: { dispatch: { legendClick: function(e) { $timeout(function(){ getMinMax(); }, 0); } } }, The getMinMax function is a quick and dirty one and may most likely be done in a more elegantly manner, however it does its job: var getMinMax = function(){ var maxVal, minVal = null; for(var i=0;i<$scope.data.length;i++) { // Only displayed should be considered if (!$scope.data[i].disabled) { var tempMinVal = d3.max($scope.data[i].values, function(d) { return d.x;} ); var tempMaxVal = d3.min($scope.data[i].values, function(d) { return d.x;} ); minVal = (!minVal || tempMinVal < minVal) ? tempMinVal : minVal; maxVal = (!maxVal || tempMaxVal > maxVal) ? tempMaxVal : maxVal; } } return [minVal, maxVal]; }; Will get the min and max from the data in this format: [ { "key": "AA", "values": [ { "x": 1440712800000, "y": "6", "series": 0 }, { "x": 1440712800000, "y": "6", "series": 0 } ] }, { "key": "BB", "values": [ { "x": 1441144800000, "y": "3", "series": 1 }, { "x": 1443045600000, "y": "3", "series": 1 }, { "x": 1453244400000, "y": "3", "series": 1 }, { "x": 1454022000000, "y": "3", "series": 1 } ] }, { "key": "CC", "values": [ { "x": 1442872800000, "y": "5", "series": 2 }, { "x": 1442872800000, "y": "5", "series": 2 } ] }, { "key": "DD", "values": [ { "x": 1443650400000, "y": "1", "series": 3 }, { "x": 1443650400000, "y": "1", "series": 3 } ] }, { "key": "EE", "values": [ { "x": 1444773600000, "y": "9", "series": 4 }, { "x": 1446073200000, "y": "9", "series": 4 } ] } ] As I reached this far the client changed mind and didn't want the functionality that required this solution. Hope it may be of use for someone else.