Including several Maps from GoogleMaps API without callback - javascript

I've been wondering about a way to include a random number of maps in a web page. I'm currently working with GWT and embedding my javascript code into a JSNI function. I have an array of maps but due to my architecture, every map does know nothing about the others. My problem is that I have to include the gmaps script this way (asynchronously):
var script = $doc.createElement("script");
script.type = "text/javascript";
script.src = "http://maps.googleapis.com/maps/api/js?sensor=false&initializeMaps";
$doc.body.appendChild(script);
The issue here is that I don't know the ids of the maps when loading the script, so I cannot load all of them within the 'initializeMaps' function.
I would like to know whether it is possible to load each map separately instead of depending on the 'initializeMaps' callback, where as I have said, I don't know the maps ids yet.

After a few days I've figured out about how to do it. I thought that loading the Gmaps script at first with no callback wasn't correct and I still don't know, althought I did it.
I included:
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
within the head of my document and then I initialized every map with the same function to which I provided map ids as input. As you can see the parameter "initializeMaps" which I was using as callback is not placed in the GMaps url anymore.
The problem is that I have to carry that included script in some places where I don't need it. I don't know whether this is a right approach to the use of GoogleMaps API, but it has been impossible to do it for me without this workaround.

Related

Cannot find Google Maps key

I realize that this may be a moot question, and it may not be possible to find what I am asking, but here goes nothing.
I would like to find the API key or its location in code/database which is being used by Google Maps on my website.
It's a WordPress website, and I am currently using a theme called Directory Engine from Engine Themes.
Please see the URL.
The map block shows an error, after initially loading for a second.
I have used different plugins, even combed through the code to figure out where it could be, but couldn't
I know this is a long shot, and any help would be much appreciated.
Go to the following URL and generate a key.
https://developers.google.com/maps/documentation/javascript/get-api-key
in your code replace the following link.
//maps.googleapis.com/maps/api/js?sensor=false&signed_in=false&ver=1&key=YOUR_GENERATE_KEY
after that, your issue will be fixed.
To correctly use the google maps api you must include YOUR_API_KEY in the code
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"
async defer>
</script>
your code has
<script type="text/javascript"
src="//maps.googleapis.com/maps/api/js?sensor=false&signed_in=false&ver=1">
</script>
sign up for your own API key here and place that in the code above
Search your code base
if you are having trouble locating where in your code base the api is set you could try to use a command line script on your root folder
grep -r "googleapis"
Search your Database
you could try to do a sql dump then search that file for the string

Creating reusable function in Google AdWords

I'm currently writing a script in Google AdWords, and I'm managing lots of campaigns that use the same function (which I have had to copy-paste around 90+ times). Whenever I want to edit this function it becomes incredibly hard as I need to manually to through every script individually.
Is there any way of creating a reusable function, store it as a separate script and call it from AdWords like how I can call Logger and DriveApp? I've tried to use the following resources, which has been pretty useless so far:
Standalone Scripts - Google somehow allows you to create scripts but not execute them from within AdWords (at least that's as far as I've managed to come)
Execution API - Gave up after getting constant 'Unauthenticated' errors (even when setting the permissions to 'Anyone, even anonymous')
MCC Scripts - This allows me to update all accounts, but doesn't do what I need
If anyone knows any way of simply storing a function somewhere and calling it within Google AdWords, it would be greatly appreciated.
You can write your function a save it in a Google Drive file and the use it from there:
var scriptFile = getFile(location);
var scriptText = scriptFile.getBlob().getDataAsString();
eval(scriptText);

including javascript files in my page

I have many (almost 15) javascript files which I am using in my webpage.
What is the best way to include all of these files?
Simply at bottom or is there some other technique that should be used which can load javascript faster?
You could combine and minify them. YUI Compressor could do that.
You may consider using a parallel/non-blocking javascript loader.
Following are some great libraries that could do this for you..
http://headjs.com/
http://requirejs.org/
http://labjs.com/
Google Closure Compiler has a convient web api for merging and minifying all your js.
https://developers.google.com/closure/compiler/docs/api-ref
You can put a script tag with a direct link to the api.
I haven't quite mastered implementing all this yet I have found that a fair amount of minification & concatenation can be automated by servers, I have learned a fair amount from reading the (well-commented) .htaccess file in the HTML5 Boilerplate and associated docs.
Modernizr also features an asyncronous loader function and it was well enough documented that I was able to get it to work when I just couldn't quite figure out require.js
You could use a script loader library or you can do it yourself.
Where to include scripts and how the browser loads resources
Always at the bottom just before the closing <body> tag, to enhance the user experience. It ensures that the page content gets rendered first, which gives the impression that your pages load quicker.
The browser runs a single thread and will process the page content from top to bottom, if it happens on a resource, it first has to retrieve the resource, process it and then only continue with the next tag on the page. Since we generally want to wait for the DOM to be finished loading, before running any scripts in any case, this strategy is always a win win.
Size matters
For production you want to ensure that all your scripts are minified regardless of the strategy you are going to employ to get them loaded (smaller size == less to download == quicker)
The correct order
Most important is always the dependency order, if we call a function or access a variable and the browser doesn't know about it first, the script will fail. You want to ensure that a script is only included after any scripts they depend on. So the first thing to do is to work out the order by which you need to include and introduce functionality to the browser.
How to include scripts into a page
There is only one way to include a script in a page (not recommending same origin ajax/eval) and that is by means of the <script> tag.
There are only 2 ways to create a <script> tag:
Statically located in html or
dynamically added with JavaScript.
Statically added scripts
Since we know the order we need our scripts included we can add them one by one after each other like this
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.5.2/jquery.tablesorter.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.5.2/jquery.tablesorter.widgets.min.js"></script>
Dynamically added scripts
There are three ways to effectively create script tags in the dom, dynamically, which we will explore. These are certainly not the only ways...
document.write
The write method will append to the existing dom.
document.write('<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>');
But now we have a problem as there is no way of telling that the script is done loading, because we have to wait until it is complete before loading the next one or calling something that is defined there.
document.createElement
The createElement method creates a dom element and we can insert it anywhere in the dom we choose.
The following example checks if jQuery exists or creates a <script> element to go fetch it. In any event, the function ready_go is called and we should have jQuery.
(function() {
if (!window.jQuery) {
var jq = document.createElement('script');
jq.type = 'text/javascript';
jq.async = true;
jq.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js'
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(jq, s);
jq.onreadystatechange = jq.onload = ready_go;
} else ready_go();
})();
jQuery.getScript
Since we have jQuery now we don't have to do things the hard way, getScript takes as first argument the script url and will call the function as 2nd argument once the script is complete.
function ready_go() {
$.getScript('http://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.5.2/jquery.tablesorter.min.js', function () {
// script is done loading we can include the next
$.getScript('http://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.5.2/jquery.tablesorter.widgets.min.js', function () {
// script is done loading we can include the next or start using our stuff
});
});
}
Where to get the scripts from?
You either want to get the scripts from public CDN or host them yourself. An important concept to bear in mind is that scripts, as with any other resources get cached by the browser and you will not be required to repeatedly download the same scripts.
Scripts from a Content Delivery Network
The advantage of a CDN is twofold;
you get closer to the user, because a CDN consists of POPs distributed across the world and even though you are calling one url the server responding may be different
many sites may use the same CDN if your user already got jQuery from google's CDN when visiting my site his browser will simply use the cache copy already in its possession when requested by you.
Scripts served from origin (your server)
I agree with the strategy that #Mario and #Xharze suggests, beats including 18 scripts on every page.
Use CDNs where scripts are available but for the rest.
Concatenate all your scripts together, keeping in mind that the same dependency order applies, and minify them.
Having one script will simplify your includes and because the browser will cache the script no additional downloads will be required again, especially beneficial in application used for extended periods and accessing many pages.
The only advantage separate scripts hold is for users who exit from the landing page and why do we care to optimise for them they're not going to stay because of it.
nJoy!

How to avoid lost calls to an external JS file before loading it

My issue is that multiple websites are going to include my JS file and when calling something like this:
<script src="..."></script>
hello.say("yay");
there going to be a race issue so sometimes it could make it sometimes not. i know that i can solve that easily by putting every function in a window.onload but that wouldn't be clean as i've seen other websites magically solve that like google analytics:
.. Calling google analytics JS..
<script type="text/javascript">
try{
var pageTracker = _gat._getTracker("UA-xxxxxx-x"); <-- this an object !
pageTracker._trackPageview();
} catch(err) {}
</script>
How to do that?
Google Analytics uses a trick that's a perfect example of something that can only be done in duck typed languages. The main object is an array if the GA-script hasn't loaded, but if it has it changes behaviour. Let's see if I can explain it.
I pulled this piece from the source here at stackoverflow:
var _gaq = _gaq || [];
_gaq.push(['_setAccount','UA-5620270-1']);
_gaq.push(['_trackPageview']);
It looks like an array with some values being pushed to it. In fact, if _gaq is falsy when this code is run (as it is if no other analytics-JavaScript has run yet), it as an array. Then, when the main analytics script (included with a script-tag anywhere on the page) loads it examines this array and performs some task based on the contents of the array.
So, if this happens in opposite order (the main script is loaded first, and then the snippet above) the main script set _gaq to an object with a push-method that does whatever google wants it to do. Later, when the code above runs, _gaq.push doesn't just add values to an array; it actually executes arbitrary code (and doesn't push to an array at all).
Hence, regardless of which script runs first, the end result will be the same when both have finished.
If you include your file in the header part of the html page, it will be loaded before any other javascript in the page is run.
UPD: Also, I think even files included in the text of thml are downloaded before the processing of the rest of javascripts. Are you sure that is your problem in the first place?
You will need to delay the execution of any javascript code that depends on the external javascript until after the page has been fully loaded and you can do that by attaching the execution to the window.onload event.
window.onload = function() {
hello.say('yay');
}
But this has the disadvantage of only working for one function and will override any functions that have been initially attached to that event. You would want to read Simon Wilson's post and the comments for solutions on how to handle this situation.
http://simonwillison.net/2004/May/26/addLoadEvent/
I'm a bit unsure as to what you think the race issue is here.
Browsers always* execute script tags in the order they see them. If this were not true, a good portion of the internet would break - as well as pretty much every common JavaScript library in existence.
So, as long as users load your script earlier in the document than when they call its APIs, you should have no problem. The only potential exception to this I can think of is if your script's initialization relies on asynchronous logic, in which case you should think about providing a standard callback mechanism of your own for users to write their code in.
If users might load your script AFTER the point they use its APIs, then the trick Jakob alludes to in his answer would work. But I'm not even sure you're aiming for that level of complexity.
*edit: I should note, to be perfectly honest, there are specific exceptions to this, but not so long as you're simply dealing with standard non-deferred usage of <script> tags within an HTML document.

How do I dynamically add points to a Google Map when the bounds change?

I can currently place static points in the map window:
var latlng = new GLatLng(lat, lng);
map.addOverlay(new GMarker(latlng, markerOptions));
And I know how to get the bounds of the window. I can also code a page that will take the bounds and return the points that are inside them in any format.
The problems I have now:
Does the moveend event capture all moves, including zoom changes? Or do I need to watch for that event separately?
How should I call my external datasource? (should I just do a JQuery $.get request?)
What should that datasource return?
How do I display that data on the map?
I'm using this in one of my sites. I think it's exactly what you are looking for. But be warned "gmaps-utility-library" plugins have some buggy/bad code so it's a good idea to go over it and double check if everything is working as it should (I haven't encountered any bugs in marker manager but in some other plugins from that library).
Here's reference and examples.
Even if you want to code your own this one is probably a good starting point.
EDIT
My answer for 3-4:
It really depends on situation. If it's static (you just need to manage a lot points on map > 300) then you could serve all points together with the page where the map is located in (as JavaScript array for example). If user interacts with data then probably it's better to use AJAX. If you use jQuery (or any other JS library) in your site then use ajax function from that library if not then go with the one which comes from gmaps. It's because it's nice to use same AJAX function in whole site instead of using 2 which does the same job.
If you are taking AJAX path you have 2 options:
Load all markers for whole map in one request.
Load markers that shows up on user screen + small margin.
If you expect that user wants to see the big picture or that he will want to see all/most of the points then go for option 1 + marker manager (like the one I recommended or your own similar).
If there's really a lot of points and user will never be interested in most of them then go for option 2 + manager or just this simple algorithm: Clear map -> Request points for map window bounds + magin / (Cache) -> Draw points -> Repeat for each move/zoom.
From personal experience (I've used both AJAX options) marker manager does quite nice job, can handle a lot points and overall user experience is a lot smoother then loading points for just viewport. Requesting new points and drawing them on map is quite laggy/choppy. Of course it depends on amount of points.
Here is a great example of making external calls to a data source from google:
Google Maps PHP and SQL
If you're storing the points in just an external javascript file then I would recommend using JSON format over XML as the XML parser that google maps uses is much slower than json.
Moveend yes captures any kind of changes.
If you're using only an external XML file then you can use google's function to call and download the XML file (seen in the link above), otherwise I would create a file that can be updated, and parse with json.
I believe it should return a JSON as i've discovered it is much quicker than XML parsing.
You would parse through the array and create a marker with each of these. Here is a good example of using json:
Jquery and Google Maps
Good Luck!
I'm currently doing something very similar to this, along with clustering on the server.
Yes, moveend will capture zoom changes.
If you're already using jQuery, a $.get request would work great.
I have tried returning both XML and JSON. These worked fine, but I discovered that parsing through these data formats caused the application to get significantly slower as more points were added to the database. I now return plain Javascript which I execute with eval(). I don't have a problem with this since I completely trust the source of the Javascript (me).
The Javascript function which adds a marker contains only the latitude, longitude, and id of the marker. The page already contains a Javascript array with all of the data for each marker, which can be accessed when the marker is clicked on.
That's how I'm doing it, but you could certainly accompish what you want to do with a number of methods.

Categories

Resources