Is there a way to get random values from a JSON file? My JSON contains a lot of content based on same musical artist, so I wanted to display data more randomly and add a show more button afterwards...
so my JSON looks something like this:
[
data: [{
"name" : "rihanna",
"song" : "pour it up"
},
{
"name" : "rihanna"
"song" : "diamonds"
},
{
"name" : "ladygaga"
"song" : "lovegame"
},
{
"name" : "ladygaga"
"song" : "lovegame"
},
{
"name" : "ladygaga"
"song" : "pokerface"
},
{
"name" : "ladygaga"
"song" : "alejandro"
},
{
"name" : "fergie"
"song" : "fergalicious"
},
{
"name" : "fergie"
"song" : "clumsy"
},
etc etc
So, is there a way to achieve this?
Try this :)
var random = Math.floor(Math.random() * jsonObject.length);
var rData = jsonObject[random];
P.S. : Where jsonObject ist your data property.
Here is how you can acheive it. PLUNKER
$(document).ready(function() {
$('button').on('click', function() {
getRandom();
var html = template(context);
$('#artistlist').html(html);
});
var source = $("#entry-template").html();
var template = Handlebars.compile(source);
var musicArray = [{
"name": "rihanna",
"song": "pour it up"
}, {
"name": "rihanna",
"song": "diamonds"
}, {
"name": "ladygaga",
"song": "lovegame"
}, {
"name": "ladygaga",
"song": "lovegame"
}, {
"name": "ladygaga",
"song": "pokerface"
}, {
"name": "ladygaga",
"song": "alejandro"
}, {
"name": "fergie",
"song": "fergalicious"
}, {
"name": "fergie",
"song": "clumsy"
}];
var context = {
music: []
};
var musicClone = $.extend(true, [], musicArray);
function getRandom() {
var i = 2;
while (i-- && musicClone.length >= 1) {
var random = Math.floor(Math.random() * musicClone.length);
var data = musicClone[random];
context.music.push(data);
musicClone.splice(random, 1);
}
}
});
Related
I use a google sheet as an endpoint to import data into an html table. Depending on the type of data in the sheet I get a different JSON structure.
To explain the problem, I built a Google sheet with two very simple tables.
The only difference between the two tables is the Age field which is numeric in Sheet1 and textual in Sheet2.
Link document
If I use sheets as JSON endpont I get this behavior: Sheet1 exports the header correctly, but Sheet2 shows an empty header (column headers become normal row values).
Sheet1 JSON
{
"version": "0.6",
"reqId": "0",
"status": "ok",
"sig": "325167901",
"table": {
"cols": [
{
"id": "A",
"label": "Name",
"type": "string"
},
{
"id": "B",
"label": "Age",
"type": "number",
"pattern": "General"
}
],
"rows": [
{
"c": [
{
"v": "Vittorio"
},
{
"v": 52.0,
"f": "52"
}
]
}
],
"parsedNumHeaders": 1
}
}
Sheet2 JSON
{
"version": "0.6",
"reqId": "0",
"status": "ok",
"sig": "1566616543",
"table": {
"cols": [
{
"id": "A",
"label": "",
"type": "string"
},
{
"id": "B",
"label": "",
"type": "string"
}
],
"rows": [
{
"c": [
{
"v": "Name"
},
{
"v": "Age"
}
]
},
{
"c": [
{
"v": "Vittorio"
},
{
"v": "52"
}
]
}
],
"parsedNumHeaders": 0
}
}
Is there any way to fix Sheet2 behavior?
It seems there is a problem, meanwhile what I suggest is to test the JSON endpont labels as follows
const jsonString = `/*O_o*/
google.visualization.Query.setResponse({"version":"0.6","reqId":"0","status":"ok","sig":"1566616543","table":{"cols":[{"id":"A","label":"","type":"string"},{"id":"B","label":"","type":"string"}],"rows":[{"c":[{"v":"Name"},{"v":"Age"}]},{"c":[{"v":"Vittorio"},{"v":"52"}]}],"parsedNumHeaders":0}});`
function jsonWithLabels(jsonString) {
var json = JSON.parse(jsonString.slice(47,-2))
var labels = json.table.cols.map(c => c.label)
return (labels.join('') != '')
}
function test(){
console.log (jsonWithLabels(jsonString))
}
if false, you need to fetch the labels from row 1
const jsonString = `/*O_o*/
google.visualization.Query.setResponse({"version":"0.6","reqId":"0","status":"ok","sig":"1566616543","table":{"cols":[{"id":"A","label":"","type":"string"},{"id":"B","label":"","type":"string"}],"rows":[{"c":[{"v":"Name"},{"v":"Age"}]},{"c":[{"v":"Vittorio"},{"v":"52"}]}],"parsedNumHeaders":0}});`
var json = JSON.parse(jsonString.slice(47,-2))
var labels = json.table.cols.map(c => c.label)
console.log (labels.join('') != '')
here is a complete script to rebuild the table with and without labels
const jsonString = `/*O_o*/
google.visualization.Query.setResponse({"version":"0.6","reqId":"0","status":"ok","sig":"1566616543","table":{"cols":[{"id":"A","label":"","type":"string"},{"id":"B","label":"","type":"string"}],"rows":[{"c":[{"v":"Name"},{"v":"Age"}]},{"c":[{"v":"Vittorio"},{"v":"52"}]}],"parsedNumHeaders":0}});`
document.getElementById("json").innerHTML = myItems(jsonString.slice(47, -2))
function myItems(jsonString) {
var json = JSON.parse(jsonString);
var table = '<table>';
var flag = jsonWithLabels(json);
if (flag) {
table += '<tr>';
json.table.cols.forEach(colonne => table += '<th>' + colonne.label + '</th>')
table += '</tr>';
}
json.table.rows.forEach((row, index) => {
table += '<tr>';
row.c.forEach(cel => {
try { var valeur = cel.f ? cel.f : cel.v }
catch (e) { var valeur = '' }
if (!flag && index == 0) { table += '<th>' + valeur + '</th>' }
else { table += '<td>' + valeur + '</td>' }
})
table += '</tr>';
})
table += '</table>';
return table
}
function jsonWithLabels(json) {
var labels = json.table.cols.map(c => c.label);
return (labels.join('') != '')
}
table {border-collapse: collapse;}
th,td {border: 1px solid black;}
<div id="json">json here</div>
"open" suppose to take a boolean value and I should be able to do my filter the results with it but I'm ending up with an empty array as result, excuse the messy code please
let queryToMatch = [{$match: {name: project}},{$unwind:"$issues"}];
if(_id != undefined){
queryToMatch.push({$match: {"_id": _id}})
}
if(open != undefined){
queryToMatch.push({$match: {"open": open}})
}
if(issue_title != undefined){
queryToMatch.push({$match:{"issue_title": issue_title}})
}
if(issue_text != undefined){
queryToMatch.push({$match:{"issue_text": issue_text}})
}
if(created_by != undefined){
queryToMatch.push({$match:{"created_by": created_by}})
}
if(assigned_to != undefined){
queryToMatch.push({$match:{"assigned_to": assigned_to}})
}
if(status_text != undefined){
queryToMatch.push({$match:{"status_text": status_text}})
}
console.log(queryToMatch)
res.json("works")
Project.aggregate(queryToMatch, (err, data) => {
//console.log(data)
res.json(data)
})
You have not included the schema, or sample documents you are attempting to query. For this reason my answer may not be as you expect.
If I add the following documement...
db.test.insert(
{
"_id" : ObjectId("60b44ae6af90ae8f4deca589"),
"name": "project",
"open": "open",
"issue_title": "mytitle",
"issue_text": "mytext",
"created_by": "barry",
"assigned_to": "john",
"status_text": "mystatus",
"issues": [
{
"issue_type": "type1",
"issue_date": new Date
},
{
"issue_type": "type2",
"issue_date": new Date
},
{
"issue_type": "type3",
"issue_date": new Date
},
]
}
)
I can run the following mongo shell commands...
var _id = ObjectId("60b44ae6af90ae8f4deca589");
var open = "open";
var issue_title = "mytitle";
var issue_text = "mytext";
var created_by = "barry";
var assigned_to = "john";
var status_text = "mystatus";
let queryToMatch = [{"$match": {"name": "project"}},{$unwind:"$issues"}];
if(_id != undefined){
queryToMatch.push({$match: {"_id": _id}})
}
if(open != undefined){
queryToMatch.push({$match: {"open": open}})
}
if(issue_title != undefined){
queryToMatch.push({$match:{"issue_title": issue_title}})
}
if(issue_text != undefined){
queryToMatch.push({$match:{"issue_text": issue_text}})
}
if(created_by != undefined){
queryToMatch.push({$match:{"created_by": created_by}})
}
if(assigned_to != undefined){
queryToMatch.push({$match:{"assigned_to": assigned_to}})
}
if(status_text != undefined){
queryToMatch.push({$match:{"status_text": status_text}})
}
... then I can issue the following aggregate statement...
db.test.aggregate(queryToMatch).pretty()
... and I get the following results...
{
"_id" : ObjectId("60b44ae6af90ae8f4deca589"),
"name" : "project",
"open" : "open",
"issue_title" : "mytitle",
"issue_text" : "mytext",
"created_by" : "barry",
"assigned_to" : "john",
"status_text" : "mystatus",
"issues" : {
"issue_type" : "type1",
"issue_date" : ISODate("2021-05-31T02:46:04.670Z")
}
}
{
"_id" : ObjectId("60b44ae6af90ae8f4deca589"),
"name" : "project",
"open" : "open",
"issue_title" : "mytitle",
"issue_text" : "mytext",
"created_by" : "barry",
"assigned_to" : "john",
"status_text" : "mystatus",
"issues" : {
"issue_type" : "type2",
"issue_date" : ISODate("2021-05-31T02:46:04.670Z")
}
}
{
"_id" : ObjectId("60b44ae6af90ae8f4deca589"),
"name" : "project",
"open" : "open",
"issue_title" : "mytitle",
"issue_text" : "mytext",
"created_by" : "barry",
"assigned_to" : "john",
"status_text" : "mystatus",
"issues" : {
"issue_type" : "type3",
"issue_date" : ISODate("2021-05-31T02:46:04.670Z")
}
}
It seems your code does work in the context of mongo shell. My advice is to combine the $match stages together first, then perform the $unwind. I assume each of the predicates you are tacking on via a push are intended to be an 'AND' condition, not an 'OR' condition. Here is what the end result of your aggregation looks like after all the logical shenanigans...
[
{
"$match" : {
"name" : "project"
}
},
{
"$unwind" : "$issues"
},
{
"$match" : {
"_id" : ObjectId("60b44ae6af90ae8f4deca589")
}
},
{
"$match" : {
"open" : "open"
}
},
{
"$match" : {
"issue_title" : "mytitle"
}
},
{
"$match" : {
"issue_text" : "mytext"
}
},
{
"$match" : {
"created_by" : "barry"
}
},
{
"$match" : {
"assigned_to" : "john"
}
},
{
"$match" : {
"status_text" : "mystatus"
}
}
]
Perhaps this is a cleaner and easier to read query...
[
{
"$match" : {
"_id" : ObjectId("60b44ae6af90ae8f4deca589"),
"name" : "project",
"open" : "open",
"issue_title" : "mytitle",
"issue_text" : "mytext",
"created_by" : "barry",
"assigned_to" : "john",
"status_text" : "mystatus"
}
},
{
"$unwind" : "$issues"
},
]
Consider instead of using push you create an object for your $match predicate...
var match = new Object();
match.name = "project";
if(_id != undefined){
match._id = _id;
}
if(open != undefined){
match.open = open;
}
if(issue_title != undefined){
match.issue_title = issue_title;
}
if(issue_text != undefined){
match.issue_text = issue_text;
}
if(created_by != undefined){
match.created_by = created_by;
}
if(assigned_to != undefined){
match.assigned_to = assigned_to;
}
if(status_text != undefined){
match.status_text = status_text;
}
let queryToMatch = [{"$match": match},{$unwind:"$issues"}];
db.test.aggregate(queryToMatch).pretty()
I'm new to Mongoose and I've been trying for days on how to solve this issue and I'm still having trouble.
My document object is below.
"person" : [
{
"title" : "front-end developer",
"skills" : [
{
"name" : "js",
"project" : "1",
},
{
"name" : "CSS",
"project" : "5",
}
]
},
{
"title" : "software engineer",
"skills" : [
{
"name" : "Java",
"project" : "1",
},
{
"name" : "c++",
"project" : "5",
}
]
}
]
What I would like accomplish is to return all documents that have person.title = software engineer AND person.skills.name = c++. The skill c++ has to belong to the software engineer person object. So returning documents when a front-end developer has c++ is not ideal.
Here's what I've tried doing so far. The query works but it returns documents which meet either one of the conditions and not both.
var query = {
_id: { $nin: [userID] },
$and: [
{person: {
$elemMatch: {
name: {$regex: `^${titleName}$`, $options: "i"}
}
}},
{[`person.skills`]: {
$elemMatch: {
name: {$regex: `^${skillName}$`, $options: "i"}
}
}}
]
};
Any help would be greatly appreciated. Thanks!
You can try below query. Move the and condition inside the $elemMatch
var query = {
"_id": {
"$nin": [userID]
},
"person": {
"$elemMatch": {
"name":{$regex: `^${titleName}$`, $options: "i"},
"skills.name": {$regex: `^${skillName}$`, $options: "i"}
}
}
};
I want to construct an app of hotel and rooms.
Every hotel can have more rooms, I retrieve this data from external server in XML, I parse it and now I have divided into two arrays: hotel and rooms like this:
hotel.json
[
{
"id": "1",
"name": "Hotel1"
},
{
"id": "2",
"name": "Hotel2"
},
{
"id": "3",
"name": "Hotel3"
}
]
rooms.json
[
{
"id" : "r1",
"hotel_id" : "1",
"name" : "Singola",
"level" : "1"
},
{
"id" : "r1_1",
"hotel_id" : "1",
"name" : "Doppia",
"level" : "2"
},
{
"id" : "r1_3",
"hotel_id" : "1",
"name" : "Doppia Uso singol",
"level" : "1"
},
{
"id" : "r2",
"hotel_id" : "2",
"name" : "Singola",
"level" : "1"
},
{
"id" : "r2_1",
"hotel_id" : "2",
"name" : "Tripla",
"level" : "1"
}
]
Into my backbone app I have to make some controller and some parse to retrieve rooms for its hotel.
I want to know if is better for backbone to construct a Json like that:
[
{
"id": "1",
"name": "Hotel1",
"rooms": [
{
"id" : "r1",
"hotel_id" : "1",
"name" : "Singola",
"level" : "1"
},
{
"id" : "r1_1",
"hotel_id" : "1",
"name" : "Doppia",
"level" : "2"
}
]
},
{
"id": "2",
"name": "Hotel2",
"rooms": [
{
"id" : "r2",
"hotel_id" : "2",
"name" : "Singola",
"level" : "1"
},
{
"id" : "r2_1",
"hotel_id" : "1",
"name" : "Doppia",
"level" : "2"
}
]
},
{
"id": "3",
"name": "Hotel3"
}
]
Which is the better mode for backbone in terms of efficiency and parsing?
I thinked the first case but after construct the app I'm not sure.
I would recommend keeping the data structures flat, as Backbone doesn't really support nested collections without some extra effort. Keeping the data model flat will also make it easier for you to map to REST endpoints (ie. '/hotels/1/rooms', 'rooms/1', etc.).
Just to demonstrate the complexities, here is an example of how one would have to associate a collection to a model:
HotelModel = Backbone.Model.extend({
initialize: function() {
// because initialize is called after parse
_.defaults(this, {
rooms: new RoomCollection
});
},
parse: function(response) {
if (_.has(response, "rooms")) {
this.rooms = new RoomCollection(response.rooms, {
parse: true
});
delete response.rooms;
}
return response;
},
toJSON: function() {
var json = _.clone(this.attributes);
json.rooms = this.rooms.toJSON();
return json;
}
});
With a flat data structure, you could do something like this:
HotelModel = Backbone.Model.extend({
idAttribute:'hotel_id',
urlRoot:'/hotels'
});
RoomModel = Backbone.Model.extend({
idAttribute:'room_id',
urlRoot:'/rooms'
});
HotelCollection = Backbone.Collection.extend({
url: '/hotels',
model:HotelModel
});
RoomCollection = Backbone.Collection.extend({
url: '/rooms',
model:RoomModel,
getByHotelId: function(hotelId){
return this.findWhere({hotel_id:hotelId});
}
});
I have the following JSON:
{
"wrapper": {
"table": {
"rows": [
{
"cells": [
{
"fname": "Jack",
"label": "fname",
"editable": false
},
{
"lname": "Kalra",
"label": "lname",
"editable": true,
"details": [
{
"industry": "music"
},
{
"industry": "media"
}
]
}
]
},
{
"cells": [
{
"fname": "Steven",
"editable": true,
"label": "fname"
},
{
"lname": "Martini",
"editable": true,
"label": "lname"
}
]
},
{
"cells": [
{
"fname": "Andrea",
"editable": true,
"label": "fname"
},
{
"lname": "Dmello",
"editable": true,
"label": "lname",
"details": [
{
"industry": "finance"
},
{
"industry": "HR"
},
{
"industry": "media"
}
]
}
]
},
{
"cells": [
{
"fname": "James",
"label": "fname",
"editable": false
},
{
"label": "lname",
"lname": "Diamond",
"editable": true,
"details": [
{
"industry": "music"
},
{
"industry": "media"
}
]
}
]
},
{
"cells": [
{
"fname": "Aba",
"label": "fname",
"editable": true
},
{
"label": "lanme",
"lname": "Duck",
"editable": true,
"details": [
{
"industry": "finance"
},
{
"industry": "technology"
},
{
"industry": "media"
}
]
}
]
},
{
"cells": [
{
"fname": "Henry",
"label": "fname",
"editable": true
},
{
"label": "lname",
"lname": "Hebert",
"editable": true,
"details": [
{
"industry": "finance"
},
{
"industry": "HR"
},
{
"industry": "media"
},
{
"industry": "IT"
}
]
}
]
}
]
}
}
}
All cells are editable.
I'm trying to loop through each row and then each cell to find out the number of properties in "details". In inline editing mode, it should be a text field and the value of text field should be the corresponding number of properties.
Example - for Marc Kalra, the details cell will be a text field with a value of 2.
Here's my code
loadComplete: function(data){
var x, y, cellProp;
for (x = 0; x < data.wrapper.table.rows.length; x++) {
var cellCount = data.wrapper.table.rows[x].cells.length;
for (y = 0; y < cellCount; y += 1) {
cellProp = data.wrapper.table.rows[x].cells[y];
var prop, listCount, cellLabel;
listCount = data.wrapper.table.rows[x].cells[y].details.length;
cellLabel = data.wrapper.table.rows[x].cells[y].label;
function gridCustomEdit (value, options){
var el = document.createElement("input");
el.type="text";
el.value = listCount;
return el;
}
for (prop in cellProp) { if (prop === "details"){
$("#jqgrid").setColProp(cellLabel, {
editable: true,
edittype: "custom",
editoptions: {
custom_element: gridCustomEdit
}
});
}
}
}
}
PROBLEM - is that el.value = listCount; in the above code always returns 4 as the number of properties for each row/cell.
Can someone point me my mistake?
UPDATED
loadComplete: function(data){
var x, y, cellProp;
for (x = 0; x < data.wrapper.table.rows.length; x++) {
var cellCount = data.wrapper.table.rows[x].cells.length;
for (y = 0; y < cellCount; y += 1) {
cellProp = data.wrapper.table.rows[x].cells[y];
var isEditable = cellProp.editable;
if (isEditable === false) {
$("#jqgrid").setColProp(cellProp.label, {
editable: false
});
}else {
var listCount, cellLabel;
listCount = data.wrapper.table.rows[x].cells[y].details.length;
cellLabel = data.form.summary.rows[x].cells[y].label;
$("#jqgrid").setColProp(cellLabel, {
editable: true,
editoptions: {
dataInit: function(elem){
$(elem).myPlugin({listCount: listCount})
}
}
})
}
}
}
}
PLUGIN CODE
(function( $ ){
$.fn.extend({
myPlugin: function(options){
var defaults = {
listCount: 0
};
var options = $.extend(defaults, options);
var o = options;
alert(o.listCount);
if (o.listCount === 3){
$(elem).html("<input type='text' value='" + o.listCount + "'>")
} else {
$(elem).html("<select>") **// this should be a dropdown with values = properties of `details`**
}
}
})
})
GRID CODE
$("#jqgrid").jqGrid({
datatype: "json",
colNames:['fname','lname'],
colModel:[
{name:'fname',index:'fname'},
{name:'lname',index:'lname'},
],
jsonReader: {
root: "wrapper.table.rows",
repeatitems: false
},
onSelectRow: function(id){
$(this).jqGrid('editRow',id);
},
})
If details exist + number of properties in details = 3, then lname is displayed as a text field in inline editing mode.
If details exist + number of properties in details > 3, then lname is displayed as a select field in inline editing mode.
The method setColProp set property for the column and not for the cell in the column. So if you set in the loop setColProp for the same column many times only the last setting will be applied. Because the last row (for "Love Hebert") in your data has 4 items in the details array only the value will be used.
The next error is that you define gridCustomEdit function which has reference to external variable listCount. In the case there are only one instance of the function with the last value of the variable. If you need to have many function instances with different values you should use closure.
In your case it seems to me you can implement all what you need even without the usage of closure and without custom editing (edittype:'custom' with custom_element and custom_value).
I suppose that all what you need to do is to set setColProp inside of onSelectRow (or before the call of editRow) and not inside of loadComplete. See the answer for more information. If you need to change the edittype of the column you can do this in the same way. So you can for example dynamically set edittype: "text" and set editoptions with dataInit which change the value of the element.
If it is needed you can even dynamically switch the edittype between edittype: "text" and edittype: "select" and set all editoptions which are required.
In the way you will receive simple and flexible code which don't use custom editing at all.