refactored form handling

This commit is contained in:
Peter Schojer
2008-09-11 09:09:11 +00:00
parent b9fa3377a0
commit dd3f43c37d
35 changed files with 357 additions and 79 deletions

View File

@@ -101,8 +101,7 @@ void Button::init(Cell::Ptr ptrCell)
{
ButtonCell::Ptr pCell = ptrCell.cast<ButtonCell>();
poco_check_ptr (pCell);
pCell->buttonClicked = delegate(*this, &Button::fireButtonClicked);
pCell->ajaxButtonClicked = ajaxDelegate(*this, &Button::fireAjaxButtonClicked);
pCell->buttonClicked = ajaxDelegate(*this, &Button::fireButtonClicked);
setCell(pCell);
}
@@ -114,16 +113,9 @@ void Button::init()
}
void Button::fireAjaxButtonClicked(void* pSender, AjaxParameters& params)
void Button::fireButtonClicked(void* pSender, AjaxParameters& params)
{
ajaxButtonClicked(pSender, params);
}
void Button::fireButtonClicked(void* pSender)
{
ButtonEvent clickedEvent(this);
buttonClicked(this, clickedEvent);
buttonClicked(pSender, params);
}

View File

@@ -76,10 +76,9 @@ void ButtonCell::handleAjaxRequest(const Poco::Net::NameValueCollection& args, P
if (ev == EV_BUTTONCLICKED)
{
bool handled(false);
ajaxButtonClicked(this, args, response, handled);
buttonClicked(this, args, response, handled);
if (!handled)
response.send();
buttonClicked(this);
}
else
response.send();

View File

@@ -36,6 +36,7 @@
#include "Poco/WebWidgets/ComboBoxCell.h"
#include "Poco/WebWidgets/RequestHandler.h"
#include "Poco/DateTime.h"
namespace Poco {
@@ -133,4 +134,20 @@ void ComboBoxCell::setSelected(const Any& elem)
selected(this, aPair);
}
bool ComboBoxCell::serializeJSON(std::ostream& out, const std::string& name)
{
out << name;
if (hasSelected())
{
const Poco::Any& sel = getSelected();
if (sel.type() == typeid(std::string) || sel.type() == typeid(Poco::DateTime))
out << ":'" << getFormatter()->format(sel) << "'";
else
out << ":" << getFormatter()->format(sel);
}
return true;
}
} } // namespace Poco::WebWidgets

View File

@@ -63,4 +63,15 @@ void DateFieldCell::setFormat(const std::string& dateFormat)
}
bool DateFieldCell::serializeJSON(std::ostream& out, const std::string& name)
{
out << name;
if (this->hasValue())
{
out << ":'" << getFormatter()->format(getValue()) << "'";
}
return true;
}
} } // namespace Poco::WebWidgets

View File

@@ -35,6 +35,9 @@
#include "Poco/WebWidgets/Form.h"
#include "Poco/WebWidgets/RequestHandler.h"
#include "Poco/NumberParser.h"
#include "Poco/Net/HTMLForm.h"
namespace Poco {
@@ -42,6 +45,7 @@ namespace WebWidgets {
const std::string Form::FORM_ID("__form__");
const std::string Form::EV_RELOAD("reload");
const std::string Form::METHOD_GET("GET");
const std::string Form::METHOD_POST("POST");
const std::string Form::ENCODING_URL("application/x-www-form-urlencoded");
@@ -52,7 +56,8 @@ Form::Form(const Poco::URI& uri):
ContainerView(typeid(Form)),
_method(METHOD_POST),
_encoding(ENCODING_MULTIPART),
_uri(uri)
_uri(uri),
_namedChildren()
{
}
@@ -61,7 +66,8 @@ Form::Form(const std::string& name, const Poco::URI& uri):
ContainerView(name, typeid(Form)),
_method(METHOD_POST),
_encoding(ENCODING_MULTIPART),
_uri(uri)
_uri(uri),
_namedChildren()
{
}
@@ -70,7 +76,8 @@ Form::Form(const std::string& name, const std::type_info& type, const Poco::URI&
ContainerView(name, type),
_method(METHOD_POST),
_encoding(ENCODING_MULTIPART),
_uri(uri)
_uri(uri),
_namedChildren()
{
}
@@ -79,7 +86,8 @@ Form::Form(const std::type_info& type, const Poco::URI& uri):
ContainerView(type),
_method(METHOD_POST),
_encoding(ENCODING_MULTIPART),
_uri(uri)
_uri(uri),
_namedChildren()
{
}
@@ -101,4 +109,92 @@ void Form::setEncoding(const std::string& encoding)
}
void Form::handleForm(const std::string& field, const std::string& value)
{
}
void Form::handleForm(const Poco::Net::HTMLForm& form)
{
Renderable::ID formID = Poco::NumberParser::parse(form.get(Form::FORM_ID));
poco_assert (formID == id());
Poco::Net::NameValueCollection::ConstIterator it = form.begin();
RequestProcessorMap processors = _namedChildren; // copy so that a second submit works too!
for (;it != form.end(); ++it)
{
const std::string& key = it->first;
RequestProcessorMap::iterator itR = processors.find(key);
if (itR != processors.end())
{
itR->second->handleForm(key, it->second);
processors.erase(itR);
}
}
//those that are not included are either deselected or empty
RequestProcessorMap::iterator itR = processors.begin();
std::string empty;
for (; itR != processors.end(); ++itR)
{
itR->second->handleForm(itR->first, empty);
}
}
void Form::handleAjaxRequest(const Poco::Net::NameValueCollection& args, Poco::Net::HTTPServerResponse& response)
{
//a form only supports the refresh event
const std::string& ev = args[RequestHandler::KEY_EVID];
if (ev == EV_RELOAD)
{
Form* pThis = this;
beforeReload.notify(this, pThis);
/// send the JS presentation of the page
response.setContentType("text/javascript");
response.setChunkedTransferEncoding(true);
serializeJSONImpl(response.send());
}
response.send();
}
void Form::serializeJSONImpl(std::ostream& out)
{
// FIXME: ExtJs specific
out << "{";
out << "success: true,";
out << "data: { ";
// serialize children
RequestProcessorMap::iterator it = _namedChildren.begin();
bool writeComma = false;
for (; it != _namedChildren.end(); ++it)
{
if (writeComma)
out << ",";
writeComma = it->second->serializeJSON(out, it->first);
}
out << "}";
out << "}";
}
void Form::registerFormProcessor(const std::string& fieldName, RequestProcessor* pProc)
{
// per default we register everything that has a name as form processor
std::pair<RequestProcessorMap::iterator, bool> res = _namedChildren.insert(std::make_pair(fieldName, pProc));
if (!res.second)
res.first->second = pProc;
}
RequestProcessor* Form::getFormProcessor(const std::string& fieldName)
{
RequestProcessorMap::iterator it = _namedChildren.find(fieldName);
if (it == _namedChildren.end())
return 0;
return it->second;
}
} } // namespace Poco::WebWidgets

View File

@@ -35,6 +35,7 @@
#include "Poco/WebWidgets/ListBoxCell.h"
#include "Poco/DateTime.h"
namespace Poco {
@@ -168,4 +169,19 @@ const Any& ListBoxCell::getSelected() const
}
bool ListBoxCell::serializeJSON(std::ostream& out, const std::string& name)
{
out << name;
if (hasSelected())
{
const Poco::Any& sel = getSelected();
if (sel.type() == typeid(std::string) || sel.type() == typeid(Poco::DateTime))
out << ":'" << getFormatter()->format(sel) << "'";
else
out << ":" << getFormatter()->format(sel);
}
return true;
}
} } // namespace Poco::WebWidgets

View File

@@ -54,4 +54,15 @@ NumberFieldCell::~NumberFieldCell()
}
bool NumberFieldCell::serializeJSON(std::ostream& out, const std::string& name)
{
out << name;
if (this->hasValue())
{
out << ":" << getFormatter()->format(getValue());
}
return true;
}
} } // namespace Poco::WebWidgets

View File

@@ -52,4 +52,15 @@ PasswordFieldCell::~PasswordFieldCell()
}
bool PasswordFieldCell::serializeJSON(std::ostream& out, const std::string& name)
{
out << name;
if (this->hasValue())
{
out << ":'" << getFormatter()->format(getValue()) << "'";
}
return true;
}
} } // namespace Poco::WebWidgets

View File

@@ -181,12 +181,7 @@ void RequestHandler::handleAjaxRequest(Poco::Net::HTTPServerRequest& request, Po
response.send();
return;
}
SubmitButtonCell* pCell = dynamic_cast<SubmitButtonCell*>(pProc);
if (pCell) // hide click event from submitbuttons
{
response.send();
return;
}
try
{
pProc->handleAjaxRequest(args, response);

View File

@@ -352,4 +352,10 @@ Table::LoadData::LoadData(Poco::Net::HTTPServerResponse* pR, Table* pT, int row,
}
bool Table::serializeJSON(std::ostream& out, const std::string& name)
{
return false;
}
} } // namespace Poco::WebWidgets

View File

@@ -73,4 +73,15 @@ void TextEditCell::handleForm(const std::string& field, const std::string& value
}
bool TextEditCell::serializeJSON(std::ostream& out, const std::string& name)
{
out << name;
if (this->hasValue())
{
out << ":'" << getFormatter()->format(getValue()) << "'";
}
return true;
}
} } // namespace Poco::WebWidgets

View File

@@ -85,4 +85,15 @@ void TextFieldCell::handleForm(const std::string& field, const std::string& valu
}
bool TextFieldCell::serializeJSON(std::ostream& out, const std::string& name)
{
out << name;
if (this->hasValue())
{
out << ":'" << getFormatter()->format(getValue()) << "'";
}
return true;
}
} } // namespace Poco::WebWidgets

View File

@@ -77,4 +77,15 @@ void TimeFieldCell::setFormat(TimeField::Format fmt)
}
bool TimeFieldCell::serializeJSON(std::ostream& out, const std::string& name)
{
out << name;
if (this->hasValue())
{
out << ":'" << getFormatter()->format(getValue()) << "'";
}
return true;
}
} } // namespace Poco::WebWidgets

View File

@@ -85,4 +85,16 @@ void ToggleButtonCell::setChecked(bool checked)
}
}
bool ToggleButtonCell::serializeJSON(std::ostream& out, const std::string& name)
{
//FIXME: this is extjs specific
out << name << ":";
if (isChecked())
out << "'on'";
else
out << "'off'";
return true;
}
} } // namespace Poco::WebWidgets

View File

@@ -113,20 +113,19 @@ void WebApplication::beginForm(const Form& form)
if (!_forms.empty())
throw WebWidgetsException("nested forms not allowed");
_forms.push(form.id());
_formMap.insert(std::make_pair(form.id(), RequestProcessorMap()));
_formMap.insert(std::make_pair(form.id(), const_cast<Form*>(&form)));
}
void WebApplication::registerFormProcessor(const std::string& fieldName, RequestProcessor* pProc)
{
// per default we register everyting that has a name as form processor
// per default we register everything that has a name as form processor
if (!_forms.empty())
{
FormMap::iterator itForm = _formMap.find(_forms.top());
poco_assert (itForm != _formMap.end());
std::pair<RequestProcessorMap::iterator, bool> res = itForm->second.insert(std::make_pair(fieldName, pProc));
if (!res.second)
res.first->second = pProc;
itForm->second->registerFormProcessor(fieldName, pProc);
}
}
@@ -137,10 +136,7 @@ RequestProcessor* WebApplication::getFormProcessor(Renderable::ID formId, const
if (itForm == _formMap.end())
return 0;
RequestProcessorMap::iterator it = itForm->second.find(fieldName);
if (it == itForm->second.end())
return 0;
return it->second;
return itForm->second->getFormProcessor(fieldName);
}
@@ -184,27 +180,8 @@ void WebApplication::handleForm(const Poco::Net::HTMLForm& form)
FormMap::iterator itForm = _formMap.find(formID);
if (itForm == _formMap.end())
throw Poco::NotFoundException("unknown form id");
Poco::Net::NameValueCollection::ConstIterator it = form.begin();
RequestProcessorMap& processors = itForm->second;
for (;it != form.end(); ++it)
{
const std::string& key = it->first;
RequestProcessorMap::iterator itR = processors.find(key);
if (itR != processors.end())
{
itR->second->handleForm(key, it->second);
processors.erase(itR);
}
}
//those that are not included are either deselected or empty
RequestProcessorMap::iterator itR = processors.begin();
std::string empty;
for (; itR != processors.end(); ++itR)
{
itR->second->handleForm(itR->first, empty);
}
processors.clear();
itForm->second->handleForm(form);
}
@@ -219,8 +196,7 @@ void WebApplication::notifySubmitButton(Renderable::ID id)
SubmitButton* pSubmit = dynamic_cast<SubmitButton*>(pOwner);
if (pSubmit)
{
Button::ButtonEvent clickedEvent(pSubmit);
pSubmit->buttonClicked.notify(pSubmit, clickedEvent);
pSubmit->afterSubmit.notify(pSubmit, pSubmit);
}
}