Marzhill Musings

... Next>>

Advanced Nitrogen Elements

Published On: 2009-06-16 23:33:58
In my last post I walked you through creating a basic nitrogen element. In this one I'll be covering some of the more advanced topics in nitrogen elements.
  • Event handlers and delegation
  • scripts and dynamic javascript postbacks

Nitrogen Event handlers

Nitrogen event handlers get called for any nitrogen event. A nitrogen event is specified by assigning #event to an actions attribute of a nitrogen element. The event handler in the pages module will get called with the postback of the event. Postbacks are an attribute of the event record and define the event that was fired. To handle the event you create an event function in the target module that matches your postback. For Example: 1 2 % given this event 3 #event{ type=click, postback={click, Id} } 4 % this event function would handle it 5 event({click, ClickedId}) -> 6 io:format("I [~p] was clicked", [ClickedId]) . Erlangs pattern matching makes it especially well suited for this kind of event based programming. The one annoying limitation of this event though is that each page has to handle it individually. You could of course create a dispatching module that handled the event for you but why when nitrogen already did it for you. You can delegate an event to a specific module by setting the delegate attribute to the atom identifying that module. 1 2 % delgated event 3 #event{ type=click, postback={click, Id}, delegate=my_module } You can delgate to any module you want. I use the general rule of thumb that if the event affects other elements on the page then the page module should probably handle it. If, however, the event doesn't affect other elements on the page then the element's module can handle it.

Scripts and Dynamic Postback

Now lets get make it a little more interesting. Imagine a scenario where we want to interact with some javascript on a page and dynamically generate data to send back to nitrogen. As an example lets create a silly element that grabs the mouse coordinates of a click on the element and sends that back to nitrogen. A first attempt might look something like so: 1 2 -record(silly, {?ELEMENT_BASE(element_silly)}). And the module is likewise simple: 1 2 -module(element_silly). 3 -compile(export_all). 4 -include("elements.hrl"). 5 -include_lib("nitrogen/include/wf.inc"). 6 render(ControlId, R) -> 7 Id = wf:temp_id(), 8 %% wait!! where do we get the loc from?! 9 ClickEvent = #event{type=click, postback={click, Loc}} 10 Panel = #panel{id=Id, style="width:'100px' height='100px'", 11 actions=ClickEvent}, element_panel:render(Panel). 12 13 event({click, Loc}) -> 14 wf:update(body, wf:f("you clicked at point: ~s", Loc)). Well of course you spot the problem here. Since the click happens client side we don't know what to put in the Loc variable for the postback. A typical postback won't work because the data will be generated in the client and not the Nitrogen server. So how could we get the value of the coordinates sent back? The javascript to grab the coordinates with jquery looks like this: 1 2 var coord = obj('me').pageX + obj('me').pageY; To plug that in to the click event is pretty easy since action fields in an event can hold other events or javascript or a list combining both: 1 2 Script = "var coord = obj('me').pageX + obj('me').pageY;", 3 ClickEvent = #event{type=click, postback={click, Loc}, actions=Script} Now we've managed to capture the coordinates of the mouse click, but we still haven't sent it back to the server. This javascript needs a little help. What we need is a drop box. Lets enhance our element with a few helpers: 1 2 -module(element_silly). 3 -compile(export_all). 4 -include("elements.hrl"). 5 -include_lib("nitrogen/include/wf.inc"). 6 render(ControlId, R) -> 7 Id = wf:temp_id(), 8 DropBoxId = wf:temp_id(), 9 MsgId = wf:temp_id(), 10 Script = wf:f("var coord = obj('me').pageX + obj('me').pageY; $('~s').value = coord;", 11 [DropBoxId]), 12 ClickEvent = #event{type=click, postback={click, Id, MsgId}, 13 actions=Script}, 14 Panel = #panel{id=Id, style="width:'100px'; height='100px'", 15 actions=ClickEvent, body=[#hidden{id=DropBoxId}, 16 #panel{id=MsgId}]}, 17 element_panel:render(Panel). 18 19 event({click, Id, Msg}) -> 20 Loc = hd(wf:q(Id)), 21 wf:update(Msg, wf:f("you clicked at point: ~s", Loc)). Ahhh there we go. Now our element when clicked will:
  1. use javascript to grab the coordinates of the mouse click
  2. use javascript to store those coordinates in the hidden element
  3. use a postback to send the click event back to a nitrogen event handler with the id of the hidden element where it stored the coordinates.
We have managed to grab dynamically generated data from the client side and drop it somehwere that nitrogen can retrieve it. In the process we have used an event handler, custom javascript, and dynamic javascript postbacks. Edit: Corrected typo - June 16, 2009 at 11:40 pm

Tags:

Oh my goodness he just updated his blog!!

Published On: 2009-04-05 20:29:18
Hi there! Honestly I'm not dead, I've just been all wrapped up in this whole life thing. You know... that whole, "Holy cow!!!! I work at Google now!! When did this happen exactly?" thing, where you're incredibly busy just trying to get up to speed on it all and catch your breath? Well anyway, I feel bad since I've been silent for so long, so here goes. An update from the trenches of the Life of Jeremy Wall. Since I wrote last I have
  • been "acquired by Google"
  • had my first "truly successful" Open Source Project
  • and actually got my Student Loan back under control.
I'm actually absurdly proud of that last one... And still a bit bewildered by the first one. So lets go down the list one at a time shall we?

"The Acquisition"

The company I worked for DoubleClick Performics got bought by Google. Who would have thought it? Somehow I landed an actual job at Google doing what I love. Crafting Code. I have to say, I think this has to have been a "God thing". I can't see any other way to explain it. Google of course is an awesome place to work. Free food, Smart people, Gameroom (strangely I almost never make into there though), Snacks, and really interesting technology to play with. I'm learning a lot about working in Highly Available, Highly Scalable environments. I keep waiting to wake up and find out it was all a dream.

"The Open Source Project"

My last post was about etap, my learn erlang project. I had no idea that the project would get the attention of Nick, a coder with EA, who was looking for a TAP compliant testing framework for their erlang code. He contacted me and asked if he could take over management of the code. I said" sure", as long as I still got to contribute when I had time. Before I knew it EA was using etap internally and I had what I consider to be my first truly successful open source project. etap has now gotten used commercially, traveled to conferences, and is soon to be featured in a book. Not bad for a learners project huh?

"The School Loan"

And perhaps most awesome of all I'm making headway on the whole credit repair thing. The school loan is back under control and no longer has a devestating impact on my credit report. This is an accomplishment that makes me really wonder if I'm in some kind of awesome dream or something. Life is really looking up around here. I'll try to get more regular on my posting again as I play with more erlang, think about writing a book, and Oh almost forgot to mention "Joose" the meta-object protocol for javascript. I'll write more about that later.

Tags:

Oh my goodness he just updated his blog!!

Published On: 2009-04-05 20:29:18
Hi there! Honestly I'm not dead, I've just been all wrapped up in this whole life thing. You know... that whole, "Holy cow!!!! I work at Google now!! When did this happen exactly?" thing, where you're incredibly busy just trying to get up to speed on it all and catch your breath? Well anyway, I feel bad since I've been silent for so long, so here goes. An update from the trenches of the Life of Jeremy Wall. Since I wrote last I have
  • been "acquired by Google"
  • had my first "truly successful" Open Source Project
  • and actually got my Student Loan back under control.
I'm actually absurdly proud of that last one... And still a bit bewildered by the first one. So lets go down the list one at a time shall we?

"The Acquisition"

The company I worked for DoubleClick Performics got bought by Google. Who would have thought it? Somehow I landed an actual job at Google doing what I love. Crafting Code. I have to say, I think this has to have been a "God thing". I can't see any other way to explain it. Google of course is an awesome place to work. Free food, Smart people, Gameroom (strangely I almost never make into there though), Snacks, and really interesting technology to play with. I'm learning a lot about working in Highly Available, Highly Scalable environments. I keep waiting to wake up and find out it was all a dream.

"The Open Source Project"

My last post was about etap, my learn erlang project. I had no idea that the project would get the attention of Nick, a coder with EA, who was looking for a TAP compliant testing framework for their erlang code. He contacted me and asked if he could take over management of the code. I said" sure", as long as I still got to contribute when I had time. Before I knew it EA was using etap internally and I had what I consider to be my first truly successful open source project. etap has now gotten used commercially, traveled to conferences, and is soon to be featured in a book. Not bad for a learners project huh?

"The School Loan"

And perhaps most awesome of all I'm making headway on the whole credit repair thing. The school loan is back under control and no longer has a devestating impact on my credit report. This is an accomplishment that makes me really wonder if I'm in some kind of awesome dream or something. Life is really looking up around here. I'll try to get more regular on my posting again as I play with more erlang, think about writing a book, and Oh almost forgot to mention "Joose" the meta-object protocol for javascript. I'll write more about that later.

Tags:
... Next>>