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
+1 -1
View File
@@ -6,6 +6,6 @@ docs: >
This example shows how to use a dynamic ArcGIS REST MapService. This example shows how to use a dynamic ArcGIS REST MapService.
This source type supports Map and Image Services. For dyamic ArcGIS This source type supports Map and Image Services. For dyamic ArcGIS
services. services.
tags: arcgis, image, dynamiclayer" tags: "arcgis, image, dynamiclayer"
--- ---
<div id="map" class="map"></div> <div id="map" class="map"></div>
+1 -1
View File
@@ -7,6 +7,6 @@ docs: >
This source type supports Map and Image Services. For cached ArcGIS This source type supports Map and Image Services. For cached ArcGIS
services, better performance is available by using services, better performance is available by using
<code>ol/source/XYZ</code> instead. <code>ol/source/XYZ</code> instead.
tags: arcgis, tile, tilelayer" tags: "arcgis, tile, tilelayer"
--- ---
<div id="map" class="map"></div> <div id="map" class="map"></div>
+1 -2
View File
@@ -18,8 +18,7 @@ for (i = 0, ii = styles.length; i < ii; ++i) {
visible: false, visible: false,
preload: Infinity, preload: Infinity,
source: new BingMaps({ source: new BingMaps({
key: key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp',
'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
imagerySet: styles[i], imagerySet: styles[i],
// use maxZoom 19 to see stretched tiles instead of the BingMaps // use maxZoom 19 to see stretched tiles instead of the BingMaps
// "no photos at this zoom level" tiles // "no photos at this zoom level" tiles
+1 -121
View File
@@ -70,128 +70,8 @@
} }
</style> </style>
<script type="text/javascript" src="Jugl.js"></script> <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" 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> <title>OpenLayers Examples</title>
</head> </head>
+113
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);
});
})();
+2 -4
View File
@@ -13,8 +13,7 @@ const map1 = new Map({
new TileLayer({ new TileLayer({
preload: Infinity, preload: Infinity,
source: new BingMaps({ source: new BingMaps({
key: key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp',
'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
imagerySet: 'Aerial', imagerySet: 'Aerial',
}), }),
}), }),
@@ -28,8 +27,7 @@ const map2 = new Map({
new TileLayer({ new TileLayer({
preload: 0, // default value preload: 0, // default value
source: new BingMaps({ source: new BingMaps({
key: key: 'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp',
'ApTJzdkyN1DdFKkRAE6QIDtzihNaf6IWJsT-nQ_2eMoO4PN__0Tzhl2-WgJtXFSp ',
imagerySet: 'AerialWithLabelsOnDemand', imagerySet: 'AerialWithLabelsOnDemand',
}), }),
}), }),
+1
View File
@@ -71,6 +71,7 @@ module.exports = {
{from: 'resources', to: 'resources'}, {from: 'resources', to: 'resources'},
{from: 'Jugl.js', to: 'Jugl.js'}, {from: 'Jugl.js', to: 'Jugl.js'},
{from: 'index.html', to: 'index.html'}, {from: 'index.html', to: 'index.html'},
{from: 'index.js', to: 'index.js'},
], ],
}), }),
], ],
+12 -14
View File
@@ -42,26 +42,19 @@ function createWordIndex(exampleData) {
const keys = ['shortdesc', 'title', 'tags']; const keys = ['shortdesc', 'title', 'tags'];
exampleData.forEach((data, i) => { exampleData.forEach((data, i) => {
keys.forEach((key) => { keys.forEach((key) => {
let text = data[key]; let text = data[key] || '';
if (Array.isArray(text)) { if (Array.isArray(text)) {
text = text.join(' '); text = text.join(' ');
} }
const words = text ? text.split(/\W+/) : []; const words = text.toLowerCase().split(/\W+/);
words.forEach((word) => { words.forEach((word) => {
if (word) { if (word) {
word = word.toLowerCase();
let counts = index[word]; let counts = index[word];
if (counts) { if (!counts) {
if (index in counts) {
counts[i] += 1;
} else {
counts[i] = 1;
}
} else {
counts = {}; counts = {};
counts[i] = 1;
index[word] = counts; index[word] = counts;
} }
counts[i] = (counts[i] || 0) + 1;
} }
}); });
}); });
@@ -169,14 +162,19 @@ class ExampleBuilder {
await Promise.all(promises); await Promise.all(promises);
exampleData.sort((a, b) =>
a.title.localeCompare(b.title, 'en', {sensitivity: 'base'})
);
const info = { const info = {
examples: exampleData, examples: exampleData,
index: createWordIndex(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)}`; const indexSource = `const info = ${JSON.stringify(info)};`;
compilation.assets['index.js'] = new RawSource(indexSource); compilation.assets['examples-info.js'] = new RawSource(indexSource);
}); });
} }