f41b982009-05-07Martin Stjernholm // This is a roxen pike module. Copyright © 2001 - 2009, Roxen IS.
9857c32001-09-17Martin Nilsson //
0917d32013-03-04Anders Johansson // $Id$
9857c32001-09-17Martin Nilsson  //! Functions that helps generating HTML. All functions generates
a497332001-09-24Johan Sundström //! HTML that is XHTML compliant as well as backwards compatible
9857c32001-09-17Martin Nilsson //! with old HTML standards in what extent is possible. //! Creates an HTML select list. //! //! @param name //! The name of the select list. Will be used in the name attribute //! of the select element. //! @param choices //! May either be an array of strings, where each string is a choice, //! or an array of pairs. A pair is an array with two strings. The //! first string is the value of the choice while the second string //! is the presentation text associated with the value. //! @param selected //! The value that should be selected by default, if any. //! //! @example //! select("language", //! ({ ({ "eng", "English" }), //! ({ "swe", "Swedish" }), //! ({ "nor", "Norwegian" }) }), //! "swe"); string select(string name, array(string)|array(array(string)) choices, void|string selected) { string ret = "<select name=\"" + name + "\">\n"; if(sizeof(choices) && arrayp(choices[0])) { foreach([array(array(string))]choices, array(string) value) ret += "<option value=\"" + value[0] + "\"" + (value[0]==selected?" selected=\"selected\"":"") + ">" + value[1] + "</option>\n"; } else { foreach([array(string)]choices, string value) ret += "<option value=\"" + value + "\"" + (value==selected?" selected=\"selected\"":"") + ">" + value + "</option>\n"; } return ret + "</select>"; } //! This function should solve most of the obox needs that arises. It creates a table out //! of the array of arrays of strings fed into it. The tables will (with default settings) //! have a thin black outline around the table and between its cells. Much effort has gone //! into finding a simple HTML reresentation of such obox that is rendered in a similar way //! in all popular browsers. The current implementation has been tested against IE, Netscape, //! Mozilla, Opera and Konquest. //! //! @param rows //! Simply an array of arrays with strings. The strings are the values that should appear //! in the table cells. All rows should have equal number of cells, otherwise the result //! will not be very eye pleasing. //! @param frame_color //! The color of the surrounding frame. Defaults to "#000000". //! @param cell_color //! The background color of the cells. Defaults to "#ffffff". //! @param width //! The border width. Defaults to "1". //! @param padding //! The amount of padding in each cell. Defaults to "3". //! @param cell_callback //! If provided, the cell callback will be called for each cell. As in parameters it //! will get the current x and y coordinates in the table. The upper left cell is 0,0. //! In addition to the coordinates it will also recieve the background color and the //! contents of the current cell. It is expected to return a td-element. //! //! @example //! function cb = lambda(int x, int y, string bgcolor, string contents) { //! if(y%2) return "<td bgcolor='#aaaaff'>"+contents+"</td>"; //! return "<td bgcolor='"+bgcolor+"'>"+contents+"</td>"; //! }
b424492001-09-17Martin Nilsson //! simple_obox(my_rows, "#0000a0", 0, "1", "3", cb);
9857c32001-09-17Martin Nilsson //! //! @seealso //! pad_rows string simple_obox( array(array(string)) rows, void|string frame_color, void|string cell_color, void|string width, void|string padding, void|function(int, int, string, string : string) cell_callback ) { string res = ""; if(!cell_color) cell_color = "#ffffff"; if(cell_callback) { int y; foreach(rows, array(string) row) { int x; res += "<tr>"; foreach(row, string cell) { res += cell_callback(x, y, cell_color, cell); x++; } res += "</tr>"; y++; } } else foreach(rows, array(string) row) { res += "<tr>"; foreach(row, string cell) res += "<td bgcolor='" + cell_color + "'>" + cell + "</td>"; res += "</tr>"; } return wrap_simple_obox(res, frame_color, width, padding); } private string wrap_simple_obox( string rows, void|string frame_color, void|string width, void|string padding ) { if(!frame_color) frame_color = "#000000";
b9621b2001-09-25Martin Nilsson  return "<table bgcolor='" + frame_color + "' cellspacing='0' cellpadding='0' border='0'><tr><td>\n"
9857c32001-09-17Martin Nilsson  "<table bgcolor='" + frame_color + "' cellspacing='" + (width||"1") + "' cellpadding='" + (padding||"3") + "' border='0'>\n" + rows + "</table></td></tr></table>"; } //! Pads out the rows in a array of rows to equal length. The new elements in //! the rows will have the value provided in @[padding], or "&nbsp;". array(array(string)) pad_rows( array(array(string)) rows, void|string padding ) { int m = max( @map(rows, sizeof) ); if(!padding) padding = "&nbsp;"; for(int i; i<sizeof(rows); i++) if(sizeof(rows[i])<m) rows[i] = rows[i] + allocate(m-sizeof(rows[i]), padding); return rows; }
daf5342002-12-04Martin Stjernholm // Kludge: An alternative name to allow access from OBox.pad_rows.
fc40392008-08-15Martin Stjernholm protected array(array(string)) _pad_rows( array(array(string)) rows, void|string padding )
daf5342002-12-04Martin Stjernholm  {return pad_rows (rows, padding);}
9857c32001-09-17Martin Nilsson //! Provides the same functionality as the @[simple_obox] function, //! in a "streaming" way. The real gain is different addtition methods //! as well as the possibility to change the cell callback at any time. //! //! @seealso //! simple_obox class OBox {
fc40392008-08-15Martin Stjernholm  protected {
9857c32001-09-17Martin Nilsson  string frame_color; string cell_color = "#ffffff"; string width; string padding; int x; int y; array(array(string)) rows = ({ ({}) }); function(int, int, string, string : string) cb; mapping(string:string)|array(mapping(string:string)) args; }
b424492001-09-17Martin Nilsson  //! @decl void create(void|string frame_color, void|string cell_color,@ //! void|string width, void|string padding,@ //! void|function(int, int, string, string : string) cell_callback)
9857c32001-09-17Martin Nilsson  void create( void|string _frame_color, void|string _cell_color, void|string _width, void|string _padding, void|function(int, int, string, string : string) _cb) { if(_frame_color) frame_color = _frame_color; if(_cell_color) cell_color = _cell_color; if(_width) width = _width; if(_padding) padding = _padding; if(_cb) cb = _cb; }
b424492001-09-17Martin Nilsson  //! @decl void set_cell_callback(@ //! function(int, int, string, string : string) cell_callback)
9857c32001-09-17Martin Nilsson  void set_cell_callback( function(int, int, string, string : string) _cb ) { cb = _cb; }
b424492001-09-17Martin Nilsson  //! @decl void set_extra_args( mapping(string:string) extra_args ) //! The argument in the mapping will be added to all created table cells.
6b780a2001-11-16Martin Nilsson 
b424492001-09-17Martin Nilsson  //! @decl void set_extra_args( array(mapping(string:string)) extra_args ) //! The argument in the mappings will be added to the cell in the //! cooresponding column of the table.
6b780a2001-11-16Martin Nilsson 
9857c32001-09-17Martin Nilsson  void set_extra_args( mapping(string:string)|array(mapping(string:string)) _args) { if(mappingp(_args)) { if(!_args->bgcolor) _args->bgcolor = cell_color; } else foreach(_args, mapping m) if(!m->bgcolor) m->bgcolor = cell_color; args = _args; }
b424492001-09-17Martin Nilsson  //! Adds this cell to the table unmodified, e.g. it should have an enclosing //! td or th element.
9857c32001-09-17Martin Nilsson  void add_raw_cell( string cell ) { rows[-1] += ({ cell }); x++; }
b424492001-09-17Martin Nilsson  //! Creates a cell from the provided arguments and adds it to the table. //! //! @param tag //! The name of the element that should be produces. Typically //! "td" or "th". //! @param args //! A mapping with the elements attributes. //! @param contents //! The element contents. void add_tagdata_cell( string tag, mapping(string:string) args, string contents ) {
9857c32001-09-17Martin Nilsson  if(!args->bgcolor) args->bgcolor = cell_color; rows[-1] += ({ sprintf("<%s%{ %s='%s'%}>%s</%[0]s>", tag, (array)args, contents) }); }
b424492001-09-17Martin Nilsson  //! Adds a cell with the provided content.
9857c32001-09-17Martin Nilsson  void add_cell( string contents ) { if(cb) rows[-1] += ({ cb(x, y, cell_color, contents) }); else if(args && mappingp(args)) add_tagdata_cell( "td", args, contents ); else if(args && sizeof(args)>x) add_tagdata_cell( "td", args[x], contents ); else rows[-1] += ({ "<td bgcolor='" + cell_color + "'>" + contents + "</td>" }); x++; }
b424492001-09-17Martin Nilsson  //! Begin a new row. Succeeding cells will be added to this //! row instead of the current.
9857c32001-09-17Martin Nilsson  void new_row() { x = 0; y++; rows += ({ ({}) }); }
b424492001-09-17Martin Nilsson  //! Adds a complete row. If the current row is nonempty a //! new row will be started.
9857c32001-09-17Martin Nilsson  void add_row( array(string) cells ) { if(sizeof(rows[-1])) new_row(); foreach(cells, string cell) add_cell( cell ); }
b424492001-09-17Martin Nilsson  //! Ensures that all rows have the same number of cells.
9857c32001-09-17Martin Nilsson  void pad_rows() {
daf5342002-12-04Martin Stjernholm  rows = _pad_rows(rows, "<td bgcolor='" + cell_color + "'>&nbsp;</td>");
9857c32001-09-17Martin Nilsson  }
b424492001-09-17Martin Nilsson  //! Returns the result. string render() {
9857c32001-09-17Martin Nilsson  return wrap_simple_obox( "<tr>" + map(rows, `*, "")*"</tr><tr>\n" + "</tr>", frame_color, width, padding ); } //! mixed cast(string to) { if(to=="array") return rows; if(to=="string")
b424492001-09-17Martin Nilsson  return render();
9857c32001-09-17Martin Nilsson  error("Could not cast OBox object to %s.\n", to); } }