I have WEbDataconnector in Javascript, which download data from .json file and load table:
myConnector.getData = function(table, doneCallback) {
$.getJSON("http://url/api/opls/number/tasks?apiKey", function(resp) {
var feat = resp.data,
tableData = [];
// Iterate over the JSON object
var keys = Object.keys(feat);
for (var i = 0, len = keys.length; i < len; i++) {
tableData.push({
"taskId": feat[keys[i]].taskId,
"owner": feat[keys[i]].owner,
"description": feat[keys[i]].description,
"responsible": feat[keys[i]].responsible,
});
}
table.appendRows(tableData);
doneCallback();
});
My problem is that i have multiple URL, with different numbers and apikeys. And i need combine data from all URLs into one table.
Could anyone please help me out? Thank you.
edit:
If i add more elements to data.push() method it ends with:"null is not an object" because some objects in JSON are null,
example of JSON:
"1026533": {
"taskId": 1026533,
"opl": 6919,
"owner": "name",
"description": "text",
"responsible": "name",
"taskStart": {
"date": "2016-03-21 13:28:11.000000",
"timezone_type": 3,
"timezone": "Europe\/Prague"
but sometimes there is an element taskStart with null:
"1026535": {
"taskId": 1026535,
"opl": 6919,
"owner": "name",
"description": "text",
"responsible": "name",
"taskStart": null,
how can i check this and push all data or null? thank you
Use recursion and named function expression with a list of URL.
myConnector.getData = function (table, doneCallback) {
var urls = [ /* the urls */]
if (urls.length == 0) return doneCallback();
$.getJSON(urls.shift(), function callback(resp) {
var feat = resp.data,
tableData = [];
// Iterate over the JSON object
var keys = Object.keys(feat);
for (var i = 0, len = keys.length; i < len; i++) {
tableData.push({
"taskId": feat[keys[i]].taskId,
"owner": feat[keys[i]].owner,
"description": feat[keys[i]].description,
"responsible": feat[keys[i]].responsible,
});
}
table.appendRows(tableData);
var url = urls.shift();
if (url) return $.getJSON(url, callback); // recursion happens here
doneCallback();
});
}
Keep an array containing all the urls that you need to fetchs.
urls = [
'http://url/api/opls/number1/tasks?apiKey1',
'http://url/api/opls/number2/tasks?apiKey2',
'http://url/api/opls/number3/tasks?apiKey3'
];
Then iterate over the array and send an ajax request on each url.
urls.forEach(function(url) {
$.getJSON(url, function(resp) {
var feat = resp.data,
let data = [];
// Iterate over the JSON object
var keys = Object.keys(feat);
for (var i = 0, len = keys.length; i < len; i++) {
data.push({
"taskId": feat[keys[i]].taskId,
"owner": feat[keys[i]].owner,
"description": feat[keys[i]].description,
"responsible": feat[keys[i]].responsible,
});
}
table.appendRows(data);
doneCallback();
});
});
Related
I am trying to loop through an array that is part of a JSON object from a page speed insights call to add all of the unused javascript Urls to a google sheet using the script editor.
Here is an example of the JSON object:
"audits": {
"unused-javascript": {
"id": "unused-javascript",
"title": "Remove unused JavaScript",
"description": "Remove unused JavaScript to reduce bytes consumed by network activity. [Learn more](https://web.dev/unused-javascript/).",
"score": 0.43,
"scoreDisplayMode": "numeric",
"numericValue": 1350,
"numericUnit": "millisecond",
"displayValue": "Potential savings of 231 KiB",
"details": {
"type": "opportunity",
"headings": [
{
"key": "url",
"valueType": "url",
"subItemsHeading": {
"key": "source",
"valueType": "code"
},
"label": "URL"
},
{
"key": "totalBytes",
"valueType": "bytes",
"subItemsHeading": {
"key": "sourceBytes"
},
"label": "Transfer Size"
},
{
"key": "wastedBytes",
"valueType": "bytes",
"subItemsHeading": {
"key": "sourceWastedBytes"
},
"label": "Potential Savings"
}
],
"items": [
{
"url": "https://connect.facebook.net/signals/config/1926350194273730?v=2.9.2=stable",
"totalBytes": 140229,
"wastedBytes": 108197,
"wastedPercent": 77.15757011763822
},
{
"url": "https://static.example.com/domain.us.modern.bundle.a02fef045566caf5d464.js",
"totalBytes": 306716,
"wastedBytes": 106243,
"wastedPercent": 34.63892414884589
},
{
"url": "https://www.googletagmanager.com/gtm.js?id=GTM-KZ",
"totalBytes": 127214,
"wastedBytes": 21845,
"wastedPercent": 17.17151000374831
}
],
"overallSavingsMs": 1350,
"overallSavingsBytes": 236285
}
},
I am attempting to loop through the "items" array within the "unused-javascript" object and get all of the urls to show in google sheets.
Here is the code I have within the script editor. When I run this, only one URL shows on the sheet. However, I am trying to get all of the URLs added to the sheet.
function pageSpeed(Url) {
var key = "AIzaSyAyHY";
var serviceUrl = "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=" + Url + "&key=" + key;
var array = [];
if (key == "YOUR_API_KEY")
return "Please enter your API key to the script";
var response = UrlFetchApp.fetch(serviceUrl);
if (response.getResponseCode() == 200) {
var content = JSON.parse(response.getContentText());
if ((content != null) && (content["lighthouseResult"] != null)) {
if (content["captchaResult"]) {
var timetointeractive = content["lighthouseResult"]["audits"]["interactive"]["displayValue"].slice(0, -2);
var firstcontentfulpaint = content["lighthouseResult"]["audits"]["first-contentful-paint"]["displayValue"].slice(0, -2);
var firstmeaningfulpaint = content["lighthouseResult"]["audits"]["first-meaningful-paint"]["displayValue"].slice(0, -2);
var speedindex = content["lighthouseResult"]["audits"]["speed-index"]["displayValue"].slice(0, -2);
var unusedJs = content["lighthouseResult"]["audits"]["unused-javascript"]["details"]["items"];
for (var i = 0; i < unusedJs.items.length; i++) {
var unusedUrl;
unusedUrl = unusedJs[i]["url"]
}
}
else {
var timetointeractive = "An error occured";
var firstcontentfulpaint = "An error occured";
var firstmeaningfulpaint = "An error occured";
var speedindex = "An error occured";
var unusedJs = "An error occured";
}
}
var currentDate = new Date().toJSON().slice(0, 10).replace(/-/g, '/');
array.push([timetointeractive, firstcontentfulpaint, firstmeaningfulpaint, speedindex, currentDate, "complete", unusedUrl]);
Utilities.sleep(1000);
return array;
}
}
Any and all help is appreciated!
You're on the right track.
Take a look below at my usage of Array.prototype.map. That's the simpler route.
Your for loop would work just as well IF you declared unusedUrl outside of (ie. before) the loop AND pushed to an existing array. As it is, there's an issue of scope, so unusedUrl is redeclared on every iteration, meaning you'll only assign the last iteration's value to unusedUrl.
Both solutions are below.
Using map
var content = {
lighthouseResult: {
audits: {
'unused-javascript': {
// Other stuff
details: {
// Other stuff
items: [
{
url:
'https://connect.facebook.net/signals/config/1926350194273730?v=2.9.2=stable',
totalBytes: 140229,
wastedBytes: 108197,
wastedPercent: 77.15757011763822,
},
{
url:
'https://static.example.com/domain.us.modern.bundle.a02fef045566caf5d464.js',
totalBytes: 306716,
wastedBytes: 106243,
wastedPercent: 34.63892414884589,
},
{
url: 'https://www.googletagmanager.com/gtm.js?id=GTM-KZ',
totalBytes: 127214,
wastedBytes: 21845,
wastedPercent: 17.17151000374831,
},
],
overallSavingsMs: 1350,
overallSavingsBytes: 236285,
},
},
},
},
}
var items = content.lighthouseResult.audits['unused-javascript'].details.items
var unusedUrls = items.map(item => item.url) // OR, using es6, items.map(({ url }) => url)
console.log(unusedUrls)
Using for
var items = content.lighthouseResult.audits['unused-javascript'].details.items
var unusedUrls = []
for (var i = 0; i < items.length; i++) {
unusedUrls.push(items[i]['url'])
}
I'm working with jQuery Sortable to create some block of codes with nested list ( for loop and function block), then I got this json string use JSON.stringify on console.log(jsonString):
{
"codes": [
[
{
"id": "code_run",
"code": "run",
"name": "code_when_run"
},
{
"id": "",
"code": "loop",
"name": "code_block_repeat",
"children": [
[
{
"id": "",
"code": "up",
"name": "code_arrow_up"
},
{
"id": "",
"code": "up",
"name": "code_arrow_up"
}
]
]
}
]
]
}
Here's my code from the jQuery sortable's example :
let oldContainer, codeBlockId, codeBlockItem;
$("ol.nest_workspace").sortable({
group: 'nested',
onDragStart: function ($item, container, _super) {
// Duplicate items of the no drop area
if(!container.options.drop)
$item.clone().insertAfter($item);
_super($item, container);
},
afterMove: function (placeholder, container) {
if(oldContainer != container){
if(oldContainer)
oldContainer.el.removeClass("active");
container.el.addClass("active");
oldContainer = container;
}
},
onDrop: function ($item, container, _super) {
container.el.removeClass("active");
$item.addClass("block_code_on_workspace");
var data = group.sortable("serialize").get();
var jsonString = JSON.stringify({"codes":data}, null, '\t');
console.log(jsonString);
_super($item, container);
},
});
How can I process the sub array (children[]) ?
I have plan to make it all block as a real codes, so it could execute with another function.
I may expect the text output printed some function like moveUp(), or if its loop with some function inside, then would be like :
for (var i = 0; i < 3; i++) {
moveUp();
}
Any help or suggest would be great, thanks!
If your JSON string will always look like this. Then you can target there “children" array like this.
I wrote this code base only on the format of the JSON that you have above.
const childrenArr = jsonString.codes[0][1].children;
Based on the code we’re you are stringifying your data this code should work.
var jsonString = JSON.stringify({"codes":data}, null, '\t');
console.log(jsonString),
ChildrenArr = jsonString.codes[0][1].children;
I've found a solution for my problem, here's the code :
$("ol.nest_workspace").sortable({
group: 'nested',
onDragStart: function ($item, container, _super) {
// Duplicate items of the no drop area
if(!container.options.drop)
$item.clone().insertAfter($item);
if($item.hasClass('RepeatCode')){
$item.attr('id','block_loop_function_drag');
}
_super($item, container);
},
afterMove: function (placeholder, container) {
if(oldContainer != container){
if(oldContainer)
oldContainer.el.removeClass("active");
container.el.addClass("active");
oldContainer = container;
}
},
onDrop: function ($item, container, _super) {
$(".coding-script").empty();
container.el.removeClass("active");
$item.addClass("block_code_on_workspace");
$hasID = document.getElementById('block_loop_function_drag');
var data = group.sortable("serialize").get();
// console.log(data);
for(var i = 0; i < data[0].length; i++){
if($hasID){
$item.attr('id','block_loop_function_'+i+'');
}
var obj = data[0][i];
if(obj.hasOwnProperty("children")){
var objChildren = obj.children[0];
console.log(obj.code +'-'+i);
ConvertToCodeScripts(obj.code, i);
for(var j = 0; j < objChildren.length; j++){
console.log('loop-'+i+'-'+objChildren[j].code);
ConvertToCodeScripts('loop-'+i+'-'+objChildren[j].code, i);
}
}
else{
console.log(obj.code);
ConvertToCodeScripts(obj.code, i);
}
console.log('lha - '+i);
}
_super($item, container);
},
});
But let me know if you guys have a better solution.
Cheers
I'm calling the below Parse Query using the Parse Server Javascript API. I have a class called Device, which has a pointer object to Device_Type which in turn has a pointer to Manufacturer.
I can successfully display the deviceID in inventoryItem, but get undefined for manufacturer, despite there being the relevant data in the JSON network return.
$scope.getDeviceItems = function () {
var query = new Parse.Query("Device");
query.include("Device_Type");
query.include("Device_Type.Manufacturer");
query.find({
success: function (results) {
$scope.deviceItems = [];
for (i = 0; i < results.length; i++) {
var d = results[i].get("Device_Type");
var m = results[i].get("Device_Type.Manufacturer");
var inventoryItem = {
deviceID: d.get("Device_ID"),
manufacturer: m.get("Manufacturer_Name")
}
};
};
};
};
How would I correctly obtain the nested pointer data into manufacturer?
Here's a sample JSON Object:
{
"results": [{
"objectId": "q3D2myHG3e",
"createdAt": "2017-07-30T22:28:05.035Z",
"updatedAt": "2017-09-19T20:40:05.580Z",
"Device_Type": {
"objectId": "Ksej3F2sdp5",
"Device_Name": "Device 1",
"createdAt": "2017-07-30T21:57:58.638Z",
"updatedAt": "2017-08-08T20:20:14.397Z",
"Manufacturer": {
"objectId": "3NahYBNIiC",
"Manufacturer_Name": "ABC Ltd",
"createdAt": "2017-07-30T21:56:40.557Z",
"updatedAt": "2017-07-30T22:13:07.425Z",
"Devices": {
"__type": "Relation",
"className": "DeviceType"
},
"__type": "Object",
"className": "DeviceManufacturer"
},
"__type": "Object",
"className": "DeviceType"
},
...
}]
}
$scope.getDeviceItems = function () {
var query = new Parse.Query("Device");
query.include("Device_Type");
query.include("Device_Type.Manufacturer");
query.find({
success: function (results) {
$scope.deviceItems = [];
for (i = 0; i < results.length; i++) {
var curResult = results[i];
var d = curResult.Device_Type;
var m = curResult.Device_Type.Manufacturer;
var inventoryItem = {
deviceID: d.Device_ID
manufacturer: m.Manufacturer_Name
}
};
};
};
};
Not sure why a map is being used a regular JS object as shown above would work easier (assuming find function just resolved with the JS object from parsing the JSON instead of turning it into a Map object)
Using a Map you need to call get twice as far as I can tell to resolve "deeper" keys.
$scope.getDeviceItems = function () {
var query = new Parse.Query("Device");
query.include("Device_Type");
query.include("Device_Type.Manufacturer");
query.find({
success: function (results) {
$scope.deviceItems = [];
for (i = 0; i < results.length; i++) {
var curResult = results[i];
var d = curResult.get('Device_Type');
var m = curResult.get('Device_Type').get('Manufacturer'); // or d.get('Manufacturer')
var inventoryItem = {
deviceID: d.get('Device_ID')
manufacturer: m.get('Manufacturer_Name')
}
};
};
};
};
var testObj = new Map();
testObj.set('a', new Map());
testObj.get('a').set('b', 4);
console.log(testObj.get('a').get('b'))
I have this JSON that I'm getting back from a web service call:
{
"name": "My Name",
"path": "my path",
"id": "44",
"type": "my type",
"classes": "my classes"
},
{
"name": "his Name",
"path": "his path",
"id": "76",
"type": "his type",
"classes": "his classes"
}
I then need to convert it to this format
{
"44" : { "name" : "My Name", "path" : "my path" },
"76" : { "name" : "his Name", "path" : "his path" }
}
My initial naive attempt was this:
var myData = [];
for (var i = 0; i < rawData.length; i++) {
myData.push({
rawData[i].id :
{
"path": rawData[i].path,
"name": rawData[i].name
}
});
which fails with syntax errors, so I eventually got to this:
var myData = [];
for (var i = 0; i < rawData.length; i++) {
myData.push(rawData[i].id,
{
"path": rawData[i].path,
"name": rawData[i].name
});
and it mostly works. My array is populated, but the problem is that my myData array doesn't have the "44", and "76" part of the object, just the { "name" : "", "path" : "" } part. I expect this is due to a lack of understanding on my part of how JSON and javscript objects work.
Your desired output isn't an array, so that's your starting point. The output you've said you want is an object, not an array.
You build your result by creating a blank object and then adding the objects to it using id as the key:
var myData = {};
rawData.forEach(function(entry) {
myData[entry.id] = {
name: entry.name,
path: entry.path
};
});
Or if you don't want to use forEach (it's ES5, but can be shimmed for older browsers), the old-fashioned way:
var myData = {};
var index, entry;
for (index = 0; index < rawData.length; ++index) {
entry = rawData[index];
myData[entry.id] = {
name: entry.name,
path: entry.path
};
}
Don't use Array.prototype.push(), use the square bracket notation and define your output as an object not an array.
var myData = {};
for (var i = 0; i < rawData.length; i++) {
myData[rawData[i].id] = {
"path": rawData[i].path,
"name": rawData[i].name
}
}
You need to convert your id to a string?
var myData = {};
for (var i = 0; i < rawData.length; i++) {
myData[String(rawData[i].id)] = {
"path": rawData[i].path,
"name": rawData[i].name
};
}
A variation on what other posters have written:
// Create a new empty object.
var out = {};
// Loop over your array of objects
// Add the each object id as a key to the output object, and the object as the value.
for (var i = 0, l = arr.length; i <l; i++) {
var obj = arr[i];
out[obj.id] = obj;
// Delete the properties from the newly added object you don't want.
delete obj.id;
delete obj.type;
delete obj.classes;
}
I have an ko.observableArray with two dimensions, i.e. "id" and "name".
Id will always be distinct, but name can hold the same value.
self.myArray = ko.observableArray( [
{ "id": "1", "name": "Barbara" },
{ "id": "2", "name": "Edwin" },
{ "id": "3", "name": "Barbara" }
] );
However I want to filter the array so that my result holds only the first occurrence of "name".
The result I want is:
self. myFilteredArray = [
{ "id": "1", "name": "Barbara" },
{ "id": "2", "name": "Edwin" }
];
I have been trying to figure this out using ko.utils.arrayGetDistinctValues(), but how can I utilize it on solely one chosen dimension?
You could use a computed for this:
viewModel.myFilteredArray = ko.computed(function() {
var rv = [], names = [];
for(var i=0; i<this.myArray().length; i++) {
if(names.indexOf(this.myArray()[i].name) === -1) {
rv.push(this.myArray()[i]);
names.push(this.myArray()[i].name);
}
}
return rv;
}, viewModel);
I can suggest a function, that loops through the array, builds map of property values for each item and checks, whether the current value was already added. Something like this:
function filterByFirstOccurance(arr, prop) {
var propValuesHash = {},
result = [];
for (var i = 0, l = arr.length; i < l; i++) {
var item = arr[i],
propValue = item[prop];
if (item.hasOwnProperty(prop) && !propValuesHash[propValue]) {
propValuesHash[propValue] = true;
result.push(item);
}
}
return result;
};
Fiddle