Plotting multiple Points from html spans in ArcGIS - arcgis

I'm trying to plot multiple Points on an ArcGIS map using span#longitude and span#latitude in the HTML. I can get the very first point to plot, but not any subsequent points.
I'm new to ArcGIS, and my javascript knowledge is limited. Any help is appreciated!
<script>
var map, agraphicsLayer, symbol;
function addPointtoMap(x, y) {
require([
"esri/geometry/Point",
"esri/graphic",
"dojo/domReady!"],
function(Point, Graphic) {
var pt = new Point(x, y);
map.centerAt(pt);
agraphicsLayer.add(new Graphic(pt, symbol));
});
}
(function($) {
if($("div#mapDiv").length) {
$.getScript( "http://js.arcgis.com/3.14/" )
.done(function( script, textStatus ) {
require(["esri/map",
"esri/symbols/SimpleMarkerSymbol",
"esri/geometry/Point",
"esri/graphic",
"esri/Color",
"esri/layers/GraphicsLayer",
"dojo/domReady!"
],
function(
Map,
SimpleMarkerSymbol,
Point,
Graphic,
Color,
GraphicsLayer) {
map = new Map("mapDiv", {
center: [-56.049, 32.485],
zoom: 5,
basemap: "topo",
logo: false
});
map.on("load", function() {
map.disableScrollWheelZoom();
});
agraphicsLayer = new GraphicsLayer();
map.addLayer(agraphicsLayer);
symbol = new SimpleMarkerSymbol();
symbol.setColor(new Color("#00ADA1"));
var pt = new Point($("span#longitude").html(), $("span#latitude").html());
map.centerAt(pt);
agraphicsLayer.add(new Graphic(pt, symbol));
});
})
.fail(function( jqxhr, settings, exception ) { });
}
</script>
<div id="mapDiv"></div>
<span id="longitude">37.82</span>
<span id="latitude">-2.28</span>
<span id="longitude">34.82</span>
<span id="latitude">1.36</span>
<span id="longitude">34.31</span>
<span id="latitude">-0.67</span>
<span id="longitude">40.19</span>
<span id="latitude">.10</span>

in both the HTML 4.01 and HTML 5 specifications the "id" attribute must be unique among all the IDs in the document so
$("span#longitude").html()
is only ever going to give you the first longitude (or at least it's not going to give you what you want which is to loop through all the lat/longs)
There's are a lot of ways to accomplish your goal. One way is to store the lat/longs in your javascript instead of in the HTML.
you would do that like so
<script>
var map, agraphicsLayer, symbol,
data = {"type": "FeatureCollection",
"features": [{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [37.82, -2.28]
}},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [34.82, 1.36]
}},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [34.31, -0.67]
}},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [40.19, 0.10]
}}]
};
...code snipped for brevity
//here you want to loop through the points
data.features.forEach(function(feature){
var pt = new Point(feature.geometry.coordinates, map.spatialReference);
agraphicsLayer.add(new Graphic(pt, symbol));
})
</script>
if you really want to store the data in spans like you are now then you need to change the "id" attribute to a "class" attribute and then wrap the lat/long spans in some grouping element like a div or another span
<div class="coordinate">
<span class="longitude">37.82</span>
<span class="latitude">-2.28</span>
</div>
and then in the javascript do something like this
$(".coordinate").each(function(){
//this refers to each "coordinate" div as we loop through them
var long = $(this).find(".longitude").html()
var lat = $(this).find(".lattitude").html()
var pt = new Point(long, lat);
//etc
})

Related

Adding and reading json data stored in vuex

I have a vuex store and i am adding some josn data and this is the format.
[
{
"id":1,
"firstname": "toto",
"lastname": "titi"
},
{ "id":2,
"firstname": "one",
"lastname": "two"
}
]
I am adding the data on an on click action and this is the action method
addLink: function() {
var dt = '[{"id":1,"firstname":"xx","lastname": "yy"},{"id":2,"firstname": "one","lastname": "two"}]';
this.ADD_LINK(dt)
this.newLink = '';
},
The data is getting added to the store and i can access it like this
computed: {
users(){
return this.countLinks;
}
}
I can display the data this way {{users}} and this is getting displayed. This is because i clicked twice and added the json twice.
[ "[{\"id\":1,\"firstname\":\"xx\",\"lastname\": \"yy\"},{\"id\":2,\"firstname\": \"one\",\"lastname\": \"two\"}]", "[{\"id\":1,\"firstname\":\"xx\",\"lastname\": \"yy\"},{\"id\":2,\"firstname\": \"one\",\"lastname\": \"two\"}]" ]
However, when i try to use v-for
<ul id="users">
<li v-for="user in users" :key="user.id">
{{ users.firstname}}
</li>
</ul>
i cannot display any data and i have no error. How can i display the data saved in vuex?.
You can create a computed property that returns the objects in one list parsed as JSON:
new Vue({
el:"#app",
data: () => ({
users: [ "[{\"id\":1,\"firstname\":\"xx\",\"lastname\": \"yy\"},{\"id\":2,\"firstname\": \"one\",\"lastname\": \"two\"}]", "[{\"id\":1,\"firstname\":\"xx\",\"lastname\": \"yy\"},{\"id\":2,\"firstname\": \"one\",\"lastname\": \"two\"}]" ]
}),
computed: {
usersList: function() {
return this.users.flatMap(userList => JSON.parse(userList));
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ul id="users">
<li v-for="(user, index) in usersList" :key="index">
{{ user.firstname}}
</li>
</ul>
</div>
Note: Since ids are not unique in your example, you can use an index in v-for as the key. Also, to show the first name, you need to use the user object.
Another solution: Parse dt in the store and use Array#concat to add the elements as objects to the initial list:
let countLinks = [
{ "id":1, "firstname": "toto", "lastname": "titi" },
{ "id":2, "firstname": "one", "lastname": "two" }
];
function ADD_LINK(dt) {
countLinks = countLinks.concat(JSON.parse(dt));
}
const dt = '[{"id":1,"firstname":"xx","lastname": "yy"},{"id":2,"firstname": "one","lastname": "two"}]';
ADD_LINK(dt);
console.log(countLinks);
you have to store the data as is, rather than converting into string
addLink: function() {
var dt = [
{
"id":1,
"firstname": "xx",
"lastname": "yy"
},
{
"id":2,
"firstname": "one",
"lastname": "two"
}
];
// remove the single quote from the above array
this.ADD_LINK(dt)
this.newLink = '';
},
In case you are getting the var dt from external source then you should consider converting into valid js json format using this:
addLink: function() {
var dt = '[{"id":1,"firstname":"xx","lastname": "yy"},{"id":2,"firstname": "one","lastname": "two"}]';
// parse it to json format
var parsedDt = JSON.parse(dt);
// add the `parsedDt`
this.ADD_LINK(parsedDt)
this.newLink = '';
},

Vue select with deep nested data

I'm trying to make a v-select according to instruction on official documentation but my data is more nested than it shown in documentation, i can not show in my v-select the llcName of my data, and i'm stuck with this.
This is my html div and Vue instance with data below
<div id="vs">
<h1>Vue Select</h1>
<v-select multiple :options="options" :reduce="node=> node.llcName" label='llcName' v-model='selected' />
<pre>[[$data]]</pre>
</div>
<script>
Vue.component('v-select', VueSelect.VueSelect)
new Vue({
el: '#vs',
delimiters: ["[[", "]]"],
data: {
options: [
{
"node": {
"id": "U3VwcGxpZXJPYmplY3Q6MzA1",
"llcName": "new",
"suppPayment": {
"edges": [0]
}
}
},
{
"node": {
"id": "U3VwcGxpZXJPYmplY3Q6MzA2",
"llcName": "new2",
"suppPayment": {
"edges": [1]
}
}
},
{
"node": {
"id": "U3VwcGxpZXJPYmplY3Q6MzA3",
"llcName": "rteer",
"suppPayment": {
"edges": [2]
}
}
}
],
selected:"",
}
})
</script>
I think you should use getOptionLabel instead of label and there is a mistake in your reduce property.
<v-select
multiple
v-model='selected'
:options='options'
:get-option-label='option => option.node.llcName'
:reduce='option => option.node.llcName'/>
Fiddle

VueJS - Auto create a A-Z letters list from the data

Is it possible to create a A-Z letters list (like this) from the data from a API and Vue to be able to determine if a property in a data contains a name that starts with what letter. If the data doesn't contain a specific letter name then remove/disable the href attribute from the letter anchor tag.
In the linked example, letters K, X and Z are missing coz they don't have the data
JSON
[
{
"id": 77,
"link": "http://my-site/cosmoquotes/authors/anonymous/",
"name": "Anonymous",
"slug": "anonymous"
},
{
"id": 72,
"link": "http://my-site/authors/ferdinand-marcos/",
"name": "Ferdinand Marcos",
"slug": "ferdinand-marcos"
},
{
"id": 75,
"link": "http://my-site/authors/john-f-kennedy/",
"name": "John F. Kennedy",
"slug": "john-f-kennedy"
},
{
"id": 67,
"link": "http://my-site/authors/john-maxwell/",
"name": "John Maxwell",
"slug": "john-maxwell"
}
]
Component
export default {
data() {
return {
authorsRequest: {
type: 'authors',
params: {
per_page: 100
}
},
}
},
computed: {
authors () {
return this.$store.getters.requestedItems(this.authorsRequest)
},
},
methods: {
getAuthors() {
return this.$store.dispatch('getItems', this.authorsRequest)
},
},
created() {
this.getAuthors()
}
}
So as per the returned data, only the letters 'A', 'F' and 'J' should be clickable/displayed.
I managed to do it like this,
unfortunatly it needs the authors array and the conditionnal function to be outside of the Vue component because I couldn't find how to pass argument to computed values
But since I'm new to vue (didn't even finish reading the introduction) I'm sure there has to be a better solution
EDIT: found the way to have the function in the component with methods, I could then move the data in the component too
let a = new Vue({
el: "#selector",
data: {
authors: [{"id": 77,"link": "http://my-site/cosmoquotes/authors/anonymous/","name": "Anonymous","slug": "anonymous"},{"id": 72,"link": "http://my-site/authors/ferdinand-marcos/","name": "Ferdinand Marcos","slug": "ferdinand-marcos"},{"id": 75,"link": "http://my-site/authors/john-f-kennedy/","name": "John F. Kennedy","slug": "john-f-kennedy"},{"id": 67,"link": "http://my-site/authors/john-maxwell/","name": "John Maxwell","slug": "john-maxwell"}]
},
computed: {
// there have to be a way to get this array without doing it like this but I don't know it ^^
letters() {
let letters = []
for(let i = "A".charCodeAt(0); i <= "Z".charCodeAt(0); i++) {letters.push(String.fromCharCode([i]))}
return letters
}
},
methods: {
// you may add a toUpperCase()/toLowerCase() if you're not sure of the capitalisation of you datas
isALink(letter) {
return this.authors.some(aut => aut.name.startsWith(letter))
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="selector">
<template v-for="letter in letters">
<a v-if="isALink(letter)" :href="letter">{{ letter }}</a>
<a v-else>{{ letter }}</a>
</template>
</div>
you can set the unique name as the id of dom. when you click to letter X, just get the first name start with X , and use getElementById to match the dom and scroll to the dom.

Read all element bindings from a Vue template

I'm trying to pre-process a Vue 2 template and get a list of all of the element bindings. So if I have a file like this:
<html>
<body>
<div id="app">
<p>Here's a message: {{message1}}</p>
<p>Here's an input: <input type="text" v-model="message2"></p>
</div>
<script type="application/javascript" src="vue.js"></script>
<script type="application/javascript">
new Vue({
el: "#app",
data: {
message1: "foo",
message2: "bar"
}
});
</script>
</body>
</html>
Then somewhere (beforeMount?) I could query Vue and it would tell me the bindings are ['message1', 'message2']. Is that possible?
I ended up solving this by getting the text of the render function (by calling vm.$options.render.toString() ) and then parsing the bindings from that.
For instance, the rendering function for a simple list view looks like this:
function() {
var _vm = this
var _h = _vm.$createElement
var _c = _vm._self._c || _h
return _c(
"table",
{ attrs: { border: "1", cellpadding: "5", cellspacing: "0" } },
[
_vm._m(0),
_vm._l(_vm.rows, function(row) {
return _c("tr", [
_c(
"td",
[
_c("router-link", { attrs: { to: "/detail/" + row.ID } }, [
_vm._v(_vm._s(_vm._f("truncate")(row.TITLE, 100)))
])
],
1
),
_c("td", [_vm._v(_vm._s(_vm._f("truncate")(row.DESCRIPTION, 200)))]),
_c("td", [_vm._v(_vm._s(row.TYPE))])
])
})
],
2
)
}
It looks like the bindings are always contained in an _s() element, and optionally a vm.f() instruction when using filters.

How to add AggregateRatingin in GTM using DOM element Variables?

The Product Schema code that i am using as a custom HTML tag for implementing product schema using DOM variables in GTM..
<script>
var jsonData = {
"#context": "http://schema.org",
"#type": "Product",
"name": {{productName}},
"image": {{productImg}},
"url": {{Page URL}},
"aggregateRating": {
"#type": "AggregateRating",
"ratingValue": {{avgRating}},
"reviewCount": {{ratingsCount}},
}
}
var script = document.createElement('script');
script.type = 'application/ld+json';
script.text = JSON.stringify(jsonData);
$("head").append(script);
</script>
how can i configure the DOM element variable for AggregateRating Variables (avgRating, ratingsCount) in GTM.
here is the Markup
<div class="woocommerce-product-rating">
<div class="star-rating">
<span style="width:100%">
<strong class="rating">5.00</strong> out of <span>5</span> based on <span class="rating">1</span> customer rating </span>
</div>
(<span class="count">1</span> customer review) </div>
You need to create two variables in GTM
1) Go to Variables->User-Defined Variables->New->Custom Javascript
2) Create variable with name ProductAvgRating and JS code:
function () {
try {
return parseFloat(document.querySelector('.woocommerce-product-rating strong.rating').innerText);
}
catch(e) {return 0;}
}
2) Create variable with name ProductRatingsCount and JS code:
function () {
try {
return parseInt(document.querySelector('.woocommerce-product-rating span.rating').innerText);
}
catch(e) {return 0;}
}
And then change your html tag like that:
<script>
var jsonData = {
"#context": "http://schema.org",
"#type": "Product",
"name": {{productName}},
"image": {{productImg}},
"url": {{Page URL}},
"aggregateRating": {
"#type": "AggregateRating",
"ratingValue": {{ProductAvgRating}},
"reviewCount": {{ProductRatingsCount}},
}
}
var script = document.createElement('script');
script.type = 'application/ld+json';
script.text = JSON.stringify(jsonData);
$("head").append(script);
</script>
P.S. You didn't ask about productName and productImg variables, i guess you already have it