I only load Google maps When needed. Before I refactored my code, it worked and looked like this:
function initialize_map_brand() {
(...)
}
jQuery(document).ready(function ($) {
load_google_map('initialize_map_brand');
});
After refactoring, my code looks like this:
lib = {
loadGoogleMapScript: function(_callback) {
(...)
script.src = 'http://maps.google.com/maps/api/js?sensor=false&callback=' +_callback;
}
}
Page = {
viewPage: {
init: function() {
lib.loadGoogleMapScript(self.initialize_map);
},
initialize_map: function() {
var locations = [ (...)
}
}
}
jQuery(document).ready(function ($) {
Page.viewBPage.init();
});
And now I'm getting this error:
"NetworkError: 400 Bad Request -
http://maps.google.com/maps/api/js?sensor=false&callback=function%20()%20{var%20locations%20=%20[[%....
It seems it takes the entire function code and passes it in the url. So how can I load the Google Maps script correctly with my new code?
Se my fiddle here.
According to the documentation You need to provide a string for the url callback parameter with the name of a function in the global scope.
You instead passed the function as parameter, so the function body gets appended to the url.
var Page = {
viewPage: {
init: function() {
lib.loadGoogleMapScript('Page.viewPage.initialize_map');
},
initialize_map: function() {
}
}
};
window.Page = Page;
Related
I'm currently loading the Google Maps API using JavaScript like so:
// Private methods
function loadApi() {
var script = document.createElement('script');
script.onerror = function(e) {
exit('MarvMap: Unable to load Google Map API, please check the URL.');
};
script.onload = function () {
if (this.options.debug) console.log('MarvMap (Debug): Google Map API loaded, using: ' + this.options.api.key);
}.call(this);
script.src = this.options.api.url;
document.head.appendChild(script);
}
This loads the script and ads it before the closing </head> tag. However the script it loads appears to load additional scripts so it's not ready to use straight away.
Here you can see that i'm calling the above function first, and then trying to use the Google Maps API:
// Public methods
MarvMap.prototype.init = function() {
loadApi.call(this);
// Setup map options and map reference
initMapOptions.call(this);
// Build the map
build.call(this);
};
However im getting an error saying google is not defined on the line marked below:
function initMapOptions() {
this.mapReference = new google.maps; // Error here
this.map_options = {
map_type: function(i) {
if (this.mapReference.MapTypeId[(i-1)] !== undefined) {
return this.mapReference.MapTypeId[(i-1)];
} else { exit(this.errors.map_type(i)); }
}.bind(this)
};
}
to delay api usage while i wait for some file (or multiple files) to load i would use something like:
loadApi(this);
ensureApiIsLoaded();
function ensureApiIsLoaded(){
if(typeof google == 'undefined'){
setTimeout(ensureApiIsLoaded, 125);
return;
} else {
callbackGoesHere(); //initMapOptions?
}
};
regarding your while loop:
while (typeof google != 'undefined') {
setTimeout(function() { }, 1000);
}
google;
you initiate the script loading -> api isn't ready, obviously
the while condition will evaluate to 'false' -> body of while loop is dismissed
google is still undefined because there wasn't any time to actually load the lib in between ordering that the script file be acquired and the attempted usage
-> error.
I have a array where i have specified the files i need to load in javascript before calling specific script. Lets call those particular lines of code as myscript.
I did as follows
var fileNamesArray = new Array();
fileNamesArray.push("abc.js");
fileNamesArray.push("pqr.js");
fileNamesArray.push("xyz.js");
fileNamesArray.push("klm.js");
var totalFiles = jQuery(fileNamesArray).length;
var tempCount = 0;
jQuery.each(fileNamesArray, function(key, value) {
jQuery.getScript(value, function() {
tempCount++;
});
});
to check whether all files are being loaded or not, i done following thing but doesn't seems to be effective
var refreshIntervalId = setInterval(function() {
if (tempCount == totalFiles) {
clearInterval(refreshIntervalId);
return;
}
}, 10);
i have implemented these in object oriented javascript as follows
function Loader() {
this.jQuery = null;
// check for specifically jQuery 1.8.2+, if not, load it
if (jQuery == undefined) {
jQuery.getScript(
"/Common/javascript/jquery/map/javascript/jquery-1.8.2.js",
function() {
this.jQuery = jQuery.noConflict();
});
} else {
var jQueryVersion = $.fn.jquery;
jQueryVersion = parseInt(jQueryVersion.split('.').join(""));
if (182 > jQueryVersion) {
jQuery.getScript(
"/Common/javascript/jquery/map/javascript/jquery-1.8.2.js",
function() {
this.jQuery = jQuery.noConflict();
});
}
}
}
Loader.prototype.LoadAllFile = function() {
//here i am loading all files
}
Loader.prototype.bindMap = function(options) {
this.LoadAllFile();
//execute the script after loading the files... which we called as myscript
}
i am loading more than 12-14 js files via ajax.
if you observe Loader.prototype.bindMap, i am loading all the files first and then executing the script.
But it seems that myscript the script start executing before all files being loaded.
what are the better ways to execute the script only after all js files are loaded.
Take a look at jQuery's .load() http://api.jquery.com/load-event/
$('script').load(function () { });
Based on the documentation on Jquery.getScript , it is a shorthand for Jquery.ajax. By default this in async call. You might want to change it to do a synchronous call.
To set this property, you can refer to this
So instead of doing a setInterval, you can just loop in your array and do a Jquery.getScript.
So I've setup my first JS design pattern - but I've run into an issue.
Here is my code on fiddle:
http://jsfiddle.net/jrutter/CtMNX/
var emailSignup = {
'config': {
// Configurable Options
'container': $('#email-signup'),
'emailButton': $('#email-submit'),
'emailInput': $('#email-input'),
'brontoDirectAddURL': 'URL',
'brontoListID': '0bbc03ec000000000000000000000003287b',
},
'init': function (config) {
// stays the same
// provide for custom configuration via init()
if (config && typeof (config) == 'object') {
$.extend(emailSignup.config, config);
}
// Create and/or cache some DOM elements
emailSignup.$container = $(emailSignup.config.container);
emailSignup.$button = $(emailSignup.config.emailButton);
emailSignup.$input = $(emailSignup.config.emailInput);
emailSignup.$brontoURL = emailSignup.config.brontoDirectAddURL;
emailSignup.$brontoList = emailSignup.config.brontoListID;
// Add email track to drop image pixel into for submission
emailSignup.$container.append('<div class="email-error"></div>');
emailSignup.$container.append('<div class="email-track"></div>');
// Call getEmaile
emailSignup.getEmail(emailSignup.$button, emailSignup.$input);
// make a note that the initialization is complete
emailSignup.initialized = true;
},
'getEmail': function ($button, $input) {
// click event
emailSignup.$button.click(function () {
// get the val
var $emailVal = $(emailSignup.$input).val();
// Call validateEmail
console.log($emailVal);
emailSignup.validateEmail($emailVal);
return false;
});
},
'validateEmail': function ($emailVal) {
var $emailRegEx = /^([\w-\.]+#([\w-]+\.)+[\w-]{2,4})?$/;
//console.log($emailVal);
if ($emailVal == '') {
$(".email-error").html('<p>You forgot to enter an email address.</p>');
} else if (!$emailRegEx.test($emailVal)) {
$(".email-error").html('<p>Please enter a valid email address.</p>');
} else {
$(".email-error").hide();
emailSignup.submitEmail($emailVal);
}
},
'submitEmail': function ($emailVal) {
$(".email-track").html('<img src=' + emailSignup.$brontoURL+'&email='+$emailVal+'&list1=' + emailSignup.$brontoList + '" width="0" height="0" border="0" alt=""/>');
},
};
Its a function to add a subscriber to an email list via bronto - it works perfectly when the script is included on the page and the init function is setup on the page too. But when I include the script in a shared header and try to fire the function from the document-ready, it doesnt seem to be working.
Also, if I try to pass in a 'container' - that also is breaking the script. Not sure what Im doing wrong? But if I pass in the URL - that does work!
$(function () {
emailSignup.init({
'brontoDirectAddURL':'URL','container':'#email-signup'
});
});
Any advice would be greatly appreciated!
Change the following code...
emailSignup.$container = emailSignup.config.container;
emailSignup.$button = emailSignup.config.emailButton;
emailSignup.$input = emailSignup.config.emailInput;
emailSignup.$brontoURL = emailSignup.config.brontoDirectAddURL;
emailSignup.$brontoList = emailSignup.config.brontoListID;
into the following...
// Create and/or cache some DOM elements
emailSignup.$container = $(emailSignup.config.container);
emailSignup.$button = $(emailSignup.config.emailButton);
emailSignup.$input = $(emailSignup.config.emailInput);
emailSignup.$brontoURL = $(emailSignup.config.brontoDirectAddURL);
emailSignup.$brontoList = $(emailSignup.config.brontoListID);
// Add email track to drop image pixel into for submission
emailSignup.$container.append('<div class="email-error"></div>');
emailSignup.$container.append('<div class="email-track"></div>');
You can not call append on a string. I've update your JSFiddle.
Your default config object contains jQuery collections. However, you are simply passing the string "#email-signup" as your container instead of $("#email-signup"). That's where the error is coming from. Your initial call should thusly be:
$(function () {
emailSignup.init({
'brontoDirectAddURL':'URL','container': $('#email-signup')
});
});
Note that as your initial module includes some jQuery calls, you will need to wrap the whole emailSignup mess into a $(document).ready() as well.
You may consider reconfiguring this whole thing as a jQuery plugin.
I am using sammy.js plugin in my single page application. The plugin is not working, whenever user tries to navigate in the page it is showing the following error on console :
[Tue Dec 04 2012 17:48:13 GMT+0530 (India Standard Time)] #main 404 Not Found get /page_home
Error
arguments: undefined
get stack: function () { [native code] }
message: "404 Not Found get /page_home "
set stack: function () { [native code] }
type: undefined
__proto__: d
What is this issue and how can it be fixed ?
EDIT
Sammy configuration code:
var app = $.sammy('#main', function () {
this.get('#/:name', function () {
var id = this.params['name'];
$.trim(id);
var flag = true;
if ($("#main").hasClass("presentation")) {
$.each(slides, function (i, v) {
if ($(v).attr("class") == id) {
ScanNavigationD(id);
flag = false;
return false;
}
});
if (flag) {
ScanNavigationD($(slides[0]).attr("class"));
}
}
else if ($("#main").hasClass("printdoc") || typeof $("#main").attr("class") == "undefined") {
$.each(Pages, function (i, v) {
if ($(v).attr("class") == id) {
ScanNavigationD(id);
flag = false;
return false;
}
});
if (flag) {
ScanNavigationD($(Pages[0]).attr("class"));
}
}
});
});
$(function () {
app.run();
});
#tom-rider the problem is the app.run called without argument.
The sammy app.run function accept a start_url argument to set (via the _setLocation method) the app current location before call _checkLocation method to check if url is changed...
So try to change
app.run();
with
app.run('#/');
this work for me.
Follow this fiddle for a working demo and look at the console: no error!
will this simple code work?
var app = $.sammy('#main', function () {
this.get('#/:name', function () {
alert(this.params['name']);
});
});
$(function () {
app.run();
});
if this small code alerts 'page_home' there is something wrong with your script inside:
then you should be able to answer these questions: where is the ScanNavigationD-Function? where are the "slides"/"Pages" - arrays defined?
EDIT:
ok, i did another test at my computer. thats what i did:
created a html-document
included first jQuery then sammy.js
<script src="http://code.jquery.com/jquery-1.8.3.min.js" type="text/javascript">
<script src="sammy.js" type="text/javascript">
i filled the vars and functions i asked for with dummy-content:
<script>
var ScanNavigationD = function() {},
slides = ['slide1', 'slide2'],
Pages = ['page1', 'page2'];
<script>
then i copy pasted your code into my html-document.
<script>
//your code
<script>
then i created the div-main container:
everything worked. the last thing i see you are doing wrong is, that you are just on your local filesystem.
sammy.js seems to need a webserver to run! at least localhost!
file://...
WILL NOT WORK
Seems like you are sending in page_home as a parameter when running the script which resolves to a 404 not found error. Try look for 'page_home' throughout your files, recursively to find where this is coming from.
Jquery provides a very convenient way to delay executing code until the DOM is fully loaded:
$(function() {
dom_is_loaded();
});
The Facebook Javascript SDK, when loaded asynchronously, provides a similar mechanism:
window.fbAsyncInit = function() {
fb_is_loaded();
}
What's the most elegant way to delay code from running until the DOM and Facebook's SDK have both fully initialized?
Is there a reason why just doing
window.fbAsyncInit = function() {
$(function() {
both_loaded();
});
}
doesn't work?
Why not:
var jq_ready = false, fb_ready = false;
function bothReady(){
...
}
$(function() {
dom_is_loaded();
jq_ready = true;
if(fb_ready){
bothReady();
}
});
window.fbAsyncInit = function() {
fb_is_loaded();
fb_ready = true;
if(jq_ready){
bothReady();
}
}
I think this is cleaner than setting an interval and will handle either event happening first.
Probably set a flag in your fbAsyncInit function and check it in the jQuery load:
$(handleLoad);
function handleLoad() {
if (!facebookLoaded) {
setTimeout(handleLoad, 10); // Or 100 or whatever
}
else {
// You're good to go
bothLoaded();
}
}
I expect there's already some global you can check for whether Facebook is loaded (I haven't used the Facebook API). If not, you can use your own flag (ideally not a global):
(function() {
var fbLoaded = false;
window.fbAsyncInit = function() {
fbLoaded = true;
};
jQuery(handleLoad);
function handleLoad() {
if (!facebookLoaded) {
setTimeout(handleLoad, 10); // Or 100 or whatever
}
else {
// You're good to go
bothLoaded();
}
}
})();
You might want to check out this explanation
http://pivotallabs.com/users/jdean/blog/articles/1400-working-with-asynchronously-loaded-javascript