Bug #1847
closeddoJavaScript on WWidget in wt.3.3.0
Description
Hi,
I have this object structure:
CBase : WTemplate
{
public:
CBase()
{
addFunction("tr", &Wt::WTemplate::Functions::tr);
...
bindWidget("b1", b1_);
bindWidget("b2", b2_);
}
protected:
virtual void refresh()
{
WTemplate::refresh();
doJavaScript('custom_java_script_function');
}
...
private:
//internal widgets
Wt::WPushButton* b1_;
Wt::WPushButton* b2_;
}
CDerived : public CBase
{
public:
CDerived()
{
setTemplateText(tr("MyTemplate"));
...
bindWidget("medit", edit_);
}
private:
Wt::WLineEdit* edit_;
}
The problem arises when calling WApplication::setLocale on my web application, for changing the locale. I've noticed that setLocale calls WApplication::refresh() which calls refresh on every widget in the application, so CBase::doJavaScript is called on changing the locale.
When the 'custom_java_script_function' is executed, it checks the presence of the DOM object associated with the Wt::WLineEdit* edit_ in CDerived, but the object is not present in the DOM tree yet (I think this is true for all widgets that are bound in the template, from base class too). As you can see above, in CBase, the called doJavaScript is the WWidget::doJavaScript so I would expect that the DOM object associated with the edit_ to be in the DOM tree when the 'custom_java_script_function' is called since it is a member of CDerived template widget.
I tried to override the refresh() method in CDerived too and have it call WTemplate::refresh() and CBase::refresh(), but with the same effect.
This problem didn't manifest with wt.3.2.1. I have checked, and with wt.3.2.1 all widgets (CBase and CDerived with their members)exist in the DOM tree at the moment when 'custom_java_script_function' executes.
Also it doesn't occur when refreshing the page using F5 in browser.
Is this a bug in wt.3.3.0 or maybe I should use another approach ?
Files
Updated by Koen Deforche over 11 years ago
- Status changed from New to InProgress
- Assignee set to Koen Deforche
- Target version set to 3.3.1
Hey,
I can't completely follow your explanation, but I cannot recall a change from 3.2.3 to 3.3.0 that could be involved. Clearly it sounds like a bug in 3.3.0.
I would be really interested if this can be reproduced with a small test case ?
Regards,
koen
Updated by W X over 11 years ago
Hi,
I was busy with some other stuff and now I found the time to create a small test case.
I have added it as an archive to this post. It contains the binaries built with wt3.2.1 and wt3.3.0 and also the source code.
Details on how to run the tests are in a file named 'HowTo.txt'.
I hope this helps finding the root-cause. If it is indeed a bug, could you provide a patch on top of wt.3.3.0 ? If is not a bug, please let me know what I do wrong.
Thank you!
Updated by W X over 11 years ago
After starting the test application, accessing localhost from a browser should display an edit box and a combo box. The issue can be reproduced by changing the selection in the combo box. That will trigger the changing of the application locale with setLocale().
Updated by W X over 11 years ago
Hey,
I see there is no update on this. Do you plan to look over this issue? Thanks!
Updated by Wim Dumon over 11 years ago
- Status changed from InProgress to Resolved
- Assignee changed from Koen Deforche to Wim Dumon
Thanks for the test case, it's indeed a regression where for WTemplate doJavaScript was executed before the DOM is fully constructed. It is now fixed. Will appear in public git soon.
Wim.
Updated by W X over 11 years ago
Thanks, guys! Could you provide a patch for this?
Updated by Wim Dumon over 11 years ago
----------------------------- src/web/DomElement.C -----------------------------
@@ -1157,6 +1157,7 @@ void DomElement::createElement(EscapeOStream& out, WApplication *app,
out << "');";
out << domInsertJS;
renderInnerHtmlJS(out, app);
+ renderDeferredJavaScript(out);
} else {
out << "document.createElement('" << elementNames_[type_] << "');";
out << domInsertJS;
@@ -1333,6 +1334,10 @@ std::string DomElement::asJavaScript(EscapeOStream& out,
out << "$('#" << childrenToSave_[i] << "').replaceWith(c"
<< var_ << (int)i << ");";
+ // Fix for http://redmine.emweb.be/issues/1847: custom JS
+ // won't find objects that still have to be moved in place
+ renderDeferredJavaScript(out);
+
if (!childrenUpdated)
for (unsigned i = 0; i < updatedChildren_.size(); ++i) {
DomElement *child = updatedChildren_[i];
@@ -1395,11 +1400,6 @@ void DomElement::renderInnerHtmlJS(EscapeOStream& out, WApplication *app) const
}
}
- if (!javaScript_.empty()) {
- declare(out);
- out << javaScript_ << '\n';
- }
-
if (timeOut_ != -1) {
out << app->javaScriptClass() << "._p_.addTimerEvent('"
<< id_ << "', " << timeOut_ << ','
@@ -1407,6 +1407,14 @@ void DomElement::renderInnerHtmlJS(EscapeOStream& out, WApplication *app) const
}
}
+void DomElement::renderDeferredJavaScript(EscapeOStream& out) const
+{
+ if (!javaScript_.empty()) {
+ declare(out);
+ out << javaScript_ << '\n';
+ }
+}
+
void DomElement::setJavaScriptProperties(EscapeOStream& out,
WApplication *app) const
{
----------------------------- src/web/DomElement.h -----------------------------
@@ -519,6 +519,7 @@ private:
const std::string& parentVar, int pos,
WApplication *app);
void renderInnerHtmlJS(EscapeOStream& out, WApplication *app) const;
+ void renderDeferredJavaScript(EscapeOStream& out) const;
Mode mode_;
bool wasEmpty_;
Updated by Koen Deforche over 11 years ago
- Status changed from Resolved to Closed