Merge pull request #11287 from MoonE/examples-search2

Examples index page fixes
This commit is contained in:
Andreas Hocevar
2020-07-18 09:33:36 +02:00
committed by GitHub
10 changed files with 134 additions and 145 deletions

View File

@@ -6,6 +6,6 @@ docs: >
This example shows how to use a dynamic ArcGIS REST MapService.
This source type supports Map and Image Services. For dyamic ArcGIS
services.
tags: arcgis, image, dynamiclayer"
tags: "arcgis, image, dynamiclayer"
---
<div id="map" class="map"></div>

View File

@@ -7,6 +7,6 @@ docs: >
This source type supports Map and Image Services. For cached ArcGIS
services, better performance is available by using
<code>ol/source/XYZ</code> instead.
tags: arcgis, tile, tilelayer"
tags: "arcgis, tile, tilelayer"
---
<div id="map" class="map"></div>

View File

@@ -6,7 +6,7 @@ docs: >
<p>When the Bing Maps tile service doesn't have tiles for a given resolution and region it returns "placeholder" tiles indicating that. Zoom the map beyond level 19 to see the "placeholder" tiles. If you want OpenLayers to display stretched tiles in place of "placeholder" tiles beyond zoom level 19 then set <code>maxZoom</code> to <code>19</code> in the options passed to <code>ol/source/BingMaps</code>.</p>
tags: "bing, bing-maps"
cloak:
- key: ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp
- key: ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
---
<div id="map" class="map"></div>

View File

@@ -18,8 +18,7 @@ for (i = 0, ii = styles.length; i < ii; ++i) {
visible: false,
preload: Infinity,
source: new BingMaps({
key:
'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp',
imagerySet: styles[i],
// use maxZoom 19 to see stretched tiles instead of the BingMaps
// "no photos at this zoom level" tiles

View File

@@ -70,128 +70,8 @@
}
</style>
<script type="text/javascript" src="Jugl.js"></script>
<script type="text/javascript" src="examples-info.js"></script>
<script type="text/javascript" src="index.js"></script>
<script type="text/javascript">
var template, target;
function listExamples(examples) {
target.innerHTML = "";
var node = template.process({
context: {examples: examples},
clone: true,
parent: target
});
document.getElementById("count").innerHTML = "(" + examples.length + ")";
}
var timerId;
function inputChange() {
if (timerId) {
window.clearTimeout(timerId);
}
var text = this.value;
timerId = window.setTimeout(function() {
filterList(text);
}, 500);
}
function filterList(text) {
var examples;
if (text.length < 2) {
examples = info.examples;
} else {
var words = text.split(/\W+/);
var scores = {};
for(var i=0; i<words.length; ++i) {
var word = words[i].toLowerCase();
var dict = info.index[word];
var updateScores = function() {
for(exIndex in dict) {
var count = dict[exIndex];
if(scores[exIndex]) {
if(scores[exIndex][word]) {
scores[exIndex][word] += count;
} else {
scores[exIndex][word] = count;
}
} else {
scores[exIndex] = {};
scores[exIndex][word] = count;
}
}
};
if (dict) {
updateScores();
} else {
var r;
for (idx in info.index) {
r = new RegExp(word);
if (r.test(idx)) {
dict = info.index[idx];
updateScores();
}
}
}
}
examples = [];
for (var j in scores) {
var ex = info.examples[j];
ex.score = scores[j];
examples.push(ex);
}
// sort examples by first by number of words matched, then
// by word frequency
examples.sort(function(a, b) {
var cmp;
var aWords = 0, bWords = 0;
var aScore = 0, bScore = 0;
for (var i in a.score) {
aScore += a.score[i];
aWords += 1;
}
for (var j in b.score) {
bScore += b.score[j];
bWords += 1;
}
if (aWords == bWords) {
cmp = bScore - aScore;
} else {
cmp = bWords - aWords;
}
return cmp;
});
}
listExamples(examples);
}
function parseQuery() {
var params = {};
var list = window.location.search.substring(1).split("&");
for (var i = 0; i < list.length; ++i) {
var pair = list[i].split("=");
if (pair.length == 2) {
params[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
}
if (params["q"]) {
var input = document.getElementById("keywords");
input.value = params["q"];
inputChange.call(input);
}
}
window.onload = function() {
for (var i = 0; i < info.examples.length; ++i) {
info.examples[i].link += window.location.search;
}
template = new jugl.Template("template");
target = document.getElementById("examples");
listExamples(info.examples);
document.getElementById("keywords").onkeyup = inputChange;
parseQuery();
};
</script>
<title>OpenLayers Examples</title>
</head>

113
examples/index.js Normal file
View File

@@ -0,0 +1,113 @@
(function () {
'use strict';
/* global info, jugl */
let template, target;
function listExamples(examples) {
target.innerHTML = '';
template.process({
context: {examples: examples},
clone: true,
parent: target,
});
document.getElementById('count').innerHTML = '(' + examples.length + ')';
}
let timerId;
function inputChange() {
if (timerId) {
window.clearTimeout(timerId);
}
const text = this.value;
timerId = window.setTimeout(function () {
filterList(text);
}, 500);
}
function getMatchingExamples(text) {
text = text.trim();
if (text.length === 0) {
return info.examples;
}
const words = text.toLowerCase().split(/\W+/);
const scores = {};
const updateScores = function (dict, word) {
// eslint-disable-next-line prefer-const
for (let exIndex in dict) {
let exScore = scores[exIndex];
if (!exScore) {
exScore = {};
scores[exIndex] = exScore;
}
exScore[word] = (exScore[word] || 0) + dict[exIndex];
}
};
words.forEach(function (word) {
const dict = info.index[word];
if (dict) {
updateScores(dict, word);
} else {
const r = new RegExp(word);
// eslint-disable-next-line prefer-const
for (let idx in info.index) {
if (r.test(idx)) {
updateScores(info.index[idx], word);
}
}
}
});
const examples = [];
// eslint-disable-next-line prefer-const
for (let exIndex in scores) {
const ex = info.examples[exIndex];
ex.score = 0;
ex.words = 0;
// eslint-disable-next-line prefer-const
for (let word in scores[exIndex]) {
ex.score += scores[exIndex][word];
ex.words++;
}
examples.push(ex);
}
// sort examples, first by number of words matched, then
// by word frequency
examples.sort(function (a, b) {
return a.score - b.score || a.words - b.words;
});
return examples;
}
function filterList(text) {
const examples = getMatchingExamples(text);
listExamples(examples);
}
function parseParams() {
const params = {};
const list = window.location.search
.substring(1)
.replace(/\+/g, '%20')
.split('&');
for (let i = 0; i < list.length; ++i) {
const pair = list[i].split('=');
if (pair.length === 2) {
params[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
}
}
return params;
}
window.addEventListener('load', function () {
for (let i = 0; i < info.examples.length; ++i) {
info.examples[i].link += window.location.search;
}
template = new jugl.Template('template');
target = document.getElementById('examples');
const params = parseParams();
const text = params['q'] || '';
const input = document.getElementById('keywords');
input.addEventListener('input', inputChange);
input.value = text;
filterList(text);
});
})();

View File

@@ -6,7 +6,7 @@ docs: >
<p>The map on the top preloads low resolution tiles. The map on the bottom does not use any preloading. Try zooming out and panning to see the difference.</p>
tags: "preload, bing"
cloak:
- key: ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp
- key: ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp
value: Your Bing Maps Key from http://www.bingmapsportal.com/ here
---
<div id="map1" class="map"></div>

View File

@@ -13,8 +13,7 @@ const map1 = new Map({
new TileLayer({
preload: Infinity,
source: new BingMaps({
key:
'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp',
imagerySet: 'Aerial',
}),
}),
@@ -28,8 +27,7 @@ const map2 = new Map({
new TileLayer({
preload: 0, // default value
source: new BingMaps({
key:
'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp',
imagerySet: 'AerialWithLabelsOnDemand',
}),
}),

View File

@@ -71,6 +71,7 @@ module.exports = {
{from: 'resources', to: 'resources'},
{from: 'Jugl.js', to: 'Jugl.js'},
{from: 'index.html', to: 'index.html'},
{from: 'index.js', to: 'index.js'},
],
}),
],

View File

@@ -42,26 +42,19 @@ function createWordIndex(exampleData) {
const keys = ['shortdesc', 'title', 'tags'];
exampleData.forEach((data, i) => {
keys.forEach((key) => {
let text = data[key];
let text = data[key] || '';
if (Array.isArray(text)) {
text = text.join(' ');
}
const words = text ? text.split(/\W+/) : [];
const words = text.toLowerCase().split(/\W+/);
words.forEach((word) => {
if (word) {
word = word.toLowerCase();
let counts = index[word];
if (counts) {
if (index in counts) {
counts[i] += 1;
} else {
counts[i] = 1;
}
} else {
if (!counts) {
counts = {};
counts[i] = 1;
index[word] = counts;
}
counts[i] = (counts[i] || 0) + 1;
}
});
});
@@ -169,14 +162,19 @@ class ExampleBuilder {
await Promise.all(promises);
exampleData.sort((a, b) =>
a.title.localeCompare(b.title, 'en', {sensitivity: 'base'})
);
const info = {
examples: exampleData,
index: createWordIndex(exampleData),
tags: Array.from(uniqueTags),
tags: Array.from(uniqueTags)
.sort() // sort twice to get predictable, case insensitve order
.sort((a, b) => a.localeCompare(b, 'en', {sensitivity: 'base'})),
};
const indexSource = `var info = ${JSON.stringify(info)}`;
compilation.assets['index.js'] = new RawSource(indexSource);
const indexSource = `const info = ${JSON.stringify(info)};`;
compilation.assets['examples-info.js'] = new RawSource(indexSource);
});
}