Asynchronous Javascript problem

39 views
Skip to first unread message

Channing Walton

unread,
Jul 29, 2009, 5:27:30 PM7/29/09
to Lift
Hi,
I'm working on an app which has a google map which users can use to
search for locations, and on which I want to place markers.

The asynchronous call is a call to google's geocoder service which
takes a string to search for from an input field, and a callback
function that the position will be passed to:

geocoder.getLatLng(address,showAddress);

function showAddress(point) {
if (!point) {
alert(address + " not found");
} else {
map.setCenter(point, 13);
}
}

So the issue here is that after map.setCenter I want to make an ajax
call to retrieve marker data from the server using the 'point'. I
would like to use lift's javascript abstraction to build this but I'm
struggling to see how to do it given the asynchronous call.

Any ideas?

David Pollak

unread,
Jul 29, 2009, 8:17:47 PM7/29/09
to lif...@googlegroups.com
You can put a little JavaScript on the page which contains a function that you can call... for example:

define a JsonHandler:

object PointHandler extends JsonHandler {
  def apply(in: Any): JsCmd = in match {
    case JsonCmd("setPoint", _, yourData, _) =>
      /// do something with yourData
      Noop
  }
}

Now, build a stable function to send to the browser:

Script(Function("sendPointToServer", "point", PointHandler.call("setPoint", JsVal("point"))))


You'll have a JavaScript function, sendPointToServer that you cal with the point and the rest is automatic.

Thanks,

David
--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp

Channing Walton

unread,
Jul 30, 2009, 2:11:18 AM7/30/09
to Lift
Excellent, thanks David.

On Jul 30, 1:17 am, David Pollak <feeder.of.the.be...@gmail.com>
wrote:
> You can put a little JavaScript on the page which contains a function that
> you can call... for example:
>
> define a JsonHandler:
>
> object PointHandler extends JsonHandler {
>   def apply(in: Any): JsCmd = in match {
>     case JsonCmd("setPoint", _, yourData, _) =>
>       /// do something with yourData
>       Noop
>   }
>
> }
>
> Now, build a stable function to send to the browser:
>
> Script(Function("sendPointToServer", "point", PointHandler.call("setPoint",
> JsVal("point"))))
>
> You'll have a JavaScript function, sendPointToServer that you cal with the
> point and the rest is automatic.
>
> Thanks,
>
> David
>
> On Wed, Jul 29, 2009 at 2:27 PM, Channing Walton <channingwal...@mac.com>wrote:
>
>
>
>
>
>
>
> > Hi,
> > I'm working on an app which has a google map which users can use to
> > search for locations, and on which I want to place markers.
>
> > The asynchronous call is a call to google's geocoder service which
> > takes a string to search for from an input field, and a callback
> > function that the position will be passed to:
>
> >    geocoder.getLatLng(address,showAddress);
>
> >  function showAddress(point) {
> >  if (!point) {
> >          alert(address + " not found");
> >    } else {
> >      map.setCenter(point, 13);
> >    }
> >  }
>
> > So the issue here is that after map.setCenter I want to make an ajax
> > call to retrieve marker data from the server using the 'point'. I
> > would like to use lift's javascript abstraction to build this but I'm
> > struggling to see how to do it given the asynchronous call.
>
> > Any ideas?
>
> --
> Lift, the simply functional web frameworkhttp://liftweb.net
> Beginning Scalahttp://www.apress.com/book/view/1430219890

Channing Walton

unread,
Jul 30, 2009, 4:51:05 PM7/30/09
to Lift
Hi,
I had to replace JsVal("point") with JsVar("point"), but when I run it
up, I get "ReferenceError: Can't find variable: F542198622797IUJ" in
the browser console. The function in the page looks like this:

function sendPointToServer(point) {
F542198622797IUJ({'command': 'setPoint', 'params':point});
}

I guess I am missing something else?

David Pollak

unread,
Jul 30, 2009, 7:13:57 PM7/30/09
to lif...@googlegroups.com

Are you putting the result of:

Script(Function("sendPointToServer", "point", PointHandler.call("setPoint", JsVal("point"))))

Anywhere on your page?
 



Channing Walton

unread,
Jul 31, 2009, 1:55:56 AM7/31/09
to Lift

> Are you putting the result of:
>
> Script(Function("sendPointToServer", "point", PointHandler.call("setPoint",
> JsVal("point"))))
>
> Anywhere on your page?

I believe so, the page has a snippet:

<lift:mapSnippet.mapFunctions/>

which looks like this:

def mapFunctions(xhtml : NodeSeq) : NodeSeq = {
val node = Script(Function("sendPointToServer", List("point"),
PointHandler.call("setPoint", JsVar("point"))))
node ++ <head>{Script(OnLoad(Call("initialize")))}</head>
}

and in the page I see:

David Pollak

unread,
Jul 31, 2009, 1:41:34 PM7/31/09
to lif...@googlegroups.com
On Thu, Jul 30, 2009 at 10:55 PM, Channing Walton <channin...@mac.com> wrote:


> Are you putting the result of:
>
> Script(Function("sendPointToServer", "point", PointHandler.call("setPoint",
> JsVal("point"))))
>
> Anywhere on your page?

I believe so, the page has a snippet:

<lift:mapSnippet.mapFunctions/>

which looks like this:

def mapFunctions(xhtml : NodeSeq) : NodeSeq =  {
   val node = Script(Function("sendPointToServer", List("point"),
PointHandler.call("setPoint", JsVar("point"))))
   node ++ <head>{Script(OnLoad(Call("initialize")))}</head>
 }

Whoops... should be:

Script(Function("sendPointToServer", "point", PointHandler.call("setPoint", JsVal("point"))) & PointHandler.jsCmd)
 

and in the page I see:
> function sendPointToServer(point) {
>    F542198622797IUJ({'command': 'setPoint', 'params':point});
>    }



Channing Walton

unread,
Jul 31, 2009, 4:28:59 PM7/31/09
to Lift
cool thanks, that did it.

Google recommends running a script on unload, their example has: <body
onload="initialize()" onunload="GUnload()">

I couldn't see any Unload function anyway, I guess it would be a
useful thing to add?

Channing Walton

unread,
Aug 1, 2009, 3:50:57 PM8/1/09
to Lift
ok I am getting somewhere. Thanks for your patience, I'll write this
up somewhere in case someone else needs a google map in a liftweb app.

The functions being generated are good:

function sendPointToServer(point) {
F298945645192D4K({'command': 'setPoint', 'params':point});
}

function F298945645192D4K(obj) {lift_ajaxHandler('F298945645192D4K='+
encodeURIComponent(JSON.stringify(obj)), null,null);

But I get a "Can't find variable: JSON" error.

Channing Walton

unread,
Aug 2, 2009, 10:48:33 AM8/2/09
to Lift
On Aug 1, 8:50 pm, Channing Walton <channingwal...@mac.com> wrote:
> But I get a "Can't find variable: JSON" error.

forget that, I was having some kind of safari issue.

But the problem I am having now is a NumberFormatException:

2009-08-02 15:42:58,098 WARN lift:246 - Request for /ajax_request/
F782434648742DNZ/ failed For input string: "51.(.~List(3, 2, 5, 6, 1,
2, 3))"
java.lang.NumberFormatException: For input string: "51.(.~List(3, 2,
5, 6, 1, 2, 3))"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:
1224)
at java.lang.Double.parseDouble(Double.java:510)
at scala.runtime.RichString.toDouble(RichString.scala:216)
at net.liftweb.util.JSONParser$$anonfun$intFrac$2.apply(JSON.scala:
89)
at net.liftweb.util.JSONParser$$anonfun$intFrac$2.apply(JSON.scala:
89)

The string its parsing is: {"command":"setPoint","params":{"mf":
51.3256123,"$a":-0.6379592,"x":-0.6379592,"y":51.3256123}}

The scala json parser seems ok with it though.

David Pollak

unread,
Aug 2, 2009, 1:14:55 PM8/2/09
to lif...@googlegroups.com
Channing,

We don't use the Scala JSON parsing stuff because it does not do well with very long JSON expressions (stack overflow problems).

The parsing defects (which I've fixed and added tests for) are a result of some strong typing that Scala *should* be enforcing and is not (the compiler was not rejecting certain patterns which should never have been allowed.)

Give it an hour and give it a try.

Thanks for hanging with me through these defects.

David

Channing Walton

unread,
Aug 2, 2009, 2:57:47 PM8/2/09
to Lift


On Aug 2, 6:14 pm, David Pollak <feeder.of.the.be...@gmail.com> wrote:
> Give it an hour and give it a try.
>
> Thanks for hanging with me through these defects.

Thanks David, its much appreciated - on a Sunday too!

Channing Walton

unread,
Aug 2, 2009, 3:09:49 PM8/2/09
to Lift
ok just caught up and tried again, this time I get:

2009-08-02 20:07:16,981 WARN lift:246 - Request for /ajax_request/
F1105202520287L3C/ failed For input string: "(-~0)"
java.lang.NumberFormatException: For input string: "(-~0)"
at java.lang.NumberFormatException.forInputString
(NumberFormatException.java:48)
at java.lang.Long.parseLong(Long.java:403)
at java.lang.Long.parseLong(Long.java:461)
at scala.runtime.RichString.toLong(RichString.scala:214)
at net.liftweb.util.JSONParser$$anonfun$anInt$5$$anonfun$apply
$69.apply(JSON.scala:101)
at net.liftweb.util.JSONParser$$anonfun$anInt$5$$anonfun$apply
$69.apply(JSON.scala:101)

I'm not sure where that (-~0) comes from, the input string is

David Pollak

unread,
Aug 2, 2009, 5:01:34 PM8/2/09
to lif...@googlegroups.com
This is very odd because the very data set that you included is part of the tests for the JSON parser.

Please delete ~/.m2/respository and do a clean build and see if it works.

Channing Walton

unread,
Aug 2, 2009, 5:30:11 PM8/2/09
to Lift
yup tried that and am still getting the same error. I presume I
should be using the 1.1-SNAPSHOT?

On Aug 2, 10:01 pm, David Pollak <feeder.of.the.be...@gmail.com>
wrote:
> This is very odd because the very data set that you included is part of the
> tests for the JSON parser.
>
> Please delete ~/.m2/respository and do a clean build and see if it works.
>
> On Sun, Aug 2, 2009 at 12:09 PM, Channing Walton <channingwal...@mac.com>wrote:
>
>
>
>
>
>
>
> > ok just caught up and tried again, this time I get:
>
> > 2009-08-02 20:07:16,981 WARN  lift:246 - Request for /ajax_request/
> > F1105202520287L3C/ failed For input string: "(-~0)"
> > java.lang.NumberFormatException: For input string: "(-~0)"
> >        at java.lang.NumberFormatException.forInputString
> > (NumberFormatException.java:48)
> >        at java.lang.Long.parseLong(Long.java:403)
> >        at java.lang.Long.parseLong(Long.java:461)
> >        at scala.runtime.RichString.toLong(RichString.scala:214)
> >        at net.liftweb.util.JSONParser$$anonfun$anInt$5$$anonfun$apply
> > $69.apply(JSON.scala:101)
> >        at net.liftweb.util.JSONParser$$anonfun$anInt$5$$anonfun$apply
> > $69.apply(JSON.scala:101)
>
> > I'm not sure where that (-~0) comes from, the input string is
> > {"command":"setPoint","params":{"mf":
> > 51.3256123,"$a":-0.6379592,"x":-0.6379592,"y":51.3256123}}
>
> --
> Lift, the simply functional web frameworkhttp://liftweb.net
> Beginning Scalahttp://www.apress.com/book/view/1430219890

Channing Walton

unread,
Aug 2, 2009, 5:35:29 PM8/2/09
to Lift
ah wait, I am not seeing the latest code changes you made in the
snapshot source I just downloaded from the mvn repos. I will endeavour
to figure out why.

On Aug 2, 10:01 pm, David Pollak <feeder.of.the.be...@gmail.com>
wrote:
> This is very odd because the very data set that you included is part of the
> tests for the JSON parser.
>
> Please delete ~/.m2/respository and do a clean build and see if it works.
>
> On Sun, Aug 2, 2009 at 12:09 PM, Channing Walton <channingwal...@mac.com>wrote:
>
>
>
>
>
>
>
> > ok just caught up and tried again, this time I get:
>
> > 2009-08-02 20:07:16,981 WARN  lift:246 - Request for /ajax_request/
> > F1105202520287L3C/ failed For input string: "(-~0)"
> > java.lang.NumberFormatException: For input string: "(-~0)"
> >        at java.lang.NumberFormatException.forInputString
> > (NumberFormatException.java:48)
> >        at java.lang.Long.parseLong(Long.java:403)
> >        at java.lang.Long.parseLong(Long.java:461)
> >        at scala.runtime.RichString.toLong(RichString.scala:214)
> >        at net.liftweb.util.JSONParser$$anonfun$anInt$5$$anonfun$apply
> > $69.apply(JSON.scala:101)
> >        at net.liftweb.util.JSONParser$$anonfun$anInt$5$$anonfun$apply
> > $69.apply(JSON.scala:101)
>
> > I'm not sure where that (-~0) comes from, the input string is
> > {"command":"setPoint","params":{"mf":
> > 51.3256123,"$a":-0.6379592,"x":-0.6379592,"y":51.3256123}}
>
> --
> Lift, the simply functional web frameworkhttp://liftweb.net
> Beginning Scalahttp://www.apress.com/book/view/1430219890

David Pollak

unread,
Aug 2, 2009, 7:02:45 PM8/2/09
to lif...@googlegroups.com
It looks like Hudson had another brain cramp and stopped building on Friday.  I just restarted it.
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890

Channing Walton

unread,
Aug 3, 2009, 3:43:34 AM8/3/09
to Lift
Victory is ours!

Thanks for all the help David.

Channing Walton

unread,
Aug 4, 2009, 4:15:45 AM8/4/09
to Lift
spoke too soon :-(

when I test this on a new browser or flush browser caches, I am
getting a javascript error: Undefined variable: JSON

I am not wrapping my the input field in a json form as described in
the book because when I do the page reloads. Could that be the
problem? In which case how do I prevent the page reloading?

David Pollak

unread,
Aug 4, 2009, 11:38:09 AM8/4/09
to lif...@googlegroups.com
Are you including the /classpath/json.js JavaScript file?

Channing Walton

unread,
Aug 4, 2009, 4:50:33 PM8/4/09
to Lift
doh! I missed that.

Channing Walton

unread,
Aug 4, 2009, 5:48:37 PM8/4/09
to Lift
In Safari 4.0.2, and Opera 9.64 on OS X, I get RangeError: Maximum
call stack size exceeded at line 27 in json.js

But in the latest nightly build of webkit, it works.

I will try on windows asap.

David Pollak

unread,
Aug 4, 2009, 5:51:09 PM8/4/09
to lif...@googlegroups.com
Please put together some simple code that reproduces the problem and I'll make it go away.

Channing Walton

unread,
Aug 4, 2009, 6:33:39 PM8/4/09
to Lift
will do

On Aug 4, 10:51 pm, David Pollak <feeder.of.the.be...@gmail.com>
wrote:
> Please put together some simple code that reproduces the problem and I'll
> make it go away.
>
> On Tue, Aug 4, 2009 at 2:48 PM, Channing Walton <channingwal...@mac.com>wrote:
>
>
>
> > In Safari 4.0.2, and Opera 9.64 on OS X, I get RangeError: Maximum
> > call stack size exceeded at line 27 in json.js
>
> > But in the latest nightly build of webkit, it works.
>
> > I will try on windows asap.
>
> --
> Lift, the simply functional web frameworkhttp://liftweb.net
> Beginning Scalahttp://www.apress.com/book/view/1430219890

Channing Walton

unread,
Aug 5, 2009, 11:01:51 AM8/5/09
to Lift
ok, lots of jscript debugging and I'm pretty sure its this:

JSON.stringify(new GLatLng(0,0))

where GLatLng is a google map object.

the imports needed for this are

<script src="http://maps.google.com/maps?
file=api&amp;v=2.x&amp;key=your-key&amp;sensor=false" type="text/
javascript"></script>
<script type="text/javascript" src="/classpath/jquery.js"
id="jquery"></script>
<script src="/classpath/json.js" type="text/javascript"></script>

there is a key=your-key argument in that first import. don't worry
about that, just make sure you test the page using localhost, not
127.0.0.1, just localhost. The key is not used for file:// and
localhost addresses.

Channing Walton

unread,
Aug 5, 2009, 3:13:57 PM8/5/09
to Lift
actually that example doesn't work in Opera, but does in safari and
firefox. To see the problem in safari I had to modify the script like
this:

var geocoder = new GClientGeocoder();
geocoder.getLatLng("london",doit);

function doit(point) {
var s = JSON.stringify(point);
alert(s)
}

This does work in Firefox though, but my full version doesn't.
Hopefully these examples will help a little. I am beginning to think I
should just pass simple objects to the server via JSON.

David Pollak

unread,
Aug 5, 2009, 3:30:24 PM8/5/09
to lif...@googlegroups.com

In order to debug the problem, I need something that is fully running (e.g., fork http://github.com/dpp/lift_1_1_sample/tree/master and implement something that demonstrates the problem).

The mechanism we are working on is passing the objects to the server via JSON.  JSON.stringify is the JSON serializer and an JavaScript object must be serialized to send to the server.
 


Channing Walton

unread,
Aug 5, 2009, 6:25:11 PM8/5/09
to Lift
ok I've done that: git://github.com/channingwalton/lift_1_1_sample.git

run the app up and go to http://localhost:8080/mapSearch and try the
search. I find stack overflow in Safari 4.0.2, and Opera 9.64. The
query works in Firefox 3.5.2 and Webkit Version 4.0.2 (5530.19,
r46770) (latest nightly) - all OS X

I haven't been able to test on windows yet.

Channing Walton

unread,
Aug 6, 2009, 4:33:11 AM8/6/09
to Lift
I've added a much simpler example too, see simple.html

David Pollak

unread,
Aug 7, 2009, 4:32:39 PM8/7/09
to lif...@googlegroups.com
I reproduced the issue on Opera... then Google banned my IP address for excessive requests... :-(

I'll sign up for a google maps account.


On Thu, Aug 6, 2009 at 1:33 AM, Channing Walton <channin...@mac.com> wrote:

I've added a much simpler example too, see simple.html




Channing Walton

unread,
Aug 8, 2009, 3:55:51 PM8/8/09
to Lift


On Aug 7, 9:32 pm, David Pollak <feeder.of.the.be...@gmail.com> wrote:
> I reproduced the issue on Opera... then Google banned my IP address for
> excessive requests... :-(

they need to move to lift to handle the load ;)
Reply all
Reply to author
Forward
0 new messages