From 681fc155a7b55ad6226771ca4833b7824410287c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sun, 12 Jul 2020 10:59:56 +0200 Subject: [PATCH 01/10] Move js code into separate file to benefit from code analysis --- examples/index.html | 122 +--------------------------- examples/index.js | 120 +++++++++++++++++++++++++++ examples/webpack/config.js | 1 + examples/webpack/example-builder.js | 2 +- 4 files changed, 123 insertions(+), 122 deletions(-) create mode 100644 examples/index.js diff --git a/examples/index.html b/examples/index.html index 46ad23293a..8714671b4b 100644 --- a/examples/index.html +++ b/examples/index.html @@ -70,128 +70,8 @@ } + - OpenLayers Examples diff --git a/examples/index.js b/examples/index.js new file mode 100644 index 0000000000..089815a608 --- /dev/null +++ b/examples/index.js @@ -0,0 +1,120 @@ +(function () { + 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 Date: Sun, 12 Jul 2020 11:13:39 +0200 Subject: [PATCH 02/10] Prettier code This also fixes two undeclared variables and the regex is only created once per word --- examples/index.js | 92 ++++++++++++++++------------- examples/webpack/example-builder.js | 2 +- 2 files changed, 51 insertions(+), 43 deletions(-) diff --git a/examples/index.js b/examples/index.js index 089815a608..eede9227a1 100644 --- a/examples/index.js +++ b/examples/index.js @@ -1,42 +1,45 @@ (function () { - var template, target; + 'use strict'; + /* global info, jugl */ + let template, target; function listExamples(examples) { - target.innerHTML = ""; - var node = template.process({ + target.innerHTML = ''; + template.process({ context: {examples: examples}, clone: true, - parent: target + parent: target, }); - document.getElementById("count").innerHTML = "(" + examples.length + ")"; + document.getElementById('count').innerHTML = '(' + examples.length + ')'; } - var timerId; + let timerId; function inputChange() { if (timerId) { window.clearTimeout(timerId); } - var text = this.value; - timerId = window.setTimeout(function() { + const text = this.value; + timerId = window.setTimeout(function () { filterList(text); }, 500); } function filterList(text) { - var examples; + let examples; if (text.length < 2) { examples = info.examples; } else { - var words = text.split(/\W+/); - var scores = {}; - for(var i=0; i Date: Sun, 12 Jul 2020 11:22:59 +0200 Subject: [PATCH 03/10] Split searching and listing --- examples/index.js | 129 ++++++++++++++++++++++++---------------------- 1 file changed, 66 insertions(+), 63 deletions(-) diff --git a/examples/index.js b/examples/index.js index eede9227a1..d80ecd926b 100644 --- a/examples/index.js +++ b/examples/index.js @@ -24,78 +24,81 @@ }, 500); } - function filterList(text) { - let examples; + function getMatchingExamples(text) { if (text.length < 2) { - examples = info.examples; - } else { - const words = text.split(/\W+/); - const scores = {}; - for (let i = 0; i < words.length; ++i) { - const word = words[i].toLowerCase(); - let dict = info.index[word]; - const updateScores = function () { - // eslint-disable-next-line prefer-const - for (let exIndex in dict) { - const count = dict[exIndex]; - if (scores[exIndex]) { - if (scores[exIndex][word]) { - scores[exIndex][word] += count; - } else { - scores[exIndex][word] = count; - } + return info.examples; + } + const words = text.split(/\W+/); + const scores = {}; + for (let i = 0; i < words.length; ++i) { + const word = words[i].toLowerCase(); + let dict = info.index[word]; + const updateScores = function () { + // eslint-disable-next-line prefer-const + for (let exIndex in dict) { + const count = dict[exIndex]; + if (scores[exIndex]) { + if (scores[exIndex][word]) { + scores[exIndex][word] += count; } else { - scores[exIndex] = {}; scores[exIndex][word] = count; } + } else { + scores[exIndex] = {}; + scores[exIndex][word] = count; } - }; - if (dict) { - updateScores(); - } else { - const r = new RegExp(word); - // eslint-disable-next-line prefer-const - for (let idx in info.index) { - if (r.test(idx)) { - dict = info.index[idx]; - updateScores(); - } + } + }; + if (dict) { + updateScores(); + } else { + const r = new RegExp(word); + // eslint-disable-next-line prefer-const + for (let idx in info.index) { + if (r.test(idx)) { + dict = info.index[idx]; + updateScores(); } } } - examples = []; - // eslint-disable-next-line prefer-const - for (let j in scores) { - const 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) { - let cmp; - let aWords = 0, - bWords = 0; - let aScore = 0, - bScore = 0; - // eslint-disable-next-line prefer-const - for (let i in a.score) { - aScore += a.score[i]; - aWords += 1; - } - // eslint-disable-next-line prefer-const - for (let j in b.score) { - bScore += b.score[j]; - bWords += 1; - } - if (aWords == bWords) { - cmp = bScore - aScore; - } else { - cmp = bWords - aWords; - } - return cmp; - }); } + const examples = []; + // eslint-disable-next-line prefer-const + for (let j in scores) { + const 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) { + let cmp; + let aWords = 0, + bWords = 0; + let aScore = 0, + bScore = 0; + // eslint-disable-next-line prefer-const + for (let i in a.score) { + aScore += a.score[i]; + aWords += 1; + } + // eslint-disable-next-line prefer-const + for (let j in b.score) { + bScore += b.score[j]; + bWords += 1; + } + if (aWords == bWords) { + cmp = bScore - aScore; + } else { + cmp = bWords - aWords; + } + return cmp; + }); + return examples; + } + + function filterList(text) { + const examples = getMatchingExamples(text); listExamples(examples); } From 84463c3030ebe6ee8d45a4bcec5ea9056bfbdc98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sun, 12 Jul 2020 11:53:20 +0200 Subject: [PATCH 04/10] Make example builds repeatable --- examples/webpack/example-builder.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/examples/webpack/example-builder.js b/examples/webpack/example-builder.js index 80cc1d174f..6851012834 100644 --- a/examples/webpack/example-builder.js +++ b/examples/webpack/example-builder.js @@ -169,10 +169,15 @@ 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 = `const info = ${JSON.stringify(info)};`; From 687795ba242647e4cdabbd653e072ca5f47584e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sun, 12 Jul 2020 14:20:54 +0200 Subject: [PATCH 05/10] Skip listing all examples if query param is set. Also use the `input` event instead of `keyup` and addEventlistener instead of setting the onload / onchange properties. And handle space character encoded as `+` in query string correctly. --- examples/index.js | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/examples/index.js b/examples/index.js index d80ecd926b..02cb2cdfc7 100644 --- a/examples/index.js +++ b/examples/index.js @@ -102,30 +102,32 @@ listExamples(examples); } - function parseQuery() { + function parseParams() { const params = {}; - const list = window.location.search.substring(1).split('&'); + 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) { + if (pair.length === 2) { params[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); } } - if (params['q']) { - const input = document.getElementById('keywords'); - input.value = params['q']; - inputChange.call(input); - } + return params; } - window.onload = function () { + 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'); - listExamples(info.examples); - document.getElementById('keywords').onkeyup = inputChange; - parseQuery(); - }; + const params = parseParams(); + const text = params['q'] || ''; + const input = document.getElementById('keywords'); + input.addEventListener('input', inputChange); + input.value = text; + filterList(text); + }); })(); From b41a43cb7f50a9a095cd3d17b48a34aa06bc017b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sun, 12 Jul 2020 14:26:16 +0200 Subject: [PATCH 06/10] Simplify sorting of the examples by precalculating the score / words --- examples/index.js | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/examples/index.js b/examples/index.js index 02cb2cdfc7..665d41731a 100644 --- a/examples/index.js +++ b/examples/index.js @@ -64,35 +64,21 @@ } const examples = []; // eslint-disable-next-line prefer-const - for (let j in scores) { - const ex = info.examples[j]; - ex.score = scores[j]; + 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 by first by number of words matched, then + // sort examples, first by number of words matched, then // by word frequency examples.sort(function (a, b) { - let cmp; - let aWords = 0, - bWords = 0; - let aScore = 0, - bScore = 0; - // eslint-disable-next-line prefer-const - for (let i in a.score) { - aScore += a.score[i]; - aWords += 1; - } - // eslint-disable-next-line prefer-const - for (let j in b.score) { - bScore += b.score[j]; - bWords += 1; - } - if (aWords == bWords) { - cmp = bScore - aScore; - } else { - cmp = bWords - aWords; - } - return cmp; + return a.score - b.score || a.words - b.words; }); return examples; } From 856830b834969f2304bd01059010748d7fe35f06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sun, 12 Jul 2020 15:17:51 +0200 Subject: [PATCH 07/10] No empty string words / allow 1 character search If a space character is at either end of the input string splitting it procuces an empty string that matches everything. Allow single character words as there are is a single character tag: `x` --- examples/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/index.js b/examples/index.js index 665d41731a..7c50304a5c 100644 --- a/examples/index.js +++ b/examples/index.js @@ -25,7 +25,8 @@ } function getMatchingExamples(text) { - if (text.length < 2) { + text = text.trim(); + if (text.length === 0) { return info.examples; } const words = text.split(/\W+/); From b6404fb7669b464a8cc7ac79ae3ee64998f27ec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sun, 12 Jul 2020 15:25:44 +0200 Subject: [PATCH 08/10] Remove unnecessary space at end of bing key --- examples/bing-maps.html | 2 +- examples/bing-maps.js | 3 +-- examples/preload.html | 2 +- examples/preload.js | 6 ++---- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/examples/bing-maps.html b/examples/bing-maps.html index e201f69efc..2752130f9e 100644 --- a/examples/bing-maps.html +++ b/examples/bing-maps.html @@ -6,7 +6,7 @@ docs: >

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 maxZoom to 19 in the options passed to ol/source/BingMaps.

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 ---
diff --git a/examples/bing-maps.js b/examples/bing-maps.js index 13f988fc6a..77bcdd2b69 100644 --- a/examples/bing-maps.js +++ b/examples/bing-maps.js @@ -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 diff --git a/examples/preload.html b/examples/preload.html index e13138d2aa..193a6bd0ec 100644 --- a/examples/preload.html +++ b/examples/preload.html @@ -6,7 +6,7 @@ docs: >

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.

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 ---
diff --git a/examples/preload.js b/examples/preload.js index 4ee22ba30c..2ca51436aa 100644 --- a/examples/preload.js +++ b/examples/preload.js @@ -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', }), }), From 557563f331630666c276805ab4955c998af3fedd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Sun, 12 Jul 2020 17:11:59 +0200 Subject: [PATCH 09/10] Update scoring / indexing code Add dict / word as parameters to updateScore function so it does not need to be created in each loop, and shorten it a bit. --- examples/index.js | 39 ++++++++++++----------------- examples/webpack/example-builder.js | 15 +++-------- 2 files changed, 20 insertions(+), 34 deletions(-) diff --git a/examples/index.js b/examples/index.js index 7c50304a5c..cc73582dff 100644 --- a/examples/index.js +++ b/examples/index.js @@ -29,40 +29,33 @@ if (text.length === 0) { return info.examples; } - const words = text.split(/\W+/); + const words = text.toLowerCase().split(/\W+/); const scores = {}; - for (let i = 0; i < words.length; ++i) { - const word = words[i].toLowerCase(); - let dict = info.index[word]; - const updateScores = function () { - // eslint-disable-next-line prefer-const - for (let exIndex in dict) { - const 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; - } + 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(); + 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)) { - dict = info.index[idx]; - updateScores(); + updateScores(info.index[idx], word); } } } - } + }); const examples = []; // eslint-disable-next-line prefer-const for (let exIndex in scores) { diff --git a/examples/webpack/example-builder.js b/examples/webpack/example-builder.js index 6851012834..39a94acec7 100644 --- a/examples/webpack/example-builder.js +++ b/examples/webpack/example-builder.js @@ -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; } }); }); From 217f6486083e4782402efb5c6437c993cfa8d208 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Kr=C3=B6g?= Date: Fri, 17 Jul 2020 20:43:05 +0200 Subject: [PATCH 10/10] Fix quotes in tags yaml --- examples/arcgis-image.html | 2 +- examples/arcgis-tiled.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/arcgis-image.html b/examples/arcgis-image.html index 87b6e43089..241e0c1def 100644 --- a/examples/arcgis-image.html +++ b/examples/arcgis-image.html @@ -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" ---
diff --git a/examples/arcgis-tiled.html b/examples/arcgis-tiled.html index 576abf6b4d..a92546eca5 100644 --- a/examples/arcgis-tiled.html +++ b/examples/arcgis-tiled.html @@ -7,6 +7,6 @@ docs: > This source type supports Map and Image Services. For cached ArcGIS services, better performance is available by using ol/source/XYZ instead. -tags: arcgis, tile, tilelayer" +tags: "arcgis, tile, tilelayer" ---