/* * SPL - The SPL Programming Language * Copyright (C) 2004, 2005 Clifford Wolf * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * mod_wsf_edit.spl: A WSF Component for editing data */ /** * A module which provides a generic WSF component for creating edit frontends * for any kind of data tuples. See [[wsf_edit_sql:]] for an implementation. */ load "wsf"; /** * This is a base object for WSF components which assemble edit frontends for * any kind of data tuples. Usually one would not use this object directly but * an object which is derived from it, such as [[wsf_edit_sql:WsfEditSql]]. * * A 'data tuple' may be anything that can be represented as list of key-value * pairs, such as a tuple from an SQL table. * * The basic idea is that the methods [[.edit_load()]] and [[.edit_save]] are * overloaded so they can load and save the data tuple to be edited. * * The [[.get_html()]] method should also be overloaded so it evaluates a * template which is using the methods [[.edit_input()]], [[.edit_textarea]] * and [[.edit_select()]] for creating the form elements. * * An example for using [[WsfEdit]] can be found in the documentation of * [[wsf_edit_sql:WsfEditSql]]. * * This object is derived from [[wsf:WsfComponent]]. */ object WsfEdit WsfComponent { /** * A hash containing the data tuple. When [[.edit_save()]] is called, * this contains the data sent to the browser, not the new data * returned by the user. This can be used to check if the data has * actually been modified. */ var edit_data; /** * The fields included in the edit form generated. This can be used to * check which fields in the tuple have actually been shown to the user. * The [[.edit_save()]] method should only save the fields defined in * this hash. This is especially important if the template includes some * fields conditionally, e.g. because the user has not the accurate * permissions to edit all fields. */ var edit_fields; /** * This hash can be used to define additional actions to be executed * instead of simply calling [[.edit_save()]]. * * If a query string parameter matches a key defined in that hash, * the value of that hash entry will be executed (as function/method * pointer) and [[.edit_save()]]. Won't be called. * * Usually this is used to implement things such as "Back to List" * buttons. */ var edit_actions; /** * The [[.edit_save()]] method should set this variable to '1' when * is saved the new data. This can e.g. be used by the template to * display a "Database updated" message. */ var just_updated; /** * This method must be executed by [[.get_html()]] before evaluating * the template. It resets [[.edit_fields]] and calls [[.edit_load()]]. */ method edit_reset() { edit_fields = undef; edit_load(); } /** * Returns the HTML code for a input box. * * The parameter 'field' is a key in the [[.edit_data]] hash. * * The following named parameters are supported: * * style value for the css style attribute * size value for the size attribute * * Simply include that function in your template using the ${ .. } * substitution. */ method edit_input(field, %opt) { var style = opt["style"]; var size = opt["size"]; edit_fields[field] = field; var sizeattr = defined size ? 'size="${xml::size}"' : ''; return ''; } /** * Returns the HTML code for a textarea. * * The following named parameters are supported: * * style value for the css style attribute * cols value for the cols attribute * rows value for the rows attribute * * (see also [[.edit_input()]]) */ method edit_textarea(field, %opt) { var style = opt["style"]; var cols = opt["cols"]; var rows = opt["rows"]; edit_fields[field] = field; var colsattr = defined cols ? 'cols="${xml::cols}"' : ''; var rowsattr = defined rows ? 'rows="${xml::rows}"' : ''; return ''; } /** * Returns the HTML code for a select box. * * The list parameter is a hash with the possible values as keys and * the description texts as values. * * The following named parameters are supported: * * style value for the css style attribute * * emptydesc * If this parameter is defined, an additional option with * that description and an empty value is added as first * option to the list of possible options. * * (see also [[.edit_input()]]) */ method edit_select(field, list, %opt) { var style = opt["style"]; var emptydesc = opt["emptydesc"]; edit_fields[field] = field; var html = ''; } /** * This method must be overloaded. * * It must fill the [[.edit_data]] hash with values. */ method edit_load() { panic "Not overloaded WsfEdit.edit_load() called!"; } /** * This method must be overloaded. * * For all keys defined in [[.edit_fields]], it must update the values * in the backend storage. * * The data must be obtained from 'cgi.param["edit_$keyname"]'. * * It is possible to compare the new values with the old values in * [[.edit_data]] to see if the values have actually changed. * * The variable [[.just_updated]] must be set to '1' if anything has * been updated. */ method edit_save() { panic "Not overloaded WsfEdit.edit_save() called!"; } /** * Overloaded [[wsf:WsfComponent.main()]]. */ method main() { while(1) { task_co_return(); var got_edit_action = 0; foreach a (edit_actions) { if (declared cgi.param[a]) { got_edit_action = 1; edit_actions[a](); } } if (!got_edit_action) { edit_save(); dirty = 1; } } } /** * Overloaded [[wsf:WsfComponent.get_html()]]. * * This method must be overloaded again by object actually implementing * an editor. The method [[.edit_reset()]] must be called in the very * beginning of that method. */ method get_html() { edit_reset(); return '
\n'; } /** * Constructor. */ method init() { just_updated = 0; return *WsfComponent.init(); } }