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,[],[]}}}.
out(A) ->
[{ssi, "TAB.inc", "%%",[{"dynamic", "choosen"}]},
{ehtml,
[{'div', [{id, "entry"}],
[
{h1, [],"Generating Dynamic Content"},
{p,[], ["Yaws has very nice support for generating dynamic content on the fly. "
"We use embedded erlang code to generate the content. The Erlang code "
"is separated from the HTML code by ",
{tt, [], "<erl>"},
" and ",
{tt, [], "\</erl>"},
" markers. For example: "]},
box("
Foobar
\
out(Arg) ->
{html, \"Funky Stuff\"}.
\
Baz
"),
{p,[], ["Is a very small example where we have a HTML document with embedded "
"erlang code. A file which contains embedded erlang code must have the file "
"suffix ",
{tt, [], ".yaws"}]},
{br,[],[]},
{p, [], "The embedded erlang code can return the different values which will "
" trigger the yaws webserver to do different things. We list some of the simple "
" return values here: "},
{ul, [],
[{li,[],
[{p, [],
[{tt,[],"{html, DeepCharOrBinaryList}"},
" Which will make the value of ",
{tt, [],"DeepCharOrBinaryList"},
" be substituted into the HTML document."]}]},
{li,[],
{p,[],
[{tt,[],"{ehtml, ErlangTermStructure}"}]}}]},
{p, [],
["It is often more convenient to return "
"erlang terms which are then transformed to HTML instead "
"of returning plain HTML in string form using the ",
{tt,[], "html"}, " tag "]},
{p,[],
["Using the ehtml return value, we can return deep structured "
" erlang terms that correspond directly to HTML code. For example: "]},
box("
{table, [{bgcolor, \"tan\"}],
{tr, [],
[{td, [{width, \"70%\"}], {p, [{class, \"foo\"}], \"Hi there\"}}]}}
"),
{p, [], "Corresponds to the following HTML code: "},
box("
"),
{ul, [],
[{li,[],
{p,[],
[{tt,[], "{header, Header}"},
" If a " ,
{tt, [], "header"},
" structure is returned, an additional header is inserted among the HTTP headers generated by yaws. "
"This is used to insert for example Set-Cookie headers. The ",
{tt,[], "Header"}, " variable must not be newline terminated."]}},
{li,[],
{p,[],
[{tt,[], "{allheaders, Header}"},
" If an ",
{tt, [], "allheaders"},
" structure is returned, all previous headers that have been generated, including those "
"default hedaers generated by yaws itself are erased, and replaced by "
"the headers in ",
{tt, [], "Headers"},
". The variable ",
{tt,[], "Headers"},
" must be a list of ",
{tt, [], "{header, Str}"},
" tuples. The ",
{tt, [], "Str"},
" must not be newline terminated. "]}},
{li,[],
{p,[],
[{tt, [], "{status, StatusCodeInt} "},
"Is used to force yaws to return a different status code than the "
" default 200 code."]}},
{li,[],
{p,[],
[{tt, [], "ok"}, " Do nothing."]}},
{li,[],
{p,[],
[{tt, [], "{content, MimeType, Content} "},
"Sets the mime type, that is "
"the Content-Type: header to be ", {tt, [], "MimeType"},
" The default value is of course \"text/html\", but applications that "
"generate i.e wml or pdf, must set the Content-Type. "
" A pdf generating application can for example return the "
"tuple ", {tt, [], " {content, \"application/pdf\", PdfContentData} "}]}},
{li,[],
{p,[],
[{tt, [], "{redirect, URL} "}," a redirect is issued to the location in ",
{tt, [], " URL "}]}},
{li,[],
{p,[],
[{tt, [], "{redirect_local, Path} "}," a redirect is issued to the local "
"server using the same method (http or https) as the incoming request "
" and the path part of the location header to the value in ", {tt, [], " Path "},"."]}},
{li,[],
{p,[],
[{tt, [], "{'EXIT', normal}"}," which will terminate the "
" client connection in an uncontrolled way. "]}},
{li,[],
{p,[],
[{tt, [], "{ssi, File, Delimiter, Bindings}"},
" Using this construct, we can deep inside a ehtml structure, "
" return (ssi) Server Side Include content from a file. "
"This construct is further described in ",
{a, [{href, "ssi.yaws"}], "ssi.yaws"}, "."]}}
]},
{p,[],["The embedded erlang code can also return a list of the "
" above values. For example the following value "]},
box("
[{status, 303},
{allheaders,
[{header, [\"Location: \",\"http://www.funky.org/\"]},
{header, [\"Set-Cookie: \",\"namn=ruler;\"]}
]},
{html,\" Redirected to funky.org \"}
"),
{p,[],"Can be returned if we want to issue a redirect and set a cookie "
"at the same time."},
{p,[],["All possible return values from the out/1 function are documented in "
"the man page for ",
{a, [{href, "yman.yaws?page=yaws_api"}],
["",
{tt, [], "yaws_api (5)"}]}]},
{p,[],"It can also be instructive to look at the actual source "
"for the pages we are viewing at this very moment. Here are some of them"},
{ul, [],
[
{li,[],
[{p,[],
[{a, [{href, "index.yaws"}], "The top page, index.yaws"},
" and then the ",
{a, [{href, "code.yaws?file=/index.yaws"}], "corresponding source"}]}]},
{li,[],
[{p,[],
[{a, [{href, "dynamic.yaws"}], "This page, dynamic.yaws"},
" and then the ",
{a, [{href, "code.yaws?file=/dynamic.yaws"}], "corresponding source"}]}]}
]},
{h2,[],"The argument "},
{p,[],["The ", {tt, [], "out/1"}," function is supplied with a record argument. The "
"definition of that record is automatically included in the embedded erlang code "
"and the record definition is: "]},
ssi("ssi/dynamic.2"),
{p,[], "And some of the refered records are defined as:"},
ssi("ssi/dynamic.3"),
{p, [], "Each chunk of erlang code will be compiled into a separate module. "
"The module names are automatically generated. If we have functions inside the "
"erlang chunks that we want to call from other chunks or modules, it is possible "
" to explicitly name the modue that will be used as in: "},
box("
\
out(A) ->
io:format('This is the foobar module',[]).
func() ->
i_am_exported_from_foobar.
\")
]}]}].
out(A) -> {ssi, "END2",[],[]}.