diff --git a/WebWidgets/ExtJS/src/ComboBoxCellRenderer.cpp b/WebWidgets/ExtJS/src/ComboBoxCellRenderer.cpp index 185573d49..24312d562 100644 --- a/WebWidgets/ExtJS/src/ComboBoxCellRenderer.cpp +++ b/WebWidgets/ExtJS/src/ComboBoxCellRenderer.cpp @@ -118,6 +118,10 @@ void ComboBoxCellRenderer::renderHead(const Renderable* pRenderable, const Rende ostr << "})"; pCell->beforeLoad += Poco::delegate(&ComboBoxCellRenderer::onLoad); WebApplication::instance().registerAjaxProcessor(Poco::NumberFormatter::format(pOwner->id()), pCell); + if (!pOwner->getName().empty()) + { + WebApplication::instance().registerFormProcessor(pOwner->getName(), const_cast(pCell)); + } } diff --git a/WebWidgets/ExtJS/src/DateFieldCellRenderer.cpp b/WebWidgets/ExtJS/src/DateFieldCellRenderer.cpp index fc2e5cd38..f0c904ea7 100644 --- a/WebWidgets/ExtJS/src/DateFieldCellRenderer.cpp +++ b/WebWidgets/ExtJS/src/DateFieldCellRenderer.cpp @@ -39,6 +39,7 @@ #include "Poco/WebWidgets/ExtJS/FormRenderer.h" #include "Poco/WebWidgets/ExtJS/Utility.h" #include "Poco/WebWidgets/DateFieldCell.h" +#include "Poco/WebWidgets/WebApplication.h" namespace Poco { @@ -67,6 +68,10 @@ void DateFieldCellRenderer::renderHead(const Renderable* pRenderable, const Rend DateFieldCellRenderer::writeCellProperties(pCell, ostr); ostr << "})"; + if (pCell->getOwner() && !pCell->getOwner()->getName().empty()) + { + WebApplication::instance().registerFormProcessor(pCell->getOwner()->getName(), const_cast(pCell)); + } } diff --git a/WebWidgets/ExtJS/src/FormRenderer.cpp b/WebWidgets/ExtJS/src/FormRenderer.cpp index 414abaf50..170633561 100644 --- a/WebWidgets/ExtJS/src/FormRenderer.cpp +++ b/WebWidgets/ExtJS/src/FormRenderer.cpp @@ -67,13 +67,14 @@ void FormRenderer::renderHead(const Renderable* pRenderable, const RenderContext if (pForm->getMethod() == Form::METHOD_POST) ostr << "method:'POST',"; ostr << "title:'" << pForm->getName() << "',autoHeight:true,autoWidth:true,url:'" << pForm->getURI().toString() << "',frame:true,items:["; + //we need to add a hidden entry that contains the Form::FORM_ID plus its id + ostr << "new Ext.form.Hidden({name:'" << Form::FORM_ID << "', value:" << pForm->id() << "})"; ContainerView::ConstIterator it = pForm->begin(); ContainerView::ConstIterator itEnd = pForm->end(); for (; it != itEnd; ++it) { - if (it != pForm->begin()) - ostr << ","; + ostr << ","; // it points to a view pointer (*it)->renderHead(context, ostr); diff --git a/WebWidgets/ExtJS/src/NumberFieldCellRenderer.cpp b/WebWidgets/ExtJS/src/NumberFieldCellRenderer.cpp index 5278ea4de..78ce97566 100644 --- a/WebWidgets/ExtJS/src/NumberFieldCellRenderer.cpp +++ b/WebWidgets/ExtJS/src/NumberFieldCellRenderer.cpp @@ -39,6 +39,7 @@ #include "Poco/WebWidgets/ExtJS/FormRenderer.h" #include "Poco/WebWidgets/ExtJS/Utility.h" #include "Poco/WebWidgets/NumberFieldCell.h" +#include "Poco/WebWidgets/WebApplication.h" namespace Poco { @@ -67,6 +68,10 @@ void NumberFieldCellRenderer::renderHead(const Renderable* pRenderable, const Re TextFieldCellRenderer::writeCellProperties(pCell, ostr); ostr << "})"; + if (pCell->getOwner() && !pCell->getOwner()->getName().empty()) + { + WebApplication::instance().registerFormProcessor(pCell->getOwner()->getName(), const_cast(pCell)); + } } diff --git a/WebWidgets/ExtJS/src/PasswordFieldCellRenderer.cpp b/WebWidgets/ExtJS/src/PasswordFieldCellRenderer.cpp index e6572b9b9..7ff621d77 100644 --- a/WebWidgets/ExtJS/src/PasswordFieldCellRenderer.cpp +++ b/WebWidgets/ExtJS/src/PasswordFieldCellRenderer.cpp @@ -39,6 +39,7 @@ #include "Poco/WebWidgets/ExtJS/FormRenderer.h" #include "Poco/WebWidgets/ExtJS/Utility.h" #include "Poco/WebWidgets/PasswordFieldCell.h" +#include "Poco/WebWidgets/WebApplication.h" namespace Poco { @@ -67,6 +68,10 @@ void PasswordFieldCellRenderer::renderHead(const Renderable* pRenderable, const TextFieldCellRenderer::writeCellProperties(pCell, ostr); ostr << "})"; + if (pCell->getOwner() && !pCell->getOwner()->getName().empty()) + { + WebApplication::instance().registerFormProcessor(pCell->getOwner()->getName(), const_cast(pCell)); + } } diff --git a/WebWidgets/include/Poco/WebWidgets/Form.h b/WebWidgets/include/Poco/WebWidgets/Form.h index 10f09330b..674a1fc36 100644 --- a/WebWidgets/include/Poco/WebWidgets/Form.h +++ b/WebWidgets/include/Poco/WebWidgets/Form.h @@ -54,6 +54,8 @@ class WebWidgets_API Form: public ContainerView public: typedef Poco::AutoPtr
Ptr; + static const std::string FORM_ID; + Form(const Poco::URI& uri); /// Creates an anonymous Form. diff --git a/WebWidgets/include/Poco/WebWidgets/WebApplication.h b/WebWidgets/include/Poco/WebWidgets/WebApplication.h index 5b37b85ae..186b09b10 100644 --- a/WebWidgets/include/Poco/WebWidgets/WebApplication.h +++ b/WebWidgets/include/Poco/WebWidgets/WebApplication.h @@ -41,6 +41,7 @@ #include "Poco/WebWidgets/WebWidgets.h" +#include "Poco/WebWidgets/Form.h" #include "Poco/WebWidgets/Page.h" #include "Poco/WebWidgets/LookAndFeel.h" #include "Poco/WebWidgets/ResourceManager.h" @@ -58,6 +59,7 @@ namespace WebWidgets { class RequestProcessor; +class SubmitButtonCell; class WebWidgets_API WebApplication @@ -116,11 +118,20 @@ public: static std::string clientHostName(); /// Returns the host name of the caller + + void notifySubmitButton(Renderable::ID formId); + /// triggers the click event of the submitbutton + /// required because click event and POST happens in parallel + /// and we want click to be triggered after POST +private: + static Form::Ptr insideForm(const View* pChild); + private: WebApplication(const WebApplication&); WebApplication& operator = (const WebApplication&); typedef std::map RequestProcessorMap; + typedef std::map SubmitButtons; ResourceManager::Ptr _pResource; LookAndFeel::Ptr _pLookAndFeel; @@ -128,6 +139,7 @@ private: Poco::URI _uri; RequestProcessorMap _requestProcessorMap; RequestProcessorMap _ajaxProcessorMap; + SubmitButtons _submitButtons; static Poco::ThreadLocal _pInstance; static Poco::ThreadLocal _clientMachine; }; diff --git a/WebWidgets/src/Form.cpp b/WebWidgets/src/Form.cpp index 57214f83e..4b508a3bf 100644 --- a/WebWidgets/src/Form.cpp +++ b/WebWidgets/src/Form.cpp @@ -41,6 +41,7 @@ namespace Poco { namespace WebWidgets { +const std::string Form::FORM_ID("__form__"); 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"); diff --git a/WebWidgets/src/RequestHandler.cpp b/WebWidgets/src/RequestHandler.cpp index e31594921..78c55eec5 100644 --- a/WebWidgets/src/RequestHandler.cpp +++ b/WebWidgets/src/RequestHandler.cpp @@ -41,9 +41,11 @@ #include "Poco/WebWidgets/Page.h" #include "Poco/WebWidgets/RenderContext.h" #include "Poco/WebWidgets/RequestProcessor.h" +#include "Poco/WebWidgets/SubmitButtonCell.h" #include "Poco/WebWidgets/WebWidgetsException.h" #include "Poco/Net/HTTPServerRequest.h" #include "Poco/Net/HTTPServerResponse.h" +#include "Poco/NumberParser.h" #include "Poco/URI.h" #include "Poco/ThreadLocal.h" #include @@ -90,6 +92,11 @@ void RequestHandler::handleRequest(Poco::Net::HTTPServerRequest& request, Poco:: { handleForm(form); } + Poco::Net::NameValueCollection::ConstIterator it = form.find(Form::FORM_ID); + if (it != form.end()) + { + _pApp->notifySubmitButton(Poco::NumberParser::parse(it->second)); + } handlePageRequest(request, response); } else @@ -144,7 +151,12 @@ void RequestHandler::handleAjaxRequest(Poco::Net::HTTPServerRequest& request, Po response.send(); return; } - + SubmitButtonCell* pCell = dynamic_cast(pProc); + if (pCell) // hide click event from submitbuttons + { + response.send(); + return; + } try { pProc->handleAjaxRequest(args, response); diff --git a/WebWidgets/src/WebApplication.cpp b/WebWidgets/src/WebApplication.cpp index 029bd8ccf..78cd963d8 100644 --- a/WebWidgets/src/WebApplication.cpp +++ b/WebWidgets/src/WebApplication.cpp @@ -36,8 +36,11 @@ #include "Poco/WebWidgets/WebApplication.h" #include "Poco/WebWidgets/RequestProcessor.h" +#include "Poco/WebWidgets/SubmitButtonCell.h" +#include "Poco/WebWidgets/WebWidgetsException.h" #include "Poco/Net/HTMLForm.h" #include "Poco/Net/HTTPServerRequest.h" +#include "Poco/NumberFormatter.h" namespace Poco { @@ -119,6 +122,16 @@ RequestProcessor* WebApplication::getFormProcessor(const std::string& fieldName) void WebApplication::registerAjaxProcessor(const std::string& id, RequestProcessor* pProc) { + SubmitButtonCell* pCell = dynamic_cast(pProc); + if (pCell) + { + Form::Ptr pForm = insideForm(pCell->getOwner()); + if (!pForm) + throw Poco::WebWidgets::WebWidgetsException("submitButton without outer Form detected"); + std::pair res = _submitButtons.insert(std::make_pair(pForm->id(), pCell)); + if (!res.second) + res.first->second = pCell; + } std::pair res = _ajaxProcessorMap.insert(std::make_pair(id, pProc)); if (!res.second) res.first->second = pProc; @@ -158,4 +171,31 @@ void WebApplication::handleForm(const Poco::Net::HTMLForm& form) } +void WebApplication::notifySubmitButton(Renderable::ID id) +{ + SubmitButtons::iterator it = _submitButtons.find(id); + if (it == _submitButtons.end()) + throw WebWidgetsException("failed to find submitButton with id " + Poco::NumberFormatter::format(id)); + + it->second->buttonClicked(this); + _submitButtons.erase(it); +} + + + +Form::Ptr WebApplication::insideForm(const View* pChild) +{ + Form::Ptr ptr; + + while (pChild && !ptr) + { + View::Ptr ptrView = pChild->parent(); + ptr = ptrView.cast(); + pChild = ptrView; + } + + return ptr; +} + + } } // namespace Poco::WebWidgets