Skip to content

Commit a649af5

Browse files
author
Koen Deforche
committed
Several changes:
- implemented configuration-based meta headers (#2887) - fix WDatePicker not closing when clicking date picker icon (#2926)
1 parent 1aca2f1 commit a649af5

File tree

11 files changed

+169
-59
lines changed

11 files changed

+169
-59
lines changed

resources/themes/polished/wt.css

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,12 @@ span.Wt-disabled, fieldset.Wt-disabled legend {
474474
border: 1px inset #CCC;
475475
}
476476

477+
.Wt-btn[disabled] {
478+
border: 1px outset #CCC;
479+
cursor: not-allowed;
480+
opacity: 0.75;
481+
}
482+
477483
.Wt-btn-default {
478484
font-weight: bold;
479485
border: 1px outset #37E;

src/Wt/WApplication

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,25 @@ class SoundManager;
7272
typedef boost::function<WApplication* (const WEnvironment&)> ApplicationCreator;
7373
#endif // !WT_TARGET_JAVA
7474

75+
#ifdef WT_TARGET_JAVA
76+
/*! \brief An HTML Meta Header
77+
*/
78+
#endif // WT_TARGET_JAVA
79+
struct MetaHeader {
80+
/*! \brief Constructor
81+
*
82+
* Creates a meta header. The lang and user agents are optional, and should
83+
* be an empty string if not used.
84+
*/
85+
MetaHeader(MetaHeaderType type, const std::string& name,
86+
const WString& content, const std::string& lang,
87+
const std::string& userAgent);
88+
89+
MetaHeaderType type;
90+
std::string name, lang, userAgent;
91+
WString content;
92+
};
93+
7594
/*! \class WApplication Wt/WApplication Wt/WApplication
7695
* \brief Represents an application instance for a single session.
7796
*
@@ -1642,33 +1661,36 @@ public:
16421661

16431662
/*! \brief Adds an HTML meta header.
16441663
*
1645-
* A meta header can only be added in the following situations:
1664+
* \sa addMetaHeader(MetaHeaderType, const std::string&, const WString&, const std::string&)
1665+
*/
1666+
void addMetaHeader(const std::string& name, const WString& content,
1667+
const std::string& lang = "");
1668+
1669+
/*! \brief Adds an HTML meta header.
1670+
*
1671+
* This method sets either a "name" meta headers, which configures a
1672+
* document property, or a "http-equiv" meta headers, which defines
1673+
* a HTTP headers (but these latter headers are being deprecated).
1674+
*
1675+
* A meta header can however only be added in the following situations:
16461676
*
16471677
* - when a plain HTML session is used (including when the user agent is a
16481678
* bot), you can add meta headers at any time.
1649-
*
16501679
* - or, when \ref progressive_bootstrap "progressive bootstrap" is
16511680
* used, you can set meta headers for any type of session, from
16521681
* within the application constructor (which corresponds to the
16531682
* initial request).
1654-
*
16551683
* - but never for a Wt::WidgetSet mode application since then the
16561684
* application is hosted within a foreign HTML page.
16571685
*
1658-
* When a header was previously set for the same \p name, its
1659-
* contents is replaced.
1686+
* These situations coincide with WEnvironment::ajax() returning \c
1687+
* false (see environment()). The reason that it other cases the
1688+
* HTML page has already been rendered, and will not be rerendered
1689+
* since all updates are done dynamically.
16601690
*
1661-
* These situations coincide with WEnvironment::ajax()
1662-
* returning \c false (see environment()).
1663-
*/
1664-
void addMetaHeader(const std::string& name, const WString& content,
1665-
const std::string& lang = "");
1666-
1667-
/*! \brief Adds an HTML meta header.
1668-
*
1669-
* This overloaded method allows to define both "name" meta headers,
1670-
* relating to document properties as well as "http-equiv" meta
1671-
* headers, which define HTTP headers.
1691+
* As an alternative, you can use the &lt;meta-headers&gt;
1692+
* configuration property in the configuration file, which will be
1693+
* applied in all circumstances.
16721694
*
16731695
* \sa removeMetaHeader()
16741696
*/
@@ -2103,15 +2125,6 @@ private:
21032125
bool operator== (const ScriptLibrary& other) const;
21042126
};
21052127

2106-
struct MetaHeader {
2107-
MetaHeader(MetaHeaderType type, const std::string& name,
2108-
const WString& content, const std::string& lang);
2109-
2110-
MetaHeaderType type;
2111-
std::string name, lang;
2112-
WString content;
2113-
};
2114-
21152128
struct MetaLink {
21162129
MetaLink(const std::string &href,
21172130
const std::string &rel,

src/Wt/WApplication.C

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,20 @@ const WtLibVersion WT_INCLUDED_VERSION = WtLibVersion();
4444

4545
const char *WApplication::RESOURCES_URL = "resourcesURL";
4646

47+
MetaHeader::MetaHeader(MetaHeaderType aType,
48+
const std::string& aName,
49+
const WString& aContent,
50+
const std::string& aLang,
51+
const std::string& aUserAgent)
52+
: type(aType), name(aName), lang(aLang), userAgent(aUserAgent),
53+
content(aContent)
54+
{ }
55+
4756
WApplication::ScriptLibrary::ScriptLibrary(const std::string& anUri,
4857
const std::string& aSymbol)
4958
: uri(anUri), symbol(aSymbol)
5059
{ }
5160

52-
WApplication::MetaHeader::MetaHeader(MetaHeaderType aType,
53-
const std::string& aName,
54-
const WString& aContent,
55-
const std::string& aLang)
56-
: type(aType), name(aName), lang(aLang), content(aContent)
57-
{ }
58-
5961
WApplication::MetaLink::MetaLink(const std::string &aHref,
6062
const std::string &aRel,
6163
const std::string &aMedia,
@@ -1103,7 +1105,8 @@ void WApplication::addMetaHeader(MetaHeaderType type,
11031105
}
11041106

11051107
if (!content.empty())
1106-
metaHeaders_.push_back(MetaHeader(type, name, content, lang));
1108+
metaHeaders_.push_back(MetaHeader(type, name, content, lang,
1109+
std::string()));
11071110
}
11081111

11091112
void WApplication::removeMetaHeader(MetaHeaderType type,

src/Wt/WDatePicker.C

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ void WDatePicker::create(WInteractWidget *displayWidget,
100100

101101
displayWidget->clicked().connect(popup_, &WWidget::show);
102102
displayWidget->clicked().connect(this, &WDatePicker::setFromLineEdit);
103-
displayWidget->clicked().preventPropagation();
104103

105104
if (!forEdit_->validator())
106105
forEdit_->setValidator(new WDateValidator(format_, this));

src/Wt/WPdfImage.C

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,6 @@
3030
#endif
3131

3232
namespace {
33-
std::string toUpper(const std::string& s) {
34-
std::string result = s;
35-
std::transform(result.begin(), result.end(), result.begin(), toupper);
36-
return result;
37-
}
38-
3933
void HPDF_STDCALL error_handler(HPDF_STATUS error_no,
4034
HPDF_STATUS detail_no,
4135
void *user_data) {

src/Wt/WWebWidget.C

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1770,7 +1770,7 @@ bool WWebWidget::needsToBeRendered() const
17701770
}
17711771

17721772
bool WWebWidget::setFirstFocus() {
1773-
for (int i = 0; i < children().size(); i++)
1773+
for (unsigned i = 0; i < children().size(); i++)
17741774
if (children()[i]->setFirstFocus())
17751775
return true;
17761776

src/web/Configuration.C

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,41 @@ void Configuration::readApplicationSettings(xml_node<> *app)
813813
properties_[name] = value;
814814
}
815815
}
816+
817+
std::vector<xml_node<> *> metaHeaders = childElements(app, "meta-headers");
818+
for (unsigned i = 0; i < metaHeaders.size(); ++i) {
819+
xml_node<> *metaHeader = metaHeaders[i];
820+
821+
std::string userAgent;
822+
attributeValue(metaHeader, "user-agent", userAgent);
823+
824+
std::vector<xml_node<> *> metas = childElements(metaHeader, "meta");
825+
for (unsigned j = 0; j < metas.size(); ++j) {
826+
xml_node<> *meta = metas[j];
827+
828+
std::string name, property, httpEquiv, content;
829+
attributeValue(meta, "name", name);
830+
attributeValue(meta, "http-equiv", httpEquiv);
831+
attributeValue(meta, "property", property);
832+
attributeValue(meta, "content", content);
833+
834+
MetaHeaderType type;
835+
if (!name.empty())
836+
type = MetaName;
837+
else if (!httpEquiv.empty()) {
838+
type = MetaHttpHeader;
839+
name = httpEquiv;
840+
} else if (!property.empty()) {
841+
type = MetaProperty;
842+
name = property;
843+
} else {
844+
throw WServer::Exception
845+
("<meta> requires attribute 'name', 'property' or 'http-equiv'");
846+
}
847+
848+
metaHeaders_.push_back(MetaHeader(type, name, content, "", userAgent));
849+
}
850+
}
816851
}
817852

818853
void Configuration::rereadConfiguration()

src/web/Configuration.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ class WT_API Configuration
123123
void setNumThreads(int threads);
124124
#endif // WT_TARGET_JAVA
125125

126+
const std::vector<MetaHeader>& metaHeaders() const { return metaHeaders_; }
126127
SessionPolicy sessionPolicy() const;
127128
int numProcesses() const;
128129
int numThreads() const;
@@ -239,6 +240,7 @@ class WT_API Configuration
239240
bool webglDetection_;
240241

241242
std::vector<BootstrapEntry> bootstrapConfig_;
243+
std::vector<MetaHeader> metaHeaders_;
242244

243245
bool connectorSlashException_;
244246
bool connectorNeedReadBody_;

src/web/WebRenderer.C

Lines changed: 60 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "Wt/WApplication"
1212
#include "Wt/WContainerWidget"
1313
#include "Wt/WRandom"
14+
#include "Wt/WRegExp"
1415
#include "Wt/WWebWidget"
1516
#include "Wt/WStringStream"
1617
#include "Wt/WTheme"
@@ -1754,32 +1755,75 @@ void WebRenderer::learningIncomplete()
17541755
std::string WebRenderer::headDeclarations() const
17551756
{
17561757
EscapeOStream result;
1758+
1759+
const Configuration& conf = session_.env().server()->configuration();
1760+
1761+
const std::vector<MetaHeader>& confMetaHeaders = conf.metaHeaders();
1762+
std::vector<MetaHeader> metaHeaders;
1763+
1764+
for (unsigned i = 0; i < confMetaHeaders.size(); ++i) {
1765+
const MetaHeader& m = confMetaHeaders[i];
1766+
1767+
bool add = true;
1768+
if (!m.userAgent.empty()) {
1769+
WT_USTRING s = WT_USTRING::fromUTF8(session_.env().userAgent());
1770+
WRegExp expr(WT_USTRING::fromUTF8(m.userAgent));
1771+
if (!expr.exactMatch(s))
1772+
add = false;
1773+
}
1774+
1775+
if (add)
1776+
metaHeaders.push_back(confMetaHeaders[i]);
1777+
}
17571778

17581779
if (session_.app()) {
1759-
for (unsigned i = 0; i < session_.app()->metaHeaders_.size(); ++i) {
1760-
const WApplication::MetaHeader& m = session_.app()->metaHeaders_[i];
1780+
const std::vector<MetaHeader>& appMetaHeaders
1781+
= session_.app()->metaHeaders_;
17611782

1762-
result << "<meta";
1783+
for (unsigned i = 0; i < appMetaHeaders.size(); ++i) {
1784+
const MetaHeader& m = appMetaHeaders[i];
17631785

1764-
if (!m.name.empty()) {
1765-
std::string attribute;
1766-
switch (m.type) {
1767-
case MetaName: attribute = "name"; break;
1768-
case MetaProperty: attribute = "property"; break;
1769-
case MetaHttpHeader: attribute = "http-equiv"; break;
1770-
}
1786+
bool add = true;
1787+
for (unsigned j = 0; j < metaHeaders.size(); ++j) {
1788+
MetaHeader& m2 = metaHeaders[j];
17711789

1772-
appendAttribute(result, attribute, m.name);
1790+
if (m.type == m2.type && m.name == m2.name) {
1791+
m2.content = m.content;
1792+
add = false;
1793+
break;
1794+
}
17731795
}
17741796

1775-
if (!m.lang.empty())
1776-
appendAttribute(result, "lang", m.lang);
1797+
if (add)
1798+
metaHeaders.push_back(m);
1799+
}
1800+
}
17771801

1778-
appendAttribute(result, "content", m.content.toUTF8());
1802+
for (unsigned i = 0; i < metaHeaders.size(); ++i) {
1803+
const MetaHeader& m = metaHeaders[i];
17791804

1780-
closeSpecial(result);
1805+
result << "<meta";
1806+
1807+
if (!m.name.empty()) {
1808+
std::string attribute;
1809+
switch (m.type) {
1810+
case MetaName: attribute = "name"; break;
1811+
case MetaProperty: attribute = "property"; break;
1812+
case MetaHttpHeader: attribute = "http-equiv"; break;
1813+
}
1814+
1815+
appendAttribute(result, attribute, m.name);
17811816
}
1782-
1817+
1818+
if (!m.lang.empty())
1819+
appendAttribute(result, "lang", m.lang);
1820+
1821+
appendAttribute(result, "content", m.content.toUTF8());
1822+
1823+
closeSpecial(result);
1824+
}
1825+
1826+
if (session_.app()) {
17831827
for (unsigned i = 0; i < session_.app()->metaLinks_.size(); ++i) {
17841828
const WApplication::MetaLink& ml = session_.app()->metaLinks_[i];
17851829

@@ -1807,7 +1851,6 @@ std::string WebRenderer::headDeclarations() const
18071851
* progressive boot.
18081852
*/
18091853
if (session_.env().agent() < WEnvironment::IE9) {
1810-
const Configuration& conf = session_.env().server()->configuration();
18111854
bool selectIE7 = conf.uaCompatible().find("IE8=IE7")
18121855
!= std::string::npos;
18131856

src/web/WebRenderer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <string>
1111
#include <vector>
1212
#include <set>
13+
1314
#include "Wt/WDateTime"
1415
#include "Wt/WEnvironment"
1516
#include "Wt/WStatelessSlot"
@@ -20,7 +21,9 @@ class WebRequest;
2021
class WebResponse;
2122
class WebStream;
2223
class DomElement;
24+
class EscapeOStream;
2325
class FileServe;
26+
class MetaHeader;
2427

2528
class WApplication;
2629
class WWidget;

0 commit comments

Comments
 (0)