Use more generic code for common table

This commit is contained in:
Andreas Öman 2008-04-21 16:44:59 +00:00
parent 63870e59cf
commit 569b1a276c
6 changed files with 266 additions and 244 deletions

View file

@ -75,68 +75,161 @@ ajaxui_escape_apostrophe(const char *content)
}
/**
* AJAX table header
* AJAX table
*/
void
ajax_table_header(http_connection_t *hc, tcp_queue_t *tq,
const char *names[], int weights[],
int scrollbar, int columnsizes[])
ajax_table_top(ajax_table_t *t, http_connection_t *hc, tcp_queue_t *tq,
const char *names[], int weights[])
{
int n = 0, i, tw = 0;
while(names[n]) {
tw += weights[n];
n++;
}
assert(n <= 20);
t->columns = n;
memset(t, 0, sizeof(ajax_table_t));
t->tq = tq;
for(i = 0; i < n; i++)
columnsizes[i] = 100 * weights[i] / tw;
t->csize[i] = 100 * weights[i] / tw;
if(scrollbar)
tcp_qprintf(tq, "<div style=\"padding-right: 20px\">");
tcp_qprintf(tq, "<div style=\"overflow: auto; width: 100%\">");
tcp_qprintf(tq, "<div style=\"padding-right: 20px\">");
tcp_qprintf(tq, "<div style=\"overflow: auto; width: 100%%\">");
for(i = 0; i < n; i++)
tcp_qprintf(tq, "<div style=\"float: left; width: %d%%\">%s</div>",
columnsizes[i], *names[i] ? names[i]: "&nbsp;");
tcp_qprintf(tq, "</div>");
if(scrollbar)
tcp_qprintf(tq, "</div>");
t->csize[i], *names[i] ? names[i]: "&nbsp;");
tcp_qprintf(tq, "</div></div><hr><div class=\"normaltable\">\r\n");
}
/**
* AJAX table row
* AJAX table new row
*/
void
ajax_table_row(tcp_queue_t *tq, const char *cells[], int columnsizes[],
int *bgptr, const char *idprefix[], const char *idpostfix)
ajax_table_row_start(ajax_table_t *t, const char *id)
{
int i = 0;
t->rowid = id;
t->rowcol = !t->rowcol;
tcp_qprintf(t->tq, "%s<div style=\"%soverflow: auto; width: 100%\">",
t->inrow ? "</div>\r\n" : "",
t->rowcol ? "background: #fff; " : "");
t->inrow = 1;
t->curcol = 0;
}
tcp_qprintf(tq, "<div style=\"%soverflow: auto; width: 100%\">",
*bgptr ? "background: #fff; " : "");
*bgptr = !*bgptr;
while(cells[i]) {
tcp_qprintf(tq,
"<div %s%s%s%s%sstyle=\"float: left; width: %d%%\">%s</div>",
idprefix && idprefix[i] ? "id=\"" : "",
idprefix && idprefix[i] ? idprefix[i] : "",
idprefix && idprefix[i] && idpostfix ? "_" : "",
idprefix && idprefix[i] && idpostfix ? idpostfix : "",
idprefix && idprefix[i] ? "\" " : "",
columnsizes[i], cells[i]);
i++;
}
tcp_qprintf(tq, "</div>\r\n");
/**
* AJAX table new row
*/
void
ajax_table_subrow_start(ajax_table_t *t)
{
tcp_qprintf(t->tq, "<div style=\"overflow: auto; width: 100%\">");
t->curcol = 0;
}
/**
* AJAX table new row
*/
void
ajax_table_subrow_end(ajax_table_t *t)
{
tcp_qprintf(t->tq, "</div>");
t->curcol = 0;
}
/**
* AJAX table new row
*/
void
ajax_table_details_start(ajax_table_t *t)
{
assert(t->inrow == 1);
t->inrow = 0;
/* Extra info */
tcp_qprintf(t->tq, "</div><div id=\"details_%s\" style=\"%sdisplay: none\">",
t->rowid, t->rowcol ? "background: #fff; " : "");
}
/**
* AJAX table new row
*/
void
ajax_table_details_end(ajax_table_t *t)
{
/* Extra info */
tcp_qprintf(t->tq, "</div>");
}
/**
* AJAX table cell
*/
void
ajax_table_cell(ajax_table_t *t, const char *id, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if(t->rowid && id) {
tcp_qprintf(t->tq, "<div id=\"%s_%s\"", id, t->rowid);
} else {
tcp_qprintf(t->tq, "<div");
}
tcp_qprintf(t->tq,
" style=\"float: left; width: %d%%\">", t->csize[t->curcol]);
t->curcol++;
if(t->curcol == 20)
abort();
if(fmt == NULL)
tcp_qprintf(t->tq, "&nbsp;");
else
tcp_qvprintf(t->tq, fmt, ap);
va_end(ap);
tcp_qprintf(t->tq, "</div>");
}
/**
* AJAX table cell for toggling display of more details
*/
void
ajax_table_cell_detail_toggler(ajax_table_t *t)
{
ajax_table_cell(t, NULL,
"<a id=\"toggle_details_%s\" href=\"javascript:void(0)\" "
"onClick=\"showhide('details_%s')\" >"
"More</a>",
t->rowid, t->rowid);
}
/**
* AJAX table cell for selecting row
*/
void
ajax_table_cell_checkbox(ajax_table_t *t)
{
ajax_table_cell(t, NULL,
"<input id=\"sel_%s\" type=\"checkbox\" class=\"nicebox\">",
t->rowid);
}
/**
* AJAX table footer
*/
void
ajax_table_bottom(ajax_table_t *t)
{
tcp_qprintf(t->tq, "%s</div>", t->inrow ? "</div>" : "");
}
/**
* AJAX box start
*/

View file

@ -54,6 +54,13 @@ img { border: 0; }
* Misc classes
*/
.normaltable {
height: 300px;
overflow: auto;
overflow-y: scroll;
overflow-x: hidden;
}
.iconbackdrop {
background: #fff;
height: 64px;

View file

@ -25,11 +25,41 @@ typedef enum {
AJAX_BOX_BORDER,
} ajax_box_t;
void ajax_box_begin(tcp_queue_t *tq, ajax_box_t type,
const char *id, const char *style, const char *title);
void ajax_box_end(tcp_queue_t *tq, ajax_box_t type);
typedef struct {
int columns;
int curcol;
int inrow;
const char *rowid;
int csize[20];
tcp_queue_t *tq;
int rowcol;
} ajax_table_t;
void ajax_table_top(ajax_table_t *t, http_connection_t *hc, tcp_queue_t *tq,
const char *names[], int weights[]);
void ajax_table_row_start(ajax_table_t *t, const char *id);
void ajax_table_cell(ajax_table_t *t, const char *id, const char *fmt, ...);
void ajax_table_bottom(ajax_table_t *t);
void ajax_table_cell_detail_toggler(ajax_table_t *t);
void ajax_table_cell_checkbox(ajax_table_t *t);
void ajax_table_details_start(ajax_table_t *t);
void ajax_table_details_end(ajax_table_t *t);
void ajax_table_subrow_start(ajax_table_t *t);
void ajax_table_subrow_end(ajax_table_t *t);
void ajax_js(tcp_queue_t *tq, const char *fmt, ...);
@ -71,14 +101,6 @@ int ajax_transport_build_list(http_connection_t *hc, tcp_queue_t *tq,
struct th_transport_list *tlist,
int ntransports);
void ajax_table_header(http_connection_t *hc, tcp_queue_t *tq,
const char *names[], int weights[],
int scrollbar, int columnsizes[]);
void ajax_table_row(tcp_queue_t *tq, const char *cells[], int columnsizes[],
int *bgptr, const char *idprefix[], const char *idpostfix);
const char *ajaxui_escape_apostrophe(const char *content);
#endif /* AJAXUI_H_ */

View file

@ -540,21 +540,15 @@ static int
ajax_adaptermuxlist(http_connection_t *hc, http_reply_t *hr,
const char *remain, void *opaque)
{
ajax_table_t ta;
th_dvb_mux_instance_t *tdmi;
tcp_queue_t *tq = &hr->hr_tq;
th_dvb_adapter_t *tda;
char buf[50], buf2[500], buf3[20];
const char *txt;
char buf[50];
int fetype, n, m;
th_transport_t *t;
int o = 1, v;
int csize[10];
int nmuxes = 0;
int displines = 21;
const char *cells[10];
if(remain == NULL || (tda = dvb_adapter_find_by_identifier(remain)) == NULL)
return HTTP_STATUS_NOT_FOUND;
@ -565,71 +559,45 @@ ajax_adaptermuxlist(http_connection_t *hc, http_reply_t *hr,
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link)
nmuxes++;
ajax_table_header(hc, tq,
(const char *[])
{"Freq", "Status", "State", "Name", "Services", NULL},
(int[]){4,3,2,4,2},
nmuxes > displines,
csize);
tcp_qprintf(tq, "<hr>");
v = displines;
if(nmuxes < displines)
v = nmuxes;
tcp_qprintf(tq, "<div id=\"dvbmuxinnerlist%s\" "
"style=\"height: %dpx; overflow: auto\" class=\"normallist\">",
tda->tda_identifier, v * 14);
if(nmuxes == 0) {
tcp_qprintf(tq, "<div style=\"text-align: center\">"
"No muxes configured</div>");
} else LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
} else {
tdmi_displayname(tdmi, buf, sizeof(buf));
ajax_table_top(&ta, hc, tq,
(const char *[])
{"Freq", "Status", "State", "Name", "Services", NULL},
(int[])
{4,3,2,4,2});
snprintf(buf2, sizeof(buf2),
"<a href=\"javascript:void(0);\" "
"onClick=\"new Ajax.Updater('servicepane', "
"'/ajax/dvbmuxeditor/%s', {method: 'get', evalScripts: true})\""
">%s</a>", tdmi->tdmi_identifier, buf);
LIST_FOREACH(tdmi, &tda->tda_muxes, tdmi_adapter_link) {
tdmi_displayname(tdmi, buf, sizeof(buf));
cells[0] = buf2;
cells[1] = dvb_mux_status(tdmi);
ajax_table_row_start(&ta, tdmi->tdmi_identifier);
switch(tdmi->tdmi_state) {
case TDMI_IDLE: txt = "Idle"; break;
case TDMI_IDLESCAN: txt = "Scanning"; break;
case TDMI_RUNNING: txt = "Running"; break;
default: txt = "???"; break;
ajax_table_cell(&ta, NULL,
"<a href=\"javascript:void(0);\" "
"onClick=\"new Ajax.Updater('servicepane', "
"'/ajax/dvbmuxeditor/%s', "
"{method: 'get', evalScripts: true})\""
">%s</a>",
tdmi->tdmi_identifier, buf);
ajax_table_cell(&ta, "status", "%s", dvb_mux_status(tdmi));
ajax_table_cell(&ta, "state", "%s", dvb_mux_state(tdmi));
ajax_table_cell(&ta, "name", "%s", tdmi->tdmi_network ?: "<unknown>");
n = m = 0;
LIST_FOREACH(t, &tdmi->tdmi_transports, tht_mux_link) {
n++;
if(transport_is_available(t))
m++;
}
ajax_table_cell(&ta, "nsvc", "%d / %d", m, n);
}
cells[2] = txt;
txt = tdmi->tdmi_network;
if(txt == NULL)
txt = "Unknown";
cells[3] = txt;
n = m = 0;
LIST_FOREACH(t, &tdmi->tdmi_transports, tht_mux_link) {
n++;
if(transport_is_available(t))
m++;
}
snprintf(buf3, sizeof(buf3), "%d / %d", m, n);
cells[4] = buf3;
cells[5] = NULL;
ajax_table_row(tq, cells, csize, &o,
(const char *[]){NULL, "status", "state", "name", "nsvc"},
tdmi->tdmi_identifier);
ajax_table_bottom(&ta);
}
tcp_qprintf(tq, "</div>");
http_output_html(hc, hr);
return 0;
}

View file

@ -42,14 +42,10 @@ int
ajax_transport_build_list(http_connection_t *hc, tcp_queue_t *tq,
struct th_transport_list *tlist, int numtransports)
{
char buf[1000];
th_transport_t *t;
const char *v;
int o = 1;
th_stream_t *st;
const char *extra;
int displines = 21;
int csize[10];
ajax_table_t ta;
tcp_qprintf(tq, "<script type=\"text/javascript\">\r\n"
"//<![CDATA[\r\n");
@ -121,114 +117,67 @@ ajax_transport_build_list(http_connection_t *hc, tcp_queue_t *tq,
tcp_qprintf(tq, "<form id=\"transports\">");
ajax_table_header(hc, tq,
(const char *[])
{"", "ServiceID", "Crypto", "Type", "Source service",
"", "Target channel", "", NULL},
(int[]){3,5,4,4,12,3,12,1},
numtransports > displines,
csize);
tcp_qprintf(tq, "<hr>");
tcp_qprintf(tq, "<div id=\"xyzxyz\" "
"style=\"height: %dpx; overflow: auto\" class=\"normallist\">",
MIN(numtransports, displines) * 14);
ajax_table_top(&ta, hc, tq,
(const char *[]){"", "ServiceID", "Crypto",
"Type", "Source service",
"", "Target channel", "", NULL},
(int[]){3,5,4,4,12,3,12,1});
LIST_FOREACH(t, tlist, tht_tmp_link) {
tcp_qprintf(tq, "<div%s>", o ? " style=\"background: #fff\"" : "");
o = !o;
ajax_table_row_start(&ta, t->tht_identifier);
ajax_table_cell_detail_toggler(&ta);
tcp_qprintf(tq, "<div style=\"overflow: auto; width: 100%\">");
ajax_table_cell(&ta, NULL, "%d", t->tht_dvb_service_id);
ajax_table_cell(&ta, NULL, "%s", t->tht_scrambled ? "Yes" : "No");
ajax_table_cell(&ta, NULL, "%s", transport_servicetype_txt(t));
ajax_table_cell(&ta, NULL, "%s", t->tht_servicename ?: "");
tcp_qprintf(tq, "<div style=\"float: left; width: %d%%\">"
"<a id=\"toggle_svcinfo%s\" href=\"javascript:void(0)\" "
"onClick=\"showhide('svcinfo%s')\" >"
"More</a></div>",
csize[0], t->tht_identifier, t->tht_identifier);
tcp_qprintf(tq, "<div style=\"float: left; width: %d%%\">%d</div>",
csize[1], t->tht_dvb_service_id);
tcp_qprintf(tq, "<div style=\"float: left; width: %d%%\">%s</div>",
csize[2], t->tht_scrambled ? "CSA" : "Free");
tcp_qprintf(tq, "<div style=\"float: left; width: %d%%\">%s</div>",
csize[3], transport_servicetype_txt(t));
tcp_qprintf(tq, "<div style=\"float: left; width: %d%%\">%s</div>",
csize[4], t->tht_servicename ?: "");
tcp_qprintf(tq,
"<div style=\"float: left; width: %d%%; text-align: center\">"
"<a href=\"javascript:void(0)\" "
"onClick=\"new "
"Ajax.Request('/ajax/transport_op/%s', "
"{parameters: {action: 'toggle'}})\">"
"<img id=\"map%s\" src=\"/gfx/%smapped.png\"></a></div>",
csize[5],
t->tht_identifier, t->tht_identifier,
t->tht_channel ? "" : "un");
tcp_qprintf(tq, "<div id=\"chname%s\" style=\"float: left; width: %d%%\">",
t->tht_identifier, csize[6]);
ajax_table_cell(&ta, NULL,
"<a href=\"javascript:void(0)\" "
"onClick=\"new Ajax.Request('/ajax/transport_op/%s', "
"{parameters: {action: 'toggle'}})\">"
"<img id=\"map_%s\" src=\"/gfx/%smapped.png\"></a>",
t->tht_identifier, t->tht_identifier,
t->tht_channel ? "" : "un");
if(t->tht_channel == NULL) {
/* Unmapped */
v = t->tht_channelname;
snprintf(buf, sizeof(buf),
"tentative_chname('chname%s', "
"'/ajax/transport_rename_channel/%s', '%s')",
t->tht_identifier, t->tht_identifier, v);
ajax_a_jsfunc(tq, v, buf, "");
ajax_table_cell(&ta, "chname",
"<a href=\"javascript:void(0)\" "
"onClick=\"tentative_chname('chname%s', "
"'/ajax/transport_rename_channel/%s', '%s')\">"
"%s</a>",
t->tht_identifier, t->tht_identifier,
t->tht_channelname, t->tht_channelname);
} else {
/* Mapped */
tcp_qprintf(tq, "%s", t->tht_channel->ch_name);
ajax_table_cell(&ta, "chname", "%s", t->tht_channel->ch_name);
}
tcp_qprintf(tq, "</div>");
ajax_table_cell_checkbox(&ta);
ajax_table_details_start(&ta);
tcp_qprintf(tq, "<div style=\"float: left; width: %d%\">"
"<input id=\"sel_%s\" type=\"checkbox\" class=\"nicebox\">"
"</div>", csize[7], t->tht_identifier);
tcp_qprintf(tq, "</div>");
/* Extra info */
tcp_qprintf(tq, "<div id=\"svcinfo%s\" style=\"display: none\">",
t->tht_identifier);
tcp_qprintf(tq, "<p>");
tcp_qprintf(tq, "<div style=\"overflow: auto; width: 100%\">");
tcp_qprintf(tq, "<div style=\"float: left; width: %d%%\">"
"&nbsp;</div>", csize[0]);
tcp_qprintf(tq, "<div class=\"pidheader\" style=\"width: %d%%\">"
"PID</div>", csize[1]);
tcp_qprintf(tq, "<div class=\"pidheader\" style=\"width: %d%%\">"
"Payload</div>", csize[2] + csize[3]);
tcp_qprintf(tq, "<div class=\"pidheader\" style=\"width: %d%%\">Details"
"</div>",
csize[4] + csize[5] + csize[6] + csize[7]);
tcp_qprintf(tq, "</div>");
ajax_table_subrow_start(&ta);
ajax_table_cell(&ta, NULL, NULL);
ajax_table_cell(&ta, NULL, "PID");
ajax_table_cell(&ta, NULL, NULL);
ajax_table_cell(&ta, NULL, NULL);
ajax_table_cell(&ta, NULL, "Payload");
ajax_table_cell(&ta, NULL, NULL);
ajax_table_cell(&ta, NULL, "Details");
ajax_table_subrow_end(&ta);
LIST_FOREACH(st, &t->tht_streams, st_link) {
tcp_qprintf(tq, "<div style=\"overflow: auto; width: 100%\">");
tcp_qprintf(tq, "<div style=\"float: left; width: %d%%\">&nbsp;</div>",
csize[0]);
tcp_qprintf(tq, "<div style=\"float: left; width: %d%%\">%d</div>",
csize[1], st->st_pid);
tcp_qprintf(tq, "<div style=\"float: left; width: %d%%\">%s</div>",
csize[2] + csize[3],
htstvstreamtype2txt(st->st_type));
ajax_table_subrow_start(&ta);
ajax_table_cell(&ta, NULL, NULL);
ajax_table_cell(&ta, NULL, "%d", st->st_pid);
ajax_table_cell(&ta, NULL, NULL);
ajax_table_cell(&ta, NULL, NULL);
ajax_table_cell(&ta, NULL, "%s", htstvstreamtype2txt(st->st_type));
switch(st->st_type) {
case HTSTV_MPEG2AUDIO:
case HTSTV_AC3:
@ -242,19 +191,16 @@ ajax_transport_build_list(http_connection_t *hc, tcp_queue_t *tq,
break;
}
if(extra != NULL)
tcp_qprintf(tq, "<div style=\"float: left; width: %d%%\">%s</div>",
csize[4] + csize[5] + csize[6] + csize[7],
extra);
tcp_qprintf(tq, "</div>");
ajax_table_cell(&ta, NULL, NULL);
ajax_table_cell(&ta, NULL, extra);
ajax_table_subrow_end(&ta);
}
tcp_qprintf(tq, "</p></div>");
tcp_qprintf(tq, "</div>\r\n");
ajax_table_details_end(&ta);
}
tcp_qprintf(tq, "</div><hr>\r\n");
ajax_table_bottom(&ta);
tcp_qprintf(tq, "<hr>\r\n");
tcp_qprintf(tq, "<div style=\"overflow: auto; width: 100%\">");
@ -304,7 +250,7 @@ ajax_transport_rename_channel(http_connection_t *hc, http_reply_t *hr,
v = newname;
snprintf(buf, sizeof(buf),
"tentative_chname('chname%s', "
"tentative_chname('chname_%s', "
"'/ajax/transport_rename_channel/%s', '%s')",
t->tht_identifier, t->tht_identifier, v);
@ -327,8 +273,8 @@ dvb_map_channel(th_transport_t *t, tcp_queue_t *tq)
t->tht_servicename, t->tht_channel->ch_name);
tcp_qprintf(tq,
"$('chname%s').innerHTML='%s';\n\r"
"$('map%s').src='/gfx/mapped.png';\n\r",
"$('chname_%s').innerHTML='%s';\n\r"
"$('map_%s').src='/gfx/mapped.png';\n\r",
t->tht_identifier, t->tht_channel->ch_name,
t->tht_identifier);
}
@ -345,12 +291,12 @@ dvb_unmap_channel(th_transport_t *t, tcp_queue_t *tq)
printf("Unmapped transport %s\n", t->tht_servicename);
tcp_qprintf(tq,
"$('chname%s').innerHTML='"
"$('chname_%s').innerHTML='"
"<a href=\"javascript:void(0)\" "
"onClick=\"javascript:tentative_chname(\\'chname%s\\', "
"onClick=\"javascript:tentative_chname(\\'chname_%s\\', "
"\\'/ajax/transport_rename_channel/%s\\', \\'%s\\')\">%s</a>"
"';\n\r"
"$('map%s').src='/gfx/unmapped.png';\n\r",
"$('map_%s').src='/gfx/unmapped.png';\n\r",
t->tht_identifier, t->tht_identifier, t->tht_identifier,
t->tht_channelname, t->tht_channelname, t->tht_identifier);
}

View file

@ -46,11 +46,7 @@ ajax_config_xmltv_tab(http_connection_t *hc, http_reply_t *hr)
tcp_queue_t *tq = &hr->hr_tq;
xmltv_grabber_t *xg;
int ngrabbers = 0;
int displines = 21;
int csize[10];
const char *cells[10];
int o = 1;
char buf[200];
ajax_table_t ta;
tcp_qprintf(tq, "<div style=\"overflow: auto; width: 100%\">");
@ -82,32 +78,22 @@ ajax_config_xmltv_tab(http_connection_t *hc, http_reply_t *hr)
LIST_FOREACH(xg, &xmltv_grabbers, xg_link)
ngrabbers++;
ajax_table_header(hc, tq,
(const char *[]){"Grabber", "Status", NULL},
(int[]){4,2}, ngrabbers > displines, csize);
tcp_qprintf(tq, "<hr><div "
"style=\"height: %dpx; overflow: auto\" class=\"normallist\">",
MAX(displines, ngrabbers) * 14);
ajax_table_top(&ta, hc, tq,
(const char *[]){"Grabber", "Status", NULL},
(int[]){4,2});
LIST_FOREACH(xg, &xmltv_grabbers, xg_link) {
snprintf(buf, sizeof(buf),
ajax_table_row_start(&ta, xg->xg_identifier);
ajax_table_cell(&ta, NULL,
"<a href=\"javascript:void(0);\" "
"onClick=\"new Ajax.Updater('grabberpane', "
"'/ajax/xmltvgrabber/%s', {method: 'get', evalScripts: true})\""
">%s</a>", xg->xg_identifier, xg->xg_title);
cells[0] = buf;
cells[1] = xmltv_grabber_status(xg);
cells[2] = NULL;
ajax_table_row(tq, cells, csize, &o,
(const char *[]){NULL, "status"},
xg->xg_identifier);
ajax_table_cell(&ta, "status", xmltv_grabber_status(xg));
}
tcp_qprintf(tq, "</div>");
ajax_table_bottom(&ta);
ajax_box_end(tq, AJAX_BOX_SIDEBOX);