Namdak Tonpa 8 years ago
parent
commit
d3a8083e45
5 changed files with 103 additions and 37 deletions
  1. 5 0
      include/nitro.hrl
  2. 3 3
      src/elements/element_upload.erl
  3. 92 26
      src/nitro.erl
  4. 0 2
      src/render/wf_event.erl
  5. 3 6
      src/render/wf_render_elements.erl

+ 5 - 0
include/nitro.hrl

@@ -1,6 +1,11 @@
 -ifndef(NITRO_HRL).
 -ifndef(NITRO_HRL).
 -define(NITRO_HRL, true).
 -define(NITRO_HRL, true).
 
 
+-record(cx,      { handlers, actions, req, module, lang, path, session, formatter=false, params, form, state=[] }).
+
+-define(CTX, (get(context))).
+-define(REQ, (get(context))#cx.req).
+
 -define(DEFAULT_BASE, {?ELEMENT_BASE(undefined)}).
 -define(DEFAULT_BASE, {?ELEMENT_BASE(undefined)}).
 -define(DEFAULT_BASE_TAG(Tag), {?ELEMENT_BASE(undefined,Tag,undefined)}).
 -define(DEFAULT_BASE_TAG(Tag), {?ELEMENT_BASE(undefined,Tag,undefined)}).
 -define(ELEMENT_BASE(Module), ?ELEMENT_BASE(Module,undefined,undefined)).
 -define(ELEMENT_BASE(Module), ?ELEMENT_BASE(Module,undefined,undefined)).

+ 3 - 3
src/elements/element_upload.erl

@@ -2,9 +2,9 @@
 -compile(export_all).
 -compile(export_all).
 -include_lib("nitro/include/nitro.hrl").
 -include_lib("nitro/include/nitro.hrl").
 
 
-render_element(#upload{id=Id} = U) ->
+render_element(#upload{id=Id}) ->
     Uid = case Id of undefined -> wf:temp_id(); I -> I end,
     Uid = case Id of undefined -> wf:temp_id(); I -> I end,
-    wf:wire("ftp_file=undefined;"),
+    nitro:wire("ftp_file=undefined;"),
     bind(ftp_open,  click,  wf:f("qi('~s').click(); event.preventDefault();", [wf:to_list(Uid)])),
     bind(ftp_open,  click,  wf:f("qi('~s').click(); event.preventDefault();", [wf:to_list(Uid)])),
     bind(ftp_start, click,  "ftp.start(ftp_file);"),
     bind(ftp_start, click,  "ftp.start(ftp_file);"),
     bind(ftp_stop,  click,  "ftp.stop(ftp_file);"),
     bind(ftp_stop,  click,  "ftp.stop(ftp_file);"),
@@ -19,4 +19,4 @@ render_element(#upload{id=Id} = U) ->
     ] } ] }, wf:render(Upload).
     ] } ] }, wf:render(Upload).
 
 
 bind(Control,Event,Code) ->
 bind(Control,Event,Code) ->
-    wf:wire(#bind{target=Control,type=Event,postback=Code}).
+    nitro:wire(#bind{target=Control,type=Event,postback=Code}).

+ 92 - 26
src/nitro.erl

@@ -65,7 +65,7 @@ depickle(SerializedData, TTLSeconds) -> ?PICKLER:depickle(SerializedData, TTLSec
 render(X) -> wf_render:render(X).
 render(X) -> wf_render:render(X).
 wire(Actions) -> action_wire:wire(Actions).
 wire(Actions) -> action_wire:wire(Actions).
 
 
-unique_integer() -> try erlang:unique_integer() catch _:_ -> {MS,S,US} = erlang:now(), (MS*1000000+S)*1000000+US end.
+unique_integer() -> erlang:unique_integer().
 temp_id() -> "auto" ++ integer_to_list(unique_integer() rem 1000000).
 temp_id() -> "auto" ++ integer_to_list(unique_integer() rem 1000000).
 
 
 html_encode(L,Fun) when is_function(Fun) -> Fun(L);
 html_encode(L,Fun) when is_function(Fun) -> Fun(L);
@@ -78,34 +78,100 @@ html_encode(L, whites) -> html_encode_whites(nitro:to_list(lists:flatten([L]))).
 html_encode(<<>>) -> [];
 html_encode(<<>>) -> [];
 html_encode([]) -> [];
 html_encode([]) -> [];
 html_encode([H|T]) ->
 html_encode([H|T]) ->
-	case H of
-		$< -> "&lt;" ++ html_encode(T);
-		$> -> "&gt;" ++ html_encode(T);
-		$" -> "&quot;" ++ html_encode(T);
-		$' -> "&#39;" ++ html_encode(T);
-		$& -> "&amp;" ++ html_encode(T);
-		BigNum when is_integer(BigNum) andalso BigNum > 255 ->
-			%% Any integers above 255 are converted to their HTML encode equivilant,
-			%% Example: 7534 gets turned into &#7534;
-			[$&,$# | nitro:to_list(BigNum)] ++ ";" ++ html_encode(T);
-		Tup when is_tuple(Tup) ->
-			throw({html_encode,encountered_tuple,Tup});
-		_ -> [H|html_encode(T)]
-	end.
+    case H of
+        $< -> "&lt;" ++ html_encode(T);
+        $> -> "&gt;" ++ html_encode(T);
+        $" -> "&quot;" ++ html_encode(T);
+        $' -> "&#39;" ++ html_encode(T);
+        $& -> "&amp;" ++ html_encode(T);
+        BigNum when is_integer(BigNum) andalso BigNum > 255 ->
+        [$&,$# | nitro:to_list(BigNum)] ++ ";" ++ html_encode(T);
+        Tup when is_tuple(Tup) -> throw({html_encode,encountered_tuple,Tup});
+        _ -> [H|html_encode(T)]
+    end.
 
 
 html_encode_whites([]) -> [];
 html_encode_whites([]) -> [];
 html_encode_whites([H|T]) ->
 html_encode_whites([H|T]) ->
-	case H of
-		$\s -> "&nbsp;" ++ html_encode_whites(T);
-		$\t -> "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" ++ html_encode_whites(T);
-		$< -> "&lt;" ++ html_encode_whites(T);
-		$> -> "&gt;" ++ html_encode_whites(T);
-		$" -> "&quot;" ++ html_encode_whites(T);
-		$' -> "&#39;" ++ html_encode_whites(T);
-		$& -> "&amp;" ++ html_encode_whites(T);
-		$\n -> "<br>" ++ html_encode_whites(T);
-		_ -> [H|html_encode_whites(T)]
-	end.
+    case H of
+        $\s -> "&nbsp;" ++ html_encode_whites(T);
+        $\t -> "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" ++ html_encode_whites(T);
+        $< -> "&lt;" ++ html_encode_whites(T);
+        $> -> "&gt;" ++ html_encode_whites(T);
+        $" -> "&quot;" ++ html_encode_whites(T);
+        $' -> "&#39;" ++ html_encode_whites(T);
+        $& -> "&amp;" ++ html_encode_whites(T);
+        $\n -> "<br>" ++ html_encode_whites(T);
+        _ -> [H|html_encode_whites(T)]
+    end.
 
 
 script() -> get(script).
 script() -> get(script).
 script(Script) -> put(script,Script).
 script(Script) -> put(script,Script).
+
+% Update DOM nitro:update
+
+update(Target, Elements) ->
+    nitro:wire(#jq{target=Target,property=outerHTML,right=Elements,format="'~s'"}).
+
+insert_top(Tag,Target, Elements) ->
+    Pid = self(),
+    Ref = make_ref(),
+    spawn(fun() -> R = nitro:render(Elements), Pid ! {R,Ref,nitro:actions()} end),
+    {Render,Ref,Actions} = receive {_, Ref, _} = A -> A end,
+    nitro:wire(nitro:f(
+        "qi('~s').insertBefore("
+        "(function(){var div = qn('~s'); div.innerHTML = '~s'; return div.firstChild; })(),"
+        "qi('~s').firstChild);",
+        [Target,Tag,Render,Target])),
+    nitro:wire(nitro:render(Actions)).
+
+insert_bottom(Tag, Target, Elements) ->
+    Pid = self(),
+    Ref = make_ref(),
+    spawn(fun() -> R = nitro:render(Elements), Pid ! {R,Ref,nitro:actions()} end),
+    {Render,Ref,Actions} = receive {_, Ref, _} = A -> A end,
+    nitro:wire(nitro:f(
+        "(function(){ var div = qn('~s'); div.innerHTML = '~s';"
+                     "qi('~s').appendChild(div.firstChild); })();",
+        [Tag,Render,Target])),
+    niro:wire(nitro:render(Actions)).
+
+insert_adjacent(Command,Target, Elements) ->
+    Pid = self(),
+    Ref = make_ref(),
+    spawn(fun() -> R = nitro:render(Elements), Pid ! {R,Ref,nitro:actions()} end),
+    {Render,Ref,Actions} = receive {_, Ref, _} = A -> A end,
+    nitro:wire(nitro:f("qi('~s').insertAdjacentHTML('~s', '~s');",[Target,Command,Render])),
+    nitro:wire(nitro:render(Actions)).
+
+actions() -> get(actions).
+actions(Ac) -> put(actions,Ac).
+
+insert_top(Target, Elements) when element(1,Elements) == tr -> insert_top(tbody,Target, Elements);
+insert_top(Target, Elements) -> insert_top('div',Target, Elements).
+insert_bottom(Target, Elements) when element(1,Elements) == tr -> insert_bottom(tbody, Target, Elements);
+insert_bottom(Target, Elements) -> insert_bottom('div', Target, Elements).
+insert_before(Target, Elements) -> insert_adjacent(beforebegin,Target, Elements).
+insert_after(Target, Elements) -> insert_adjacent(afterend,Target, Elements).
+
+remove(Target) ->
+    nitro:wire("var x=qi('"++nitro:to_list(Target)++"'); x && x.parentNode.removeChild(x);").
+
+% Wire JavaScript nitro:wire
+
+state(Key) -> erlang:get(Key).
+state(Key,Value) -> erlang:put(Key,Value).
+
+% Redirect and purge connection nitro:redirect
+
+redirect({http,Url}) -> n2o:header(<<"Location">>,nitro_conv:to_binary(Url)), nitro:state(status,302), [];
+redirect(Url) -> nitro:wire(#jq{target='window.top',property=location,args=simple,right=Url}).
+header(K,V) -> nitro:context((?CTX)#cx{req=cowboy_req:set_resp_header(K,V,?REQ)}).
+
+% Convert and Utils API
+
+display(Element,Status) -> 
+   nitro:wire("{ var x = qi('"++
+      nitro:to_list(Element)++"'); if (x) x.style.display = '"++nitro:to_list(Status)++"'; }").
+
+show(Element) -> display(Element,block).
+hide(Element) -> display(Element,none).

+ 0 - 2
src/render/wf_event.erl

@@ -5,8 +5,6 @@
 -compile(export_all).
 -compile(export_all).
 
 
 -record(ev, { module, msg, trigger, name }).
 -record(ev, { module, msg, trigger, name }).
--record(cx, { handlers, actions, req, module, lang, path, session, formatter, params, form, state=[] }).
--define(CTX, (get(context))).
 
 
 -define(B(E), nitro:to_binary(E)).
 -define(B(E), nitro:to_binary(E)).
 -define(L(E), nitro:to_list(E)).
 -define(L(E), nitro:to_list(E)).

+ 3 - 6
src/render/wf_render_elements.erl

@@ -17,13 +17,10 @@ render_element(Element) when is_tuple(Element) ->
          nitro:wire(nitro:f("{var name='~s'; qi(name)"
          nitro:wire(nitro:f("{var name='~s'; qi(name)"
            ".addEventListener('validation',"
            ".addEventListener('validation',"
               "function(e) { if (!(~s)) e.preventDefault(); });"
               "function(e) { if (!(~s)) e.preventDefault(); });"
-              "qi(name).validation = true;}",[Id,Code]));
-         _ -> skip end,
+              "qi(name).validation = true;}",[Id,Code])) end,
     case element(#element.module,Element) of
     case element(#element.module,Element) of
-        undefined ->
-	    default_render(Tag, Element);
-        Module ->
-	    nitro:to_binary(Module:render_element(setelement(#element.id,Element,Id))) end;
+        undefined -> default_render(Tag, Element);
+        Module -> nitro:to_binary(Module:render_element(setelement(#element.id,Element,Id))) end;
 render_element(Element) -> io:format("Unknown Element: ~p~n\r",[Element]).
 render_element(Element) -> io:format("Unknown Element: ~p~n\r",[Element]).
 
 
 default_render(Tag, Record) ->
 default_render(Tag, Record) ->