Added: URL #fragment navigation.

This commit is contained in:
Nimetu 2015-11-26 11:29:50 +02:00
parent 9014aa6fad
commit d3625364c6
2 changed files with 114 additions and 5 deletions

View file

@ -343,6 +343,10 @@ namespace NLGUI
// Current URL // Current URL
std::string _URL; std::string _URL;
// Fragment from loading url
std::string _UrlFragment;
std::map<std::string,NLGUI::CInterfaceElement *> _Anchors;
std::vector<std::string> _AnchorName;
// Current DOMAIN // Current DOMAIN
bool _TrustedDomain; bool _TrustedDomain;
@ -378,6 +382,7 @@ namespace NLGUI
bool _IgnoreText; bool _IgnoreText;
// the script to execute // the script to execute
std::string _LuaScript; std::string _LuaScript;
bool _LuaHrefHack;
bool _Object; bool _Object;
std::string _ObjectScript; std::string _ObjectScript;
@ -673,6 +678,8 @@ namespace NLGUI
// search if the action / params match the url. look recurs into procedures // search if the action / params match the url. look recurs into procedures
bool actionLaunchUrlRecurs(const std::string &ah, const std::string &params, const std::string &url); bool actionLaunchUrlRecurs(const std::string &ah, const std::string &params, const std::string &url);
void registerAnchor(CInterfaceElement* elm);
// Browse undo and redo // Browse undo and redo
enum {MaxUrlUndoRedo= 256}; enum {MaxUrlUndoRedo= 256};
std::string _BrowseUndoButton; std::string _BrowseUndoButton;
@ -683,7 +690,8 @@ namespace NLGUI
std::deque<std::string> _BrowseUndo; std::deque<std::string> _BrowseUndo;
std::deque<std::string> _BrowseRedo; std::deque<std::string> _BrowseRedo;
void pushUrlUndoRedo(const std::string &url); 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 updateUndoRedoButtons();
void updateRefreshButton(); void updateRefreshButton();

View file

@ -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<bool> &present, const std::vector<const char *> &value) void CGroupHTML::addLink (uint element_number, const std::vector<bool> &present, const std::vector<const char *> &value)
{ {
if (_Browsing) if (_Browsing)
{ {
if (element_number == HTML_A) 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]) if (present[MY_HTML_A_HREF] && value[MY_HTML_A_HREF])
{ {
string suri = value[MY_HTML_A_HREF]; string suri = value[MY_HTML_A_HREF];
@ -716,7 +730,7 @@ namespace NLGUI
else else
_Link.push_back (""); _Link.push_back ("");
} }
else if (_TrustedDomain && suri[0] == '#') else if (_TrustedDomain && suri[0] == '#' && _LuaHrefHack)
{ {
// Direct url (hack for lua beginElement) // Direct url (hack for lua beginElement)
_Link.push_back (suri.substr(1)); _Link.push_back (suri.substr(1));
@ -1043,6 +1057,8 @@ namespace NLGUI
case HTML_DIV: case HTML_DIV:
{ {
registerAnchorName(MY_HTML_DIV);
if (present[MY_HTML_DIV_NAME] && value[MY_HTML_DIV_NAME]) if (present[MY_HTML_DIV_NAME] && value[MY_HTML_DIV_NAME])
_DivName = value[MY_HTML_DIV_NAME]; _DivName = value[MY_HTML_DIV_NAME];
@ -1208,36 +1224,42 @@ namespace NLGUI
} }
break; break;
case HTML_H1: case HTML_H1:
registerAnchorName(MY_HTML_H1);
newParagraph(PBeginSpace); newParagraph(PBeginSpace);
_FontSize.push_back(H1FontSize); _FontSize.push_back(H1FontSize);
_TextColor.push_back(H1Color); _TextColor.push_back(H1Color);
_GlobalColor.push_back(H1ColorGlobalColor); _GlobalColor.push_back(H1ColorGlobalColor);
break; break;
case HTML_H2: case HTML_H2:
registerAnchorName(MY_HTML_H2);
newParagraph(PBeginSpace); newParagraph(PBeginSpace);
_FontSize.push_back(H2FontSize); _FontSize.push_back(H2FontSize);
_TextColor.push_back(H2Color); _TextColor.push_back(H2Color);
_GlobalColor.push_back(H2ColorGlobalColor); _GlobalColor.push_back(H2ColorGlobalColor);
break; break;
case HTML_H3: case HTML_H3:
registerAnchorName(MY_HTML_H3);
newParagraph(PBeginSpace); newParagraph(PBeginSpace);
_FontSize.push_back(H3FontSize); _FontSize.push_back(H3FontSize);
_TextColor.push_back(H3Color); _TextColor.push_back(H3Color);
_GlobalColor.push_back(H3ColorGlobalColor); _GlobalColor.push_back(H3ColorGlobalColor);
break; break;
case HTML_H4: case HTML_H4:
registerAnchorName(MY_HTML_H4);
newParagraph(PBeginSpace); newParagraph(PBeginSpace);
_FontSize.push_back(H4FontSize); _FontSize.push_back(H4FontSize);
_TextColor.push_back(H4Color); _TextColor.push_back(H4Color);
_GlobalColor.push_back(H4ColorGlobalColor); _GlobalColor.push_back(H4ColorGlobalColor);
break; break;
case HTML_H5: case HTML_H5:
registerAnchorName(MY_HTML_H5);
newParagraph(PBeginSpace); newParagraph(PBeginSpace);
_FontSize.push_back(H5FontSize); _FontSize.push_back(H5FontSize);
_TextColor.push_back(H5Color); _TextColor.push_back(H5Color);
_GlobalColor.push_back(H5ColorGlobalColor); _GlobalColor.push_back(H5ColorGlobalColor);
break; break;
case HTML_H6: case HTML_H6:
registerAnchorName(MY_HTML_H6);
newParagraph(PBeginSpace); newParagraph(PBeginSpace);
_FontSize.push_back(H6FontSize); _FontSize.push_back(H6FontSize);
_TextColor.push_back(H6Color); _TextColor.push_back(H6Color);
@ -1604,6 +1626,8 @@ namespace NLGUI
break; break;
case HTML_TABLE: case HTML_TABLE:
{ {
registerAnchorName(MY_HTML_TABLE);
// Get cells parameters // Get cells parameters
getCellsParameters (MY_HTML_TABLE, false); getCellsParameters (MY_HTML_TABLE, false);
@ -2024,6 +2048,7 @@ namespace NLGUI
// init // init
_TrustedDomain = false; _TrustedDomain = false;
_ParsingLua = false; _ParsingLua = false;
_LuaHrefHack = false;
_IgnoreText = false; _IgnoreText = false;
_BrowseNextTime = false; _BrowseNextTime = false;
_PostNextTime = false; _PostNextTime = false;
@ -2035,6 +2060,7 @@ namespace NLGUI
_LI = false; _LI = false;
_SelectOption = false; _SelectOption = false;
_GroupListAdaptor = NULL; _GroupListAdaptor = NULL;
_UrlFragment.clear();
// Register // Register
CWidgetManager::getInstance()->registerClockMsgTarget(this); CWidgetManager::getInstance()->registerClockMsgTarget(this);
@ -3087,11 +3113,11 @@ namespace NLGUI
void CGroupHTML::refresh() void CGroupHTML::refresh()
{ {
if (!_URL.empty()) 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 // Stop previous browse
if (_Browsing) if (_Browsing)
@ -3111,8 +3137,29 @@ namespace NLGUI
nlwarning("(%s) Browsing URL : '%s'", _Id.c_str(), url); nlwarning("(%s) Browsing URL : '%s'", _Id.c_str(), url);
#endif #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 // go
_URL = url; _URL = uri.toString();
_Connecting = false; _Connecting = false;
_BrowseNextTime = true; _BrowseNextTime = true;
@ -3177,6 +3224,13 @@ namespace NLGUI
void CGroupHTML::updateCoords() void CGroupHTML::updateCoords()
{ {
CGroupScrollText::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) void CGroupHTML::addString(const ucstring &str)
{ {
ucstring tmpStr = str; ucstring tmpStr = str;
@ -3381,6 +3454,8 @@ namespace NLGUI
newLink->setModulateGlobalColor(getGlobalColor()); newLink->setModulateGlobalColor(getGlobalColor());
// newLink->setLineAtBottom (true); // newLink->setLineAtBottom (true);
registerAnchor(newLink);
if (getA() && !newLink->Link.empty()) if (getA() && !newLink->Link.empty())
{ {
getParagraph()->addChildLink(newLink); getParagraph()->addChildLink(newLink);
@ -3666,6 +3741,8 @@ namespace NLGUI
_TR.clear(); _TR.clear();
_Forms.clear(); _Forms.clear();
_Groups.clear(); _Groups.clear();
_Anchors.clear();
_AnchorName.clear();
_CellParams.clear(); _CellParams.clear();
_Title = false; _Title = false;
_TextArea = false; _TextArea = false;
@ -3747,6 +3824,8 @@ namespace NLGUI
_Paragraph = NULL; _Paragraph = NULL;
} }
registerAnchor(group);
if (!_DivName.empty()) if (!_DivName.empty())
{ {
group->setName(_DivName); 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 () void CGroupHTML::draw ()
{ {
CGroupScrollText::draw (); CGroupScrollText::draw ();
@ -4762,7 +4857,13 @@ namespace NLGUI
beginElement(element_number, present, value); beginElement(element_number, present, value);
if (element_number == HTML_A) if (element_number == HTML_A)
{
// ingame lua scripts from browser are using <a href="#http://..."> url scheme
// reason unknown
_LuaHrefHack = true;
addLink(element_number, present, value); addLink(element_number, present, value);
_LuaHrefHack = false;
}
return 0; return 0;
} }