Created
June 30, 2013 10:14
-
-
Save Tarmil/5894620 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module XmlCE | |
open IntelliFactory.WebSharper | |
// I don't want to open IF.WS.Html here, because I'm defining my own HTML combinators | |
type IPagelet = IntelliFactory.WebSharper.Html.IPagelet | |
module E = IntelliFactory.WebSharper.Html.Events | |
/// The type of XML attributes. | |
/// I added a couple DOM events to show that we can have more | |
/// than just key/value attributes. | |
type Attribute = | |
| Attribute of string * string | |
| OnAfterRender of (IPagelet -> unit) | |
| OnClick of (IPagelet -> E.MouseEvent -> unit) | |
/// The type of XML nodes, which is also the computation expression builder. | |
type Node = | |
/// Node(tagName, attributes, children) | |
| Node of string * Attribute list * Node list | |
/// Text(content) | |
| Text of string | |
/// Start with no added children or attributes. | |
[<JavaScript>] | |
member this.Zero() = [] | |
/// Add a node. | |
[<JavaScript>] | |
member this.Sequence(x: Node, l: Node list) = | |
x :: l | |
/// Add a sequence of nodes. | |
[<JavaScript>] | |
member this.Sequence(x: seq<Node>, l: Node list) = | |
List.ofSeq x @ l | |
/// Add an attribute. | |
[<JavaScript>] | |
member this.Sequence(x: Attribute, l: Attribute list) = | |
x :: l | |
/// Add a sequence of attributes. | |
[<JavaScript>] | |
member this.Sequence(x: seq<Attribute>, l: Attribute list) = | |
List.ofSeq x @ l | |
/// Add a text node. Just a shortcut for this.Sequence(Text x, l). | |
[<JavaScript>] | |
member this.Sequence(x: string, l) = | |
Text x :: l | |
/// Add a sequence of children or attributes using for. | |
[<JavaScript>] | |
member this.For(s, f) = | |
List.ofSeq (Seq.collect f s) | |
/// Combine two sequences of new children or attributes. | |
[<JavaScript>] | |
member this.Combine(x, l) = | |
x @ l | |
/// This does nothing remarkable, but for some reason it must be present. | |
[<JavaScript>] | |
[<Inline>] | |
member this.Delay f = f() | |
/// Build a new node with the collected attributes. | |
[<JavaScript>] | |
member this.Run(attrs) = | |
match this with | |
| Node(name, a, children) -> Node(name, a @ attrs, children) | |
| Text s -> Node("span", attrs, [this]) | |
/// Build a new node with the collected children. | |
[<JavaScript>] | |
member this.Run(children) = | |
match this with | |
| Node(name, attrs, c) -> Node(name, attrs, c @ children) | |
| Text s -> Node("span", [], this :: children) | |
/// Helper constructors. | |
[<JavaScript>] | |
let attr n v = Attribute(n, v) | |
[<JavaScript>] | |
let node n = Node(n, [], []) | |
/// A bunch of HTML nodes. | |
/// I'm not going to implement the whole standard here, you get the idea :) | |
[<JavaScript>] | |
let Div = node "div" | |
[<JavaScript>] | |
let H1 = node "h1" | |
[<JavaScript>] | |
let Span = node "span" | |
[<JavaScript>] | |
let A = node "a" | |
[<JavaScript>] | |
let Table = node "table" | |
[<JavaScript>] | |
let TR = node "tr" | |
[<JavaScript>] | |
let TD = node "td" | |
[<JavaScript>] | |
let TH = node "th" | |
[<JavaScript>] | |
let HR = node "hr" | |
/// A few attributes as well. Same remark applies. | |
[<JavaScript>] | |
let Style = attr "style" | |
[<JavaScript>] | |
let HRef = attr "href" | |
module Example = | |
type Person = | |
{ | |
FirstName: string | |
LastName: string | |
ProfileUrl: string | |
Age: int | |
} | |
[<JavaScript>] | |
let showPeople people = | |
Div { | |
H1 { "People" } | |
HR | |
Table { Style "border-collapse: collapse;" } { | |
TR { | |
TH { "First Name" } | |
TH { "Last Name" } | |
TH { "Age" } | |
} | |
for person in people do | |
let myTd = TD { Style "border: solid 1px #888; width: 200px" } | |
let nameFields = [ | |
myTd { person.FirstName } | |
myTd { person.LastName } | |
] | |
TR { | |
nameFields | |
myTd { string person.Age } | |
myTd { | |
"See " | |
A { HRef person.ProfileUrl } { "Profile" } | |
} | |
} | |
} | |
} | |
module Client = | |
open IntelliFactory.WebSharper | |
open IntelliFactory.WebSharper.Html | |
[<JavaScript>] | |
let rec Render (x: Node) = | |
match x with | |
| Node(name, attrs, children) -> | |
let children = children |> List.map Render | |
let t = Tags.NewTag name children | |
attrs |> List.iter (function | |
| Attribute(n, v) -> t.Append(NewAttr n v) | |
| OnAfterRender f -> OnAfterRender f t | |
| OnClick f -> OnClick f t) | |
t :> IPagelet | |
| Text t -> Text t |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment