How to create complex javascript object for JSON API - javascript

Below is the structure of JSON which I use to query an API
"order_items": [
{
"menu_item_id": "VD1PIEBIIG",
"menu_item_name": "Create Your Own",
"modifiers": [
{
"modifier_id": "6HEK9TXSBQ",
"modifier_name": "Shrimp"
}
],
"quantity": "1",
"total": 15.99,
"variant_id": "TXDOR7S83E",
"variant_name": "X-Lg 18\""
}
]
Now I want to call this API from an HTML page using Javascript(Using HTML elements like forms and drop down menus etc). I want to create a Javascript object with proper structure and then convert it to JSON using "stringify" function. But I am not able to create the Javascript object. Can anyone help with this?
Like i want to have the following structure
obj.order_items[0].menu_item_id="VD1PIEBIIG";
obj.order_items[0].menu_item_name="Create Your Own";
obj.order_items[0].modifiers[0].modifier_id="6HEK9TXSBQ";
and so on.

var jsonToSend = { "order_items": [ ] };
// then for each order item
var orderItem = { "menu_item_id": <whatever>,
"menu_item_name": <whatever>,
"quantity": <whatever>,
"total": <whatever>,
"variant_id": <whatever>,
"variant_name": <whatever>,
"modifiers": []
};
// then for each modifier
var modifier = { "modifier_id": <whatever>, "modifier_name": <whatever> };
orderItem.modifiers.push(modifier);
jsonToSend.order_items.push(orderItem);
JSON.stringify(jsonToSend);

Well there are a couple of ways to do this.
Manually create the Json object to send from the HTML elements:
$.ajax({
type: "POST",
url: "some.php",
data: new {"order_items": [
{
"total": $('total').Val(),
"variant_id": $('variant_id').Val(),
"variant_name": $('variant_name').Val()
}
]})
.done(function( msg ) {
alert( "Data Saved: " + msg );
});
You could use a great framework like KnockoutJs, this will keep your JSON object up to date with your form, so that you don't have to do it manually. When you are ready you just submit your original json back to the server.
See this basic example on JsFiddle
var ClickCounterViewModel = function() {
this.numberOfClicks = ko.observable(0);
this.registerClick = function() {
this.numberOfClicks(this.numberOfClicks() + 1);
};
this.resetClicks = function() {
this.numberOfClicks(0);
};
this.hasClickedTooManyTimes = ko.computed(function() {
return this.numberOfClicks() >= 3;
}, this);
};
ko.applyBindings(new ClickCounterViewModel());
You can use any number of plugins to Serialize the form, but the problem is getting the JSON structure just right.
See SerializeArray
$( "form" ).submit(function( event ) {
console.log( $( this ).serializeArray() );
event.preventDefault();
});

Related

How to send data from jquery to javascript

<script>
$.getJSON('chartState',{
stateCode : $(this).val(),
ajax : 'true'
},
function(data) {
alert("state data"+data);
});
</script>
I have the value in data and want to show in javascript given below.
The fields data is given want to push my state data there.
<script>
var salesChartData = {
datasets: [{
data: ["here i want my data"]
}]
};
</script>
Both are written in diffrent script
datasets is an array with an object on index 0. So to define or redeclare the data property in there the syntax is
salesChartData.datasets[0].data = data;
Use it in your callback function:
function(data) {
salesChartData.datasets[0].data = data;
});
Not sure if I understand correctly, is this what you need?
var salesChartData = {
datasets: [
{
data : {}
}
]
};
$.getJSON('chartState',{
stateCode : $(this).val(),
ajax : 'true'
},
function(data) {
salesChartData.datasets[0].data = data;
});
Just set the data after receiving it
if you need to show the ajax result in a variable salesChartData, you can try this
salesChartData.datasets[0].data[0] = "new data"
salesChartData is a JSON object with key datasets contains an array of JSON objects.
So if salesChartData is declared globally, then you can replace in the success of the ajax
Here below, it done using web storage. This is used to access from different file.
// File 1
var salesChartData = {
datasets: [{
data: ["here i want my data"]
}]
};
localStorage.setItem("salesChart", JSON.stringify(salesChartData));
//-----------------------------------------------------------------------
// File 2
var salesChartData = JSON.parse(localStorage.getItem("salesChart"));
// ajax call
$.getJSON('chartState', {
stateCode: $(this).val(),
ajax: 'true'
},
function (data) {
alert("state data" + data);
salesChartData.datasets[0].data[0] = data // "new data"
});
Hope this will work.
Thank You
I have done with my self
$.getJSON('chartState',{
stateCode : $(this).val(),
ajax : 'true'
},
function(data) {
var chr=data;
var a=chr[0];var b=chr[1];var c=chr[2];var d=chr[3];
var e=chr[4];var f=chr[5];var g=chr[6];
After that I have sended one by one data
var salesChartData = {
datasets: [
{
data : [g,f,e,d,c,b,a]
}
]
};
As you mention that both parts of the script are in different tags you can solve the problem with a global, this is not recommended. The better solution would be to refactor the structure and not have multiple script tags. But if you have no control over this then you should do something like this:
<script>
// No var used to make it global
chart_state_data = false;
$.getJSON('chartState',{
stateCode : $(this).val(),
ajax : 'true'
},
function(data) {
// the data is set to this variable on callback
chart_state_data = data
});
</script>
And:
<script>
// chart_state_data contains data retrieved from ajax call or false
var salesChartData = {
datasets: [{
data: chart_state_data
}]
};
</script>

How to filter search input to show correct autocomplete in JQUERY?

I have a search input where my autocomplete shows but for some reason it the results are not being filtered - can anyone tell or show me a way to filter results to show the correct autocomplete prior in my code below.. Below is the json format and the html code updated. Thanks for the help.
Here is my code
$( function() {
var cache = {};
$( "#searchTextField" ).autocomplete({
minLength: 2,
source: function( request, response ) {
var term = request.term;
if ( term in cache ) {
response( cache[ term ] );
return;
}
$.post( "http://localhost:8080/myApp/JobSearchItem.xhtml", request,
function( data, status, xhr ) {
cache[ term ] = data;
response( data );
});
}
});
} );
JobSearchItem Return JSON
[
{
"id": "9000",
"label": "PROGRAMMER TEST 1 (9000) ",
"value": "90000"
},
]
html
<h:body>
<f:view transient="true">
<tp:header/>
<tp:searchForm/>
<div id="results">
</div>
<h:panelGroup id="dTable" class="container">
</h:panelGroup>
</f:view>
<f:view transient="true">
<div class="jobEntity">
<div class="job-container-header">
<h4>#{testBean.jobEntity.toString()}</h4>
<c:if test="#{testBean.jobEntity.validURLConnection}">
<a href="#{testBean.jobEntity.pGradeDescriptionLink}"
class="btn btn-info-One"
target="_blank">[ Test ]</a>
</c:if>
<h4>#{testBean.jobEntity.mu} - #{testBean.jobEntity.muDescription}</h4>
<h4>#{testBean.jobEntity.specialNotes}</h4>
<h4>#{testBean.jobEntity.syRgeMnSepMsg}</h4>
</div>
<c:if test="${testBean.jobEntity.sectionToDisplay eq 'Range'}">
<table class="table">
<tbody>
<tr>
<th></th>
<c:forEach var="stepNumber" begin="1" end="#{testBean.jobEntity.stepSize}">
<th>Step #{stepNumber}</th>
</c:forEach>
</tr>
<c:forEach items="#{testBean.jobEntity.jobRows}" var="jobRow">
<tr>
<th>#{jobRow.rateType}</th>
<c:forEach items="#{jobRow.steps}" var="step">
<td>#{step.amount}</td>
</c:forEach>
</tr>
</c:forEach>
</tbody>
</table>
</c:if>
</div>
When you specify a remote URL as the datasource like this, the remote server is expected to do the filtering based on the search term given to it by the autocomplete, and return the results already filtered.
Autocomplete only carries out the filtering if you provide it with static data. See http://api.jqueryui.com/autocomplete/#option-source for more details.
N.B. If your remote server is unable to do any filtering (e.g. because it just returns a static file) then you'd have to filter the data client-side in your callback before you return it to the autocomplete. But of course this is not very efficient because you keep downloading all the data and then discarding most of it (unless the browser helpfully caches it).
Since you are calling data from a .xhtml file, it is not going to be able to filter the results, unless you can update the server side script to accept and perform activities based on data posted to it.
I would suggest you gather the static data upfront and then filter based on that. This might look something like:
$( function() {
var myData;
$.get( "http://localhost:8080/myApp/JobSearchItem.xhtml", function( data ){
myData = data;
} );
$( "#searchTextField" ).autocomplete( {
minLength: 2,
source: myData
} );
} );
This assumes that your xhtml is providing a Array of data (usually in JSON format). This can be simple:
[
"Item 1",
"Item 2",
"Item 3"
];
Or something more advanced:
[{
"label": "Item 1",
"value": 1
},{
"label": "Item 2",
"value": 2
},{
"label": "Item 3",
"value": 3
}];
If the data you get back is something else: HTML Table, XML, or text, then using a function with Source will help you. If you update your question and provide an example of the data, we could provide a more complete example or guidance.
Update 1
Given the following JSON Data:
[{
"id": "9000",
"pGrade": "0",
"label": "PROGRAMMER TEST 1"
},{
"id": "6000",
"pGrade": "0",
"label": "WEB PROGRAMMER TEST 1"
}];
This does not comply with the standard Autocomplete expected data. If you are able to POST data to JobSearchItem.xhtml, then you can have it filter first and return data. If JobSearchItem.xhtml does not accept POST, then I would perform a GET of all the data up front and then filter it later. I will include an example of both.
POST
If you are posting the data, the server-side script needs to know what data you are sending it in the form of a variable name and value. You did not supply a variable name in your example and you have not supplied the JobSearchItem.xhtml content, so it's really hard to identify how this script works.
For this example, we will use term and our example data will be we. If this was a GET command, it would look like:
JobSearchItem.xhtml?term=we
For Post we will use an Object that is submitted:
{ "term": "we" };
Here are the basics:
$(function(){
var cache = {};
$("#searchTextField").autocomplete( {
minLength: 2,
source: function(request, response){
var t = request.term;
if (t in cache){
response(cache[t]);
return;
}
var results = [];
$.ajax({
url: "http://localhost:8080/myApp/JobSearchItem.xhtml",
data: {
term: t
},
dataType: "json",
method: "POST",
success: function( data, status, xhr ) {
$.each(data, function(k, v){
results.push({
label: v.label,
value: v.label,
id: v.id,
grade: v.pGrade
});
});
cache[t] = results;
});
response(results);
});
}
});
});
So, in this case, if the user enters we, this is sent to the script, which will filter the results and will send back JSON that should look like:
[{
"id": "6000",
"pGrade": "0",
"label": "WEB PROGRAMMER TEST 1"
}];
Since Autocomplete is expecting an object containing label and value can't just be sent direct to response(). Using $.each() we can iterate the results and adjust so that it's formatted for Autocomplete.
GET
If your obSearchItem.xhtml is static and just provides a list of JSON data, using GET might be a good way to collect this data. Consider that you can get all this data up front, and then use it later. This is the most common way to use Autocomplete, but the data still has to be in the right format.
$( function() {
var myData = [];
$.get("http://localhost:8080/myApp/JobSearchItem.xhtml", function(data){
$.each(data, function(k, v){
myData.push({
label: v.label,
value: v.label,
id: v.id,
grade: v.pGrade
});
});
});
$("#searchTextField").autocomplete({
minLength: 2,
source: myData
});
});
One of these should work.

How to use JSON data in rails and provide it to javascript

I have a rails application where I have JSON data as shown below:
{"makes":[{"id":200347864,"name":"AM General","niceName":"am-general","models":[{"id":"AM_General_Hummer","name":"Hummer","niceName":"hummer","years":[{"id":3407,"year":1998},{"id":1140,"year":1999},{"id":305,"year":2000}]}]}]}
This is a very long list of car objects with multi-levels of nesting. Make, model, year, trim etc.
I want to send this JSON to javascript and populate my autofill drop down menu.
Previously, I was using a third-party API and the code looked like:
$( document ).ready(function() {
var prev ="https://xyz/makes";
var rest ="?fmt=json&api_key=";
var key = "<%= ENV['XYZ_API_KEY'] %>";
var net = prev+rest+key;
var options = [];
options.push("All");
var dictionary = {};
$.ajax({
url: net,
dataType: "json",
type: "get",
data: $(this).serialize()
}).done(function(data){
change_make(data);
change_model();
});
function change_make(data) {
for (var key in data["makes"]){
if (data["makes"].hasOwnProperty(key)){
var make = data["makes"][key];
options.push(make.name);
buffer = [];
// console.log(make.models);
for (var key2 in make.models){
// console.log(make.models[key2].name);
if (make.models.hasOwnProperty(key2)){
// console.log(make.models[key2].name);
buffer.push(make.models[key2].name);
}
}
dictionary[make.name] = buffer;
}
}
dictionary["All"] = ["All"]
// console.log(options);
$.each(options, function(key, value) {
$('#category')
.append($("<option></option>")
.attr("value", value.html_safe)
.text(value));
});
};
$('#category').on('change', function(){
console.log("change success");
change_model();
});
function change_model(){
var make = $('#category').find(":selected").text();
var models = dictionary[make];
// models.unshift("All");
$('#subcategory').empty();
$.each(models, function(key, value) {
$('#subcategory')
.append($("<option></option>")
.attr("value",value.html_safe)
.text(value));
});
}
$("#searchboxcontainer").delay(100).fadeIn(200);
});
Instead of using the ajax request, I want to use json string directly.
I wrote a helper method in application helper module as shown:
def edmunds_json
the_json_object
end
But when I am using it in javascript, its adding &gm characters and theobject comes out as:
{:makes=>[{:id=>200347864, :name=>"AM General",...
and the code is giving errors
Uncaught SyntaxError: Unexpected token :
When I am using escape in JSON, it's giving me the error on rails unexpected $undefined. expecting ').
The JSON object is using double quotes and I want to use it in my code. How should I proceed so &gt etc won't be added.
I think what you need to do is to first convert your Ruby Hash into json in your helper
def edmunds_json
the_json_object.to_json
end code here
Then in your view in a script tag do something like this
<script>
const object = <%= raw edmunds_json %>
console.log(typeof(object)) // => Object
</script>
Solved it by using:
<%= get_make_model_json.to_s.gsub("=>",":").html_safe %>; in javascript
where get_make_model_json is:
def get_make_model_json
JSON.parse(
'{
"makes": [{
"id": 200347864,
"name": "AM General",
"niceName": "am-general",
"models": [{
"id": "AM_General_Hummer",
"name": "Hummer",
"niceName": "hummer",
"years": [{
"id": 3407,
"year": 1998
}, {
"id": 1140,
"year": 1999
}, {
"id": 305,
"year": 2000
}]
}]
},...
end

Create a Cookie after an jQuery AJAX request?

My script is a simple like and dislike buttons (called reactions). It works well but now I want to have a quick cookie created if the vote went through so people can't vote for this particular comment ever again (ie. 1 year.. or when they remove their cookies.)
The entire function works but I am confused on how to add the cookie for each specific comment they have reacted to?
(function( $ ) {
'use strict';
$( document ).ready(function() {
$(document).on('click', '.enco-reaction', function(e){
var data = {
'action': 'enco_reaction',
'reaction': $(this).data('reaction'),
'comment': $(this).data('id')
};
$.post(
ajax_object.ajax_url,
data,
function( obj ) {
if( obj.error ) {
alert( obj.error );
} else {
$('#enco-reaction-' + obj.reaction + '-' + obj.comment + ' .enco-reaction-count' ).html( obj.value );
}
},
'json'
);
});
});
})( jQuery );
Best not to use cookies (I would recommend local storage over cookies for storing data as you can store JSON data better and larger) as it's more used for temporary data.
But for whatever reason you don't want to.
I'd store data in a JSON Object with a user identifier (however you wish to identifier users from each other) and a list of comments id's.
{
"users": {
"user_ids": {
"123": [
"111",
"222",
"333"
],
"456": [
"111",
"222",
"333"
]
}
}
}
and just JSON.stringify() before storing it in either cookies or local storage.
as per people's recommendations, I've opted for a simple table in my database and I log ip, comment_id, date, etc. and then I just retrieve the last date for a given IP and check.
thanks!

Setting my model with Backbone.js

I'm attempting to use Backbone.js to simplify data (JSON) management and interaction with DOM.
Firstly, I'm not sure if Backbone.js can indeed simplify and improve the current process, but I'd like to assume it can.
Previously I'm retrieving the data with jQuery AJAX function. Now, I'm retrieving the data(still with AJAX) Backbone style into the Backbone model.
For update, previously I was parsing through the JSON object itself to update data. I would then send back the updated json to the back-end (just as I've received it).
Now, is it possible to use the set function in Backbone to simplify something like the below and ideally where should the set attribute behaviour (and all other UI bindings like change events) be constructed? Would it be on the fetch() success handler, which is in the View initializer?
function setBucketOffer(bucketName, newId) {
var segments = json.segments;
for (var i = 0; i < segments.length; i++) {
if (segments[i].market.toLowerCase() === g_market) {
var genders = segments[i].gender;
for (var i = 0; i < genders.length; i++) {
if (genders[i].name.toLowerCase() === g_segment) {
var buckets = genders[i].buckets;
for (var i = 0; i < buckets.length; i++) {
if (buckets[i].name === bucketName) {
buckets[i].confirm = newId;
return;
}
}
}
}
}
}
}
Example JSON
{
"segments": [
{
"market": "Market1",
"gender": [
{
"name": "male",
"buckets": [
{
"name": "Market1_M_CBD",
"subscribers": "50,000",
"postcode": "20000-2010",
"lastsend": "13/03/12 4:30PM",
"suggest": "10054",
"confirm": ""
},
{
"name": "Market1_M_North",
"subscribers": "50,000",
"postcode": "20000-2010",
"lastsend": "13/03/12 4:30PM",
"suggest": "10054",
"confirm": ""
}
]
},
{
"name": "female",
"buckets": [
{
"name": "Market1_F_CBD",
"subscribers": "50,000",
"postcode": "20000-2010",
"lastsend": "13/03/12 4:30PM",
"suggest": "10054",
"confirm": "10054"
}
]
}
]
},
{
"market": "Market2",
"gender": [
{
"name": "male",
"buckets": [
{
"name": "Market2_M_CBD",
"subscribers": "50,000",
"postcode": "20000-2010",
"lastsend": "13/03/12 4:30PM",
"suggest": "10054",
"confirm": "10054"
},
{
"name": "Market2_M_North",
"subscribers": "50,000",
"postcode": "20000-2010",
"lastsend": "13/03/12 4:30PM",
"suggest": "10054",
"confirm": "10054"
},
{
"name": "Market2_M_South",
"subscribers": "50,000",
"postcode": "20000-2010",
"lastsend": "13/03/12 4:30PM",
"suggest": "10054",
"confirm": "10054"
}
]
}
]
}
]
}
Edit 1
From here, I'm trying to make good use of Parse and to get just segments from my JSON:
var Offers = Backbone.Collection.extend({
url: 'URL',
parse: function (response) {
return response.segments;
}
});
Here, I'm getting more than just response.segments. Also not sure if it's right for me to use the render function or fetch success function to populate the DOM. Suppose I have my html template in the DOM... I want to clone it using jQuery clone() and populate the clone using a forEach on segments, and push back all the clones into the html body. Is this workable in backbone, how would you do it? (I'm able to do this without backbone.js, but would like to see how I can improve with backbone.js, and bind all the data on the clones to model changes)
var OfferView = Backbone.View.extend({
initialize: function () {
this.model = new Offers();
this.model.fetch({
success: function (collection, response) {
console.log(response);
}
});
this.model.on('change', this.modelChange);
this.model.on('change', this.render);
this.modelChange = function () {
alert('model changed');
};
},
render: function () {
}
});
Edit 2
I'm up to creating individual views through a forEach but am having trouble inserting these back into the DOM. What am I doing wrong? (Not sure around the return this part)
// DEFINE VIEW
var OfferView = Backbone.View.extend({
initialize: function () {
this.model = new Offers();
this.model.fetch();
this.model.on('change', this.modelChange);
this.model.on('change', this.render);
this.modelChange = function () {
alert('model changed');
};
this.render();
},
render: function () {
var self = this;
this.model.forEach(function (s) {
var view = new OfferMarketView({
id: "container" + s.get('name').toLowerCase().replace(/\s*/g, '')
});
$('#leftCol').append(view.el);
});
return this;
}
});
var OfferMarketView = Backbone.View.extend({
tagName: "div",
className: "marketContainer",
events: {},
render: function() {
}
});
Whenever you call fetch on a model the response is passed through a parse method that can be defined in your model. parse takes one parameter, the ajax response:
parse: function(response) {
}
In that function you can do whatever you want with the data that comes back from your ajax request and eventually return that object. The object returned by the parse method will be set on your model.
For event binding, you'll want to do that in your view. In the initialize method of your view you can do something like:
this.collection.on("change", this.someFunction);
Now, any time something causes that model to trigger its change event someFunction ( also defined in your view ) will run.
EDIT
The sample json you added to the question looks to be pretty normalized. With that data, I'd be fetching it into a collection. If that's the structure you want your models to look like then you don't need to do much parsing.
in you collection file if you create a parse method that does the following:
parse: function(response) {
return response.segments;
}
When you call your fetch, this.collection.fetch() on a successful request, your collection will be filled with models that contain attributes in a structure that matches your response.
EDIT 2
Your binding looks ok.
in this section of code:
this.collection.fetch({
success: function (model, attributes) {
initAll(attributes);
// populate ui with attributes from model
}
})
The parameters that are passed back on a success in a collection fetch are (collection, response) collection is the result of collection call and what this.collection will end up being. response is the response of your ajax request.
I'm not sure what initAll(attributes) is supposed to be doing. If you add a parse method like I posted above, your collection will contain a set of models with the attributes of each segment.
Also, rather than calling this.render() at the end, you could do bind render to the change event:
this.collection.on('change', this.render);
That way any time your collection changes, that view will automatically render again so your changes will show up.

Categories

Resources