patternjavascriptMinor
Passing JSON object through loop to be used in jQuery Dialog
Viewed 0 times
passingusedloopjquerydialogthroughjsonobject
Problem
I'm wondering if there is a better (cleaner?) method than my current implementation. I'm currently encoding a PHP
Examples from my current implementation below:
Function to display dialog implemented anonymously outside of
Main loop for displaying Tracking ID, Most Recent Event, and Mail Class for each API response- I'm currently generating a content div appended to
As I'm sure you can see, this feels like an incredibly tedious way of accomplishing the desired outcome, to which there is surely a better alternative. As a newcomer to JavaScript/jQuery, I've done pl
SimpleXMLObject (USPS Tracking API) to JSON and looping through said JSON object via JavaScript to operate the front-end.Examples from my current implementation below:
Function to display dialog implemented anonymously outside of
.ready():var moreInfo_popup = function(i) {
$('#moreinfo'+i).dialog({
modal:false,
autoOpen:false,
height:555,
title: 'Detailed View',
width:500,
draggable:false,
buttons: {
Ok: function(){
$(this).dialog("close");
}
}
});
$('#moreinfo'+i).dialog('open');
}Main loop for displaying Tracking ID, Most Recent Event, and Mail Class for each API response- I'm currently generating a content div appended to
#modal_container, then calling moreInfo_popup() inline via ``:for(var key in obj) {
if(obj.hasOwnProperty(key)) {
if(key % 2 === 0) {
$('#page-nav').append(""+obj[key].TrackInfo.Attributes.ID+""+obj[key].TrackInfo.StatusSummary+""+obj[key].TrackInfo.Class+"");
$('#modal_container').append("" + obj[key].TrackInfo.Attributes.ID +"").hide();
}
else {
$('#page-nav').append(""
+ obj[key].TrackInfo.Attributes.ID + "" + obj[key].TrackInfo.StatusSummary + ""
+ obj[key].TrackInfo.Class + "");
$('#modal_container').append("" + obj[key].TrackInfo.Attributes.ID +" OK");
}
}
$("#page-nav td:contains('undefined')").html("Invalid");
}As I'm sure you can see, this feels like an incredibly tedious way of accomplishing the desired outcome, to which there is surely a better alternative. As a newcomer to JavaScript/jQuery, I've done pl
Solution
The key problem I have with your code right now is that it doesn't separate data from presentation. This is a maintainability issue because it means now your data is inexplicably tied to your view, and you cannot change one without altering the other. How can we fix this?
As someone earlier suggested, you could use a template library. When I'm doing stand-alone development (i.e, not using a framework), I really like rivets. It's lightweight (6.2kb), simple and unopinionated.
I would have recommended dropping jQuery, but I see that you're using a plugin for jQuery, so I can't really suggest that. I would say that if you can find a way to avoid using jQuery here, that would be great. The reason I don't want you using jQuery is because it's a heavyweight library; it's 34kb, which is over 5x the size of Rivets.
The time-to-last-byte is very important in JavaScript development because until your consumer has received the last byte, your JavaScript is doing nothing, which potentially makes part of your site unusuable. As such, if you can remove any cruft from your site to make it load all of the script tags faster, the better off you will be.
First, we'll define a HTML layout for your tracking info. As your tracking info is tangential to the current information, we can make this use the `
As someone earlier suggested, you could use a template library. When I'm doing stand-alone development (i.e, not using a framework), I really like rivets. It's lightweight (6.2kb), simple and unopinionated.
I would have recommended dropping jQuery, but I see that you're using a plugin for jQuery, so I can't really suggest that. I would say that if you can find a way to avoid using jQuery here, that would be great. The reason I don't want you using jQuery is because it's a heavyweight library; it's 34kb, which is over 5x the size of Rivets.
The time-to-last-byte is very important in JavaScript development because until your consumer has received the last byte, your JavaScript is doing nothing, which potentially makes part of your site unusuable. As such, if you can remove any cruft from your site to make it load all of the script tags faster, the better off you will be.
First, we'll define a HTML layout for your tracking info. As your tracking info is tangential to the current information, we can make this use the `
HTML element.
ID
Summary
Class
Detail
So above is the basic structure of your dialog. There's a lot of inline styling, and the only thing your "if" statement is for is to add alternating classes. No need to do that here! We can do that in CSS just fine. First of all, lets apply your styles with a bit of CSS. We'll add a .data-table class to your table, although I would definitely recommend naming it something more descriptive; .data-table is pretty ambigious. You want to describe the role this thing fulfills, not what it is. In other words, be more declarative with your css names. In addition, we'll add a .results-table class to the encapsulating . Whilst I'm not sure this is completely correct, it appears to be closest to what you are doing.
First, let's tackle the overarching styles of each of the tables:
.data-table {
border: 0;
width: 60%;
align: center;
}
You'll notice I have not included the styling. This is because the width of a is decided by the browser and not the CSS. This makes sense if you are using truly tabular data. If you're not using tabular data (and I suspect you're not), then you should use a . are definition lists which may be more suited for this sort of thing.
You appear to have some kind of alternate styling based on whether or not a .data-table is an even .data-table. I'm not sure what this styling is because it isn't supplied, but you can replicate this class by using the following CSS selector:
.results-table:nth-child(even) {
// some CSS styling here
}
So far, we have this:
Detail
Now, your data model looks something like this:
var model = {
someNumericValue: {
TrackInfo: {
Attributes: {
ID: 0
},
StatusSummary: "summary",
Class: "first"
}
}
};
Wow, this looks a lot like an array! It might be, or it might not be. It's hard to tell because arrays are actually objects. This means that they have access to the hasOwnProperty of an object. Lets assume it is an array because that makes more sense.
var models = [
{
TrackInfo: {
Attributes: {
ID: 0
},
StatusSummary: "summary",
Class: "first"
}
}
];
With this data model, we can easily slot this into our template using rivets bindings. Lets take a look at how it pans out (I've skipped the popup at the moment, we'll get into that in a bit).
Detail
Now when we set up rivets on this element, as long as we pass in all of our models to "models" - voila, you'll have data binding. Of course, this isn't 100% perfect because we're still relying on our JavaScript to populate the data, however it's a good start; the HTML structure is there and it's declarative. Anyone reading over this file with some knowledge of how rivets works would be able to tell what this does, and the HTML isn't hidden away in JavaScript - the only thing we're getting from JavaScript is the repeating behaviour and the values. This is a good shift!
How would you use this, you might ask? Well, to bind the to data, it really is as simple as this:
var dialog = document.querySelector('aside.results-table');
rivets.bind(dialog, { order: models });
Where, obviously, models` is your array of data. This will ensure that all of your data is bound correctly. Note that this is only one-way data binding though, so any changes you make (DOM -> Model, such as a form) will not be reflected in the change to the view - only modeCode Snippets
<aside>
<table>
<tr>
<td>ID</td>
<td>Summary</td>
<td>Class</td>
<td>
<button>Detail</button>
</td>
</tr>
</table>
</aside>.data-table {
border: 0;
width: 60%;
align: center;
}.results-table:nth-child(even) {
// some CSS styling here
}<aside class='results-table'>
<table class='data-table'>
<tr>
<td></td>
<td></td>
<td></td>
<td>
<button>Detail</button>
</td>
</tr>
</table>
</aside>var model = {
someNumericValue: {
TrackInfo: {
Attributes: {
ID: 0
},
StatusSummary: "summary",
Class: "first"
}
}
};Context
StackExchange Code Review Q#103808, answer score: 5
Revisions (0)
No revisions yet.