diff --git a/code/nel/include/nel/gui/group_html.h b/code/nel/include/nel/gui/group_html.h
index bdec4009e..9e24bfda6 100644
--- a/code/nel/include/nel/gui/group_html.h
+++ b/code/nel/include/nel/gui/group_html.h
@@ -343,6 +343,10 @@ namespace NLGUI
// Current URL
std::string _URL;
+ // Fragment from loading url
+ std::string _UrlFragment;
+ std::map _Anchors;
+ std::vector _AnchorName;
// Current DOMAIN
bool _TrustedDomain;
@@ -378,6 +382,7 @@ namespace NLGUI
bool _IgnoreText;
// the script to execute
std::string _LuaScript;
+ bool _LuaHrefHack;
bool _Object;
std::string _ObjectScript;
@@ -673,6 +678,8 @@ namespace NLGUI
// search if the action / params match the url. look recurs into procedures
bool actionLaunchUrlRecurs(const std::string &ah, const std::string ¶ms, const std::string &url);
+ void registerAnchor(CInterfaceElement* elm);
+
// Browse undo and redo
enum {MaxUrlUndoRedo= 256};
std::string _BrowseUndoButton;
@@ -683,7 +690,8 @@ namespace NLGUI
std::deque _BrowseUndo;
std::deque _BrowseRedo;
void pushUrlUndoRedo(const std::string &url);
- void doBrowse(const char *url);
+ void doBrowse(const char *url, bool force = false);
+ void doBrowseAnchor(const std::string &anchor);
void updateUndoRedoButtons();
void updateRefreshButton();
diff --git a/code/nel/src/gui/group_html.cpp b/code/nel/src/gui/group_html.cpp
index 24610f7eb..338d4f541 100644
--- a/code/nel/src/gui/group_html.cpp
+++ b/code/nel/src/gui/group_html.cpp
@@ -700,12 +700,26 @@ namespace NLGUI
// ***************************************************************************
+ #define registerAnchorName(prefix) \
+ {\
+ if (present[prefix##_ID] && value[prefix##_ID]) \
+ _AnchorName.push_back(value[prefix##_ID]); \
+ }
+
+ // ***************************************************************************
+
void CGroupHTML::addLink (uint element_number, const std::vector &present, const std::vector &value)
{
if (_Browsing)
{
if (element_number == HTML_A)
{
+ registerAnchorName(MY_HTML_A);
+
+ // #fragment works with both ID and NAME so register both
+ if (present[MY_HTML_A_NAME] && value[MY_HTML_A_NAME])
+ _AnchorName.push_back(value[MY_HTML_A_NAME]);
+
if (present[MY_HTML_A_HREF] && value[MY_HTML_A_HREF])
{
string suri = value[MY_HTML_A_HREF];
@@ -716,7 +730,7 @@ namespace NLGUI
else
_Link.push_back ("");
}
- else if (_TrustedDomain && suri[0] == '#')
+ else if (_TrustedDomain && suri[0] == '#' && _LuaHrefHack)
{
// Direct url (hack for lua beginElement)
_Link.push_back (suri.substr(1));
@@ -1043,6 +1057,8 @@ namespace NLGUI
case HTML_DIV:
{
+ registerAnchorName(MY_HTML_DIV);
+
if (present[MY_HTML_DIV_NAME] && value[MY_HTML_DIV_NAME])
_DivName = value[MY_HTML_DIV_NAME];
@@ -1208,36 +1224,42 @@ namespace NLGUI
}
break;
case HTML_H1:
+ registerAnchorName(MY_HTML_H1);
newParagraph(PBeginSpace);
_FontSize.push_back(H1FontSize);
_TextColor.push_back(H1Color);
_GlobalColor.push_back(H1ColorGlobalColor);
break;
case HTML_H2:
+ registerAnchorName(MY_HTML_H2);
newParagraph(PBeginSpace);
_FontSize.push_back(H2FontSize);
_TextColor.push_back(H2Color);
_GlobalColor.push_back(H2ColorGlobalColor);
break;
case HTML_H3:
+ registerAnchorName(MY_HTML_H3);
newParagraph(PBeginSpace);
_FontSize.push_back(H3FontSize);
_TextColor.push_back(H3Color);
_GlobalColor.push_back(H3ColorGlobalColor);
break;
case HTML_H4:
+ registerAnchorName(MY_HTML_H4);
newParagraph(PBeginSpace);
_FontSize.push_back(H4FontSize);
_TextColor.push_back(H4Color);
_GlobalColor.push_back(H4ColorGlobalColor);
break;
case HTML_H5:
+ registerAnchorName(MY_HTML_H5);
newParagraph(PBeginSpace);
_FontSize.push_back(H5FontSize);
_TextColor.push_back(H5Color);
_GlobalColor.push_back(H5ColorGlobalColor);
break;
case HTML_H6:
+ registerAnchorName(MY_HTML_H6);
newParagraph(PBeginSpace);
_FontSize.push_back(H6FontSize);
_TextColor.push_back(H6Color);
@@ -1604,6 +1626,8 @@ namespace NLGUI
break;
case HTML_TABLE:
{
+ registerAnchorName(MY_HTML_TABLE);
+
// Get cells parameters
getCellsParameters (MY_HTML_TABLE, false);
@@ -2024,6 +2048,7 @@ namespace NLGUI
// init
_TrustedDomain = false;
_ParsingLua = false;
+ _LuaHrefHack = false;
_IgnoreText = false;
_BrowseNextTime = false;
_PostNextTime = false;
@@ -2035,6 +2060,7 @@ namespace NLGUI
_LI = false;
_SelectOption = false;
_GroupListAdaptor = NULL;
+ _UrlFragment.clear();
// Register
CWidgetManager::getInstance()->registerClockMsgTarget(this);
@@ -3087,11 +3113,11 @@ namespace NLGUI
void CGroupHTML::refresh()
{
if (!_URL.empty())
- doBrowse(_URL.c_str());
+ doBrowse(_URL.c_str(), true);
}
// ***************************************************************************
- void CGroupHTML::doBrowse(const char *url)
+ void CGroupHTML::doBrowse(const char *url, bool force)
{
// Stop previous browse
if (_Browsing)
@@ -3111,8 +3137,29 @@ namespace NLGUI
nlwarning("(%s) Browsing URL : '%s'", _Id.c_str(), url);
#endif
+
+ CUrlParser uri(url);
+ if (uri.hash.size() > 0)
+ {
+ // Anchor to scroll after page has loaded
+ _UrlFragment = uri.hash;
+
+ uri.inherit(_URL);
+ uri.hash.clear();
+
+ // compare urls and see if we only navigating to new anchor
+ if (!force && _URL == uri.toString())
+ {
+ // scroll happens in updateCoords()
+ invalidateCoords();
+ return;
+ }
+ }
+ else
+ _UrlFragment.clear();
+
// go
- _URL = url;
+ _URL = uri.toString();
_Connecting = false;
_BrowseNextTime = true;
@@ -3177,6 +3224,13 @@ namespace NLGUI
void CGroupHTML::updateCoords()
{
CGroupScrollText::updateCoords();
+
+ // all elements are in their correct place, tell scrollbar to scroll to anchor
+ if (!_Browsing && !_UrlFragment.empty())
+ {
+ doBrowseAnchor(_UrlFragment);
+ _UrlFragment.clear();
+ }
}
// ***************************************************************************
@@ -3228,6 +3282,25 @@ namespace NLGUI
// ***************************************************************************
+ void CGroupHTML::registerAnchor(CInterfaceElement* elm)
+ {
+ if (_AnchorName.size() > 0)
+ {
+ for(uint32 i=0; i < _AnchorName.size(); ++i)
+ {
+ // filter out duplicates and register only first
+ if (!_AnchorName[i].empty() && _Anchors.count(_AnchorName[i]) == 0)
+ {
+ _Anchors[_AnchorName[i]] = elm;
+ }
+ }
+
+ _AnchorName.clear();
+ }
+ }
+
+ // ***************************************************************************
+
void CGroupHTML::addString(const ucstring &str)
{
ucstring tmpStr = str;
@@ -3381,6 +3454,8 @@ namespace NLGUI
newLink->setModulateGlobalColor(getGlobalColor());
// newLink->setLineAtBottom (true);
+ registerAnchor(newLink);
+
if (getA() && !newLink->Link.empty())
{
getParagraph()->addChildLink(newLink);
@@ -3666,6 +3741,8 @@ namespace NLGUI
_TR.clear();
_Forms.clear();
_Groups.clear();
+ _Anchors.clear();
+ _AnchorName.clear();
_CellParams.clear();
_Title = false;
_TextArea = false;
@@ -3747,6 +3824,8 @@ namespace NLGUI
_Paragraph = NULL;
}
+ registerAnchor(group);
+
if (!_DivName.empty())
{
group->setName(_DivName);
@@ -4355,6 +4434,22 @@ namespace NLGUI
// ***************************************************************************
+ void CGroupHTML::doBrowseAnchor(const std::string &anchor)
+ {
+ CInterfaceElement *pIE = _Anchors.find(anchor)->second;
+ if (pIE)
+ {
+ // hotspot depends on vertical/horizontal scrollbar
+ CCtrlScroll *pSB = getScrollBar();
+ if (pSB)
+ {
+ pSB->ensureVisible(pIE, Hotspot_Tx, Hotspot_Tx);
+ }
+ }
+ }
+
+ // ***************************************************************************
+
void CGroupHTML::draw ()
{
CGroupScrollText::draw ();
@@ -4762,7 +4857,13 @@ namespace NLGUI
beginElement(element_number, present, value);
if (element_number == HTML_A)
+ {
+ // ingame lua scripts from browser are using url scheme
+ // reason unknown
+ _LuaHrefHack = true;
addLink(element_number, present, value);
+ _LuaHrefHack = false;
+ }
return 0;
}