Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Voormann2020-09-30 10:21:28 +0000
committerAndrey Loskutov2020-10-05 08:52:08 +0000
commit0a142a8b188eaa620184690b3f1129b674c109d8 (patch)
tree0fad887cc5a6e6accc35ceff22ebd4381d4ab5a4
parente9568208f216b865ec16d6d1487650729d2bad3e (diff)
downloadeclipse.platform.ua-0a142a8b188eaa620184690b3f1129b674c109d8.tar.gz
eclipse.platform.ua-0a142a8b188eaa620184690b3f1129b674c109d8.tar.xz
eclipse.platform.ua-0a142a8b188eaa620184690b3f1129b674c109d8.zip
This is a prototype that can be activated with the following Java property: -Dorg.eclipse.help.webapp.experimental.ui=m/index.html For testing/debugging, further development, etc. see: /org.eclipse.help.webapp/m/README.md This prototype is based on HTML 5 with an iframe for the content and, unlike the legacy UI, does not use HTML 4 framesets. Technically, it sits on top of the legacy UI. For example, when doing a full search, the HTML page of the legacy UI will be parsed and rendered in the web browser using JavaScript. This has disadvantages, but it made it easier to develop this prototype as a plugin without the need to patch Eclipse. But once it is integrated into Eclipse, this should be changed (in 'm/README.md' see 'Further development'). Improvements compared to the legacy UI: - Responsive, e.g. by automatically hiding the TOC bar on small screens - Search as you type and auto completion of search terms - Topic preview when hovering over instant search results - Search scopes drop-down in the search field to search in all books, in the current book, in the current chapter or in a user-defined scope - Full search results shown as a page instead of as side bar - Full search results can be filtered by books - Infocenter: UI designed aware of mobile devices - Infocenter: URL contains topic or search, so a deep link can be bookmarked or shared in the usual way The "Index" tab of the legacy UI was dropped in favor of a simpler UI. Things to improve, where this prototype falls behind the legacy UI: - Internationalization (by externalize Strings) - Right-to-left (RTL) support - Accessibility (HTML5 ARIA, keyboard support, color contrast, etc.) - Dark theme support - Customization, e.g. to be able to specify an Infocenter header/footer - ...? The prototype was developed as a plugin on GitHub and both authors agreed to contribute it to Eclipse (see Signed-off-by below): https://github.com/howlger/Eclipse-Help-Modernized Change-Id: I8635deabf69a84ed293a9e89e2424b8be1212262 Signed-off-by: Harald Hermann <harald.hermann@advantest.com> Signed-off-by: Holger Voormann <eclipse@voormann.de>
-rw-r--r--org.eclipse.help.webapp/build.properties3
-rw-r--r--org.eclipse.help.webapp/index.jsp33
-rw-r--r--org.eclipse.help.webapp/m/README.md170
-rw-r--r--org.eclipse.help.webapp/m/index.css668
-rw-r--r--org.eclipse.help.webapp/m/index.html19
-rw-r--r--org.eclipse.help.webapp/m/index.js2845
-rw-r--r--org.eclipse.help.webapp/plugin.xml5
7 files changed, 3740 insertions, 3 deletions
diff --git a/org.eclipse.help.webapp/build.properties b/org.eclipse.help.webapp/build.properties
index 2c55ef6b3..a61948a72 100644
--- a/org.eclipse.help.webapp/build.properties
+++ b/org.eclipse.help.webapp/build.properties
@@ -24,7 +24,8 @@ bin.includes = plugin.xml,\
index.jsp,\
advanced/,\
.options,\
- advancedstate/
+ advancedstate/,\
+ m/
output.. = bin/
javacWarnings..=-unavoidableGenericProblems
diff --git a/org.eclipse.help.webapp/index.jsp b/org.eclipse.help.webapp/index.jsp
index 6d6f47443..117fc46e0 100644
--- a/org.eclipse.help.webapp/index.jsp
+++ b/org.eclipse.help.webapp/index.jsp
@@ -12,6 +12,8 @@
IBM Corporation - initial API and implementation
--%>
<%@ page import="org.eclipse.help.internal.webapp.data.*" errorPage="/advanced/err.jsp" contentType="text/html; charset=UTF-8"%>
+<%@ page import="java.util.Scanner" %>
+<%@ page import="java.net.URL" %>
<%
request.setCharacterEncoding("UTF-8");
ServerState.webappStarted(application,request, response);
@@ -33,7 +35,34 @@
</body>
</html>
<%
- }else {
- request.getRequestDispatcher("/advanced/index.jsp" + data.getQuery()).forward(request, response);
+ } else {
+
+ // Experimental UI: see bug 501718
+ String experimentalUi = System.getProperty("org.eclipse.help.webapp.experimental.ui");
+ if (request.getParameter("legacy") == null && experimentalUi != null) {
+ try {
+ // In a JSP forwarding to non JSP resources does not work
+ // (page is shown, but "java.lang.IllegalStateException: STREAM" is thrown)
+ // so read from URL instead:
+ URL baseUrl = new URL(request.getRequestURL().toString());
+ URL forwardUrl = new URL(baseUrl, experimentalUi);
+ // Same-origin policy
+ if (!baseUrl.getProtocol().equals(forwardUrl.getProtocol())
+ || !baseUrl.getHost().equals(forwardUrl.getHost())
+ || baseUrl.getPort() != forwardUrl.getPort()) throw new Exception();
+ // Read it as InputStream and convert it to a String
+ // (by using a Scanner with a delimiter that cannot be found: \A - start of input)
+ Scanner scanAll = new Scanner(forwardUrl.openStream()).useDelimiter("\\A");
+ response.getWriter().write(scanAll.hasNext() ? scanAll.next() : "");
+ } catch (Exception e) {
+ // Experimental UI resource not found, so fall back to legacy UI
+ request.getRequestDispatcher("/advanced/index.jsp" + data.getQuery()).forward(request, response);
+ }
+
+ // legacy UI
+ } else {
+ request.getRequestDispatcher("/advanced/index.jsp" + data.getQuery()).forward(request, response);
+ }
+
}
%>
diff --git a/org.eclipse.help.webapp/m/README.md b/org.eclipse.help.webapp/m/README.md
new file mode 100644
index 000000000..5f90459a8
--- /dev/null
+++ b/org.eclipse.help.webapp/m/README.md
@@ -0,0 +1,170 @@
+# Modernized help UI
+
+This prototype is based on HTML 5 with an `iframe` for the content and, unlike
+the legacy UI, does not use HTML 4 `frameset`s. Technically, it sits on top of
+the legacy UI. For example, when doing a full search, the HTML page of the
+legacy UI will be parsed and rendered in the web browser (widget) using
+JavaScript. This has disadvantages, but it has made it easier to develop this
+prototype as a plugin without the need to patch Eclipse.
+
+Once the new UI no longer requires anything from the legacy UI and is no longer
+lagging behind in terms of internationalization and accessibility, the legacy UI
+can be deprecated and removed: see [_Further development_](#further-development)
+below.
+
+Improvements compared to the legacy UI:
+* Responsive, e.g. by automatically hiding the TOC bar on small screens
+* Search as you type and auto completion of search terms
+* Topic preview when hovering over instant search results
+* Search scopes drop-down in the search field to search in all books, in the
+ current book, in the current chapter or in a user-defined scope
+* Full search results shown as a page instead of as side bar
+* Full search results can be filtered by books
+* Infocenter: UI designed aware of mobile devices
+* Infocenter: URL contains topic or search, so a deep link can be bookmarked or
+ shared in the usual way
+
+
+## Activation
+
+This prototype can be activated with the following Java property:
+
+ -Dorg.eclipse.help.webapp.experimental.ui=m/index.html
+
+To test, modify and/or customize this prototype, the files in this folder can
+be put in a separate plugin (in `index.html` the links to the JavaScript and
+CSS file have to be changed from `m/...` to something like
+`rtopic/com.example.my_plugin/...`) and activated as follows (assuming
+the plugin has the symbolic name `com.example.my_plugin`; using the raw
+topic help link `rtopic/<plugin>/<optional-path>/<file>`):
+
+ -Dorg.eclipse.help.webapp.experimental.ui=rtopic/com.example.my_plugin/index.html
+
+
+## Further development
+
+Unsorted list of things to improve and where the legacy UI is currently used:
+* Create the page dynamically to avoid a callback to determine the mode, whether
+Infocenter or Eclipse embedded help (the latter with previous/next navigation
+buttons and bookmark support) and to determine the initial content page.
+ * [`/advanced/tabs.jsp`](http://127.0.0.1:49999/help/advanced/tabs.jsp)
+ * [`/advanced/content.jsp`](http://127.0.0.1:49999/help/advanced/content.jsp)
+* Return search results directly as HTML page instead of parsing and re-rendering legacy HTML page
+ * [`/advanced/searchView.jsp`](http://127.0.0.1:49999/help/advanced/searchView.jsp?showSearchCategories=false&searchWord=test&maxHits=500)
+* Print chapter
+ * [`/advanced/print.jsp`](127.0.0.1:49999/help/advanced/print.jsp?topic=/../nav/0)
+* Rest API to get the following as JSON instead of requesting and parsing the legacy UI
+ * Search as you type and search term completion: currently, when typing `fo`, a search is executed for `fo*` (which means starts with `fo`), but this disables stemming like in the full search (which means when entering `logging`, pages containing `log` or `logs` are not found; ideally _starts with_ and stemming should be combined; the search term completion proposals are currently computed from the words contained in the results, for which there are better ways to do this on the server side
+ * [`/advanced/searchView.jsp`](http://127.0.0.1:49999/help/advanced/searchView.jsp?showSearchCategories=false&searchWord=test*&maxHits=7)
+ * User-defined search scopes
+ * [`/advanced/workingSetManager.jsp`](http://127.0.0.1:49999/help/advanced/workingSetManager.jsp) - list of scopes
+ * [`/advanced/workingSetState.jsp`](http://127.0.0.1:49999/help/advanced/workingSetState.jsp?operation=add&workingSet=example_scope) - add, edit or remove a scope
+ * [`/scopeState.jsp`](http://127.0.0.1:49999/scopeState.jsp?workingSet=) - set or unset scope
+ * Bookmarks
+ * [`/advanced/bookmarksView.jsp`](127.0.0.1:49999/help/advanced/print.jsp?topic=/../nav/0)
+ * Storing UI settings: TOC side bar width and show/hidden, search results filter tree expanded or collapsed, etc.
+* Things to improve (where this prototype currently falls behind the legacy UI):
+ * Internationalization (by externalize Strings)
+ * Right-to-left (RTL) support
+ * Accessibility (HTML5 ARIA, keyboard support, color contrast, etc.)
+ * Dark theme support
+ * User-defined search scope:
+ * Prevent to create an empty scope
+ * Activate search scope on creation
+ * Printing via shortcut (Ctrl+P) should print the content
+ only, even when the focus is outside the content (e.g. in
+ the search field)
+ * Bookmarks: adding a bookmark should be more intuitive
+ * Customization, e.g. to be able to specify an Infocenter
+ (header/banner, footer, etc.): support of
+ [legacy options](https://help.eclipse.org/latest/topic/org.eclipse.platform.doc.isv/guide/ua_help_setup_preferences.htm)
+ * ...
+* By default redirect via `.../index.jsp#topic/...` instead of via `.../index.jsp?topic=...`, but still support such legacy links
+* ...
+
+
+## Design decisions and debugging hints
+
+To use a web browser for debugging, specify a fixed port for the help server,
+e.g. `-Dserver_port=49999`, in Eclipse open the help window
+(_Help > Help Contents_) and in the web browser open one or more of the
+following pages:
+* [Modernized UI: `http://127.0.0.1:49999/help/index.jsp`](http://127.0.0.1:49999/help/index.jsp)
+* [Legacy UI: `http://127.0.0.1:49999/help/index.jsp?legacy`](http://127.0.0.1:49999/help/index.jsp?legacy)
+
+
+### Drop of _Index_ tab
+
+The _Index_ tab of the legacy UI was dropped in favor of a simpler UI.
+
+
+### Browser support
+
+On the one hand state of the art should be used, on the other hand as many
+browsers as possible should be supported.
+
+&#8594; Support browsers that support Flexbox ([98.74%](https://caniuse.com/#feat=flexbox)):
+Chrome 21, Internet Explorer 10, Firefox 22, Android Browser 21, etc. and higher
+
+See:
+* [Browser support](https://caniuse.com/)
+* Tutorial/specification: [CSS](https://www.w3schools.com/csS/default.asp),
+ [JavaScript](https://www.w3schools.com/js/default.asp)
+* JavaScript minifiers:
+ * https://javascript-minifier.com/
+ * https://javascriptminifier.com/
+
+
+### General layout (CSS): [`Flexbox`](https://www.w3schools.com/csS/css3_flexbox.asp) ([tutorial](https://css-tricks.com/snippets/css/a-guide-to-flexbox/), [98.74%](https://caniuse.com/#feat=flexbox))
+
+* Instead of `float`, layout via tables (both are deprecated for that) and `gridx` (since it is too new and not yet widely supported)
+* If needed, consider add fallback for IE 6-9 (see [Flexbox Fallbacks](http://maddesigns.de/flexbox-fallbacks-2670.html))
+
+
+### Navigation and deep linking
+
+Going back in the browser history can cause issues in combination with deep linking, since the navigation is done in
+the `iframe` except for the search page which is not shown in the `iframe`.
+The problem is that when going back to a search page, the search might need to be submitted again and for this the
+query must be known.
+
+Ways that don't work:
+
+* Deep link containing query as hash of the top window (`...#q=...`) set via
+ [`history.pushState(...)`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState):
+ top window hash might not be restored when navigation happens also in the content `iframe`
+* Query as hash or as query of the content `iframe` set via
+ [`history.pushState(...)`](https://developer.mozilla.org/en-US/docs/Web/API/History/pushState):
+ conflicts with existing hashes/queries of content pages and does not work with external content pages
+* [Data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs) used in content `iframe`
+ containing the query: not allowed in Internet Explorer for security reasons
+
+Chosen solution:
+
+* For full search set content `iframe` instead of doing a remote request and get
+ result from live DOM of the `iframe` when loaded
+
+
+### Search
+
+* Without [interim results](https://github.com/howlger/Eclipse-Help-Modernized/blob/541481f486008f665244446052d2a7e6d147223c/de.agilantis.help_ui_modernized/index.js#L482-L513) displayed [semi-transparent](https://github.com/howlger/Eclipse-Help-Modernized/blob/541481f486008f665244446052d2a7e6d147223c/de.agilantis.help_ui_modernized/index.js#L607) since this is only helpful in rare cases (very slow responds and previous cached query containing hits of current query)
+
+To simulate a slow response replace `return function(data) {` with
+
+```
+ return function(data) {
+setTimeout(function(data) { return function() {processData(data)}}(data), 1000);
+};
+function processData(data) {
+```
+
+
+## Issues caused by `<iframe>`
+
+To catch mouse and click events (for slider and drop-down menues) add an overlay element covering the whole page (see `createOverlay()`).
+
+Debug overlay by adding the following line after the line `overlayStyle.width = '100%';`:
+
+```
+overlayStyle.background = 'rgba(200, 100, 100, .2)';
+```
diff --git a/org.eclipse.help.webapp/m/index.css b/org.eclipse.help.webapp/m/index.css
new file mode 100644
index 000000000..2595bff90
--- /dev/null
+++ b/org.eclipse.help.webapp/m/index.css
@@ -0,0 +1,668 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Holger Voormann and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************
+
+ Structure:
+ ____________________________________________
+ | #h(eader) |
+ |--------------------------------------------|
+ | #m(ain area) |
+ | ________________________________________ |
+ | | | | | |
+ | | #t(oc) | #s(lider) | #c(ontent iframe) | |
+ | |________|___________|___________________| |
+ |--------------------------------------------|
+ | #f(ooter) |
+ |____________________________________________|
+
+ *******************************************************************************/
+* {
+ border: 0;
+ margin: 0;
+ padding: 0;
+}
+input:focus {
+ outline: none;
+}
+html, body, #m {
+ height: 100%;
+ overflow: hidden;
+}
+body, input, button {
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Lucida Grande", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
+ font-size: 1rem;
+ color: #222;
+}
+body {
+ display: -webkit-flex;
+ display: flex;
+ -webkit-flex-flow: column;
+ flex-flow: column;
+ background: #eef0f3;
+}
+a {
+ text-decoration: none;
+}
+strong {
+ color: #444;
+}
+button {
+ background: transparent;
+ font-size: 1em;
+ cursor: pointer;
+}
+#h {
+ padding: 6px 6px 4px;
+ display: flex;
+}
+#m {
+ width: 100%;
+ height: 100%;
+ padding: 2px 0 0;
+ -webkit-flex: 0 1 auto;
+ flex: 0 1 auto;
+ display: -webkit-flex;
+ display: flex;
+}
+#t {
+ width: 400px;
+ overflow: auto;
+ scroll-behavior: smooth;
+}
+#t.hide {
+ -ms-overflow-style: -ms-autohiding-scrollbar; /* IE and Edge: avoid that the scrollbar is shown even when TOC is hidden */
+}
+#t .tree {
+ padding-top: 6px;
+}
+#s {
+ width: 12px;
+ z-index: 2;
+ cursor: e-resize;
+}
+#c, .c {
+ -webkit-flex: auto;
+ flex: auto;
+}
+.c {
+ overflow: auto;
+ flex-basis: 0;
+}
+#t, #c, .c {
+ height: 1px;
+ min-height: 100%;
+ max-height: 100%;
+}
+#t, #c, .c, .qf, #a {
+ background: #fff;
+ box-shadow: 0 1px 3px rgba(0,0,0,0.15);
+}
+
+#f { display: none; }
+
+/*** main toolbar (in the upper left) ***/
+.y {
+ display: flex;
+ margin-right: 6px;
+}
+
+/*** button ***/
+.b {
+ display: inline-block;
+ padding: 8px;
+ font-size: 0;
+ color: #555;
+ background: transparent;
+ box-sizing: content-box;
+ height: 20px;
+ width: 20px;
+}
+.b:hover, #h .q0 > .b:hover {
+ background: #d7d9db;
+ border-radius: 5px;
+}
+
+/*** search field (area) ***/
+.q0 {
+ flex: auto;
+ display: flex;
+}
+.q1 {
+ position: relative;
+ max-width: 640px;
+ flex: auto;
+}
+.q, .qf, .qm {
+ display: flex;
+ border-radius: 8px;
+ background: #fff;
+}
+.q {
+ border: 1px solid #fff;
+ box-shadow: 0 1px 1px rgba(0,0,0,0.05);
+}
+.qf, .qm {
+ border: 1px solid #37e;
+ box-shadow: 0 1px 3px rgba(119,153,238,0.4);
+}
+.qm {
+ border-radius: 8px 8px 2px 0;
+ border-bottom-color: rgba(255,255,255,0);
+}
+.q0 .b:hover {
+ background: none;
+}
+.qf.qa .b, .qm.qa .b, .q.qa .b:hover, #b .a .b, #b .a .b:hover {
+ color: #fff;
+ background: #37e;
+ margin: 0 -0.5px 0 0; /* workaround for Microsoft Edge to avoid white between blue button and blue border */
+}
+.qf.qa .b {
+ border-radius: 0 7px 7px 0;
+}
+.qm.qa .b {
+ border-radius: 0 7px 0 0;
+}
+.q .b:hover {
+ background: #fff;
+ cursor: default;
+}
+.q0 .b {
+ border-radius: 7px;
+ margin: 0;
+ padding: 7.8px;
+}
+.q .b, .qf .b {
+ cursor: default;
+}
+.q2 {
+ display: flex;
+ flex: auto;
+}
+.q2, .q1 .b {
+ z-index: 2;
+}
+#q, .qh {
+ width: 100%; /* needed for some mobiles where "flex: auto" is not enough or does not work */
+ flex: auto;
+ min-width: 24px;
+ border: 0;
+ margin: 2px 0;
+ font-size: 1rem;
+ background: #fff;
+}
+.qh {
+ margin: 0;
+ color: #ddd;
+}
+#q::placeholder {
+ color: #999;
+ opacity: 1;
+ font-style: italic;
+}
+.u {
+ position: relative;
+}
+
+/*** search proposals (.p) and scopes button (.s) with drop-down (.u) ***/
+.c {
+ padding: 6px;
+}
+.r0 {
+ margin: 1em;
+ padding: 6px 0;
+}
+.j, .j li, .j a, .j button {
+ list-style: none outside none;
+ display: block;
+}
+.j {
+ overflow-wrap: anywhere;
+}
+.p a, .p button, .u li {
+ padding: 0.5em 9px;
+ box-sizing: border-box;
+ width: 100%;
+ text-align: left;
+ cursor: pointer;
+}
+.p .w {
+ float: right;
+}
+.p .n {
+ clear: both;
+ margin-top: 3px;
+}
+.p .v {
+ display: inline-block;
+}
+#r .j li a, #b li a, .ba {
+ max-width: 640px;
+ margin: 0 0 0.25em 10px;
+ padding: 6px;
+ border-radius: 4px;
+}
+.j .z a, .j .z button, .j a:focus, .j button:focus, .u .z {
+ background: #e8f2fe;
+ outline: none;
+}
+.j, .j a, #r .t, #b a {
+ color: #222;
+}
+.j a .w, #r .tree .l, #r .t .tl {
+ color: #062;
+}
+#r .l {
+ cursor: pointer;
+}
+.w, .n {
+ font-size: 85%;
+}
+#r .w, #r .n {
+ margin-top: 3px;
+}
+.p, .u {
+ position: absolute;
+ float: left;
+ left: 0;
+ margin-top: -1px;
+ top: 100%;
+ width: 100%;
+ padding: 0;
+ z-index: 3;
+ background: rgba(0, 0, 0, 0);
+}
+.u {
+ margin: -4px 0 0 3px;
+ width: auto;
+}
+.s0 {
+ position: relative;
+ z-index: 5;
+}
+.s {
+ background: #f2f4f7;
+ box-sizing: content-box;
+ display: flex;
+ margin: 3px 6px 3px 3px;
+ padding: 0 0 0 8px;
+ align-items: center;
+ border-radius: 5px;
+ font-size: 1rem;
+ white-space: nowrap;
+}
+.s span {
+ max-width: 240px;
+ overflow: hidden;
+}
+.s, .d, .de {
+ color: #999;
+}
+.qf .s, .qm .s, .s:hover .d, .s:hover .de {
+ color: #222;
+}
+.s .d, .s .de {
+ display: inline-block;
+ transform: rotate(90deg);
+ margin-left: -6px;
+ margin-right: 6px;
+ margin: 0 2px 0 -4px;
+}
+.s .de {
+ margin: 0 6px 0 -6px;
+}
+.p ol, .u ul {
+ display: block;
+ padding: 0;
+ margin: 0;
+ background: #fff;
+ border: 1px solid #37e;
+ border-top: none;
+ border-radius: 0 0 7px 7px;
+ box-shadow: 0 3px 4px rgba(0, 0, 0, 0.2);
+ overflow: hidden;
+}
+.s, .u ul {
+ border: 1px solid #edeff2; /* -2 V of background */
+}
+.u li {
+ white-space: nowrap;
+ padding-left: 36px;
+}
+.u li.x, .u li.y {
+ padding-left: 9px;
+}
+.u li.l {
+ border-top: 1px solid #edeff2;
+}
+.u li.x:before {
+ margin-right: 6px;
+}
+.p .f {
+ display: none;
+ position: absolute;
+ top: 0;
+ left: 100%;
+ margin-left: -1px;
+ height: 100%;
+ min-height: 42em;
+ width: 100%;
+ background: #ffffff;
+ border: 1px solid #999999;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
+ z-index: 5;
+}
+.p .z .f {
+ display: block;
+ z-index: 5;
+}
+.count {
+ display: inline-block;
+ background: #eee;
+ border-radius: 2em;
+ color: #666;
+ font-size: 0.8em;
+ font-weight: bold;
+ line-height: 1;
+ margin: 0;
+ min-width: 1em;
+ padding: 3px 7px 4px 7px;
+ position: relative;
+ text-align: center;
+ vertical-align: top;
+}
+#r .tree {
+ margin-bottom: 0.75em;
+}
+.tree input {
+ margin-right: 0.5em;
+}
+
+#h .q0 > .b {
+ margin-left: 6px;
+}
+
+/*** bookmarks (#b) and scopes (#o) ***/
+.g {
+ margin: 0 0 0.5em 10px;
+ font-weight: bold;
+}
+#b .b, #o .b {
+ width: auto;
+ font-size: 1em;
+ font-weight: bold;
+ background: #f2f4f7;
+ border: 1px solid #edeff2;
+ border-radius: 5px;
+ margin: 0.5em -12px 0 18px;
+ color: #999;
+}
+#b .b:hover, #o .b:hover {
+ color: #222;
+}
+#b .br:hover, #o .br:hover {
+ color: #fff;
+ background-color: #c11;
+}
+#b .bc, #o .bc {
+ color: #555;
+ background: none;
+ border: none;
+ margin: 1em 0 2px 2em;
+ float: right;
+}
+#b .bc:hover, #o .bc:hover {
+ background: #d7d9db;
+}
+#b li .b {
+ margin: 0;
+}
+#o li .b {
+ margin: 1px;
+}
+#b input, #o .a input {
+ width: 320px;
+}
+#b .br, #o .br {
+ color: #fff;
+ background: #e33;
+}
+#b li .br, #o li .b {
+ padding: 4px 8px;
+}
+#b .a .b {
+ border: none;
+ border-radius: 0 5px 5px 0;
+}
+#b li, #o li {
+ margin: 0 0 0 18px;
+ list-style: none;
+}
+#b li a, .ba {
+ display: inline-flex;
+ align-items: center;
+ margin: 0;
+ padding: 0 3px;
+}
+#b li a:hover, .ba:hover {
+ background-color: #e8f2fe;
+}
+#b li a span, .ba {
+ padding: 3px;
+}
+.c .a {
+ border: 1px solid #37e;
+ border-radius: 8px;
+ margin: 1em 0 1em 16px;
+ display: inline-flex;
+ min-height: 36px;
+ align-items: center;
+}
+#o div.g {
+ margin: 1em 0 0.5em 10px;
+}
+.c .tree {
+ padding: 0 0 8px 0;
+}
+#b input, #o .a input {
+ margin: 3px 0.5em;
+}
+
+/*** menu ***/
+#a {
+ background: #eef0f3;
+ height: 100%;
+ width: 0;
+ position: fixed;
+ z-index: 9;
+ top: 0;
+ right: 0;
+ overflow-x: hidden;
+ transition: all 0.25s ease-in;
+ border-left: #ddd solid 1px;
+ display: flex;
+ flex-direction: column;
+}
+.e {
+ text-align: right;
+ padding: 6px;
+}
+#a > .b {
+ width: auto;
+ height: auto;
+ font-size: 1em;
+ margin: 3px 6px;
+ color: #222;
+ text-align: left;
+ padding-left: 40px; /* = 8 + 20 + 12 */
+}
+#af {
+ margin: 3px 6px;
+}
+#af span {
+ display: inline-block;
+ padding: 8px 8px 8px 40px;
+}
+#af .b {
+ font-size: 1rem;
+}
+#a > #ap.b, #a > #app.b {
+ padding-left: 8px;
+}
+#a > .b:hover {
+ color: #111;
+}
+#a > #ah {
+ padding-left: 40px;
+}
+#a > #ah.x {
+ padding-left: 6px;
+}
+#ah.x:before, #ap:before, #app:before {
+ display: inline-block;
+ vertical-align: bottom;
+ font-size: 0;
+ width: 20px;
+ height: 20px;
+ margin: 0 12px 0 0;
+}
+#ah.x:before, .u li.x:before {
+ content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20' focusable='false' role='presentation'%3E%3Cpath d='M 18.720152,3.3629316 C 18.060084,2.7820531 17.056888,2.8348761 16.47601,3.4949448 L 7.7898314,13.157953 3.4335592,8.9600604 C 2.7999482,8.3528147 1.7966621,8.3791818 1.1894164,9.0128871 0.58217173,9.6465896 0.60853792,10.649785 1.2422432,11.257031 l 5.5443048,5.333102 c 0.2903944,0.290393 0.6864358,0.448864 1.1088434,0.448864 h 0.052827 c 0.4224085,-0.02636 0.8448161,-0.211204 1.1088434,-0.528055 L 18.825715,5.6334442 C 19.432961,4.9470093 19.380137,3.9438138 18.720159,3.3629353 Z' fill='%2354595d'/%3E%3C/svg%3E");
+
+ /* required for IE: */
+ display: inline-block;
+ width: 20px;
+
+}
+#ap:before, #app:before {
+ content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 20 20' focusable='false' role='presentation'%3E%3Cpath d='m 6.1536984,14.617279 v 1.536358 h 7.6920456 v -1.536358 z m 0,-2.564015 v 1.536357 h 7.6920456 v -1.536357 z m -4.615227,1.536357 h 1.538409 v 4.10345 c -0.0051,1.246112 0.281016,1.537384 1.538409,1.537384 H 15.384153 c 1.257393,0 1.538409,-0.231787 1.538409,-1.537384 v -4.10345 h 1.538409 c 1.307648,0.02051 1.553281,-0.270247 1.538409,-1.537383 V 6.411404 c 0,-1.2050867 -0.194865,-1.5394343 -1.538409,-1.5394343 H 16.922562 V 2.30898 C 16.937433,1.0423563 16.691801,0.76954505 15.384153,0.76954505 H 4.6152894 c -1.230727,0 -1.543537,0.29332335 -1.538409,1.53943495 v 2.5629897 h -1.538409 c -1.323032,0 -1.538409999868,0.2881953 -1.538409999868,1.5394343 v 5.640834 C -0.0050386,13.298349 0.3077434,13.610134 1.5384714,13.589621 Z M 15.384153,17.692046 H 4.6152894 v -6.66644 H 15.384153 Z m 0.96407,-9.485831 c 0,-0.461523 0.369218,-0.830228 0.830741,-0.830228 0.461522,0 0.830741,0.368705 0.830741,0.830228 0,0.461523 -0.369219,0.830741 -0.830741,0.830741 -0.461523,0 -0.830741,-0.369218 -0.830741,-0.830741 z M 4.6152894,2.3079544 H 15.384153 V 4.8740209 H 4.6152894 Z' fill='%2354595d'/%3E%3C/svg%3E");
+}
+.ht {
+ background: #ff6;
+}
+
+/*** tree ***/
+.tree ul {
+ margin: 0;
+ padding: 0 0 0 8px;
+ line-height: 1.3;
+}
+.tree .closed ul, div#results .closed ul {
+ display: none;
+}
+.tree .l {
+ display: inline-block;
+ padding: 2px 6px;
+ border-radius: 4px;
+ color: #222;
+
+ /* TODO with icons */
+ margin-left: 32px;
+
+ /* TODO without icons */
+ margin-left: 12px;
+
+}
+.tree .l img {
+
+ /* TODO with icons */
+ margin: 0 4px -2px -20px;
+
+ /* TODO without icons */
+ display: none;
+
+}
+.tree li {
+ padding: 0 0 0 10px; /* indent TOC subitems: 10px => .tree a padding-left: 42px - 10px = 32px */
+ list-style: none;
+ position: relative;
+}
+.tree li.xx > .l, .tree li.x > .l {
+ font-weight: bold;
+}
+.tree li.xx > .l {
+ color: #333;
+}
+.tree li.x > .l {
+ color: #444;
+}
+.tree li.xx > .l {
+ background-color: #eef0f3;
+}
+.tree .l, .tree li.xx > .l, .tree li.x > .l, .tree li.xx > .l:hover, .tree li.x > .l:hover {
+ transition: all 0.1s ease;
+}
+.tree li > .l:hover {
+ transition: all 0.1s 0.1s ease;
+ background-color: #f4f9ff;
+}
+.tree li > .l:focus {
+ background-color: #e8f2fe;
+ outline: none;
+}
+.tree .h {
+ /* prevent text selection */
+ user-select: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none; /* otherwise in MS Edge a blinking text cursor will be shown */
+ display: inline-block;
+ position: absolute;
+ left: -2px;
+ cursor: pointer;
+ animation: fly-left 3s ease-in forwards;
+ color: #999;
+ transition: transform .25s, color .25s;
+}
+.tree .open > .h {
+ color: #333;
+ transform: rotate(90deg);
+}
+
+/*** logo ***/
+.k1 /* width: 36..146 */ {
+ /* logo icon */
+}
+.kf /* width: > 146 */ {
+ /* logo full */
+}
+
+/*******************************************************************************
+ * Mobile */
+
+@media screen and (max-width: 768px) {
+
+ #t, #s, .i, .k0, .k1, .kf, .ke0, .ke1, .kef {
+ display: none;
+ }
+ #m {
+ overflow: hidden;
+ }
+ #t.show {
+ display: block;
+ min-width: 100%;
+ }
+ .s span {
+ max-width: 60px;
+ overflow: hidden;
+ }
+
+}
+
+@media screen and (max-height: 360px) {
+ .p ol {
+ overflow-y: auto;
+ max-height: calc(100vh - 38px);
+ -ms-overflow-style: none;
+ scrollbar-width: none;
+ }
+ .p ol::-webkit-scrollbar {
+ display: none;
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.help.webapp/m/index.html b/org.eclipse.help.webapp/m/index.html
new file mode 100644
index 000000000..69c78558e
--- /dev/null
+++ b/org.eclipse.help.webapp/m/index.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="UTF-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Help</title>
+ <link rel="stylesheet" type="text/css" href="m/index.css">
+ <script type="text/javascript" src="m/index.js"></script>
+</head>
+<body>
+ <header id="h"></header>
+ <div id="m">
+ <aside id="t"></aside>
+ <iframe id="c" name="c"></iframe>
+ </div>
+ <footer id="f"></footer>
+</body>
+</html> \ No newline at end of file
diff --git a/org.eclipse.help.webapp/m/index.js b/org.eclipse.help.webapp/m/index.js
new file mode 100644
index 000000000..b06be0671
--- /dev/null
+++ b/org.eclipse.help.webapp/m/index.js
@@ -0,0 +1,2845 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Holger Voormann and others.
+ *
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ ******************************************************************************/
+(function(window, document) {
+
+ var SMALL_SCREEN_WIDTH = 768;
+ var LOGO_ICON_WIDTH = 36;
+ var LOGO_FULL_WIDTH = 146;
+ var MENU_FONT_SIZING = 0;
+ var MENU_HELP = 0;
+ var MENU_ABOUT = 0;
+ var TOC_SIDEBAR_DEFAULT_WIDTH = 380;
+ var TOC_SIDEBAR_MINIMUM_WIDTH = 76;
+ var TOC_SIDEBAR_WIDTH_COOKIE_NAME = 'toc_width';
+ var TOC_ICON_DESCRIPTION = 'Toggle table of content';
+ var TOC_ICON = '<svg width="20" height="20" viewBox="0 0 20 20"><path fill="currentColor" d="M19 5H1V3h18v2zm0 10H1v2h18v-2zm-4-6H1v2h14V9z"/></svg>';
+ var HISTORY_BACK_DESCRIPTION = 'Go back one page';
+ var HISTORY_BACK_ICON = '<svg width="20" height="20" viewBox="0 0 20 20"><path fill="currentColor" d="m 8.27224,17.95644 c 0.39048,0.390343 1.023592,0.390211 1.413938,0 0.390613,-0.390612 0.390613,-1.023597 -1.33e-4,-1.41421 L 4.144057,11.000499 18.27041,10.999748 c 0.55219,-1.31e-4 0.999731,-0.447671 0.999731,-1.0001299 -1.34e-4,-0.552189 -0.447674,-0.999595 -0.999864,-0.999595 l -14.126755,9.99e-4 5.542723,-5.543204 c 0.390479,-0.390479 0.390479,-1.023727 0,-1.414074 -0.195307,-0.195173 -0.451138,-0.292892 -0.707102,-0.292892 -0.255832,0 -0.511664,0.09772 -0.70697,0.292759 l -7.249421,7.250043 c -0.187575,0.18744 -0.292893,0.441666 -0.292893,0.7069649 1.33e-4,0.2653 0.105451,0.519396 0.293025,0.707237 z"/></svg>';
+ var HISTORY_FORWARD_DESCRIPTION = 'Go back one page';
+ var HISTORY_FORWARD_ICON = '<svg width="20" height="20" viewBox="0 0 20 20"><path fill="currentColor" d="m 11.72776,17.95644 c -0.39048,0.390343 -1.023592,0.390211 -1.413938,0 -0.390613,-0.390612 -0.390613,-1.023597 1.33e-4,-1.41421 L 15.855943,11.000499 1.72959,10.999748 C 1.1774,10.999617 0.729859,10.552077 0.729859,9.9996181 0.729993,9.4474291 1.177533,9.0000231 1.729723,9.0000231 l 14.126755,9.99e-4 -5.542723,-5.543204 c -0.390479,-0.390479 -0.390479,-1.023727 0,-1.414074 0.195307,-0.195173 0.451138,-0.292892 0.707102,-0.292892 0.255832,0 0.511664,0.09772 0.70697,0.292759 l 7.249421,7.250043 c 0.187575,0.18744 0.292893,0.441666 0.292893,0.7069649 -1.33e-4,0.2653 -0.105451,0.519396 -0.293025,0.707237 z"/></svg>';
+ var BOOKMARKS_ICON = '<svg width="20" height="20" viewBox="0 0 20 20"><path fill="currentColor" d="M 10.019531 0.5 A 1.000065 1.000065 0 0 0 9.1035156 1.0566406 L 6.5742188 6.1816406 L 0.91796875 7.0039062 A 1.000065 1.000065 0 0 0 0.36523438 8.7089844 L 4.4570312 12.699219 L 3.4902344 18.332031 A 1.000065 1.000065 0 0 0 4.9414062 19.384766 L 10 16.726562 L 15.058594 19.384766 A 1.000065 1.000065 0 0 0 16.509766 18.332031 L 15.542969 12.699219 L 19.634766 8.7089844 A 1.000065 1.000065 0 0 0 19.082031 7.0039062 L 13.425781 6.1816406 L 10.896484 1.0566406 A 1.000065 1.000065 0 0 0 10.019531 0.5 z M 10 3.7597656 L 11.865234 7.5390625 A 1.000065 1.000065 0 0 0 12.617188 8.0859375 L 16.789062 8.6914062 L 13.771484 11.632812 A 1.000065 1.000065 0 0 0 13.482422 12.517578 L 14.195312 16.673828 L 10.464844 14.710938 A 1.000065 1.000065 0 0 0 9.5351562 14.710938 L 5.8046875 16.673828 L 6.5175781 12.517578 A 1.000065 1.000065 0 0 0 6.2285156 11.632812 L 3.2109375 8.6914062 L 7.3828125 8.0859375 A 1.000065 1.000065 0 0 0 8.1347656 7.5390625 L 10 3.7597656 z"/></svg>';
+ var BOOKMARKS_DESCRIPTION = 'Bookmarks';
+ var BOOKMARKS_CLOSE_DESCRIPTION = 'Close bookmarks';
+ var BOOKMARKS_ADD_PAGE_DESCRIPTION = 'Bookmark current page';
+ var BOOKMARKS_ADD_SEARCH_DESCRIPTION = 'Bookmark current search';
+ var BOOKMARKS_DELETE = 'Delete';
+ var BOOKMARKS_DELETE_DESCRIPTION = 'Delete this bookmarks (cannot be undone)';
+ var BOOKMARKS_DELETE_ALL = 'Delete all bookmarks';
+ var BOOKMARKS_DELETE_ALL_DESCRIPTION = 'Delete all bookmarks (cannot be undone)';
+ var BOOKMARKS_PATTERN = new RegExp('<tr[^<]*<td[^<]*<a\\s+(?:(?!href)[\\w\\-]+\\s*=\\s*(?:(?:\'[^\']*\')|(?:"[^"]*"))\\s+)*href\\s*=\\s*\'([^\']*)\'[^<]*<img[^>]*>\\s*([^<]*)</a>', 'gi');
+ var MENU_ICON = '<svg width="20" height="20" viewBox="0 0 20 20"><path fill="currentColor" d="M 10 1.5 A 2 2 0 0 0 8 3.5 A 2 2 0 0 0 10 5.5 A 2 2 0 0 0 12 3.5 A 2 2 0 0 0 10 1.5 z M 10 8 A 2 2 0 0 0 8 10 A 2 2 0 0 0 10 12 A 2 2 0 0 0 12 10 A 2 2 0 0 0 10 8 z M 10 14.5 A 2 2 0 0 0 8 16.5 A 2 2 0 0 0 10 18.5 A 2 2 0 0 0 12 16.5 A 2 2 0 0 0 10 14.5 z"/></svg>';
+ var MENU_ICON_DESCRIPTION = 'Show menu';
+ var MENU_CLOSE_ICON = '<svg width="20" height="20" viewBox="0 0 20 20"><path fill="currentColor" d="M 4.34375 2.9296875 L 2.9296875 4.34375 L 8.5859375 10 L 2.9296875 15.65625 L 4.34375 17.070312 L 10 11.414062 L 15.65625 17.070312 L 17.070312 15.65625 L 11.414062 10 L 17.070312 4.34375 L 15.65625 2.9296875 L 10 8.5859375 L 4.34375 2.9296875 z"/></svg>';
+ var MENU_CLOSE_ICON_DESCRIPTION = 'Hide menu';
+ var TREE_HANDLE = '<svg width="24" height="24" viewBox="0 0 24 24" focusable="false" role="presentation">-<path d="M10.294 9.698a.988.988 0 0 1 0-1.407 1.01 1.01 0 0 1 1.419 0l2.965 2.94a1.09 1.09 0 0 1 0 1.548l-2.955 2.93a1.01 1.01 0 0 1-1.42 0 .988.988 0 0 1 0-1.407l2.318-2.297-2.327-2.307z" fill="currentColor"/></svg>';
+ var BOOK_NAME_SHORTENER = function shortenBookName(bookName) { return bookName.replace(/\s+(Documentation\s*)?(\-\s+([0-9,\-]+\s+)?Preview(\s+[0-9,\-]+)?\s*)?$/i, ''); };
+ var BOOK_SCOPE_BY_DEFAULT = 0;
+ var BOOK_SCOPE_COOKIE = 'book-scope';
+ var SEARCH_SCOPE_CLOSE_DESCRIPTION = 'Close scopes';
+ var SEARCH_ICON = '<svg width="20" height="20" viewBox="0 0 20 20"><g fill="#fff"><path fill="currentColor" d="M 7.5 0 C 3.3578644 0 0 3.3578644 0 7.5 C 0 11.642136 3.3578644 15 7.5 15 C 8.8853834 14.997 10.242857 14.610283 11.421875 13.882812 L 17.185547 19.662109 C 17.632478 20.113489 18.36112 20.112183 18.8125 19.660156 L 19.623047 18.845703 C 20.072507 18.398153 20.072507 17.665594 19.623047 17.214844 L 13.871094 11.447266 C 14.607206 10.26212 14.998156 8.8951443 15 7.5 C 15 3.3578644 11.642136 0 7.5 0 z M 7.5 2 A 5.5 5.5 0 0 1 13 7.5 A 5.5 5.5 0 0 1 7.5 13 A 5.5 5.5 0 0 1 2 7.5 A 5.5 5.5 0 0 1 7.5 2 z"/></g></svg>';
+ var SEARCH_FIELD_DESCRIPTION = '* = any string\n? = any character\n"" = phrase\nAND, OR & NOT = boolean operators';
+ var SEARCH_FIELD_PLACEHOLDER = 'Search';
+ var BASE_URL;
+ var SEARCH_BASE_URL;
+ var SEARCH_HITS_MAX = 500;
+ var SEARCH_AS_YOU_TYPE_PROPOSAL_MAX = 7;
+ var SEARCH_RESULTS_INDEXING_PATTERN = new RegExp('[\'"]divProgress[\'"]\\s+STYLE\\s*=\\s*[\'"]\\s*width\\s*:\\s*([\\d]+)\\s*px', 'i');
+ var SEARCH_RESULTS_PATTERN = new RegExp('<tr[^<]*<td[^<]*<img[^<]*</td[^<]*<td[^<]*<a\\s+(?:(?!href)(?!title)[\\w\\-]+\\s*=\\s*(?:(?:\'[^\']*\')|(?:"[^"]*"))\\s+)*(href|title)\\s*=\\s*"([^"]*)"\\s+(?:(?!href)(?!title)[\\w\\-]+\\s*=\\s*(?:(?:\'[^\']*\')|(?:"[^"]*"))\\s+)*(href|title)\\s*=\\s*"([^"]*)"[^>]*>([^<]*)</a>(?:(?:(?!<[/]?tr)[\\s\\S])*</tr\\s*>\\s*<tr(?:(?!</tr)(?!class="location">)[\\s\\S])*class="location">((?:(?!</div)[\\s\\S])*))?(?:(?:(?!</tr)(?!\\sclass=["\']description["\'])[\\s\\S])*</tr){1,2}(?:(?!</tr)(?!\\sclass=["\']description["\'])[\\s\\S])*\\sclass=["\']description["\'][^>]*>([^<]*)', 'gi');
+ var SEARCH_RESULTS_BREADCRUMB_SNIPPET_PATTERN = new RegExp('<a\\s+href="([^"]+)">([^<]+)</a>', 'gi');
+ var SEARCH_SCOPE_LABEL_NONE = 'All';
+ var SEARCH_SCOPE_LABEL_BOOK = 'Book';
+ var SEARCH_SCOPE_LABEL_CHAPTER = 'Chapter';
+// var SEARCH_SCOPE_LABEL_TOPIC = 'Find in page';
+ var SEARCH_SCOPE_CURRENT_PATTERN = new RegExp('<div\\s+id\\s*=\\s*"scope"\\s*>([^<]*)<');
+ var SEARCH_SCOPE_ALL_PATTERN = new RegExp('<a\\s+(?:(?!title)[\\w\\-]+\\s*=\\s*(?:(?:\'[^\']*\')|(?:"[^"]*"))\\s+)*title\\s*=\\s*"([^"]*)"', 'gi');
+ var SEARCH_SCOPE_NAME_PATTERN = new RegExp('<input\\s+type\\s*=\\s*["\']text["\']\\s+(?:(?!value)[\\w\\-]+\\s*=\\s*(?:(?:\'[^\']*\')|(?:"[^"]*"))\\s+)*value\\s*=\\s*\'([^\']*)\'', 'i');
+ var SEARCH_SCOPE_IS_NEW_PATTERN = new RegExp('oldName\\s*=\\s*\'\'', 'i');
+ var SEARCH_SCOPE_HREFS_PATTERN = new RegExp('<input(?:\\s+(?!checked)[\\w\\-]+\\s*=\\s*(?:(?:\'[^\']*\')|(?:"[^"]*")))*(\\s+checked)?[^<]+<label\\s+for\\s*=\\s*"([^"]*)"[^>]*>([^<]*)</label>\\s*(</div)?', 'gi');
+ var SEARCH_AS_YOU_TYPE_CACHE_SIZE = 7;
+ var SEARCH_FULL_SEARCH_CACHE_SIZE = 3;
+ var SEARCH_DELAY_IN_MILLISECOND = 99;
+ var SEARCH_CACHE = {fi: -1, f: [], ti: -1, t: [] };
+
+ // TODO integration: the browser should not have to calculate the following variables itself;
+ // only "init()" should be called instead
+ var embeddedMode = 1;
+ var title = 'Help';
+ var bookmarksPage;
+ var scopesPage;
+ var searchPage;
+ var renderFullSearch;
+ var updateScopeByToc;
+ var setSearchScope;
+ var currentSearch = {};
+ var searchScope = {l: 0, s: '', t: 0};
+
+ addEvent(window, 'load', function() {
+
+ // (search) base URL
+ var a = createElement(0, 'a');
+ a.href = window.location.pathname.indexOf('/index.jsp') >= 0 ? 'x' : '../../x';
+ BASE_URL = a.href.substring(0, a.href.length - 1);
+ SEARCH_BASE_URL = BASE_URL + 'advanced/searchView.jsp?showSearchCategories=false&searchWord=';
+
+ remoteRequest(BASE_URL + 'advanced/search.jsp', function(responseText) {
+
+ // read user defined search scope
+ var match = SEARCH_SCOPE_CURRENT_PATTERN.exec(responseText);
+ searchScope.i = match ? match[1] : match;
+
+ // make sure no scope is set (a scope might have been set via the legacy UI before)
+ remoteRequest(BASE_URL + 'scopeState.jsp?workingSet=');
+
+ // title
+ remoteRequest(BASE_URL + 'index.jsp?legacy', function(responseText) {
+ var match = new RegExp('<title>([^<]*)</title>').exec(responseText);
+ if (!match) return;
+ document.title = decodeHtml(match[1]);
+ });
+
+ // embedded or Infocenter mode? + read scopes
+ remoteRequest(BASE_URL + 'advanced/tabs.jsp', function(responseText) {
+ if (responseText.indexOf('e_bookmarks_view.') < 0) embeddedMode = 0;
+
+ // read scopes
+ remoteRequest(BASE_URL + 'advanced/workingSetManager.jsp?t=' + Date.now(), function(responseText) {
+ var scopeIndex = 0;
+ SEARCH_SCOPE_ALL_PATTERN.lastIndex = 0;
+ for (var match; (match = SEARCH_SCOPE_ALL_PATTERN.exec(responseText)) != null;) {
+ var scopeName = decodeHtml(match[1]);
+ if (scopeName.substring(0, 1) == '\u200B') {
+ if (scopeName.length < 3) {
+ searchScope.l = scopeName.length;
+ break;
+ } else {
+ searchScope.l = 4;
+ searchScope.t = scopeName.length - 3;
+ continue;
+ }
+ }
+ if (searchScope.i && searchScope.i == scopeName) {
+ searchScope.l = 4;
+ searchScope.s = scopeName;
+ break;
+ } else if (searchScope.l == 4 && searchScope.t == scopeIndex) {
+ searchScope.s = scopeName;
+ }
+ scopeIndex++;
+ }
+
+ init();
+
+ });
+ });
+
+ });
+
+ });
+
+ function init() {
+
+ // bookmarks page
+ bookmarksPage = createElement(getElementById('m'), 0, 'c');
+ bookmarksPage.id = 'b';
+ bookmarksPage.s = function(show) {
+ bookmarksPage.o = !!show;
+ if (show && scopesPage) scopesPage.s();
+ bookmarksPage.style.display = show ? 'block' : 'none';
+ getElementById('c').style.display = show || (searchPage && searchPage.o) ? 'none' : 'block';
+ if (searchPage) searchPage.style.display = searchPage.o && !show ? 'block' : 'none';
+ if (!show) return;
+ bookmarksPage.innerHTML = '';
+
+ // add bookmark
+ try {
+ var url = frames.c.location.href;
+ var title = searchPage.o ? searchPage.l : frames.c.document.title;
+ if (title == null || title == '') {
+ title = url;
+ }
+ createElement(bookmarksPage, 'span', 'g', 'Add:');
+ var addArea = createElement(bookmarksPage, 'span', 'a');
+ var input = createElement(addArea, 'input');
+ input.type = 'text';
+ input.autocomplete = 'off';
+ input.value = title;
+ var addButtonTooltip = searchPage.o ? BOOKMARKS_ADD_SEARCH_DESCRIPTION : BOOKMARKS_ADD_PAGE_DESCRIPTION;
+ createButton(addArea, BOOKMARKS_ICON, addButtonTooltip, function() {
+ try {
+ var url = frames.c.location.href;
+ if (url.substring(0, BASE_URL.length + 6) == BASE_URL + 'topic/') {
+ url = url.substring(BASE_URL.length + 5);
+
+ // workaround for a bug of the legacy UI: non-topic links (e.g. ".../nav/..." instead of
+ // ".../topic/...") are stored absolutely instead of relatively (which doesn't work, because by
+ // default a random port number is chosen when restarting Eclipse)
+ } else if (url.substring(0, BASE_URL.length) == BASE_URL) {
+ url = '/../' + url.substring(BASE_URL.length);
+ }
+
+ var title = frames.c.document.title;
+ if (title == null || title == '') {
+ title = url;
+ }
+ remoteRequest( BASE_URL + 'advanced/bookmarksView.jsp?operation=add&'
+ + 'bookmark=' + encodeURIComponent(url)
+ + '&title=' + encodeURIComponent(input.value)
+ + '&t=' + Date.now());
+ bookmarksPage.s();
+ } catch (e) {}
+ });
+ } catch (e) {}
+
+ // "x" button
+ setClassName(createButton(bookmarksPage, MENU_CLOSE_ICON, BOOKMARKS_CLOSE_DESCRIPTION, function() {
+ bookmarksPage.s();
+ }), 'b bc');
+
+ remoteRequest(BASE_URL + 'advanced/bookmarksView.jsp?t=' + Date.now(), function(responseText) {
+ var ol;
+ var element = createElement();
+ var deleteButtons = [];
+ BOOKMARKS_PATTERN.lastIndex = 0;
+ for (var match; (match = BOOKMARKS_PATTERN.exec(responseText)) != null;) {
+ if (!ol) {
+ createElement(bookmarksPage, 0, 'g', 'Bookmarks:');
+ ol = createElement(bookmarksPage, 'ol');
+ }
+ var groups = [];
+ for (var i = 1; i < 4; i++) {
+ element.innerHTML = match[i];
+ groups.push((element.textContent ? element.textContent : element.innerText).replace(/^\s+|\s+$/g,'').replace(/\s+/g,' '));
+ }
+ var li = createElement(ol, 'li');
+ var href = groups[0].substring(0, 3) == '../' ? BASE_URL + '/' + groups[0] : groups[0];
+ var deleteButton = createButton(li,
+ BOOKMARKS_DELETE,
+ BOOKMARKS_DELETE_DESCRIPTION,
+ function(href, title, li) {
+ return function() {
+ remoteRequest( BASE_URL + 'advanced/bookmarksView.jsp?operation=remove&'
+ + 'bookmark=' + encodeURIComponent(href)
+ + '&title=' + encodeURIComponent(title)
+ + '&t=' + Date.now());
+ li.style.display = 'none';
+ }
+ }(groups[0].substring(0, 9) == '../topic/' ? groups[0].substring(8) : groups[0], groups[1], li));
+ deleteButton.style.display = 'none';
+ deleteButton.className = 'b br';
+ deleteButtons.push(deleteButton);
+ var a = createElement(li, 'a');
+ a.target = 'c';
+ a.href = href;
+ createElement(a, 'span').innerHTML = BOOKMARKS_ICON;
+ createElement(a, 'span', 0, groups[1]);
+ }
+ if (deleteButtons.length) {
+ var editButton = createButton(bookmarksPage, 'Edit', 'Delete bookmarks', function() {
+ var editMode = editButton.innerHTML == 'Edit';
+ editButton.innerHTML = editMode ? BOOKMARKS_DELETE_ALL : 'Edit';
+ editButton.title = editMode ? BOOKMARKS_DELETE_ALL_DESCRIPTION : 'Delete bookmarks';
+ setClassName(editButton, editMode ? 'b br' : 'b');
+ for (var i = 0; i < deleteButtons.length; i++) {
+ deleteButtons[i].style.display = 'inline-block';
+ }
+ if (!editMode) {
+ remoteRequest(BASE_URL + 'advanced/bookmarksView.jsp?operation=removeAll&t=' + Date.now());
+ bookmarksPage.s();
+ }
+ });
+ }
+ createButton(bookmarksPage, 'Cancel', BOOKMARKS_CLOSE_DESCRIPTION, function() { bookmarksPage.s(); });
+
+ });
+ }
+ bookmarksPage.s();
+
+ // scopes page
+ scopesPage = createElement(getElementById('m'), 0, 'c');
+ scopesPage.id = 'o';
+ scopesPage.s = function(show) {
+ scopesPage.o = !!show;
+ if (show && bookmarksPage) bookmarksPage.s();
+ scopesPage.style.display = show ? 'block' : 'none';
+ getElementById('c').style.display = show || (searchPage && searchPage.o) ? 'none' : 'block';
+ if (searchPage) searchPage.style.display = searchPage.o && !show ? 'block' : 'none';
+ if (!show) return;
+ function showScopesPage(query, scopeNr) {
+ scopesPage.innerHTML = '';
+
+ // "x" button
+ setClassName(createButton(scopesPage, MENU_CLOSE_ICON, SEARCH_SCOPE_CLOSE_DESCRIPTION, function() {
+ scopesPage.s();
+ }), 'b bc');
+
+ // get and show content
+ remoteRequest( BASE_URL
+ + 'advanced/workingSet'
+ + (query ? '.jsp?' + query + '&' : 'Manager.jsp?')
+ + 't=' + Date.now(),
+ function(responseText) {
+ var match = SEARCH_SCOPE_NAME_PATTERN.exec(responseText);
+ if (match) {
+ createElement(scopesPage, 'span', 'g', 'Scope:');
+ var scopeName = decodeHtml(match[1]);
+ var nameInput = createElement(createElement(scopesPage, 'span', 'a'), 'input');
+ nameInput.type = 'text';
+ nameInput.value = scopeName;
+ var tree = [];
+ var allNodes = [];
+ var parentNode;
+ SEARCH_SCOPE_HREFS_PATTERN.lastIndex = 0;
+ for (; (match = SEARCH_SCOPE_HREFS_PATTERN.exec(responseText)) != null;) {
+ var node = {n: {l: decodeHtml(match[3]), v: decodeHtml(match[2]), c: [], x: !!match[1]}, l: 1};
+ allNodes.push(node.n);
+ if (match[4] && parentNode) {
+ parentNode.l = 0;
+ parentNode.n.c.push(node);
+ node.n.p = parentNode.n;
+ } else {
+ parentNode = node;
+ tree.push(node);
+ }
+ }
+ createTree(scopesPage,
+
+ // content provider
+ function(node, processChildrenFn) {
+ processChildrenFn(node ? node.c : tree);
+ },
+
+ // label provider
+ function(li, node) {
+ var checkboxWithLabel = createElement(li);
+ var checkbox = createElement(checkboxWithLabel, 'input');
+ checkbox.type = 'checkbox';
+ checkbox.id = node.v;
+ if (node.x) {
+ checkbox.checked = 'checked';
+ }
+ node.b = checkbox;
+ checkbox.n = node;
+ updateOrGetScopeCheckboxStates(node);
+ if (updateOrGetScopeCheckboxStates(node, 1)) {
+ setClassName(li, 'open');
+ }
+ addEvent(checkbox, 'click', (function(node) {
+ return function() {
+ updateOrGetScopeCheckboxStates(node.p);
+ setSubtreeState(node, node.b.checked);
+ };
+ })(node));
+ var label = createElement(checkboxWithLabel, 'label', 0, node.l);
+ setAttribute(label, 'for', node.v);
+ return checkboxWithLabel;
+ }
+
+ );
+ function getHrefs() {
+ hrefs = '';
+ for (var i = 0; i < allNodes.length; i++) {
+ var node = allNodes[i];
+ if ( (node.b ? node.b.checked : node.x)
+ && (!node.p || !(node.p.b ? node.p.b.checked : node.p.x))) {
+ hrefs += '&hrefs=' + node.v;
+ }
+ }
+ return hrefs;
+ }
+ if (SEARCH_SCOPE_IS_NEW_PATTERN.exec(responseText)) {
+ createButton(scopesPage, 'Create', 'Add new scope', function() {
+ doScopesOperation( 'add&oldName=&workingSet='
+ + encodeURIComponent(nameInput.value)
+ + getHrefs());
+ });
+ } else {
+ var deleteButton = createButton(scopesPage, 'Delete', 'Delete this scope', function() {
+ doScopesOperation('remove&workingSet=' + encodeURIComponent(scopeName));
+ });
+ deleteButton.className = 'b br';
+ createButton(scopesPage, 'Apply', 'Update this scope', function() {
+ doScopesOperation( 'edit&oldName='
+ + encodeURIComponent(scopeName)
+ + '&workingSet='
+ + encodeURIComponent(nameInput.value)
+ + getHrefs());
+ setSearchScope([4, scopeName, scopeNr]);
+ });
+ }
+ createButton(scopesPage, 'Cancel', 'Go back to list of scopes',function() { showScopesPage(); });
+
+ } else {
+ createElement(scopesPage, 0, 'g', 'Scopes:');
+ var ol = createElement(scopesPage, 'ol');
+ SEARCH_SCOPE_ALL_PATTERN.lastIndex = 0;
+ for (var scopeIndex = 0; (match = SEARCH_SCOPE_ALL_PATTERN.exec(responseText)) != null;) {
+ var scopeName = decodeHtml(match[1]);
+ if (scopeName.substring(0, 1) == '\u200B') continue;
+ var li = createElement(ol, 'li');
+ createButton(li, scopeName, 0, function(scopeName, scopeIndex) {
+ return function() { showScopesPage('operation=edit&workingSet=' + encodeURIComponent(scopeName), scopeIndex); };
+ }(scopeName, scopeIndex), 'ba');
+ scopeIndex++;
+ }
+ createButton(scopesPage, 'New', 'Add a new scope', function() { showScopesPage('operation=add'); });
+ createButton(scopesPage, 'Cancel', SEARCH_SCOPE_CLOSE_DESCRIPTION, function() { scopesPage.s(); });
+ }
+ });
+ }
+ function doScopesOperation(query) {
+ remoteRequest( BASE_URL
+ + 'workingSetState.jsp?operation='
+ + query
+ + '&t=' + Date.now(),
+ function() { showScopesPage(); });
+ }
+ showScopesPage();
+ }
+ function updateOrGetScopeCheckboxStates(node, computeState) {
+ for (var parent = node; parent; parent = parent.p) {
+ var allChecked = 1;
+ var allUnchecked = 1;
+ for (var i = 0; i < parent.c.length; i++) {
+ var childNode = parent.c[i].n;
+ if (childNode.b ? childNode.b.checked : childNode.x) {
+ allUnchecked = 0;
+ } else {
+ allChecked = 0;
+ }
+ }
+ if (computeState) {
+ return !allChecked && !allUnchecked;
+ }
+ if (!parent.c.length) continue;
+ parent.b.checked = !!allChecked;
+ parent.b.indeterminate = !allChecked && !allUnchecked;
+ }
+ }
+ function setSubtreeState(node, state) {
+ for (var i = 0; i < node.c.length; i++) {
+ var childNode = node.c[i].n;
+ if (childNode.b) {
+ childNode.b.checked = !!state;
+ } else {
+ childNode.x = state;
+ }
+ setSubtreeState(childNode, state);
+ }
+ }
+ scopesPage.s();
+
+ // search page
+ searchPage = createElement(getElementById('m'), 0, 'c', 'Loading...');
+ searchPage.id = 'r';
+ searchPage.s = function(show) {
+ searchPage.o = !!show;
+ searchPage.style.display = show ? 'block' : 'none';
+ getElementById('c').style.display = show ? 'none' : 'block';
+ if (bookmarksPage) bookmarksPage.s();
+ if (scopesPage) scopesPage.s();
+ if (show) {
+ document.title = searchPage.l + ' - ' + title;
+ } else {
+ try {
+ var topicTitle = contentFrame.contentDocument.title;
+ document.title = topicTitle ? (topicTitle + ' - ' + title) : title;
+ } catch(e) {
+ document.title = title;
+ }
+ }
+ }
+ searchPage.s();
+
+ // toolbar: TOC sidebar button and history Back/Forward buttons (in embedded help, but not in Infocenter mode)
+ var header = getElementById('h');
+ var toolbarContainer = createElement(header);
+ var toolbar = createElement(toolbarContainer, 0, 'y');
+ var tocSidebarToggleButton = createButton(toolbar, TOC_ICON, TOC_ICON_DESCRIPTION);
+ if (embeddedMode) {
+ createButton(toolbar, HISTORY_BACK_ICON, HISTORY_BACK_DESCRIPTION, function() {
+ window.history.back();
+ });
+ createButton(toolbar, HISTORY_FORWARD_ICON, HISTORY_FORWARD_DESCRIPTION, function() {
+ window.history.forward();
+ });
+ }
+
+ // TOC slider (to change TOC sidebar width by moving the slider)
+ var smallScreenAutoCloseFn = createSlider(tocSidebarToggleButton, toolbarContainer, createElement(header, 0, 'i'));
+
+ // fill TOC and create search field
+ var toc = getElementById('t');
+ createTree(toc,
+ tocContentProvider,
+ function(li, node) {
+ if (node.toc) {
+ li.toc = node.toc;
+ }
+ li.n = node;
+ var a = createElement(li, 'a');
+ a.href = node.h;
+ a.target = 'c';
+ addEvent(a, 'click', smallScreenAutoCloseFn);
+ li.h = a.href;
+ li.a = a.hash;
+ li.b = a.protocol + '//' + a.host + a.pathname;
+ if (node.i) {
+ var iconImg = createElement(a, 'img');
+ iconImg.setAttribute('src', BASE_URL
+ + 'advanced/images/'
+ + node.i
+ + '.svg');
+ }
+ a.appendChild(document.createTextNode(node.t));
+ return a;
+ },
+ 1);
+ toc.c = 1; // scroll into view if needed: to upper third instead of scroll as less as possible
+ var contentFrame = getElementById('c');
+ addEvent(contentFrame, 'load', function() {
+
+ // full search?
+ var contentFrameHref = frames.c.location.href;
+ if (contentFrameHref.substring(0, SEARCH_BASE_URL.length) == SEARCH_BASE_URL) {
+ var data = frames.c.document.documentElement.innerHTML;
+ renderFullSearch(contentFrameHref.substring(SEARCH_BASE_URL.length), data);
+ searchPage.s(1);
+ return;
+ }
+
+ // close maybe open bookmarks, scopes or search page
+ if (bookmarksPage) bookmarksPage.s();
+ if (scopesPage) scopesPage.s();
+ searchPage.s();
+ updateDeepLink();
+
+ // font sizing
+ setFontSize(0, 1, 1);
+
+ // update title and deep link
+ try {
+ var topicTitle = contentFrame.contentDocument.title;
+ document.title = topicTitle ? (topicTitle + ' - ' + title) : title;
+ } catch(e) {
+ document.title = title;
+ }
+
+ // sync with TOC
+ try {
+ syncToc();
+ addEvent(contentFrame.contentWindow, 'hashchange', function() { syncToc(); updateDeepLink(); });
+ } catch(e) {
+ toc.x(0);
+ }
+
+ });
+ addEvent(window, 'hashchange', function() {
+ var newHash = window.location.hash;
+ if (isQueryHash(newHash)) {
+ searchFullByHash(newHash);
+ } else {
+ searchPage.s();
+ }
+ });
+
+ }
+ function createButton(parent, innerHtml, description, clickFn, className, text) {
+ var button = createElement(parent, 'button', className ? className : 'b', text);
+ if (description) {
+ button.title = description;
+ }
+ if (innerHtml) {
+ setInnerHtml(button, innerHtml);
+ }
+ if (clickFn) {
+ addEvent(button, 'click', function(e) { preventDefault(e); clickFn(e); });
+ }
+ return button;
+ }
+
+ function initContentPage() {
+
+ // set initial start/cover page...
+ // ...by hash
+ var hash = window.location.hash;
+ try {
+ if (hash && ( 'q=' == hash.substring(1, 3)
+ || 'nav/' == hash.substring(1, 5)
+ || 'topic/' == hash.substring(1, 7)
+ || 'rtopic/' == hash.substring(1, 8)
+ || 'ntopic/' == hash.substring(1, 8)
+ || 'nftopic/' == hash.substring(1, 9))) {
+ if ('q=' == hash.substring(1, 3)) {
+ searchFullByHash(hash);
+ } else {
+ getElementById('c').src = BASE_URL + hash.substring(1);
+ }
+ return;
+ }
+ } catch(e) {}
+
+ // ...by legacy query parameters (topic/nav or search link)
+ var params = getParams(window.location.href.replace(/^[^#\?]*(?:\?([^#\?]*))?(#.*)?$/, '$1'));
+ var topicOrNav = params.topic || params.nav;
+ if (params.searchWord && params.tab == 'search') {
+ window.history.replaceState(null, '', window.location.pathname);
+ searchFullByHash('#q=' + encodeURIComponent(params.searchWord));
+ return;
+ }
+ if (topicOrNav) {
+ getElementById('c').src = BASE_URL
+ + (params.nav ? 'nav' : 'topic')
+ + topicOrNav
+ + (params.anchor ? '#' + params.anchor : '');
+ window.history.replaceState(null, '', window.location.pathname);
+ updateDeepLink();
+ return;
+ }
+
+ // ...default start/cover page
+ remoteRequest(BASE_URL + 'advanced/content.jsp', function(responseText) {
+ var start = responseText.indexOf('title="Topic View" src=\'');
+ if (start > 0) {
+ var end = responseText.indexOf("'", start + 24);
+ var element = createElement(null, 'p');
+ element.innerHTML = responseText.substring(start + 24, end);
+ getElementById('c').src = BASE_URL
+ + 'topic/'
+ + (element.textContent ? element.textContent : element.innerText);
+ updateDeepLink();
+ }
+ });
+
+ }
+
+ function syncToc() {
+ var newLocation = getElementById('c').contentWindow.location;
+ var toc = getElementById('t');
+ if (toc.s && toc.s.h == newLocation.href) return;
+ var newLocationHrefWithoutQueryAndHash = newLocation.protocol + '//' + newLocation.host + newLocation.pathname;
+ var newLocationHash = newLocation.hash;
+ var liMatch;
+ var liWhithoutHashMatch;
+ toc.v(function(li) {
+ if (newLocationHrefWithoutQueryAndHash != li.b) return 1;
+ if (!newLocationHash || newLocationHash == li.a) {
+ liMatch = li;
+ return 0;
+ }
+ if (!liWhithoutHashMatch) {
+ liWhithoutHashMatch = li;
+ }
+ return 1;
+ });
+ if (liMatch) {
+ toc.x(liMatch, toc, 1);
+ } else if (liWhithoutHashMatch) {
+ toc.x(liWhithoutHashMatch, toc, 1);
+ } else {
+ toc.y(newLocation.href, toc, 1);
+ }
+ }
+
+ function updateDeepLink(query) {
+ var hash;
+ if (query) {
+ hash = 'q=' + query;
+ } else {
+ try {
+ var src = getElementById('c').contentDocument.location.href;
+ if (BASE_URL != src.substring(0, BASE_URL.length)) return;
+ var current = src.substring(BASE_URL.length);
+ if ( 'nav/' == current.substring(0, 4)
+ || 'topic/' == current.substring(0, 6)
+ || 'rtopic/' == current.substring(0, 7)
+ || 'ntopic/' == current.substring(0, 7)
+ || 'nftopic/' == current.substring(0, 8)) {
+ hash = current;
+ }
+ } catch(e) {}
+ }
+ try {
+ var url = hash ? '#' + hash : window.location.href.replace(/^([^#\?]*(?:\?([^#\?]*))?)(#.*)?$/, '$1');
+ window.history.replaceState(null, '', url);
+ } catch(e) {}
+ }
+ function isQueryHash(hash) {
+ return hash && ( (hash.length > 1 && hash.substring(0, 2) == 'q=')
+ || (hash.length > 2 && hash.substring(0, 3) == '#q='));
+ }
+
+ function createSlider(tocSidebarToggleButton, toolbar, headSpacerElement) {
+
+ // create slider element
+ var slider = createElement();
+ slider.id = 's';
+ getElementById('m').insertBefore(slider, getElementById('c'));
+ var sliderWidth = slider.getBoundingClientRect().width;
+ var sliderHalfWidth = sliderWidth > 0 ? sliderWidth / 2 : 0;
+
+ // create overlay required for smooth slider drag'n'drop
+ var overlay = createOverlay();
+
+ // TOC sidebar with its style and width
+ var tocWidth;
+ var tocSidebar = getElementById('t');
+ var tocSidebarStyle = tocSidebar.style;
+ var headSpacerElementStyle = headSpacerElement.style;
+ var toolbarWidth = toolbar.getBoundingClientRect().width;
+ var tocSidebarMinimumWidth = TOC_SIDEBAR_MINIMUM_WIDTH > toolbarWidth ? TOC_SIDEBAR_MINIMUM_WIDTH : toolbarWidth;
+
+ // slider movement
+ function move(e) {
+ tocWidth = (e.touches ? e.touches[0].clientX : e.pageX) - sliderHalfWidth;
+ if (tocWidth < 0) {
+ tocWidth = 0;
+ }
+ tocSidebarStyle.width = tocWidth + 'px';
+ updateSpacerWidth();
+ preventDefault(e);
+ }
+ function moveEnd(e) {
+ if (e.touches) {
+ addOrRemoveEventListener(0, 'touchmove', move, 1);
+ addOrRemoveEventListener(0, 'touchcancel', moveEnd);
+ addOrRemoveEventListener(0, 'touchend', moveEnd);
+ } else {
+ addOrRemoveEventListener(0, 'mousemove', move);
+ addOrRemoveEventListener(0, 'mouseup', moveEnd);
+ }
+ overlay.o();
+ tocSidebarStyle.userSelect = '';
+ if (tocWidth < tocSidebarMinimumWidth) {
+ var oldWidth = getCookie('toc-width');
+ tocWidth = oldWidth ? oldWidth : TOC_SIDEBAR_DEFAULT_WIDTH;
+ toggleTocSidebar();
+ }
+ setCookie(TOC_SIDEBAR_WIDTH_COOKIE_NAME, tocWidth);
+ preventDefault(e);
+ stopPropagation(e);
+ }
+ function moveStart(e) {
+ if (e.which && e.which != 1) return;
+ if (e.touches) {
+ addOrRemoveEventListener(1, 'touchend', moveEnd);
+ addOrRemoveEventListener(1, 'touchcancel', moveEnd);
+ addOrRemoveEventListener(1, 'touchmove', move, 1);
+ } else {
+ addOrRemoveEventListener(1, 'mouseup', moveEnd);
+ addOrRemoveEventListener(1, 'mousemove', move);
+ }
+ overlay.a();
+ setClassName(tocSidebar, '');
+ tocSidebarStyle.transition = '';
+ headSpacerElementStyle.transition = '';
+ preventDefault(e);
+ stopPropagation(e);
+ }
+ var documentElement = document.documentElement;
+ function addOrRemoveEventListener(add, event, fn, passive) {
+ if (add) {
+ documentElement.addEventListener(event, fn, passive ? { passive: false } : false);
+ } else {
+ documentElement.removeEventListener(event, fn, passive ? { passive: false } : false);
+ }
+ }
+ function updateSpacerWidth(hideToc, tocWidth, withTransition) {
+ if (withTransition) {
+ headSpacerElementStyle.transition = 'width .25s ease-in';
+ }
+ var spacerWidth = (tocWidth || tocSidebar.getBoundingClientRect().right)
+ + sliderWidth
+ - toolbar.getBoundingClientRect().right;
+ var displayWidth = hideToc || spacerWidth < 0 ? 0 : spacerWidth;
+ headSpacerElementStyle.width = displayWidth + 'px';
+ var widthPostfix = displayWidth >= LOGO_ICON_WIDTH ? (displayWidth >= LOGO_FULL_WIDTH ? 'f' : 1) : 0;
+ setClassName(headSpacerElement, 'k' + (embeddedMode ? 'e' : '') + widthPostfix);
+ }
+
+ addEvent(slider, 'mousedown', moveStart);
+ addEvent(slider, 'touchstart', moveStart);
+
+ // TOC sidebar toggling
+ function toggleTocSidebar(e, initialize, asSmallScreenAutoCloseFn) {
+ if (!asSmallScreenAutoCloseFn) {
+ preventDefault(e);
+ }
+ var isSmall = isSmallScreen();
+ var currentClass = getClassName(tocSidebar);
+ if (asSmallScreenAutoCloseFn && (!isSmall || currentClass != 'show')) return;
+ var hideToc = isSmall ? currentClass == 'show' : tocWidth > 0;
+ if (initialize) {
+ tocWidth = -getCookie(TOC_SIDEBAR_WIDTH_COOKIE_NAME, TOC_SIDEBAR_DEFAULT_WIDTH);
+ hideToc = isSmall || tocWidth > 0;
+ } else {
+ tocSidebarStyle.transition = 'width .25s ease-in';
+ headSpacerElementStyle.transition = 'margin-right .25s ease-in';
+ }
+ setClassName(tocSidebar, isSmall ? (hideToc ? '' : 'show') : (hideToc ? 'hide' : ''));
+ if (initialize || !isSmall) {
+ tocWidth = -tocWidth;
+ if (!initialize) {
+ setCookie(TOC_SIDEBAR_WIDTH_COOKIE_NAME, tocWidth);
+ }
+ }
+ if (initialize || !isSmall) {
+ tocSidebarStyle.width = (hideToc ? 0 : tocWidth > tocSidebarMinimumWidth
+ ? tocWidth
+ : TOC_SIDEBAR_DEFAULT_WIDTH)
+ + 'px';
+ }
+ tocSidebarStyle.userSelect = hideToc ? 'none' : '';
+ if (!hideToc && tocSidebar.f) {
+ tocSidebar.f();
+ }
+ if (!isSmall) {
+ updateSpacerWidth(hideToc, tocWidth, 1);
+ }
+ }
+ toggleTocSidebar(0, 1);
+ addEvent(slider, 'dblclick', toggleTocSidebar);
+ addEvent(tocSidebarToggleButton, 'click', toggleTocSidebar);
+
+ // function to close TOC if screen is small
+ return function(e) {
+ toggleTocSidebar(e, 0, 1);
+ };
+
+ }
+
+ function tocContentProvider(node, processChildrenFn) {
+ var callbackUrl = BASE_URL + 'advanced/tocfragment'
+ + (node
+ ? (node.toc ? '?toc=' + node.toc : '')
+ + (node.path ? '&path=' + node.path : '')
+ + (node.topic ? '?errorSuppress=true&topic=' + node.topic : '')
+ + (node.expand ? '?errorSuppress=true&expandPath=' + node.expand : '')
+ : '');
+ remoteRequest(callbackUrl, function(responseText) {
+ var nodes = tocXmlNodes(parseXml(responseText), node ? node.toc : 0, node ? node.path : 0);
+ var children;
+ for (var i = 0; i < nodes.length; i++) {
+ var n = nodes[i];
+ if (n.tagName == 'numeric_path') {
+ tocContentProvider({expand: getAttribute(n, 'path')}, processChildrenFn);
+ return;
+ }
+ if (n.tagName == 'node') {
+ children = tocToNodes(nodes, node ? node.toc : 0, node ? node.expand : 0);
+ break;
+ }
+ }
+ if (!node) {
+ createSearchField();
+ initContentPage();
+ setFontSize(0, 1);
+ }
+ processChildrenFn(children);
+ });
+ }
+ function tocXmlNodes(xml, toc, path) {
+ var books = xml.documentElement.childNodes;
+ if (!toc) return books;
+ var book;
+ for (var i = 0; i < books.length; i++) {
+ book = books[i];
+ if (book.tagName == 'node' && toc == book.getAttribute('id')) {
+ if (!path) return book.childNodes;
+ break;
+ }
+ }
+ var nodes = book.childNodes;
+ tocLevelLoop: while (1) {
+ for (var i = 0; i < nodes.length; i++) {
+ n = nodes[i];
+ if (n.tagName != 'node') continue;
+ var id = n.getAttribute('id');
+ if (path == id) return n.childNodes;
+ if ( id
+ && path.length > id.length
+ && path.substring(0, id.length + 1) == id + '_') {
+ nodes = n.childNodes;
+ continue tocLevelLoop;
+ }
+ }
+ break;
+ }
+ return [];
+ }
+ function tocToNodes(xmlChildren, toc, expandPath) {
+ var children = [];
+ for (var i = 0; i < xmlChildren.length; i++) {
+ var n = xmlChildren[i];
+ if (n.tagName != 'node') continue;
+ var currentToc = toc ? toc : getAttribute(n, 'id');
+ children.push({
+ n/*node*/: {
+ toc: currentToc,
+ path: toc ? getAttribute(n, 'id') : 0,
+ t: getAttribute(n, 'title'),
+ h: BASE_URL + getAttribute(n, 'href').substring(3),
+ i: n.getAttribute('image'),
+ y: expandPath,
+ l/*is leaf*/: getAttribute(n, 'is_leaf')
+ },
+ l/*is leaf*/: getAttribute(n, 'is_leaf'),
+ c/*children*/: tocToNodes(n.childNodes, currentToc)
+ });
+ }
+ return children;
+ }
+
+ function isSmallScreen() {
+ var clientWidth = document.documentElement.clientWidth || document.body.clientWidth;
+ return clientWidth <= SMALL_SCREEN_WIDTH;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Search: search-as-you-type ('t') and full search ('f')
+
+ function createSearchField() {
+ var currentTocLi;
+
+ // create overlay required for closing proposals drop-down even when clicking into the content iframe
+ var overlay = createOverlay();
+ addEvent(overlay, 'click', hideProposals);
+
+ // area (containing scope drop-down, search field and button)
+ // "searchFieldAreaWrapper" as workaround for sub-pixel problem in Firefox (1px border might become 0.8px border
+ // to align real pixels on high-DPI to CSS px), otherwise proposals drop-down might not correctly aligned with
+ // search field area
+ var searchFieldAreaWrapper = createElement(getElementById('h'), 0, 'q0');
+ var searchFieldArea = createElement(createElement(searchFieldAreaWrapper, 0, 'q1'), 'form', 'q');
+
+ if (embeddedMode) {
+ createButton(searchFieldAreaWrapper, BOOKMARKS_ICON, BOOKMARKS_DESCRIPTION, function() {
+ bookmarksPage.s(!bookmarksPage.o);
+ });
+ }
+
+ var searchFieldAreaHasFocus;
+ var searchFieldAreaContainsQuery;
+ var proposals;
+ function updateSearchFieldAreaClass() {
+ setClassName(searchFieldArea,
+ 'q' + (proposals.style.display == 'block' ? 'm' : (searchFieldAreaHasFocus ? 'f' : ''))
+ + (searchFieldAreaContainsQuery ? ' qa' : '')
+ );
+ }
+ createMenu();
+
+ // scopes drop-down
+ var scopeButtonWrapper = createElement(searchFieldArea, 0, 's0');
+
+ var booksButton = createElement(scopeButtonWrapper, 'button', 's');
+ setAttribute(booksButton, 'type', 'button');
+ booksButtonText = createElement(booksButton, 'span');
+ var dropDownHandle = createElement(booksButton, 'span', 'de');
+ setInnerHtml(dropDownHandle, TREE_HANDLE);
+ var booksDropDown = createElement(scopeButtonWrapper, 0, 'u');
+ booksDropDown.s = function(show) {
+ var isOpen = booksDropDown.style.display == 'block';
+ if (!isOpen == !show) return;
+ booksDropDown.style.display = show ? 'block' : 'none';
+ if (!show) return;
+ setInnerHtml(booksDropDown);
+ var booksDropDownUl = createElement(booksDropDown, 'ul', 'r');
+ var menuItems = [];
+ var dataItems = [];
+ var currentBook;
+ var currentChapter;
+ for (var tocLi = currentTocLi; tocLi && tocLi.n; tocLi = tocLi.p) {
+ if (!tocLi.n.path) {
+ currentBook = tocLi.n.t;
+ if (!currentChapter) {
+ currentChapter = currentBook;
+ }
+ } else if (!currentChapter && !tocLi.n.l) {
+ currentChapter = tocLi.n.t;
+ }
+ }
+ menuItems.push(createElement(booksDropDownUl, 'li', searchScope.l == 0 ? 'x': 0, SEARCH_SCOPE_LABEL_NONE));
+ dataItems.push([0]);
+ menuItems.push(createElement(booksDropDownUl, 'li', searchScope.l == 1 ? 'x': 0, SEARCH_SCOPE_LABEL_BOOK + (currentBook ? ': ' + currentBook : '')));
+ dataItems.push([1]);
+ menuItems.push(createElement(booksDropDownUl, 'li', searchScope.l == 2 ? 'x': 0, SEARCH_SCOPE_LABEL_CHAPTER + (currentChapter ? ': ' + currentChapter : '')));
+ dataItems.push([2]);
+// menuItems.push(createElement(booksDropDownUl, 'li', searchScope.l == 3 ? 'x': 0, SEARCH_SCOPE_LABEL_TOPIC));
+// dataItems.push([3]);
+ remoteRequest(BASE_URL + 'advanced/workingSetManager.jsp?t=' + Date.now(), function(menuItems, dataItems) {
+ return function(responseText) {
+ var delimiter = 'l ';
+ var scopeIndex = 0;
+ SEARCH_SCOPE_ALL_PATTERN.lastIndex = 0;
+ for (var match; (match = SEARCH_SCOPE_ALL_PATTERN.exec(responseText)) != null;) {
+ var label = decodeHtml(match[1]);
+ if (label.substring(0, 1) == '\u200B') continue;
+ var className = delimiter + (searchScope.l == 4 && searchScope.s == label ? 'x' : '');
+ menuItems.push(createElement(booksDropDownUl, 'li', className, label));
+ delimiter = '';
+ dataItems.push([4, label, scopeIndex]);
+ scopeIndex++;
+ }
+ menuItems.push(createElement(booksDropDownUl, 'li', 'l y', 'Scopes...'));
+ dataItems.push([5]);
+ toMenu(booksButton, menuItems, dataItems, setSearchScope);
+ }
+ }(menuItems, dataItems));
+ }
+ booksDropDown.s();
+ var scopeOverlay = createOverlay(4);
+ addEvent(scopeOverlay, 'click', function() { booksDropDown.s(); scopeOverlay.o(); });
+ addEvent(booksButton, 'mousedown', function(e) {
+ var isOpen = booksDropDown.style.display == 'block';
+ try {
+ booksButton.focus();
+ } catch(e) {}
+ booksDropDown.s(!isOpen);
+ if (isOpen) {
+ scopeOverlay.o();
+ } else {
+ scopeOverlay.a();
+ }
+ preventDefault(e);
+ stopPropagation(e);
+ });
+ addEvent(booksButton, 'click', function(e) {stopPropagation(e)});
+ addEvent(booksButton, 'focus', function() {
+ booksDropDown.hasFocus = true;
+ booksDropDown.s(1);
+ scopeOverlay.a();
+ });
+// addEvent(booksButton, 'blur', function() {
+// booksDropDown.hasFocus = false;
+// setTimeout(function() {if (!booksDropDown.hasFocus) booksDropDown.style.display = 'none'}, 200);
+// });
+ if (!embeddedMode && BOOK_SCOPE_BY_DEFAULT && searchScope.l == 0 && getCookie(BOOK_SCOPE_COOKIE) != 'init') {
+ setCookie(BOOK_SCOPE_COOKIE, 'init');
+ setTimeout(function(){ if(setSearchScope) setSearchScope([1]); }, 420);
+ } else {
+ updateScopeButtonLabel();
+ }
+
+ setSearchScope = function(scopeData) {
+ booksDropDown.s();
+ scopeOverlay.o();
+ if (scopeData[0] == 5) {
+ scopesPage.s(1);
+ return;
+ }
+ if (searchScope.l != scopeData[0]) {
+ var scopeToRemove;
+ if (searchScope.l == 1 || searchScope.l == 2 || searchScope.l == 4) {
+ scopeToRemove = '%E2%80%8B' + (searchScope.l > 1 ? '%E2%80%8B' : '');
+ for (var i = 0; searchScope.l == 4 && i <= searchScope.t; i++) {
+ scopeToRemove += '%E2%80%8B';
+ }
+ }
+ var scopeToAdd;
+ if (scopeData[0] == 1 || scopeData[0] == 2 || scopeData[0] == 4) {
+ scopeToAdd = '%E2%80%8B' + (scopeData[0] > 1 ? '%E2%80%8B' : '');
+ for (var i = 0; scopeData[0] == 4 && i <= scopeData[2]; i++) {
+ scopeToAdd += '%E2%80%8B';
+ }
+ }
+ if (scopeToRemove || scopeToAdd) {
+ remoteRequest( BASE_URL
+ + 'workingSetState.jsp?operation='
+ + (scopeToRemove && scopeToAdd ? 'edit' : (scopeToRemove ? 'remove' : 'add'))
+ + (scopeToRemove && scopeToAdd ? '&oldName=' + scopeToRemove : '')
+ + '&workingSet='
+ + (!scopeToAdd ? scopeToRemove : scopeToAdd)
+ + '&t=' + Date.now());
+ }
+ }
+ searchScope.l = scopeData[0];
+ searchScope.s = searchScope.l == 4 ? scopeData[1] : 0;
+ searchScope.t = searchScope.l == 4 ? scopeData[2] : 0;
+ updateScopeButtonLabel();
+ }
+ updateScopeByToc = function(li) {
+ currentTocLi = li;
+ updateScopeButtonLabel();
+ }
+ function updateScopeButtonLabel() {
+ setInnerHtml(booksButtonText, '');
+ if (searchScope.l == 0 || (searchScope.l < 3 && !currentTocLi)) return;
+ var newButtonlabel;
+ for (var tocLi = currentTocLi; searchScope.l < 3 && tocLi && tocLi.n; tocLi = tocLi.p) {
+ if (!tocLi.n.path || (searchScope.l == 2 && !tocLi.n.l)) {
+ newButtonlabel = tocLi.n.t;
+ break;
+ }
+ }
+ if (searchScope.l == 4) {
+ newButtonlabel = searchScope.s;
+ }
+ if (newButtonlabel) {
+ booksButtonText.appendChild(document.createTextNode(BOOK_NAME_SHORTENER(newButtonlabel)));
+ }
+ }
+
+ // search field
+ var wrap = createElement(searchFieldArea, 0, 'q2');
+ wrap.style.position = 'relative';
+ var searchField = createElement(wrap, 'input');
+ searchField.id = 'q';
+ searchField.type = 'text';
+ searchField.alt = SEARCH_FIELD_DESCRIPTION;
+ searchField.title = SEARCH_FIELD_DESCRIPTION;
+ searchField.autocomplete = 'off';
+ searchField.placeholder = SEARCH_FIELD_PLACEHOLDER;
+ addEvent(searchField, 'input', search); // for IE 8 do also on 'propertychange'
+ addEvent(searchField, 'focus', search);
+
+ var searchButton = createElement(searchFieldArea, 'button', 'b');
+ setInnerHtml(searchButton, SEARCH_ICON);
+ addEvent(searchFieldArea, 'submit', function(e) {preventDefault(e); search(e, 1);});
+
+ // hint
+ var hintField = createElement(wrap, 'input', 'qh');
+ if (searchField.nextSibling) {
+ searchField.parentNode.insertBefore(hintField, searchField.nextSibling);
+ }
+ searchField.style.position = 'relative';
+ hintField.style.position = 'absolute';
+ hintField.style.left = 0;
+ hintField.style.top = 0;
+ hintField.style.height = '100%';
+ hintField.style.width = '100%';
+ hintField.style.background = 'transparent';
+ hintField.style.borderColor = 'transparent';
+ hintField.setAttribute('disabled', 'disabled');
+ wrap.appendChild(searchField);
+ searchField.style.background = 'url("data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw%3D%3D") repeat';
+
+ var searchFieldAreaElements = [booksButton, searchField, searchButton];
+ for (var i = 0; i < searchFieldAreaElements.length; i++) {
+ addEvent(searchFieldAreaElements[i], 'focus', function() {
+ searchFieldAreaHasFocus = 1;
+ updateSearchFieldAreaClass();
+ });
+ addEvent(searchFieldAreaElements[i], 'blur', function() {
+ searchFieldAreaHasFocus = 0;
+ updateSearchFieldAreaClass();
+ });
+ }
+
+ // proposals drop-down
+ proposals = createElement(searchFieldArea, 0, 'p');
+ addEvent(proposals, 'click', function(e) {stopPropagation(e)});
+ function showProposals() {
+ proposals.style.display = 'block';
+ overlay.a();
+ updateSearchFieldAreaClass();
+ }
+ function hideProposals() {
+ proposals.style.display = 'none';
+ overlay.o();
+ updateSearchFieldAreaClass();
+ }
+ hideProposals();
+
+ // focus search field
+ searchField.focus();
+
+ function search(e, fullSearch) {
+ var noPendingQueries = !currentSearch[getSearchTypeId(fullSearch)];
+
+ // get search word, query, URL and remember query to detect stale responses
+ var searchWord = searchField.value
+
+ // trim
+ .replace(/(^\s+|\s+$)/ig, '')
+
+ // TODO if Eclipse bug 351077 (https://bugs.eclipse.org/351077), remove following line
+ .replace(/\-([^\-\s]*$)/ig, ' $1');
+
+ var tocScope = currentTocLi ? currentTocLi.n : currentTocLi;
+ for (var tocLi = currentTocLi; searchScope.l < 3 && tocLi && tocLi.n; tocLi = tocLi.p) {
+ if (!tocLi.n.path || (searchScope.l == 2 && !tocLi.n.l)) {
+ tocScope = tocLi.n;
+ break;
+ }
+ }
+ var query = searchWord.length
+ ? ( encodeURIComponent(searchWord.toLowerCase())
+ + ((searchScope.l == 1 || searchScope.l == 2) && tocScope && tocScope.toc ? '&toc=' + encodeURIComponent(tocScope.toc) : '')
+ + (searchScope.l == 2 && tocScope && tocScope.path ? '&path=' + tocScope.path : '')
+ + (searchScope.l == 4 && searchScope.s ? '&scope=' + encodeURIComponent(searchScope.s) : ''))
+ : '';
+ var url = SEARCH_BASE_URL
+ + query.replace(/(\&|$)/, (fullSearch ? '' : '*') + '$1')
+ + '&maxHits='
+ + (fullSearch ? SEARCH_HITS_MAX : SEARCH_AS_YOU_TYPE_PROPOSAL_MAX)
+ + (query.indexOf('&toc=') < 0 ? '' : '&quickSearch=true&quickSearchType=QuickSearchToc');
+ currentSearch[getSearchTypeId(fullSearch)] = query;
+ if (fullSearch) {
+ currentSearch['t'] = 0;
+ hideProposals();
+ if (bookmarksPage) bookmarksPage.s();
+ if (scopesPage) scopesPage.s();
+ updateDeepLink(query);
+ } else {
+
+ // hide hint
+ hintField.value = '';
+
+ }
+
+ // empty search?
+ searchFieldAreaContainsQuery = searchWord.length;
+ updateSearchFieldAreaClass();
+ if (!searchWord.length) {
+ if (!fullSearch) {
+ hideProposals();
+ }
+ return;
+ }
+
+ // init UI
+ if (fullSearch) {
+ if (searchPage.o && query == searchPage.q) return;
+ searchPage.s(1);
+ if (query == searchPage.q) {
+ window.frames.c.location = url;
+ return;
+ }
+ setInnerHtml(searchPage, 'Searching...');
+ searchPage.scrollTop = 0;
+ } else if (query == proposals.q) {
+ preventDefault(e);
+ showProposals();
+ return;
+ }
+
+ // cached?
+ var cache = SEARCH_CACHE[getSearchTypeId(fullSearch)];
+ for (var i = 0; i < cache.length; i++) {
+ var r = cache[i];
+ if (query == r.q) {
+ if (fullSearch) {
+ window.frames.c.location = url;
+ }
+ renderResults(fullSearch, r.r, r.b, query, searchWord, r.s);
+ return;
+ }
+ }
+
+ // submit query to server
+ if (fullSearch) {
+ window.frames.c.location = url;
+ return;
+ }
+ var currentSearchScope = {
+ /* level */ l: searchScope.l,
+ /* (custom) scope name */ s: searchScope.s,
+ /* path */ p: 0
+ };
+ if (searchScope.l > 0 && searchScope.l < 3 && currentTocLi) {
+ currentSearchScope.p = [currentTocLi.n];
+ for (var parentLi = currentTocLi.p; searchScope.l > 1 && parentLi && parentLi.n; parentLi = parentLi.p) {
+ currentSearchScope.p.unshift(parentLi.n);
+ }
+ }
+ var callbackFn = callbackFor(fullSearch, query, searchWord, currentSearchScope);
+ if (noPendingQueries) {
+ remoteRequest(url, callbackFn, getSearchTypeId(fullSearch));
+ } else {
+ setTimeout(function() {
+
+ // remote request if and only if not staled/outdated
+ if (query == currentSearch[getSearchTypeId(fullSearch)])
+ remoteRequest(url, callbackFn, getSearchTypeId(fullSearch));
+
+ }, SEARCH_DELAY_IN_MILLISECOND);
+ }
+ }
+
+ renderFullSearch = function(queryPart, data) {
+ var query = queryPart.substring(0, queryPart.indexOf('&maxHits='));
+ updateDeepLink(query);
+ if (query == searchPage.q) return;
+ var valuePairs = queryPart.split('&');
+ var searchWord;
+ var toc;
+ var path;
+ var scope;
+ for (var i = 0; i < valuePairs.length; i++) {
+ if (!searchWord && valuePairs[i].indexOf('=') < 0) {
+ searchWord = decodeURIComponent(valuePairs[i]);
+ } else if (valuePairs[i].substring(0, 4) == 'toc=') {
+ toc = decodeURIComponent(valuePairs[i].substring(4));
+ } else if (valuePairs[i].substring(0, 5) == 'path=') {
+ path = decodeURIComponent(valuePairs[i].substring(5));
+ } else if (valuePairs[i].substring(0, 6) == 'scope=') {
+ scope = decodeURIComponent(valuePairs[i].substring(6));
+ }
+ }
+ var currentSearchScope = {
+ /* level */ l: scope ? 4 : (toc ? (path ? 2 : 1) : 0),
+ /* (custom) scope name */ s: scope,
+ /* path */ p: 0
+ };
+ var scopeFound = !toc;
+ if (toc && currentTocLi && currentTocLi.n) {
+ var nodes = [currentTocLi.n];
+ for (var parentLi = currentTocLi.p; parentLi && parentLi.n; parentLi = parentLi.p) {
+ if (path) {
+ nodes.unshift(parentLi.n);
+ } else {
+ nodes = [parentLi.n];
+ }
+ }
+ if (toc == nodes[0].toc && (!path || path == nodes[nodes.length - 1].path)) {
+ currentSearchScope.p = nodes;
+ scopeFound = 1;
+ }
+ }
+ if (!scopeFound) {
+ remoteRequest( BASE_URL + 'advanced/tocfragment?toc=' + encodeURIComponent(toc)
+ + (path ? '&path=' + path : ''), (function(toc, path, currentSearchScope, searchWord, query, data) {
+ return function(responseText) {
+ var nodePath = [];
+ var books = parseXml(responseText).documentElement.childNodes;
+ var book;
+ for (var i = 0; i < books.length; i++) {
+ book = books[i];
+ if (book.tagName == 'node' && toc == book.getAttribute('id')) {
+ nodePath.push({t: book.getAttribute('title'), toc: toc});
+ break;
+ }
+ }
+ var nodes = book.childNodes;
+ tocLevelLoop: while (path) {
+ for (var i = 0; i < nodes.length; i++) {
+ n = nodes[i];
+ if (n.tagName != 'node') continue;
+ var id = n.getAttribute('id');
+ if (path == id) {
+ nodePath.push({t: n.getAttribute('title'), toc: toc, path: id});
+ break tocLevelLoop;
+ };
+ if ( id
+ && path.length > id.length
+ && path.substring(0, id.length + 1) == id + '_') {
+ nodes = n.childNodes;
+ nodePath.push({t: n.getAttribute('title'), toc: toc, path: id});
+ continue tocLevelLoop;
+ }
+ }
+ break;
+ }
+ currentSearchScope.p = nodePath;
+ (callbackFor(1, query, searchWord, currentSearchScope))(data);
+ };})(toc, path, currentSearchScope, searchWord, query, data));
+ return;
+ }
+ (callbackFor(1, query, searchWord, currentSearchScope))(data);
+ }
+
+ function callbackFor(fullSearch, query, searchWord, searchScope) {
+ return function(data) {
+
+ // indexing in progress?
+ var match = SEARCH_RESULTS_INDEXING_PATTERN.exec(data);
+ if (match != null) {
+ if (fullSearch) {
+ setInnerHtml(searchPage, 'Indexing... ' + match[1] + '%');
+ }
+ return;
+ }
+
+ // parse HTML for results
+ var element = createElement();
+ var hasBreadcrumbs = 0;
+ var results = [];
+
+ SEARCH_RESULTS_PATTERN.lastIndex = 0;
+ for (var match; (match = SEARCH_RESULTS_PATTERN.exec(data)) != null;) {
+ var items = [];
+ for (var i = 2; i < 8; i++) {
+ element.innerHTML = match[i];
+ items.push((element.textContent ? element.textContent : element.innerText).replace(/^\s+|\s+$/g,'').replace(/\s+/g,' '));
+ }
+ var breadcrumb = [];
+ if (match[6]) {
+ SEARCH_RESULTS_BREADCRUMB_SNIPPET_PATTERN.lastIndex = 0;
+ for (var breadcrumbMatch; (breadcrumbMatch = SEARCH_RESULTS_BREADCRUMB_SNIPPET_PATTERN.exec(match[6])) != null;) {
+ for (var i = 1; i < 3; i++) {
+ element.innerHTML = breadcrumbMatch[i];
+ breadcrumb.push((element.textContent ? element.textContent : element.innerText).replace(/^\s+|\s+$/g,'').replace(/\s+/g,' '));
+ }
+ }
+ hasBreadcrumbs = 1;
+ }
+ var hrefFollowedByTitle = 'href' == match[1];
+ results.push({
+ /* title */ t: items[3],
+ /* description */ d: items[5],
+ /* href */ h: items[hrefFollowedByTitle ? 0 : 2].substring(8),
+ /* breadcrumb */ b: match[6] ? breadcrumb : [0, items[hrefFollowedByTitle ? 2 : 0]]
+ });
+ }
+
+ // cache parsed results
+ var queryResult = {
+ /* results */ r: results,
+ /* has breadcrumbs */ b: hasBreadcrumbs,
+ /* query */ q: query,
+ /* search scope */ s: searchScope
+ }
+ var cache = SEARCH_CACHE[getSearchTypeId(fullSearch)];
+ var cacheIndexId = getSearchTypeId(fullSearch) + 'i';
+ var cacheSize = fullSearch ? SEARCH_FULL_SEARCH_CACHE_SIZE : SEARCH_AS_YOU_TYPE_CACHE_SIZE;
+ SEARCH_CACHE[cacheIndexId] = (SEARCH_CACHE[cacheIndexId] + 1) % cacheSize;
+ if (cache.length < cacheSize) {
+ cache.push(queryResult);
+ } else {
+ cache[SEARCH_CACHE[cacheIndexId]] = queryResult;
+ }
+
+ renderResults(fullSearch, results, hasBreadcrumbs, query, searchWord, searchScope);
+ }
+
+ }
+
+ function renderResults(fullSearch, results, hasBreadcrumbs, query, searchWord, searchScope) {
+
+ // staled?
+ if (!fullSearch && query != currentSearch[getSearchTypeId(fullSearch)]) return;
+
+ // show results
+ var items = [];
+ var data = [];
+ var filters = [];
+ var filterValues = [];
+ function applyFilters(e) {
+ var includeFilters = [];
+ var excludeFilters = [];
+ for (var i = 0; i < filters.length; i++) {
+ var f = filters[i];
+ if (!f.checked && !f.indeterminate) excludeFilters.push(filterValues[i]);
+ if (f.checked && !f.indeterminate) includeFilters.push(filterValues[i]);
+ }
+ for (var i = 0; i < items.length; i++) {
+ items[i].style.display = arrayContainsPrefix(includeFilters, data[i])
+ && !arrayContainsPrefix(excludeFilters, data[i])
+ ? 'block'
+ : 'none';
+ }
+ stopPropagation(e);
+ }
+
+ var searchScopeLabel = searchScope.l > 3 ? searchScope.s : '';
+ if (searchScope.p) {
+ for (var i = 0; i < searchScope.p.length; i++) {
+ if (i > 0) {
+ searchScopeLabel += ' > ';
+ }
+ searchScopeLabel += searchScope.p[i].t;
+ }
+ }
+ var parentElement = fullSearch ? searchPage : proposals;
+ setInnerHtml(parentElement, '');
+ parentElement.q = query;
+ parentElement.l = 'Search' + (searchScope.l > 0 ? ' (' + searchScopeLabel+ ')': '') + ': ' + searchWord;
+ if (fullSearch) {
+ document.title = searchPage.l + ' - ' + title;
+
+ // no results?
+ if (!results.length) {
+ var noResults = createElement(searchPage, 0, 'r0', 'No results found for ');
+ createElement(noResults, 'strong', 0, searchWord);
+ return;
+ }
+
+ // filter tree
+ var filterTree = asTree(results, [], 9, true);
+ // TODO correction of tree for deeper scopes (below) might be done in "asTree" or "asTree" might be better simplified
+ if (searchScope.p && filterTree.length == 1 && filterTree[0].isNode) {
+ var afterCutOff = searchScope.p.length * 2 - filterTree[0].name.length;
+ if (afterCutOff < 0) {
+ filterTree[0].name = filterTree[0].name.slice(searchScope.p.length * 2);
+ } else if (afterCutOff >= 0) {
+ filterTree = filterTree[0].children;
+ if (afterCutOff > 0 && filterTree.length > 0 && filterTree[0].isNode) {
+ if (filterTree[0].name.length <= afterCutOff) {
+ filterTree = filterTree[0].children;
+ } else {
+ filterTree[0].name = filterTree[0].name.slice(afterCutOff);
+ }
+ }
+ }
+ }
+ createTree(searchPage,
+
+ // content provider
+ function(node, processChildrenFn) {
+ if (!node) {
+ processChildrenFn([{ n/*ode*/: {children: filterTree}, l/*eaf*/: 0 }], 1);
+ return;
+ }
+ var children = [];
+ for (var i = 0; i < (node.isNode ? node.children.length : filterTree.length); i++) {
+ var childNode = node ? node.children[i] : filterTree[i];
+ if (childNode.isNode) {
+ var isLeaf = 1;
+ for (var j = 0; j < childNode.children.length; j++) {
+ if (childNode.children[j].isNode) {
+ isLeaf = 0;
+ break;
+ }
+ }
+ children.push({ n/*ode*/: childNode, l/*eaf*/: isLeaf });
+ childNode.p/*arent*/ = node;
+ }
+ }
+ processChildrenFn(children);
+ },
+
+ // label provider
+ function(li, node) {
+ var isRoot = !node.isNode;
+
+ // checkbox
+ var checkboxWithLabel = createElement(li);
+ var checkbox = createElement(checkboxWithLabel, 'input');
+ checkbox.type = 'checkbox';
+ checkbox.checked = node.p ? node.p.x.checked : true;
+ node.x = checkbox;
+ if (node.p) {
+ checkbox.parentCheckbox = node.p.x;
+ }
+ checkbox.numberOfResults = isRoot ? results.length : node.count;
+ filters.push(checkbox);
+ filterValues.push(isRoot ? '' : toValue(node.l.concat(node.name)));
+
+ // label
+ var labelText = '';
+ if (isRoot) {
+ checkbox.style.display = 'none';
+ labelText = 'Results ' + (searchScope && searchScope.l > 0 ? 'in ' : '');
+ } else {
+ addEvent(checkbox, 'click', (function(liCheck, li) {
+ return function() {
+ selectSubtree(li, liCheck.checked);
+ updateParentsChecks(liCheck);
+ applyFilters();
+ };
+ })(checkbox, li));
+ for (var i = 0; i < node.name.length; i+=2) {
+ labelText += (i == 0 ? '' : ' > ') + node.name[i+1];
+ }
+ }
+ var label = createElement(checkboxWithLabel, 'span', node.isNode ? 0 : 't', labelText + ' ');
+ if (isRoot && searchScope && searchScope.l > 0 ) {
+ createElement(label, 'span', 'tl', searchScopeLabel + ' ');
+ }
+ createElement(label, 'span', 'count', checkbox.numberOfResults);
+ addEvent(label, 'click', (function(checkbox, li) {
+ return function() {
+ var root;
+ for (root = checkbox; root.parentCheckbox; root = root.parentCheckbox);
+ for (var i = 0; i < 5; i++) {
+ root = getParentElement(root);
+ if (root.tagName == 'UL') break;
+ }
+ selectSubtree(root, false);
+ selectSubtree(li, true);
+ updateParentsChecks(checkbox);
+ applyFilters();
+ };
+ })(checkbox, li));
+
+ return checkboxWithLabel;
+ },
+ 0);
+
+ }
+ var resultList = createElement(parentElement, 'ol', 'j');
+ if (!fullSearch) {
+
+ // no results?
+ if (!results.length) return;
+
+ // hint
+ var wordBeginRegEx = queryToRegEx(query);
+ var newHints = {};
+ for (var i = 0; i < results.length && searchWord.length < 36; i++) {
+ var match = wordBeginRegEx.exec(results[i].t/*title*/);
+ if (match) {
+ var pHint = match[0].toLowerCase();
+ newHints[pHint] = (newHints[pHint] ? newHints[pHint] : 0)
+ + (1 + (results.length - i) / results.length) / results.length;
+ }
+ match = wordBeginRegEx.exec(results[i].d/*description*/);
+ if (match) {
+ var pHint = match[0].toLowerCase();
+ newHints[pHint] = (newHints[pHint] ? newHints[pHint] : 0)
+ + (0.7 + (results.length - i) / results.length) / results.length;
+ }
+ }
+ var allHints = [];
+ for (var i in newHints) {
+ if (newHints[i] < 1.8 / results.length) continue;
+ allHints.push(newHints[i].toFixed(7) + i);
+ }
+ allHints.sort().reverse();
+ hintField.value = allHints.length > 0
+ ? searchField.value + wordBeginRegEx.exec(allHints[0].substring(9))[1]
+ : '';
+
+ // query proposals
+ for (var i = 0; i < allHints.length && i < 3; i++) {
+ var hintText = allHints[i].substring(9);
+ var li = createElement(resultList, 'li');
+ var button = createElement(li, 'button');
+ var spacerElementStyle = createElement(button, 'span').style;
+ spacerElementStyle.display = 'inline-block';
+ spacerElementStyle.width = booksButton.offsetWidth + 'px';
+ createElement(button, 'span', null, hintText.substring(0, searchWord.length));
+ createElement(button, 'strong', null, hintText.substring(searchWord.length));
+ items.push(li);
+ data.push([hintText]);
+ }
+
+ }
+
+ function toValue(path) {
+ var result = '';
+ for (var i = 0; i < path.length; i++) result += (i > 0 ? '\n' : '') + path[i];
+ return result;
+ }
+
+ // list results
+ for (var i = 0; i < results.length; i++) {
+ var node = results[i];
+ var li = createElement(resultList, 'li');
+ var a = createElement(li, 'a');
+ a.href = BASE_URL + 'topic' + node.h/*href*/;
+ a.target = 'c';
+ var titleAndLocation = createElement(a, 0, 'm');
+
+ // title
+ addHighlightedText(createElement(titleAndLocation, 0, 'v'), node.t/*title*/, searchWord);
+
+ // show book title only for no book/chapter scope
+ if (!fullSearch && !searchScope.p) {
+ createElement(titleAndLocation, 0, 'w', node.b/*breadcrumb*/[1]);
+ }
+
+ // breadcrumb
+ if (fullSearch && hasBreadcrumbs && node.b/*breadcrumb*/) {
+ var location = createElement(titleAndLocation, 0, 'w');
+ for (var j = searchScope && searchScope.p ? searchScope.p.length * 2 : 0; j < node.b/*breadcrumb*/.length; j+=2) {
+ createElement(location, 'span', 0, node.b/*breadcrumb*/[j+1]);
+ if (j < node.b/*breadcrumb*/.length-2) {
+ createElement(location, 'span', 0, ' > ');
+ }
+ }
+ }
+
+ // description
+ addHighlightedText(createElement(a, 0, 'n'), node.d/*description*/, searchWord);
+
+ // UI element and corresponding data
+ items.push(li);
+ if (fullSearch) {
+ var resultofStart = node.h/*href*/.indexOf('?resultof=');
+ var hrefNormed = '../topic' + (resultofStart < 0 ? node.h/*href*/ : node.h/*href*/.substring(0, resultofStart));
+ data.push(toValue(node.b/*breadcrumb*/.slice().concat(hrefNormed).concat(node.t/*title*/)));
+ } else {
+ data.push([node.t/*title*/, node.h/*href*/]);
+ }
+
+ }
+
+ // add key support (and show proposals)
+ if (fullSearch) {
+// toMenu(searchField, items, results, function(d) {
+// getElementById('c').src = BASE_URL + 'topic' + d.h/*href*/;
+// },
+// 0,
+// 0,
+// function(item, data, viaMouse) {
+// if (!viaMouse) {
+// scrollIntoViewIfNeeded(searchPage, item);
+// }
+// },
+// 1);
+ } else {
+
+ // key support
+ toMenu(searchField, items, data, function(d) {
+
+ // apply hint
+ if (d.length < 2) {
+ hintField.value = '';
+ searchField.value = d;
+ search();
+ return;
+ }
+
+ // show search result
+ var searchWord = d[0];
+ var toc;
+ var tocStart = searchWord.indexOf('&toc=');
+ if (tocStart > 0) {
+ toc = decodeURIComponent(searchWord.substring(tocStart + 5));
+ searchWord = searchWord.substring(0, tocStart);
+ }
+ if (searchSearchWord(searchWord + '*', toc, d[1], false, true)) return;
+ getElementById('c').src = BASE_URL + 'topic' + d[1];
+ hideProposals();
+
+ },
+ function(d, key) {
+
+ // empty search field?
+ if (!searchField.value) return false;
+
+ // ignore RIGHT (key: 39) if cursor not at the end
+ if ( key == 39
+ && searchField
+ && searchField.selectionStart
+ && searchField.value
+ && searchField.value.length != searchField.selectionStart)
+ return false;
+
+ if (d && d.length > 0 && d[0].length < 2) {
+ searchField.value = d[0][0];
+ search();
+ return true;
+ }
+ return false;
+ },
+ hideProposals,
+ function(a, b) {
+ if (b.length < 2 || a.armed) return;
+ a.armed = true;
+ var iFrame = createElement(a, 'iframe', 'f');
+ iFrame.frameBorder = 0;
+
+ // TODO handle absolute paths
+ iFrame.src = BASE_URL + 'topic' + b[1];
+ });
+
+ // show proposals
+ showProposals();
+
+ }
+
+ // done (no pending queries)
+ if (query == currentSearch[getSearchTypeId(fullSearch)]) {
+ currentSearch[getSearchTypeId(fullSearch)] = 0;
+ }
+
+ }
+
+ function getSearchTypeId(fullSearch) {
+ return fullSearch ? 'f' : 't';
+ }
+
+ function asTree(results, path, depth) {
+ if (depth < 1) return results;
+ var tree = [];
+ var grouped = {};
+ for (var i = 0; i < results.length; i++) {
+ var r = results[i];
+ r.p = i;
+ r.q = r.b/*breadcrumb*/.slice();
+ var resultofStart = r.h/*href*/.indexOf('?resultof=');
+ r.q.push('../topic' + (resultofStart < 0 ? r.h/*href*/ : r.h/*href*/.substring(0, resultofStart)));
+ r.q.push(r.t/*title*/);
+
+ // child?
+ if (!r.b/*breadcrumb*/ || r.b/*breadcrumb*/.length <= path.length) {
+ tree.push(r);
+ continue;
+ }
+
+ // not child -> contained in a subtree
+ var key = r.b/*breadcrumb*/[path.length] + '\n' + r.b/*breadcrumb*/[path.length+1];
+ if (!grouped[key]) {
+ var node = {
+ isNode: true,
+ name: [r.b/*breadcrumb*/[path.length], r.b/*breadcrumb*/[path.length+1]],
+ l/*ocation*/: path.slice(),
+ children: [r]
+ };
+ grouped[key] = node;
+ tree.push(node);
+ } else {
+ grouped[key].children.push(r);
+ }
+
+ }
+
+ // calculate count and set the root (if it exists)
+ for (var i = 0; i < tree.length; i++) {
+ var r = tree[i];
+ if (r.isNode) {
+ r.count = r.children.length + (r.root ? 1 : 0);
+ continue;
+ }
+ var rootOfGroup = grouped[r.q[r.q.length-2] + '\n' + r.t/*title*/];
+ if (rootOfGroup) {
+ rootOfGroup.children.push(r);
+ rootOfGroup.count++;
+ tree.splice(i,1);
+ i--;
+ }
+ }
+
+ // compact and recursion
+ for (var i = 0; i < tree.length; i++) {
+ var r = tree[i];
+ if (!r.isNode) continue;
+ compact(path, r);
+ r.children = asTree(r.children, r.children[0].q.slice(0, path.length + r.name.length), depth - 1);
+ }
+
+ return tree;
+ }
+ function compact(path, r) {
+ for (var i = path.length+2; r.children.length > 0 && !r.root; i+=2) {
+ if (r.children.length == 1 && r.children[0].b/*breadcrumb*/.length == i) return;
+ for (var j = 0; j < r.children.length; j++) {
+ var p0 = r.children[0].q;
+ var p = r.children[j].q;
+ if ( p.length < i+1
+ || p[i] != p0[i]
+ || p[i+1] != p0[i+1]) return;
+ }
+ var p0 = r.children[0].q;
+ r.name.push(p0[i]);
+ r.name.push(p0[i+1]);
+ }
+ }
+
+ function queryToRegEx(query) {
+ query = query.indexOf('&') < 0
+ ? query
+ : query.substr(0, query.indexOf('&'));
+ query = decodeURIComponent(query.replace(/\+/g, '%20'));
+ query = query.replace(/([\.\?\*\+\-\(\)\[\]\{\}\\])/g, '\\$1');
+ return new RegExp("\\b(?:" + query + ")((?:\\w+|\\W+\\w+))", "i");
+ }
+
+ function searchSearchWord(searchWord, toc, href, path, isSearchWordDecoded) {
+ try {
+
+ // No SearchFrame or no NavFrame? -> exception handling
+ var root = parent.parent.parent;
+ var searchFrame = root.HelpToolbarFrame.SearchFrame;
+ var navFrame = root.HelpFrame.NavFrame;
+
+ var scopeElement = searchFrame.document.getElementById('scope');
+ var searchInput = searchFrame.document.getElementById('searchWord');
+ if ( searchInput
+ && scopeElement
+ && scopeElement.firstChild.nodeValue == 'All topics') {
+
+ // no scope -> update top left search input field only
+ searchInput.value = searchWord;
+
+ } else {
+
+ // disable scope and update top left search input field
+ searchFrame.location.replace( BASE_URL
+ + 'scopeState.jsp?workingSet=&searchWord='
+ + encodeURIComponent(searchWord));
+
+ }
+ var newNavUrl = BASE_URL
+ + 'advanced/nav.jsp?e=h&tab=search&searchWord=' // 'e=h' for tracking (to distinguish normal queries from queries done with this script)
+ + (isSearchWordDecoded ? searchWord : encodeURIComponent(searchWord));
+ if (toc) newNavUrl += '&quickSearch=true&quickSearchType=QuickSearchToc&toc=' + encodeURIComponent(toc);
+ if (path) newNavUrl += '&path=' + path;
+ navFrame.location.replace(newNavUrl);
+
+ // topic (use 'setTimeout()' otherwise in Internet Explorer
+ // 'Go Back' does not work sometimes)
+ if (href) {
+ setTimeout(function(){window.location.href = BASE_URL + 'topic' + href}, 9);
+ }
+
+ return true;
+ } catch(e) {
+ return false;
+ }
+ }
+
+ // filter tree functions
+ function selectSubtree(element, checkStatus) {
+ for (var i = 0; i < element.children.length; i++) {
+ var n = element.children[i];
+ if ('UL' == n.tagName || 'LI' == n.tagName || 'DIV' == n.tagName) {
+ selectSubtree(n, checkStatus);
+ } else if ('INPUT' == n.tagName) {
+ n.indeterminate = false;
+ n.checked = checkStatus;
+ n.notAllChecked = false;
+ }
+ }
+ }
+ function getChildrenChecks(checkbox) {
+ if (!checkbox || !checkbox.parentElement || !checkbox.parentElement.parentElement || 'LI' != checkbox.parentElement.parentElement.tagName) return [];
+ var li = checkbox.parentElement.parentElement;
+ var children = [];
+ for (var i = 0; i < li.children.length; i++) {
+ var n1 = li.children[i];
+ if ('UL' != n1.tagName) continue;
+ for (var j = 0; j < n1.children.length; j++) {
+ var n2 = n1.children[j];
+ if ('LI' != n2.tagName) continue;
+ for (var k = 0; k < n2.children.length; k++) {
+ var n3 = n2.children[k];
+ for (var l = 0; l < n3.children.length; l++) {
+ var n4 = n3.children[l];
+ if ('INPUT' == n4.tagName) children.push(n4);
+ }
+ }
+ }
+ }
+ return children;
+ }
+ function updateParentsChecks(checkbox) {
+ for (var parentCheckbox = checkbox.parentCheckbox; parentCheckbox; parentCheckbox = parentCheckbox.parentCheckbox) {
+ var checkedNumberOfResults = 0;
+ var uncheckedNumberOfResults = 0;
+ var uncheckedAll = true;
+ var notAllChecked = false;
+ var totalNumberOfResults = 0;
+ var indeterminateChildren = 0;
+ var children = getChildrenChecks(parentCheckbox);
+ for (var i = 0; i < children.length; i++) {
+ var n = children[i];
+ if (n.notAllChecked) notAllChecked = true;
+ if (n.indeterminate) {
+ indeterminateChildren++;
+ uncheckedAll = false;
+ notAllChecked = true;
+ } else if (n.checked) {
+ checkedNumberOfResults += n.numberOfResults;
+ totalNumberOfResults += n.numberOfResults;
+ uncheckedAll = false;
+ } else {
+ uncheckedNumberOfResults += n.numberOfResults;
+ totalNumberOfResults += n.numberOfResults;
+ notAllChecked = true;
+ }
+ }
+ if (checkedNumberOfResults == parentCheckbox.numberOfResults && !notAllChecked) {
+ parentCheckbox.indeterminate = false;
+ parentCheckbox.checked = true;
+ parentCheckbox.notAllChecked = false;
+ } else if ( uncheckedNumberOfResults == parentCheckbox.numberOfResults
+ || (parentCheckbox.indeterminate && uncheckedAll)) {
+ parentCheckbox.indeterminate = false;
+ parentCheckbox.checked = false;
+ } else if ( totalNumberOfResults == parentCheckbox.numberOfResults
+ || ( !parentCheckbox.indeterminate
+ && !parentCheckbox.checked
+ && (indeterminateChildren || checkedNumberOfResults || notAllChecked))){
+ parentCheckbox.indeterminate = true;
+ } else {
+ parentCheckbox.notAllChecked = notAllChecked;
+ }
+ }
+ }
+
+ function toMenu(master, items, data, chooseFn, applyFn, cancelFn, armFn) {
+ //var isNotInputField = master.nodeName != 'INPUT';
+ var cursorIndex = 0;
+ var isInit = 0;
+ master.onkeydown = function(e) {
+ e = e || window.event;
+ var key = e.keyCode || e.charCode;
+
+ if ( cursorIndex > 0
+ && getClassName(items[cursorIndex-1]) == items[cursorIndex-1].z) {
+ cursorIndex = 0;
+ }
+
+ // RIGHT (key: 39) or TAB without SHIFT (key: 9) to apply
+ if (applyFn && (key == 39 || (key == 9 && !e.shiftKey))) {
+ if (applyFn(data, key)) preventDefault(e);
+ }
+
+ // ESC to cancel
+ if (cancelFn && key == 27) {
+ cancelFn();
+ preventDefault(e);
+ return;
+ }
+
+ // ENTER to choose
+ if (key == 13 && cursorIndex > 0) {
+ preventDefault(e);
+ stopPropagation(e);
+ setClassName(items[cursorIndex-1], items[cursorIndex-1].z);
+ chooseFn(data[cursorIndex-1]);
+ cursorIndex = 0;
+ return;
+ }
+
+ // select by UP and DOWN
+ if (key != 40 && key != 38) return;
+ preventDefault(e);
+ var isDown = key == 40;
+ if (cursorIndex > 0) {
+ setClassName(items[cursorIndex-1], items[cursorIndex-1].z);
+ }
+ cursorIndex = cursorIndex < 1
+ ? (isDown ? 1 : items.length)
+ : (cursorIndex + (isDown ? 1 : -1)) % (items.length + 1);
+ if (cursorIndex > 0) {
+ var item = items[cursorIndex-1];
+ setClassName(item, item.z + ' z');
+ if (armFn) armFn(item, data[cursorIndex-1], 0);
+ }
+ }
+ for (var i = 0; i < items.length; i++) {
+ items[i].z = getClassName(items[i]);
+ items[i].onmousedown = function() {setTimeout(function() {if (master && !master.hasFocus) master.focus()}, 42)};
+ items[i].onmouseup = items[i].ontouchend = function(a, b) {return function(e) {preventDefault(e); if (!a.canceled) {chooseFn(b); setClassName(a, a.z); cursorIndex = 0}}}(items[i], data[i]);
+ items[i].onmouseover = items[i].ontouchstart = function(a, b, c) {return function() {if (!isInit) return; if (cursorIndex > 0) setClassName(items[cursorIndex-1], items[cursorIndex-1].z); setClassName(a, a.z + ' z'); cursorIndex = b; a.canceled = ''; if (armFn && b > 0) armFn(a, c, 1)}}(items[i], i+1, data[i]);
+ items[i].onmouseout = function(a) {return function() {setClassName(a, a.z)}}(items[i]);
+ }
+ setTimeout(function() {isInit = 1; }, 142);
+ }
+
+ function addHighlightedText(element, text, searchWord) {
+ var searchWordLowerCase = searchWord.toLowerCase();
+ var textLowerCase = text.toLowerCase();
+ var hIndex = textLowerCase.indexOf(searchWordLowerCase);
+ if (hIndex < 0) {
+ element.appendChild(document.createTextNode(text));
+ return;
+ }
+
+ var lastEnd = 0;
+ while (hIndex >=0) {
+ element.appendChild(document.createTextNode(text.substring(lastEnd, hIndex)));
+ lastEnd = hIndex + searchWord.length;
+ if ( hIndex == 0
+ || text.substring(hIndex - 1, hIndex).replace(/\w/, "").length != 0) {
+ var strong = createElement(element, 'strong');
+ strong.appendChild(document.createTextNode(text.substring(hIndex, lastEnd)));
+ } else {
+ element.appendChild(document.createTextNode(text.substring(hIndex, lastEnd)));
+ }
+ hIndex = textLowerCase.indexOf(searchWordLowerCase, lastEnd);
+ }
+ element.appendChild(document.createTextNode(text.substring(lastEnd)));
+ }
+
+ }
+
+ function searchFullByHash(hash) {
+ var url = SEARCH_BASE_URL + hash.substring(3) + '&maxHits=' + SEARCH_HITS_MAX
+ + (hash.indexOf('&toc=') < 0 ? '' : '&quickSearch=true&quickSearchType=QuickSearchToc');
+ window.frames.c.location = url;
+
+ // fill search field
+ var searchWord = getParams(hash)['#q'];
+ if (searchWord && searchWord != getElementById('q').value) {
+ getElementById('q').value = searchWord;
+ }
+
+ // TODO set search socpe?
+
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Menu
+
+ function createMenu() {
+
+ // menu
+ var menu = createOverlay(9, 1);
+ var overlay = createOverlay(8);
+ menu.id = 'a';
+ menuStyle = menu.style;
+ menu.a = function(e) { preventDefault(e); overlay.a(); menuStyle.width = '270px'; };
+ menu.o = function(e) { preventDefault(e); overlay.o(); menuStyle.width = '0'; };
+ menu.o();
+ addEvent(overlay, 'click', menu.o);
+ function createMenuItem(label, description, fn, id, href, parent) {
+ var item = createElement(parent ? parent : menu, fn ? 'button' : 'a', 'b', label);
+ item.href = href ? (BASE_URL + href) : '#';
+ item.target = 'c';
+ item.title = description;
+ if (id) {
+ item.id = id;
+ }
+ addEvent(item, 'click', function(e) {
+ if (fn) { preventDefault(e); fn(e); }
+ if (href) { getElementById('c').contentDocument.location.href = BASE_URL + href; }
+ if (!parent) menu.o();
+ });
+ return item;
+ }
+
+ // "x" button
+ var closeMenuButton = createElement(createElement(menu, 0, 'e'), 'a', 'b');
+ closeMenuButton.href = '#';
+ addEvent(closeMenuButton, 'click', menu.o);
+ closeMenuButton.alt = MENU_CLOSE_ICON_DESCRIPTION;
+ closeMenuButton.title = MENU_CLOSE_ICON_DESCRIPTION;
+ setInnerHtml(closeMenuButton, MENU_CLOSE_ICON);
+
+ // "Highlight search terms" dummy
+ function HighlightConnector() {};
+ HighlightConnector.prototype.setButtonState = function(/*name, state*/) {
+ // dummy for highlight() in org.eclipse.help.webapp/advanced/highlight.js
+ };
+ window.ContentToolbarFrame = new HighlightConnector();
+ var highlight = createMenuItem(0, 'Toggle search term highlighting', toggleHighlight, 'ah');
+ createElement(highlight, 'span', 'hl', 'Highlight');
+ createElement(highlight, 'span', 'hs', ' ');
+ createElement(highlight, 'span', 'ht', 'search term');
+ toggleHighlight(0, 1);
+
+ // "Font: - +"
+ if (MENU_FONT_SIZING) {
+ var fontSizer = createElement(menu);
+ fontSizer.id = 'af';
+ createElement(fontSizer, 'span', 0, 'Font:');
+ createMenuItem('\u2013', 'Decrease font size', function() { setFontSize(0); }, 'afm', 0, fontSizer);
+ createMenuItem('+', 'Increase font size', function() { setFontSize(1); }, 'afp', 0, fontSizer);
+ }
+
+ // "Bookmarks..."
+ if (embeddedMode) {
+ createMenuItem('Bookmarks...', 'Bookmark current topic and manage existing bookmarks', function() {
+ bookmarksPage.s(1);
+ });
+ }
+
+ // "Search scopes..."
+ createMenuItem('Search scopes...', 'Manage search scopes', function() {
+ scopesPage.s(1);
+ });
+
+ // "Print topic..."
+ createMenuItem('Print topic...', 'Print topic without its subtopics', function() {
+ try {
+ getElementById('c').contentWindow.print();
+ } catch (e) {
+ }
+ }, 'ap');
+
+ // "Print chapter..."
+ createMenuItem('Print chapter...', 'Print topic including subtopics', printChapter, 'app');
+
+ // "Help"
+ if (MENU_HELP) {
+ createMenuItem('Help', 'How to use help', 0, 'ai', 'topic/org.eclipse.help.base/doc/help_home.html');
+ }
+
+ // "About"
+ if (MENU_ABOUT) {
+ createMenuItem('About', 'Configuration details', 0, 'aa', 'about.html');
+ }
+
+ // show menu button
+ var menuButton = createElement(getElementById('h'), 'a', 'b');
+ menuButton.href = '#';
+ menuButton.alt = MENU_ICON_DESCRIPTION;
+ menuButton.title = MENU_ICON_DESCRIPTION;
+ setInnerHtml(menuButton, MENU_ICON);
+ addEvent(menuButton, 'click', menu.a);
+
+ }
+
+ function toggleHighlight(_event, initalize) {
+
+ var enableHighlighting = 'false' == getCookie('highlight');
+ if (initalize) {
+ enableHighlighting = !enableHighlighting;
+ } else {
+ setCookie('highlight', enableHighlighting ? 'true' : 'false');
+ var contentFrameWindow = getElementById('c').contentWindow;
+ if (contentFrameWindow && contentFrameWindow.highlight && contentFrameWindow.toggleHighlight) {
+ contentFrameWindow.toggleHighlight();
+ contentFrameWindow.highlight();
+ }
+ }
+ setClassName(getElementById('ah'), enableHighlighting ? 'b x' : 'b');
+ }
+
+ function setFontSize(increase, initalize, updateContentFrameOnly) {
+ if (!MENU_FONT_SIZING) return;
+ var newFontSize;
+ var contentFrameDocument = getElementById('c').contentWindow.document;
+ var contentFrameDocumentElement = contentFrameDocument.documentElement || contentFrameDocument.body;
+ var toc = document.getElementById('t');
+ var tocStyle = getComputedStyle(toc, null).getPropertyValue('font-size');
+ var tocFontSize = parseFloat(tocStyle);
+ if (initalize) {
+ newFontSize = getCookie('font-size');
+ } else if (increase && !initalize && tocFontSize < 64) {
+ newFontSize = (tocFontSize + 3);
+ } else if (!increase && !initalize && tocFontSize > 12) {
+ newFontSize = (tocFontSize - 3);
+ }
+ if (!newFontSize) return;
+ contentFrameDocumentElement.style.fontSize = newFontSize + 'px';
+ if (!updateContentFrameOnly) {
+ toc.style.fontSize = newFontSize + 'px';
+ searchPage.style.fontSize = newFontSize + 'px';
+ }
+ setCookie('font-size', newFontSize, 365);
+ }
+
+ function printChapter() {
+ var contentElement = getElementById('c');
+ var contentWindow = contentElement.contentWindow;
+ var topicHref = contentWindow.location.href;
+ if (!topicHref) return;
+ var dummy = document.createElement('a');
+ dummy.href = BASE_URL + 'x';
+ var topic = topicHref.substring(dummy.href.length - 2);
+ if (topic.length > 7 && '/topic/' == topic.substring(0, 7)) topic = topic.substring(6);
+ else if (topic.length > 5 && '/nav/' == topic.substring(0, 5)) topic = '/..' + topic;
+ else if (topic.length > 8 && ('/rtopic/' == topic.substring(0, 8) || '/ntopic/' == topic.substring(0, 8))) topic = topic.substring(7);
+ var w = contentWindow.innerWidth || contentWindow.document.body.clientWidth;
+ var h = contentWindow.innerHeight || contentWindow.document.body.clientHeight;
+ var x = window.screenX;
+ var y = window.screenY;
+ for (var e = contentElement; !!e; e = e.offsetParent) {
+ if (e.tagName == "BODY") {
+ var xScroll = e.scrollLeft || document.documentElement.scrollLeft;
+ var yScroll = e.scrollTop || document.documentElement.scrollTop;
+ x += (e.offsetLeft - xScroll + e.clientLeft);
+ y += (e.offsetTop - yScroll + e.clientTop);
+ } else {
+ x += (e.offsetLeft - e.scrollLeft + e.clientLeft);
+ y += (e.offsetTop - e.scrollTop + e.clientTop);
+ }
+ }
+ var anchor = '';
+ var anchorStart = topic.indexOf('#');
+ if (anchorStart > 0) {
+ anchor = '&anchor=' + topic.substr(anchorStart + 1);
+ topic = topic.substr(0, anchorStart);
+ }
+ var query = '';
+ var queryStart = topic.indexOf('?');
+ if (queryStart > 0) {
+ query = '&' + topic.substr(queryStart + 1);
+ topic = topic.substr(0, queryStart);
+ }
+ window.open(BASE_URL + 'advanced/print.jsp?topic=' + topic + query + anchor, 'printWindow', 'directories=yes,location=no,menubar=yes,resizable=yes,scrollbars=yes,status=yes,titlebar=yes,toolbar=yes,width=' + w + ',height=' + h + ',left=' + x + ',top=' + y);
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Tree
+
+ function createTree(element, contentProvider, labelProvider, selectable) {
+ var root = createElement(element, 0, 'tree');
+ function createNode(parent, node) {
+ contentProvider(node, createNodeChildrenFn(parent, node));
+ };
+ function createNodeChildrenFn(parent) {
+ return function(children, open) {
+ var ul = createElement(parent, 'ul');
+ for (var i = 0; i < children.length; i++) {
+ var li = createElement(ul, 'li', 'closed');
+ li.p = parent;
+ var child = children[i];
+ if (!child.l) {
+
+ // c(hildren): yes
+ li.c = 1;
+
+ // i(nit) function to load children
+ li.i = (function(li, node) {
+ return function() {
+ createNode(li, node);
+ li.i = 0;
+ };
+ })(li, child.n);
+
+ // handle (to toggle subtree)
+ var handle = createElement(li, 'span', 'h');
+ handle.innerHTML = TREE_HANDLE;
+ addEvent(handle, 'click', (function(li) {
+ return function(e) {
+ toggleLi(li);
+ stopPropagation(e);
+
+ // focus next element (to avoid losing focus since the handle cannot be focused)
+ try {
+ li.childNodes[1].focus();
+ } catch(e) {}
+
+ };
+ })(li));
+
+ }
+ var label = labelProvider(li, child.n);
+ setClassName(label, 'l');
+ if (selectable) {
+ addEvent(label, 'click', (function(li) {
+ return function(e) {
+ if (element.s === li) return;
+ element.x(li);
+ stopPropagation(e);
+ };
+ })(li));
+ }
+ addEvent(label, 'dblclick', (function(li) {
+ return function(e) {
+ toggleLi(li);
+ stopPropagation(e);
+ }
+ })(li));
+ if (open || getClassName(li) == 'open') toggleLi(li);
+ }
+ }
+ };
+ element.x = function(li, scrollArea, closeSiblings) {
+ for (var n = element.s; isLi(n); n = n.p) {
+ n.xx = 0;
+ n.x = 0;
+ updateLiClasses(n);
+ }
+ element.s = li;
+ if (!li) return;
+ li.xx = 1;
+ updateLiClasses(li);
+ for (var n = li.p; isLi(n); n = n.p) {
+ if (!n.o) {
+ toggleLi(n);
+ }
+ n.x = 1;
+ updateLiClasses(n);
+ }
+
+ // close siblings of the selected node and its ancestors
+ for (var current = li; closeSiblings && current.tagName == 'LI'; current = current.p) {
+ var ul = getParentElement(current);
+ for (var i = 0; i < ul.childNodes.length; i++) {
+ var n = ul.childNodes[i];
+ if (current !== n && n.o) {
+ toggleLi(n);
+ }
+ }
+ }
+
+ // scroll label into view if needed
+ for (var i = 0; i < li.childNodes.length; i++) {
+ var n = li.childNodes[i];
+ if (n.tagName == 'A' || n.tagName == 'BUTTON') {
+ scrollIntoViewIfNeeded(scrollArea, n);
+ break;
+ }
+ }
+
+ // update search field book scope
+ if (updateScopeByToc && li.toc) {
+ updateScopeByToc(li);
+ }
+
+ };
+ element.y = function(href, scrollArea, closeSiblings) {
+ contentProvider({topic: href}, function(children) {
+ if (!children || children.length != 1 || !children[0].n || !children[0].n.y) {
+
+ // deselect current selection
+ element.x(0);
+
+ return;
+ }
+ var expandPath = children[0].n.y.split('_');
+ var parentLi = root;
+ var parentNode = {};
+ var childNodes = children;
+ for (var i = 0; i < expandPath.length; i++) {
+ var nr = parseInt(expandPath[i]);
+ if (parentLi.i) {
+ (createNodeChildrenFn(parentLi, parentNode))(childNodes);
+ parentLi.i = 0;
+ }
+ var ul = 0;
+ for (var j = 0; j < parentLi.childNodes.length; j++) {
+ var n = parentLi.childNodes[j];
+ if (n.tagName == 'UL') {
+ ul = n;
+ break;
+ }
+ }
+ var li = 0;
+ var liNr = 0;
+ for (var j = 0; j < ul.childNodes.length; j++) {
+ var n = ul.childNodes[j];
+ if (n.tagName == 'LI') {
+ if (liNr == nr) {
+ li = n;
+ break;
+ }
+ liNr++;
+ }
+ }
+ if (i == expandPath.length - 1) {
+ element.x(li, scrollArea, closeSiblings);
+ }
+ parentLi = li;
+ var child = childNodes[i == 0 ? 0 : nr];
+ parentNode = child.n;
+ childNodes = child.c;
+ }
+ });
+ }
+ createNode(root);
+
+ // handling via the keys up, down, left, right, home and end
+ addEvent(element, 'keydown', function(e) {
+ var keyCode = e.keyCode || window.event.keyCode;
+ if (keyCode < 35 || keyCode > 40) return;
+
+ // compute focused tree node
+ var li;
+ for (li = e.target || e.srcElement; li && li !== root; ) {
+ if (isLi(li)) break;
+ li = getParentElement(li);
+ }
+ if (!li) return;
+
+ // left/right
+ if (keyCode == 37 || keyCode == 39) {
+ if (keyCode == 37 ^ !li.o) {
+ toggleLi(li);
+ } else if (keyCode == 37) {
+ focusTreeNode(li.p);
+ } else {
+ focusFirstChildNode(li);
+ }
+
+ // down
+ } else if(keyCode == 40) {
+
+ // expanded? -> focus first child, ...
+ if (li.o) {
+ focusFirstChildNode(li);
+ preventDefault(e);
+ return;
+ }
+
+ // ...otherwise -> focus next sibling at this or higher level
+ for (var level = li; isLi(level); level = level.p) {
+ for (var next = getNextSibling(level); next; next = getNextSibling(next)) {
+ if (!isLi(next)) continue;
+ focusTreeNode(next);
+ preventDefault(e);
+ return;
+ }
+ }
+
+ // up
+ } else if(keyCode == 38) {
+
+ // previous sibling? -> focus previous sibling, ...
+ for (var prev = getPreviousSibling(li); prev !== null; prev = getPreviousSibling(prev)) {
+ if (!isLi(prev)) continue;
+ focusDeepestVisibleChild(prev);
+ preventDefault(e);
+ return;
+ }
+
+ // ...otherwise -> focus parent
+ focusTreeNode(li.p);
+
+ // home
+ } else if(keyCode == 36) {
+ focusFirstChildNode(root);
+
+ // end
+ } else if(keyCode == 35) {
+ focusDeepestVisibleChild(root);
+
+ }
+ preventDefault(e);
+
+ });
+ element.f = function() {
+ focusTreeNode(element.s);
+ };
+ if (selectable) {
+ addEvent(element, 'click', element.f);
+ }
+
+ // visitor pattern: visit the nearby nodes first (first the selected node with its subtree deep-first, then the
+ // parent, then the siblings with their subtrees and repeating for each higher level with the parent (if any)
+ // and the siblings, without the already processed node and its subtree)
+ element.v = function(vistorFn) {
+ var todoSiblingsAndAncestorsOf = element.s;
+ var todoSubtrees = element.s ? [element.s] : toArray(root.childNodes[0].childNodes);
+ while (todoSubtrees.length || todoSiblingsAndAncestorsOf) {
+ var next;
+
+ // subtree done? -> go one level up
+ if (!todoSubtrees.length) {
+ var sibling = todoSiblingsAndAncestorsOf;
+ while (sibling = getNextSibling(sibling)) {
+ todoSubtrees.unshift(sibling);
+ }
+ sibling = todoSiblingsAndAncestorsOf;
+ while (sibling = getPreviousSibling(sibling)) {
+ todoSubtrees.unshift(sibling);
+ }
+ if (todoSiblingsAndAncestorsOf.p && todoSiblingsAndAncestorsOf.p.tagName == 'LI') {
+ next = todoSiblingsAndAncestorsOf = todoSiblingsAndAncestorsOf.p;
+ } else {
+ todoSiblingsAndAncestorsOf = 0;
+ continue;
+ }
+ } else {
+ next = todoSubtrees.pop();
+
+ // add children of next (if any)
+ for (var i = 0; i < next.childNodes.length; i++) {
+ var n = next.childNodes[i];
+ if (n.tagName != 'UL') continue;
+ for (var j = n.childNodes.length - 1; j >= 0; j--) {
+ var m = n.childNodes[j];
+ if (isLi(m)) {
+ todoSubtrees.push(m);
+ }
+ }
+ }
+
+ }
+
+ // call visitor
+ if (!vistorFn(next)) return;
+
+ }
+
+ }
+ function toArray(nodeList) {
+ var result = [];
+ for (var i = 0; i < nodeList.length; i++) {
+ result.push(nodeList[i]);
+ }
+ return result;
+ }
+
+ function toggleLi(li) {
+ if (!li.c) return;
+ if (li.i) {
+ li.i();
+ }
+ li.o = !li.o;
+ updateLiClasses(li);
+ }
+ function isLi(element) {
+ return element && element.tagName == 'LI'
+ }
+ function updateLiClasses(li) {
+ setClassName(li, (li.o ? 'open': 'closed') + (li.xx ? ' xx' : '') + (li.x ? ' x' : ''))
+ }
+ function focusFirstChildNode(li) {
+ for (var i = 0; i < li.childNodes.length; i++) {
+ var n = li.childNodes[i];
+ if (n.tagName != 'UL') continue;
+ for (var j = 0; j < n.childNodes.length; j++) {
+ var m = n.childNodes[j];
+ if (isLi(m)) {
+ focusTreeNode(m);
+ return;
+ }
+ }
+ }
+ }
+ function focusDeepestVisibleChild(li) {
+ for (var i = 0; li.o && i < li.childNodes.length; i++) {
+ var n = li.childNodes[i];
+ if (n.tagName != 'UL') continue;
+ for (var j = n.childNodes.length - 1; j >= 0; j--) {
+ var m = n.childNodes[j];
+ if (!isLi(m)) continue;
+ focusDeepestVisibleChild(m);
+ return;
+ }
+ }
+ focusTreeNode(li);
+ }
+ function focusTreeNode(li) {
+ if (!li) return;
+ for (var i = 0; i < li.childNodes.length; i++) {
+ var n = li.childNodes[i];
+ if (n.tagName != 'A' && n.tagName != 'BUTTON') continue;
+ try {
+ n.focus();
+ } catch(e) {}
+ return;
+ }
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Overlay
+
+ function createOverlay(zIndex, withoutStyles) {
+ var overlay = createElement();
+ var header = getElementById('h');
+ getParentElement(header).insertBefore(overlay, header);
+ if (!withoutStyles) {
+ var overlayStyle = overlay.style;
+ overlayStyle.display = 'none';
+ overlayStyle.zIndex = zIndex ? zIndex : 1;
+ overlayStyle.position = 'absolute';
+ overlayStyle.height = '100%';
+ overlayStyle.width = '100%';
+ }
+ overlay.a = function() { overlayStyle.display = 'block'; };
+ overlay.o = function() { overlayStyle.display = 'none'; };
+ return overlay;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Utility functions (polyfill/retrofit functions see below)
+
+ function addEvent(element, type, fn) {
+ if (element.addEventListener) {
+ element.addEventListener(type, fn, false);
+ } else if (element.attachEvent) {
+ element['e' + type + fn] = fn;
+ element[type + fn] = function() {
+ element['e' + type + fn](window.event);
+ }
+ element.attachEvent('on' + type, element[type + fn]);
+ }
+ }
+
+ function decodeHtml(htmlString) {
+ if (!htmlString) return htmlString;
+ var element = createElement();
+ setInnerHtml(element, htmlString);
+ return element.textContent || element.innerText;
+ }
+
+ function getElementById(id) {
+ return document.getElementById(id);
+ }
+
+ function getParentElement(element) {
+ return element.parentElement;
+ }
+
+ function getPreviousSibling(element) {
+ return element.previousSibling;
+ }
+
+ function getNextSibling(element) {
+ return element.nextSibling;
+ }
+
+ function getClassName(element) {
+ return element.className;
+ }
+
+ function setClassName(element, value) {
+ element.className = value;
+ return element;
+ }
+
+ function getAttribute(element, attribute) {
+ return element.getAttribute(attribute);
+ }
+
+ function setAttribute(element, attribute, value) {
+ element.setAttribute(attribute, value);
+ return element;
+ }
+
+ function setInnerHtml(element, innerHtml) {
+ element.innerHTML = innerHtml ? innerHtml : '';
+ }
+
+ function preventDefault(e) {
+ e = e || window.event;
+ if (!e) return;
+ try {
+ if (e.preventDefault) e.preventDefault();
+ e.returnValue = false;
+ } catch(e) {}
+ }
+
+ function stopPropagation(e) {
+ e = e || window.event;
+ if (!e) return;
+ e.cancelBubble = true;
+ if (e.stopPropagation) e.stopPropagation();
+ }
+
+ function getParams(queryPart) {
+ var params = {};
+ queryPart.replace(/(?:^|&+)([^=&]+)=([^&]*)/gi,
+ function(_match, group1Param, group2Value) { params[group1Param] = decodeURIComponent(group2Value); });
+ return params;
+ }
+
+ function getCookie(cookieName, defaultValue) {
+ var name = cookieName + "=";
+ var decodedCookie = decodeURIComponent(document.cookie);
+ var allCookies = decodedCookie.split(';');
+ for (var i = 0; i < allCookies.length; i++) {
+ var cookie = allCookies[i];
+ while (cookie.charAt(0) == ' ') {
+ cookie = cookie.substring(1);
+ }
+ if (cookie.indexOf(name) == 0) {
+ return cookie.substring(name.length, cookie.length);
+ }
+ }
+ return defaultValue;
+ }
+
+ function setCookie(cookieName, value) {
+ var d = new Date();
+ d.setTime(d.getTime() + (365 * 24 * 60 * 60 * 1000));
+ var expires = 'expires=' + d.toUTCString();
+ document.cookie = cookieName + '=' + value + ';' + expires + ';path=/;samesite=strict';
+ }
+
+ var openRequests = {};
+ function remoteRequest(url, callbackFn, cancelId) {
+ var request = new XMLHttpRequest();
+ if (callbackFn) request.onreadystatechange = function() {
+ if (request.readyState == 4 && request.status == 200) callbackFn(request.responseText);
+ }
+ request.open('GET', url);
+ request.send();
+ if (cancelId) {
+ if (openRequests[cancelId] && openRequests[cancelId].abort) openRequests[cancelId].abort();
+ openRequests[cancelId] = request;
+ }
+ }
+
+ var parseXml;
+ if (typeof window.DOMParser != 'undefined') {
+ parseXml = function(xmlStr) {
+ return (new window.DOMParser()).parseFromString(xmlStr, 'text/xml');
+ };
+ } else if ( typeof window.ActiveXObject != 'undefined'
+ && new window.ActiveXObject('Microsoft.XMLDOM')) {
+ parseXml = function(xmlStr) {
+ var xmlDoc = new window.ActiveXObject('Microsoft.XMLDOM');
+ xmlDoc.async = 'false';
+ xmlDoc.loadXML(xmlStr);
+ return xmlDoc;
+ };
+ }
+
+ function scrollIntoViewIfNeeded(scrollArea, element) {
+ if (!scrollArea) return;
+ try {
+ var scrollAreaBoundaries = scrollArea.getBoundingClientRect();
+ var elementBoundaries = element.getBoundingClientRect();
+ if ( elementBoundaries.top >= scrollAreaBoundaries.top
+ && elementBoundaries.bottom <= scrollAreaBoundaries.bottom) return;
+
+ scrollArea.scrollTop += scrollArea.c
+
+ // show element in upper third
+ ? (( (elementBoundaries.bottom - scrollAreaBoundaries.bottom)
+ + (elementBoundaries.top - scrollAreaBoundaries.top) * 2) / 3)
+
+ // scroll as less as possible
+ : (elementBoundaries.bottom <= scrollAreaBoundaries.bottom
+ ? elementBoundaries.top - scrollAreaBoundaries.top
+ : elementBoundaries.bottom - scrollAreaBoundaries.bottom);
+
+ } catch (e) {}
+ }
+
+ function arrayContainsPrefix(array, value) {
+ for (var i = 0; i < array.length; i++) {
+ if (array[i].length <= value.length && value.substring(0, array[i].length) == array[i]) return true;
+ }
+ return false;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Polyfill/retrofit utility functions
+
+ function createElement(parent, name, className, text) {
+ var element = document.createElement(name ? name : 'div');
+ if (parent) {
+ try {
+ parent.appendChild(element);
+ } catch(e) {
+
+ // POLYFILL IE<=8
+ // HTML5 semantic tags (https://www.w3schools.com/html/html5_browsers.asp)
+ // polyfill adding child element to the empty HTML 5 semantic element 'aside' (for IE 8 and lower)
+ if (parent.tagName == 'ASIDE') {
+ var pp = parent.parentElement;
+ var rest = [];
+ for (var i = 0; i < pp.childNodes.length; i++) {
+ if (parent === pp.childNodes[i]) {
+ if (div) continue;
+ var div = document.createElement('div');
+ for (var j = 0; j < parent.attributes.length; j++) {
+ var attribute = parent.attributes[j];
+ if ('' + parent.getAttribute(attribute.name) != '' + div.getAttribute(attribute.name)
+ && !('' + parent.getAttribute(attribute.name) == 'null'
+ && '' + div.getAttribute(attribute.name) == '')) {
+ setAttribute(div, attribute.name, attribute.value);
+ }
+ }
+ pp.removeChild(parent);
+ div.appendChild(element);
+ rest.push(div);
+ i--;
+ continue;
+ }
+ if (rest && pp.childNodes[i].tagName == '/' + parent.tagName) {
+ pp.removeChild(pp.childNodes[i]);
+ i--;
+ continue;
+ }
+ if (!rest) continue;
+ rest.push(pp.removeChild(pp.childNodes[i]));
+ i--;
+ }
+ for (var i = 0; i < rest.length; i++) pp.appendChild(rest[i]);
+ } else throw e;
+
+ }
+ }
+ if (className) {
+ setClassName(element, className);
+ }
+ if (text) {
+ element.appendChild(document.createTextNode(text));
+ }
+ return element;
+ }
+
+}(window, document));
diff --git a/org.eclipse.help.webapp/plugin.xml b/org.eclipse.help.webapp/plugin.xml
index 6935a878d..3ff916510 100644
--- a/org.eclipse.help.webapp/plugin.xml
+++ b/org.eclipse.help.webapp/plugin.xml
@@ -36,6 +36,11 @@
base-name="/advanced"
httpcontextId="help">
</resource>
+ <resource
+ alias="/m"
+ base-name="/m"
+ httpcontextId="help">
+ </resource>
<serviceSelector
filter="(other.info=org.eclipse.help)">
</serviceSelector>

Back to the top