diff options
-rw-r--r-- | lib/js/urweb.js | 13 | ||||
-rw-r--r-- | lib/ur/basis.urs | 5 | ||||
-rw-r--r-- | lib/ur/json.ur | 4 | ||||
-rw-r--r-- | src/css.sml | 1 | ||||
-rw-r--r-- | src/monoize.sml | 4 | ||||
-rw-r--r-- | tests/cradio.py | 33 | ||||
-rw-r--r-- | tests/cradio.ur | 26 | ||||
-rw-r--r-- | tests/cradio.urp | 3 | ||||
-rw-r--r-- | tests/cradio.urs | 1 | ||||
-rwxr-xr-x | tests/driver.sh | 2 | ||||
-rw-r--r-- | tests/jsonTest.ur | 2 |
11 files changed, 90 insertions, 4 deletions
diff --git a/lib/js/urweb.js b/lib/js/urweb.js index d8198ed0..99b45ec9 100644 --- a/lib/js/urweb.js +++ b/lib/js/urweb.js @@ -1205,6 +1205,19 @@ function time(s, name) { return inpt("time", s, name); } +function crad(s) { + if (suspendScripts) + return; + + var x = input(document.createElement("input"), s, + function(x) { return function(v) { x.checked = (x.value === v); }; }, "radio"); + x.onclick = x.onkeyup = x.oninput = x.onchange = x.onpropertychange = function() { sv(s, x.value) }; + setTimeout(function() { + x.defaultChecked = x.checked = (s.data === x.value); + }, 10); + + return x; +} function selectValue(x) { if (x.options.length == 0) diff --git a/lib/ur/basis.urs b/lib/ur/basis.urs index dc1b9b76..66cc0e50 100644 --- a/lib/ur/basis.urs +++ b/lib/ur/basis.urs @@ -1081,10 +1081,13 @@ val button : cformTag ([Value = string, Disabled = bool] ++ boxAttrs) [] val ccheckbox : cformTag ([Size = int, Source = source bool] ++ boxAttrs ++ inputAttrs') [] +val cradio : cformTag ([Source = source (option string), Value = string] ++ boxAttrs ++ inputAttrs') [] + val cselect : cformTag ([Source = source string] ++ boxAttrs ++ inputAttrs') [Cselect] val coption : unit -> tag [Value = string, Selected = bool] [Cselect, Body] [] [] [] -val ctextarea : cformTag ([Rows = int, Cols = int, Placeholder = string, Source = source string] ++ boxAttrs ++ inputAttrs) [] +val ctextarea : cformTag ([Rows = int, Cols = int, Placeholder = string, Source = source string, + Ontext = transaction unit] ++ boxAttrs ++ inputAttrs) [] (*** Tables *) diff --git a/lib/ur/json.ur b/lib/ur/json.ur index 1e3e3f39..817ec16e 100644 --- a/lib/ur/json.ur +++ b/lib/ur/json.ur @@ -52,6 +52,8 @@ fun escape s = | #"\t" => "\\t" | #"\"" => "\\\"" | #"\'" => "\\\'" + | #"\\" => "\\\\" + | #"/" => "\\/" | x => String.str ch ) ^ esc (String.suffix s 1) end @@ -100,6 +102,8 @@ fun unescape s = | #"t" => "\t" | #"\"" => "\"" | #"\'" => "\'" + | #"\\" => "\\" + | #"/" => "/" | x => error <xml>JSON unescape: Bad escape char: {[x]}</xml>) ^ unesc (i+2) diff --git a/src/css.sml b/src/css.sml index 9e50686f..17ec01d5 100644 --- a/src/css.sml +++ b/src/css.sml @@ -104,6 +104,7 @@ val tags = [("span", inline), ("cpassword", replaced), ("button", replaced), ("ccheckbox", replaced), + ("cradio", replaced), ("cselect", replaced), ("ctextarea", replaced), ("tabl", table), diff --git a/src/monoize.sml b/src/monoize.sml index 85a66e87..11c6ea31 100644 --- a/src/monoize.sml +++ b/src/monoize.sml @@ -3070,7 +3070,7 @@ fun monoExp (env, st, fm) (all as (e, loc)) = | _ => (attrs, NONE) - val dynamics = ["dyn", "ctextbox", "cpassword", "ccheckbox", "cselect", "coption", "ctextarea", "active", "script", "cemail", "csearch", "curl", "ctel", "ccolor"] + val dynamics = ["dyn", "ctextbox", "cpassword", "ccheckbox", "cradio", "cselect", "coption", "ctextarea", "active", "script", "cemail", "csearch", "curl", "ctel", "ccolor"] fun isSome (e, _) = case e of @@ -3560,6 +3560,8 @@ fun monoExp (env, st, fm) (all as (e, loc)) = | "ctime" => cinput ("time", "time") | "ccheckbox" => cinput ("checkbox", "chk") + | "cradio" => cinput ("radio", "crad") + | "cselect" => (case List.find (fn ("Source", _, _) => true | _ => false) attrs of NONE => diff --git a/tests/cradio.py b/tests/cradio.py new file mode 100644 index 00000000..cc075593 --- /dev/null +++ b/tests/cradio.py @@ -0,0 +1,33 @@ +import unittest +import base + +class Suite(base.Base): + def test_1(self): + """Test case 1""" + self.start("Cradio/main") + txt = self.xpath('div[1]').text + self.assertEqual("Hello, I'm B. I'll be your waiter for this evening.", txt) + txt2 = self.xpath('div[2]').text + self.assertEqual('Value:', txt2) + el1 = self.xpath('label[1]/input') + el2 = self.xpath('label[2]/input') + self.assertEqual(False, el1.is_selected()) + self.assertEqual(True, el2.is_selected()) + el1.click() + alert = self.driver.switch_to.alert + self.assertEqual("Now it's A", alert.text) + alert.accept() + self.assertEqual(True, el1.is_selected()) + self.assertEqual(False, el2.is_selected()) + txt = self.xpath('div[1]').text + self.assertEqual("Hello, I'm A. I'll be your waiter for this evening.", txt) + txt2 = self.xpath('div[2]').text + self.assertEqual('Value:', txt2) + # now check that the second radio group works as well + el3 = self.xpath('label[4]/input') + el3.click() + alert = self.driver.switch_to.alert + alert.accept() + txt2 = self.xpath('div[2]').text + self.assertEqual('Value: Y', txt2) + self.assertEqual("Hello, I'm A. I'll be your waiter for this evening.", txt) diff --git a/tests/cradio.ur b/tests/cradio.ur new file mode 100644 index 00000000..48c04f1e --- /dev/null +++ b/tests/cradio.ur @@ -0,0 +1,26 @@ +fun main () = +s <- source (Some "B"); +r <- source None; +let + val onc = v <- get s; alert ("Now it's " ^ show v) + val onc_r = v <- get r; alert ("Changed to " ^ show v) +in + return <xml><body> + <h1>First group</h1> + + <label>Wilbur <cradio source={s} value="A" onchange={onc}/></label> + <label>Walbur <cradio source={s} value="B" onchange={onc}/></label> + + <div> + Hello, I'm <dyn signal={s <- signal s; return <xml>{[s]}</xml>}/>. I'll be your waiter for this evening. + </div> + + <h1>Second group</h1> + + <label>X <cradio source={r} value="X" onchange={onc_r}/></label> + <label>Y <cradio source={r} value="Y" onchange={onc_r}/></label> + <label>Z <cradio source={r} value="Z" onchange={onc_r}/></label> + + <div>Value: <dyn signal={r <- signal r; return <xml>{[r]}</xml>}/></div> + </body></xml> +end diff --git a/tests/cradio.urp b/tests/cradio.urp new file mode 100644 index 00000000..0681ab21 --- /dev/null +++ b/tests/cradio.urp @@ -0,0 +1,3 @@ +debug + +cradio diff --git a/tests/cradio.urs b/tests/cradio.urs new file mode 100644 index 00000000..6ac44e0b --- /dev/null +++ b/tests/cradio.urs @@ -0,0 +1 @@ +val main : unit -> transaction page diff --git a/tests/driver.sh b/tests/driver.sh index cc62644b..879c093d 100755 --- a/tests/driver.sh +++ b/tests/driver.sh @@ -21,5 +21,5 @@ fi $TESTSRV -q -a 127.0.0.1 & echo $! >> $TESTPID sleep 1 -python -m unittest $1.py +python3 -m unittest $1.py kill `cat $TESTPID` diff --git a/tests/jsonTest.ur b/tests/jsonTest.ur index 38d0d201..bce269bd 100644 --- a/tests/jsonTest.ur +++ b/tests/jsonTest.ur @@ -1,7 +1,7 @@ open Json fun main () : transaction page = return <xml><body> - <pre>{[ fromJson "\"line 1\\nline 2\"" : string ]}</pre><br/> + <pre>{[ fromJson "\"\\\\line \/ 1\\nline 2\"" : string ]}</pre><br/> <pre>{[fromJson "[1, 2, 3]" : list int]}</pre><br/> <pre>{[toJson ("hi" :: "bye\"" :: "hehe" :: [])]}</pre> </body></xml> |