/* radio("priority", "{low: 0, med: 1, high: 2}", NULL) radio("priority", "{low: 0, med: 1, high: 2}", "{value:'2'}") */ PUBLIC void espRadio(HttpConn *conn, cchar *field, cchar *choicesString, cchar *optionsString) { MprKey *kp; MprHash *choices, *options; cchar *value, *checked; choices = httpGetOptions(choicesString); options = httpGetOptions(optionsString); value = getValue(conn, field, options); for (kp = 0; (kp = mprGetNextKey(choices, kp)) != 0; ) { checked = (smatch(kp->data, value)) ? " checked" : ""; espRender(conn, "%s <input type='radio' name='%s' value='%s'%s%s />\r\n", spascal(kp->key), field, kp->data, checked, map(conn, options)); } }
/* Control the refresh of dynamic elements in the page */ PUBLIC void espRefresh(HttpConn *conn, cchar *on, cchar *off, cchar *optionString) { MprHash *options; options = httpGetOptions(optionString); espRender(conn, "<img src='%s' " EDATA("on") "='%s' " EDATA("off") "='%s%s' class='" ESTYLE("refresh") "' />", on, on, off, map(conn, options)); }
PUBLIC void espLabel(HttpConn *conn, cchar *text, cchar *optionString) { MprHash *options; options = httpGetOptions(optionString); espRender(conn, "<span%s>%s</span>", map(conn, options), text); }
PUBLIC void espImage(HttpConn *conn, cchar *uri, cchar *optionString) { MprHash *options; options = httpGetOptions(optionString); espRender(conn, "<img src='%s'%s />", httpUri(conn, uri), map(conn, options)); }
PUBLIC void espScript(HttpConn *conn, cchar *uri, cchar *optionString) { MprHash *options; cchar *indent, *newline, *path; EspScript *sp; EspRoute *eroute; bool minified; eroute = conn->rx->route->eroute; options = httpGetOptions(optionString); if (uri) { espRender(conn, "<script src='%s' type='text/javascript'></script>", httpUri(conn, uri)); } else { minified = smatch(httpGetOption(options, "minified", 0), "true"); indent = ""; for (sp = defaultScripts; sp->name; sp++) { if (sp->option && !smatch(httpGetOption(options, sp->option, "false"), "true")) { continue; } if (sp->flags & SCRIPT_IE) { espRender(conn, "%s<!-- [if lt IE 9]>\n", indent); } path = sjoin("~/", mprGetPathBase(eroute->clientDir), sp->name, minified ? ".min.js" : ".js", NULL); uri = httpUri(conn, path); newline = sp[1].name ? "\r\n" : ""; espRender(conn, "%s<script src='%s' type='text/javascript'></script>%s", indent, uri, newline); if (sp->flags & SCRIPT_IE) { espRender(conn, "%s<![endif]-->\n", indent); } indent = " "; } } }
/* dropdown("priority", makeGrid("[{ id: 0, low: 0}, { id: 1, med: 1}, {id: 2, high: 2}]"), 0) dropdown("priority", makeGrid("[{ low: 0}, { med: 1}, {high: 2}]"), 0) dropdown("priority", makeGrid("[0, 10, 100]"), 0) Options can provide the defaultValue in a "value" property. */ PUBLIC void espDropdown(HttpConn *conn, cchar *field, EdiGrid *choices, cchar *optionString) { EdiRec *rec; MprHash *options; cchar *id, *currentValue, *selected, *value; int r; if (choices == 0) { return; } options = httpGetOptions(optionString); currentValue = getValue(conn, field, options); if (field == 0) { field = httpGetOption(options, "field", "id"); } espRender(conn, "<select name='%s'%s>\r\n", field, map(conn, options)); for (r = 0; r < choices->nrecords; r++) { rec = choices->records[r]; if (rec->nfields == 1) { value = rec->fields[0].value; } else { value = ediGetFieldValue(rec, field); } if ((id = ediGetFieldValue(choices->records[r], "id")) == 0) { id = value; } selected = (smatch(value, currentValue)) ? " selected='yes'" : ""; espRender(conn, " <option value='%s'%s>%s</option>\r\n", id, selected, value); } espRender(conn, " </select>"); }
PUBLIC void espDivision(HttpConn *conn, cchar *body, cchar *optionString) { MprHash *options; options = httpGetOptions(optionString); espRender(conn, "<div%s>%s</div>", map(conn, options), body); }
/* tabs(makeGrid("[{ name: 'Status', uri: 'pane-1' }, { name: 'Edit', uri: 'pane-2' }]")) Options: click toggle remote */ PUBLIC void espTabs(HttpConn *conn, EdiGrid *grid, cchar *optionString) { MprHash *options; EdiRec *rec; cchar *attr, *uri, *name, *klass; int r, toggle; options = httpGetOptions(optionString); httpInsertOption(options, "class", ESTYLE("tabs")); attr = httpGetOption(options, "toggle", EDATA("click")); if ((toggle = smatch(attr, "true")) != 0) { attr = EDATA("toggle"); } espRender(conn, "<div%s>\r\n <ul>\r\n", map(conn, options)); for (r = 0; r < grid->nrecords; r++) { rec = grid->records[r]; name = ediGetFieldValue(rec, "name"); uri = ediGetFieldValue(rec, "uri"); uri = toggle ? uri : httpUri(conn, uri); if ((r == 0 && toggle) || smatch(uri, conn->rx->pathInfo)) { klass = smatch(uri, conn->rx->pathInfo) ? " class='esp-selected'" : ""; } else { klass = ""; } espRender(conn, " <li %s='%s'%s>%s</li>\r\n", attr, uri, klass, name); } espRender(conn, " </ul>\r\n </div>\r\n"); }
PUBLIC void espButton(HttpConn *conn, cchar *name, cchar *value, cchar *optionString) { MprHash *options; options = httpGetOptions(optionString); espRender(conn, "<input name='%s' type='submit' value='%s'%s />", name, value, map(conn, options)); }
PUBLIC void espMail(HttpConn *conn, cchar *name, cchar *address, cchar *optionString) { MprHash *options; options = httpGetOptions(optionString); espRender(conn, "<a href='mailto:%s'%s>%s</a>", address, map(conn, options), name); }
PUBLIC void espButtonLink(HttpConn *conn, cchar *text, cchar *uri, cchar *optionString) { MprHash *options; options = httpGetOptions(optionString); httpSetOption(options, EDATA("click"), httpUri(conn, uri)); espRender(conn, "<button%s>%s</button>", map(conn, options), text); }
PUBLIC void espAnchor(HttpConn *conn, cchar *text, cchar *uri, cchar *optionString) { MprHash *options; options = httpGetOptions(optionString); text = escapeValue(text, options); espRender(conn, "<a href='%s'%s>%s</a>", uri, map(conn, options), text); }
PUBLIC void espProgress(HttpConn *conn, cchar *percent, cchar *optionString) { MprHash *options; options = httpGetOptions(optionString); httpAddOption(options, EDATA("progress"), percent); espRender(conn, "<div class='" ESTYLE("progress") "'>\r\n"); espRender(conn, " <div class='" ESTYLE("progress-inner") "'%s>%s %%</div>\r\n</div>", map(conn, options), percent); }
PUBLIC void espAlert(HttpConn *conn, cchar *text, cchar *optionString) { MprHash *options; options = httpGetOptions(optionString); httpInsertOption(options, "class", ESTYLE("alert")); text = escapeValue(text, options); espRender(conn, "<div%s>%s</div>", map(conn, options), text); }
/* checkbox field checkedValue -- Value for which the checkbox will be checked. Defaults to true. Example: checkbox("admin", "true") */ PUBLIC void espCheckbox(HttpConn *conn, cchar *field, cchar *checkedValue, cchar *optionString) { MprHash *options; cchar *value, *checked; options = httpGetOptions(optionString); value = getValue(conn, field, options); checked = scaselessmatch(value, checkedValue) ? " checked='yes'" : ""; espRender(conn, "<input name='%s' type='checkbox'%s%s value='%s' />\r\n", field, map(conn, options), checked, checkedValue); espRender(conn, " <input name='%s' type='hidden'%s value='' />", field, map(conn, options)); }
PUBLIC void form(EdiRec *record, cchar *optionString) { HttpConn *conn; MprHash *options; cchar *action, *recid, *method, *uri, *token; conn = getConn(); if (record == 0) { record = getRec(); } else { conn->record = record; } options = httpGetOptions(optionString); recid = 0; /* If record provided, get the record id. Can be overridden using options.recid */ if (record) { if (record->id && !httpGetOption(options, "recid", 0)) { httpAddOption(options, "recid", record->id); } recid = httpGetOption(options, "recid", 0); emitFormErrors(conn, record, options); } if ((method = httpGetOption(options, "method", 0)) == 0) { method = (recid) ? "PUT" : "POST"; } if (!scaselessmatch(method, "GET") && !scaselessmatch(method, "POST")) { /* All methods use POST and tunnel method in data-method */ httpAddOption(options, EDATA("method"), method); method = "POST"; } if ((action = httpGetOption(options, "action", 0)) == 0) { action = (recid) ? "@update" : "@create"; } uri = httpUri(conn, action); if (smatch(httpGetOption(options, "remote", 0), "true")) { espRender(conn, "<form method='%s' " EDATA("remote") "='%s'%s >\r\n", method, uri, map(conn, options)); } else { espRender(conn, "<form method='%s' action='%s'%s >\r\n", method, uri, map(conn, options)); } if (recid) { espRender(conn, " <input name='recid' type='hidden' value='%s' />\r\n", recid); } if (!httpGetOption(options, "insecure", 0)) { if ((token = httpGetOption(options, "securityToken", 0)) == 0) { token = httpGetSecurityToken(conn, 0); } espRender(conn, " <input name='%s' type='hidden' value='%s' />\r\n", BIT_XSRF_PARAM, token); } }
PUBLIC void espIcon(HttpConn *conn, cchar *uri, cchar *optionString) { MprHash *options; EspRoute *eroute; eroute = conn->rx->route->eroute; options = httpGetOptions(optionString); if (uri == 0) { /* Suppress favicon */ uri = "data:image/x-icon;,"; } else if (*uri == 0) { uri = sjoin("~/", mprGetPathBase(eroute->clientDir), "/images/favicon.ico", NULL); } espRender(conn, "<link href='%s' rel='shortcut icon'%s />", httpUri(conn, uri), map(conn, options)); }
PUBLIC void espStylesheet(HttpConn *conn, cchar *uri, cchar *optionString) { EspRoute *eroute; MprHash *options; cchar *indent, *newline; char **up; bool less; eroute = conn->rx->route->eroute; if (uri) { espRender(conn, "<link rel='stylesheet' type='text/css' href='%s' />", httpUri(conn, uri)); } else { indent = ""; options = httpGetOptions(optionString); less = smatch(httpGetOption(options, "type", "css"), "less"); up = less ? defaultLess : defaultCss; for (; *up; up++) { uri = httpUri(conn, sjoin("~/", mprGetPathBase(eroute->clientDir), *up, NULL)); newline = up[1] ? "\r\n" : ""; espRender(conn, "%s<link rel='stylesheet%s' type='text/css' href='%s' />%s", indent, less ? "/less" : "", uri, newline); indent = " "; } } }
PUBLIC HttpUri *httpLinkUri(HttpConn *conn, cchar *target, MprHash *options) { HttpRoute *route, *lroute; HttpRx *rx; HttpUri *uri; cchar *routeName, *action, *controller, *originalAction, *tplate; char *rest; rx = conn->rx; route = rx->route; controller = 0; if (target == 0) { target = ""; } if (*target == '@') { target = sjoin("{action: '", target, "'}", NULL); } if (*target != '{') { tplate = target; if (!options) { options = route->vars; } } else { if (options) { options = mprBlendHash(httpGetOptions(target), options); } else { options = httpGetOptions(target); } options = mprBlendHash(options, route->vars); /* Prep the action. Forms are: . @action # Use the current controller . @controller/ # Use "index" as the action . @controller/action */ if ((action = httpGetOption(options, "action", 0)) != 0) { originalAction = action; if (*action == '@') { action = &action[1]; } if (strchr(action, '/')) { controller = stok((char*) action, "/", (char**) &action); action = stok((char*) action, "/", &rest); } if (controller) { httpSetOption(options, "controller", controller); } else { controller = httpGetParam(conn, "controller", 0); } if (action == 0 || *action == '\0') { action = "list"; } if (action != originalAction) { httpSetOption(options, "action", action); } } /* Find the template to use. Strategy is this order: . options.template . options.route.template . options.action mapped to a route.template, via: . /app/STAR/action . /app/controller/action . /app/STAR/default . /app/controller/default */ if ((tplate = httpGetOption(options, "template", 0)) == 0) { if ((routeName = httpGetOption(options, "route", 0)) != 0) { routeName = expandRouteName(conn, routeName); lroute = httpLookupRoute(conn->host, routeName); } else { lroute = 0; } if (!lroute) { if ((lroute = httpLookupRoute(conn->host, actionRoute(route, controller, action))) == 0) { if ((lroute = httpLookupRoute(conn->host, actionRoute(route, "{controller}", action))) == 0) { if ((lroute = httpLookupRoute(conn->host, actionRoute(route, controller, "default"))) == 0) { lroute = httpLookupRoute(conn->host, actionRoute(route, "{controller}", "default")); } } } } if (lroute) { tplate = lroute->tplate; } } if (!tplate) { mprLog("error http", 0, "Cannot find template for URI %s", target); target = "/"; } } target = httpTemplate(conn, tplate, options); uri = httpCreateUri(target, 0); /* This was changed from: httpCreateUri(rx->uri) to rx->parsedUri. The use case was appweb: /auth/form/login which redirects using: https:///auth/form/login on localhost:4443 This must extract the existing host and port from the prior request */ uri = httpResolveUri(rx->parsedUri, 1, &uri, 0); return httpNormalizeUri(uri); }
PUBLIC void espText(HttpConn *conn, cchar *field, cchar *optionString) { textInner(conn, field, httpGetOptions(optionString)); }
PUBLIC void espTable(HttpConn *conn, EdiGrid *grid, cchar *optionString) { MprHash *options, *colOptions, *rowOptions, *thisCol; MprList *cols; EdiRec *rec; EdiField *fp; cchar *title, *width, *o, *header, *value, *sortColumn; char index[8]; int c, r, ncols, sortOrder; assert(grid); if (grid == 0) { return; } options = httpGetOptions(optionString); if (grid->nrecords == 0) { espRender(conn, "<p>No Data</p>\r\n"); return; } if (grid->flags & EDI_GRID_READ_ONLY) { grid = ediCloneGrid(grid); } if ((sortColumn = httpGetOption(options, "sort", 0)) != 0) { sortOrder = httpOption(options, "sortOrder", "ascending", 1); ediSortGrid(grid, sortColumn, sortOrder); } colOptions = httpGetOptionHash(options, "columns"); filterCols(grid, options, colOptions); if (httpOption(options, "pivot", "true", 0) != 0) { pivotTable(conn, ediPivotGrid(grid, 1), options); return; } cols = ediGetGridColumns(grid); ncols = mprGetListLength(cols); rowOptions = mprCreateHash(0, MPR_HASH_STABLE); httpSetOption(rowOptions, EDATA("click"), httpGetOption(options, EDATA("click"), 0)); httpRemoveOption(options, EDATA("click")); httpSetOption(rowOptions, EDATA("remote"), httpGetOption(options, EDATA("remote"), 0)); httpSetOption(rowOptions, EDATA("key"), httpGetOption(options, EDATA("key"), 0)); httpSetOption(rowOptions, EDATA("params"), httpGetOption(options, EDATA("params"), 0)); httpSetOption(rowOptions, EDATA("edit"), httpGetOption(options, EDATA("edit"), 0)); httpInsertOption(options, "class", ESTYLE("table")); httpInsertOption(options, "class", ESTYLE("stripe")); espRender(conn, "<table%s>\r\n", map(conn, options)); /* Table header */ if (httpOption(options, "showHeader", "true", 1)) { espRender(conn, " <thead>\r\n"); if ((title = httpGetOption(options, "title", 0)) != 0) { espRender(conn, " <tr class='" ESTYLE("table-title") "'><td colspan='%s'>%s</td></tr>\r\n", mprGetListLength(cols), title); } espRender(conn, " <tr class='" ESTYLE("table-header") "'>\r\n"); rec = grid->records[0]; for (c = 0; c < ncols; c++) { assert(c <= rec->nfields); fp = &rec->fields[c]; width = ((o = httpGetOption(options, "width", 0)) != 0) ? sfmt(" width='%s'", o) : ""; thisCol = mprLookupKey(colOptions, itosbuf(index, sizeof(index), c, 10)); header = httpGetOption(thisCol, "header", spascal(fp->name)); espRender(conn, " <th%s>%s</th>\r\n", width, header); } espRender(conn, " </tr>\r\n </thead>\r\n"); } espRender(conn, " <tbody>\r\n"); /* Table body data */ for (r = 0; r < grid->nrecords; r++) { rec = grid->records[r]; httpSetOption(rowOptions, "id", rec->id); espRender(conn, " <tr%s>\r\n", map(conn, rowOptions)); for (c = 0; c < ncols; c++) { fp = &rec->fields[c]; thisCol = mprLookupKey(colOptions, itosbuf(index, sizeof(index), c, 10)); if (httpGetOption(thisCol, "align", 0) == 0) { if (fp->type == EDI_TYPE_INT || fp->type == EDI_TYPE_FLOAT) { if (!thisCol) { thisCol = mprCreateHash(0, MPR_HASH_STABLE); } httpInsertOption(thisCol, "align", "right"); } } value = formatValue(fp, thisCol); espRender(conn, " <td%s>%s</td>\r\n", map(conn, thisCol), value); } espRender(conn, " </tr>\r\n"); } espRender(conn, " </tbody>\r\n</table>\r\n"); }
PUBLIC HttpUri *httpLinkUri(HttpConn *conn, cchar *target, MprHash *options) { HttpRoute *route, *lroute; HttpRx *rx; HttpUri *uri; cchar *routeName, *action, *controller, *originalAction, *tplate; char *rest; assert(conn); rx = conn->rx; route = rx->route; controller = 0; if (target == 0) { target = ""; } if (*target == '@') { target = sjoin("{action: '", target, "'}", NULL); } if (*target != '{') { tplate = target; if (!options) { options = route->vars; } } else { if (options) { options = mprBlendHash(httpGetOptions(target), options); } else { options = httpGetOptions(target); } options = mprBlendHash(options, route->vars); /* Prep the action. Forms are: . @action # Use the current controller . @controller/ # Use "index" as the action . @controller/action */ if ((action = httpGetOption(options, "action", 0)) != 0) { originalAction = action; if (*action == '@') { action = &action[1]; } if (strchr(action, '/')) { controller = stok((char*) action, "/", (char**) &action); action = stok((char*) action, "/", &rest); } if (controller) { httpSetOption(options, "controller", controller); } else { controller = httpGetParam(conn, "controller", 0); } if (action == 0 || *action == '\0') { action = "list"; } if (action != originalAction) { httpSetOption(options, "action", action); } } /* Find the template to use. Strategy is this order: . options.template . options.route.template . options.action mapped to a route.template, via: . /app/STAR/action . /app/controller/action . /app/STAR/default . /app/controller/default */ if ((tplate = httpGetOption(options, "template", 0)) == 0) { if ((routeName = httpGetOption(options, "route", 0)) != 0) { routeName = expandRouteName(conn, routeName); lroute = httpLookupRoute(conn->host, routeName); } else { lroute = 0; } if (!lroute) { if ((lroute = httpLookupRoute(conn->host, actionRoute(route, controller, action))) == 0) { if ((lroute = httpLookupRoute(conn->host, actionRoute(route, "{controller}", action))) == 0) { if ((lroute = httpLookupRoute(conn->host, actionRoute(route, controller, "default"))) == 0) { lroute = httpLookupRoute(conn->host, actionRoute(route, "{controller}", "default")); } } } } if (lroute) { tplate = lroute->tplate; } } if (!tplate) { mprLog("error http", 0, "Cannot find template for URI %s", target); target = "/"; } } target = httpTemplate(conn, tplate, options); if ((uri = httpCreateUri(target, 0)) == 0) { return 0; } return uri; }