Chandra
view release on metacpan or search on metacpan
AV *fields;
I32 i, len;
SV *html;
const char *form_id;
STRLEN form_id_len;
char *cur_group = NULL;
int in_fieldset = 0;
form_id = SvPV(*id_svp, form_id_len);
fields = (AV *)SvRV(*fields_svp);
len = av_len(fields);
html = newSVpvs("<form class=\"chandra-form");
if (cls_svp && SvOK(*cls_svp)) {
sv_catpvs(html, " ");
sv_catsv(html, *cls_svp);
}
sv_catpvs(html, "\" id=\"");
{
SV *esc_id = _elem_escape_attr(aTHX_ form_id, form_id_len);
sv_catsv(html, esc_id);
SvREFCNT_dec(esc_id);
}
sv_catpvs(html, "\">");
for (i = 0; i <= len; i++) {
SV **fref = av_fetch(fields, i, 0);
HV *fhv;
SV **type_svp, **name_svp, **opts_svp, **grp_svp;
const char *type, *name;
STRLEN type_len, name_len;
HV *opts;
char fid[128];
int fid_len;
SV *field_html = NULL;
if (!fref || !SvROK(*fref)) continue;
fhv = (HV *)SvRV(*fref);
type_svp = hv_fetchs(fhv, "type", 0);
name_svp = hv_fetchs(fhv, "name", 0);
opts_svp = hv_fetchs(fhv, "opts", 0);
if (!type_svp || !name_svp) continue;
type = SvPV(*type_svp, type_len);
name = SvPV(*name_svp, name_len);
opts = (opts_svp && SvROK(*opts_svp)) ? (HV *)SvRV(*opts_svp) : newHV();
/* Generate field id */
fid_len = my_snprintf(fid, sizeof(fid), "%.*s-%.*s",
(int)form_id_len, form_id,
(int)name_len, name);
/* Handle group transitions */
grp_svp = hv_fetchs(fhv, "group", 0);
if (grp_svp && SvOK(*grp_svp)) {
const char *grp = SvPV_nolen(*grp_svp);
if (!cur_group || !strEQ(cur_group, grp)) {
if (in_fieldset)
sv_catpvs(html, "</fieldset>");
sv_catpvs(html, "<fieldset class=\"chandra-group\"><legend>");
{
STRLEN glen;
const char *g = SvPV(*grp_svp, glen);
SV *esc = _elem_escape_html(aTHX_ g, glen);
sv_catsv(html, esc);
SvREFCNT_dec(esc);
}
sv_catpvs(html, "</legend>");
cur_group = SvPV_nolen(*grp_svp);
in_fieldset = 1;
}
} else {
if (in_fieldset) {
sv_catpvs(html, "</fieldset>");
in_fieldset = 0;
cur_group = NULL;
}
}
/* Render field by type */
if (strEQ(type, "text") || strEQ(type, "password") ||
strEQ(type, "email") || strEQ(type, "number") ||
strEQ(type, "range") || strEQ(type, "hidden")) {
field_html = _form_render_input(aTHX_ type, name, name_len,
opts, fid, fid_len);
} else if (strEQ(type, "select")) {
field_html = _form_render_select(aTHX_ name, name_len,
opts, fid, fid_len);
} else if (strEQ(type, "textarea")) {
field_html = _form_render_textarea(aTHX_ name, name_len,
opts, fid, fid_len);
} else if (strEQ(type, "checkbox")) {
field_html = _form_render_checkbox(aTHX_ name, name_len,
opts, fid, fid_len);
} else if (strEQ(type, "radio")) {
field_html = _form_render_radio(aTHX_ name, name_len,
opts, fid, fid_len);
}
if (field_html) {
sv_catsv(html, field_html);
SvREFCNT_dec(field_html);
}
}
if (in_fieldset)
sv_catpvs(html, "</fieldset>");
/* Submit button */
if (submit_svp && SvOK(*submit_svp)) {
STRLEN slen;
const char *slbl = SvPV(*submit_svp, slen);
SV *esc = _elem_escape_html(aTHX_ slbl, slen);
sv_catpvs(html, "<div class=\"chandra-field chandra-field-submit\">"
"<button type=\"submit\" class=\"chandra-submit\">");
sv_catsv(html, esc);
sv_catpvs(html, "</button></div>");
SvREFCNT_dec(esc);
}
sv_catpvs(html, "</form>");
RETVAL = html;
}
OUTPUT:
RETVAL
# ---- bind_js() - returns the JavaScript needed for two-way binding ----
( run in 0.798 second using v1.01-cache-2.11-cpan-2398b32b56e )