mirror of
https://github.com/pocoproject/poco.git
synced 2025-11-25 06:36:37 +01:00
refactored form handling
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user