Sort JSON data by Date/Time value - json

Hope someone could help with this small task. I have an array of text blocks that have a DateTime value assigned to them. I would like to publish those text blocks sorted by DateTime so that the latest updated item is always on top.
Here is the script:
function jsonCallBack(data) {
var strRows = "";
$.each(data.News, function(i, item) {
var htmlNewsBody = item["htmlNewsBody"];
var maxLength = 120
var trimmedString = htmlNewsBody.substr(0, maxLength);
trimmedString = trimmedString.substr( 0, Math.min( trimmedString.length,
trimmedString.lastIndexOf(" ") ) );
strRows += "<div id='nrNewsItem-" + i + "'>";
strRows += "<h3>" + item["txtTitle"] + "</h3>";
strRows += "<p>" + item["dtDateTime"] + "</p>";
strRows += "<p>" + trimmedString + "...</p>";
strRows += "</div>"
});
$("#printHere").html(strRows);
};
Also have a working jsFiddle with JSON data.

You can add a custom compare method:
function compare(a,b) {
if (a.dtDateTime < b.dtDateTime) {
return 1;
}
if (a.dtDateTime > b.dtDateTime) {
return -1;
}
return 0;
}
Then in your function:
function jsonCallBack(data) {
data.News.sort(compare);
....

Related

Convert JSON data to table

I am trying to create table from my JSON data which looks like this:
It works for a specific JSON data:
var items = [
{"Name":"A","Type":2,"Result":"0"},
{"Name":"A","Type":1,"Result":"1"},
{"Name":"B","Type":2,"Result":"1"},
{"Name":"B","Type":1,"Result":"0"},
]
But, it doesn't create table correctly if the columns ("Type") is random
var items = [
{"Name":"A","Type":5,"Result":"1"}
{"Name":"A","Type":2,"Result":"0"},
{"Name":"A","Type":1,"Result":"1"},
{"Name":"B","Type":3,"Result":"1"},
{"Name":"B","Type":2,"Result":"1"},
{"Name":"B","Type":1,"Result":"0"},
]
Can someone tell me what's the issue with my code?
I want to create table for dynamic JSON data which may not have cell values for all the columns. With this code, I don't see entry in column 5 for A as 1.
function get_prop(obj, prop) {
return prop.split('.').reduce((o,k) => obj[k], obj);
}
function coll2tbl(json, row_header, col_header, cell) {
var table = {};
var row_headers = [];
var cols = {};
json.map(function(a) {
var h = get_prop(a, row_header);
if (h in table === false) {
table[h] = {};
row_headers.push(h);
}
var c = get_prop(a, col_header);
cols[c] = null;
table[h][c] = get_prop(a, cell);
});
var cells = [];
for (var row in table) {
cells.push(Object.values(table[row]));
}
console.log('row_headers' + row_headers);
console.log('Object.keys(cols)' + Object.keys(cols));
console.log('cells' + cells);
var headerRow = '<th>' + capitalizeFirstLetter('TestName') + '</th>';
var colKeys = Object.keys(cols);
colKeys.map(function(col) {
headerRow += '<th>' + capitalizeFirstLetter(col) + '</th>';
});
var bodyRows = '';
for (var i in cells) {
bodyRows += '<tr>';
bodyRows += '<td>' + row_headers[i] + '</td>';
for (var j in cells[i]) {
console.log('Processing row: ' + row_headers[i] + ' result: ' + cells[i][j] + ' i=' + i + ' j=' + j);
bodyRows += '<td>';
if (cells[i][j] === "1") {
bodyRows += '<font color="green">' + cells[i][j] + '</font>';
}
else if (cells[i][j] === "0") {
bodyRows += '<font color="red">' + cells[i][j] + '</font>';
}
else if (cells[i][j] === "-1") {
bodyRows += '<font color="orange">' + cells[i][j] + '</font>';
}
else {
bodyRows += "-";
}
bodyRows += '</td>';
}
bodyRows += '</tr>';
}
//return { row_headers, col_headers: Object.keys(cols), cells };
return ('<table> <thead><tr>' + headerRow + '</tr></thead><tbody>' + bodyRows + '</tbody></table>');
}
function capitalizeFirstLetter(string) {return
string.charAt(0).toUpperCase() + string.slice(1);
}
coll2tbl(items, 'Name', 'Type', 'Result');
My table should like like this:
Name 1 2 3 4 5
A 1 1 - - 1
B 1 1 1 - -
The answer https://stackoverflow.com/a/52199138/10320683 is of course correct, but if you need or want to stick to your specific code, you can put this below your json.map (which should by the way use forEach and not map, since you do not use the returned array anyways)
for (var col in cols) {
for (row in table) {
if (!table[row].hasOwnProperty(col)) {
table[row][col] = "-";
}
}
}
The reason why your code did not work is that by iterating over the rows, you do not get all the possible type properties, which becomes clear if you inspect your table variable: { a: {1: "1", 2: "0", 5: "1"}, b: {...}} (this is missing the 3 type property), so by calling Object.values(table[row]) later on, you get the following array for your cells: ["1", "0", "1"], but you do have 4 columns, so the "Type 5" result (1) gets shifted one column to the left.
Also, you need to be careful because your code is relying on the sorting that Object.values() produces, which means that if you want to change the order of your columns, your code would not work.

Using recursion, how do you iterate over an object to produce HTML?

I am trying to sort an object of key:values recursively. It seems to work , at least to the console. The code takes the object and iterates over the key value pairs. If it finds another object it calls itself to iterate over that object. The problem I have is that the subsequent call doesn't seem to produce any html, but it does show the key value pairs in the console. This is my first attempt at recursion, I'm not sure if it's the way I'm declaring variables or if I'm missing something in how recursion works.
$(document).ready(function(){
let conditionReport = {
weekNo:"5",
laps:"8",
heat:"6",
feature:"9",
tireSize:
{lf:"15",lr:"16",rf:"16.5",rr:"17"},
airPressure:
{lf:"8",lr:"10",rf:"12",rr:"16"},
tireTemperature:
{lf:"9",lr:"11",rf:"13",rr:"15"},
suspensionAdjustment:
{lf:"4",lr:"5",rf:"6",rr:"7"},
engineRPM:"2000",
trackCondition:"4",
damage2car:"3",
suspensionAdjustment2:
{upper:
{lf:"4",lr:"5",rf:"6",rr:"7"},
lower:
{lf:"4",lr:"5",rf:"6",rr:"7"},
},
notes:"note 3"
}
s = x => document.getElementById(x);
const isObject = val => (typeof val === "object") ? true : false;
const getKeyValue = (obj) => {
let html = '<ul>';
for(let key in obj) {
let value = obj[key]
if(!isObject(value)){
//console.log(isObject(value));
console.log(key + ":" + value);
html += '<li>' + key + ":" + value + "</li>";
}
else{
if(isObject(value)){
//console.log(isObject(value));
console.log(key + "=>");
getKeyValue(value);
html += '<li>' + key + ":"+ "</li>";
}
}
}
html += "</ul>";
s('cards').innerHTML = html;
}
getKeyValue(conditionReport);
});
Use return values:
const getKeyValue = (obj) => {
let html = '<ul>';
for (let key in obj) {
let value = obj[key]
if (!isObject(value)) {
html += '<li>' + key + ":" + value + "</li>";
} else {
var innerValue = getKeyValue(value);
// ^^^^^^^^^^^^^^^^
html += '<li>' + key + ":"+ innerValue + "</li>";
// ^^^^^^^^^^
}
}
html += "</ul>";
return html;
// ^^^^^^
}
Then do
s('cards').innerHTML = getKeyValue(conditionReport);

AS3: How to check, all zip files has been extracted?

How to check all zip files has been extracted?
var reader: ZipFileReader = new ZipFileReader();
reader.addEventListener(ZipEvent.ZIP_DATA_UNCOMPRESS, zipDataUncompressHandler);
var zipFile: File = new File(zipFilePath);
reader.open(zipFile);
var list: Array = reader.getEntries();
zipFileCount = list.length;
trace(zipFileCount + " Numbers of items");
for each(var entry: ZipEntry in list) {
var filename: String = entry.getFilename();
if (entry.isDirectory()) {
trace("DIR --->" + filename);
} else {
trace("FILE --->" + filename + "(" + entry.getCompressRate() + ")");
reader.unzipAsync(entry);
}
zipFileWritedCount = zipFileWritedCount + 1;
}
function zipDataUncompressHandler(e: ZipEvent): void {
var entry: ZipEntry = e.entry;
var zfile: File = File.userDirectory.resolvePath('somefolder' + File.separator + entry.getFilename());
var fs: FileStream = new FileStream();
fs.open(zfile, FileMode.WRITE);
fs.writeBytes(e.data);
fs.close();
trace("Refresh Scene");
//include "RefreshScene.as";
}
My files were extracted, but I need to check all files are actually extracted.
Is there any way i can do that.
And I am using airxzip while working with zip file.
Also if I can add an loader.
You can shorten zipFileWritedCount = zipFileWritedCount + 1;
By using just a zipFileWritedCount +=1; or even
zipFileWritedCount++;
Anyways for checking the "all files extracted" amount you could try
the Equality == operator as mentioned in the manual.
Quick example :
for each(var entry: ZipEntry in list)
{
var filename: String = entry.getFilename();
if ( entry.isDirectory() ) { trace("DIR --->" + filename); }
else
{
trace("FILE --->" + filename + "(" + entry.getCompressRate() + ")");
reader.unzipAsync(entry);
}
zipFileWritedCount += 1; //add plus 1
if ( zipFileWritedCount == zipFileCount ) //if Equal to zipFileCount..
{
trace ("unzipped all files...");
trace ("zipFileCount: " + zipFileCount + " -VS- " + "zipFileWritedCount: " + zipFileWritedCount )
}
}

How do I make a JSON object produce HTML on the page

Here is my JSON
var gal = [
{
"folder":"nu_images",
"pic":"gd_42.jpg",
"boxclass":"pirobox_gall",
"alt":"Rand Poster 1",
"title":"Rand Poster 1",
"thfolder":"th",
"thumbpic":"th_gd_42.jpg"
},
{
"folder":"nu_images",
"pic":"gd_13.jpg",
"boxclass":"pirobox_gall",
"alt":"Explosive Pixel Design",
"title":"Explosive Pixel Design",
"thfolder":"th",
"thumbpic":"th_gd_13.jpg"
}
];
and here is my for loop
for (i = 0; i < gal.length; i++) {
document.getElementById("gallery").innerHTML = "" + "<img src=\"" + "http:\/\/galnova.com\/" + gal[i].folder + "\/" + "th\/" + gal[i].thumbpic + "\"" + "border=\"0\"" + "alt=\"" + gal[i].alt + "\"" + "title=\"" + gal[i].title + "\"\/>" + ""
};
I am trying to make my JSON show all of the objects in HTML one after the other. I can get it to show the first one or whatever number I put into the array but I don't know how to make it generate a list of them.
Here is a link to my jsfiddle. Any help you can offer would be greatly appreciated.
http://jsfiddle.net/o7cuxyhb/10/
It's being generated here <p id="gallery"></p> just not correctly.
You're overwriting your html with every loop iteration:
document.getElementById("gallery").innerHTML = ...
^---
Perhaps you want something more like
document.getElementById("gallery").innerHTML += ...
^---
which will concatenation the original html contents with your new stuff.
And technically, you shouldn't be doing this in a loop. Changing .innerHTML like that causes the document to be reflowed/re-rendered each time you change .innerHTML, which gets very expensive when you do it in a loop. You should be building your html as a plain string, THEN adding it to the dom.
e.g.
var str = '';
foreach(...) {
str += 'new html here';
}
document.getElementById("gallery").innerHTML += str;
for (i = 0; i < gal.length; i++) {
document.getElementById("gallery").innerHTML += "" + "<img src=\"" + "http:\/\/galnova.com\/" + gal[i].folder + "\/" + "th\/" + gal[i].thumbpic + "\"" + "border=\"0\"" + "alt=\"" + gal[i].alt + "\"" + "title=\"" + gal[i].title + "\"\/>" + "" };
Add a += instead of an = after innerHTML
Try this:
function displayJson(jsonArray){
var container = document.getElementById("gallery");
for (var i=0; i<jsonArray.length; i++){
var newElement = document.createElement("a").innerHTML = jsonToHtml(jsonArray[i])
container.appendChild(newElement);
}
}
function jsonToHtml(jsonObj){
//Define your dom object here
var el = document.createElement("a").innerHTML = '' // you code here
...
return el;
}
displayJson(gal);

How to elegantly plot charts in ASP.NET MVC 3 using Highcharts?

I've been working with highcharts and MVC 3 for two years by now (I never done anything complicated, just load data and make it work stuff), and I worked with two different scenarios:
Chart code written in the directly in the view, loading data through Json
Html helper responsible to plot the chart
The Html helper approach seems to me a more elegant choice ... but then, just to illustrate to you guys, here is how it looks like (just part of it):
public static string DisplayChart(
this HtmlHelper helper,
ChartOptions options,
TimedChartSeries[] data)
{
string[] axisList = data.GroupBy(t => t.Unit).Select(t => t.Key).ToArray();
string result = "";
result += "<script type=\"text/javascript\">\n";
result += "var " + options.ChartName + ";\n";
result += "$(document).ready(function() {\n";
result += options.ChartName + "= new Highcharts.Chart({\n";
result += "chart: {renderTo: '" + options.DivName + "',zoomType: ''},\n";
result += "title: { text: '" + options.Title + "'},\n";
result += "subtitle: {text: '" + options.SubTitle + "'},\n";
result += "xAxis: { type: 'datetime'," +
"\n dateTimeLabelFormats: {month: '%e. %b', year: '%b' },"
+ "labels:{rotation: -45}\n},\n";
string axes = "";
for (int i = 0; i < axisList.Length; i++)
{
var temporaryData = data.First(t => t.Unit == axisList[i]);
if (i != 0)
axes += ", ";
axes += "{labels:{\n " +
"formatter : function(){return this.value + '" + temporaryData.Unit + "';},\n" +
"style:{color:'#" + temporaryData.Color.Name.Remove(0, 2) + "'}},\n" +
"title:{text:'',style:{color:'#" + temporaryData.Color.Name.Remove(0, 2) + "'}},\n" +
"}\n";
}
result += "yAxis: [\n" + axes + "],\n";
string units = "";
for (int i = 0; i < data.Length; i++)
{
if (i != 0)
units += ", ";
units += "'" + data[i].Title + "': '" + data[i].Unit + "'\n";
}
result += "tooltip:{\nshared: true,\n backgroundColor: 'none' ,\nborderColor: 'none'," +
"\nshadow:false\n ,crosshairs: true,\n" +
"formatter: function() {var s = '<table class=\"table-list\"><tr><th>Hora</th><th>'+ test(this.x) +'</th></tr>';" +
"\n$.each(this.points, function(i, point) {" +
"\ns += '<tr><td>'+point.series.name + '</td><td>'+point.y+'</td></tr>'});s+='</table>';" +
"\n$('#tooltip').html(s);}},";
result += "lang: {" +
"months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho'," +
"'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro']," +
"weekdays: ['Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado']},";
string series = "";
int x = 0;
for (int j = 0; j < axisList.Length; j++)
{
var temporaryData = data.Where(t => t.Unit == axisList[j]).ToArray();
for (int i = 0; i < temporaryData.Length; i++)
{
if (x > 0)
series += ", ";
series += "{name: '" + temporaryData[i].Title + "',\n color: '#" + temporaryData[i].Color.Name.Remove(0, 2) +
"', \ntype: '" + temporaryData[i].Type + "',\nunit:'" + temporaryData.First().Unit + "', \nyAxis:" + j + " , \ndata:[" + FromArrayToString(temporaryData[i].Data) +
"], marker: { enabled: false}}\n";
x++;
}
}
result += "series: [\n" + series + "]\n";
result += "});});";
result += "\nfunction test(i)\n{\nvar j = new Date(i + 2*60*60*1000);\n" +
"return new Date(i + 3*60*60*1000).format('d/m/Y H:i:s.')+j.getMilliseconds();\n}\n</script>";
result += "\n<div id=\"" + options.DivName + "\" style=\"width:" + options.Width + ";height: " + options.Height + "\"></div>" +
"<div id=\"tooltip\"></div>";
return result;
}
It's really simple to call this helper:
#Html.Raw(Html.DisplayChart((ChartOptions)Model.Options,(TimedChartSeries[])Model.Series))
As you guys can see, I have to use the Html.Raw helper in order to make it work ... that is problem nº 1 (and it probably has an easy solution). But the second problem is really great: the chart becomes entirely tied to my domain. If I wanted to plot a, say, bar chart displaying data of the last 3 years in months (each month being represented by a bar), it would be impossible to use this helper.
And it also looks kind of ugly.
So, guys, which option do you think is more elegant, the Json or the Helper approach?
About the use of Html.Raw and the easy solution:
Change your function to
public static HtmlString DisplayChart(this HtmlHelper helper, ...)
{
...
return new HtmlString(result);
}
You then may use #Html.DisplayChart(...) in your razor views.
Also, please make sure that options.DivName, options.Title, options.SubTitle etc. are properly escaped - a title like Everybody's favorite chart will break the output.