%% vim: ts=4 sw=4 et
-module (demos_sync_panel).
-include_lib ("nitrogen_core/include/wf.hrl").
-compile(export_all).

-define(TEXTFILE, "./scratch/comet_demo_text").

main() -> #template { file="./templates/demos46.html" }.
    
title() -> "Synchronized Elements".

headline() -> "Synchronized Elements".

left() -> 
    [
        "
        <p>
        Nitrogen provides an easy mechanism to synchronize page elements across
        multiple clients by registering elements directly to a comet pool.
        <p>
        Calling <code>element_sync_panel:refresh(Trigger)</code> will trigger
        all the elements on all connected clients to refresh their contents by
        calling their assigned render function (which might typically read
        contents from a database or other data source).
        <p>
        In this demo, we will simulate users clicking one of the 'Msg' buttons,
        changing the status in the database and triggering a redraw on all
        connected clients, with the 'database' here being a simple text file on
        the hard drive.
        <p>
        To fully appreciate this demo, you'll want more than one browser
        window opened on this page to see the contents change in the other
        window.
        <p>
        To help you understand why this is useful, there is a <a
        href='http://sigma-star.com/blog/post/sync_panel'>blog post describing
        a specific use case</a> (after all, Nitrogen provides a number of
        comet/asynchronous tools and it might not be obvious why this
        rather simple tool is useful).  The key is that it provides a simple
        mechanism for all connected clients page contents to be synchronized
        with only a few simple lines.",

        linecount:render()
    ].

%% Notice how we use the fun ?MODULE:body_function/0 syntax rather than just
%% fun body_function/0? This is to ensure that when the module is recompiled
%% that the new version of body_function/0 will be called.
right() -> 
    _Body = [
        #panel{ text="Open this page in a couple browser windows then click some of the buttons below" },
        #sync_panel{
            style="border: dotted 2px black",
            pool=demo_sync_panel,
            triggers=[update_sync_panel],
            body_fun=fun ?MODULE:body_function/0
        },
        #button{postback={message, 1}, text="Msg 1"},
        #button{postback={message, 2}, text="Msg 2"},
        #button{postback={message, 3}, text="Msg 3"},
        #button{postback={message, 4}, text="Msg 4"},
        #button{postback={message, 5}, text="Msg 5"},
        #button{postback={message, 6}, text="Msg 6"}
    ].

%% body_function() is referenced by the body_fun attribute in the
%% #sync_panel{} element above. It will simply read the contents from our
%% "database" and prepare nitrogen elements to be used as the body of the
%% panel. This function is basically no different than any other function you
%% might use to define the body of a page element, except that instead of
%% calling it, for example with #panel{body=body_function()}, you'll instead
%% assign it to the #sync_panel.body_fun field and it will be called and used
%% to refresh the contents whenever its triggered to.
body_function() ->
    Msg = read_contents(),
    [
        #span{style="font-weight:bold", text="Boromir Says: "},
        #span{text=Msg}
    ].

%% This emulates our database by reading text from a file.
read_contents() ->
    case file:read_file(?TEXTFILE) of
        {ok, Body} -> Body;
        _ -> stock_message(1)
    end.

%% This emulates a save operation on our text file.
save_contents(N) ->
    file:write_file(?TEXTFILE, stock_message(N)).

%% Handle the postbacks generated by the message button presses
event({message, N}) ->
    save_contents(N),
    element_sync_panel:refresh(demo_sync_panel, update_sync_panel).

%% Some stock messages to use.
stock_message(1) -> "One does not simply walk into Mordor.";
stock_message(2) -> "Its black gates are guarded by more than just Orcs.";
stock_message(3) -> "There is evil there that does not sleep and the Great Eye is ever watchful.";
stock_message(4) -> "It is a barren wasteland, riddled with fire and ash and dust...the very air you breathe is a poisonous fume.";
stock_message(5) -> "Not with ten thousand men could you do this.";
stock_message(6) -> "It is folly.".