
<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,[],[]}}}.

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, [], "&lt;erl&gt;"},
                 " and ",
                 {tt, [], "\&lt;/erl&gt;"},
                 " markers. For example: "]},

         box("
<html>
 <h1>Foobar</h1>
 \<erl>

 out(Arg) ->
    {html, \"Funky Stuff\"}.
 \</erl>

 <h1>Baz</h1>

 </html>
"),

         {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("
<table bgcolor=\"tan\">
   <tr>
      <td width=\"70%\">
        <p class=\"foo\"> Hi there </p>
      </td>
   </tr>
</table>
"),

         {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: \",\"https://www.funky.org/\"]},
      {header, [\"Set-Cookie: \",\"namn=ruler;\"]}
     ]},
 {html,\"<html> Redirected to funky.org </html>\"}
"),
         {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("
   \<erl module=foobar>
      out(A) ->
         io:format('This is the foobar module',[]).

      func() ->
         i_am_exported_from_foobar.
    \</erl>")


         ]}]}].



</erl>


<erl>
out(A) -> {ssi, "END2",[],[]}.
</erl>

