2 using System
.Collections
;
3 using System
.Collections
.Generic
;
13 public delegate object HtmlFunc();
14 //static WvLog log = new WvLog("WvHtml");
18 public string name
, value;
20 public Attr(string name
, string value)
22 wv
.assert(name
!= null);
23 wv
.assert(value != null);
34 public static readonly Attr noattr
= null;
40 public Verbatim(string s
)
47 List
<object> content
= new List
<object>();
48 Stack
<WvHtml
> opens
= new Stack
<WvHtml
>();
50 public WvHtml(string tagname
, params object[] args
)
52 //log.print("Creating '{0}'\n", tagname);
53 this.tagname
= tagname
; // may be null
62 public string ToString(int indent
)
64 //log.print("tostring: {0}\n", tagname);
66 var attrs
= new Dictionary
<string, string>();
67 StringBuilder ab
= new StringBuilder();
68 StringBuilder cb
= new StringBuilder();
70 while (opens
.Count
> 0)
74 ab
.Append(wv
.fmt("<{0}", tagname
));
76 foreach (object _o
in content
)
78 Action
<object> handler
;
80 // Okay, this is a little funny. The inner part of this loop
81 // can call itself recursively :) It's a nice way to handle
82 // things like IEnumerable.
83 handler
= delegate(object o
)
87 else if (o
is HtmlFunc
)
88 handler(((HtmlFunc
)o
)());
91 // Normal objects get automatically html-encoded. If
92 // you need to supply verbatim html, use v().
93 cb
.Append(HttpUtility
.HtmlEncode(o
.ToString()));
97 // Collect all the attributes together to end up as
98 // part of our tag. If the same attribute name occurs
99 // more than once, concatenate all the values with
100 // spaces between. (This is useful for attributes like
101 // class="list blue")
102 wv
.assert(tagname
!= null);
104 string v
= HttpUtility
.HtmlAttributeEncode(a
.value);
105 if (attrs
.ContainsKey(a
.name
))
106 attrs
[a
.name
] = attrs
[a
.name
] + ' ' + v
;
108 attrs
.Add(a
.name
, v
);
110 else if (o
is Verbatim
)
112 cb
.Append(((Verbatim
)o
).s
);
114 else if (o
is WvHtml
)
116 // WvHtml objects have already been html-encoded.
117 string s
= ((WvHtml
)o
).ToString(indent
+2);
118 cb
.Append(wv
.fmt("\n{0}", "".PadRight(indent
+2)));
120 if (s
.Contains("\n"))
121 cb
.Append(wv
.fmt("\n{0}", "".PadRight(indent
)));
123 else if (o
is IEnumerable
)
125 // CAREFUL! This branch catches all sorts of objects.
126 // For example, string is IEnumerable.
127 foreach (object oo
in (IEnumerable
)o
)
131 cb
.Append(o
.ToString());
139 foreach (string k
in attrs
.Keys
)
140 ab
.Append(wv
.fmt(" {0}=\"{1}\"", k
, attrs
[k
]));
142 string c
= cb
.ToString().TrimEnd();
143 /* if (c.Length == 0)
144 return ab.ToString() + " />";
145 else */ if (c
.Contains("\n"))
146 return wv
.fmt("{0}>{1}\n{2}</{3}>",
147 ab
.ToString(), c
, "".PadRight(indent
),
150 return wv
.fmt("{0}>{1}</{2}>",
151 ab
.ToString(), c
, tagname
);
154 return cb
.ToString();
157 public override string ToString()
162 public WvHtml
topmost()
170 public void add(params object[] args
)
173 opens
.Peek().add(args
);
176 foreach (object o
in args
)
184 // Make subsequent add() calls add to an entirely different WvHtml
185 // object. You can call this, do a bunch of adds, and then
186 // take the return value of pop() and add it somewhere too.
189 opens
.Push(new WvHtml());
192 // The reverse of push(). Returns the finished WvHtml subtree,
193 // which you can then add().
199 // WARNING MAGIC: use insert_contents_here as a marker in a
200 // deep hierarchy, then use twist() to make add() point at that
201 // part of the hierarchy, then use pop() to start adding back
202 // at the parent level. For example:
203 // add(html(body(div(insert_content_here),
205 // // add()s here come after the html() tag
207 // // add()s here come inside the div()
208 // add(p("hello world")); // this gets inserted at the i_c_h
210 // // subsequent add()s come after the html() tag.
211 public WvHtml insert_content_here
{
213 WvHtml h
= new WvHtml();
214 wv
.assert(ich
== null,
215 "There was no twist() after the last i_c_h!");
225 wv
.assert(ich
!= null,
226 "twist() only works after insert_content_here");
231 // To make them stand out, we prefix all the attribute-adding functions
233 public Attr
_attr(string name
, string value)
234 { return new Attr(name, value); }
235 public Attr
_attr(string name
, string fmt
, params object[] args
)
236 { return new Attr(name, wv.fmt(fmt, args)); }
237 public Attr
_id(string value)
238 { return _attr("id", value); }
239 public Attr
_class(string value)
240 { return _attr("class", value); }
241 public Attr
_style(string value)
242 { return _attr("style", value); }
243 public Attr
_name(string value)
244 { return _attr("name", value); }
245 public Attr
_value(string value)
246 { return _attr("value", value); }
247 public Attr
_type(string value)
248 { return _attr("type", value); }
249 public Attr
_colspan(string value)
250 { return _attr("colspan", value); }
251 public Attr
_rowspan(string value)
252 { return _attr("rowspan", value); }
253 public Attr
_src(string value)
254 { return _attr("src", value); }
255 public Attr
_align(string value)
256 { return _attr("align", value); }
257 public Attr
_size(int size
)
258 { return _attr("size", size.ToString()); }
259 public Attr
_selected()
260 { return _attr("selected", "true"); }
261 public Attr
_rows(int count
)
262 { return _attr("rows", count.ToString()); }
263 public Attr
_cols(int count
)
264 { return _attr("cols", count.ToString()); }
267 public WvHtml
v(params string[] args
)
268 { return new WvHtml(null, args.map((s) => new Verbatim(s))); }
269 public WvHtml
v(params object[] args
)
270 { return new WvHtml(null, args); }
271 public WvHtml
tag(string tagname
, params object[] args
)
272 { return new WvHtml(tagname, args); }
273 public WvHtml
fmt(string f
, params object[] args
)
274 { return new WvHtml(null, wv.fmt(f, args)); }
275 public WvHtml
func(Func
<WvHtml
> f
)
276 { return new WvHtml(null, new HtmlFunc(f)); }
279 public Attr
_confirm(string msg
)
281 return _attr("onclick",
282 wv
.fmt("return confirm(\"{0}\");", msg
));
286 public WvHtml
html(params object[] args
)
290 v("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" "
291 + "\"http://www.w3.org/TR/html4/strict.dtd\">\n"),
296 public WvHtml
head(params object[] args
)
297 { return tag("head", args); }
298 public WvHtml
title(params object[] args
)
299 { return tag("title", args); }
300 public WvHtml
meta(params object[] args
)
301 { return tag("meta", args); }
302 public WvHtml
link(params object[] args
)
303 { return tag("link", args); }
305 // FIXME: script tags get confused by IE if you use <script... />
306 // syntax, so we have to force (badly!) <script>...</script> syntax
308 public WvHtml
script(params object[] args
)
309 { return tag("script", args); }
312 public WvHtml
javascript_file(string src
, params object[] args
)
313 { return script(_attr("type", "text/javascript"),
316 public WvHtml
js_file(string src
, params object[] args
)
317 { return javascript_file(src, args); }
320 public WvHtml
css_file(string src
, params object[] args
)
321 { return link(_attr("rel", "stylesheet"),
323 _attr("type", "text/css"),
327 public WvHtml
body(params object[] args
)
328 { return tag("body", args); }
331 public WvHtml
img(string src
, params object[] args
)
332 { return tag("img", _src(src), args); }
335 public WvHtml
a(params object[] args
)
336 { return tag("a", args); }
337 public WvHtml
ahref(string href
, params object[] args
)
338 { return a(_attr("href", href), args); }
341 public WvHtml
p(params object[] args
)
342 { return tag("p", args); }
343 public WvHtml
div(params object[] args
)
344 { return tag("div", args); }
345 public WvHtml
span(params object[] args
)
346 { return tag("span", args); }
348 // This looks weird, but works better with IE.
349 get { return new WvHtml(null, v("<br />")); }
353 public WvHtml
b(params object[] args
)
354 { return tag("b", args); }
355 public WvHtml
i(params object[] args
)
356 { return tag("i", args); }
357 public WvHtml
sup(params object[] args
)
358 { return tag("sup", args); }
360 get { return v(" "); }
364 public WvHtml
h1(params object[] args
)
365 { return tag("h1", args); }
366 public WvHtml
h2(params object[] args
)
367 { return tag("h2", args); }
368 public WvHtml
h3(params object[] args
)
369 { return tag("h3", args); }
370 public WvHtml
h4(params object[] args
)
371 { return tag("h4", args); }
372 public WvHtml
h5(params object[] args
)
373 { return tag("h5", args); }
374 public WvHtml
h6(params object[] args
)
375 { return tag("h6", args); }
378 public WvHtml
ol(params object[] args
)
379 { return tag("ol", args); }
380 public WvHtml
ul(params object[] args
)
381 { return tag("ul", args); }
382 public WvHtml
li(params object[] args
)
383 { return tag("li", args); }
386 public WvHtml
table(params object[] args
)
387 { return tag("table", args); }
388 public WvHtml
tr(params object[] args
)
389 { return tag("tr", args); }
390 public WvHtml tr_empty
391 { get { return tr(td(nbsp)); }
}
392 public WvHtml
td(params object[] args
)
393 { return tag("td", args); }
394 public WvHtml
th(params object[] args
)
395 { return tag("th", args); }
398 public WvHtml
form(string method
, string url
,
399 params object[] args
)
401 _attr("method", method
),
402 _attr("action", url
),
404 public WvHtml
submit(string id
, params object[] args
)
405 { return tag("input", _attr("type", "submit"),
409 public WvHtml
input(string id
, int length
, string defval
,
410 params object[] args
)
411 { return tag("input", _name(id
), _size(length
),
412 _value(defval
), args
); }
413 public WvHtml
input(string id
, int length
)
414 { return input(id, length, ""); }
415 public WvHtml
hidden(string id
, object value)
416 { return tag("input", _type("hidden"),
417 _name(id
), _value(value.ToString())); }
418 public WvHtml
select(string id
, params object[] args
)
419 { return tag("select", _name(id), args); }
420 public WvHtml
option(string name
, string display
,
421 params object[] args
)
422 { return tag("option", _value(name
), display
, args
,
424 public WvHtml
textarea(string name
, params object[] args
)
425 { return tag("textarea", _name(name), args); }