I am trying to load my google map asynchronously and it works but it is loading the map in twice. If I remove "box.onload = initialize;" this stops that problem but then the infobox doesn't show...how do I fix my code so it only loads the map once AND shows the infobox.
function loadScript() {
var map = document.createElement('script');
map.type = 'text/javascript';
map.src = 'https://maps.googleapis.com/maps/api/js?key=key_goes_here&sensor=false&callback=initialize';
document.body.appendChild(map);
map.onload = function() {
var box = document.createElement('script');
box.type = 'text/javascript';
box.src = 'https://google-maps-utility-library-v3.googlecode.com/svn/trunk/infobox/src/infobox_packed.js';
document.body.appendChild(box);
box.onload = initialize;
};
}
window.onload = loadScript;
The map appears twice because you're calling initialize twice.
Before fixing that, let's simplify your code a bit. Never let yourself repeat blocks of code like that; instead make it into a common function.
Also, don't load infobox.js from googlecode.com; Google Code is not a CDN. Load your own copy.
So, the code may look like this:
function addScript( url, callback ) {
var script = document.createElement( 'script' );
if( callback ) script.onload = callback;
script.type = 'text/javascript';
script.src = url;
document.body.appendChild( script );
}
function loadMapsAPI() {
addScript( 'https://maps.googleapis.com/maps/api/js?key=key_goes_here&sensor=false&callback=mapsApiReady' );
}
function mapsApiReady() {
addScript( 'infobox.js', initialize );
}
window.onload = loadMapsAPI;
I created this script. You can call this and add any callback function, so you have to just include this to your scripts and call
googleMapsLoadAsync(function(){ alert('google maps loaded'); });
script
var googleMapsAsyncLoaded = false;
var googleMapsAsyncCallback = function(){ };
function googleMapsLoadAsync(callback) {
if (typeof callback !== 'undefined') { googleMapsAsyncCallback=callback; }
if(!googleMapsAsyncLoaded) {
$.getScript('https://maps.googleapis.com/maps/api/js?sensor=false&async=2&callback=googleMapsAsyncLoadedFunction');
} else {
googleMapsAsyncLoadedFunction();
}
}
function googleMapsAsyncLoadedFunction() {
googleMapsAsyncLoaded = true;
if(googleMapsAsyncCallback && typeof(googleMapsAsyncCallback) === "function") {
googleMapsAsyncCallback();
}
googleMapsAsyncCallback = function(){ };
}
Related
I want to conditionally insert few javascript files inside the DOM of the webpage. I also want to add a dependency.
var load = function(filename, callback) {
fileref = document.createElement("script")
fileref.setAttribute "type", "text/javascript"
fileref.setAttribute "src", filename
document.getElementsByTagName("head")[0].appendChild fileref
if (typeof callback !== "undefined" && callback !== null) {
callback();
}
}
load("http://www.myserver.com/lib.js",
function() { load("http://www.myserver.com/core.js") }
)
But I want to check whether the 'lib.js' is actually executed. For that, I would want to wait till a variable inside lib.js is available. How do I do it?
Don't run your callback immediately. Because content scripts share the DOM with their page, you can wait for the load event on the DOM <script> element:
var load = function(filename, callback) {
fileref = document.createElement("script");
fileref.setAttribute("type", "text/javascript");
fileref.setAttribute("src", filename);
// fire callback when script loads
fileref.addEventListener("load", function() {
if (typeof callback !== "undefined" && callback !== null) {
callback();
}
});
document.getElementsByTagName("head")[0].appendChild(fileref);
}
load("http://www.myserver.com/lib.js",
// this callback will run only after lib.js has fully loaded
function() { load("http://www.myserver.com/core.js") }
)
I have problems using an OnLoad event in a function:
(function () {
var ds = document.createElement('script');
ds.type = 'text/javascript';
ds.async = true;
ds.src = 'http://' + ds_shortname + '.myscript.com/emb.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ds);
ds.onLoad = function(){
alert('ok');
var ds_div = $('ds-div');
if (IsConnected())
{
alert('connect');
}else{
alert('not connect');
}
}
})();
In fact my ds.onLoad doesn't execute and I don't know why. I think it because my function execute herselve but I have no isea how to solve that.
Thanks a lot.
Use the Utilities/Asset classes from More for this, for example like this:
new Asset.javascript('//connect.facebook.net/en_US/all.js', {
onLoad:function(){
$('message').set('text', 'Facebook loaded!');
},
async: true
});
Working sample: http://jsfiddle.net/FU5rk/
Directly related to your problem: you inject the element into the DOM before applying the onLoad event. I'm pretty sure that if the file is in cache, or a really fast download, it's simply loaded before you set the event handler.
I would like to be able to load the Google.maps API only once for alle my pages.
Then i would like to be able to use geolocation or loading a map into a page anywhere on my web app.
The problem is that I cant figure out to seperate API loading and map initialization.
Which means i need to load the API each time I create a map.
I have referenced most of my code further down in the post but i suppose the following code is the problem.That piece of code takes care of the API Loading but at the same time it takes care of setting the initialize() function as a callback function and calling it.
var script = document.createElement("script");
script.type = "text/javascript";
script.src ="http://maps.googleapis.com/maps/api/js?key=mykey&sensor=false&callback=initialize";
document.body.appendChild(script);
How do i load the api once, lets say in the header, and then create a new map each time I go to specific page. WIthout loading the maps API again. (Note that im using Jquery mobile so my header only gets loaded one time for a session.)
I get this error:
Warning: you have included the Google Maps API multiple times on this page. This may cause unexpected errors.
Ii would like to tell you my setup.
-Im using Google Map APi v3
-I'm loading the API dynamically after the page has loaded.
-I'm using Jquery mobile, which means the page with google maps only gets partially reloaded when you visit it.
-Im using google maps for two things to show the map and for geolocation.
-I'm using the Google map api on several pages.
Im interacting with the map in 3 different places: In a header javascript see code below
A header javascript
A javascript in the body
The DIV in the body that holds the map.
Here is my code for the javascript that handles loading the API, showing the map, markers etc:
<script>
$('.error').hide();
//search criterias
var radius;
var timerange;
var type;
//user position variables
var userposition = false;
var mylatitudedegree = "=55.698";
var mylongitudedegree = "=12.579";
//map variables
var mapready = false;
var map;
var bound;
var markersArray = [];
//array for keeping track of the markers
var markercenter;
//hack
var pageinit = 0;
var initializer = 0;
var triggersearch = 0;
var loadscripts = 0;
var isgooglemapsloaded = false;
$( '#soegsagside' ).live( 'pageinit',function(event)
{
pageinit++;
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(setPosition, function(error) {
alert('Din location er ikke tilgængelig! Error code: ' + error.code);
userposition = false;
}, {
maximumAge : 60000,
timeout : 10000,
enableHighAccuracy : true
});
}
else {
alert("Din browser tillader ikke, at vise din lokation!");
userposition = false;
}
loadScript();
$("#search_filter_button").click(function() {
//hide the "skal udfyldes" labels
$('.error').hide();
// validate and process form here
radius = $("select#choose_radius_select").val();
if (radius == "vælg") {
$("label#radius_error").show();
$("select#choose_radius_select").focus();
return false;
}
timerange = $("select#choose_timerange_select").val();
if (timerange == "vælg") {
$("label#timerange_error").show();
$("select#choose_timerange_select").focus();
return false;
}
type = $("select#vælg_type").val();
if (type == "vælg") {
$("label#select_type_error").show();
$("select#vælg_type").focus();
return false;
}
//------------------post to php script ---------------
var dataString = 'radius=' + radius + '&timerange=' + timerange + '&type=' + type + '&mylatitudedegree=' + mylatitudedegree + '&mylongitudedegree=' + mylongitudedegree;
$.ajax({
type : "POST",
url : "soegsagDB.php",
data : dataString,
success : function(data) {
$('#søgeresultater').html(data);
$('#søgeresultater').trigger('create');
clearOverlays();
createtaskmarkers();
findCenterOfMarkers();
if (userposition) {
usergeoposition = new google.maps.LatLng(mylatitudedegree, mylongitudedegree);
map.setCenter(usergeoposition);
createuserposition(usergeoposition);
} else {
map.setCenter(markercenter);
}
expandMapBoundForMarkers()
}
});
//end of post search query to server
return false;
});
//end of click seach button
});
//end of page ready
function setPosition(position) {
userposition = true;
myposition = position.coords;
mylatitudedegree = position.coords.latitude;
mylongitudedegree = position.coords.longitude;
var milli = new Date();
}
//function for clearing the markerArray
function clearOverlays() {
for (var i = 0; i < markersArray.length; i++) {
markersArray[i].setMap(null);
}
}
//Function for initializing the map, which is called when the map is created
function initialize() {
initializer++;
bound = new google.maps.LatLngBounds();
var mapOptions = {
zoom : 13,
center : new google.maps.LatLng(55, 12),
mapTypeId : google.maps.MapTypeId.ROADMAP
}
//Create a map
map = new google.maps.Map(document.getElementById("map"), mapOptions);
mapready = true;
$("#search_filter_button").trigger('click');//Trigger click on the search button
triggersearch++;
}
//create user positio marker
function createuserposition(usergeoposition) {
var userPositionMarker = new google.maps.Marker({
position : usergeoposition,
map : map,
title : "Din position",
});
markersArray.push(userPositionMarker);
}
function createtaskmarkers() {
//Create the markers of the tasks
//1. find the task <li> that contain the data and loop through each one
//2. for each task collect the dato into variables and create markers and infowindows
//3. calculate center of point
//4. extendt map area to contain all points
var data = $.map($('li'), function(element) {
if (element.hasAttribute("data-latitude")) {
var tempPos = new google.maps.LatLng($(element).attr('data-latitude'), $(element).attr('data-longitude'));
var link = $(element).attr('data-link');
var title = $(element).attr('data-title');
var type = $(element).attr('data-type');
var date = $(element).attr('data-date');
tempMarker = new google.maps.Marker({
position : tempPos,
map : map,
title : title,
});
tempMarker.setIcon('http://maps.google.com/mapfiles/ms/icons/blue-dot.png')
var tempContentString = '<div style="width: 200px; height: 100px;">' + date + '<br></br>' + '<b>' + type + ' , ' + title + '</b>' + '</div>';
//Create infowindow
var tempInfowindow = new google.maps.InfoWindow({
content : tempContentString
});
//add market to markerArray
markersArray.push(tempMarker);
//Create event with infowindow
google.maps.event.addListener(tempMarker, 'click', function() {
tempInfowindow.open(map, this);
});
}
});
}
function findCenterOfMarkers() {
//calculate center of markers and change mapcenter to that
var sumlatitude = 0;
var sumlongitude = 0;
for ( position = 0; position < markersArray.length; position++) {
sumlatitude += markersArray[position].getPosition().lat();
sumlongitude += markersArray[position].getPosition().lat();
}
avglatitude = sumlatitude / markersArray.length;
avglongitude = sumlongitude / markersArray.length;
markercenter = new google.maps.LatLng(avglatitude, avglongitude);
}
function expandMapBoundForMarkers() {
//Extend bounds for map to fit all markers into map
for (var i in markersArray) {
bound.extend(markersArray[i].getPosition());
}
map.fitBounds(bound);
}
//loads the google maps api with KEY and appends the script to the document body
function loadScript() {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://maps.googleapis.com/maps/api/js?key=AIzaSyC8wZ6RmFySy0DnWvrUaA-2OJqcM1_AOIc&sensor=false&callback=initialize";
document.body.appendChild(script);
}
</script>
The only thing in the body of the page that has to do with the maps. Is the DIV that the map is loaded into.
<div id="map" style="width: 80%; height: 280px; margin: auto; background-color: gray">Kortet loader, vent venligst.</div> <!--alternative for full screen style="position:absolute;top:30px;bottom:50px;left:0;right:0;"-->
The API is also loaded in a common header script. Because I in general need to load it on other pages.
<script src='http://maps.google.com/maps/api/js?sensor=false'></script>
<script type="text/javascript">
$(document).ready( function () {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "http://maps.google.com/maps/api/js?sensor=false&callback=mynamespace.init_google_maps";
document.body.appendChild(script);
$(document).bind('pageinit', function() {
//do stuff here that happens each time a new page is loaded
});
});
});
</script>
the api is loaded once inside .ready(). you can create a new map in the callback that was passed to .bind() which is called each time a new page loads or is inserted. you can initialize the map inside mynamespace. mynamespace is a .js file included on the page
I know how to drag and drop in one window with html5. But how to drag and drop across frames?
Here is my script which can work in one window. Can someone help me?
<script>
var drag = document.getElementById("drag");
var drop = document.getElementById("drop");
drag.onselectstart = function () {
return false;
}
drag.ondragstart = function (ev) {
ev.dataTransfer.effectAllowed = "move";
ev.dataTransfer.setData("text", ev.target.innerHTML);
}
drag.ondragend = function (ev) {
var text = ev.dataTransfer.getData("text");
alert(text);
ev.dataTransfer.clearData("text");
return false;
}
drop.ondragover = function (ev) {
ev.preventDefault();
return true;
}
drop.ondragenter = function (ev) {
this.background = "#ffffff";
return true;
}
drop.ondrop = function (ev) {
}
</script>
#Nickolay: oh, ok.
There's an example at http://www.useragentman.com/blog/2010/01/10/cross-browser-html5-drag-and-drop/ .
Added:
I'm not sure why the OP's code didn't work - maybe it wasn't loaded in both frames? I modified their Javascript a little to give more indications:
window.onload = function () {
var drag = document.getElementById('drag');
var drop = document.getElementById("drop");
if (drag) {
drag.style.backgroundColor = '#00ff00';
drag.onselectstart = function () {
return false;
}
drag.ondragstart = function (ev) {
ev.dataTransfer.effectAllowed = "move";
ev.dataTransfer.setData("text", ev.target.innerHTML);
}
drag.ondragend = function (ev) {
var text = ev.dataTransfer.getData("text");
alert(text);
//ev.dataTransfer.clearData("text");
return false;
}
}
if (drop != null) {
drop.style.backgroundColor = '#0000ff';
drop.ondragover = function (ev) {
ev.preventDefault();
return false;
}
drop.ondragenter = function (ev) {
this.style.backgroundColor = "#ff0000";
return false;
}
drop.ondrop = function (ev) {
return false;
}
}
}
It works between iframes and between browser windows (only tested in Firefox 11 and IE9 on Windows 7 x64).
I modified your script to work in the case that the iframe name is "frame1". Please check it now.
<script type="text/javascript">
window.onload = function ()
{
var drag = document.getElementById("drag");
var drop = frame1.document.getElementById("drop");
drag.draggable = true;
drag.onselectstart = function () {
return false;
}
drag.ondragstart = function (ev) {
ev.dataTransfer.effectAllowed = "move";
ev.dataTransfer.setData("text", ev.target.innerHTML);
}
drop.ondragover = function (ev) {
ev.preventDefault();
return true;
}
drop.ondragenter = function (ev) {
this.background = "#ffffff";
return true;
}
drop.ondrop = function (ev) {
var data = ev.dataTransfer.getData("text");
drop.innerHTML += data;
ev.preventDefault();
}
}
Check out the tutorial for Cross-Frame Drag and Drop. It explains the events required and the basic flow when working with multiple frames.
http://blog.dockphp.com/post/78640660324/cross-browser-drag-and-drop-interface-development-using
How are the iframes hosted? are you just using html files? as this could potentially be the issue.
I created a couple of html files with the drag and drop code in your question, this didn't work when just referencing each other. However when I added the files to IIS server and referenced the files using localhost it then started to work.
how to access outer function's argument 'parent' ??? please see comments in code
!!last edit : This question is misleading, my problem is caused by wrong input argument
renderData : function(parent, children){
children.each(function(e, index){
var li = new Element('li');
var hasChildren = false;
if(e.children && e.children.length >0){
var img = new Element('img');
img.src = 'a1.png';
img.inject(li);
hasChildren = true;
}
if(e.icon){
var img = new Element('img');
img.src = e.icon;
img.inject(li);
}else{
var img = new Element('img');
img.src = 'b1.png';
img.inject(li);
}
li.set('html',e.text);
console.log(this);
// how to access outer function's argument 'parent' ???
li.inject(parent);
if(hasChildren){
var ul = new Element('ul');
this.renderData(ul, e.childRen);
ul.inject(e);
}
}.bind(this));
within an each loop:
array.each(function(el) {
this.method(); // this == (instance / scope)
}, this); // where **this** is your parent scope.
another acceptable way is:
var self = this;
...
array.each(function(el) {
self.method(); // fine.
}); // where this is your parent scope.
http://mootools.net/docs/core/Types/Array#Array:Array-each
although, using .bind(this) should work too... http://www.jsfiddle.net/dimitar/fFy4J/ - so what is the problem?
if i understood correctly, your problem is that you cant do li.inject(parent)
there's no reason why you can't access 'parent' since it's been passed as a parameter to the function renderData()
I've tried this simple test
var test;
window.addEvent('domready', function(){
test = new TestClass();
});
var TestClass = new Class({
Implements: [Options, Events],
initialize: function(){
this.renderData($('parent'),$$('span'))
},
renderData : function(parent, children){
children.each(function(e, index){
console.log(parent);
}.bind(this));
}
});
and it works fine... but i'm no really sure what's the problem on your code