I have json with array of objects in it. I build my page depends on elements in this array. If there is no duplicate values of key called points, i render page with some info and description, using value of points to find this element in array. However if i have 2 and more duplicate values of key called points i render list of these elements. In this case i cant use value of points to find element in array. I know i can use index number of array element, and then pass it as parameter to my function that find and build info and description, but i'm not sure how to do that. How do i get index number of element in array?
P.S. Can provide my code if needed
Code that i'm using
var allRewards = null;
$("#reward").live('pagecreate', function(e) {
var request = $.ajax({
type: "GET",
url: "example.com/test.json"
dataType: "json",
error: function (data, textStatus){
console.log( "it`s error" );
console.log( status );
console.log( data );},
success: function (data, textStatus){
console.log( "success" );
console.log( status );
console.log( data );
}
})
request.success(function(data, textStatus){
var lis = "";
var arr = [];
var iter = 0;
allRewards = data
$.each(data.rewards, function(key, val){
if ($.inArray(val.points, arr) == -1)
{
lis += "<div data-points='"+ val.points +"'align=CENTER class = 'rewards-block ui-block-" + String.fromCharCode(97 + iter%3) + "'><a href ='#' class ='ui-link-inherit' onclick='showreward("+val.points+")'><img src ='./img/reward-icon.png'/><span>" + val.points + " pts</span></a></div>";
arr.push(val.points);
iter += 1;
}
});
$("#rewards_table").html(lis);
})
});
function showreward(point)
{
$.mobile.changePage('show-rewards.html')
console.log(allRewards);
$("#showrewards").live('pagecreate', function(e) {
var items = "";
var arr = [];
var counter = 0;
var result = $.grep(allRewards.rewards, function(e){ return e.points == point; });
if (result.length > 1)
{
$.each(result, function(key, val){
items += "<div style='color:white;'>" + val.title + "</div>"
console.log(val.title);
})
}
else if (result.length == 1)
{
// $.each(result, function(key, val){
// items += "div style='color:white;'"+ val.points + "></div>"
// console.log(val.points);
// })
$.each(result, function(key, val){
items += "<div style='background:white; padding:5px 5px 20px 5px;'><img style ='float:right; width:45%; margin-top:22px; padding: 0 0 10px 10px;' src ='" + val.main_photo_url + "'/><h3>"+ val.title + "</h3><p>" + val.description + "</p><p style='font-weight:bold; font-size:13px;'>Reedem below for " + val.points + " Zingle Points</p><table class='pagemenu' style='width:200px;'><tr><td class='width_5'><input type='submit' data-theme='w' value='Reedem Now' data-inline='true'></td><td><a data-role='button' data-icon='pagemenu-share' data-iconpos='notext' href='index.html' data-shadow='false' data-corners='false'></a></td></tr></table></div>"
});
}
console.log(items);
$("#rewards-list").html(items);
});
}
I think you're looking for Array.indexOf.
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf
PS. This is available in Underscore as _.indexOf.
Related
i have been tasked by my senior to print values of line items using higher order functions (.filter/.map/.reject/.reduce). I m confused how to write the higher order function instead of a for loop(for printing the line values in Invoice Printout). I need to print the line only when the qty is more than 3. I m an intern and i dont know how it will work, kindly help.
Link to The code snippet: https://drive.google.com/file/d/1uVQQb0dsg_bo53fT3vk9f0G8WwZomgQg/view?usp=sharing
I always used if condition for printing the row only when the quantity field has value more than 3. I even know how to .filter but i dont know how to call it and where to call it. Please help
I don't believe Array.from works in server side code. If it does then use that. What I have been using are the following functions. They don't conform to the higher order functions specified but they work with Netsuite syntax and go a long way towards simplifying sublist handling and encapsulating code:
//SS2.x
//I have this as a snippet that can be included in server side scripts
function iter(rec, listName, cb){
var lim = rec.getLineCount({sublistId:listName});
var i = 0;
var getV = function (fld){
return rec.getSublistValue({sublistId:listName, fieldId:fld, line:i});
};
for(; i< lim; i++){
cb(i, getV);
}
}
// to use it:
iter(ctx.newRecord, 'item', function(idx, getV){
if(parseInt(getV('quantity')) >3){
...
}
});
or for SS1 scripts I have the following which allows code to be shared between UserEvent and Scheduled scripts or Suitelets
function forRecordLines(rec, machName, op, doReverse) {
var i, pred, incr;
var getVal = rec ? function(fld) {
return rec.getLineItemValue(machName, fld, i);
} : function(fld) {
return nlapiGetLineItemValue(machName, fld, i);
};
var getText = rec ? function(fld) {
return rec.getLineItemText(machName, fld, i);
} : function(fld) {
return nlapiGetLineItemText(machName, fld, i);
};
var setVal = rec ? function(fld, val) {
rec.setLineItemValue(machName, fld, i, val);
} : function(fld, val) {
nlapiSetLineItemValue(machName, fld, i, val);
};
var machCount = rec ? rec.getLineItemCount(machName) : nlapiGetLineItemCount(machName);
if(!doReverse){
i = 1;
pred = function(){ return i<= machCount;};
incr = function(){ i++;};
}else{
i = machCount;
pred = function(){ return i>0;};
incr = function(){ i--;};
}
while(pred()){
var ret = op(i, getVal, getText, setVal);
incr();
if (typeof ret != 'undefined' && !ret) break;
}
}
// User Event Script:
forRecordLines(null, 'item', function(idx, getV, getT, setV){
if(parseInt(getV('quantity')) >3){
...
}
});
// in a Scheduled Script:
forRecordLines(nlapiLoadRecord('salesorder', id), 'item', function(idx, getV, getT, setV){
if(parseInt(getV('quantity')) >3){
...
}
});
Usually its a straight forward task, but since you are getting length and based on that you are iterating, you can use Array.from. Its signature is:
Array.from(ArrayLikeObject, mapFunction);
var tableData = Array.from({ length: countItem}, function(index) {
vendorBillRec.selectLineItem('item', index);
var item = vendorBillRec.getCurrentLineItemText('item', 'item');
var description = nlapiEscapeXML(vendorBillRec.getCurrentLineItemValue('item', 'description'));
var quantity = parseFloat(nullNumber(vendorBillRec.getCurrentLineItemValue('item', 'quantity')));
return { item, description, quantity}
});
var htmlData = tableData.filter(...).map(getRowMarkup).join('');
function getRowMarkup(data) {
const { itemName, descript, quantity } = data;
return '<tr>' +
'<td colspan="6">' +
'<p>' + itemName + ' ' + descript + '</p>'+
'</td>' +
'<td colspan="2" align="right">' + quantity + '</td>' +
'</tr>';
}
Or if you like to use more functional approach:
Create a function that reads and give you all data in Array format. You can use this data for any task.
Create a function that will accept an object of specified properties and returns a markup.
Pass the data to this markup after any filter condition.
Idea is to isolate both the task:
- Getting data that needs to be processed
- Presentation logic and style related code
var htmlString = Array.from({ length: countItem}, function(index) {
vendorBillRec.selectLineItem('item', index);
var item = vendorBillRec.getCurrentLineItemText('item', 'item');
var description = nlapiEscapeXML(vendorBillRec.getCurrentLineItemValue('item', 'description'));
var qty = parseFloat(nullNumber(vendorBillRec.getCurrentLineItemValue('item', 'quantity')));
return getRowMarkup(item, description, qty)
}).join('');
function getRowMarkup(itemName, descript, quantity) {
return '<tr>' +
'<td colspan="6">' +
'<p>' + itemName + ' ' + descript + '</p>'+
'</td>' +
'<td colspan="2" align="right">' + quantity + '</td>' +
'</tr>';
}
guys i know it is dummy question but i spent several hours and still cant reach .. i want to print a json array from variable startIndex and endIndex .. all what i did is printing it all .. here is my code
GridLibrary.prototype.display = function() {
$.ajax({
url : this.getFileName(),
dataType : "json",
error : function(that, e) {
console.log(e);
},
success : function(data) {
size = data.length;
var html = [];
html.push("<table >\n<tbody>");
html.push("<tr>");
for ( var propertyNames in data[0]) {
html.push("<th>" + propertyNames + "</th>");
}
html.push("</tr>");
// loop through the array of objects
data.forEach(function(item) {
html.push("<tr>");
for ( var key in item) {
html.push("<td>" + item[key] + "</td>");
}
html.push("</tr>");
});
html.push("<table>\n</tbody>");
$('body').append(html.join(""));
}
});
};
try this, loop through only the data you need
for( var i = startIndex; var item = data[i]; i<endIndex && typeof item != 'undefined' ; i++){
html.push("<tr>");
for ( var key in item) {
html.push("<td>" + item[key] + "</td>");
}
html.push("</tr>");
}
Just before your data.forEach(...) you could use splice() to cut your data array.
Like this:
data = data.splice(startIndex, endIndex);
I have multiple items in my JSON list. I want to loop through it and display it on my page. I can't seem to get to the next object though.
{
"room":[
{"campusName":"A",
"buildingCode":"B",
"roomNumber":"208",
"times":["7-8", "9-10"]
}],
"room2":[
{"campusName":"C",
"buildingCode":"D",
"roomNumber":"208",
"times":["7-8", "9-10"
]}
]}
$(document).ready(function(){
$.getJSON("data.json", function(data){
$.each(data.room, function(){
for(var i = 0; i < data.length; i++){
$("ul").append("<li>campus: "+this['campusName']+"</li><li>building: "+this['buildingCode']+"</li><li>times: "+this.times+"</li>");
}
});
});
});
Try this
var list = '';
$.each(data, function (i, root) {
$.each(root, function (i, el) {
list += "<li>campus: " + this.campusName + "</li><li>building: " + this.buildingCode + "</li><li>times: " + this.times.join(' ') + "</li>";
});
});
$('ul').html(list);
Example
If root's has only one element in array
var list = '';
$.each(data, function (i, root) {
list += "<li>campus: " + root[0].campusName + "</li><li>building: " + root[0].buildingCode + "</li><li>times: " + root[0].times.join(' ') + "</li>";
});
$('ul').html(list);
Example
$.each(data, ..) --> Each element will be:
"room":[
{"campusName":"A",
"buildingCode":"B",
"roomNumber":"208",
"times":["7-8", "9-10"]
}]
Then, this[0] will provide the object you need to construct your li:
$.each(data, function(){
$("ul").append("<li>campus: "+this[0]['campusName']+"</li><li>building: "+this[0]['buildingCode']+"</li><li>times: "+this[0].times+"</li>");
});
Fiddle
i have this code as shown below,
i got this from a developer who went afk because he has family troubles
basically this code below should grab the json results and form them into a table after sorting the price and then placing it in the table.
heres the code
//first define a function
var sortTable = function () {
$("#tableid tbody tr").detach().sort(function (a, b) {
//substring was added to omit currency sign, you can remove it if data-price attribute does not contain it.
return parseFloat($(a).data('price').substring(1)) - parseFloat($(b).data('price').substring(1));
})
.appendTo('#tableid tbody');
};
//include two files where rows are loaded
//1.js
$.ajax({
type: 'GET',
crossDomain: true,
dataType: 'json',
url: 'api link here',
success: function (json) {
//var json = $.parseJSON(data);
for (var i = 0; i < json.results.length; i++) {
var section = json.results[i].section;
var no = json.results[i].avalible;
var price = json.results[i].price;
var button = "<button class='redirect-button' data-url='LINK'>Compare</button>";
$("#tableid tbody").append("<tr data-price='" + price + "'><td>" + section + "</td><td>" + no + "</td><td>" + price + "</td><td>" + button + "</td></tr>");
$("#tableid").find(".redirect-button").click(function () {
location.href = $(this).attr("data-url");
});
}
sortTable();
},
error: function (error) {
console.log(error);
}
});
//and here is the 2nd js file
$.ajax({
type: 'GET',
crossDomain: true,
dataType: 'json',
url: '2nd api',
success: function (json) {
//var json = $.parseJSON(data);
for (var i = 0; i < json.results.length; i++) {
var section = json.results[i].section;
var no = json.results[i].avalible;
var price = json.results[i].amount;
var button = "<button class='redirect-button' data-url='LINK'>Click Here</button>";
$("#tableid tbody").append("<tr data-price='" + price + "'><td>" + section + "</td><td>" + no + "</td><td>" + price + "</td><td>" + button + "</td></tr>");
$("#tableid").find(".redirect-button").click(function () {
location.href = $(this).attr("data-url");
});
}
sortTable();
},
error: function (error) {
console.log(error);
}
});
Accessing the DOM, to get data that needs to be sorted, is a bad practice IMO. Even worse when you had the results in raw JSON form in the first place (in the success callback of the ajax call). Your success function should do something like this
success: function (json) {
//first sort the results - or better store these results somewhere
//and use that as a data store that is responsible for what is rendered in the DOM
json.results.sort(function(a,b) {
//using substring and parseFloat just like it was done in sortTable
//assuming price field has prices as strings with currency symbol in the first place
return parseFloat(a.substring(1)) - parseFloat(b.substring(1))
});
for (var i = 0; i < json.results.length; i++) {
var section = json.results[i].section;
var no = json.results[i].avalible;
var price = json.results[i].amount;
var button = "<button class='redirect-button' data-url='LINK'>Click Here</button>";
$("#tableid tbody").append("<tr data-price='" + price + "'><td>" + section + "</td><td>" + no + "</td><td>" + price + "</td><td>" + button + "</td></tr>");
$("#tableid").find(".redirect-button").click(function () {
location.href = $(this).attr("data-url");
});
}
}
I am trying to parse a json file using jquery getJson. I have no problem looping through the first layer, but I need to assign a nested array to li as well.
My JSON Code
{"Controls":[
{
"Object":"Button",
"ButtonAttr": [{"x": "1","y": "2","width": "3","height": "4"}]
},
{
"Object":"Image",
"ButtonAttr": [{"x": "5","y": "6","width": "7","height": "8"}]
},
{
"Object":"TextField",
"ButtonAttr": [{"x": "9","y": "10","width": "11","height": "12"}]
}
]}
My JS/JQUERY Code where I have no problem bringing in the first layer of the JSON and appending it to a li. I need to figure out how to get the 'ButtonAttr' layer
//Get JSON File which contains all Controls
$.getJSON('controls.json', function(data) {
//Build Objects List
var objectList="<ul>";
for (var i in data.Controls) {
objectList+="<li>" + data.Controls[i].Object +"</li>";
}
objectList+="</ul>";
$('#options').append(objectList);
//Add new Code Object based on #Options LI Index
$(document).on('click','#options li', function() {
var index = $('#options li').index(this);
$('#code').append('<li>' + data.Controls[index].Object + '</li>');
//Shows Selected LI Index
$('#optionsIndex').text("That was div index #" + index);
});
});
I cannot for the life of me get it to loop through the second array and list out the x,y,width, and height fields.
Here is my desired output
<ul>
<li>Button</li>
<ul>
<li>x:1</li>
<li>y:2</li>
<li>width:3</li>
<li>height:4</li>
</ul>
<li>Image</li>
<ul>
<li>x:5</li>
<li>y:6</li>
<li>width:7</li>
<li>height:8</li>
</ul>
<li>TextField</li>
<ul>
<li>x:9</li>
<li>y:10</li>
<li>width:11</li>
<li>height:12</li>
</ul>
</ul>
Any help would be greatly appreciated
I worked through this in another question.
How to handle comma separated objects in json? ( [object Object],[object Object] )
You want a recursive function that starts a <ul> and adds <li> for each item in the list. It also tests items, and if they are themselves lists, it calls itself with that piece of data as the argument. Each time the function is called from within the function you get a <ul> within a <ul>.
function buildULfromOBJ(obj){
var fragments = [];
//declare recursion function
function recurse(item){
fragments.push('<ul>'); // start a new <ul>
$.each(item, function(key, val) { // iterate through items.
if((val != null) && (typeof val == 'object') && // catch nested objects
((val == '[object Object]') || (val[0] == '[object Object]'))){
fragments.push('<li>[' + key + '] =></li>'); // add '[key] =>'
recurse(val); // call recurse to add a nested <ul>
}else if(typeof(val)=='string'){ // catch strings, add double quotes
fragments.push('<li>[' + key + '] = \"' + val + '\"</li>');
}else if($.isArray(val)){ // catch arrays add [brackets]
fragments.push('<li>[' + key + '] = [' + val + ']</li>');
}else{ // default: just print it.
fragments.push('<li>[' + key + '] = ' + val + '</li>');
}
});
fragments.push('</ul>'); // close </ul>
}
// end recursion function
recurse(obj); // call recursion
return fragments.join(''); // return results
} // end buildULfromOBJ()
save your self the pain of trying to do with with for loops etc. and use client-side templating like json2html.com
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src='http://json2html.com/js/jquery.json2html-3.1-min.js'></script>
<ul id='out'></ul>
<script>
var data =
{"Controls":[
{
"Object":"Button",
"ButtonAttr": [{"x": "1","y": "2","width": "3","height": "4"}]
},
{
"Object":"Image",
"ButtonAttr": [{"x": "5","y": "6","width": "7","height": "8"}]
},
{
"Object":"TextField",
"ButtonAttr": [{"x": "9","y": "10","width": "11","height": "12"}]
}
]};
var template = {"tag":"li","children":[
{"tag":"span","html":"${Object}"},
{"tag":"ul","children":[
{"tag":"li","html":"x: ${ButtonAttr.0.x}"},
{"tag":"li","html":"y: ${ButtonAttr.0.y}"},
{"tag":"li","html":"width: ${ButtonAttr.0.width}"},
{"tag":"li","html":"height: ${ButtonAttr.0.height}"}
]}
]};
$('#out').json2html(data.Controls,template);
</script>
You can do it like this.. using the $.each and a for in loop
var str = '<ul>';
$.each(data.Controls, function(k, v) {
str += '<li>' + v.Object + '</li><ul>';
for(var kk in v.ButtonAttr[0]){
str += '<li>' + kk + ':' + v.ButtonAttr[0][kk] + '</li>';
}
str += '</ul>';
});
str += '</ul>';
FIDDLE
or with 2 $.each loops
var str = '<ul>';
$.each(data.Controls, function(k, v) {
str += '<li>' + v.Object + '</li><ul>';
$.each(v.ButtonAttr[0],function(kk,vv){
str += '<li>' + kk + ':' + vv + '</li>';
});
str += '</ul>';
});
str += '</ul>';
FIDDLE
You can loop through the second array just as easily as the first, like so:
$(document).on('click','#options li', function() {
var index = $('#options li').index(this);
$('#code').append('<li>' + data.Controls[index].Object + '</li>');
// Create a new sub-UL to after the LI
var $subUl = $(('<ul>')
// Iterate through each attribute in ButtonAttr
$.each(data.Controls[index].ButtonAttr, function(key, value){
// Append a new LI with that attribute's key/value
$subUl.append('<li>' + key + ':' + value + '</li>');
});
// Append that new sub-UL we made after the last LI we made
$('#code li:last').after($subUl);
//Shows Selected LI Index
$('#optionsIndex').text("That was div index #" + index);
});