I have the script below placed in the HEAD of the page. The map should initialize when the page loads. There's two pieces to this puzzle, one is the script within the document.ready which sets all variables and configures the map i am wanting to place on a page. The second piece is the window.onload=initialize_map; that starts the map.
I believe everything is running correctly, however, i don't know for sure. All i know is that the initialize_map function never runs. I even tried to set an onclick on a button with initialize_map(); to try and manually start the map and it still didn't work. Is there something wrong with my code? Any help is greatly appreciated.
Thanks!
CODE IN QUESTION:
<script src= "http://maps.google.com/maps?file=api&v=2&key=ABQIAAAAhTrgZ5jvdqcEQouEpPcZ_hS81NmJwGXlxuJr8lEEo4Njw3WRVhT8auzZb55JSMDkwIaCdNkPHL5gNg" type="text/javascript"> </script>
<script type="text/javascript">
$(document).ready(function(){
var dealerName = $('.name', '.adr').text();
var customerName = dealerName.slice(0, - 1);
var customerAddress = $('.street', '.adr').text() + ', ' + $('.locality', '.adr').text() + ', ' + $('.state', '.adr').text() + ', ' + $('.zipCode', '.adr').text();
$("#nameAddress .placeholderName").html(customerName);
$("#nameAddress .placeholderAddress").html(customerAddress);
var error_address_empty = 'Please enter a valid address first.';
var error_invalid_address = 'This address is invalid. Make sure to enter your street number and city as well?';
var error_google_error = 'There was a problem processing your request, please try again.';
var error_no_map_info = 'Sorry! Map information is not available for this address.';
var default_address = customerAddress;
var current_address = null;
var map = null;
var geocoder = null;
var gdir = null;
var map_compatible = false;
if( GBrowserIsCompatible() ) {
map_compatible = true;
}
function initialize_map() {
if( map_compatible ) {
map = new GMap2(document.getElementById('map_canvas'));
geocoder = new GClientGeocoder();
show_address(default_address);
map.addControl(new GSmallMapControl());
map.addControl(new GMapTypeControl());
}
}
function show_address(address) {
if( map_compatible && geocoder ) {
current_address = address;
geocoder.getLatLng(
address,
function( point ) {
if( !point ) {
alert(error_no_map_info);
} else {
map.setCenter(point, 13);
var marker = new GMarker(point);
map.addOverlay(marker);
marker.openInfoWindowHtml("<span style='font-size:14px; font-weight:bold;'>" + customerName + "<br /></span><span style='font-size:12px;'>" + address + "</span>");
}
}
);
}
return false;
}
function get_directions() {
if( map_compatible ) {
if( document.direction_form.from_address.value == '' ) {
alert(error_address_empty);
return false;
}
document.getElementById('directions').innerHTML = '';
gdir = new GDirections(map, document.getElementById('directions'));
GEvent.addListener(gdir, 'error', handleErrors);
set_directions(document.direction_form.from_address.value, current_address);
}
return false;
}
function set_directions(fromAddress, toAddress) {
gdir.load("from: " + fromAddress + " to: " + toAddress,
{ "locale": "en" });
}
function handleErrors(){
if( gdir.getStatus().code == G_GEO_UNKNOWN_ADDRESS )
alert(error_invalid_address);
else if( gdir.getStatus().code == G_GEO_SERVER_ERROR )
alert(error_google_error);
else if( gdir.getStatus().code == G_GEO_MISSING_QUERY )
alert(error_address_empty);
else
alert(error_invalid_address);
}
});
window.onload=initialize_map;
</script>
Two problems jump out right away:
initialize_map is not in the global scope (it's defined within the anonymous ready event handler), so you're likely assigning an undefined value to window.onload, as you've placed the assignment itself outside of that function (in the global scope).
Why are you mixing jQuery's ready handler with window.onload? At worst, this is flat-out not going to work - from the jQuery documentation:
The .ready() method is generally incompatible with the attribute. If load must be used, either do not use .ready() or use jQuery's .load() method to attach load event handlers to the window or to more specific items, like images.
...and even at best, it's unnecessary. Use jQuery for both or neither:
$(document).ready(function(){
...
$(window).load(initialize_map);
...
});
The entire body of your function is in an if statement that depends on the boolean variable map_compatible being true. Are you sure that it is true?
Try putting an alert before the if statement and see if it runs that way. Maybe print out the value of map_compatible.
If it is not true then you can use a tool like firebug for firefox to step through your javascript and see why it is not being set to true as you expect it to.
Related
I've downloaded this script for use conditional fields in forms:
(function ($) {
$.fn.conditionize = function(options) {
var settings = $.extend({
hideJS: true
}, options );
$.fn.showOrHide = function(is_met, $section) {
if (is_met) {
$section.slideDown();
}
else {
$section.slideUp();
$section.find('select, input').each(function(){
if ( ($(this).attr('type')=='radio') || ($(this).attr('type')=='checkbox') ) {
$(this).prop('checked', false).trigger('change');
}
else{
$(this).val('').trigger('change');
}
});
}
}
return this.each( function() {
var $section = $(this);
var cond = $(this).data('condition');
// First get all (distinct) used field/inputs
var re = /(#?\w+)/ig;
var match = re.exec(cond);
var inputs = {}, e = "", name ="";
while(match !== null) {
name = match[1];
e = (name.substring(0,1)=='#' ? name : "[name=" + name + "]");
if ( $(e).length && ! (name in inputs) ) {
inputs[name] = e;
}
match = re.exec(cond);
}
// Replace fields names/ids by $().val()
for (name in inputs) {
e = inputs[name];
tmp_re = new RegExp("(" + name + ")\\b","g")
if ( ($(e).attr('type')=='radio') || ($(e).attr('type')=='checkbox') ) {
cond = cond.replace(tmp_re,"$('" + e + ":checked').val()");
}
else {
cond = cond.replace(tmp_re,"$('" + e + "').val()");
}
}
//Set up event listeners
for (name in inputs) {
$(inputs[name]).on('change', function() {
$.fn.showOrHide(eval(cond), $section);
});
}
//If setting was chosen, hide everything first...
if (settings.hideJS) {
$(this).hide();
}
//Show based on current value on page load
$.fn.showOrHide(eval(cond), $section);
});
}
}(jQuery));
I'm trying this because I need to use conditionize() in one of my tabs and when I reload the tab, all works but if I go to other tab and I return to the previous tab(where I need this works), I get that error.
When I change tabs, I'm only reloading one part of the page.
When I load the page this works perfectly, but if I try to call function again from browser console, it tells me that TypeError: $(...)conditionize() is not a function.
I have included the script in header tag and I'm calling it with this script on the bottom of body:
<script type="text/javascript">
$('.conditional').conditionize();
</script>
EDIT:
I have written
<script type="text/javascript">
console.log($('.conditional').conditionize);
setTimeout(function () {console.log($('.conditional').conditionize);}, 2);
</script>
and this print me at console the function, and when 2 milliseconds have passed, it print me undefined
I have found the solution.
Because any reason, the $ object and jQuery object are not the same in my code.
I have discovered it using this on browser console:
$===jQuery
This return false (This was produced because in other JS, I was using the noConflict(), which give me the problem)
Explanation: noConflict()
So I have solved it changing the last line of my JS by:
//Show based on current value on page load
$.fn.showOrHide(eval(cond), $section);
});
}
}($));
Putting the $ instead of 'jQuery'
I have the following code
(function() {
var weather = new Weather();
var input = document.getElementById("inputCity");
var weatherHolder = document.getElementsByClassName("weather");
var loading = document.getElementById("loadingSign");
input.focus();
input.onkeyup = function(e) {
if (e.keyCode == 13 && input.value != "") {
loading.classList.remove("hidden");
weather.getWeather(input.value, function (returnValue) {
for (iter in returnValue) {
weatherHolder[iter].classList.remove('hidden');
document.getElementById("weather" + (parseInt(iter) + 1)).innerHTML = returnValue[iter].date;
}
});
loading.classList.add("hidden");
}
};
})();
I want to force the execution of the line loading.classList.remove("hidden"); before waiting for the closure bellow to complete.
If I remove the closure lines the script works perfectly, however, I can't make it work if the closure fails.
For instance, the code below works perfectly:
(function() {
var weather = new Weather();
var input = document.getElementById("inputCity");
var weatherHolder = document.getElementsByClassName("weather");
var loading = document.getElementById("loadingSign");
input.focus();
input.onkeyup = function(e) {
if (e.keyCode == 13 && input.value != "") {
loading.classList.remove("hidden");
alert("teste");
loading.classList.add("hidden");
}
};
})();
The problem is in the line loading.classList.remove("hidden"); . This is supposed to remove a class that's hiding a message and a spinner. If I replace the closure lines with an alert the spinner shows, however, if I have that closure function the spinner is never shown.
How can I force that line to be called whether the closure is successful or not?
I don't really understand the question but judging from the code you have, it would be wiser to add the loading.classList.add("hidden"); inside the callback so it gets executed correctly.
(function() {
var weather = new Weather();
var input = document.getElementById("inputCity");
var weatherHolder = document.getElementsByClassName("weather");
var loading = document.getElementById("loadingSign");
input.focus();
input.onkeyup = function(e) {
if (e.keyCode == 13 && input.value != "") {
loading.classList.remove("hidden");
weather.getWeather(input.value, function (returnValue) {
for (iter in returnValue) {
weatherHolder[iter].classList.remove('hidden');
document.getElementById("weather" + (parseInt(iter) + 1)).innerHTML = returnValue[iter].date;
}
// Here
loading.classList.add("hidden");
});
}
};
})();
Ok so you are asking to "force the execution of..." but in fact what I suspect is happening here is that: the line we moved was not "waiting" on getWeather to finish.
I have a question about multi browser compatibility. I want to use the event.target instead event.srcElement in the following code to make it work for firefox.
I have used target = event.target || event.srcElement. It is not working. Any help will be appreciated.
function jumptoPopupMenuItem(theMenuID)
{
if (event.srcElement.className == "RightClickMenuItems")
{
if (event.srcElement.getAttribute("url") != null)
{
var strParameters = "";
if (theMenuID == "mnuAppointmentMenu")
{
strParameters = "AppointmentNumber=" + m_strAppointmentTypeYearNumber;
}
else if (theMenuID == "mnuAvailableHourMenu")
{
strParameters = "PreFillLanguageID=" + m_nLanguageID;
strParameters = strParameters + "&PreFillInterpreterID=" + m_nInterpreterID;
strParameters = strParameters + "&PreFillDateOfService=" + m_dtDateOfService;
}
if (event.srcElement.getAttribute("target") != null)
{
var PopupWindow = window.open(
event.srcElement.url + strParameters,
event.srcElement.getAttribute("target"));
PopupWindow.focus();
}
else
{
window.location = event.srcElement.url;
}
}
hidePopupMenu(theMenuID);
}
}
Some standard ways to register event handlers with compatibility (very simplified code):
HTML:
<button onclick="eventHandlerFunc(event)" />
<!-- better to register as: -->
<button onclick="eventHandlerFunc.call(this,event)" />
JavaScript (addEventListener or attachEvent):
if (window.addEventListener) someElem.addEventListener("click",eventHandlerFunc,false);
else if (window.attachEvent) someElem.attachEvent("onclick",eventHandlerFunc);
JavaScript (element property):
someElem.onclick = eventHandlerFunc;
Where eventHandlerFunc() function defined as:
function eventHandlerFunc(event) { // or var eventHandlerFunc = function(event) {
event = event||window.event; // can be needed only for IE6-IE8
// because `event` parameter hide `event` global
// variable (`window.event`)
var target = event.target||event.srcElement
}
NOTE: If needed compatibility for this variable additional code must be added.
If then needed to use event variable (defined inside eventHandlerFunc() as parameter) inside other functions you must send it to these functions:
function eventHandlerFunc(event) {
event = event||window.event; // can be needed only for IE6-IE8
/*
...
*/
jumptoPopupMenuItem(event,theMenuID);
}
function jumptoPopupMenuItem(event,theMenuID) {
}
I'm trying to create a mash Up of sorts... I want the functions to be in one file but when I add my Ajax functions (half way down ) nothing displays.
Also I want to display them with jQuery, and the top function(Google maps with marker and info) all works a treat until I add the bottom functions.
Should I add them in the (function () {} ) like Google has and what is the (); on the end of the googlemap function?
and when I call my functions in my code how will I call the ajax for the preview as the window.onload has been called in the Google one.
I know that I can use the $.ready function(){} but do I just put the function names in the .ready function { }
I am unsure how to add all the functions in one file and make them work. Basically
this is the code:
(function() {
//define global variables
var map, geocoder, marker, infowindow;
window.onload = function() {
//creating the map
var options = {
zoom: 5,
center: new google.maps.LatLng(53.383, -1.483),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map'), options);
//code for catching the form submit event goes here
//Getting the reference to the HTML form
var form = document.getElementById('addressForm');
//Catching the forms submit event
form.onsubmit = function () {
//getting the address from the text input
var address = document.getElementById('address').value;
//Making the geocode call
getAddress(address);
//Preventing the form from doing a page submit
return false;
}
}
//Function Stub
function getAddress(address) {
//Check to see if we already have a geocode object.
//If not we create one
if(!geocoder) {
geocoder = new google.maps.Geocoder();
}
//Creating the geoCoderRequest Object
var geocoderRequest = {
address: address
}
//Making the geocode request
geocoder.geocode(geocoderRequest, function (results, status) {
//Check if status is ok beofre proceeding
if (status == google.maps.GeocoderStatus.OK){
//Center the map on the returned location
map.setCenter(results[0].geometry.location);
//Check to see if already a Marker there
if (!marker){
//Create a new marker and add it to the map
marker = new google.maps.Marker({
map: map
});
}
//Setting position of the Marker to returned location
marker.setPosition(results[0].geometry.location);
//Check to see if we've already an info window
if(!infowindow) {
//Creating a new info window
infowindow = new google.maps.InfoWindow();
}
//Creating the content of the info window to the Address
//and the returned position
var content = '<strong>' + results[0].formatted_address + '</strong><br />';
content += 'Lat: ' + results[0].geometry.location.lat() + '<br />';
content += 'Lng: ' + results[0].geometry.location.lng();
//Adding the content to the info window
infowindow.setContent(content);
//Opening the infoWindow
infowindow.open(map, marker);
}
});
}
})();
// beginning of new function
var xhr = false;
var xPos, yPos;
function prev(){
var link = document.getElementByTagName("a").onmouseover = showPreview;
}
function showPreview(evt) {
if (evt) {
var url = evt.target;
}
else{
evt = window.event;
var url = evt.srcElement;
}
xPos = evt.clientX;
yPos = evt.clientY;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else {
if (window.ActiveXObject) {
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) { }
}
}
if (xhr) {
xhr.onreadystatechange = showContents;
xhr.open("GET", url, true);
xhr.send(null);
}
else {
alert("Sorry, but I couldn't create an XMLHttpRequest");
}
return false;
}
function showContents() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var outMsg = xhr.responseText;
}
else {
var outMsg = "There was a problem with the request " + xhr.status;
}
var preview = document.getElementById('preview');
preview.innerHTML = outMsg;
preview.style.top = parseInt(yPos)+2 + "px";
preview.style.left = parseInt(xPos)+2 + "px";
preview.style.visibility = "visible";
preview.onmouseout = function(){
document.getElementById('preview').style.visibility = "hidden";
}
}
It depends on why you're adding functions. but here is a simple formula. If you want you're functions to be called on document ready only and want them to be called once when the document is loaded. Then you add them as "anonymous functions"
EXAMPLE:
$(function () {
//you code
...............
// you can call your named functions also here.
//like
somefunction();
});
But if you expect them to be called later on as well, when the document has already been loaded. Then add the "named functions"
EXAMPLE:
function somename()
{
............
}
In both cases you can have them in one file and regarding the (); at the end of the function, it is a way of calling anonymous functions immediately in JavaScript, like document.ready in jQuery.
everybody. I'm puzzled as to why I keep getting the error "GM_registerMenuCommand is not defined" when I try to run a userscript that I created. I have tried this in Firefox using Scriptish 1.0b9 and the latest version of Greasemonkey. I even disabled all addons except Scriptish to see if it was a conflict, but with no joy.
I'm including jQuery in my userscript using this template by Erik Vold. Before trying this template, I put the exact same code block in the template proposed by Joan Piedra and everything worked fine. Unfortunately, Piedra's template did not work in Chrome, which is something that I think is necessary, considering Chrome's growing userbase. The snippet that's throwing the error is below:
// a function that loads jQuery and calls a callback function when jQuery has finished loading
function addJQuery(callback) {
var script = document.createElement("script");
script.setAttribute("src", "http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js");
script.addEventListener('load', function() {
var script = document.createElement("script");
script.textContent = "(" + callback.toString() + ")();";
document.body.appendChild(script);
}, false);
document.body.appendChild(script);
}
// the guts of this userscript
function main() {
var isLevelupMove = false;
var isTutorMove = false;
var isTM = false;
var TMhead = $('#moves\\:machine');
var hasSecondEvo = false;
var hasFinalEvo1 = false;
var hasFinalEvo2 = false;
var header = $('.header-row').eq(1);
var TMmoves = new Array();
//This section deals with the user-defined colors
GM_registerMenuCommand("Color for pre-evolutionary-only moves", prevoColorPrompt);
GM_registerMenuCommand("Color for first evolution-only moves", evoColorPrompt);
if(localStorage.getItem('prevoColor') == null || localStorage.getItem('evoColor') == null)
{
localStorage.setItem('prevoColor', 'red');
localStorage.setItem('evoColor', 'orange');
}
var prevoColor = localStorage.getItem('prevoColor');
var evoColor = localStorage.getItem('evoColor');
function prevoColorPrompt()
{
var input = prompt("Please enter a desired 6-digit hex color-code for pre-evolutionary pokemon:")
localStorage.setItem('prevoColor', '#'+input);
}
function evoColorPrompt()
{
var input = prompt("Please enter the desired 6-digit hex color-code for first-evolution pokemon:")
localStorage.setItem('evoColor', '#'+input);
}
//This loop tests each 'th' element in a sample header row, determining how many Evos are currently present in the chart.
$('.header-row').eq(1).find('th').each(function(index)
{
if($(this).find('a').length != 0)
{
switch(index)
{
case 2:
hasSecondEvo = true;
break;
case 3:
hasFinalEvo1 = true;
break;
case 4:
hasFinalEvo2 = true;
break;
}
}
});
//All 'tr' siblings are TM moves, since it's the last section on the page
//This array puts only the names of the available TMs into the TMmoves array
TMhead.nextAll().each(function(index)
{
TMmoves.push($(this).children(":first").find('a').eq(0).html());
});
$('tr').each(function(index)
{
var moveName = $(this).children(":first").find('a').eq(0).html();
moveName = $.trim(moveName);
switch($(this).attr('id'))
{
case 'moves:level-up':
isLevelupMove = true;
break;
case 'moves:egg':
isLevelupMove = false;
break;
case 'moves:tutor':
isTutorMove = true;
case 'moves:machine':
isTM = true;
}
if(isLevelupMove || isTutorMove)
{
var babyMoveCell = $(this).find('td').eq(0);
babyMoveText = $.trim(babyMoveCell.html());
secondEvoCell = babyMoveCell.next();
secondEvoText = $.trim(secondEvoCell.html());
finalEvo1Cell = secondEvoCell.next();
finalEvo1Text = $.trim(finalEvo1Cell.html());
finalEvo2Cell = finalEvo1Cell.next();
finalEvo2Text = $.trim(finalEvo2Cell.html());
//This checks if evolutions have checkmarks
if(babyMoveText.length > 0)
{
if(hasSecondEvo && secondEvoText.length == 0 || hasFinalEvo1 && finalEvo1Text.length == 0 ||
hasFinalEvo2 && finalEvo2Text.length == 0)
{
//See if the move is a TM before proceeding
var tm = tmCheck(moveName);
if(!tm)
{
if(secondEvoText.length > 0)
{
babyMoveCell.css("color", evoColor);
secondEvoCell.css("color", evoColor);
babyMoveCell.prev().find('a').eq(0).css("color", evoColor); //highlights move name
}
else
{
babyMoveCell.css("color", prevoColor);
babyMoveCell.prev().find('a').eq(0).css("color", prevoColor);
}
}
}
}
else if(secondEvoText.length > 0)
{
if(hasFinalEvo1 && finalEvo1Text.length == 0 || hasFinalEvo2 && finalEvo2Text.length == 0)
{
var tm = tmCheck(moveName);
if(!tm)
{
secondEvoCell.css("color", evoColor);
babyMoveCell.prev().find('a').eq(0).css("color", evoColor);
}
}
}
}
});
function tmCheck(input)
{
var isTM = false;
//Iterate through TMmoves array to see if the input matches any entries
for(var i = 0; i < TMmoves.length; i++)
{
if(input == TMmoves[i])
{
isTM = true;
break;
}
}
if(isTM == true)
return true;
else
return false;
}
//alert("evoColor: " + localStorage.getItem('evoColor') + ". prevoColor: " + localStorage.getItem('prevoColor'))
}//end main()
// load jQuery and execute the main function
addJQuery(main);
This is the userscript I'm trying to implement this for. If anyone has any suggestions or ideas about why I'm getting the error, I'd love to hear them!
This does not work because, if you look carefully at what addJQuery does, you'll realize that it injects the code of the function you pass it into a script element that gets appended to the end of the body element.
This means that you're now working in the same space as the scripts the website has, so all GM_* are not going to be available. What you can do is to move some of the code which require those functions to outside the main function, but remember that the Greasemonkey sandbox means that code running inside the main function cannot communicate with code outside it directly. You can have indirect communication, through for example watching DOM manipulation, or even unsafeWindow, but looking at your code it does not appear to be easily separateable.
This approach will not work because addJQuery() is not transferring workspace objects to the page's scope, it's essentially recreating your code from the source.
That means that the GM_ functions are not usable because there is no link between the sandbox and the copy of the code that addJQuery() made.
If your script needs GM_ functions, then just use straight GM code with the // #require directive for things like jQuery. Your only option for Chrome is Tampermonkey.
In both cases, addJQuery()-like tricks are not needed.