mirror of
https://github.com/pocoproject/poco.git
synced 2025-10-18 11:39:00 +02:00
refactored form handling
This commit is contained in:
@@ -43,10 +43,11 @@
|
|||||||
#include "Poco/WebWidgets/ExtJS/ExtJS.h"
|
#include "Poco/WebWidgets/ExtJS/ExtJS.h"
|
||||||
#include "Poco/WebWidgets/Renderer.h"
|
#include "Poco/WebWidgets/Renderer.h"
|
||||||
#include "Poco/WebWidgets/Form.h"
|
#include "Poco/WebWidgets/Form.h"
|
||||||
|
#include "Poco/WebWidgets/JSDelegate.h"
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
namespace WebWidgets {
|
namespace WebWidgets {
|
||||||
|
class Form;
|
||||||
namespace ExtJS {
|
namespace ExtJS {
|
||||||
|
|
||||||
|
|
||||||
@@ -68,6 +69,10 @@ public:
|
|||||||
|
|
||||||
static std::string formVariableName(const Form* pForm);
|
static std::string formVariableName(const Form* pForm);
|
||||||
/// Creates the variable name for the form
|
/// Creates the variable name for the form
|
||||||
|
|
||||||
|
static Poco::WebWidgets::JSDelegate createReloadFunction(const std::string& fctName, const Form* pForm);
|
||||||
|
/// Creates a function with the given fctName (can be empty) that reloads the form
|
||||||
|
/// E.g.: add the returned JSDelegate to pReload->buttonClicked
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -38,7 +38,9 @@
|
|||||||
#include "Poco/WebWidgets/Form.h"
|
#include "Poco/WebWidgets/Form.h"
|
||||||
#include "Poco/WebWidgets/Button.h"
|
#include "Poco/WebWidgets/Button.h"
|
||||||
#include "Poco/WebWidgets/WebApplication.h"
|
#include "Poco/WebWidgets/WebApplication.h"
|
||||||
|
#include "Poco/WebWidgets/RequestHandler.h"
|
||||||
#include "Poco/NumberFormatter.h"
|
#include "Poco/NumberFormatter.h"
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@@ -83,6 +85,7 @@ void FormRenderer::renderHead(const Renderable* pRenderable, const RenderContext
|
|||||||
}
|
}
|
||||||
ostr << "]})";
|
ostr << "]})";
|
||||||
theApp.endForm(*pForm);
|
theApp.endForm(*pForm);
|
||||||
|
WebApplication::instance().registerAjaxProcessor(Poco::NumberFormatter::format(pForm->id()), const_cast<Form*>(pForm));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -98,4 +101,18 @@ std::string FormRenderer::formVariableName(const Form* pForm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Poco::WebWidgets::JSDelegate FormRenderer::createReloadFunction(const std::string& fctName, const Form* pForm)
|
||||||
|
{
|
||||||
|
std::ostringstream out;
|
||||||
|
out << "function ";
|
||||||
|
out << fctName << "(){" << std::endl;
|
||||||
|
out << "var theForm = Ext.getCmp('" << pForm->id() << "');" << std::endl;
|
||||||
|
out << "var uri = '" << pForm->getURI().toString() << "/;" << RequestHandler::KEY_EVID << "=" << Form::EV_RELOAD << "&";
|
||||||
|
out << RequestHandler::KEY_ID << "=" << pForm->id() << "';" << std::endl;
|
||||||
|
out << "theForm.load({url:uri,method:'GET'});" << std::endl; // success, failure handlers
|
||||||
|
out << "}" << std::endl;
|
||||||
|
return jsDelegate(out.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } } // namespace Poco::WebWidgets::ExtJS
|
} } } // namespace Poco::WebWidgets::ExtJS
|
||||||
|
@@ -58,11 +58,8 @@ class WebWidgets_API Button: public Control
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Poco::AutoPtr<Button> Ptr;
|
typedef Poco::AutoPtr<Button> Ptr;
|
||||||
typedef Event<Button> ButtonEvent;
|
|
||||||
|
|
||||||
JavaScriptEvent<AjaxParameters> ajaxButtonClicked;
|
|
||||||
|
|
||||||
JavaScriptEvent<ButtonEvent> buttonClicked;
|
JavaScriptEvent<AjaxParameters> buttonClicked;
|
||||||
|
|
||||||
Button(const std::string& name);
|
Button(const std::string& name);
|
||||||
/// Creates a Button with the given name.
|
/// Creates a Button with the given name.
|
||||||
@@ -73,11 +70,8 @@ public:
|
|||||||
Button();
|
Button();
|
||||||
/// Creates an anonymous Button.
|
/// Creates an anonymous Button.
|
||||||
|
|
||||||
void fireAjaxButtonClicked(void* pSender, AjaxParameters& params);
|
void fireButtonClicked(void* pSender, AjaxParameters& params);
|
||||||
/// Fires the ajaxButtonClicked event.
|
/// Fires the ajaxButtonClicked event.
|
||||||
|
|
||||||
void fireButtonClicked(void* pSender);
|
|
||||||
/// Fires the buttonClicked event.
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Button(const std::string& name, const std::type_info& type);
|
Button(const std::string& name, const std::type_info& type);
|
||||||
|
@@ -57,9 +57,7 @@ public:
|
|||||||
|
|
||||||
static const std::string EV_BUTTONCLICKED;
|
static const std::string EV_BUTTONCLICKED;
|
||||||
|
|
||||||
AjaxDelegate ajaxButtonClicked;
|
AjaxDelegate buttonClicked;
|
||||||
|
|
||||||
Delegate buttonClicked;
|
|
||||||
|
|
||||||
ButtonCell(View* pOwner);
|
ButtonCell(View* pOwner);
|
||||||
/// Creates a ButtonCell.
|
/// Creates a ButtonCell.
|
||||||
@@ -68,6 +66,8 @@ public:
|
|||||||
void handleForm(const std::string& field, const std::string& value);
|
void handleForm(const std::string& field, const std::string& value);
|
||||||
|
|
||||||
void handleAjaxRequest(const Poco::Net::NameValueCollection& args, Poco::Net::HTTPServerResponse& response);
|
void handleAjaxRequest(const Poco::Net::NameValueCollection& args, Poco::Net::HTTPServerResponse& response);
|
||||||
|
|
||||||
|
bool serializeJSON(std::ostream& out, const std::string& name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~ButtonCell();
|
~ButtonCell();
|
||||||
@@ -79,6 +79,12 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline bool ButtonCell::serializeJSON(std::ostream& out, const std::string& name)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::WebWidgets
|
} } // namespace Poco::WebWidgets
|
||||||
|
|
||||||
|
|
||||||
|
@@ -102,6 +102,8 @@ public:
|
|||||||
/// the Formatter. If no Formatter has been set, sets the value
|
/// the Formatter. If no Formatter has been set, sets the value
|
||||||
/// to the given string.
|
/// to the given string.
|
||||||
|
|
||||||
|
bool hasValue() const;
|
||||||
|
|
||||||
void setString(const std::string& value);
|
void setString(const std::string& value);
|
||||||
/// Sets the value for this Cell to the given string.
|
/// Sets the value for this Cell to the given string.
|
||||||
|
|
||||||
@@ -281,6 +283,12 @@ inline Cell::EditMode Cell::getEditMode() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Cell::hasValue() const
|
||||||
|
{
|
||||||
|
return !getValue().empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::WebWidgets
|
} } // namespace Poco::WebWidgets
|
||||||
|
|
||||||
|
|
||||||
|
@@ -124,6 +124,8 @@ public:
|
|||||||
void handleAjaxRequest(const Poco::Net::NameValueCollection& args, Poco::Net::HTTPServerResponse& response);
|
void handleAjaxRequest(const Poco::Net::NameValueCollection& args, Poco::Net::HTTPServerResponse& response);
|
||||||
/// Handles a complete AJAX request submitted by the client.
|
/// Handles a complete AJAX request submitted by the client.
|
||||||
|
|
||||||
|
bool serializeJSON(std::ostream& out, const std::string& name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~ComboBoxCell();
|
~ComboBoxCell();
|
||||||
/// Destroys the ComboBoxCell.
|
/// Destroys the ComboBoxCell.
|
||||||
|
@@ -73,6 +73,8 @@ public:
|
|||||||
const Poco::DateTime& getDate() const;
|
const Poco::DateTime& getDate() const;
|
||||||
/// returns the date if set, otherwise an exception, use getValue().empty() to check if it is valid
|
/// returns the date if set, otherwise an exception, use getValue().empty() to check if it is valid
|
||||||
|
|
||||||
|
bool serializeJSON(std::ostream& out, const std::string& name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _format;
|
std::string _format;
|
||||||
};
|
};
|
||||||
|
@@ -41,20 +41,34 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Poco/WebWidgets/ContainerView.h"
|
#include "Poco/WebWidgets/ContainerView.h"
|
||||||
|
#include "Poco/WebWidgets/RequestProcessor.h"
|
||||||
#include "Poco/URI.h"
|
#include "Poco/URI.h"
|
||||||
|
#include "Poco/FIFOEvent.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
|
namespace Net {
|
||||||
|
class HTMLForm;
|
||||||
|
}
|
||||||
namespace WebWidgets {
|
namespace WebWidgets {
|
||||||
|
|
||||||
|
|
||||||
class WebWidgets_API Form: public ContainerView
|
class WebWidgets_API Form: public ContainerView, public RequestProcessor
|
||||||
/// A Form represents a HTML form.
|
/// A Form represents a HTML form.
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Poco::AutoPtr<Form> Ptr;
|
typedef Poco::AutoPtr<Form> Ptr;
|
||||||
|
|
||||||
static const std::string FORM_ID;
|
static const std::string FORM_ID; /// form name to
|
||||||
|
static const std::string EV_RELOAD; /// event name for reloading the form
|
||||||
|
static const std::string METHOD_GET;
|
||||||
|
static const std::string METHOD_POST;
|
||||||
|
|
||||||
|
static const std::string ENCODING_URL; /// "application/x-www-form-urlencoded"
|
||||||
|
static const std::string ENCODING_MULTIPART; /// "multipart/form-data"
|
||||||
|
|
||||||
|
Poco::FIFOEvent<Form*> beforeReload; /// triggered before a Form is reloaded so that you can update form fields with recent values
|
||||||
|
|
||||||
Form(const Poco::URI& uri);
|
Form(const Poco::URI& uri);
|
||||||
/// Creates an anonymous Form.
|
/// Creates an anonymous Form.
|
||||||
@@ -76,12 +90,26 @@ public:
|
|||||||
|
|
||||||
const Poco::URI& getURI() const;
|
const Poco::URI& getURI() const;
|
||||||
/// Returns the URL of the form
|
/// Returns the URL of the form
|
||||||
|
|
||||||
static const std::string METHOD_GET;
|
|
||||||
static const std::string METHOD_POST;
|
|
||||||
|
|
||||||
static const std::string ENCODING_URL; /// "application/x-www-form-urlencoded"
|
void handleForm(const std::string& field, const std::string& value);
|
||||||
static const std::string ENCODING_MULTIPART; /// "multipart/form-data"
|
/// Handles a form field submitted by the client.
|
||||||
|
|
||||||
|
void handleForm(const Poco::Net::HTMLForm& form);
|
||||||
|
/// Handles a complete form submit
|
||||||
|
|
||||||
|
void handleAjaxRequest(const Poco::Net::NameValueCollection& args, Poco::Net::HTTPServerResponse& response);
|
||||||
|
/// Handles a complete AJAX request submitted by the client.
|
||||||
|
|
||||||
|
bool serializeJSON(std::ostream& out, const std::string&);
|
||||||
|
|
||||||
|
void serializeJSONImpl(std::ostream& out);
|
||||||
|
|
||||||
|
RequestProcessor* getFormProcessor(const std::string& name);
|
||||||
|
/// Returns the requestprocessor or null
|
||||||
|
|
||||||
|
void registerFormProcessor(const std::string& name, RequestProcessor* pProc);
|
||||||
|
/// Registers a RequestProcessor for a request.
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Form(const std::string& name, const std::type_info& type, const Poco::URI& uri);
|
Form(const std::string& name, const std::type_info& type, const Poco::URI& uri);
|
||||||
@@ -94,9 +122,11 @@ protected:
|
|||||||
/// Destroys the Form.
|
/// Destroys the Form.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _method;
|
typedef std::map<std::string, RequestProcessor* > RequestProcessorMap;
|
||||||
std::string _encoding;
|
std::string _method;
|
||||||
Poco::URI _uri;
|
std::string _encoding;
|
||||||
|
Poco::URI _uri;
|
||||||
|
RequestProcessorMap _namedChildren;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -121,6 +151,13 @@ inline const Poco::URI& Form::getURI() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Form::serializeJSON(std::ostream& out, const std::string&)
|
||||||
|
{
|
||||||
|
serializeJSONImpl(out);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::WebWidgets
|
} } // namespace Poco::WebWidgets
|
||||||
|
|
||||||
|
|
||||||
|
@@ -116,6 +116,8 @@ public:
|
|||||||
|
|
||||||
// Cell
|
// Cell
|
||||||
void handleForm(const std::string& field, const std::string& value);
|
void handleForm(const std::string& field, const std::string& value);
|
||||||
|
|
||||||
|
bool serializeJSON(std::ostream& out, const std::string& name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~ListBoxCell();
|
~ListBoxCell();
|
||||||
|
@@ -59,6 +59,8 @@ public:
|
|||||||
|
|
||||||
virtual ~NumberFieldCell();
|
virtual ~NumberFieldCell();
|
||||||
/// Destroys the NumberFieldCell.
|
/// Destroys the NumberFieldCell.
|
||||||
|
|
||||||
|
bool serializeJSON(std::ostream& out, const std::string& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -97,6 +97,9 @@ public:
|
|||||||
void handleForm(const std::string& field, const std::string& value);
|
void handleForm(const std::string& field, const std::string& value);
|
||||||
/// Dummy implementation
|
/// Dummy implementation
|
||||||
|
|
||||||
|
bool serializeJSON(std::ostream& out, const std::string& name);
|
||||||
|
/// Dummy implementation
|
||||||
|
|
||||||
void addDynamicFunction(const std::string& jsCode);
|
void addDynamicFunction(const std::string& jsCode);
|
||||||
/// Adds a JavaScript function to the page. Static functions should be written to a JS file
|
/// Adds a JavaScript function to the page. Static functions should be written to a JS file
|
||||||
/// and included via the ResourceManager, only dynamic fucntions (ie. functions that are generated
|
/// and included via the ResourceManager, only dynamic fucntions (ie. functions that are generated
|
||||||
@@ -189,6 +192,12 @@ inline void Page::appendPostRenderCode(const std::string& js)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Page::serializeJSON(std::ostream&, const std::string&)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} } // namespace Poco::WebWidgets
|
} } // namespace Poco::WebWidgets
|
||||||
|
|
||||||
|
|
||||||
|
@@ -58,6 +58,8 @@ public:
|
|||||||
|
|
||||||
virtual ~PasswordFieldCell();
|
virtual ~PasswordFieldCell();
|
||||||
/// Destroys the PasswordFieldCell.
|
/// Destroys the PasswordFieldCell.
|
||||||
|
|
||||||
|
bool serializeJSON(std::ostream& out, const std::string& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Poco/WebWidgets/WebWidgets.h"
|
#include "Poco/WebWidgets/WebWidgets.h"
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@@ -65,6 +66,8 @@ public:
|
|||||||
virtual void handleAjaxRequest(const Poco::Net::NameValueCollection& args, Poco::Net::HTTPServerResponse& response) = 0;
|
virtual void handleAjaxRequest(const Poco::Net::NameValueCollection& args, Poco::Net::HTTPServerResponse& response) = 0;
|
||||||
/// Handles a complete AJAX request submitted by the client.
|
/// Handles a complete AJAX request submitted by the client.
|
||||||
|
|
||||||
|
virtual bool serializeJSON(std::ostream& out, const std::string& name) = 0;
|
||||||
|
/// Serializes a form field to the client.
|
||||||
protected:
|
protected:
|
||||||
RequestProcessor();
|
RequestProcessor();
|
||||||
/// Creates the RequestProcessor.
|
/// Creates the RequestProcessor.
|
||||||
|
@@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Poco/WebWidgets/Button.h"
|
#include "Poco/WebWidgets/Button.h"
|
||||||
|
#include "Poco/FIFOEvent.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@@ -55,6 +56,8 @@ class WebWidgets_API SubmitButton: public Button
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef Poco::AutoPtr<SubmitButton> Ptr;
|
typedef Poco::AutoPtr<SubmitButton> Ptr;
|
||||||
|
|
||||||
|
FIFOEvent<SubmitButton*> afterSubmit; /// thrown whenever all form values are assigned and the submit is done
|
||||||
|
|
||||||
SubmitButton();
|
SubmitButton();
|
||||||
/// Creates an anonymous SubmitButton.
|
/// Creates an anonymous SubmitButton.
|
||||||
|
@@ -208,6 +208,8 @@ public:
|
|||||||
bool autoEdit() const;
|
bool autoEdit() const;
|
||||||
// Returns if autoEdit is on/off
|
// Returns if autoEdit is on/off
|
||||||
|
|
||||||
|
bool serializeJSON(std::ostream& out, const std::string& name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Table(const std::string& name, const std::type_info& type, const TableColumns& tc, TableModel::Ptr pModel);
|
Table(const std::string& name, const std::type_info& type, const TableColumns& tc, TableModel::Ptr pModel);
|
||||||
/// Creates a Table and assigns it the given name.
|
/// Creates a Table and assigns it the given name.
|
||||||
|
@@ -79,6 +79,8 @@ public:
|
|||||||
|
|
||||||
// Cell
|
// Cell
|
||||||
void handleForm(const std::string& field, const std::string& value);
|
void handleForm(const std::string& field, const std::string& value);
|
||||||
|
|
||||||
|
bool serializeJSON(std::ostream& out, const std::string& name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~TextEditCell();
|
~TextEditCell();
|
||||||
|
@@ -75,6 +75,8 @@ public:
|
|||||||
|
|
||||||
// Cell
|
// Cell
|
||||||
void handleForm(const std::string& field, const std::string& value);
|
void handleForm(const std::string& field, const std::string& value);
|
||||||
|
|
||||||
|
bool serializeJSON(std::ostream& out, const std::string& name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~TextFieldCell();
|
~TextFieldCell();
|
||||||
|
@@ -73,6 +73,8 @@ public:
|
|||||||
const Poco::DateTime& getTime() const;
|
const Poco::DateTime& getTime() const;
|
||||||
/// returns the time if set, otherwise an exception, use getValue().empty() to check if it is valid
|
/// returns the time if set, otherwise an exception, use getValue().empty() to check if it is valid
|
||||||
|
|
||||||
|
bool serializeJSON(std::ostream& out, const std::string& name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _format;
|
std::string _format;
|
||||||
TimeField::Format _fmt;
|
TimeField::Format _fmt;
|
||||||
|
@@ -73,6 +73,9 @@ public:
|
|||||||
|
|
||||||
// Cell
|
// Cell
|
||||||
void handleForm(const std::string& field, const std::string& value);
|
void handleForm(const std::string& field, const std::string& value);
|
||||||
|
|
||||||
|
|
||||||
|
bool serializeJSON(std::ostream& out, const std::string& name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~ToggleButtonCell();
|
~ToggleButtonCell();
|
||||||
|
@@ -140,7 +140,7 @@ private:
|
|||||||
|
|
||||||
typedef std::map<std::string, RequestProcessor* > RequestProcessorMap;
|
typedef std::map<std::string, RequestProcessor* > RequestProcessorMap;
|
||||||
typedef std::map<Renderable::ID, SubmitButtonCell*> SubmitButtons;
|
typedef std::map<Renderable::ID, SubmitButtonCell*> SubmitButtons;
|
||||||
typedef std::map<Renderable::ID, RequestProcessorMap> FormMap;
|
typedef std::map<Renderable::ID, Form*> FormMap;
|
||||||
typedef std::stack<Renderable::ID> OpenForms;
|
typedef std::stack<Renderable::ID> OpenForms;
|
||||||
|
|
||||||
ResourceManager::Ptr _pResource;
|
ResourceManager::Ptr _pResource;
|
||||||
|
@@ -101,8 +101,7 @@ void Button::init(Cell::Ptr ptrCell)
|
|||||||
{
|
{
|
||||||
ButtonCell::Ptr pCell = ptrCell.cast<ButtonCell>();
|
ButtonCell::Ptr pCell = ptrCell.cast<ButtonCell>();
|
||||||
poco_check_ptr (pCell);
|
poco_check_ptr (pCell);
|
||||||
pCell->buttonClicked = delegate(*this, &Button::fireButtonClicked);
|
pCell->buttonClicked = ajaxDelegate(*this, &Button::fireButtonClicked);
|
||||||
pCell->ajaxButtonClicked = ajaxDelegate(*this, &Button::fireAjaxButtonClicked);
|
|
||||||
setCell(pCell);
|
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);
|
buttonClicked(pSender, params);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Button::fireButtonClicked(void* pSender)
|
|
||||||
{
|
|
||||||
ButtonEvent clickedEvent(this);
|
|
||||||
buttonClicked(this, clickedEvent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -76,10 +76,9 @@ void ButtonCell::handleAjaxRequest(const Poco::Net::NameValueCollection& args, P
|
|||||||
if (ev == EV_BUTTONCLICKED)
|
if (ev == EV_BUTTONCLICKED)
|
||||||
{
|
{
|
||||||
bool handled(false);
|
bool handled(false);
|
||||||
ajaxButtonClicked(this, args, response, handled);
|
buttonClicked(this, args, response, handled);
|
||||||
if (!handled)
|
if (!handled)
|
||||||
response.send();
|
response.send();
|
||||||
buttonClicked(this);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
response.send();
|
response.send();
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
|
|
||||||
#include "Poco/WebWidgets/ComboBoxCell.h"
|
#include "Poco/WebWidgets/ComboBoxCell.h"
|
||||||
#include "Poco/WebWidgets/RequestHandler.h"
|
#include "Poco/WebWidgets/RequestHandler.h"
|
||||||
|
#include "Poco/DateTime.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@@ -133,4 +134,20 @@ void ComboBoxCell::setSelected(const Any& elem)
|
|||||||
selected(this, aPair);
|
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
|
} } // 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
|
} } // namespace Poco::WebWidgets
|
||||||
|
@@ -35,6 +35,9 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Poco/WebWidgets/Form.h"
|
#include "Poco/WebWidgets/Form.h"
|
||||||
|
#include "Poco/WebWidgets/RequestHandler.h"
|
||||||
|
#include "Poco/NumberParser.h"
|
||||||
|
#include "Poco/Net/HTMLForm.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
namespace Poco {
|
||||||
@@ -42,6 +45,7 @@ namespace WebWidgets {
|
|||||||
|
|
||||||
|
|
||||||
const std::string Form::FORM_ID("__form__");
|
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_GET("GET");
|
||||||
const std::string Form::METHOD_POST("POST");
|
const std::string Form::METHOD_POST("POST");
|
||||||
const std::string Form::ENCODING_URL("application/x-www-form-urlencoded");
|
const std::string Form::ENCODING_URL("application/x-www-form-urlencoded");
|
||||||
@@ -52,7 +56,8 @@ Form::Form(const Poco::URI& uri):
|
|||||||
ContainerView(typeid(Form)),
|
ContainerView(typeid(Form)),
|
||||||
_method(METHOD_POST),
|
_method(METHOD_POST),
|
||||||
_encoding(ENCODING_MULTIPART),
|
_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)),
|
ContainerView(name, typeid(Form)),
|
||||||
_method(METHOD_POST),
|
_method(METHOD_POST),
|
||||||
_encoding(ENCODING_MULTIPART),
|
_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),
|
ContainerView(name, type),
|
||||||
_method(METHOD_POST),
|
_method(METHOD_POST),
|
||||||
_encoding(ENCODING_MULTIPART),
|
_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),
|
ContainerView(type),
|
||||||
_method(METHOD_POST),
|
_method(METHOD_POST),
|
||||||
_encoding(ENCODING_MULTIPART),
|
_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
|
} } // namespace Poco::WebWidgets
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "Poco/WebWidgets/ListBoxCell.h"
|
#include "Poco/WebWidgets/ListBoxCell.h"
|
||||||
|
#include "Poco/DateTime.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Poco {
|
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
|
} } // 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
|
} } // 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
|
} } // namespace Poco::WebWidgets
|
||||||
|
@@ -181,12 +181,7 @@ void RequestHandler::handleAjaxRequest(Poco::Net::HTTPServerRequest& request, Po
|
|||||||
response.send();
|
response.send();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
SubmitButtonCell* pCell = dynamic_cast<SubmitButtonCell*>(pProc);
|
|
||||||
if (pCell) // hide click event from submitbuttons
|
|
||||||
{
|
|
||||||
response.send();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pProc->handleAjaxRequest(args, response);
|
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
|
} } // 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
|
} } // 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
|
} } // 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
|
} } // 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
|
} } // namespace Poco::WebWidgets
|
||||||
|
@@ -113,20 +113,19 @@ void WebApplication::beginForm(const Form& form)
|
|||||||
if (!_forms.empty())
|
if (!_forms.empty())
|
||||||
throw WebWidgetsException("nested forms not allowed");
|
throw WebWidgetsException("nested forms not allowed");
|
||||||
_forms.push(form.id());
|
_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)
|
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())
|
if (!_forms.empty())
|
||||||
{
|
{
|
||||||
FormMap::iterator itForm = _formMap.find(_forms.top());
|
FormMap::iterator itForm = _formMap.find(_forms.top());
|
||||||
poco_assert (itForm != _formMap.end());
|
poco_assert (itForm != _formMap.end());
|
||||||
std::pair<RequestProcessorMap::iterator, bool> res = itForm->second.insert(std::make_pair(fieldName, pProc));
|
|
||||||
if (!res.second)
|
itForm->second->registerFormProcessor(fieldName, pProc);
|
||||||
res.first->second = pProc;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,10 +136,7 @@ RequestProcessor* WebApplication::getFormProcessor(Renderable::ID formId, const
|
|||||||
if (itForm == _formMap.end())
|
if (itForm == _formMap.end())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
RequestProcessorMap::iterator it = itForm->second.find(fieldName);
|
return itForm->second->getFormProcessor(fieldName);
|
||||||
if (it == itForm->second.end())
|
|
||||||
return 0;
|
|
||||||
return it->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -184,27 +180,8 @@ void WebApplication::handleForm(const Poco::Net::HTMLForm& form)
|
|||||||
FormMap::iterator itForm = _formMap.find(formID);
|
FormMap::iterator itForm = _formMap.find(formID);
|
||||||
if (itForm == _formMap.end())
|
if (itForm == _formMap.end())
|
||||||
throw Poco::NotFoundException("unknown form id");
|
throw Poco::NotFoundException("unknown form id");
|
||||||
|
|
||||||
Poco::Net::NameValueCollection::ConstIterator it = form.begin();
|
itForm->second->handleForm(form);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -219,8 +196,7 @@ void WebApplication::notifySubmitButton(Renderable::ID id)
|
|||||||
SubmitButton* pSubmit = dynamic_cast<SubmitButton*>(pOwner);
|
SubmitButton* pSubmit = dynamic_cast<SubmitButton*>(pOwner);
|
||||||
if (pSubmit)
|
if (pSubmit)
|
||||||
{
|
{
|
||||||
Button::ButtonEvent clickedEvent(pSubmit);
|
pSubmit->afterSubmit.notify(pSubmit, pSubmit);
|
||||||
pSubmit->buttonClicked.notify(pSubmit, clickedEvent);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user