<html xmlns:xforms="http://www.w3.org/2002/xforms"
xmlns:xxforms="http://orbeon.org/oxf/xml/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>XForms Password Strength Checker</title>
<xforms:model>
<xforms:instance id="password">
<instance xmlns="">
<password/>
<password-check/>
</instance>
</xforms:instance>
<xforms:instance id="conditions">
<conditions xmlns="">
<condition>8-32 characters in length</condition>
<condition>1 or more numeric characters</condition>
<condition>Mix of upper- and lower-case alphabet characters</condition>
<condition>1 or more of the following punctuation symbols: <b>!@#$%^&*()_+|=\`{}[]:";'<>?,./</b></condition>
<condition>No disallowed characters</condition>
<condition>Password valid</condition>
<condition>Password confirmed</condition>
</conditions>
</xforms:instance>
<xxforms:variable name="numbers" select="(string-to-codepoints('0') to string-to-codepoints('9'))" as="xs:integer+"/>
<xxforms:variable name="lowercase" select="(string-to-codepoints('a') to string-to-codepoints('z'))" as="xs:integer+"/>
<xxforms:variable name="uppercase" select="(string-to-codepoints('A') to string-to-codepoints('Z'))" as="xs:integer+"/>
<xxforms:variable name="special" select="string-to-codepoints('!@#$%^&*()_+|=\`{}[]:";''<>?,./')" as="xs:integer+"/>
<xxforms:variable name="all" select="($numbers, $lowercase, $uppercase, $special)" as="xs:integer+"/>
<xxforms:variable name="password" select="string-to-codepoints(instance('password')/password)" as="xs:integer+"/>
<xxforms:variable name="length" select="string-length(instance('password')/password)" as="xs:integer"/>
<xforms:bind nodeset="instance('conditions')">
<xforms:bind nodeset="condition[1]" constraint="$length ge 8 and $length lt 32"/>
<xforms:bind nodeset="condition[2]" constraint="$password = $numbers"/>
<xforms:bind nodeset="condition[3]" constraint="$password = $lowercase and $password = $uppercase"/>
<xforms:bind nodeset="condition[4]" constraint="$password = $special"/>
<xforms:bind nodeset="condition[5]" constraint="$length gt 0 and not((for $c in $password return $c = $all) = false())"/>
<xforms:bind nodeset="condition[6]" constraint="not((for $v in preceding-sibling::condition return xxforms:valid($v)) = false())"/>
<xforms:bind nodeset="condition[7]" constraint="instance('password')/password = instance('password')/password-check and xxforms:valid(preceding-sibling::condition[1])"/>
</xforms:bind>
<xforms:bind nodeset="password" constraint="xxforms:valid(instance('conditions')/condition[6])"/>
<xforms:bind nodeset="password-check" constraint="xxforms:valid(instance('conditions')/condition[7])"/>
</xforms:model>
<style type="text/css">
.xforms-label { font-weight: bold; margin-right: 1em; display: block }
.my-valid { background-color: green; color: white }
.my-invalid { background-color: red; color: white }
table td, table th { padding: .3em }
.xforms-repeat-selected-item-1 { background-color: transparent }
</style>
</head>
<body>
<p>
The following example checks a set of conditions on your password:
</p>
<table>
<tbody>
<tr>
<th>Requirement</th>
<th>Validated</th>
</tr>
<xforms:repeat nodeset="instance('conditions')/condition">
<tr>
<td>
<xforms:output value="." mediatype="text/html"/>
</td>
<td align="center" class="my-{if (xxforms:valid()) then 'valid' else 'invalid'}">
<xforms:output value="xxforms:valid()"/>
</td>
</tr>
</xforms:repeat>
</tbody>
</table>
<hr/>
<xforms:input ref="password" incremental="true">
<xforms:label>New password</xforms:label>
<xforms:alert>Password invalid</xforms:alert>
</xforms:input>
<br/>
<xforms:input ref="password-check" incremental="true">
<xforms:label>Confirm new password</xforms:label>
<xforms:alert>Password confirmation invalid</xforms:alert>
</xforms:input>
</body>
</html>