Commit 3f358c43 authored by Romain Courteaud's avatar Romain Courteaud

erp5_web_js_style: reload the page only if a different gadget is needed

This requires to rewrite all page content URLs on the fly, to respect the original document baseURI
parent 84d50fc1
......@@ -127,7 +127,32 @@
return result;
}
function parsePageContent(body_element) {
function parsePageContent(body_element, base_uri) {
var i,
element,
element_list,
j,
url_attribute_list = ['src', 'href', 'srcset', 'action'],
url_attribute;
if (base_uri !== undefined) {
// Rewrite relative url (copied from renderjs)
for (j = 0; j < url_attribute_list.length; j += 1) {
url_attribute = url_attribute_list[j];
element_list = body_element.querySelectorAll(
'[' + url_attribute + ']'
);
for (i = 0; i < element_list.length; i += 1) {
element = element_list[i];
element.setAttribute(url_attribute, new URL(
element.getAttribute(url_attribute),
base_uri
).href);
}
}
}
return {
original_content: body_element.innerHTML,
html_content: body_element.querySelector('main').innerHTML,
......@@ -157,7 +182,19 @@
result_dict.xhr.responseText,
'text/html'
),
parsed_content = parsePageContent(dom_parser.body);
parsed_content;
if (gadget.style_gadget_url !== new URL(
dom_parser.body
.getAttribute("data-nostyle-gadget-url"),
dom_parser.baseURI
).href
) {
// If the HTML is not supposed to be rendered
// with the same js style gadget,
// consider this must be reloaded
throw new Error('Trigger an error to force reload');
}
parsed_content = parsePageContent(dom_parser.body, dom_parser.baseURI);
gadget.parsed_content = parsed_content;
parsed_content.page_title = dom_parser.title;
return result_dict.style_gadget.render(parsed_content.html_content,
......@@ -168,32 +205,6 @@
});
}
function isAnotherSitemapLocation(sitemap, url1, url2) {
var is_url1_matching = (url1.indexOf(sitemap.href) === 0),
is_child_another_location,
i;
if (is_url1_matching && (url2.indexOf(sitemap.href) !== 0)) {
return true;
}
if (!is_url1_matching) {
// Both url do not match
return false;
}
// If both match, check sub urls
for (i = 0; i < sitemap.child_list.length; i += 1) {
is_child_another_location = isAnotherSitemapLocation(
sitemap.child_list[i],
url1,
url2
);
if (is_child_another_location) {
return true;
}
}
return false;
}
function listenURLChange() {
var gadget = this;
......@@ -209,9 +220,7 @@
function handleClick(evt) {
var target_element = evt.target.closest('a'),
base_uri = document.baseURI,
link_url,
matching_language_count = 0,
matching_language_base_uri_count = 0;
link_url;
if (!target_element) {
// Only handle link
......@@ -224,34 +233,10 @@
if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) {
return;
}
link_url = new URL(target_element.href, base_uri);
if (link_url.href.indexOf(base_uri) !== 0) {
// Only handle sub path of the base url
// Meaning it will also reload when going from a non default language
// to the default one
return;
}
// Check if going from the default language to another one
// Check if url is suburl from 2 languages (default + the expected one)
gadget.parsed_content.language_list.map(function (language) {
if (link_url.href.indexOf(language.href) === 0) {
matching_language_count += 1;
}
// Ensure current url is in the default language
if (base_uri.indexOf(language.href) === 0) {
matching_language_base_uri_count += 1;
}
});
if ((1 < matching_language_count) &&
(matching_language_base_uri_count === 1)) {
return;
}
// Check if going from a section to a child one
if (isAnotherSitemapLocation(gadget.parsed_content.sitemap,
link_url.href, base_uri)) {
if (base_uri.indexOf(link_url.origin) !== 0) {
// No need to query from another domain
return;
}
......@@ -271,7 +256,8 @@
// to ensure popstate listener is correctly working
// when the user will click on back/forward browser buttons
history.pushState(null, null, target_element.href);
}, function () {
}, function (error) {
console.warn('Cant render the page', error);
// Implement support for managed error
// (like URL is not an HTML document parsable)
// and redirect in such case
......@@ -308,6 +294,8 @@
parsed_content = parsePageContent(gadget.element);
gadget.parsed_content = parsed_content;
parsed_content.page_title = document.title;
gadget.style_gadget_url =
new URL(style_gadget_url, document.baseURI).href;
// Clear the DOM
while (body.firstChild) {
body.firstChild.remove();
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>testJsStyleRelativeLinkHandling</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test JS Style Demo Style</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Test JS Style Demo Style</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/init" />
<tr>
<td>open</td>
<td>${base_url}/ERP5Site_createWebJSStyleZuiteTestData?configuration=language_with_web_site_base</td>
<td></td>
</tr>
<tr>
<td>assertTextPresent</td>
<td>Web Site created.</td>
<td></td>
</tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/wait_for_activities" />
<!-- Initialize -->
<tr>
<td>open</td>
<td>${base_url}/web_site_module/erp5_web_js_style_test_site/erp5_web_js_style_test_section_1/</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//header/h1[text()='JS Style Demo']</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check the page content uses the default language (en)</b></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//main//p[text()='Frontpage content']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//p[text()='Frontpage content']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='gadget_style_url'][contains(text(), 'erp5_web_js_style_test_site/jsstyle_demo.html')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '1')]</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check that the content link are not modified during first loading</b></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//a[text()='base link' and @href='.']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//a[text()='erp5_web_js_style_test_contentpage' and @href='erp5_web_js_style_test_contentpage']</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Go to a child path</b></td>
</tr>
<tr>
<td>click</td>
<td>//nav[@id='sitemap']//a[text()='Demo Section 11']</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '2')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '2')]</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check that the content link are calculated from Demo Section 11</b></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//a[text()='base link' and @href='${base_url}/web_site_module/erp5_web_js_style_test_site/erp5_web_js_style_test_section_1/erp5_web_js_style_test_section_11/']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//a[text()='erp5_web_js_style_test_contentpage' and @href='${base_url}/web_site_module/erp5_web_js_style_test_site/erp5_web_js_style_test_section_1/erp5_web_js_style_test_section_11/erp5_web_js_style_test_contentpage']</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Go to a parent path</b></td>
</tr>
<tr>
<td>click</td>
<td>//nav[@id='sitemap']//a[text()='Demo Style With Language']</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '3')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '3')]</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check that the content link are calculated from Web Site</b></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//a[text()='base link' and @href='${base_url}/web_site_module/erp5_web_js_style_test_site/']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//a[text()='erp5_web_js_style_test_contentpage' and @href='${base_url}/web_site_module/erp5_web_js_style_test_site/erp5_web_js_style_test_contentpage']</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Go to the original path</b></td>
</tr>
<tr>
<td>click</td>
<td>//nav[@id='sitemap']//a[text()='Demo Section 1']</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '4')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '4')]</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check that the content link are calculated from Demo Section 1</b></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//a[text()='base link' and @href='${base_url}/web_site_module/erp5_web_js_style_test_site/erp5_web_js_style_test_section_1/']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//a[text()='erp5_web_js_style_test_contentpage' and @href='${base_url}/web_site_module/erp5_web_js_style_test_site/erp5_web_js_style_test_section_1/erp5_web_js_style_test_contentpage']</td>
<td></td>
</tr>
</tbody></table>
</body>
</html>
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ZopePageTemplate" module="Products.PageTemplates.ZopePageTemplate"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<tuple/>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>content_type</string> </key>
<value> <string>text/html</string> </value>
</item>
<item>
<key> <string>expand</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>testJsStyleWebSiteBrowseSitemapWithLanguageBaseUrl</string> </value>
</item>
<item>
<key> <string>output_encoding</string> </key>
<value> <string>utf-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <unicode></unicode> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<html xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test JS Style Demo Style</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">
<thead>
<tr><td rowspan="1" colspan="3">Test JS Style Demo Style</td></tr>
</thead><tbody>
<tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/init" />
<tr>
<td>open</td>
<td>${base_url}/ERP5Site_createWebJSStyleZuiteTestData?configuration=language_with_web_site_language_base</td>
<td></td>
</tr>
<tr>
<td>assertTextPresent</td>
<td>Web Site created.</td>
<td></td>
</tr>
<tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/wait_for_activities" />
<!-- Initialize -->
<tr>
<td>open</td>
<td>${base_url}/web_site_module/erp5_web_js_style_test_site/</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//header/h1[text()='JS Style Demo']</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check the page content uses the web site</b></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//main//p[text()='Frontpage content']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//p[text()='Frontpage content']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='gadget_style_url'][contains(text(), 'erp5_web_js_style_test_site/jsstyle_demo.html')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '1')]</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Change to one subsection</b></td>
</tr>
<tr>
<td>click</td>
<td>//nav[@id='sitemap']//a[text()='Demo Section 1']</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check the page content uses the web section 1</b></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '2')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//p[text()='Frontpage content']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='gadget_style_url'][contains(text(), 'erp5_web_js_style_test_site/jsstyle_demo.html')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '2')]</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Change to second level subsection</b></td>
</tr>
<tr>
<td>click</td>
<td>//nav[@id='sitemap']//a[text()='Demo Section 11']</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check the page content uses the web section 11</b></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '3')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//p[text()='Frontpage content']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='gadget_style_url'][contains(text(), 'erp5_web_js_style_test_site/jsstyle_demo.html')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '3')]</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Change to parent subsection</b></td>
</tr>
<tr>
<td>click</td>
<td>//nav[@id='sitemap']//a[text()='Demo Section 1']</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check the page content uses the web section 1</b></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '4')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//p[text()='Frontpage content']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='gadget_style_url'][contains(text(), 'erp5_web_js_style_test_site/jsstyle_demo.html')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '4')]</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Change to one sibling</b></td>
</tr>
<tr>
<td>click</td>
<td>//nav[@id='sitemap']//a[text()='Demo Section 2']</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check the page content uses the web section 2</b></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '5')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//p[text()='Frontpage content']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='gadget_style_url'][contains(text(), 'erp5_web_js_style_test_site/jsstyle_demo.html')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '5')]</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Change to one web site</b></td>
</tr>
<tr>
<td>click</td>
<td>//nav[@id='sitemap']//a[text()='Demo Style With Language']</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check the page content uses the web site</b></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '6')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//main//p[text()='Frontpage content']</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='gadget_style_url'][contains(text(), 'erp5_web_js_style_test_site/jsstyle_demo.html')]</td>
<td></td>
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '6')]</td>
<td></td>
</tr>
</tbody></table>
</body>
</html>
\ No newline at end of file
......@@ -65,15 +65,10 @@
<td colspan="3"><b>Change to the not default language</b></td>
</tr>
<tr>
<td>clickAndWait</td>
<td>click</td>
<td>//nav[@id='language']//a[text()='fr']</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//header/h1[text()='JS Style Demo']</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check the page content uses the second language (fr)</b></td>
......@@ -95,7 +90,7 @@
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '1')]</td>
<td>//p[@id='render_count'][contains(text(), '2')]</td>
<td></td>
</tr>
......@@ -103,15 +98,10 @@
<td colspan="3"><b>Change to the second not default language</b></td>
</tr>
<tr>
<td>clickAndWait</td>
<td>click</td>
<td>//nav[@id='language']//a[text()='zh']</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//header/h1[text()='JS Style Demo']</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check the page content uses the third language (zh)</b></td>
......@@ -133,7 +123,7 @@
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '1')]</td>
<td>//p[@id='render_count'][contains(text(), '3')]</td>
<td></td>
</tr>
......@@ -141,15 +131,10 @@
<td colspan="3"><b>Change to the default language</b></td>
</tr>
<tr>
<td>clickAndWait</td>
<td>click</td>
<td>//nav[@id='language']//a[text()='en']</td>
<td></td>
</tr>
<tr>
<td>waitForElementPresent</td>
<td>//header/h1[text()='JS Style Demo']</td>
<td></td>
</tr>
<tr>
<td colspan="3"><b>Check the page content uses the default language (en)</b></td>
......@@ -171,7 +156,7 @@
</tr>
<tr>
<td>assertElementPresent</td>
<td>//p[@id='render_count'][contains(text(), '1')]</td>
<td>//p[@id='render_count'][contains(text(), '4')]</td>
<td></td>
</tr>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment