JQueryUI autocomplete search with Django not working - ajax

I am working on a project with Django, for a restaurant management system. I wanted to use an autocomplete feature to take orders at the table.
As far as I understand JQueryUI function autocomplete() is what I need.
However I cannot seem to get it to work.
Following is my my HTML code for the page. It works in such a way that once the number of people in the party is inserted the same number of form input fiels is inserted in the table by a Javascrip script.
addOrder.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">
<script type="text/javascript" src={% static "js/jquery-3.3.1.min.js" %}></script>
<script src={% static "js/jquery-ui.min.js" %}></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css">
<script type="text/javascript" src={% static "js/createOrderIn.js" %}> </script>
<script type="text/javascript" src={% static "js/autocompleteDrink.js" %}></script>
<script type="text/javascript" src={% static "js/autocompleteMenu.js" %}></script>
<style>
.move {
margin: 30px;
}
</style>
<title>Add Order</title>
</head>
<body>
<div class="move">
<form action="/orders/addOrder" method="post" id="the-form" class="ui-widget">
<label> Party of </label>
<input type="text" id="people">
<input type="submit" class="btn btn-primary" value="Submit order">
</form>
</div>
</body>
</html>
This is the script I use to spawn new form input fields
createOrderIn.js
$(document).ready(function () {
var previous = 0;
var considered = 0;
$("#people").keyup(function ( ) {
var actual = this.value;
if(actual==null){
actual=1;
}
var toAdd = actual-previous;
previous = actual;
if(toAdd > 0){
for(var i=0; i<toAdd; i++){
considered+=1;
var htmlToAdd = $("<div class="+considered+"><input type=\"text\" name=\"menu_"+considered+"\" id=\"menu\"><input type=\"text\" name=\"drink_"+considered+"\" value=\"No drink\" id=\"drink\"><br></div>");
$("#the-form").append(htmlToAdd);
}
}
else{
for(var j=0; j<(-1*toAdd); j++) {
if (considered > 0) {
$("."+considered).remove();
considered -= 1;
}
}
}
});
});
The following are the relative Python/Django files
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.ordersIndex, name = "index"),
path('changeStatus/<int:pk>', views.changeStatus, name="changeStatus"),
path('addOrder', views.addOrder, name="addOrder"),
path('addOrderRender', views.addOrderRender, name="addOrderRender"),
path('getDrinks', views.getDrinks, name="getDrinks"),
path('getMenus', views.getMenus, name="getMenu"),
]
views.py (only function getMenus())
def getMenus(request):
print("I am called")
if request.is_ajax():
q = request.GET.get('term', '')
menus = Menu.objects.filter(name__contains=q)
results=[]
for menu in menus:
menu_json = {}
menu_json['name'] = menu.name
menu_json['n_courses'] = menu.number_of_courses
menu_json['price'] = menu.price
results.append(menu_json)
data = json.dump(results)
else:
data = 'fail'
mimetype = 'application/json'
return HttpResponse(data, mimetype)
And lastly this is the function that is supposed to use JQueryUI to make the ajax call and retrieve the possible menu's
autocompleteMenu.js
$(function() {
$("#menu").autocomplete({
source: "/orders/getMenus/",
});
});
As you can probably see from the getMenus() function in views.py I also print a check line ("I am called"), which sure enough does not get printed on console. Also even by switching the autocomplete() source parameter to a local array there is no result.
I do feel like I am doing some very naive mistake but I really cannot seem to figure it out (I am also pretty new with JQuery).
I think the error should be in the provided files, but I'll be happy to post edits in just in case
Thank you in advance!

I realized that the problem was due to the fact that I had to bind autocomplete to the id of the newly created id's (which I changed to classes). Also the JSON data must have a lable field, (and I had to use json.dumps(), not json.dump() :p).
The followings did the trick:
createOrderIn.js
$(document).ready(function () {
var previous = 0;
var considered = 0;
$("#people").keyup(function ( ) {
var actual = this.value;
if(actual==null){
actual=1;
}
var toAdd = actual-previous;
previous = actual;
if(toAdd > 0){
for(var i=0; i<toAdd; i++){
considered+=1;
var htmlToAdd = $("<div class="+considered+"><input type=\"text\" name=\"menu_"+considered+"\" class=\"menu\"><input type=\"text\" name=\"drink_"+considered+"\" value=\"No drink\" class=\"drink\"><br></div>");
$("#the-form").append(htmlToAdd);
$('#the-form').find('input[class=menu]:last').autocomplete({
source: "/orders/getMenus"
});
$('#the-form').find('input[class=drink]:last').autocomplete({
source: "/orders/getDrinks"
});
}
}
else{
for(var j=0; j<(-1*toAdd); j++) {
if (considered > 0) {
$("."+considered).remove();
considered -= 1;
}
}
}
});
});
views.py
def getDrinks(request):
if request.is_ajax():
q = request.GET.get('term', '')
drinks = Drink.objects.filter(name__contains=q)
results=[]
for drink in drinks:
drink_json = {}
drink_json['label'] = drink.name
results.append(drink_json)
data = json.dumps(results)
else:
data = 'fail'
mimetype = 'application/json'
return HttpResponse(data, mimetype)
def getMenus(request):
if request.is_ajax():
q = request.GET.get('term', '')
menus = Menu.objects.filter(name__contains=q)
results=[]
for menu in menus:
menu_json = {}
menu_json['label'] = menu.name
menu_json['id'] = menu.number_of_courses
results.append(menu_json)
data = json.dumps(results)
else:
data = 'fail'
mimetype = 'application/json'
return HttpResponse(data, mimetype)

Related

greasemonkey start refresh function on new tab

I have an old greasemonkey script that used to start refreshing pages on new tab:
// ==UserScript==
// #name script
// #namespace http://localhost
// #description Monitor the location page and catch the egg you want.
// #include http://192.168.10.1/index/*
// #version 1
// #grant none
// ==/UserScript==
var container = document.getElementsByClassName("A");
for (var l = 0; l < container.length; l++) {
container[l].setAttribute('id', 'A');
var A = document.getElementById("A");
var divs = A.getElementsByTagName("div");
for (var i = 0; i < divs.length; i++) {
if ((divs[i].innerHTML.indexOf("failure") != -1) || (divs[i].innerHTML.indexOf("error") != -1)) {
var div = divs[i];
var link = divs[i].innerHTML.href;
for (var b = 0; b < div.childNodes.length; b++) {
var test = div.childNodes[0].href;
//window.location.href = test;
open_in_new_tab(test);
}
}
}
}
setTimeout(function () { window.location.href = window.location.href }, 800);
function open_in_new_tab(url )
{
var win=window.open(url, '_blank');
win.focus();
}
I cant get it to work anymore, I assume that since firefox 57+ some features have changed,
Is it possible to fix/debug this, so that it'll work again?
the relevant html im trying to run this on:
<!DOCTYPE html>
<html>
<head><title></title>
<link rel="mask-icon" href="//s.192.168.10.1/mask-icon.svg" color="#990e0e">
<link type="text/css" rel="stylesheet" href="//s.192.168.10.1/cache/css/e/etsmpm.css" data-modules="1k">
<link type="text/css" rel="stylesheet" href="//s.192.168.10.1/cache/css/c/cze0ax.css" data-modules="3q">
<link type="text/css" rel="stylesheet" href="//s.192.168.10.1/cache/css/1/1vbpas.css" data-modules="1c,1e,1,3h,3g,3n,3o,3p">
</head><body class="_3q_7">
<div class="_3p_0">
<div class="_3o_6">
<h1 class="_3o_1">
<a href="/?r=1">
<img src="//s.192.168.10.1/cache/images/b/bvi5yh.png" alt="Apache" width="388" height="120">
</a></h1><div class="_3o_3"> Logged in as Test
<span title="No unread notifications" class="_3g_3" id="95f64d6ba8"><i class="_3h_0 _3h_4"></i></span>
787<i class="_3h_0 _3h_b"></i>
<span title="Night:" class="_3g_3 _3h_0 _3h_2" id="c1f1299e22"></span> 3:07 am EST
Log out
</div><div class="_3o_9">
Route
Account
Items
Trading
Help
Forum
</div></div>
<div class="_3p_6"></div>
<div class="_3p_7">
<div id="middle">
<h1>Index2</h1>
<ul class="_1k_0"><li>
index5</li>
<li>index1</li>
<li style="font-weight:bold">
index2</li><li>index3</li><li>index4</li><li>index6</li></ul><section>
<div class="A" id="44c39a0cc4"><div><a aria-labeledby="ef21da66ab" href="/get/22eKE"><img src="//s.192.168.10.1/cache/images/8/8itcaf.gif" alt="A" width="26" height="28"></a><br>
<span id="ef21da66ab">valid deascription</span></div><div><a aria-labeledby="1d460c3daf" href="/get/tg9ZF">
<img src="//s.192.168.10.1/cache/images/8/8itcaf.gif" alt="A" width="26" height="28"></a><br>
<span id="1d460c3daf">valid description</span></div><div><a aria-labeledby="1758a88110" href="/get/1qRTn">
<img src="//s.192.168.10.1/cache/images/8/8itcaf.gif" alt="A" width="26" height="28"></a><br>
<span id="1758a88110">error</span></div></div><div class="online">Users viewing this page: 1</div>
</section>
<noscript><a href="https://secure.fastclick.net/w/click.here?sid=68085&m=1&c=1" target="_blank">
<img src="https://secure.fastclick.net/w/get.media?sid=68085&m=1&tp=5&d=s&c=1&vcm_acv=1.4" style="width:728px;height:90px"></a></noscript>
</ins></div><div class="_3p_5">
</div></div></div><div class="_3p_8"></div>
</div><script>window.onerror=function(b,c,d,e,a){navigator.sendBeacon("/el",JSON.stringify([b,c,d,e,a&&a.stack]))};window.onbeforeunload=function(){delete window.onerror};(function(i,s,o,g,r,a,m){i["GoogleAnalyticsObject"]=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,"script","//www.google-analytics.com/analytics.js","ga");ga("create","UA-2864033-4","auto");ga("set","dimension1","new");ga("set","userId",89632);ga("send","pageview");!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version="2.0";n.queue=[];t=b.createElement(e);t.async=!0;t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,document,"script","https://connect.facebook.net/en_US/fbevents.js");fbq("init","1405173446393356");fbq("track","PageView");</script><noscript><img height="1" width="1" style="display:none" src="https://www.facebook.com/tr?id=1405173446393356&ev=PageView&noscript=1"></noscript><script src="//s.192.168.10.1/cache/js/c/c7yxzl.js" crossorigin="anonymous" defer></script><script>window.addEventListener('DOMContentLoaded',function(){global=window;require.config({"enforceDefine":true,"waitSeconds":60,"paths":{"1mh":"\/\/s.192.168.10.1\/cache\/js\/9\/9xrboc","2":"\/\/s.192.168.10.1\/cache\/js\/2\/2mcg3g","1cc":"\/\/s.192.168.10.1\/cache\/js\/7\/7y8rpz","1gi":"\/\/s.192.168.10.1\/cache\/js\/a\/a1ys2f","1gn":"\/\/s.192.168.10.1\/cache\/js\/8\/8zhrpq","b":"\/\/s.192.168.10.1\/cache\/js\/a\/asqoew"},"bundles":[]});require(["1mh"],function(_){_.i(document.getElementById('44c39a0cc4'))});require(["1cc"],function(_){_.init()});require(["1gi"],function(_){_.bindToElement(document.getElementById('95f64d6ba8'),"auto")});require(["1gi"],function(_){_.bindToElement(document.getElementById('c1f1299e22'),"auto")});require(["b"],function(_){_.init(document.getElementById('75079eec42'))});})</script></body></html>
when i tried running it vie firefox console it did find the text and open the link in new tab
i just cant get it to refresh and repeat the process with greasemonkey
There are issues with the script post in your post.
What is stuff as it would break the code?
What is the use of open_in_new_tab() as it is not used?
800 means 800 milliseconds. It is impractical to reload a page every 0.8 of a second as it would often take longer to load a page.
Here is a simple example...
// ==UserScript==
// #name script
// #namespace http://localhost
// #description Monitor the location page and catch the egg you want.
// #match http://192.168.10.1/index/*
// #version 1
// #grant none
// ==/UserScript==
setTimeout(function() { location.reload(); }, 5000);
Please note that some pages can interfere with reload() for example with unload event.
Update on Comment
Here is an example userscript ...
// ==UserScript==
// #name script
// #namespace http://localhost
// #description Monitor the location page and catch the egg you want.
// #include http://192.168.10.1/index/*
// #version 1
// #grant none
// ==/UserScript==
setTimeout(function() { location.reload(); }, 2000); // relaod after 2 seconds
document.querySelectorAll('.A div').forEach(item => { // get all div in class A
if(/failure|error/.test(item.textContent)) { // test div content
const a = item.querySelector('a'); // get link in div
a && openInTab(a.href); // if found, open in new tab
}
}):
function openInTab(url) {
const win = window.open(url, '_blank');
win.focus();
}

XML data pasing

Hi I am trying to display data from XML file to unordered list. Any help would be great. I do have an XML file books data wherein trying to print or display the books author etc.
<!DOCTYPE html>
<html>
<style>
</style>
<script>
function loadXMLDoc() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
report(this);
}
};
xmlhttp.open("GET", "cd_catalog.xml", true);
xmlhttp.send();
}
function report(xml){
var i;
var xmlDoc=xmlhttp.responseXML;
var table = "";
var x = xmlDoc.getElementByTagName("CD");
for(i=0; i<x.length; i++){
table+="<li>" + x[i].getElementByTagName("ARTIST")[0].childNodes[0].nodeValue +
"</li>";
}
document.getElementById("demo").innerHTML = table;
}
</script>
<body>
<ul id="demo"></ul>
<button type="submit" onclick="loadDoc()">RUUUUNNNNN</button>
</body>
</html>

Paymill: 3D-Secure bug with at least one bank?

I make payment with Paymill API using 3D secure:
paymill.createToken(params, paymillResponseHandler, tdsInit, tdsCleanup);
this part from documentation complitely don't work:
var tdsInit = function(iframeUrl, cancelFn) {
var body = document.body || document.getElementsByTagName('body')[0];
var iframe = document.createElement('iframe');
iframe.id = 'tdsIframe';
iframe.src = iframeUrl;
iframe.width = 600;
iframe.height = 500;
iframe.style.zIndex = 0xffffffff;
iframe.style.background = '#fff';
iframe.style.position = 'absolute';
body.insertBefore(iframe, body.firstChild);
};
So i do this way:
function tdsInit(iframeUrl, cancelFn) {
var body = document.body;
var div3D = document.createElement("div");
div3D.id = "div3Dsecure";
body.insertBefore(div3D, body.firstChild);
var pareq = decodeURIComponent(iframeUrl.params.PaReq.replace(/\+/g, " "));
var termurl = decodeURIComponent(iframeUrl.params.TermUrl.replace(/\+/g, " "));
div3D.innerHTML='.$dot.'<form id="3Dsecureform" action="'.$dot.'+iframeUrl.url+'.$dot.'" method="POST"><textarea name="PaReq" style="display:none">'.$dot.'+pareq+'.$dot.'</textarea><input type="hidden" name="TermUrl" value='.$dot.'+termurl+'.$dot.'><input type="hidden" name="MD" value='.$dot.'+iframeUrl.params.MD+'.$dot.'></form>'.$dot.';
var iframe = document.createElement("iframe");
iframe.id = "tdsIframe";
iframe.src = "";
iframe.width = 600;
iframe.height = 500;
iframe.style.zIndex = 0xffffffff;
iframe.style.background = "#fff";
iframe.style.position = "absolute";
iframe.scrolling = "no";
body.insertBefore(iframe, body.firstChild);
document.forms[0].target = "tdsIframe";
document.forms[0].submit();
};
Payments go ok, but when client do payment using card from Sberbank we have problem :
iframe instead of showing 3D Secure page from ACS only make a response about successfully auth this payment.
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Return to Merchant's site</title>
<SCRIPT>
function onLoadHandler() {
document["PAResForm"].submit();
}
</SCRIPT>
</head>
<body onLoad="onLoadHandler();">
<BR>
<BR>Processing...
<FORM NAME="PAResForm" METHOD="post" ACTION="https://ctpe.net/payment/threedsecure?ndcid=8BE948ADB647AF64A9C2640B81DC4B82.lon-vm-fe05&jsessionid=.lon-vm-ps02">
<INPUT NAME="PaRes" TYPE="hidden" VALUE="eJxVkLFuAjEMhl/Fyt7kOAnRwRcGKBtT6YyinI+LlMSVExCP30OEVpW82L/9/bZxe08RbiQlcB7USncKKHseQ74M6ut0eHtXW4unWYj2n+SvQhaPVIq7EIRxUPcprc+bc69XXdd3G2XxQ4TFYmPaBal7NK8U6SHveCS7RvOXPOuNbA8syVXgCTgTsEBiIaBIiXItEJbINxfDCM57lse2UBnqTFC+yYcpeFcXO90sXtyny56qC9EeSfzsctVXia2vKWjaEeZ30Px7wQ9uC2z4"><INPUT NAME="MD" TYPE="hidden" VALUE="8a8394823cd8c78d013cf365e77a3ac5">
</FORM>
</body>
</html>
First I think that there was some mistakes in Sberbank, but client make another payment using another PSP and have 3D secure window from Sberbank :
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<SCRIPT LANGUAGE="JavaScript" SRC="/sberbank/common/global.js"></SCRIPT>
<LINK href="/sberbank/common/va_style.css" rel=STYLESHEET type="text/css">
<title>Verified by VISA - Пароль безопасности</title>
<SCRIPT type="text/javascript">
strBeforeUnload = "Ваша транзакция не завершена!\
Для продолжения, нажмите кнопку 'Отмена' и введите пароль на странице проверки безопасности.";
<!-- page for OTP_SMS -->
var PAMs = new Array();
PAMs[0] = new Array("0","None");
I cannot understand where I do a mistake. Maybe anyone can help me ?
Im sorry but there seems to be an outdated code example in the documentation. Please have a look at the following example for the tdsInit() callback (this is a simplified version of the Bridge.js default implementation of this in order to illustrate the process):
var tdsInit = function tdsInit(redirect, cancelCallback) {
var url = redirect.url, params = redirect.params;
var body = document.body || document.getElementsByTagName('body')[0];
var iframe = document.createElement('iframe');
body.insertBefore(iframe, body.firstChild);
var iframeDoc = iframe.contentWindow || iframe.contentDocument;
if (iframeDoc.document) iframeDoc = iframeDoc.document;
var form = iframeDoc.createElement('form');
form.method = 'post';
form.action = url;
for (var k in params) {
var input = iframeDoc.createElement('input');
input.type = 'hidden';
input.name = k;
input.value = decodeURIComponent(params[k]);
form.appendChild(input);
}
if (iframeDoc.body) iframeDoc.body.appendChild(form);
else iframeDoc.appendChild(form);
form.submit();
};
Note however that tdsInit and tdsEnd are both optional parameters. You only need these if you want to customize the look&feel of the iframe.

The javascript function doesn't work when I try to Populate <g:select> using Ajax in Grails?

I have two SELECT box in my GSP page.And I want to change the values of one SELECT box depends on another SELECT box Onchange on the same page without doing a refresh.
Create.gsp
<%# page contentType="text/html;charset=ISO-8859-1" %>
<html>
<g:javascript library="jQuery"/>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
<meta name="layout" content="main"/>
<title>Insert title here</title>
</head>
<body>
<g:form action="" class="inputform">
<div class="body">
<div id="cntrls" style="height:550px;width: 600px;border: 1px solid #cccccc;float: left;position: relative;">
<table>
<tr>
<td>Layout or Controls :</td>
<td><g:select name="layout" id="layout" from="['Layout Component','Control']" noSelection="['0':'----Select----']" onchange="${remoteFunction(controller:'FormCreator', action:'populateControls', onComplete:'cntrl_type(e)',params:'\'filter=\' + escape(this.value)' )}"/></td>
</tr>
<tr>
<td>Control Type :</td>
<td><g:select name="cntrl_type" id="cntrl_type" from="" noSelection="['0':'----Select----']" value="${formCreator.cntrl_type }"/></td>
</tr>
</table>
</div>
</div>
</g:form>
</body>
</html>
<g:javascript>
function cntrl_type(e) {
var cntrls = eval("(" + e.responseText + ")")
if (cntrls) {
var rselect = document.getElementById("cntrl_type")
while (l > 0) { l-- rselect.remove(l)
}
// Rebuild the select
for (var i=0; i < cntrls.length; i++) {
var cntr = cntrls[i]
var opt = document.createElement("option");
opt.text = cntr.name
opt.value = cntr.name
try {
rselect.add(opt, null)
}
catch(ex) {
rselect.add(opt) // IE only
}
}
}
}
// This is called when the page loads to initialize city
var zselect = document.getElementById("layout")
var zopt = zselect.options[zselect.selectedIndex]
${remoteFunction(controller:"FormCreator", action:"populateControls", params:"'filter=' + zopt.value", onComplete:"cntrl_type(e)")}
</g:javascript>
Following handler for retrieving the list.
package autogeneration
import grails.converters.JSON
class FormCreatorController {
def populateControls={
def list
if(params.filter=="Layout Component"){
list=['Div']
}else if(params.filter=="Control"){
list=['Text Type','Combo Box','Text Area','Submit','Label']
}
render list as JSON
}
The populateControls function works when I change the value of first select box.But the javascript doesn't work.
While I believe the way you are going about this is very backwards. One of your issues may be that you are using cntr.name, while you aren't passing name down. It's just an array of strings. Try just cntr instead of cntr.name?
cntrl_type(e) {
var cntrls = eval("(" + e.responseText + ")")
for (var i=0; i < cntrls.length; i++) {
var cntr = cntrls[i]
opt.text = cntr.name
Also, if you are using JQuery its "data", not "e". You don't need the eval either. Also change it so it calls the function onSuccess instead of onComplete.
cntrl_type(e) {
var cntrls = eval("(" + e.responseText + ")")
Also, this is lazy.
def list
Do this instead:
List<String> list = []

Finding the distance between 2 points using Google Maps API

I am trying to find the distance between 2 points, one being from user input and the other an address from my database. I have put together the code below, which seems to work (I have test variables in place so no database pulls are being made for testing), however I have hit a wall; I cannot figure out why I need to click the button twice for the output to show?
Any help is much appreciated
CODE BELOW:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps JavaScript API Example: Extraction of Geocoding Data</title>
<script src="http://maps.google.com/maps?file=api&v=2&key=ABQIAAAA7j_Q-rshuWkc8HyFI4V2HxQYPm-xtd00hTQOC0OXpAMO40FHAxT29dNBGfxqMPq5zwdeiDSHEPL89A" type="text/javascript"></script>
<!-- According to the Google Maps API Terms of Service you are required display a Google map when using the Google Maps API. see: http://code.google.com/apis/maps/terms.html -->
<script type="text/javascript">
//var globalAddr = new Array();
var globalName;
var xmlhttp;
var geocoder, location1, location2;
var distanceVal;
function initialize() {
geocoder = new GClientGeocoder();
}
function showLocation() {
geocoder.getLocations(document.getElementById("address1").value, function (response) {
if (!response || response.Status.code != 200)
{
alert("Sorry, we were unable to geocode the first address");
}
else
{
location1 = {lat: response.Placemark[0].Point.coordinates[1], lon: response.Placemark[0].Point.coordinates[0], address: response.Placemark[0].address};
geocoder.getLocations(document.getElementById("address2").value, function (response) {
if (!response || response.Status.code != 200)
{
alert("Sorry, we were unable to geocode the second address");
}
else
{
location2 = {lat: response.Placemark[0].Point.coordinates[1], lon: response.Placemark[0].Point.coordinates[0], address: response.Placemark[0].address};
calculateDistance();
}
});
}
});
}
function calculateDistance()
{
var glatlng1 = new GLatLng(location1.lat, location1.lon);
var glatlng2 = new GLatLng(location2.lat, location2.lon);
var miledistance = glatlng1.distanceFrom(glatlng2, 3959).toFixed(1);
var kmdistance = (miledistance * 1.609344).toFixed(1);
distanceVal = miledistance;
}
function loadXMLDoc(url,cfunc)
{
if (window.XMLHttpRequest)
{// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
}
else
{// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=cfunc;
xmlhttp.open("GET",url,true);
xmlhttp.send();
}
function getData(str)
{
loadXMLDoc("getData.php?address="+str,function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
var x = xmlhttp.responseText;
var dnames = x.split("~~~");
var daddr = x.split("^^^");
daddr.shift();
dnames.pop();
var testArray = new Array('85281','18657','90210');
var shortest = 999999;
for(var i = 0; i <= testArray.length-1; i++)
{
document.getElementById("address2").value = testArray[i];//daddr[i];
showLocation();
//i get a blank alert 3 times here the first time, then I get the a value the 2nd time.. makes no sense!
alert(distanceVal);
if (shortest > distanceVal)
{
shortest = distanceVal;
globalName = dnames[i];
}
}
document.getElementById("results").innerHTML = globalName + " " + shortest;
}
})
}
</script>
</head>
<body onload="initialize()">
<form>
<p>
<input type="text" id="address1" name="address1" class="address_input" size="40" />
<input type="hidden" id="address2" name="address2" />
<input type="hidden" id="distance" name="distance" />
<input type="button" name="find" value="Search" onclick="getData(document.getElementsByName('address1')[0].value)"/>
</p>
</form>
<p id="results"></p>
</body>
</html>
When you call showLocation() in your getData() callback, that sets off two geocoder calls and if both are successful calls calculateDistance().
However, both those geocoder calls take time. The first getLocations() sets off a geocode request and lets it continue, to be dealt with in its callback. Within that function, there's another request which is dealt with in its own callback.
While those are waiting for results, the code execution has carried on and reached alert(distanceVal) even though calculateDistance() hasn't been called yet. Consequently distanceVal isn't set yet.
When you click the button again, the global distanceVal will have been populated through all the callback functions, so (even though the second set of geocodes/callbacks have not completed), it will have a value to display. However, if you change the values you are testing, you will find it's displaying the old value which is now incorrect.
Everything which depends on values found in a callback function must be processed within that callback function. If you move the display of data into calculateDistance() everything will be fine, because the data is available to that function.

Resources