Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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