1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// Pagination and bookmark search
var url = window.location.pathname;
var moduleRegex = new RegExp('text\\/(\\w+)\\/');
var regexArray = moduleRegex.exec(url);
var userModule = currentModule();
var modules = ['CALC', 'WRITER', 'IMPRESS', 'DRAW', 'BASE', 'MATH', 'CHART', 'BASIC', 'SHARED'];
var indexEl = document.getElementsByClassName("index")[0];
var fullLinks = fullLinkify(indexEl, bookmarks, modules, userModule);
var search = document.getElementById('search-bar');
search.addEventListener('keyup', debounce(filter, 100, indexEl));
var flexIndex = new FlexSearch.Document({ document: {
// Only the text content gets indexed, the others get stored as-is
index: [{
field: 'text',
tokenize: 'full'
}],
store: ['url','app','text']
}
});
// Populate FlexSearch index
loadSearch();
// Render the unfiltered index list on page load
fillIndex(indexEl, fullLinks, modules);
// Preserve search input value during the session
search.value = sessionStorage.getItem('searchsave');
if (search.value !== undefined) {
filter(indexEl);
}
window.addEventListener('unload', function(event) {
sessionStorage.setItem('searchsave', search.value);
});
function getQuery(q) {
var pattern = new RegExp('[?&]' + q + '=([^&]+)');
var param = window.location.search.match(pattern);
if (param) {
return param[1];
}
return null;
}
function currentModule() {
// We need to know the module that the user is using when they call for help
let module = getQuery('DbPAR');
let moduleFromURL = regexArray[1].toUpperCase();
if (module == null) {
// first deal with snowflake Base
if(url.indexOf('/sdatabase/') !== -1) {
module = 'BASE';
} else {
if (null === regexArray || moduleFromURL === 'SHARED') {
// comes from search or elsewhere, no defined module in URL
module = 'SHARED'
} else {
// drop the 's' from the start
module = moduleFromURL.substring(1);
}
}
}
return module;
};
function fullLinkify(indexEl, bookmarks, modules, currentModule) {
var fullLinkified = '';
// if user is not on a shared category page, limit the index to the current module + shared
if(currentModule !== 'SHARED') {
bookmarks = bookmarks.filter(function(obj) {
return obj['app'] === currentModule || obj['app'] === 'SHARED';
});
}
bookmarks.forEach(function(obj) {
fullLinkified += '<a href="' + obj['url'] + '" class="' + obj['app'] + '" dir="auto">' + obj['text'] + '</a>';
});
return fullLinkified;
}
function loadSearch() {
bookmarks.forEach((el, i) => {
flexIndex.add(i, el);
});
}
function fillIndex(indexEl, content, modules) {
indexEl.innerHTML = content;
var indexKids = indexEl.children;
for (var i = 0, len = indexKids.length; i < len; i++) {
indexKids[i].removeAttribute("id");
}
modules.forEach(function(module) {
var moduleHeader = indexEl.getElementsByClassName(module)[0];
if (typeof moduleHeader !== 'undefined') {
// let's wrap the header in a span, so the ::before element will not become a link
moduleHeader.outerHTML = '<span id="' + module + '" class="' + module + '">' + moduleHeader.outerHTML + '</span>';
}
});
Paginator(indexEl);
}
// filter the index list based on search field input
function filter(indexList) {
let group = [];
let target = search.value.trim();
let filtered = '';
if (target.length < 1) {
fillIndex(indexEl, fullLinks, modules);
return;
}
// Regex for highlighting the match
let regex = new RegExp(target.split(/\s+/).filter((i) => i?.length).join("|"), 'gi');
let results = flexIndex.search(target, { pluck: "text", enrich: true, limit: 1000 });
// Similarly to fullLinkify(), limit search results to the user's current module + shared
// unless they're somehow not coming from a module.
if(userModule !== 'SHARED') {
resultModules = [userModule, 'SHARED'];
} else {
resultModules = modules;
}
// tdf#123506 - Group the filtered list into module groups, keeping the ordering
modules.forEach(function(module) {
group[module] = '';
});
results.forEach(function(result) {
group[result.doc.app] += '<a href="' + result.doc.url + '" class="' + result.doc.app + '">' + result.doc.text.replace(regex, (match) => `<strong>${match}</strong>`) + '</a>';
});
resultModules.forEach(function(module) {
if (group[module].length > 0) {
filtered += group[module];
}
});
fillIndex(indexList, filtered, modules);
};
// delay the rendering of the filtered results while user is typing
function debounce(fn, wait, indexList) {
var timeout;
return function() {
clearTimeout(timeout);
timeout = setTimeout(function() {
fn.call(this, indexList);
}, (wait || 150));
};
}
// copy pycode, sqlcode and bascode to clipboard on mouse click
// Show border when copy is done
divcopyable(document.getElementsByClassName("bascode"));
divcopyable(document.getElementsByClassName("pycode"));
divcopyable(document.getElementsByClassName("sqlcode"));
function divcopyable(itemcopyable){
for (var i = 0, len = itemcopyable.length; i < len; i++) {
(function() {
var item = itemcopyable[i];
function changeBorder(item, color) {
var saveBorder = item.style.border;
item.style.borderColor = color;
setTimeout(function() {
item.style.border = saveBorder;
}, 150);
}
item.onclick = function() {
document.execCommand("copy");
changeBorder(item, "#18A303");
};
item.addEventListener("copy", function(event) {
event.preventDefault();
if (event.clipboardData) {
event.clipboardData.setData("text/plain", item.textContent);
}
});
}());
}
}
// copy useful content to clipboard on mouse click
var copyable = document.getElementsByClassName("input");
for (var i = 0, len = copyable.length; i < len; i++) {
(function() {
var item = copyable[i];
function changeColor(item, color, colorToChangeBackTo) {
item.style.backgroundColor = color;
setTimeout(function() {
item.style.backgroundColor = colorToChangeBackTo;
}, 150);
}
item.onclick = function() {
document.execCommand("copy");
changeColor(item, "#18A303", "transparent");
};
item.addEventListener("copy", function(event) {
event.preventDefault();
if (event.clipboardData) {
event.clipboardData.setData("text/plain", item.textContent);
}
});
}());
}
// auto-expand contents per subitem
var pathname = window.location.pathname;
var pathRegex = /text\/.*\.html$/;
var linkIndex = 0;
var contentMatch = pathname.match(pathRegex);
function linksMatch(content) {
var linkMatch = new RegExp(content);
var links = document.getElementById("Contents").getElementsByTagName("a");
for (var i = 0, len = links.length; i < len; i++) {
if (links[i].href.match(linkMatch)) {
return i;
}
}
}
linkIndex = linksMatch(contentMatch);
if (typeof linkIndex !== "undefined") {
var current = document.getElementById("Contents").getElementsByTagName("a")[linkIndex];
var cItem = current.parentElement;
var parents = [];
while (cItem.parentElement && !cItem.parentElement.matches("#Contents") && parents.indexOf(cItem.parentElement) == -1) {
parents.push(cItem = cItem.parentElement);
}
var liParents = [].filter.call(parents, function(item) {
return item.matches("li");
});
for (var i = 0, len = liParents.length; i < len; i++) {
var input = liParents[i].querySelectorAll(':scope > input');
document.getElementById(input[0].id).checked = true;
}
current.classList.add('contents-current');
}
// close navigation menus when clicking anywhere on the page
// (ignoring menu button clicks and mobile browsing)
document.addEventListener('click', function(event) {
let a11yButton = event.target.getAttribute("data-a11y-toggle");
let vw = Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0);
if (!a11yButton && vw >= 960) {
document.querySelectorAll("[data-a11y-toggle] + nav").forEach((el) => {
el.setAttribute("aria-hidden", true);
});
}
});
// YouTube consent click. This only works for a single video.
let youtubePlaceholder = document.querySelector(".youtube_placeholder");
if (youtubePlaceholder) {
youtubePlaceholder.prepend(...document.querySelectorAll(".youtube_consent"));
}
function youtubeLoader(ytId, width, height) {
let iframeMarkup = `<iframe width="${width}" height="${height}" src="https://www.youtube-nocookie.com/embed/${ytId}?version=3" allowfullscreen="true" frameborder="0"></iframe>`;
let placeholder = document.getElementById(ytId);
placeholder.innerHTML = iframeMarkup;
placeholder.removeAttribute("style");
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
|