# vim: ts=2 sw=2 et ft=org
#+STYLE: <LINK href="stylesheet.css" rel="stylesheet" type="text/css" />
#+STYLE: <LINK href="stylesheet_api.css" rel="stylesheet" type="text/css" />
#+TITLE: Nitrogen 2.x Documentation
#+AUTHOR: Rusty Klophaus (@rustyio)
#+OPTIONS:   H:2 num:1 toc:1 \n:nil @:t ::t |:t ^:t -:t f:t *:t <:t
#+EMAIL:

#+TEXT: [[file:./index.org][Getting Started]] | *API* | [[file:./elements.org][Elements]] | [[file:./actions.org][Actions]] | [[file:./validators.org][Validators]] | [[file:./handlers.org][Handlers]] | [[file:./config.org][Configuration Options]] | [[file:../about.org][About]]
#+HTML: <div class=headline>Nitrogen API</div>

* Index

  + [[1][AJAX Updates]]
  + [[2][Convenience Functions]]
  + [[3][Event Wiring]]
  + [[4][Asynchronous Page Updates]]
  + [[5][Redirect]]
  + [[6][Session State]]
  + [[7][Page State]]
  + [[8][Authentication and Authorization]]
  + [[9][Web Request and Response]]
  + [[10][Cookies]]
  + [[11][HTTP Headers]]
  + [[12][Serialization]]
  + [[13][Logging]]
  + [[14][Configuration]]

* AJAX Updates
# <<1>>

  TargetID can refer to the name of an element, or it can be a JQuery
  selector path. See [[./paths.org][Element Paths]] for more information.

** wf:set(TargetID,Value) -> ok
   Update a form element (textbox, dropdown, checkbox, etc) to set text value of TargetID. Can also be used to set the =src= attribute of an image tag.
   
** wf:update(TargetID, Elements) -> ok
   Update the contents of TargetID with a new set of Nitrogen Elements.

** wf:replace(TargetID, Elements) -> ok
   Replace TargetID with a new set of Nitrogen Elements.

** wf:remove(TargetID) -> ok
   Remove TargetID from the DOM.
   
** wf:insert\_top(TargetID, Elements) -> ok
   Insert Nitrogen Elements at the top of TargetID (within the contents of TargetID), shifting the existing contents downward.
   
** wf:insert\_bottom(TargetID, Elements) -> ok
   Insert Nitrogen Elements at the bottom of the TargetID (within the contents of TargetID), below the existing contents.

** wf:insert\_before(TargetID, Elements) -> ok
   Insert Nitrogen Elements before TargetID in the DOM, shifting the existing contents downward.
   
** wf:insert\_after(TargetID, Elements) -> ok
   Insert Nitrogen Elements after TargetID in the DOM, below the existing contents.

** wf:flash(Elements) -> ok
   Insert the Nitrogen Elements as a new flash message.

* Convenience Functions
# <<2>>

** wf:f(Format, Data) -> String

   Convenience function to format a string similar to
   io\_lib:format(Format, Data). Returns a flattened list.
   
** wf:coalesce([List]) -> Item

   Return the first element in the list that is not 'undefined'.
   
** wf:is\_string(Term) -> Bool

   Return true if the Term is an Erlang string. That is, a flat list
   of integers.
   
** wf:to\_list(Term) -> List

   Convert the supplied term to a flat list, if possible. Useful for
   turning Integers, Atoms, Binaries into Strings.
   
** wf:to\_atom(Term) -> Atom

   Convert the supplied term into an Atom, if possible. Useful for
   turning Integers, Binaries, and Strings into Atoms.

** wf:to\_binary(Term) -> Binary

   Convert the supplied term into a Binary, if possible. Useful for
   turning Integers, Atoms, and Strings into Binaries.

** wf:to\_integer(Term) -> Integer

   Convert the supplied term into an Integer, if possible. Useful for turning Atoms, Strings, and Binaries into Integers.

** wf:html\_encode(String) -> EncodedString

   HTML encode the supplied String, converting things like < and > into &lt; and &gt;.

** wf:html\_decode(String) -> DecodedString

   HTML decoding decode the supplied String, converting things like &lt; and &gt; into < and >.

** wf:url\_encode(String) -> EncodedString

   URL encode the supplied String, converting potentially URL-breaking characters into percent notation (%XX).

** wf:url\_decode(String) -> DecodedString

   URL decode the supplied String, converting a percent-encoded String into a normal String.

** wf:hex\_encode(String) -> EncodedString.
  
   Hex-encode the supplied String.

** wf:hex\_decode(String) -> DecodedString

   Convert a hex-encoded String to a normal String.

** wf:temp\_id() -> String

   Return a temp id. Useful for naming an Element so that you can
   refer to it during a postback later, without giving it a specific
   name.

** wf:js\_escape(String) -> EscapedString

   Convert a String to a JS-safe string by adding backslashes to quotes and newlines.

** wf:join([Terms],Delimiter) -> [Terms]

   Because Erlang doesn't provide a means to join a list in a non-string fashion, this will join the =Terms= on the delimiter, regardless of the type of =Delimiter=.

#+BEGIN_SRC erlang
   wf:join([Line1,Line2,Line2],#br{}).
#+END_SRC

* Event Wiring
# <<3>>
   
** wf:wire(Actions) -> ok

   Wire actions to the page. The Actions are applied against the entire page unless a
   trigger or target are specified within the action itself.

   For example, show a Javascript alert:

#+BEGIN_SRC erlang
   wf:wire(#alert { text="Hello, World!" })
#+END_SRC
   
** wf:wire(TargetID, Actions) -> ok

   Wire actions to the page, targeted against supplied TargetID.
   For example, hide a Panel:

#+BEGIN_SRC erlang
   wf:wire(PanelID, #hide {})
#+END_SRC

** wf:wire(TriggerID, TargetID, Actions) -> ok

   Wire actions to the page, triggering on the supplied TriggerID and targeting against
   the supplied TargetID. This allows you to wire actions (such as #event) that listen
   to a click on one element and modify a different element.

   For example, when a button is clicked, hide a panel:

#+BEGIN_SRC erlang
   wf:wire(ButtonID, PanelID, #event { type=click, actions=#hide {} })
#+END_SRC

** wf:continue(Tag, Function, IntervalInMS, TimeoutInMS) -> ok

   Spawn the provided function (arity 0) and tell the browser to poll for the results at the specified interval, with a timeout setting.
   See [[http://nitrogenproject.com/web/samples/continuations][continuations example]] for usage.

* Asynchronous Page Updates (Comet, Continuations)
# <<4>>

** wf:comet(Function) -> {ok, Pid}

   Spawn a comet function, and tell the browser to open a COMET request to receive the results in real time.
   See [[http://nitrogenproject.com/web/samples/comet1][example 1]], [[http://nitrogenproject.com/web/samples/comet2][example 2]], and [[http://nitrogenproject.com/web/samples/comet3][example 3]] for usage.

** wf:comet(Function, LocalPool) -> {ok, Pid}

   Spawn a function connected to the specified local pool.

** wf:comet\_global(Function, GlobalPool) -> {ok, Pid}

   Spawn a function connected to the specified global pool.

** wf:send(LocalPool, Message)

   Send the specified message to all comet functions connected to the
   specified local pool.

** wf:send\_global(GlobalPool, Message)

   Send the specified message to all comet function connected to the
   specified GlobalPool.
   
** wf:flush() -> ok

   Normally, the results of a comet function are sent to the browser when the function exits.
   comet\_flush/0 pushes results to the browser immediately, useful for a looping comet function.

** wf:async\_mode()

   Return the current async mode, either =comet= or ={poll, IntervalInMS}=.

** wf:async\_mode(Mode)

   Set the current async mode, either =comet= or ={poll, IntervalInMS}=.

** wf:switch\_to\_comet()

   Run all current and future async processes in comet mode. This uses more
   resources on the server, as HTTP connections stay open.

** wf:switch\_to\_polling(IntervalInMS)

   Run all current and future async processes in polling mode. This
   uses more resources on the client, as the application must issue a
   request every =IntervalInMS= milliseconds.

** wf:continue(Tag, Function) -> ok

   Spawn the provided function (arity 0) and tell the browser to poll for the results.
   See [[http://nitrogenproject.com/web/samples/continuations][continuations example]] for usage.
   
** wf:continue(Tag, Function, Interval) -> ok

   Spawn the provided function (arity 0) and tell the browser to poll for the results at the specified interval.
   See [[http://nitrogenproject.com/web/samples/continuations][continuations example]] for usage.

* Redirect
# <<5>>

** wf:redirect(Url) -> ok
   Redirect to the provided URL.
   
** wf:redirect\_to\_login(Url) -> ok

   Redirect to the provided URL, attaching a token on the end. The receiving page can call
   =wf:redirect\_from\_login(DefaultUrl)= to send the user back to the current page.
   
** wf:redirect\_from\_login(DefaultUrl) -> ok

   Redirect the user back to a page that called =wf:redirect\_to\_login(Url)=. If
   the user came to the page for some other reason, then the user is redirected to the
   provided DefaultUrl.

* Session State
# <<6>>

** wf:session(Key) -> Value or 'undefined'

   Retrieve the session value stored under the specified key.
   For example, retrieve the value of 'count' for the current user:
   =Count = wf:session(count)=

** wf:session\_default(Key, DefaultValue) -> Value.

   Retrieve the session value stored under a specific key. If not
   found, return the supplied default value.
   
** wf:session(Key, Value) -> ok
   
   Store a session variable for the current user. Key and Value can be any Erlang term.
   For example, store a count:
   =wf:session(count, Count)=
   
** wf:clear\_session() -> ok

   Clear the current user's session.
   
** wf:logout() -> ok
   Clear session state, page state, identity, and roles.

* Page State
# <<7>>
   
** wf:state(Key) -> Value

   Retrieve a page state value stored under the specified key. Page State is
   different from Session State in that Page State is scoped to a series
   of requests by one user to one Nitrogen Page.

** wf:state\_default(Key, DefaultValue) -> Value.

   Retrieve a page state value stored under the specified key. If the
   value is not set, then return the supplied default value.
   
** wf:state(Key, Value) -> ok

   Store a page state variable for the current user. Page State is
   different from Session State in that Page State is scoped to a series
   of requests by one user to one Nitrogen Page.
   
** wf:clear\_state() -> ok
   Clear a user's page state.

* Authentication and Authorization
# <<8>>
   
** wf:user() -> User or 'undefined'
   Return the user value that was previously set by =wf:user(User)=

** wf:user(User) -> ok
   Set the user for the current session.
   
** wf:clear\_user() -> ok
   Same as =wf:user(undefined)=.
   
** wf:role(Role) -> 'true' or 'false'
   Check if the current user has a specified role.
   
** wf:role(Role, IsInRole) -> ok
   Set whether the current user is in a specified role. =IsInRole= should be a
   boolean (=true= or =false=)
   
** wf:clear\_roles() -> ok
   Remove the user from all roles.

* Web Request and Response
# <<9>>

** wf:q(AtomKey) -> String

   Get all query string and POST values for the provided key. If more
   than one AtomKey matches, then this will throw an error, use
   =wf:qs(AtomKey)= instead.

   *Mnemonic:* Think =q= as "Query".

** wf:mq(ListOfAtomKeys) -> [ListOfStrings]

   Get the list of query string and POST values for the provided keys, and 
   return the list of values for the keys. Syntactical sugar equivilant of:

#+BEGIN_SRC erlang
   [wf:q(AtomKey) || AtomKey <- ListOfAtomKeys]
#+END_SRC

   *Mnemonic*: Think =mq= as "Multi Query".

** wf:q\_pl(ListOfAtomKeys) -> [{Key,Values},...]

   Takes a list of keys returns a proplist of keys and respective values from query string and POST values.

   *Mnemonic*: Think =q_pl= as "Query Proplist"

Example:
#+BEGIN_SRC erlang
  wf:qs_pl([favorite_robot,favorite_dinosaur,favorite_hobbit])
#+END_SRC

  Returns something like:
#+BEGIN_SRC erlang
  [
      {favorite_robot,"Optimus Prime"},
      {favorite_dinosaur,"Velociraptor"},
      {favorite_hobbit,"Samwise"}
  ].

#+END_SRC


** wf:qs(AtomKey) -> [String]

   Get a list of query string and POST values for the provided
   key. (This acts like =wf:q(AtomKey)= in Nitrogen 1.0.)
  
   *Mnemonic:* Think =qs= as "Query Plural"

** wf:mqs(ListOfAtomKeys) -> [ListOfStrings]

   Get a list of query string and POST values for the provided list of keys.  Syntactical sugar equivilant of:

#+BEGIN_SRC erlang
   [wf:qs(AtomKey) || AtomKey <- ListOfAtomKeys]
#+END_SRC

   *Mnemonic*: Think =mqs= as "Multi Query Plural"

** wf:qs\_pl(ListOfAtomKeys) -> [{Key,ListOfValues},...]

   Takes a list of keys and returns a proplist of keys and respective list of values from the query string and POST values.

   *Mnemonic*: Think =qs_pl= as "Query Plurals into a Proplist"

Example:
#+BEGIN_SRC erlang
  wf:qs_pl([fruit,veggie,meat])
#+END_SRC

  Returns something like:
#+BEGIN_SRC erlang
  [
     {fruit,["Apple","Peach"]},
     {veggie,["Broccoli"]},
     {meat,["Pork","Beef","Venison"]}
  ].
#+END_SRC


** wf:request\_body() -> String
   Return the complete text of the request body to the server. Note, this value 
   will use the context of the current request. For example, the result of calling 
   this during the page's initial request will be different than calling it within
   a postback event.

** wf:status\_code(IntegerCode) -> ok
   Set the HTTP response code. Default is 200.
   
** wf:content\_type(ContentType) -> ok

   Set the HTTP content type. Defaults is "text/html". This can be
   used to return text images or other files to the browser, rather than returning 
   HTML.

** wf:path\_info() -> String

   Return the path info for the requested page. In other words, if the module
   web\_my\_page is requsted with the path "/web/my/page/some/extra/stuff then
   wf:get\_path\_info() would return "some/extra/stuff".
   
** wf:page\_module() -> Atom

   Return the requested page module. Useful information to know when writing a custom
   element or action.

* Cookies
# <<10>>

** wf:cookies() -> [{AtomKey, StringValue}].

   Return a proplist of all cookies.

** wf:cookie(Key) -> String

   Get the value of a cookie.

** wf:cookie\_default(Key, Default) -> String.

   Get the value of a cookie, if it doesn't exist, return the default.

** wf:cookie(Key, Value) -> ok

   Tell Nitrogen to set a cookie on the browser. Uses \"/\" for the Path, and Nitrogen's
   session timeout setting for the MinutesToLive value.
   
** wf:cookie(Key, Value, Path, MinutesToLive) -> ok

   Tell Nitrogen to set a cookie on the browser under the specified Path that is valid
   for a certain number of minutes.

** wf:delete\_cookie(Key) -> ok

   Tell Nitrogen to set the cookie to expire immediately, effectively deleting it from 
   the browser.  Is a shortcut for =wf:cookie(Key,"","/",0)=.
 
* HTTP Headers
# <<11>>
   
** wf:headers() -> [{AtomKey, StringValue}, ...]

   Return a proplist of all HTTP headers.
   
** wf:header(AtomKey) -> Value

   Get the value of an HTTP header.

** wf:header\_default(AtomKey, Default) -> Value.
  
   Get the value of an HTTP header, if it doesn't exist, return the default.

** wf:header(StringKey, HeaderValue) -> ok

   Set an HTTP header during the next response.
   
* Serialization
# <<12>>
   
** wf:pickle(Term) -> PickledBinary
   Serialize a term into a web-safe hex string, with checksumming. (Not encrypted!)
   
** wf:depickle(PickledBinary) -> Term
   Turn a pickled binary back into the original term.
   
** wf:depickle(PickledBinary, SecondsToLive) -> Term or 'undefined'

   Turn a pickled binary back into the original term, checking to see
   if the term was pickled more than SecondsToLive second
   ago. Returns the Term if it is still 'fresh' or the atom
   'undefined'.

* Logging
# <<13>>

** wf:info(String)

   Log an informational message.

** wf:info(Format, Args)

   Log an informational message.

** wf:warning(String)

   Log a warning message.

** wf:warning(Format, Args)

   Log a warning message.
  

** wf:error(String)

   Log an error message.

** wf:error(Format, Args)

   Log an error message.

* Configuration
# <<14>>

** wf:config(Key) -> Term
   
   Get the Nitrogen configuration setting under the specified Key.

** wf:config(Key, DefaultValue) -> Term

   Get the Nitrogen configuration setting under the specified Key. If
   not set, then return DefaultValue.

  
