PageRenderTime 25ms CodeModel.GetById 14ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/src/support/z_tags.erl

https://code.google.com/p/zotonic/
Erlang | 98 lines | 68 code | 18 blank | 12 comment | 1 complexity | 48cb4facefbe086b8ac58121d2368ba0 MD5 | raw file
 1%% @author Marc Worrell <marc@worrell.nl>
 2%% @copyright 2009 Marc Worrell <marc@worrell.nl>
 3%%
 4%% Based on code Copyright (c) 2008-2009 Rusty Klophaus
 5%% Original author Tom McNulty <tom.mcnulty@cetiforge.com>
 6%%
 7%% @doc Generate a XHTML element with attributes, correctly escape all attributes.
 8
 9-module (z_tags).
10
11-include("include/zotonic.hrl").
12
13-export([render_tag/2, render_tag/3, render_tag/4]).
14-export([optional_escape/1]).
15
16%% @doc Render a tag with properties, return the tag text. div has special handling as <div/> is not allowed.
17render_tag("div", Props) ->
18    render_tag(<<"div">>, Props);
19render_tag(<<"div">>, Props) ->
20	[<<"<div ">>, write_props(Props), <<"></div>">> ];
21render_tag(TagName, Props) ->
22	[$<, TagName, write_props(Props), $/, $> ].
23
24
25%% @doc Render a tag into the context
26render_tag("div", Props, #context{} = Context) ->
27    render_tag(<<"div">>, Props, Context);
28render_tag(<<"div">>, Props, #context{} = Context) ->
29	Render   = [<<"<div ">>, write_props(Props), <<"></div>">> ],
30	z_render:render(Render, Context);
31render_tag(TagName, Props, #context{} = Context) ->
32	Render   = [$<, TagName, write_props(Props), $/, $> ],
33	z_render:render(Render, Context);
34
35render_tag(TagName, Props, Content) ->
36	[ $<, TagName, write_props(Props), $>, Content, $<, $/, TagName, $> ].
37	
38
39%%% Tags with child content %%%
40render_tag(TagName, Props, undefined, Context) ->
41    render_tag(TagName, Props, Context);
42render_tag(TagName, Props, [], Context) ->
43    render_tag(TagName, Props, Context);
44render_tag(TagName, Props, Content, Context) ->
45	Render   = [ $<, TagName, write_props(Props), $>, Content, $<, $/, TagName, $> ],
46	z_render:render(Render, Context).
47   
48    
49%%% Property display functions %%%
50    
51write_props(Props) ->
52    [ display_property(optional_escape_property(P)) || P <- Props ].
53
54display_property({_Prop, undefined}) ->
55    [];
56display_property({Prop, V}) when is_atom(Prop) ->
57    display_property({list_to_binary(atom_to_list(Prop)), V});
58display_property({_, []}) ->
59    [];
60display_property({Prop, Value}) when is_integer(Value) ->
61    [32, correct_data(Prop), $=, $', list_to_binary(integer_to_list(Value)), $'];
62display_property({Prop, Value}) when is_float(Value) ->
63	[32, correct_data(Prop), $=, $', list_to_binary(io_lib:format("~f",[Value])), $'];
64display_property({Prop, Value}) when is_list(Value) ->
65    case io_lib:char_list(Value) of
66        true -> 
67            [32, correct_data(Prop), $=, $', Value, $'];
68        false ->
69            [32, correct_data(Prop), $=, $', z_utils:combine_defined(32, Value), $']
70	end;
71display_property({Prop, Value}) when is_atom(Value) ->
72	[32, correct_data(Prop), $=, $', atom_to_list(Value), $'];
73display_property({Prop, Value}) ->
74	[32, correct_data(Prop), $=, $', Value, $'].
75
76
77optional_escape_property({href, Uri}) -> {href, optional_escape(Uri)};
78optional_escape_property({src, Uri}) -> {src, optional_escape(Uri)};
79optional_escape_property({<<"src">>, Uri}) -> {<<"src">>, optional_escape(Uri)};
80optional_escape_property({<<"href">>, Uri}) -> {<<"href">>, optional_escape(Uri)};
81optional_escape_property(P) -> P.
82
83optional_escape(S) when is_list(S) ->
84    case string:chr(S, $&) of
85        0 -> S;
86        _ ->
87            case string:str(S, "&amp;") of
88                0 -> mochiweb_html:escape(S);
89                _ -> S
90            end
91    end;
92optional_escape(S) -> S.
93
94
95% @doc Correct data_xxxx attributes, so that they are generated as data-xxxx
96correct_data("data_"++P) -> "data-"++P;
97correct_data(<<"data_",P/binary>>) -> <<"data-",P/binary>>;
98correct_data(P) -> P.