f41b982009-05-07Martin Stjernholm // This is a roxen module. Copyright © 2000 - 2009, Roxen IS.
511b1d2000-05-16Martin Nilsson // By Martin Nilsson #include <module.h> inherit "module";
0917d32013-03-04Anders Johansson constant cvs_version = "$Id$";
67f1b62001-02-10Martin Nilsson constant thread_safe = 1;
511b1d2000-05-16Martin Nilsson 
b3281f2000-09-10Martin Nilsson constant module_type = MODULE_TAG;
bc0fa02001-03-08Per Hedbor constant module_name = "Tags: Verified form";
d0d7392005-10-06Jonas Wallden constant module_doc = "Creates a self-verifying form.";
511b1d2000-05-16Martin Nilsson 
37b0122002-09-11Martin Stjernholm // maxlength is excluded so that it gets exported. value is included // since not all widgets have a value attribute, and those who do add // it themselves.
828db72013-09-24Pontus Rodling constant ARGS=(< "type", "min", "max", "scope", "trim",
02d64f2003-10-07Anders Johansson  "regexp", "glob", "minlength", "case", "date",
05f02d2003-01-07Anders Johansson  "mode", "fail-if-failed", "ignore-if-false", "ignore-if-gone",
0d8a802004-01-27Anders Johansson  "ignore-if-failed", "ignore-if-verified", "optional", "value", "disable-domain-check", >);
511b1d2000-05-16Martin Nilsson 
828db72013-09-24Pontus Rodling // pass along some HTML5-specific attributes (<type>:<attribute>)
89bfbc2014-01-24Tobias Liin constant HTML5_ARGS = (< "number:min", "number:max", "range:min", "range:max" >);
828db72013-09-24Pontus Rodling  constant HTML5_TYPES = (< "number", "email", "url", "tel", "date", "datetime", "datetime-local", "search", "month", "week", "time", "color", "range", >);
2f547a2000-09-14Martin Nilsson constant forbidden = ({"\\", ".", "[", "]", "^", "$", "(", ")", "*", "+", "|"}); constant allowed = ({"\\\\", "\\.", "\\[", "\\]", "\\^", "\\$", "\\(", "\\)", "\\*", "\\+", "\\|"});
511b1d2000-05-16Martin Nilsson 
67f1b62001-02-10Martin Nilsson Parser.HTML verified; Parser.HTML failed; void create() { verified = Parser.HTML()-> add_containers( ([ "verified" : lambda(Parser.HTML p, mapping m, string c) { return c; }, "failed" : "" ]) ); failed = Parser.HTML()-> add_containers( ([ "failed" : lambda(Parser.HTML p, mapping m, string c) { return c; }, "verified" : "" ]) ); }
2f547a2000-09-14Martin Nilsson class VInputFrame { inherit RXML.Frame; string scope_name; mapping vars;
511b1d2000-05-16Martin Nilsson 
2f547a2000-09-14Martin Nilsson  object var;
511b1d2000-05-16Martin Nilsson 
2f547a2000-09-14Martin Nilsson  array do_enter(RequestID id) { scope_name=args->scope||"vinput";
511b1d2000-05-16Martin Nilsson 
0035372000-08-25Martin Nilsson #ifdef VFORM_COMPAT
2f547a2000-09-14Martin Nilsson  if(args->is) { switch(args->is) { case "int": args->type="int"; break; case "float": args->type="float"; break; case "mail": args->type="email"; break; case "date": args->type="date"; break; case "upper-alpha": args->regexp="^[A-Z]*$"; break; case "lower-aplha": args->regexp="^[a-z]*$"; break; case "upper-alpha-num": args->regexp="^[A-Z0-9]*$"; break; case "lower-alpha-num": args->regexp="^[a-z0-9]*$"; break; } m_delete(args, "is"); } if(args->filter) { args->regexp="^["+args->filter+"]*$"; m_delete(args, "filter"); }
0035372000-08-25Martin Nilsson #endif
511b1d2000-05-16Martin Nilsson 
828db72013-09-24Pontus Rodling  int(0..1) no_html5 = 0;
73866a2001-01-26Martin Nilsson  var = id->misc->vform_objects[args->name];
2f547a2000-09-14Martin Nilsson  switch(args->type) {
828db72013-09-24Pontus Rodling  case "number": // fall through
2f547a2000-09-14Martin Nilsson  case "int":
73866a2001-01-26Martin Nilsson  if(!var) var=Variable.Int(args->value||"");
39111f2004-10-20Martin Stjernholm  // FIXME: Should check invalid integer formats in min and max. var->set_range(args->min ? (int)args->min : Variable.no_limit, args->max ? (int)args->max : Variable.no_limit);
2f547a2000-09-14Martin Nilsson  break; case "float":
73866a2001-01-26Martin Nilsson  if(!var) var=Variable.Float(args->value||"");
39111f2004-10-20Martin Stjernholm  // FIXME: Should check invalid float formats in min and max. var->set_range(args->min ? (float)args->min : Variable.no_limit, args->max ? (float)args->max : Variable.no_limit);
2f547a2000-09-14Martin Nilsson  break; case "email":
73866a2001-01-26Martin Nilsson  if(!var) var=Variable.Email(args->value||"");
5adf512000-09-17Martin Nilsson  if(args["disable-domain-check"]) var->disable_domain_check();
2f547a2000-09-14Martin Nilsson  break;
828db72013-09-24Pontus Rodling  case "datetime": case "datetime-local": if (!args["date"]) args["date"] = "%Y-%M-%DT%h:%m"; // fall through
2f547a2000-09-14Martin Nilsson  case "date":
828db72013-09-24Pontus Rodling  if(!var) var=Variable.Date(args->value||""); if(args["date"]) { // Disable HTML5 if date format is incompatible if (args["date"] != "%Y-%M-%D" && args["date"] != "%Y-%M-%DT%h:%m") no_html5 = 1; var->set_date_type( args->date ); } break;
2cd3212000-12-19Martin Nilsson  case "image":
73866a2001-01-26Martin Nilsson  if(!var) var=Variable.Image( args->value||"", 0, 0, 0 );
2cd3212000-12-19Martin Nilsson  break;
d25fde2000-10-17Per Hedbor // case "upload":
73866a2001-01-26Martin Nilsson // if(!var) var=Variable.Upload( args->value||"", 0, 0, 0 );
d25fde2000-10-17Per Hedbor // break;
2cd3212000-12-19Martin Nilsson  case "password":
73866a2001-01-26Martin Nilsson  if(!var) var=Variable.VerifiedPassword(args->value||"");
2f547a2000-09-14Martin Nilsson  case "text":
2cd3212000-12-19Martin Nilsson  if(!var) var=Variable.VerifiedText(args->value||"");
828db72013-09-24Pontus Rodling  case "color": // fall through case "tel": // ... case "week": case "month": case "time": case "search": case "url": case "range":
2f547a2000-09-14Martin Nilsson  case "string": if(!var) var=Variable.VerifiedString(args->value||"");
b37cfe2007-01-11 Erik Dahl  var->clear_verifications();
2f547a2000-09-14Martin Nilsson  if(args->regexp) var->add_regexp(args->regexp); if(args->glob) var->add_glob(args->glob); if(args->minlength) var->add_minlength((int)args->minlength); if(args->maxlength) var->add_maxlength((int)args->maxlength); if(args->case=="upper") var->add_upper(); else if(args->case=="lower") var->add_lower(); // Shortcuts if(args->equal) var->add_regexp( "^" + replace(args->equal, forbidden, allowed) + "$" ); if(args->is=="empty") var->add_glob(""); break;
04071d2002-01-07Martin Stjernholm  case 0: RXML.parse_error("There is no type argument.\n");
2cd3212000-12-19Martin Nilsson  default: RXML.parse_error("There is no type %s.\n", args->type);
2f547a2000-09-14Martin Nilsson  }
511b1d2000-05-16Martin Nilsson 
d25fde2000-10-17Per Hedbor  var->set_path( args->name );
4968532007-01-12 Erik Dahl 
6cfda62007-01-18 Erik Dahl  if ( !id->real_variables["__clear"] ) { if (args->optional && id->real_variables[args->name] && id->real_variables[args->name][0] == "") { var->set_warning(0); var->low_set (""); } else if(id->real_variables[args->name] && !(args->optional && id->real_variables[args->name][0]=="") ) { if(args->trim) id->real_variables[args->name][0] = String.trim_all_whites(id->real_variables[args->name][0]); var->set_from_form( id, 1 ); }
4968532007-01-12 Erik Dahl  }
828db72013-09-24Pontus Rodling  string type = !no_html5 && HTML5_TYPES[args->type] && args->type;
2f547a2000-09-14Martin Nilsson  mapping new_args=([]); foreach(indices(args), string arg)
828db72013-09-24Pontus Rodling  if(!ARGS[arg] || (type && HTML5_ARGS[type + ":" + arg])) new_args[arg]=args[arg]; if (type) new_args->type = type;
0035372000-08-25Martin Nilsson 
2f547a2000-09-14Martin Nilsson  vars=([ "input":var->render_form(id, new_args) ]);
5adf512000-09-17Martin Nilsson  if(var->get_warnings()) vars->warning=var->get_warnings();
73866a2001-01-26Martin Nilsson  id->misc->vform_objects[args->name] = var;
2f547a2000-09-14Martin Nilsson  return 0; }
511b1d2000-05-16Martin Nilsson 
2f547a2000-09-14Martin Nilsson  array do_return(RequestID id) {
5adf512000-09-17Martin Nilsson  int ok=!var->get_warnings();
2f547a2000-09-14Martin Nilsson  int show_err=1;
05f02d2003-01-07Anders Johansson  if((args["fail-if-failed"] && id->misc->vform_failed[args["fail-if-failed"]]) || (args["ignore-if-gone"] && !id->real_variables[args->name]))
2f547a2000-09-14Martin Nilsson  ok=1;
6f38572002-12-17Anders Johansson  if((!id->real_variables[args->name] && !args["ignore-if-gone"]) ||
2f547a2000-09-14Martin Nilsson  (args["ignore-if-false"] && !id->misc->vform_ok) ||
0909d62001-02-11Martin Nilsson  id->real_variables["__reload"] || id->real_variables["__clear"] ||
2f547a2000-09-14Martin Nilsson  (args["ignore-if-failed"] && id->misc->vform_failed[args["ignore-if-failed"]]) || (args["ignore-if-verified"] && id->misc->vform_verified[args["ignore-if-verified"]]) ) { ok=0; show_err=0; }
511b1d2000-05-16Martin Nilsson 
2f547a2000-09-14Martin Nilsson  if(ok) { id->misc->vform_verified[args->name]=1; verified_result(id); return 0; }
0035372000-08-25Martin Nilsson 
2f547a2000-09-14Martin Nilsson  id->misc->vform_failed[args->name]=1; if(show_err) failed_result(id);
5adf512000-09-17Martin Nilsson  else { m_delete(args, "warning");
2f547a2000-09-14Martin Nilsson  verified_result(id);
5adf512000-09-17Martin Nilsson  }
2f547a2000-09-14Martin Nilsson  id->misc->vform_ok = 0; return 0; }
511b1d2000-05-16Martin Nilsson 
2f547a2000-09-14Martin Nilsson  void verified_result(RequestID id ) // Create a tag result without error response. { switch(args->mode||"after") { case "complex":
67f1b62001-02-10Martin Nilsson  result = verified->clone()->finish(content)->read();
2f547a2000-09-14Martin Nilsson  break; case "before": case "after": default: result = RXML.get_var("input"); } }
511b1d2000-05-16Martin Nilsson 
2f547a2000-09-14Martin Nilsson  void failed_result(RequestID id) // Creates a tag result with widget and error response. { switch(args->mode||"after") { case "complex":
67f1b62001-02-10Martin Nilsson  result = failed->clone()->finish(content)->read();
2f547a2000-09-14Martin Nilsson  break; case "before": result = content + var->render_form(id, args);
c4bec82008-05-05Mathias Södermark  break;
2f547a2000-09-14Martin Nilsson  case "after": default: result = RXML.get_var("input") + content;
511b1d2000-05-16Martin Nilsson  } }
2f547a2000-09-14Martin Nilsson } class VInput { inherit RXML.Tag; constant name = "vinput"; mapping(string:RXML.Type) req_arg_types = ([ "name":RXML.t_text(RXML.PEnt) ]); class Frame { inherit VInputFrame; } } class TagWizzVInput {
1696152001-01-06Martin Nilsson  inherit RXML.Tag;
2f547a2000-09-14Martin Nilsson  constant name="wizz"; constant plugin_name="vinput";
1696152001-01-06Martin Nilsson  RXML.Tag get_tag() { return TagVInput(); } class TagVInput { inherit VInput; class Frame { inherit VInputFrame; array do_enter(RequestID id) { id->misc->vform_ok = id->misc->wizard->verify?id->misc->wizard->verify_ok:1; if(!id->misc->vform_verified) { id->misc->vform_verified=(<>); id->misc->vform_failed=(<>);
73866a2001-01-26Martin Nilsson  id->misc->vform_objects=([]);
1696152001-01-06Martin Nilsson  id->misc->vform_xml = !args->noxml; } ::do_enter(id); return 0; } array do_return(RequestID id) { ::do_return(id); id->misc->wizard->verify_ok = id->misc->vform_ok; return 0; } }
2f547a2000-09-14Martin Nilsson  } } class TagVForm { inherit RXML.Tag; constant name = "vform";
61b3b52016-01-20Henrik Grubbström (Grubba)  // Should disable caching since this module makes heavy use of
f66e972001-08-22Martin Stjernholm  // id->misc, which isn't intercepted by the cache system. But then // again, disabling the cache can be just as bad, so we let it be a // known misfeature that some combinations of vform and the <cache> // tag fails (just as it always has been, btw). //constant flags = RXML.FLAG_DONT_CACHE_RESULT;
57d0482001-08-21Martin Stjernholm 
2f547a2000-09-14Martin Nilsson  class TagVInput { inherit VInput; }
511b1d2000-05-16Martin Nilsson 
5b3d432000-09-14Martin Nilsson  class TagVSelect {
511b1d2000-05-16Martin Nilsson  inherit RXML.Tag; constant name = "vselect";
89034d2000-07-17Martin Nilsson  mapping(string:RXML.Type) req_arg_types = ([ "name":RXML.t_text(RXML.PEnt) ]);
511b1d2000-05-16Martin Nilsson  class Frame { inherit RXML.Frame; array do_return(RequestID id) { int ok=1;
a85a4b2005-02-08Marcus Wellhardh  if(args->not && id->real_variables[args->name] && id->real_variables[args->name][0] == args->not) ok = 0;
511b1d2000-05-16Martin Nilsson  m_delete(args, "not"); if(ok) { id->misc->vform_verified[args->name]=1;
e18b3d2000-08-22Martin Nilsson  result = RXML.t_xml->format_tag("select", args, content);
511b1d2000-05-16Martin Nilsson  } else { id->misc->vform_failed[args->name]=1; id->misc->vform_ok = 0; //Create error message
d0d7392005-10-06Jonas Wallden  string mode = args->mode || "after"; m_delete(args, "mode"); switch(mode) {
511b1d2000-05-16Martin Nilsson  case "complex": // not working...
d0d7392005-10-06Jonas Wallden  result = parse_html(content, ([ ]), ([ "failed" : lambda(string t, mapping m, string c) { return c; }, "verified" : "" ]) );
511b1d2000-05-16Martin Nilsson  break; case "before":
d0d7392005-10-06Jonas Wallden  string error = parse_html(content, ([ ]), ([ "error-message" : lambda(string t, mapping m, string c) { return c; }, "option" : "" ]) );
e18b3d2000-08-22Martin Nilsson  result = error + RXML.t_xml->format_tag("select", args, content);
511b1d2000-05-16Martin Nilsson  case "after": default:
d0d7392005-10-06Jonas Wallden  error = parse_html(content, ([]), ([ "error-message" : lambda(string t, mapping m, string c) { return c; }, "option" : "" ]) );
e18b3d2000-08-22Martin Nilsson  result = RXML.t_xml->format_tag("select", args, content) + error;
511b1d2000-05-16Martin Nilsson  } } return 0; } } } class TagReload { inherit RXML.Tag; constant name = "reload";
1b2d742001-10-08Anders Johansson  constant flags = RXML.FLAG_EMPTY_ELEMENT;
511b1d2000-05-16Martin Nilsson  class Frame { inherit RXML.Frame;
e18b3d2000-08-22Martin Nilsson  array do_return(RequestID id) {
511b1d2000-05-16Martin Nilsson  if(!args->type) args->type = "submit"; args->name="__reload";
e18b3d2000-08-22Martin Nilsson  result = Roxen.make_tag("input", args, id->misc->vform_xml);
511b1d2000-05-16Martin Nilsson  return 0; } } } class TagVerifyFail { inherit RXML.Tag; constant name = "verify-fail";
1b2d742001-10-08Anders Johansson  constant flags = RXML.FLAG_EMPTY_ELEMENT;
511b1d2000-05-16Martin Nilsson  class Frame { inherit RXML.Frame; array do_return(RequestID id) { id->misc->vform_ok = 0; if(args->name) { id->misc->vform_failed[args->name]=1; id->misc->vform_verified[args->name]=0; } return 0; } } }
6a89172001-10-24Jens Utbult  class TagVerifyOk { inherit RXML.Tag; constant name = "verify-ok"; constant flags = RXML.FLAG_EMPTY_ELEMENT; class Frame { inherit RXML.Frame; array do_return(RequestID id) { if(args->name) { id->misc->vform_failed[args->name] = 0; id->misc->vform_verified[args->name] = 1; if( !sizeof(id->misc->vform_failed) ) id->misc->vform_ok = 1; } else id->misc->vform_ok = 1; return 0; } } }
511b1d2000-05-16Martin Nilsson  class TagClear { inherit RXML.Tag; constant name = "clear";
1b2d742001-10-08Anders Johansson  constant flags = RXML.FLAG_EMPTY_ELEMENT;
511b1d2000-05-16Martin Nilsson  class Frame { inherit RXML.Frame;
e18b3d2000-08-22Martin Nilsson  array do_return(RequestID id) {
511b1d2000-05-16Martin Nilsson  if(!args->type) args->type = "submit"; args->name="__clear";
e18b3d2000-08-22Martin Nilsson  result = Roxen.make_tag("input", args, id->misc->vform_xml);
511b1d2000-05-16Martin Nilsson  return 0; } } } class TagIfVFailed { inherit RXML.Tag; constant name = "if"; constant plugin_name = "vform-failed"; int eval(string ind, RequestID id) { if(!ind || !sizeof(ind)) return !id->misc->vform_ok;
1bb73b2002-05-23Marcus Wellhardh  if(!id->real_variables[ind]) return 0;
511b1d2000-05-16Martin Nilsson  return id->misc->vform_failed[ind]; } } class TagIfVVerified { inherit RXML.Tag; constant name = "if"; constant plugin_name = "vform-verified"; int eval(string ind, RequestID id) { if(!ind || !sizeof(ind)) return id->misc->vform_ok; return id->misc->vform_verified[ind]; } }
57d0482001-08-21Martin Stjernholm  // This tag set can probably be shared, but I don't know for sure. /mast
dd9a412001-08-24Martin Stjernholm  RXML.TagSet internal = RXML.TagSet (this_module(), "internal",
57d0482001-08-21Martin Stjernholm  ({ TagVInput(), TagReload(), TagClear(), TagVSelect(), TagIfVFailed(), TagIfVVerified(), TagVerifyFail(),
6a89172001-10-24Jens Utbult  TagVerifyOk(),
57d0482001-08-21Martin Stjernholm  }) );
511b1d2000-05-16Martin Nilsson  class Frame { inherit RXML.Frame; RXML.TagSet additional_tags = internal;
73866a2001-01-26Martin Nilsson  private StateHandler.Page_state state;
511b1d2000-05-16Martin Nilsson  array do_enter(RequestID id) { id->misc->vform_ok = 1; id->misc->vform_verified=(<>); id->misc->vform_failed=(<>);
e18b3d2000-08-22Martin Nilsson  id->misc->vform_xml = !args->noxml;
0909d62001-02-11Martin Nilsson 
c453f82018-01-17Karl Gustav Sterneberg  string wizard_id = Roxen.get_wizard_id_cookie(id);
ee5bbe2016-01-20Henrik Grubbström (Grubba)  if (!sizeof(wizard_id || "")) {
19a0452018-01-19Karl Gustav Sterneberg  wizard_id = Roxen.set_wizard_id_cookie(id);
ee5bbe2016-01-20Henrik Grubbström (Grubba)  } if (wizard_id != id->variables["_roxen_wizard_id"]) { m_delete(id->real_variables, "__state"); id->misc->vform_ok = 0; id->variables["_roxen_wizard_id"] = wizard_id; }
73866a2001-01-26Martin Nilsson  state = StateHandler.Page_state(id); state->register_consumer("vform");
0909d62001-02-11Martin Nilsson  if(id->real_variables->__state) { state->use_session( StateHandler.decode_session_id(id->real_variables->__state[0]) ); state->decode(id->real_variables->__state[0]); } else state->use_session();
73866a2001-01-26Martin Nilsson  id->misc->vform_objects = state->get() || ([]);
0909d62001-02-11Martin Nilsson 
511b1d2000-05-16Martin Nilsson  return 0; } array do_return(RequestID id) { id->misc->defines[" _ok"] = id->misc->vform_ok; m_delete(id->misc, "vform_ok");
06b1bb2000-11-08Martin Nilsson  if(args["hide-if-verified"] && !sizeof(id->misc->vform_failed) &&
511b1d2000-05-16Martin Nilsson  sizeof(id->misc->vform_verified) &&
06b1bb2000-11-08Martin Nilsson  id->misc->defines[" _ok"] ) {
511b1d2000-05-16Martin Nilsson  m_delete(id->misc, "vform_verified"); m_delete(id->misc, "vform_failed");
73866a2001-01-26Martin Nilsson  m_delete(id->misc, "vform_xml");
511b1d2000-05-16Martin Nilsson  return 0; }
73866a2001-01-26Martin Nilsson  state->alter(id->misc->vform_objects); content = "<input name=\"__state\" type=\"hidden\" value=\"" +
ee5bbe2016-01-20Henrik Grubbström (Grubba)  state->encode() + "\" />\n" "<input name=\"_roxen_wizard_id\" type=\"hidden\" value=\"" + Roxen.html_encode_string(id->variables["_roxen_wizard_id"]) + "\" />\n" + content;
73866a2001-01-26Martin Nilsson  m_delete(id->misc, "vform_objects");
511b1d2000-05-16Martin Nilsson  m_delete(id->misc, "vform_verified"); m_delete(id->misc, "vform_failed");
73866a2001-01-26Martin Nilsson  m_delete(id->misc, "vform_xml");
d0d7392005-10-06Jonas Wallden  m_delete(args, "noxml"); m_delete(args, "hide-if-verified");
73866a2001-01-26Martin Nilsson 
131d572001-04-26Martin Nilsson  if(!args->method) args->method="post";
f99d272003-07-28Anders Johansson  if(!args->action) args->action=get_var("self", "page");
e18b3d2000-08-22Martin Nilsson  result = RXML.t_xml->format_tag("form", args, content);
511b1d2000-05-16Martin Nilsson  return 0; } } } TAGDOCUMENTATION; #ifdef manual constant tagdoc=([
ce8fb02001-09-21Johan Sundström "vform":({ #"<desc type='cont'><p><short>
d0d7392005-10-06Jonas Wallden  Creates a self-verifying form.</short> You can use all standard HTML input widgets in this container as well.</p>
9b03652001-03-07Kenneth Johansson 
61b3b52016-01-20Henrik Grubbström (Grubba) <p>Other tags that are related and useful are <tag>default</tag>
e36f702007-01-17 Erik Dahl and <tag>roxen-automatic-charset-variable</tag>.</p>
ce8fb02001-09-21Johan Sundström <ex-box>
5b3d432000-09-14Martin Nilsson <vform> <vinput name='mail' type='email'>&_.warning;</vinput>
9b03652001-03-07Kenneth Johansson  <input type='hidden' name='user' value='&form.userid;' />
5b3d432000-09-14Martin Nilsson  <input type='submit' />
9b03652001-03-07Kenneth Johansson </vform>
5b3d432000-09-14Martin Nilsson <then><redirect to='other_page.html' /></then> <else>No, this form is still not valid</else>
ce8fb02001-09-21Johan Sundström </ex-box>
5b3d432000-09-14Martin Nilsson </desc>
9b03652001-03-07Kenneth Johansson  <attr name='hide-if-verified'> <p>Hides the form if it is verified</p> </attr>", ([ "reload":#"<desc tag='tag'><p><short> Reload the page without variable checking.</short> </p></desc> <attr name='value' value='string'><p> The text on the button.</p> </attr>", "clear":#"<desc tag='tag'><p><short> Resets all the widgets to their initial values.</short> </p></desc> <attr name='value' value='string'><p> The text in the button.</p> </attr>", "verify-fail":#"<desc tag='tag'><p><short> If put in a vform tag, the vform will always fail.</short>This is useful e.g. if you put the verify-fail tag in an if tag. </p></desc>",
6a89172001-10-24Jens Utbult "verify-ok":#"<desc tag='tag'><p><short> If put in a vform tag, the vform will always be verified.</short>This tag is probably only useful when the name-attribute inside the tag is set. If it is it will force that specific vform-variable as verified ok even if the &lt;vinput&gt;-tag that tested the variable failed.
e60aaa2001-11-27Anders Johansson </p></desc>
6a89172001-10-24Jens Utbult  <attr name='name' value='string'><p>
e60aaa2001-11-27Anders Johansson  The name of the vform variable to force as verified ok.</p> </attr>",
6a89172001-10-24Jens Utbult 
ce8fb02001-09-21Johan Sundström "if#vform-failed":#"<desc type='plugin'><p>
9b03652001-03-07Kenneth Johansson  If used with empty argument this will be true if the complete form is failed, otherwise only if the named field failed. </p></desc>",
ce8fb02001-09-21Johan Sundström "if#vform-verified":#"<desc type='plugin'><p>
9b03652001-03-07Kenneth Johansson  If used with empty arguemnt this will be true if the complete form so far is verified, otherwise only if the named field was successfully verified. </p></desc>",
ce8fb02001-09-21Johan Sundström "vinput":({ #"<desc type='cont'><p><short>
d0d7392005-10-06Jonas Wallden  Creates a self-verifying input widget.</short>
9b03652001-03-07Kenneth Johansson </p></desc> <attr name='fail-if-failed' value='name'><p> The verification of this variable will always fail if the verification of a named variable also failed.</p>
511b1d2000-05-16Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='ignore-if-false'><p> Don't verify if the false flag i set.</p>
511b1d2000-05-16Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='ignore-if-failed' value='name'><p> Don't verify if the verification of a named variable failed.</p>
511b1d2000-05-16Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson 
6f38572002-12-17Anders Johansson <attr name='ignore-if-gone'><p> Don't verify if the variable is missing from the form scope. This is useful if the widget might be disabled. Be careful not to set this flag on all input fields since this would cause the form to verify upon first request to the page.</p> </attr>
9b03652001-03-07Kenneth Johansson <attr name='ignore-if-verified' value='name'><p> Don't verify if the verification of a named variable succeeded.</p>
511b1d2000-05-16Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='name' value='string' required='required'><p> The name of the variable that should be set.</p>
5b3d432000-09-14Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='value' value='anything'><p> The default value of this input widget.</p>
5b3d432000-09-14Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='scope' value='name' default='vinput'><p> The name of the scope that is created in this tag.</p>
5b3d432000-09-14Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='trim'><p> Trim the variable before verification.</p>
511b1d2000-05-16Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='type' value='int|float|email|date|text|string|password' required='required'><p> Set the type of the data that should be input, and hence what widget should be used and how the input should be verified.</p>
5b3d432000-09-14Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson 
66e0372001-11-26Jens Utbult <attr name='date' value='string'><p> If not specified toghether with the type=\"date\" attribute the date will be verified as an ISO-date, i.e Y-M-D. If another date format is desired it should be specified with the date-attribute.
515c452003-01-14Anders Johansson  </p>
66e0372001-11-26Jens Utbult  <p>
e51fec2002-03-12Anders Johansson  Examples:<br /> date='%Y-%M-%D %h:%m' will verify a date formatted as '2040-11-08 2:46',<br />
66e0372001-11-26Jens Utbult  date='%Y w%W %e %h:%m %p %z' will verify '1913 w4 monday 2:14 pm CET' </p>
515c452003-01-14Anders Johansson  <p>These are the format characters:</p> <xtable> <row><c><p>%Y</p></c><c><p>absolute year</p></c></row> <row><c><p>%y</p></c><c><p>dwim year (70-99 is 1970-1999, 0-69 is 2000-2069)</p></c></row> <row><c><p>%M</p></c><c><p>month (number, name or short name) (needs %y)</p></c></row> <row><c><p>%W</p></c><c><p>week (needs %y)</p></c></row> <row><c><p>%D</p></c><c><p>date (needs %y, %m)</p></c></row> <row><c><p>%d</p></c><c><p>short date (20000304, 000304)</p></c></row> <row><c><p>%a</p></c><c><p>day (needs %y)</p></c></row> <row><c><p>%e</p></c><c><p>weekday (needs %y, %w)</p></c></row> <row><c><p>%h</p></c><c><p>hour (needs %d, %D or %W)</p></c></row> <row><c><p>%m</p></c><c><p>minute (needs %h)</p></c></row> <row><c><p>%s</p></c><c><p>second (needs %m)</p></c></row> <row><c><p>%f</p></c><c><p>fraction of a second (needs %s)</p></c></row> <row><c><p>%t</p></c><c><p>short time (205314, 2053)</p></c></row> <row><c><p>%z</p></c><c><p>zone</p></c></row> <row><c><p>%p</p></c><c><p>'am' or 'pm'</p></c></row> <row><c><p>%n</p></c><c><p>empty string (to be put at the end of formats). You can also use '%*[....]' to skip some characters.</p></c></row> </xtable>
66e0372001-11-26Jens Utbult </attr>
9b03652001-03-07Kenneth Johansson <attr name='minlength' value='number'><p> Verify that the variable has at least this many characters. Only available when using the type password, string or text.</p>
511b1d2000-05-16Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='maxlength' value='number'><p> Verify that the variable has at most this many characters. Only available when using the type password, string or text.</p>
511b1d2000-05-16Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='is' value='empty'><p> Verify that the variable is empty. Pretty useless... Only available when using the type password, string or text.</p>
511b1d2000-05-16Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='glob' value='pattern'><p> Verify that the variable match a certain glob pattern. Only available when using the type password, string or text.</p>
511b1d2000-05-16Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='regexp' value='pattern'><p> Verify that the variable match a certain regexp pattern. Only available when using the type password, string or text.</p>
511b1d2000-05-16Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='case' value='upper|lower'><p> Verify that the variable is all uppercased (or all lowercased). Only available when using the type password, string or text.</p>
5b3d432000-09-14Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='equal' value='string'><p> Verify that the variable is equal to a given string. Pretty useless... Only available when using the type password, string or text.</p>
5b3d432000-09-14Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='disable-domain-check'><p> Only available when using the email type. When set the email domain will not be checked against a DNS to verify that it does exists.</p>
5adf512000-09-17Martin Nilsson </attr>
5b3d432000-09-14Martin Nilsson 
9b03652001-03-07Kenneth Johansson <attr name='mode' value='before|after|complex'><p>
80d50f2001-10-05Sara Karlsson  Select how to treat the contents of the vinput container. <i>Before</i> puts the contents before the input tag, and <i>after</i> puts it after, in the event of failed verification. If complex, use one tag
9b03652001-03-07Kenneth Johansson  <tag>verified</tag> for what should be outputted in the event of successful verification tag <tag>failed</tag> for every other event.</p>
ce8fb02001-09-21Johan Sundström <ex-box><table> <tr><td>upper</td> <vinput name='a' case='upper' mode='complex'> <verified><td bgcolor='green'>&_.input:none;</td></verified> <failed><td bgcolor='red'>&_.input:none;</td></failed>
5b3d432000-09-14Martin Nilsson </vinput></tr> <tr><td><input type='submit' /></td></tr>
ce8fb02001-09-21Johan Sundström </table></ex-box>
511b1d2000-05-16Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='min' value='number'><p> Check that the number is at least the given. Only available when using the type int or float.</p>
511b1d2000-05-16Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='max' value='number'><p>
80d50f2001-10-05Sara Karlsson  Check that the number is not greater than the given. Only available when using
9b03652001-03-07Kenneth Johansson  the type int or float.</p>
511b1d2000-05-16Martin Nilsson </attr>
9b03652001-03-07Kenneth Johansson  <attr name='optional'><p> Indicates that the variable should only be tested if it does contain something.</p> </attr>", ([
ce8fb02001-09-21Johan Sundström "&_.input;":#"<desc type='entity'><p>
9b03652001-03-07Kenneth Johansson  The input tag, in complex mode. </p></desc>",
ce8fb02001-09-21Johan Sundström "&_.warning;":#"<desc type='entity'><p>
9b03652001-03-07Kenneth Johansson  May contain a explaination of why the test failed. </p></desc>",
ce8fb02001-09-21Johan Sundström "verified":#"<desc type='cont'><p>
9b03652001-03-07Kenneth Johansson  The content will only be shown if the variable was verfied, in complex mode. </p></desc>",
ce8fb02001-09-21Johan Sundström "failed":#"<desc type='cont'><p>
9b03652001-03-07Kenneth Johansson  The content will only be shown if the variable failed to verify, in complex mode. </p></desc>" // Should this subtag exist?
ce8fb02001-09-21Johan Sundström // "vselect":"<desc type='cont'>Mail stewa@roxen.com for a description</desc>",
9b03652001-03-07Kenneth Johansson  ]) })
511b1d2000-05-16Martin Nilsson ]) }) ]); #endif