F#
HTML
Result
Hosted on
Try WebSharper
<
>
namespace WebSharper.Rappid.Test open WebSharper open WebSharper.JavaScript open WebSharper.JQuery open WebSharper.JointJs open WebSharper.Rappid.Extensions [<JavaScript>] module Client = [<assembly: Require(typeof<Rappid.Resources.RappidJs>)>] do () type Attrs = { ElementDefault : obj ElementSelected : obj ElementHighlighted : obj LinkDefault : obj LinkDefaultDirected : obj LinkHighlighted : obj } static member Value = { ElementDefault = New [ "text" => New [ "fill" => "#fff" "style" => """'text-shadow': '1px 1px 1px #999', 'text-transform': 'capitalize'""" ] "circle" => New ["fill" => "#feb663"; "stroke" => "white"] ] ElementSelected = New ["circle" => New ["fill" => "#9687fe"]] ElementHighlighted = New ["circle" => New ["fill" => "#31d0c6"]] LinkDefault = New [".connection" => New ["stroke" => "#6a6c8a"; "stroke-width" => 1]] LinkDefaultDirected = New [".marker-target" => New [ "d" => "M 6 0 L 0 3 L 6 6 z" ]] LinkHighlighted = New [".connection" => New [ "stroke" => "#33334e"; "stroke-width" => 3 ]] } let Main = let m = [ "a", ["b"; "c"] "b", ["d"; "e"] "c", ["f"; "g"] "f", ["b"] "e", ["c"] "h", ["f"; "g"] "i", ["h"; "a"; "d"; "g"] "j", ["a"] ] let graph = Joint.Dia.Graph() let paper = Joint.Dia.Paper( PaperConfig( El = JQuery.Of("#paper"), Width = 800, Height = 800, GridSize = 1, Model = graph ) ) let node (id : string) (p : SimplePoint) = let node = Joint.Shapes.Basic.Circle( ShapeConfig(Id = id, Position = p, Size = Size(40., 40.), Attrs = Attrs.Value.ElementDefault)) .AddTo(graph) node.Attr("text/text", id) let link (s : string) (t : string) = let id = Array.sort [|s; t|] Joint.Dia.Link( Id = id.JS.Join(), SourceConnection = Connection(s), TargetConnection = Connection(t), Z = -1, Attrs = Attrs.Value.LinkDefault ).AddTo(graph) let rand () = G.Point.Random(30., 600., 30., 300.) m |> Seq.iter (fun (parent, adjs) -> node parent <| rand () |> ignore adjs |> Seq.iter (fun adj -> if graph.GetCell(adj) ==. null then node adj <| rand () |> ignore link parent adj |> ignore ) ) let handler (lnk : Joint.Dia.Cell, _: obj, opt : obj) = if lnk.IsLink() then let lnk = lnk :?> Joint.Dia.Link let sid = lnk.SourceConnection.Id let tid = lnk.TargetConnection.Id if opt?ui && sid <> JS.Undefined && tid <> JS.Undefined then lnk.Remove() link sid tid |> ignore graph.OnChangeSource(handler) graph.OnChangeTarget(handler) let pathLinks = ResizeArray<Joint.Dia.Link>() let hidePath () = JQuery.Of("#path").Text("").Ignore pathLinks |> Seq.iter (fun link -> link.Attr(Attrs.Value.LinkDefault) |> ignore link.Labels <- [||] ) let showPath (path : string []) = JQuery.Of("#path").Text(path.JS.Join(" -> ")).Ignore if not <| Array.isEmpty path then let p = Array.zip path.[0..path.Length - 2] path.[1..] p |> Array.iteri (fun i (s, t) -> let id = Array.sort [|s;t|] let lnk = graph.GetCell(id.JS.Join()) :?> Joint.Dia.Link lnk.Label(0, Label(0.5, New [ "text" => New ["text" => sprintf " %d " (i + 1); "font-size" => 10; "fill" => "white"] "rect" => New ["rx" => 8; "ry" => 8; "fill" => "black"; "stroke" => "black"; "stroke-width" => 5] ] ) ) lnk.Attr(Attrs.Value.LinkHighlighted) |> ignore pathLinks.Add(lnk) ) let selected : Joint.Dia.Cell ref = ref null let editMode = ref false let directed = ref false paper.OnCellPointerDown(fun (cellView, _, _, _) -> if not !editMode && not <| cellView.Model.IsLink() then match !selected with | null -> () | sel -> sel.Attr(Attrs.Value.ElementDefault) |> ignore selected := cellView.Model (!selected).Attr(Attrs.Value.ElementSelected) |> ignore hidePath () ) paper.OnCellMouseOver(fun (cellView, evt) -> if not !editMode && not <| cellView.Model.IsLink() && cellView.Model <> !selected then match !selected with | null -> () | sel -> let path = graph.ShortestPath(sel, cellView.Model, ShortestPathConfig(Directed = !directed)) showPath path cellView.Model.Attr(Attrs.Value.ElementHighlighted) |> ignore ) paper.OnCellMouseOut(fun (cellView, evt) -> if not !editMode && not <| cellView.Model.IsLink() && cellView.Model <> !selected then cellView.Model.Attr(Attrs.Value.ElementDefault) |> ignore hidePath () ) JQuery.Of("#opt-directed").Change(fun el evt -> directed := JQuery.Of(evt.Target).Is(":checked") graph.GetLinks () |> Array.iter (fun lnk -> if !directed then lnk.Attr(Attrs.Value.LinkDefaultDirected) |> ignore else lnk.RemoveAttr(".marker-target") |> ignore ) ).Ignore JQuery.Of("#opt-edit").Change(fun el evt -> editMode := JQuery.Of(evt.Target).Is(":checked") graph.GetElements() |> Array.iter (fun el -> if !editMode then el.Attr("circle/magnet", true).Attr("text/pointer-events", "none") |> ignore else el.RemoveAttr("circle/magnet").RemoveAttr("text/pointer-events") |> ignore ) ).Ignore let fresh = let c = ref 1 fun () -> incr c !c paper.OnBlankPointerDblClick(fun (evt : Dom.Event, x, y) -> if !editMode then let guid = "n" + string (fresh ()) let nd = node guid <| SimplePoint(x, y) nd.Attr("circle/magnet", true).Attr("text/pointer-events", "none") |> ignore )
<html> <head> <title></title> </head> <body> <div class="example shorter_path_finder"> <div class="options"> <label>Directed graph<input type="checkbox" id="opt-directed" /></label> <label> Edit mode<input type="checkbox" id="opt-edit" /> <p id="edit-mode-help"> Double-click a blank paper area to create new nodes. Drag the text of nodes to create new edges. </p> </label> </div> <pre id="path" style="position: absolute" ></pre> <div id="paper" style="margin-top:15px" class="paper"></div> </div><!--end example--> <!--[BODY]--> </body> </html>