aboutsummaryrefslogtreecommitdiffhomepage
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/js/urweb.js47
-rw-r--r--lib/ur/basis.urs81
-rw-r--r--lib/ur/top.urs4
3 files changed, 103 insertions, 29 deletions
diff --git a/lib/js/urweb.js b/lib/js/urweb.js
index 2e350378..c3cab50a 100644
--- a/lib/js/urweb.js
+++ b/lib/js/urweb.js
@@ -1009,8 +1009,6 @@ function active(s) {
if (suspendScripts)
return;
- var span = document.createElement("span");
- addNode(span);
var ms = maySuspend;
maySuspend = false;
try {
@@ -1020,7 +1018,11 @@ function active(s) {
throw e;
}
maySuspend = ms;
- setInnerHTML(span, html);
+ if (html != "") {
+ var span = document.createElement("span");
+ addNode(span);
+ setInnerHTML(span, html);
+ }
}
function input(x, s, recreate, type, name) {
@@ -1111,7 +1113,7 @@ function tbx(s) {
return x;
}
-function dynClass(html, s_class, s_style) {
+function dynClass(pnode, html, s_class, s_style) {
if (suspendScripts)
return;
@@ -1119,7 +1121,7 @@ function dynClass(html, s_class, s_style) {
html = flatten(htmlCls, html);
htmlCls = htmlCls.v;
- var dummy = document.createElement("body");
+ var dummy = document.createElement(pnode);
suspendScripts = true;
dummy.innerHTML = html;
suspendScripts = false;
@@ -1150,23 +1152,23 @@ function dynClass(html, s_class, s_style) {
if (s_style) {
var htmlCls2 = s_class ? null : htmlCls;
- var x = document.createElement("script");
- x.dead = false;
- x.signal = s_style;
- x.sources = null;
- x.closures = htmlCls2;
-
- x.recreate = function(v) {
- for (var ls = x.closures; ls != htmlCls2; ls = ls.next)
+ var y = document.createElement("script");
+ y.dead = false;
+ y.signal = s_style;
+ y.sources = null;
+ y.closures = htmlCls2;
+
+ y.recreate = function(v) {
+ for (var ls = y.closures; ls != htmlCls2; ls = ls.next)
freeClosure(ls.data);
var cls = {v : null};
html.style.cssText = flatten(cls, v);
- x.closures = concat(cls.v, htmlCls2);
+ y.closures = concat(cls.v, htmlCls2);
}
- html.appendChild(x);
- populate(x);
+ html.appendChild(y);
+ populate(y);
}
}
@@ -1940,6 +1942,19 @@ function bless(s) {
}
+// Attribute name blessing
+
+function blessData(s) {
+ for (var i = 0; i < s.length; ++i) {
+ var c = s[i];
+ if (!isAlnum(c) && c != '-' && c != '_')
+ er("Disallowed character in data-* attribute name");
+ }
+
+ return s;
+}
+
+
// CSS validation
function atom(s) {
diff --git a/lib/ur/basis.urs b/lib/ur/basis.urs
index c94f2ba6..ce864563 100644
--- a/lib/ur/basis.urs
+++ b/lib/ur/basis.urs
@@ -796,11 +796,17 @@ val active : unit
val script : unit
-> tag [Code = transaction unit] head [] [] []
-val head : unit -> tag [] html head [] []
-val title : unit -> tag [] head [] [] []
-val link : unit -> tag [Id = id, Rel = string, Typ = string, Href = url, Media = string] head [] [] []
+(* Type for HTML5 "data-*" attributes. *)
+type data_attr
+val data_attr : string (* Key *) -> string (* Value *) -> data_attr
+(* This function will fail if the key doesn't meet HTML's lexical rules! *)
+val data_attrs : data_attr -> data_attr -> data_attr
-val body : unit -> tag [Onload = transaction unit, Onresize = transaction unit, Onunload = transaction unit, Onhashchange = transaction unit]
+val head : unit -> tag [Data = data_attr] html head [] []
+val title : unit -> tag [Data = data_attr] head [] [] []
+val link : unit -> tag [Data = data_attr, Id = id, Rel = string, Typ = string, Href = url, Media = string] head [] [] []
+
+val body : unit -> tag [Data = data_attr, Onload = transaction unit, Onresize = transaction unit, Onunload = transaction unit, Onhashchange = transaction unit]
html body [] []
con bodyTag = fn (attrs :: {Type}) =>
ctx ::: {Unit} ->
@@ -811,7 +817,7 @@ con bodyTagStandalone = fn (attrs :: {Type}) =>
-> [[Body] ~ ctx] =>
unit -> tag attrs ([Body] ++ ctx) [] [] []
-val br : bodyTagStandalone [Id = id]
+val br : bodyTagStandalone [Data = data_attr, Id = id]
con focusEvents = [Onblur = transaction unit, Onfocus = transaction unit]
@@ -837,8 +843,8 @@ con scrollEvents = [Onscroll = transaction unit]
con boxEvents = focusEvents ++ mouseEvents ++ keyEvents ++ resizeEvents ++ scrollEvents
con tableEvents = focusEvents ++ mouseEvents ++ keyEvents
-con boxAttrs = [Id = id, Title = string] ++ boxEvents
-con tableAttrs = [Id = id, Title = string] ++ tableEvents
+con boxAttrs = [Data = data_attr, Id = id, Title = string] ++ boxEvents
+con tableAttrs = [Data = data_attr, Id = id, Title = string] ++ tableEvents
val span : bodyTag boxAttrs
val div : bodyTag boxAttrs
@@ -865,6 +871,44 @@ val ul : bodyTag boxAttrs
val hr : bodyTag boxAttrs
+val pre : bodyTag boxAttrs
+
+(** sections **)
+val section : bodyTag boxAttrs
+val article : bodyTag boxAttrs
+val nav : bodyTag boxAttrs
+val aside : bodyTag boxAttrs
+val footer : bodyTag boxAttrs
+val header : bodyTag boxAttrs
+val main : bodyTag boxAttrs
+
+(** forms **)
+val meter : bodyTag boxAttrs
+val progress : bodyTag boxAttrs
+val output : bodyTag boxAttrs
+val keygen : bodyTag boxAttrs
+val datalist : bodyTag boxAttrs
+
+(** Interactive Elements **)
+val details : bodyTag boxAttrs
+val dialog : bodyTag boxAttrs
+val menuitem : bodyTag boxAttrs
+
+(** Grouping Content **)
+val figure : bodyTag boxAttrs
+val figcaption : bodyTag boxAttrs
+
+(** Text Level Semantics **)
+val data : bodyTag boxAttrs
+val mark : bodyTag boxAttrs
+val rp : bodyTag boxAttrs
+val rt : bodyTag boxAttrs
+val ruby : bodyTag boxAttrs
+val summary : bodyTag boxAttrs
+val time : bodyTag boxAttrs
+val wbr : bodyTag boxAttrs
+val bdi : bodyTag boxAttrs
+
val a : bodyTag ([Link = transaction page, Href = url, Target = string, Rel = string] ++ boxAttrs)
val img : bodyTag ([Alt = string, Src = url, Width = int, Height = int,
@@ -899,7 +943,7 @@ con formTag = fn (ty :: Type) (inner :: {Unit}) (attrs :: {Type}) =>
-> [[Form] ~ ctx] =>
nm :: Name -> unit
-> tag attrs ([Form] ++ ctx) inner [] [nm = ty]
-val hidden : formTag string [] [Id = string, Value = string]
+val hidden : formTag string [] [Data = data_attr, Id = string, Value = string]
val textbox : formTag string [] ([Value = string, Size = int, Placeholder = string, Source = source string, Onchange = transaction unit,
Ontext = transaction unit] ++ boxAttrs)
val password : formTag string [] ([Value = string, Size = int, Placeholder = string] ++ boxAttrs)
@@ -933,12 +977,12 @@ val fieldValue : postField -> string
val remainingFields : postField -> string
con radio = [Body, Radio]
-val radio : formTag (option string) radio [Id = id]
+val radio : formTag (option string) radio [Data = data_attr, Id = id]
val radioOption : unit -> tag ([Value = string, Checked = bool] ++ boxAttrs) radio [] [] []
con select = [Select]
val select : formTag string select ([Onchange = transaction unit] ++ boxAttrs)
-val option : unit -> tag [Value = string, Selected = bool] select [] [] []
+val option : unit -> tag [Data = data_attr, Value = string, Selected = bool] select [] [] []
val submit : ctx ::: {Unit} -> use ::: {Type}
-> [[Form] ~ ctx] =>
@@ -990,19 +1034,30 @@ val td : other ::: {Unit} -> [other ~ [Body, Tr]] => unit
-> tag ([Colspan = int, Rowspan = int] ++ tableAttrs)
([Tr] ++ other) ([Body] ++ other) [] []
+val thead : other ::: {Unit} -> [other ~ [Table]] => unit
+ -> tag tableAttrs
+ ([Table] ++ other) ([Table] ++ other) [] []
+val tbody : other ::: {Unit} -> [other ~ [Table]] => unit
+ -> tag tableAttrs
+ ([Table] ++ other) ([Table] ++ other) [] []
+val tfoot : other ::: {Unit} -> [other ~ [Table]] => unit
+ -> tag tableAttrs
+ ([Table] ++ other) ([Table] ++ other) [] []
+
(** Definition lists *)
val dl : other ::: {Unit} -> [other ~ [Body,Dl]]
=> unit
- -> tag [] ([Body] ++ other) ([Dl] ++ other) [] []
+ -> tag [Data = data_attr] ([Body] ++ other) ([Dl] ++ other) [] []
val dt : other ::: {Unit} -> [other ~ [Body,Dl]]
=> unit
- -> tag [] ([Dl] ++ other) ([Body] ++ other) [] []
+ -> tag [Data = data_attr] ([Dl] ++ other) ([Body] ++ other) [] []
val dd : other ::: {Unit} -> [other ~ [Body,Dl]]
=> unit
- -> tag [] ([Dl] ++ other) ([Body] ++ other) [] []
+ -> tag [Data = data_attr] ([Dl] ++ other) ([Body] ++ other) [] []
+
(** Aborting *)
diff --git a/lib/ur/top.urs b/lib/ur/top.urs
index 30f1eaad..2ea86dc4 100644
--- a/lib/ur/top.urs
+++ b/lib/ur/top.urs
@@ -155,6 +155,10 @@ val mapX3 : K --> tf1 :: (K -> Type) -> tf2 :: (K -> Type) -> tf3 :: (K -> Type)
-> r ::: {K} -> folder r
-> $(map tf1 r) -> $(map tf2 r) -> $(map tf3 r) -> xml ctx [] []
+(* Note that the next two functions return elements in the _reverse_ of the natural order!
+ * Such a choice interacts well with the time complexity of standard list operations.
+ * It's easy to regain the natural order by inverting a query's 'ORDER BY' condition. *)
+
val queryL : tables ::: {{Type}} -> exps ::: {Type}
-> [tables ~ exps] =>
sql_query [] [] tables exps