2 people like it.
Like the snippet!
Generate an inline editor for ascx
Somewhat implementation coupled, but the ideas are pretty neat. works in linqpad, not sure what's up with this editor
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
|
open System
type Keys = {Header:string;Pascal:string;Camel:string;Field:string;DisplayAccessor:string;HiddenDom:string}
let toPascalCase s =
s
|> Seq.mapi (fun i l -> if i=0 && Char.IsLower(l) then Char.ToUpper(l) else l)
|> String.Concat
let humanize camel :string =
seq {
let pascalCased = toPascalCase camel
yield pascalCased.[0]
for l in pascalCased |> Seq.skip(1) do
if System.Char.IsUpper(l) then
yield ' '
yield l
else
yield l
}
|> String.Concat
let createKeys camel field header accessor =
let hidden = sprintf """<input type="hidden" name="%s"/>"""
{
Keys.Header=header
Field=field
DisplayAccessor = accessor field
Camel=camel
HiddenDom= hidden field
Pascal= toPascalCase camel //FromCamel
}
let AllKeys =
let formattedPositiveIntAccessor = sprintf """GetFormattedPositiveInt(Eval("%s"))"""
let defaultAccessor = sprintf """Eval("%s")"""
let reqMembersAccessor = sprintf """GetRequestedMembers(Eval("%s")) + (Convert.ToBoolean(Eval("IsQuotaCap")) ? "*" : "")"""
seq {
yield(createKeys "overQuotaCap" "OverQuotaCap" "OverQuota Cap" formattedPositiveIntAccessor)
yield(createKeys "reqCompletes" "RequestedMembers" "Requested Completes" reqMembersAccessor)
}
//
type InlineEditorComponent =
|Display
|Editor
|EditLink
|ItemChild
type ClientSelector(inlineComponent:InlineEditorComponent,keys) =
//let roles = { InlineEditorRole.Display = sprintf "%sDisplay" keys.Pascal; Editor=sprintf "%sEditor" keys.Pascal;EditLink=sprintf "%sEditLink" keys.Pascal;ItemChild=sprintf "%sItemChild" keys.Pascal}
static member private makeRole c = match c with
|Display -> sprintf "%sDisplay"
|Editor -> sprintf "%sEditor"
|EditLink -> sprintf "%sEditLink"
|ItemChild -> sprintf "%sItemChild"
static member private dataRoleSelector = sprintf "%s: '[data-role=%s]'"
member x.InlineComponent = inlineComponent
member x.Name = ClientSelector.makeRole inlineComponent keys.Pascal
member x.Role = x.Name
member x.DataRole = ClientSelector.dataRoleSelector x.Name x.Role
member x.Dom = match inlineComponent with
|Display -> sprintf """<span data-role="%s" class="fieldDisplay"><%%#%s%%></span>""" x.Role keys.DisplayAccessor
|EditLink -> sprintf """<i data-role="%s" class="onHover fa fa-pencil-square-o" title="edit"></i>""" x.Role
|Editor -> sprintf """<input data-role="%s" type="text" disabled="disabled" name="%s<%%# Eval("ProjectQuotaId") %%>" style="display:none;width:90px" value="" data-original-value="" data-quotaGroupId="<%%# Eval("ProjectQuotaId") %%>"/>""" x.Role keys.Pascal
|ItemChild-> failwithf "Can't generate dom for itemChild directly"
type HandlerArgs = {StorageKey:string; HiddenName:string; EditorSelector:string}
type InitializeHandlerArgs = {EditLinkSelector:string;ChildSelector:string;}
type ClientSelectorCollection(keys) =
let createClient com = ClientSelector(com,keys)
member x.Keys = keys
member x.Display = createClient InlineEditorComponent.Display
member x.Editor = createClient InlineEditorComponent.Editor
member x.EditLink = createClient InlineEditorComponent.EditLink
member x.ItemChild = createClient InlineEditorComponent.ItemChild
member x.Asp = sprintf """ <asp:TemplateColumn HeaderText="%s">
<ItemTemplate>
<span data-role="%s">
%s
%s
%s
</span>
</ItemTemplate>
</asp:TemplateColumn>""" keys.Header x.ItemChild.Role x.EditLink.Dom x.Display.Dom x.Editor.Dom
member x.Selectors = [
x.Display
x.Editor
x.EditLink
x.ItemChild
]
member x.JsClientSelectors =
sprintf """ %s,
%s,
%s,
%s""" x.Display.DataRole x.Editor.DataRole x.EditLink.DataRole x.ItemChild.DataRole
member x.HandlerArgs = {HandlerArgs.StorageKey=keys.Camel+"Edits"; HiddenName=keys.Camel+"Edits";EditorSelector = sprintf "%sEditor" keys.Camel}
member x.JsBeforeReq = //before save or updatePanel request starts
sprintf """beforeSavePostHandler(currentTabIsQuotaGroups, quotaGroupTabStorage, '%s', '%s', clientSelectors.%s, $qgGrid);""" x.HandlerArgs.StorageKey x.HandlerArgs.HiddenName x.HandlerArgs.EditorSelector
member x.JsInitialize = sprintf """quotaGridInlineEditsInitializeHandler(clientSelectors.%s, clientSelectors.%s, clientSelectors.%s, clientSelectors.quotaGroupIdAttr, clientSelectors.%s, quotaGroupTabStorage, '%s');""" x.EditLink.Name x.ItemChild.Name x.Editor.Name x.Display.Name x.HandlerArgs.StorageKey
for k in AllKeys do
let csColl = ClientSelectorCollection(k)
printfn "%A" (k,csColl.Asp,csColl.Selectors,csColl.JsClientSelectors,csColl.JsBeforeReq,csColl.JsInitialize)
//validation
let targetJs = """c:\development\products\app\web\lib\javascript\editproject.js"""
let targetAspx = """c:\development\products\app\web\pages\projects\editproject.aspx"""
let targetAscx = """c:\development\products\app\web\pages\projects\usercontrols\quotagroups.ascx"""
let targetJsTextValidation =
let text = System.IO.File.ReadAllText(targetJs)
let missingSelectors =
csColl.Selectors
|>Seq.map (fun x->x.DataRole)
|>Seq.filter(fun x->text.Contains(x)=false)
if Seq.isEmpty(missingSelectors)=false then failwithf "some expected .js lines were missing %A" missingSelectors
if text.Contains(csColl.JsBeforeReq)=false then failwithf ".js: missing call(s) to beforeSavePostHandler %A" csColl.JsBeforeReq
if text.Contains(csColl.JsInitialize)= false then failwithf ".js: missing call(s) to InitializeHandler %A" csColl.JsInitialize
printfn "js tests passed"
let targetAspxValidation =
let text = System.IO.File.ReadAllText(targetAspx)
if text.Contains(csColl.Keys.HiddenDom)=false then failwithf ".aspx: missing %A" csColl.Keys.HiddenDom
printfn "aspx tests passed"
let targetAscxValidation =
let text = System.IO.File.ReadAllText(targetAscx)
csColl.Selectors
|> Seq.filter (fun s-> s.InlineComponent <> InlineEditorComponent.ItemChild)
|> Seq.iter (fun s ->
if text.Contains(s.Dom) = false then failwithf ".ascx: missing %A" s.Dom
)
printfn "ascx tests passed"
()
|
namespace System
type Keys =
{Header: string;
Pascal: string;
Camel: string;
Field: string;
DisplayAccessor: string;
HiddenDom: string;}
Full name: Script.Keys
Keys.Header: string
Multiple items
val string : value:'T -> string
Full name: Microsoft.FSharp.Core.Operators.string
--------------------
type string = String
Full name: Microsoft.FSharp.Core.string
Keys.Pascal: string
Keys.Camel: string
Keys.Field: string
Keys.DisplayAccessor: string
Keys.HiddenDom: string
val toPascalCase : s:seq<char> -> string
Full name: Script.toPascalCase
val s : seq<char>
module Seq
from Microsoft.FSharp.Collections
val mapi : mapping:(int -> 'T -> 'U) -> source:seq<'T> -> seq<'U>
Full name: Microsoft.FSharp.Collections.Seq.mapi
val i : int
val l : char
type Char =
struct
member CompareTo : value:obj -> int + 1 overload
member Equals : obj:obj -> bool + 1 overload
member GetHashCode : unit -> int
member GetTypeCode : unit -> TypeCode
member ToString : unit -> string + 1 overload
static val MaxValue : char
static val MinValue : char
static member ConvertFromUtf32 : utf32:int -> string
static member ConvertToUtf32 : highSurrogate:char * lowSurrogate:char -> int + 1 overload
static member GetNumericValue : c:char -> float + 1 overload
...
end
Full name: System.Char
Char.IsLower(c: char) : bool
Char.IsLower(s: string, index: int) : bool
Char.ToUpper(c: char) : char
Char.ToUpper(c: char, culture: Globalization.CultureInfo) : char
Multiple items
type String =
new : value:char -> string + 7 overloads
member Chars : int -> char
member Clone : unit -> obj
member CompareTo : value:obj -> int + 1 overload
member Contains : value:string -> bool
member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
member EndsWith : value:string -> bool + 2 overloads
member Equals : obj:obj -> bool + 2 overloads
member GetEnumerator : unit -> CharEnumerator
member GetHashCode : unit -> int
...
Full name: System.String
--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : unit
String.Concat([<ParamArray>] values: string []) : string
(+0 other overloads)
String.Concat(values: Collections.Generic.IEnumerable<string>) : string
(+0 other overloads)
String.Concat<'T>(values: Collections.Generic.IEnumerable<'T>) : string
(+0 other overloads)
String.Concat([<ParamArray>] args: obj []) : string
(+0 other overloads)
String.Concat(arg0: obj) : string
(+0 other overloads)
String.Concat(str0: string, str1: string) : string
(+0 other overloads)
String.Concat(arg0: obj, arg1: obj) : string
(+0 other overloads)
String.Concat(str0: string, str1: string, str2: string) : string
(+0 other overloads)
String.Concat(arg0: obj, arg1: obj, arg2: obj) : string
(+0 other overloads)
String.Concat(str0: string, str1: string, str2: string, str3: string) : string
(+0 other overloads)
val humanize : camel:seq<char> -> string
Full name: Script.humanize
val camel : seq<char>
Multiple items
val seq : sequence:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Core.Operators.seq
--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>
Full name: Microsoft.FSharp.Collections.seq<_>
val pascalCased : string
val skip : count:int -> source:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.skip
Char.IsUpper(c: char) : bool
Char.IsUpper(s: string, index: int) : bool
val createKeys : camel:string -> field:string -> header:string -> accessor:(string -> string) -> Keys
Full name: Script.createKeys
val camel : string
val field : string
val header : string
val accessor : (string -> string)
val hidden : (string -> string)
val sprintf : format:Printf.StringFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
val AllKeys : seq<Keys>
Full name: Script.AllKeys
val formattedPositiveIntAccessor : (string -> string)
val defaultAccessor : (string -> string)
val reqMembersAccessor : (string -> string)
type InlineEditorComponent =
| Display
| Editor
| EditLink
| ItemChild
Full name: Script.InlineEditorComponent
union case InlineEditorComponent.Display: InlineEditorComponent
union case InlineEditorComponent.Editor: InlineEditorComponent
union case InlineEditorComponent.EditLink: InlineEditorComponent
union case InlineEditorComponent.ItemChild: InlineEditorComponent
Multiple items
type ClientSelector =
new : inlineComponent:InlineEditorComponent * keys:Keys -> ClientSelector
member DataRole : string
member Dom : string
member InlineComponent : InlineEditorComponent
member Name : string
member Role : string
static member private dataRoleSelector : (string -> string -> string)
static member private makeRole : c:InlineEditorComponent -> (string -> string)
Full name: Script.ClientSelector
--------------------
new : inlineComponent:InlineEditorComponent * keys:Keys -> ClientSelector
val inlineComponent : InlineEditorComponent
val keys : Keys
static member private ClientSelector.makeRole : c:InlineEditorComponent -> (string -> string)
Full name: Script.ClientSelector.makeRole
val c : InlineEditorComponent
static member private ClientSelector.dataRoleSelector : (string -> string -> string)
Full name: Script.ClientSelector.dataRoleSelector
val x : ClientSelector
member ClientSelector.InlineComponent : InlineEditorComponent
Full name: Script.ClientSelector.InlineComponent
member ClientSelector.Name : string
Full name: Script.ClientSelector.Name
static member private ClientSelector.makeRole : c:InlineEditorComponent -> (string -> string)
member ClientSelector.Role : string
Full name: Script.ClientSelector.Role
property ClientSelector.Name: string
member ClientSelector.DataRole : string
Full name: Script.ClientSelector.DataRole
property ClientSelector.dataRoleSelector: string -> string -> string
property ClientSelector.Role: string
member ClientSelector.Dom : string
Full name: Script.ClientSelector.Dom
val failwithf : format:Printf.StringFormat<'T,'Result> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.failwithf
type HandlerArgs =
{StorageKey: string;
HiddenName: string;
EditorSelector: string;}
Full name: Script.HandlerArgs
HandlerArgs.StorageKey: string
HandlerArgs.HiddenName: string
HandlerArgs.EditorSelector: string
type InitializeHandlerArgs =
{EditLinkSelector: string;
ChildSelector: string;}
Full name: Script.InitializeHandlerArgs
InitializeHandlerArgs.EditLinkSelector: string
InitializeHandlerArgs.ChildSelector: string
Multiple items
type ClientSelectorCollection =
new : keys:Keys -> ClientSelectorCollection
member Asp : string
member Display : ClientSelector
member EditLink : ClientSelector
member Editor : ClientSelector
member HandlerArgs : HandlerArgs
member ItemChild : ClientSelector
member JsBeforeReq : string
member JsClientSelectors : string
member JsInitialize : string
...
Full name: Script.ClientSelectorCollection
--------------------
new : keys:Keys -> ClientSelectorCollection
val createClient : (InlineEditorComponent -> ClientSelector)
val com : InlineEditorComponent
val x : ClientSelectorCollection
Multiple items
member ClientSelectorCollection.Keys : Keys
Full name: Script.ClientSelectorCollection.Keys
--------------------
type Keys =
{Header: string;
Pascal: string;
Camel: string;
Field: string;
DisplayAccessor: string;
HiddenDom: string;}
Full name: Script.Keys
member ClientSelectorCollection.Display : ClientSelector
Full name: Script.ClientSelectorCollection.Display
member ClientSelectorCollection.Editor : ClientSelector
Full name: Script.ClientSelectorCollection.Editor
member ClientSelectorCollection.EditLink : ClientSelector
Full name: Script.ClientSelectorCollection.EditLink
member ClientSelectorCollection.ItemChild : ClientSelector
Full name: Script.ClientSelectorCollection.ItemChild
member ClientSelectorCollection.Asp : string
Full name: Script.ClientSelectorCollection.Asp
property ClientSelectorCollection.ItemChild: ClientSelector
property ClientSelectorCollection.EditLink: ClientSelector
property ClientSelector.Dom: string
property ClientSelectorCollection.Display: ClientSelector
property ClientSelectorCollection.Editor: ClientSelector
member ClientSelectorCollection.Selectors : ClientSelector list
Full name: Script.ClientSelectorCollection.Selectors
member ClientSelectorCollection.JsClientSelectors : string
Full name: Script.ClientSelectorCollection.JsClientSelectors
property ClientSelector.DataRole: string
Multiple items
member ClientSelectorCollection.HandlerArgs : HandlerArgs
Full name: Script.ClientSelectorCollection.HandlerArgs
--------------------
type HandlerArgs =
{StorageKey: string;
HiddenName: string;
EditorSelector: string;}
Full name: Script.HandlerArgs
member ClientSelectorCollection.JsBeforeReq : string
Full name: Script.ClientSelectorCollection.JsBeforeReq
property ClientSelectorCollection.HandlerArgs: HandlerArgs
member ClientSelectorCollection.JsInitialize : string
Full name: Script.ClientSelectorCollection.JsInitialize
val k : Keys
val csColl : ClientSelectorCollection
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
property ClientSelectorCollection.Asp: string
property ClientSelectorCollection.Selectors: ClientSelector list
property ClientSelectorCollection.JsClientSelectors: string
property ClientSelectorCollection.JsBeforeReq: string
property ClientSelectorCollection.JsInitialize: string
val targetJs : string
val targetAspx : string
val targetAscx : string
val targetJsTextValidation : unit
val text : string
namespace System.IO
type File =
static member AppendAllLines : path:string * contents:IEnumerable<string> -> unit + 1 overload
static member AppendAllText : path:string * contents:string -> unit + 1 overload
static member AppendText : path:string -> StreamWriter
static member Copy : sourceFileName:string * destFileName:string -> unit + 1 overload
static member Create : path:string -> FileStream + 3 overloads
static member CreateText : path:string -> StreamWriter
static member Decrypt : path:string -> unit
static member Delete : path:string -> unit
static member Encrypt : path:string -> unit
static member Exists : path:string -> bool
...
Full name: System.IO.File
IO.File.ReadAllText(path: string) : string
IO.File.ReadAllText(path: string, encoding: Text.Encoding) : string
val missingSelectors : seq<string>
val map : mapping:('T -> 'U) -> source:seq<'T> -> seq<'U>
Full name: Microsoft.FSharp.Collections.Seq.map
val filter : predicate:('T -> bool) -> source:seq<'T> -> seq<'T>
Full name: Microsoft.FSharp.Collections.Seq.filter
val x : string
String.Contains(value: string) : bool
val isEmpty : source:seq<'T> -> bool
Full name: Microsoft.FSharp.Collections.Seq.isEmpty
val targetAspxValidation : unit
property ClientSelectorCollection.Keys: Keys
val targetAscxValidation : unit
val s : ClientSelector
property ClientSelector.InlineComponent: InlineEditorComponent
val iter : action:('T -> unit) -> source:seq<'T> -> unit
Full name: Microsoft.FSharp.Collections.Seq.iter
More information