Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

281 lines (212 sloc) 8.709 kB
<erl>
box(Str) ->
{'div',[{class,"box"}],
{pre,[], yaws_api:htmlize(Str)}}.
tbox(T) ->
box(lists:flatten(io_lib:format("~p",[T]))).
ssi(File) ->
{'div',[{class,"box"}],
{pre,[],
{ssi, File,[],[]}}}.
ss(A, File) ->
{ok, B} = file:read_file(
filename:join([A#arg.docroot, File])),
box(binary_to_list(B)).
out(A) ->
[{ssi, "TAB.inc", "%%",[{"json_intro", "choosen"}]},
{ehtml,
{'div', [{id, "entry"}],
[{h1, [], "AJAX through JSON RPC"},
{p, [],
{i, [],
["Note: this documentation used to refer to the module "
"'yaws_jsonrpc'. This module has been depracated in favor "
"of 'yaws_rpc', which handles both JSON RPC, haXe and SOAP "
"remoting. All references to 'yaws_jsonrpc' on this page "
"were therefore changed to 'yaws_rpc'. For more specific "
"information about SOAP, refer to ",
{a, [{href, "/soap_intro.yaws"}], "the SOAP page."}]}},
{p, [],
["The Yaws Json binding is a way to have Javascript code in the "
"browser evaluate a remote procedure call in the Yaws server."
"JSON itself as described at ",
{a, [{href, "http://www.json.org/"}], "http://www.json.org/ "},
"is basically a simple marshaling format which can be used "
" from a variety of different programming languages, in particular "
" it completely straightforward to implement in Javascript."]},
{p, [],
"The yaws JSON implementation consist of Javascript client and a "
" server side library which must be explicitly invoked by Erlang "
"code in a .yaws page."},
{p,[],
"It is not particularly easy to show and explain an AJAX setup "
"through JSON RPC, but here is an attempt:"
},
{p,[],
"First we have an HTML page which:"},
{ol, [],
[
{li,[],{p,[], "Includes the client side of the JSON library."
" The library is included in the yaws distribution "
" and it is found under \"www/jsolait/jsolait.js\" ."}},
{li,[],{p,[],"Second the HTML code defines the name of a method, "
"i.e. the name of a server side function which shall be "
" called by the client side Javascript code"}},
{li,[],{p,[],"Finally the HTML code defines a FORM which is "
"used to invoke the RPC. This is just a really simple "
"example, really any Javascript code can invoke any RPC in "
"more interesting scenarios than submitting a form"}}]},
{p, [], "The HTML code looks like "},
ss(A,"json_sample.html"),
{p, [], ["This HTML code resides in file ",
{a,[{href, "json_sample.html"}], "json_sample.html"},
" and it is the HTML code that is the AJAX GUI !!!"]},
{p, [], "Following that we need to take a look at the page "
"json_sample.yaws which is the \"serviceURL\" according to "
"the Javascript code. This code defines the function to be "
"called. Remember that the Javascript code defined one method, "
"called \"test1\", this information will be passed to the "
"serviceURL. The code looks like:"},
ss(A, "json_sample.yaws"),
{p,[], "The two important lines on the server side are"},
{ol,[],
[
{li,[],
{pre,[],"yaws_rpc:handler_session(A2, {sample_mod, counter})."}},
{li,[],
{pre,[],"counter([{ip, IP}] = _State, {call, test1, Value} = _Request, Session)"}}]},
{p,[],
"The first line tells Yaws to forward all JSON-RPC methods to the "
" \"counter\" function in the \"sample_mod\" module. "
"The second line says, "
" basically, - this is the counter function that will be called when "
" the client invokes a method called 'test1'. We would duplicate "
" this line with a different name than 'test1' for each RPC function "
"we wish to implement."},
{p,[],"On the client side we have"},
box("
var methods = [ \"test1\" ];
var jsonrpc = imprt(\"jsonrpc\");
var service = new jsonrpc.ServiceProxy(serviceURL, methods);
"),
{p,[],"Which registers the Yaws page with the JSON-RPC handler and "
"gives it a list of methods that the Yaws page can satisfy. "
"In this case, it is only the method called 'test1'."},
{p, [],
"When we wish to return structured data - we simply let "
"the user defined RPC function return JSON structures such as "},
box(" {struct, [{field1, \"foo\"}, {field2, \"bar\"}]} "),
{p, [], " for a structure and "},
box("{array, [\"foo\", \"bar\"]}"),
{p, [],"for an array. We can nest arrays and structs in each other "},
{p, [],
"Finally, we must stress that this example is extremely simple. "
"In order to build a proper AJAX application in Yaws, a lot of "
"client side work is required, all Yaws provides is the basic "
"mechanism whereby the client side Javascript code, can RPC the "
"web server for data which can be subsequently used to populate "
"the DOM. Also required to build a good AJAX application is "
"good knowledge on how the DOM in the browser works"},
{p, [],
[{b,[],"Update:"},
"The yaws_rpc:handler will now also call: M:F(cookie_expire) which is "
"expected to return a proper Cookie expire string. This makes it possible "
"to setup the Cookie lifetime. If this calback function is non-existant, "
"the default behaviour is to not set a cookie expiration time, i.e it will "
"live for this session only."]},
{h3, [], "One more example "},
{p, [],
["Here is yet another example, stolen from ",
{a,
[{href,"http://blog.tornkvist.org/blog.yaws?id=1179347231289901#"}],
"Tobbes blog"}
]},
{h4, [], "Setup the DOM"},
{p, [], "In the file ''ex1.html'' we create the DOM with a little HTML and add some Javascript that will talk with the Erlang server side."},
box("
<html>
<head>
<script type=\"text/javascript\"
src=\"/jquery-1.2.3.js\"></script>
</head>
<body>
<script language=\"javascript\" type=\"text/javascript\">
function ex1(what) {
$.getJSON(\"/ex1.yaws\",
{'op': \"ex1\", 'what': what},
function(x) {
do_ex1(what, x)
});
}
function do_ex1(what, x) {
jQuery.each(x, doit);
}
function doit() {
$('#'+this.who).html(this.what);
}
</script>
<button onclick=\"ex1('one')\">Update one!</button>
<button onclick=\"ex1('two')\">Update two!</button>
<button onclick=\"ex1('three')\">Update three!</button>
<div id=\"one\">This is one</div>
<div id=\"two\">This is two</div>
<div id=\"three\">This is three</div>
</body>
</html>
"),
{h4, [], "The erlang server side"},
{p, [], "This is the code that needs to be installed and "
"execute on the server side. It nicely illustrates how "
"to return JSON structs to the client. "},
box("
-module(ex1).
-export([out/1]).
out(A) ->
L = yaws_api:parse_query(A),
dispatch(lkup(\"op\", L, false), A, L).
dispatch(\"ex1\", A, L) ->
ex1(A, L).
ex1(_A, L) ->
J = json:encode(array(what(lkup(\"what\", L, false)))),
return_json(J).
what(\"one\") -> one();
what(\"two\") -> one() ++ two();
what(\"three\") -> one() ++ two() ++ three().
array(L) -> {array, L}.
one() -> obj(\"one\").
two() -> obj(\"two\").
three() -> obj(\"three\").
obj(M) ->
obj(M, \"r\").
%%%
%%% How ::= \"r\" | \"a\" , r=replace, a=append
%%%
obj(M, How) ->
C = now2str(),
[{struct,
[{\"who\", M},
{\"how\", How},
{\"what\", C ++\" \"++M++\" content\"}]}].
return_json(Json) ->
{content,
\"application/json; charset=iso-8859-1\",
Json}.
now2str() ->
{A,B,C} = erlang:now(),
i2l(A)++\"-\"++i2l(B)++\"-\"++i2l(C).
i2l(I) when is_integer(I) -> integer_to_list(I);
i2l(L) when is_list(L) -> L.
lkup(Key, List, Def) ->
case lists:keysearch(Key, 1, List) of
{value,{_,Value}} -> Value;
_ -> Def
end.
") ,
{h2, [], "The json library"},
{p, [], "The Yaws JSON library contains 3 simple functions, "
" One to encode and two for decoding. See source code json.erl "
" for detailed instructions on usage "}
]}},
{ssi, "END2",[],[]}
].
</erl>
Jump to Line
Something went wrong with that request. Please try again.