data subscribed to Knockout ObservableArray but displaying empty array - javascript

I'm new to javascript. i'm having difficulty printing the data from the location ObservableArray. The data - bind works and i could list out the data from the location ObservableArray at the view but can't print it out on the console. i have been on it for hours now, any help would be appreciated. thank you
Here is the ViewModel
let MapViewModel = function() {
let map
let geocoder;
let self = this;
self.location = ko.observableArray([]);
for (let i = 0; i < locationList.length; ++i) {
self.location.push(new Location(locationList[i]));
}
console.log(this.location()); // Location, Location, Location, Location, Location, Location, Location]
console.log(this.location()[0].name); // Location {name: ƒ, address: ƒ} ...
console.log(this.location().length); //length is 7
}
let Location = function(data) {
this.name = ko.observable(data.name);
this.address = ko.observable(data.address);
}
ko.applyBindings(new MapViewModel());
Here is the Binding Code`
<div class="menu_item_container">
<h1>Neighborhood Map</h1>
<input type="text" id="search" data-bind= 'value:filterLocations, valueUpdate: 'afterKeyDown',value:filterLocations' placeholder="Search Locations...">
<hr>
<nav id=nav>
<ul data-bind='foreach:location'>
<li data-bind="text:name"></li>
</ul>
</nav>
</div>
LocationList
let locationList = [{
name: 'Brooklyn Museum',
address: '200 Eastern Pkwy, Brooklyn, NY 11238'
}, {
name: 'Empire State Building',
address: '350 5th Ave, New York, NY 10118'
}, {
name: 'Statue of liberty',
address: 'New York, NY 10004'
}, {
name: 'Rockefeller Center',
address: '45 Rockefeller Plaza, New York, NY 10111'
},
{
name: 'Brooklyn Bridge',
address: 'Brooklyn Bridge, New York, NY 10038'
},
{
name: 'Time Square',
address: '45 Rockefeller Plaza, New York, NY 10111'
},
{
name: 'World Trade Center',
address: '285 Fulton St, New York, NY 10007'
},
];

This can unwrap observable to regular js and convert this to single string (if needed) and then u can print it console :
let locationsJSON = ko.toJS(self.location);
let locationsString = JSON.stringify(locationsJSON);

Related

Using reduce to count groups of data within groups of data

As the title says, I'm trying to count groups of data within groups of data: My logic is to group all the data into states, then group date into years. so that the output should look like something like:
state,year,count
mo,1910,2
in,1910,1
il,1910,3
or,1910,4
co,1910,2
nd,1910,1
...
mo,1911,5
in,1911,4
il,1911,6
or,1911,2
co,1911,8
The CSV I'm using has a lot more columns that needed, I'm only interested in the columns state and year. My code below isn't working, any help would be great.
const countStates = filteredData.reduce((m, d) => {
if(!m[d.year]){
m[d.year] = {...d, count: 1};
return m;
}
m[d.state];
m[d.year];
m[d.year].count += 1;
return m;
},{});
const countedStates = Object.keys(countStates).map((k) => {
const item = countStates[k];
return {
state: item.state,
year: item.year,
count: item.count
}
})
Edit
Example of the dataset I'm using:
datetime,city,state,country,shape,duration (seconds),duration (hours/min),comments,date posted,latitude,longitude
10/10/1949 20:30,san marcos,tx,us,cylinder,2700,45 minutes,"This event took place in early fall around 1949-50. It occurred after a Boy Scout meeting in the Baptist Church. The Baptist Church sit",4/27/2004,29.8830556,-97.9411111
10/10/1949 21:00,lackland afb,tx,,light,7200,1-2 hrs,"1949 Lackland AFB&#44 TX. Lights racing across the sky & making 90 degree turns on a dime.",12/16/2005,29.38421,-98.581082
10/10/1955 17:00,chester (uk/england),,gb,circle,20,20 seconds,"Green/Orange circular disc over Chester&#44 England",1/21/2008,53.2,-2.916667
10/10/1956 21:00,edna,tx,us,circle,20,1/2 hour,"My older brother and twin sister were leaving the only Edna theater at about 9 PM&#44...we had our bikes and I took a different route home",1/17/2004,28.9783333,-96.6458333
10/10/1960 20:00,kaneohe,hi,us,light,900,15 minutes,"AS a Marine 1st Lt. flying an FJ4B fighter/attack aircraft on a solo night exercise&#44 I was at 50&#44000&#39 in a "clean" aircraft (no ordinan",1/22/2004,21.4180556,-157.8036111
10/10/1961 19:00,bristol,tn,us,sphere,300,5 minutes,"My father is now 89 my brother 52 the girl with us now 51 myself 49 and the other fellow which worked with my father if he&#39s still livi",4/27/2007,36.5950000,-82.1888889
10/10/1965 21:00,penarth (uk/wales),,gb,circle,180,about 3 mins,"penarth uk circle 3mins stayed 30ft above me for 3 mins slowly moved of and then with the blink of the eye the speed was unreal",2/14/2006,51.434722,-3.18
10/10/1965 23:45,norwalk,ct,us,disk,1200,20 minutes,"A bright orange color changing to reddish color disk/saucer was observed hovering above power transmission lines.",10/2/1999,41.1175000,-73.4083333
10/10/1966 20:00,pell city,al,us,disk,180,3 minutes,"Strobe Lighted disk shape object observed close&#44 at low speeds&#44 and low altitude in Oct 1966 in Pell City Alabama",3/19/2009,33.5861111,-86.2861111
10/10/1966 21:00,live oak,fl,us,disk,120,several minutes,"Saucer zaps energy from powerline as my pregnant mother receives mental signals not to pass info",5/11/2005,30.2947222,-82.9841667
10/10/1968 13:00,hawthorne,ca,us,circle,300,5 min.,"ROUND &#44 ORANGE &#44 WITH WHAT I WOULD SAY WAS POLISHED METAL OF SOME KIND AROUND THE EDGES .",10/31/2003,33.9163889,-118.3516667
10/10/1968 19:00,brevard,nc,us,fireball,180,3 minutes,"silent red /orange mass of energy floated by three of us in western North Carolina in the 60s",6/12/2008,35.2333333,-82.7344444
10/10/1970 16:00,bellmore,ny,us,disk,1800,30 min.,"silver disc seen by family and neighbors",5/11/2000,40.6686111,-73.5275000
And the code I used to filter out the data:
fs.createReadStream('./data/scrubbed.csv')
.pipe(readCSV())
.on('data', (data) => CSV.push(data))
.on('end', () => {
let data = CSV.map((d) => {
return {
year: new Date (d.datetime).getFullYear(),
state: d.state,
country: d.country
}
});
filteredData = data.filter((d) => {
return d.state !== "" && d.country === "us"
})
Which returns this (an example of the dataset):
[ { year: 1949, state: 'tx', country: 'us' },
{ year: 1956, state: 'tx', country: 'us' },
{ year: 1960, state: 'hi', country: 'us' },
{ year: 1961, state: 'tn', country: 'us' },
{ year: 1965, state: 'ct', country: 'us' }...
The above is what I'm trying to group twice using reduce
The below code gets an array of states with the year and using reduce we are getting the count of each state grouped by year as
var data = [
{ year: '1910', state: 'mo', country: 'us' },
{ year: '1910', state: 'in', country: 'us' },
{ year: '1910', state: 'il', country: 'us' },
{ year: '1910', state: 'mo', country: 'us' },
{ year: '1911', state: 'in', country: 'us' },
{ year: '1911', state: 'il', country: 'us' },
{ year: '1911', state: 'mo', country: 'us' },
{ year: '1911', state: 'in', country: 'us' }
];
var organizedData = data.reduce((acc, val, index) => {
acc[val.state] = acc[val.state] || {};
acc[val.state][val.year] = (+acc[val.state][val.year] || 0) + 1;
return acc;
}, {});
console.log(organizedData);

Create new KO.observable array and populate it from an array object

Is possible to create an ko.observable array and populate it using an array object?
My goal here is to create a ko.observable array with all the description/objects that are with the original array.
//Sample data the original data is coming from an socket query and being push on the array("people")
var people = [{
name: "Contact 1",
address: "1, a street, a town, a city, AB12 3CD",
tel: "0123456789",
email: "anemail#me.com",
type: "family"
},
{
name: "Contact 2",
address: "1, a street, a town, a city, AB12 3CD",
tel: "0123456789",
email: "anemail#me.com",
type: "friend"
}
];.
var people = [{
name: "Contact 1",
address: "1, a street, a town, a city, AB12 3CD",
tel: "0123456789",
email: "anemail#me.com",
type: "family"
},
{
name: "Contact 2",
address: "1, a street, a town, a city, AB12 3CD",
tel: "0123456789",
email: "anemail#me.com",
type: "friend"
}
];
var quotesarray = function(items) {
this.items = ko.observableArray(items);
this.itemToAdd = ko.observable("");
this.addItem = function() {
if (this.itemToAdd() != "") {
this.items.push(this.itemToAdd());
this.itemToAdd("");
}
}.bind(this);
};
ko.applyBindings(new quotesarray(people));
console.log(people);
You just needed to make it items instead of quotesarray
var people = [
{ name: "Contact 1", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail#me.com", type: "family" },
{ name: "Contact 2", address: "1, a street, a town, a city, AB12 3CD", tel: "0123456789", email: "anemail#me.com", type: "friend" }
];
var quotesarray = function(items){
this.items = ko.observableArray(items);
this.itemToAdd = ko.observable("");
this.addItem = function(){
if (this.itemToAdd() != ""){
this.items.push(this.itemToAdd());
this.itemToAdd("");
}
}.bind(this);
};
ko.applyBindings(new quotesarray(people));
console.log(people);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table>
<thead>
<tr><th>name</th><th>address</th></tr>
</thead>
<tbody data-bind="foreach: items">
<tr>
<td data-bind="text: name"></td>
<td data-bind="text: address"></td>
</tr>
</tbody>
</table>
You can create an observableArray to which the socket writes messages. You subscribe to the array to be automatically notified when the contents change (i.e. after every write by the socket).
In the subscribe callback you empty the array and add the items to your viewmodel's property.
If you expect to receive many rapidly succeeding messages, you can rateLimit the array to which you write to ensure you don't update the DOM too many times.
Here's an example. The explanations are in the code comments.
const UPDATE_EVERY_MS = 500;
// The observable array the socket writes to
const received = ko.observableArray([])
// Use a rateLimit extension if you expect to
// receive many updates from your socket
.extend({ rateLimit: UPDATE_EVERY_MS });
// The observable array in your viewmodel
const rendered = ko.observableArray([]);
received.subscribe(items => {
// Write "inbox" to viewmodel's list
rendered(rendered().concat(items));
// Clear received without triggering notification
items.length = 0;
});
ko.applyBindings({ items: rendered });
// Mock a socket that writes to `received`
setInterval(() => received.push(Math.random()), 200);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<ul data-bind="foreach: rendered">
<li data-bind="text: $data"></li>
</ul>

JS: If statement to check if var exists in array

I have a AngularJS app where I have an array defined that has a group of dealers. Something like this:
$scope.dealers = [{
name: "Dealer Name",
address: "Address goes here",
website:"site.com",
lat: "latitude",
lng: "longitude"
territory: ['County1', 'County2', 'County3']
},
{
name: "Dealer Name",
address: "Address goes here",
website:"site.com",
lat: "latitude",
lng: "longitude",
territory: ['County1', 'County2', 'County3']
},
];
A user will input their zip code, and then using the Google Geocode API, I convert their zip code to lat/long coordinates and find their closest dealer based off of coordinates between them, and all of the dealers.
That is working fine.
Here is where I need help. Each dealer has a territory (in the array as counties) that needs to be checked first, before finding the closest dealer, because some dealers have counties in their territories that are actually geographically closer to another dealer.
I have a var that stores the users County based on their zip. So I need to make an IF statement that checks the userZip variable against the dealers array to see if that county exists anywhere in the array. If it does, then I need to return the name of that dealer. If it does not, I will have an ELSE statement that just runs the function I already have, which will just find the closest dealer to their location.
You can use Array.prototype.find()
let dealers = [{
name: "Dealer Name",
address: "Address goes here",
website: "site.com",
lat: "latitude",
lng: "longitude",
territory: ['County1', 'County2', 'County3']
},
{
name: "Dealer Name",
address: "Address goes here",
website: "site.com",
lat: "latitude",
lng: "longitude",
territory: ['County1', 'County2', 'County3']
},
];
let country = 'County2';
let found = dealers.find(d => d.territory.includes(country));
if(found)
console.log(found);
else
console.log("..find closest...");
//another case
country = 'NotAnywhere';
found = dealers.find(d => d.territory.includes(country));
if(found)
console.log(found);
else
console.log("..find closest...");

jQuery make JSON output slideshow

I made a JS template
<div class="slider">
<script id="jstemplate" type="js/template">
<div class="items">
<span class="name"> {{name}} </span> : <span class="address">{{address}}</span>
</div>
</script>
</div>
and JSON object each
var JSONObject = [
{
name: 'Nyonya',
address: '199 Grand Street New York, NY 10013, United States'
},
{
name: 'Mulberry Project',
address: '149 Mulberry Street New York, NY 10013, United States'
},
{
name: 'Sweet & Vicious',
address: '5 Spring Street New York, NY 10012, United States'
},
],
template = $.trim($('#jstemplate').html());
$.each(JSONObject, function(i,v){
var temp = template.replace( /{{name}}/ig, v.name)
.replace( /{{address}}/ig, v.address);
console.log(temp);
$('.slider').append(temp);
});
Please check ONLINE SAMPLE
I can get the output successfully, my question is that,
How to make the output displays and loop one by one (eg. every 5 seconds), just like a slideshow?
Try
(function() {
var JSONObject = [{
name : 'Nyonya',
address : '199 Grand Street New York, NY 10013, United States'
}, {
name : 'Mulberry Project',
address : '149 Mulberry Street New York, NY 10013, United States'
}, {
name : 'Sweet & Vicious',
address : '5 Spring Street New York, NY 10012, United States'
}], template = $.trim($('#jstemplate').html());
var $ct = $('.slider');
$.each(JSONObject, function(i, v) {
var temp = template.replace(/{{name}}/ig, v.name).replace(
/{{address}}/ig, v.address);
$(temp).hide().appendTo($ct);
});
function x(){
var $item = $ct.children('.items').first().stop().fadeIn().delay(3000).fadeOut(function(){
$(this).appendTo($ct);
x();
})
}
x();
})();
Demo: Fiddle
http://jsfiddle.net/F98zF/8/
$('.slider div').hide().first().show();
setInterval(
function(){
$('.slider div:first').fadeOut().next().fadeIn().end().appendTo(".slider");}
,3000);

Rails Google Maps integration Javascript problem

update I
Based on feedback, I've changed var maps to var adds.
problem description
I'm working on Rails 3.0.0.beta2, following Advanced Rails Recipes "Recipe #32, Mark locations on a Google Map" and I hit a road block: I do not see a google map. My #adds view uses #adds.to_json to connect the google maps api with my model. My database contains "latitude" "longitude", as floating points. And the entire project can be accessed at github.
Can you see where I'm not connecting the to_json output with the javascript correctly? Can you see other glairing errors in my javascript? Thanks in advance!
My application.js file:
function initialize() {
if (GBrowserIsCompatible() && typeof adds != 'undefined') {
var adds = new GMap2(document.getElementById("map"));
map.setCenter(new GLatLng(37.4419, -122.1419), 13);
map.addControl(new GLargeMapControl());
function createMarker(latlng, add) {
var marker = new GMarker(latlng);
var html="<strong>"+add.first_name+"</strong><br />"+add.address;
GEvent.addListener(marker,"click", function() {
map.openInfoWindowHtml(latlng, html);
});
return marker;
}
var bounds = new GLatLngBounds;
for (var i = 0; i < adds.length; i++) {
var latlng=new GLatLng(adds[i].latitude,adds[i].longitude)
bounds.extend(latlng);
map.addOverlay(createMarker(latlng, adds[i]));
}
map.setCenter(bounds.getCenter(),map.getBoundsZoomLevel(bounds));
}
}
window.onload=initialize;
window.onunload=GUnload;
Layouts/adds.html.erb:
<script src="http://maps.google.com/maps?file=api&v=2&sensor=true_or_false&key=ABQIAAAAeH4ThRuftWNHlwYdvcK1QBTJQa0g3IQ9GZqIMmInSLzwtGDKaBQvZChl_y5OHf0juslJRNx7TbxK3Q" type="text/javascript"></script>
<% if #adds -%>
<script type="text/javascript">
var adds = <%= raw #adds.to_json %>;
</script>
<% end -%>
Rails Console Output
a = Add.all
=> [#<Add id: 1, first_name: "Jason", last_name: "Wade", address: "225 Anzavista Ave, San Francisco, CA", address2: "", zip: "94115", city: "San Francisco", phone: "415-280-6678", float: nil, campaign_id: 1, email: "jwade#gmail.com", employer: "Google", occupation: "", created_at: "2010-04-06 14:00:36", updated_at: "2010-04-06 14:00:36", latitude: 37.779623, longitude: -122.445662>]
ruby-1.9.1-p378 > a.to_json
=> "[{\"address\":\"225 Anzavista Ave, San Francisco, CA\",\"address2\":\"\",\"campaign_id\":1,\"city\":\"San Francisco\",\"created_at\":\"2010-04-06T14:00:36Z\",\"email\":\"jwade#gmail.com\",\"employer\":\"Google\",\"first_name\":\"Jason\",\"float\":null,\"id\":1,\"last_name\":\"Wade\",\"latitude\":37.779623,\"longitude\":-122.445662,\"occupation\":\"\",\"phone\":\"415-280-6678\",\"updated_at\":\"2010-04-06T14:00:36Z\",\"zip\":\"94115\"}]"
var bounds = new GLatLngBounds;
should be
var bounds = new GLatLngBounds();
And you were initially correct:
var map = new GMap2(document.getElementById("map"));

Categories