I have an array of objects that I am using as a dataset in an interactive data dashboard. I want to add a new feature that displays data from only one object at a time, rather than pulling data from all objects (which I am already doing and it works well). As a test case, I have created a simple array:
var test1 = [
[{
"name": "Piece One",
"amount": 5
}, {
"name": "Piece Two",
"amount": 5
}, {
"name": "Piece Three",
"amount": 5
}],
[{
"name": "Piece One",
"amount": 1
}, {
"name": "Piece Two",
"amount": 1
}, {
"name": "Piece Three",
"amount": 5
}]
];
and the Vega-lite javascript:
var pieCreate = {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"title": "A pie chart",
"description": "A simple pie chart with embedded data.",
"width": "container",
"height": "container",
"data": {
"values": test1[0]
},
"mark": "arc",
"encoding": {
"theta": {
"field": "amount",
"type": "quantitative"
},
"color": {
"field": "name",
"type": "nominal",
"legend": null
}
}
};
This works, but I want the user to be able to choose which object to display (in the dashboard, each object contains data on different schools, and I want the user to be able to choose which school's data to display using a dropdown menu). My first thought was to set up a signal in the "data": {"values": field that would change the number in brackets to the array I want, but after a lot of trial and error, I think that may be a dead end. Signals should work to modify "field": "amount" and "field": "name" but I've tried every iteration of [0].amount that I can think of, while dropping the brackets from test1[0] and nothing has worked. If I can manage to access the object by directly referencing it in "field": I believe I can figure out the process using a signal and html form, but I'm starting to doubt if I'm even on the right track here.
I also tried the process outlined here in the vega-lite documentation: https://vega.github.io/vega-lite/tutorials/streaming.html, but it's doing something much more complicated than what I'm trying to do, and my javascript knowledge isn't sufficient to break it down to something usable. Does anyone have any ideas on how to make this work, using any of the above approaches (or a new, better one)?
You can use the vega Api's to change the data. On your selection, add a change event and on some conditions you can toggle between your data using those API's.
Refer the below snippet or fiddle:
var test1 = [
[{
"name": "Piece One",
"amount": 5
}, {
"name": "Piece Two",
"amount": 5
}, {
"name": "Piece Three",
"amount": 5
}],
[{
"name": "Piece One",
"amount": 1
}, {
"name": "Piece Two",
"amount": 1
}, {
"name": "Piece Three",
"amount": 5
}]
];
var yourVlSpec = {
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"title": "A pie chart",
"description": "A simple pie chart with embedded data.",
"width": "350",
"height": "400",
"data": {
"values": test1[0]
},
"mark": "arc",
"encoding": {
"theta": {
"field": "amount",
"type": "quantitative"
},
"color": {
"field": "name",
"type": "nominal",
"legend": null
}
}
}
var view;
vegaEmbed("#vis", yourVlSpec).then(res => {
view = res.view;
});
function handleChange(a, b) {
var selectValue = document.getElementById("myselect").value;
if (selectValue == 'A') {
view.data('source_0', test1[0]);
} else {
view.data('source_0', test1[1]);
}
view.runAsync();
}
<script src="https://cdn.jsdelivr.net/npm/vega#5.20.2/build/vega.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-lite#5.0.0/build/vega-lite.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed#6.17.0/build/vega-embed.min.js"></script>
<select id="myselect" style="width:100px;" onchange="handleChange()">
<option>A</option>
<option>B</option>
</select>
<br>
<div id="vis"></div>
Related
I am using Elastic version 6.8, created one index into whose schema is as follow:
{
"properties": {
"title": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
},
"tags": {
"type": "keyword",
"fields": {
"raw": {
"type": "text"
}
}
}
}}
and I have added following documents into it
[{
"title": "one",
"tags": ["html", "css", "javascript"]
}, {
"title": "two",
"tags": ["java", "jsp", "servlet"]
}, {
"title": "three",
"tags": ["spring", "java"]
}, {
"title": "four",
"tags": ["react", "angular", "javascript"]
}, {
"title": "five",
"tags": ["java"]
}, {
"title": "six",
"tags": []
}]
now I have more than 10 millions document in elastic search. Now I want to search following cases:
List all tags. with unique result (using skip, limit) skip value change but limit is fixed.so here I want result like
html,
css,
javascript,
java,
jsp,
servlet,
spring,
react,
angular
Partil search inside tags, it means if I search using act then it should give result as : react this also using skip limit.
How I can get this using Elastic search query. please help me here?
You can find unique possible value by using term aggregation.
GET yourindex/_search
{
"size": 0,
"aggs": {
"all_tags": {
"terms": {
"field": "tags",
"size": 100
}
}
}
}
"size":100 Get at most 100 unique values. Default is 10. You can increase more but it will include cost. You can check more on doc.
For partial search you can use wildcard query OR you can try N-Gram Tokeninzer. Both will allow to do partial search but wildcard query will be costly. You can evaluate according to your use case.
Using javascript, vega editor and this data: https://github.com/StanWaldron/StanWaldron.github.io/blob/main/final.csv, which I got from SportDataAPI and organised using pandas, I have attempted to make a graph that plots Crystal Palace's home and away goal differences over the course of the 2020/21 season. As you can see though, I can't get a smooth plot.
The issue seems to be that the NaNs in the data are being put in as 0s for home games when they have played away and vice versa. When trying to resolve this by looping through like so:
for c in final['Home_GD']:
if math.isnan(c) == True:
c = 0.0
It doesn't seem to change the data at all. If this worked, I would just be able to simply add it to the previous value and plot it that way, for every game.
In the javascript side I have also used layers, but have struggled to find any way of separating the data completely and then using two different data sources which I can layer on the same graph.
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"title": {
"text": "Home and Away Goal Difference For Crystal Palace 2020/21",
"subtitle":["Exclusively in the Premier League"],
"subtitleFontStyle":"italic",
"subtitleFontSize":10,
"anchor": "start",
"color": "black"},
"data": {
"url":
"https://raw.githubusercontent.com/StanWaldron/StanWaldron.github.io/main/final.csv"
},
"repeat": {"layer": ["Away_GD", "Home_GD"]},
"height": 300,
"width": 300,
"spec": {
"mark": {
"type":"line",
"strokeWidth":2},
"encoding": {
"x": {
"field": "Date",
"type": "temporal",
"title":null,
"axis":{
"grid": false
}},
"y": {
"field": {"repeat": "layer"},
"type": "quantitative",
"title": null},
"color": {
"datum": {"repeat": "layer"},
"scale": {"range": ["blue", "red"]},
"legend": {
"orient":"top-left",
"fillColor":"white"}}
}
}
}
I would probably do this by filtering each value individually within a layer; here's an example (open in editor):
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"url": "https://raw.githubusercontent.com/StanWaldron/StanWaldron.github.io/main/final.csv"
},
"transform": [{"fold": ["Home_GD", "Away_GD"], "as": ["key", "Goals"]}],
"encoding": {
"x": {"field": "Date", "type": "temporal"},
"y": {"field": "Goals", "type": "quantitative"},
"color": {"field": "key", "type": "nominal"}
},
"layer": [
{
"transform": [{"filter": "datum.key == 'Home_GD' && datum.Home_GD != ''"}],
"mark": "line"
},
{
"transform": [{"filter": "datum.key == 'Away_GD' && datum.Away_GD != ''"}],
"mark": "line"
}
]
}
I hope you guys are having a wonderful day.
I have set up a webhook in my woocommerce that sends JSON data to Google sheets. The webhook has been working great for months now, just today, I am having some trouble with it. I have tracked the issue to be in google sheets receiving the JSON data, but I don't know why this is happening.
Let me explain.
https://docs.google.com/spreadsheets/d/18G-yVDjYeccl6kznpZgSuRTysRMAu57pwY2oGf6-KWI/edit?usp=sharing
This is the google sheet, when it gets Woocommerce JSON data, it populates a new row.
The problem
Sometimes google sheets doesn't populate the row upon receiving a new order. The problem doesn't lie with woocommerce, because I have checked woocommerce with reqbin and the webhook fires with every order.
Furthermore, when I send requests from reqbin.com to my sheet, the sheet performs the operation successfully 5-6 out of 10 times. Other times it shows an error.
The Error
The error is due to google sheets not being able to parse JSON data, because the JSON data it receives 5 out of 10 times is not proper JSON data. Other 5 times, it is just as it should be. I have put a catch statement if the sheet is unable to parse JSON. Instead of appending new row with the parsed data, it appends the raw received data to the sheet.
It is clear now that there is some issue with google sheets handling that JSON data because when the same data is sent from reqbin.com to webhook.site, it is perfectly as it should be 10/10 times.
How to reproduce the issue
Open this google sheet. https://docs.google.com/spreadsheets/d/18G-yVDjYeccl6kznpZgSuRTysRMAu57pwY2oGf6-KWI/edit?usp=sharing
Open reqbin.com and webhook.site, and send the following JSON from reqbin.com to webhook.site 10 times to see if any kind of error occurs.
{ "id": 47222, "parent_id": 0, "status": "processing", "currency": "PKR", "version": "5.1.0","prices_include_tax": false, "date_created": "2021-06-10T01:23:46", "date_modified": "2021-06-10T01:23:46", "discount_total": "0", "discount_tax": "0", "shipping_total": "150", "shipping_tax": "0", "cart_tax": "0", "total": "1850", "total_tax": "0", "customer_id": 0, "order_key": "wc_order_7gIuR7px6MX9C", "billing": { "first_name": "Name", "last_name": "", "company": "", "address_1": "Address", "address_2": "", "city": "City", "state": "", "postcode": "", "country": "PK", "email": "email#email.com", "phone": "1234" }, "shipping": { "first_name": "Name", "last_name": "", "company": "", "address_1": "Address", "address_2": "", "city": "City", "state": "", "postcode": "", "country": "Country" }, "payment_method": "cod", "payment_method_title": "Cash on delivery", "transaction_id": "", "customer_ip_address": "8.8.8.8", "customer_user_agent": "Mozilla/5.0 (Linux; Android 11; M2102J20SG) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.88 Mobile Safari/537.36", "created_via": "checkout", "customer_note": "", "date_completed": null, "date_paid": null, "cart_hash": "64d834c72eecc8e32b9d83fd67d10d9c", "number": "47222", "meta_data": [ { "id": 869388, "key": "_shipping_calculator", "value": "" }, { "id": 869389, "key": "is_vat_exempt", "value": "no" }, { "id": 869391, "key": "_wfacp_report_data", "value": { "wfacp_total": "0.00" } }, { "id": 869392, "key": "_woofunnel_cid", "value": "4" }, { "id": 869393, "key": "_wfacp_post_id", "value": "24852" }, { "id": 869394, "key": "_wfacp_source", "value": "https://website.com/checkouts/checkout-page/" }, { "id": 869395, "key": "_wfacp_timezone", "value": "Asia/Karachi" }, { "id": 869396, "key": "order_comments", "value": "" }, { "id": 869412, "key": "_new_order_email_sent", "value": "true" }, { "id": 869424, "key": "_woofunnel_custid", "value": "4" }, { "id": 869425, "key": "_pys_purchase_event_fired", "value": "1" }, { "id": 869426, "key": "_wfob_stats_ids", "value": [] }, { "id": 869427, "key": "_wfocu_thankyou_visited", "value": "yes" } ], "line_items": [ { "id": 35114, "name": "MTECH Ultra Resilient Knife", "product_id": 11074, "variation_id": 0, "quantity": 1, "tax_class": "", "subtotal": "1700", "subtotal_tax": "0", "total": "1700", "total_tax": "0", "taxes": [], "meta_data": [], "sku": "", "price": 1700, "parent_name": null } ], "tax_lines": [], "shipping_lines": [ { "id": 35115, "method_title": "Fast Shipping (2-4 Days)", "method_id": "flat_rate", "instance_id": "1", "total": "150", "total_tax": "0", "taxes": [], "meta_data": [ { "id": 275053, "key": "Items", "value": "MTECH Ultra Resilient Knife × 1", "display_key": "Items", "display_value": "MTECH Ultra Resilient Knife × 1" } ] } ], "fee_lines": [], "coupon_lines": [], "refunds": [], "date_created_gmt": "2021-06-09T20:23:46", "date_modified_gmt":"2021-06-09T20:23:46", "date_completed_gmt": null, "date_paid_gmt": null, "currency_symbol": "₨","_links": { "self": [ { "href": "https://website.com/wp-json/wc/v3/orders/47222" } ],"collection": [ { "href": "https://website.com/wp-json/wc/v3/orders" } ] } }
Now send the same data to the following google sheet to see if it appends the row correctly each time.
https://script.google.com/macros/s/AKfycbxupm9bje86F4PQQkyys_LWtXs_kj279R0ipgnZ-cLd7aiEADf1AN_prhk28vOPW9JsRQ/exec
How do I solve the issue? Please let me know if you need any more information. Thanks.
Edit:
Instead of getting a full JSON body like mentioned above, the google sheets seems to be getting the following JSON.
{contextPath=, queryString=, parameter={}, postData=FileUpload, parameters={}, contentLength=3981.0}
I would like to know why the google sheets default parameter (e) contains this instead of a full JSON body sent to it.
Edit # 2
I would like to know why the google sheets default parameter (e) contains this instead of a full JSON body sent to it.
This is because (e) has a body which will always contain those parameters. The error is due to Google Sheets receiving an empty JSON body. I am still unable to understand why this happens. When I send the same JSON to API testing sites, they always receive full JSON body. Google sheets, in some cases, does not. Why is that?
I managed to solve the issue with some trial and error. For anyone facing the same issue in the future, here is what worked for me.
I was using e.postData.contents to get the JSON body but this seems to have stopped working, which was causing the JSON body to be empty. I tried e.postData.getDataAsString(); which seems to be working just fine and the issue has been resolved.
Currently working with this highcharts code:
https://jsfiddle.net/umL154cd/
It works with external data source like shown below:
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=activity.json&callback=?', function (activity) {
$.each(activity.datasets, function (i, dataset) { ///
But I'd like to truncate the data and put it inside the code itself by simply anouncing json.variable:
var datafromjson =
{
"xData": [0.001567,0.011765,0.022194],
"datasets": [{
"name": "Speed",
"data": [13.833,12.524,11.441,10.651],
"unit": "km/h",
"type": "line",
"valueDecimals": 1
}, {
"name": "Elevation",
"data": [26.857,27,27.111,27.2,27.272],
"unit": "m",
"type": "area",
"valueDecimals": 0
}, {
"name": "Heart rate",
"data": [101,98,103],
"unit": "bpm",
"type": "area",
"valueDecimals": 0
}]
};
How do I replace $.getJSON request so the script will take the turncated in-script data insted of accessing external data?
Thank you!
what I am trying to do
I need to get all of the twitter usernames from a returned JSON value, currently being returned inside arrows, example would be <jgallardo949>
Assign those values as a variables
append that variable to a url from twitter.com
Take the string before the twitter username and assign that as a value
Create a new variable with the combination of other generated variables and wrap it in desired HTML
Display the desired new HTML inside of a div
Do this for every instance of strings generated inside of any div with a class of author
Sample JSON
"contributed_by":"Sasha <SashaMasondeCaires>"
Desired HTML output
Sasha #SashaMasondeCaires
Conceptual solution
Since it is currently returning in that format, name <twitter username> then what I want to do is replace < with <a href="https://www.twitter.com/ and > with </a>, but what then should i do with the name, perhaps make that a variable so that it would be something like
//To get the string inside the <>
var authTw = document.getElementsByClassName("author")[0].innerHTML;
//wrapping solution needs work
var twUsername = "<span>#" + authTw.match(/\<([a-z]*)\>/)[1] + "</span>"
document.getElementsByClassName("author")[0].innerHTML=twUsername;
var authorName = // I need to get the string before the < symbol
var contributorInfo = authorName + '' + twUsername + '';
And then I need to write the resulting contributorInfo in the div with the class .author
Current code
HTML
<div class="author">{{ beer.contributor }}</div>
JS Babel - Axios
contributor: api.contributed_by,
API Endpoint
https://api.punkapi.com/v2/beers/random
JSON - sample
[{
"id": 126,
"name": "Jet Black Heart",
"tagline": "Oatmeal Milk Stout. Dark. Roasty. Velvety.",
"first_brewed": "01/2016",
"description": "Good things come to those who wait. This smooth and roasty oatmeal milk stout won our 2015 Prototype Challenge at a canter. Roasty coffee and chocolate lead to a decadent, full-bodied richness of near uncharted depths with a velvet mouthfeel from the addition of oatmeal and a touch of wheat. This is complemented at every turn by the Magnum and Sorachi Ace hops, with the latter bringing an intensity of smooth vanilla and dark berry fruit on the long, rewarding finish.",
"image_url": "https://images.punkapi.com/v2/126.png",
"abv": 4.7,
"ibu": 45,
"target_fg": 1019,
"target_og": 1055,
"ebc": 200,
"srm": 100,
"ph": 4.4,
"attenuation_level": 70,
"volume": {
"value": 20,
"unit": "liters"
},
"boil_volume": {
"value": 25,
"unit": "liters"
},
"method": {
"mash_temp": [{
"temp": {
"value": 65,
"unit": "celsius"
},
"duration": 75
}],
"fermentation": {
"temp": {
"value": 19,
"unit": "celsius"
}
},
"twist": null
},
"ingredients": {
"malt": [{
"name": "Pale Ale",
"amount": {
"value": 2.75,
"unit": "kilograms"
}
}, {
"name": "Wheat",
"amount": {
"value": 0.25,
"unit": "kilograms"
}
}, {
"name": "Dark Crystal",
"amount": {
"value": 0.19,
"unit": "kilograms"
}
}, {
"name": "Brown",
"amount": {
"value": 0.38,
"unit": "kilograms"
}
}, {
"name": "Black",
"amount": {
"value": 0.19,
"unit": "kilograms"
}
}, {
"name": "Carafa Special Malt Type 1",
"amount": {
"value": 0.19,
"unit": "kilograms"
}
}, {
"name": "Flaked Oats",
"amount": {
"value": 0.38,
"unit": "kilograms"
}
}, {
"name": "Crystal 150",
"amount": {
"value": 0.25,
"unit": "kilograms"
}
}, {
"name": "Lactose",
"amount": {
"value": 0.38,
"unit": "kilograms"
}
}],
"hops": [{
"name": "Magnum",
"amount": {
"value": 12.5,
"unit": "grams"
},
"add": "start",
"attribute": "bitter"
}, {
"name": "Sorachi Ace",
"amount": {
"value": 6.3,
"unit": "grams"
},
"add": "middle",
"attribute": "flavour"
}],
"yeast": "Wyeast 1056 - American Ale™"
},
"food_pairing": ["Oyster beignets", "Beef shin stew", "A Shakin' jesse"],
"brewers_tips": "There's a lot of speciality malt in the mash. Make sure you take the run off nice and steady – increase the flow too much and pull in the bed at your peril.",
"contributed_by": "Sasha <SashaMasondeCaires>"
}]
Edit 1
One answer partially helped, and this is my current pen
Since I am writing strings multiple times to divs with a class of author
HTML example
<div class="author">Joe <crabshack></div>
<div class="author">juan <tacotruck></div>
<div class="author">Jesse <Canvas></div>
Current attempted JS
var user = document.getElementsByClassName('author').innerHTML;
var matches = user.match(/(.*)\s\<(.*)\>/);
var output = `${matches[1]} #${matches[2]}`;
document.body.innerHTML = output;
The part that is the problem is var user = document.getElementsByClassName('author').innerHTML;
Edit 3
When i tried
var user = document.querySelector(".author").innerHTML;
it was only giving me the first of that class, but i need to get all the values.
Here is how-to using javascript template literals ${variable} and a Regex /(.*)\s\<([a-z]*)\>/.
Stack snippet
var user = "Sasha <SashaMasondeCaires>";
var matches = user.match(/(.*)\s\<(.*)\>/);
var output = `${matches[1]} #${matches[2]}`;
document.body.innerHTML = output;
Updated based on a comment/jsfiddle demo
Here is an updated version of your demo code
var user = document.getElementsByClassName('author');
for (var i = 0; i < user.length; i++) {
var matches = user[i].innerHTML.match(/(.*)\s\<([a-z]*)\>/);
var output = `${matches[1]} #${matches[2]}<br>`;
document.body.innerHTML += output;
}
.author {
display: none;
}
<div class="author">Joe <crabshack></div>
<div class="author">juan <tacotruck></div>
<div class="author">Joe <Canvas></div>
<div id="author">Juan Gallardo <JGallardo949></div>
I guess the easiest to parse this is just:
const [name, twitter] = input.split(">")[0].split("<").map(str => str.trim());
return `${name} <a href="twitter.com/${twitter}" >#${twitter}</a>`;