Googlemaps return object from initialize function - google-maps-api-3

I have a list of infowindows lets say numbered 1 to 5.
and they have a form to get directions. When I draw the route the infowindow should colapse. Everything works, I just want the infowindow object available outside the function
infowindow.close() works fine if its in initialize, however the function calcRoute() is outside of the initialize function. I'm trying to return the infowindow from the function but not sure where I am going wrong
here is the jest of what I'm doing
function initialize() {
........
var infowindow3 = new google.maps.InfoWindow({
content: iwindow('marker3','st pete','27.81884967015435','-82.65828121138918','727-822','4011 mlk','Fl','33703','201'),
maxWidth: 300
});
.........
return infowindow3;
}
// I have tried alerting every combination of this, window and even the function name
alert(this.window.infowindow3);
// if it would alert ObjectObject I would have it.
I know I'm close and hopefully someone familiar with the maps can shed some light.
A big thank you in advance. (I have spent days trying to get this one)

This may be a stupid question, but are you saving the return value of initialize? Of course you are not showing your whole code, but that's not clear from what is there. Something like this:
var infowindow3 = initialize();
alert(infowindow3);
Of course, the typical way to call initialize is via the load event, so you wouldn't be able to get the return value that way. So you would set up a (in your example) global variable, and that set that global variable inside of initialize (and not returning anything).
Update:
Ok, after looking through the page you linked to (in your comment) I see that you are calling the alert(infowindow3); before infowindow3 gets defined. You can also see that in the page itself, the alert pops up with "undefined" and the page isn't loaded yet - you can't see any map and consequently initialize() hasn't run yet. Bear in mind that during a page load, any script outside of a function (or a function's code if the function call is in that "open space") will get executed the moment the browser reads it. This alert is an example of that. You need to put that alert (or any code that uses this variable) in a function that does not get called until it is defined by initialize(). Examples of this are functions that get called with onclick. In fact, initialize itself is an example of that (it gets called with onload).

Related

Correctly stopping an autorun() function when template is destroyed

I have a template that contains a chart, rendered using MorrisJS. The chart should update when the currentData session variable is changed, so I have made it a reactive data source with:
Template.chart.rendered = function() {
var template = this;
Deps.autorun(function(c) {
// Stop if the template is removed from the dom
// Q: Is this really right?
if(template.__component__.dom.parentNode() === null) {
c.stop();
return;
}
var results = Session.get('currentData');
// ... render a chart with `results` as the data
Morris.Bar({element: template.$(".chart-container"), data: results, ...});
});
};
Notice how I do a fairly horrid check for when to stop the autorun above. This was necessary because without this, when I navigate away from the page using the template (I'm using iron-router) to another page and back, I get warnings in the log like "Can't select in removed DomRange". I'm pretty sure this is happening because the template instance is removed, but the autorun is still running.
I feel like I'm doing something wrong here, though. Is there (a) a better place to put the autorun so that it doesn't have this problem or (b) a better way to stop the computation when the template instance is removed from the DOM?
I tried to find a way to do it with created and destroyed handlers, but I couldn't figure out how.
Tracker.autorun returns a handle that you can store as a template instance property, then call its stop method in the onDestroyed lifecycle event.
Template.chart.onRendered(function(){
this.computation = Tracker.autorun(function(){...});
});
Template.chart.onDestroyed(function(){
this.computation.stop();
});
EDIT 29-09-2014
In newer versions of Meteor (0.9 onward), there is a new autorun function available on template instances which provide simpler code to achieve the same result : no need to store and stop the computation manually, this is taken care of by the framework.
Template.chart.onRendered(function(){
this.autorun(function(){...});
});
With the new autorun
Template.chart.onRendered(function(){
this.autorun(function(computation){
...
computation.stop();
});
});
but with this autorun, when chart template is removed from the DOM it is removed automatically.
This is in Meteor documentation here:
The Computation is automatically stopped when the template is destroyed.

Detect template change in Meteor

I'm looking to make an element flash on screen when the underlying collection is updated.
It seems to me that it would make to have an equivalent of Template.my_template.rendered = function(){} which is fired every time the template is updated.
Ideally, this function would not fire the first time the template is rendered.
This is seems like such an obvious use case, am I missing something?
For Meteor < 0.8
You should use Template.myTemplate.created to do something for the very first time. From the docs Template.myTemplate.rendered is fired everytime there is a change including the first time. If you want to limit it to only the second time and changes after that (I'm guessing this is what you want), you have to write some custom logic. Currently there is no Meteor api that supports that.
For Meteor-0.8
It seems like this API underwent some backwards incompatible changes in Meteor-0.8.
There is an elegant way to achieve this as described Adaptation to the new Meteor rendered callback here. Bascially you should modify whatever function you are attaching to the variables inside your Template's javascript by calling a helper function once. For example,
var renderCount = 1;
var myHelper = function () {
console.log("rendered #" + renderCount);
renderCount++;
};
Template.myTemplate.myVariable = function () {
myHelper();
return this.name;
};
Hope this helps. There is also another alternative approach in that same repo. You might like that one.
There is no simple solution; more discussion here: https://groups.google.com/forum/#!topic/meteor-talk/iQ37mTP3hLg

Is there a way to know that an ImgTileProvider has finished loading all tiles?

I'm building out a map app that pulls in tiles via an ImgTileProvider. I would like to know when the tiles have been correctly loaded, but the only method exposed by the ImgTileProvider.Options is the getUrl function, which helps me know where to get an image tile, not when it returns.
Is there an event that is fired after each tile/all tiles has/have been created/rendered to the page? I noticed that there was an addListener function available for ImgTileProvider instances, which I would subscribe to if I knew which event was being fired on image create.
So, as I was writing this question, a thought occurred: why not check the source? Using Chrome, I prettified the map-render-display.js file and looked for events added via the addListener function. I didn't see anything for ImgTileProvider, but I found several other providers subscribing to a response event. So I added an event listener on my ImgTileProvider instance and it worked! Below is a sample of working code.
// A magic number representing the total number of tiles in the map.
var magicNumber = 22;
// Returns a new ImgTileProvider.
tileProvider = self.imgTileProvider();
tileProvider.addListener("response", function () {
magicNumber--;
if (magicNumber === 0) {
console.log("All tiles loaded");
}
});

Meteor subscribe onReady() and observe() added double counted

I want to wait for all data to be downloaded from the subscription and then create map markers for them all at once at the beginning. To do this, I have a session variable set to false. Then when onReady calls, I initialize all the markers. Then I set the session variable true indicating that the first delivery is in and initialized. In my observe callback, I check the session variable and so long as its false, I dont add any markers. Then, if its true, I will add markers -- assuming non of these markers are already initialized. Sometimes, however, I get a double-count and create twice as many markers.
I guess a good first question to ask is what the relationship is between onReady and observe added? Its not terribly clear in the docs. Is this even the correct way of doing things -- creating a session variable to suppress the observe added function until onReady is done? I dont think so. Also note that the double count doesnt happen every time so its a timing thing... kind of annoying.
Thanks
Yes this is the behavior with observe(). When you run observe initially it will have an initial query that will match everything and run into added.
It is also present when onReady hasn't yet fired but the collections are empty at that point so the initial ones aren't visible. This is mentioned in the docs
Before observe returns, added (or addedAt) will be called zero or more times to deliver the initial results of the query.
I'm not sure entirely how to avoid the initial items. I have done something like this in the past:
var QueryHandle = Collection.find().observe({
added: function() {
if(!QueryHandle) return false;
});
I know this works on the server but I'm not certain if it does on the client.
Another solution would be to run the handle before onReady is called and only stop returning if the subscription is complete: i.e
Meteor.subscribe("collection", function() {
subscribed = true;
});
var QueryHandle = Collection.find().observe({
added: function() {
if(!subscribed) return false;
}
);
Be careful not to run this in a Deps.autorun because then it would be run again if the .find() query params are reactive.
This might happen sometimes depending on how fast the server response. If you use Session it becomes a reactive hash so if it happens fast enough that subscribed returns true. Try using an ordinary variable instead.
If its not helpful there might be an alternative way to avoid the initial ones and a deeper level but it might take a dig into the livedata package.

Call function when google map loads

I'm using the basic initialize function from the Google Maps Developer pages. I'm a little new to using maps but I'm managed to achieve what I want from reading the developer site. What I can't find though is a way to call a function once initialize has LOADED the map. For example, I want to update directions based on values in pre-filled forms
I tried something like this...
google.maps.event.addDomListener(window, 'load', function() {
initialize();
updateDirections();
});
Initialize loads the map, updateDirections is the function I want to call to put in directions and some other little things to do with my webpage, but my guess is that maps needs a little time to load, then I should call updateDirections().
How is the best way to do this? I would have thought a callback or onsucess parameter in map options would have been available.
Anyway I think what I'm trying to do is really straight forward but maybe I'm wrong, or maybe it is and I'm just searching for the wrong things. I'm sure it's been answered previously, but I can't seem to find anything that simply does what I'm trying to do.
Thanks
Bizt
Inside your initialize() function, after you create the map and have a reference to it in a variable called map, add an event listener for the idle event:
google.maps.event.addListenerOnce( map, 'idle', function() {
updateDirections();
});
If the only thing you need to do there is call your updateDirections() function, you could just use it directly as the idle callback:
google.maps.event.addListenerOnce( map, 'idle', updateDirections );
Note the use of addListenerOnce() instead of addListener(), so this event listener is only called the first time the event fires. If you used addListener() it would fire every time the map is panned or zoomed.

Resources